Added support for integrating the package_version information in a comment of the header file.

The new command line argument for this is --package-version.

The TOML config file flag is package_version=true||false.

Closes #926
Co-Authored-By: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Hitbear 2024-02-09 19:28:23 +01:00 committed by Emilio Cobos Álvarez
parent 400f437643
commit af469996e0
22 changed files with 236 additions and 7 deletions

View File

@ -33,6 +33,7 @@ pub struct Bindings {
/// Bindings are generated by a recursive call to cbindgen
/// and shouldn't do anything when written anywhere.
noop: bool,
package_version: String,
}
#[derive(PartialEq, Eq)]
@ -53,6 +54,7 @@ impl Bindings {
functions: Vec<Function>,
source_files: Vec<path::PathBuf>,
noop: bool,
package_version: String,
) -> Bindings {
Bindings {
config,
@ -65,6 +67,7 @@ impl Bindings {
functions,
source_files,
noop,
package_version,
}
}
@ -209,6 +212,20 @@ impl Bindings {
return;
}
if self.config.package_version {
out.new_line_if_not_start();
match self.config.language {
Language::C | Language::Cxx => {
write!(out, "/* Package version: {} */", self.package_version);
}
Language::Cython => {
write!(out, "''' Package version: {} '''", self.package_version);
}
}
out.new_line();
}
if let Some(ref f) = self.config.header {
out.new_line_if_not_start();
write!(out, "{}", f);
@ -228,11 +245,23 @@ impl Bindings {
}
if self.config.include_version {
out.new_line_if_not_start();
match self.config.language {
Language::C | Language::Cxx => {
write!(
out,
"/* Generated with cbindgen:{} */",
crate::bindgen::config::VERSION
);
}
Language::Cython => {
write!(
out,
"''' Generated with cbindgen:{} '''",
crate::bindgen::config::VERSION
);
}
}
out.new_line();
}
if let Some(ref f) = self.config.autogen_warning {

View File

@ -361,6 +361,7 @@ impl Builder {
Default::default(),
Default::default(),
true,
String::new(),
));
}
@ -405,6 +406,7 @@ impl Builder {
result.typedefs,
result.functions,
result.source_files,
result.package_version,
)
.generate()
}

View File

@ -919,6 +919,8 @@ pub struct Config {
/// This option is useful when using cbindgen with tools such as python's cffi which
/// doesn't understand include directives
pub no_includes: bool,
// Package version: True if the package version should appear as a comment in the .h file
pub package_version: bool,
/// Optional text to output at major sections to deter manual editing
pub autogen_warning: Option<String>,
/// Include a comment with the version of cbindgen used to generate the file
@ -1040,6 +1042,7 @@ impl Default for Config {
autogen_warning: None,
include_version: false,
no_includes: false,
package_version: false,
namespace: None,
namespaces: None,
using_namespaces: None,

View File

@ -7,7 +7,7 @@ use std::collections::HashMap;
use std::io::Write;
use syn::ext::IdentExt;
use syn::{self, UnOp};
use syn::UnOp;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;

View File

@ -27,6 +27,7 @@ pub struct Library {
typedefs: ItemMap<Typedef>,
functions: Vec<Function>,
source_files: Vec<PathBuf>,
package_version: String,
}
impl Library {
@ -42,6 +43,7 @@ impl Library {
typedefs: ItemMap<Typedef>,
functions: Vec<Function>,
source_files: Vec<PathBuf>,
package_version: String,
) -> Library {
Library {
config,
@ -54,6 +56,7 @@ impl Library {
typedefs,
functions,
source_files,
package_version,
}
}
@ -141,6 +144,7 @@ impl Library {
functions,
self.source_files,
false,
self.package_version,
))
}

View File

@ -81,6 +81,13 @@ pub(crate) fn parse_lib(lib: Cargo, config: &Config) -> ParseResult {
let binding_crate = context.lib.as_ref().unwrap().binding_crate_ref();
context.parse_crate(&binding_crate)?;
context.out.source_files = context.cache_src.keys().map(|k| k.to_owned()).collect();
context.out.package_version = context
.lib
.as_ref()
.unwrap()
.binding_crate_ref()
.version
.unwrap();
Ok(context.out)
}
@ -409,6 +416,7 @@ pub struct Parse {
pub typedefs: ItemMap<Typedef>,
pub functions: Vec<Function>,
pub source_files: Vec<FilePathBuf>,
pub package_version: String,
}
impl Parse {
@ -423,6 +431,7 @@ impl Parse {
typedefs: ItemMap::default(),
functions: Vec::new(),
source_files: Vec::new(),
package_version: String::new(),
}
}
@ -471,6 +480,7 @@ impl Parse {
self.typedefs.extend_with(&other.typedefs);
self.functions.extend_from_slice(&other.functions);
self.source_files.extend_from_slice(&other.source_files);
self.package_version = other.package_version.clone();
}
fn load_syn_crate_mod<'a>(

View File

@ -49,6 +49,10 @@ fn apply_config_overrides(config: &mut Config, matches: &ArgMatches) {
config.only_target_dependencies = true;
}
if matches.get_flag("package-version") {
config.package_version = true;
}
match matches.try_get_one::<String>("style") {
Ok(Some(style)) => {
config.style = bindgen::Style::from_str(style).unwrap();
@ -163,6 +167,12 @@ fn main() {
.help("Specify the language to output bindings in")
.value_parser(["c++", "C++", "c", "C", "cython", "Cython"]),
)
.arg(
Arg::new("package-version")
.long("package-version")
.action(ArgAction::SetTrue)
.help("Include the package version in the header comment")
)
.arg(
Arg::new("cpp-compat")
.long("cpp-compat")

View File

@ -0,0 +1,12 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint64_t bar;
} Foo;
void doit(const Foo*);

View File

@ -0,0 +1,20 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint64_t bar;
} Foo;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void doit(const Foo*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@ -0,0 +1,17 @@
/* Package version: 0.1.0 */
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
struct Foo {
uint64_t bar;
};
extern "C" {
void doit(const Foo*);
} // extern "C"

View File

@ -0,0 +1,14 @@
''' Package version: 0.1.0 '''
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list
cdef extern from *:
ctypedef struct Foo:
uint64_t bar;
void doit(const Foo*);

View File

@ -0,0 +1,12 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo {
uint64_t bar;
} Foo;
void doit(const struct Foo*);

View File

@ -0,0 +1,20 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Foo {
uint64_t bar;
} Foo;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void doit(const struct Foo*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@ -0,0 +1,12 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo {
uint64_t bar;
};
void doit(const struct Foo*);

View File

@ -0,0 +1,20 @@
/* Package version: 0.1.0 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
struct Foo {
uint64_t bar;
};
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void doit(const struct Foo*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@ -0,0 +1,14 @@
''' Package version: 0.1.0 '''
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list
cdef extern from *:
cdef struct Foo:
uint64_t bar;
void doit(const Foo*);

5
tests/rust/package_version/Cargo.lock generated Normal file
View File

@ -0,0 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "package_version"
version = "0.1.0"

View File

@ -0,0 +1,7 @@
[package]
name = "package_version"
version = "0.1.0"
authors = ["hitbear"]
[features]
cbindgen = []

View File

@ -0,0 +1 @@
package_version = true

View File

@ -0,0 +1,7 @@
#[repr(C)]
pub struct Foo {
bar: u64,
}
#[no_mangle]
pub extern "C" fn doit(_: &Foo) {}

View File

@ -26,6 +26,7 @@ fn run_cbindgen(
cpp_compat: bool,
style: Option<Style>,
generate_depfile: bool,
package_version: bool,
) -> (Vec<u8>, Option<String>) {
assert!(
!(output.is_none() && generate_depfile),
@ -58,6 +59,10 @@ fn run_cbindgen(
}
}
if package_version {
command.arg("--package-version");
}
if let Some(style) = style {
command.arg("--style").arg(style_str(style));
}
@ -200,6 +205,7 @@ fn run_compile_test(
cpp_compat: bool,
style: Option<Style>,
cbindgen_outputs: &mut HashSet<Vec<u8>>,
package_version: bool,
) {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let tests_path = Path::new(&crate_dir).join("tests");
@ -248,6 +254,7 @@ fn run_compile_test(
cpp_compat,
style,
generate_depfile,
package_version,
);
if generate_depfile {
let depfile = depfile_contents.expect("No depfile generated");
@ -329,6 +336,7 @@ fn test_file(name: &'static str, filename: &'static str) {
*cpp_compat,
Some(*style),
&mut cbindgen_outputs,
false,
);
}
}
@ -341,6 +349,7 @@ fn test_file(name: &'static str, filename: &'static str) {
/* cpp_compat = */ false,
None,
&mut HashSet::new(),
false,
);
// `Style::Both` should be identical to `Style::Tag` for Cython.
@ -354,6 +363,7 @@ fn test_file(name: &'static str, filename: &'static str) {
/* cpp_compat = */ false,
Some(*style),
&mut cbindgen_outputs,
false,
);
}
}