Skip to content

Commit

Permalink
Add ParseCallbacks handler for included files
Browse files Browse the repository at this point in the history
As the clang_File_tryGetRealPathName function is only exposed by
clang_sys for clang >= 7.0, this raises the clang dependency.

Closes: #1635

The book example code for creating a builder to run inside Cargo is
extended by using the rereun-if-changed headers.
  • Loading branch information
chrysn authored and emilio committed Oct 7, 2019
1 parent b84fb5b commit 49af9b7
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 1 deletion.
6 changes: 6 additions & 0 deletions book/src/tutorial-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@ fn main() {
// shared library.
println!("cargo:rustc-link-lib=bz2");
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed=wrapper.h");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("wrapper.h")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
Expand Down
3 changes: 3 additions & 0 deletions src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,7 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
fn item_name(&self, _original_item_name: &str) -> Option<String> {
None
}

/// This will be called on every file inclusion, with the full path of the included file.
fn include_file(&self, _filename: &str) {}
}
12 changes: 12 additions & 0 deletions src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,18 @@ impl Cursor {
})
.collect()
}

/// Obtain the real path name of a cursor of InclusionDirective kind.
///
/// Returns None if the cursor does not include a file, otherwise the file's full name
pub fn get_included_file_name(&self) -> Option<String> {
let file = unsafe { clang_sys::clang_getIncludedFile(self.x) };
if file.is_null() {
None
} else {
Some(unsafe { cxstring_into_string(clang_sys::clang_getFileName(file)) })
}
}
}

/// A struct that owns the tokenizer result from a given cursor.
Expand Down
17 changes: 16 additions & 1 deletion src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1357,14 +1357,29 @@ impl ClangItemParser for Item {
CXCursor_UsingDeclaration |
CXCursor_UsingDirective |
CXCursor_StaticAssert |
CXCursor_InclusionDirective |
CXCursor_FunctionTemplate => {
debug!(
"Unhandled cursor kind {:?}: {:?}",
cursor.kind(),
cursor
);
}
CXCursor_InclusionDirective => {
let file = cursor.get_included_file_name();
match file {
None => {
warn!(
"Inclusion of a nameless file in {:?}",
cursor
);
}
Some(filename) => {
if let Some(cb) = ctx.parse_callbacks() {
cb.include_file(&filename)
}
}
}
}
_ => {
// ignore toplevel operator overloads
let spelling = cursor.spelling();
Expand Down
21 changes: 21 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,27 @@ pub fn clang_version() -> ClangVersion {
}
}

/// A ParseCallbacks implementation that will act on file includes by echoing a rerun-if-changed
/// line
///
/// When running in side a `build.rs` script, this can be used to make cargo invalidate the
/// generated bindings whenever any of the files included from the header change:
/// ```
/// use bindgen::builder;
/// let bindings = builder()
/// .header("path/to/input/header")
/// .parse_callbacks(Box::new(bindgen::CargoCallbacks))
/// .generate();
/// ```
#[derive(Debug)]
pub struct CargoCallbacks;

impl callbacks::ParseCallbacks for CargoCallbacks {
fn include_file(&self, filename: &str) {
println!("cargo:rerun-if-changed={}", filename);
}
}

/// Test command_line_flag function.
#[test]
fn commandline_flag_unit_test_function() {
Expand Down

0 comments on commit 49af9b7

Please sign in to comment.