Skip to content

Commit 63de948

Browse files
committed
Add a Builder::header_contents method to allow passing source code as a string to a Builder
Currently the Builder API requires input as header files on disk. This allows passing C source directly to clang using the existing UnsavedFile struct.
1 parent b4e3be9 commit 63de948

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

src/clang.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,9 @@ impl Drop for Diagnostic {
14091409
/// A file which has not been saved to disk.
14101410
pub struct UnsavedFile {
14111411
x: CXUnsavedFile,
1412-
name: CString,
1412+
/// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
1413+
/// `CXUnsavedFile`.
1414+
pub name: CString,
14131415
contents: CString,
14141416
}
14151417

@@ -1431,6 +1433,15 @@ impl UnsavedFile {
14311433
}
14321434
}
14331435

1436+
impl fmt::Debug for UnsavedFile {
1437+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1438+
write!(fmt,
1439+
"UnsavedFile(name: {:?}, contents: {:?})",
1440+
self.name,
1441+
self.contents)
1442+
}
1443+
}
1444+
14341445
/// Convert a cursor kind into a static string.
14351446
pub fn kind_to_str(x: CXCursorKind) -> String {
14361447
unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }

src/ir/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl<'ctx> BindgenContext<'ctx> {
182182
clang::TranslationUnit::parse(&index,
183183
"",
184184
&options.clang_args,
185-
&[],
185+
&options.input_unsaved_files,
186186
parse_options)
187187
.expect("TranslationUnit::parse failed");
188188

src/lib.rs

+16
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ impl Builder {
175175
self
176176
}
177177

178+
/// Add `contents` as an input C/C++ header named `name`.
179+
///
180+
/// The file `name` will be added to the clang arguments.
181+
pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
182+
self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents));
183+
self
184+
}
185+
178186
/// Set the output graphviz file.
179187
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
180188
let path = path.into();
@@ -573,6 +581,9 @@ pub struct BindgenOptions {
573581
/// The input header file.
574582
pub input_header: Option<String>,
575583

584+
/// Unsaved files for input.
585+
pub input_unsaved_files: Vec<clang::UnsavedFile>,
586+
576587
/// Generate a dummy C/C++ file that includes the header and has dummy uses
577588
/// of all types defined therein. See the `uses` module for more.
578589
pub dummy_uses: Option<String>,
@@ -662,6 +673,7 @@ impl Default for BindgenOptions {
662673
raw_lines: vec![],
663674
clang_args: vec![],
664675
input_header: None,
676+
input_unsaved_files: vec![],
665677
dummy_uses: None,
666678
parse_callbacks: None,
667679
codegen_config: CodegenConfig::all(),
@@ -754,6 +766,10 @@ impl<'ctx> Bindings<'ctx> {
754766
options.clang_args.push(h.clone())
755767
}
756768

769+
for f in options.input_unsaved_files.iter() {
770+
options.clang_args.push(f.name.to_str().unwrap().to_owned())
771+
}
772+
757773
let mut context = BindgenContext::new(options);
758774
try!(parse(&mut context));
759775

tests/tests.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate diff;
33
extern crate bindgen;
44
extern crate shlex;
55

6-
use bindgen::Builder;
6+
use bindgen::{Builder, builder};
77
use std::fs;
88
use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write};
99
use std::path::PathBuf;
@@ -144,3 +144,19 @@ macro_rules! test_header {
144144

145145
// This file is generated by build.rs
146146
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
147+
148+
#[test]
149+
fn test_header_contents() {
150+
let bindings = builder()
151+
.header_contents("test.h", "int foo(const char* a);")
152+
.no_unstable_rust()
153+
.generate()
154+
.unwrap()
155+
.to_string();
156+
assert_eq!(bindings, "/* automatically generated by rust-bindgen */
157+
158+
extern \"C\" {
159+
pub fn foo(a: *const ::std::os::raw::c_schar) -> ::std::os::raw::c_int;
160+
}
161+
");
162+
}

0 commit comments

Comments
 (0)