Skip to content

Commit 9159d72

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 9159d72

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

src/clang.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ 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+
pub name: CString,
14131413
contents: CString,
14141414
}
14151415

@@ -1431,6 +1431,15 @@ impl UnsavedFile {
14311431
}
14321432
}
14331433

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

src/ir/context.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ impl Builder {
175175
self
176176
}
177177

178+
/// Add `contents` as an input C/C++ header named `name`.
179+
pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
180+
self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents));
181+
self
182+
}
183+
178184
/// Set the output graphviz file.
179185
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
180186
let path = path.into();
@@ -573,6 +579,9 @@ pub struct BindgenOptions {
573579
/// The input header file.
574580
pub input_header: Option<String>,
575581

582+
/// Unsaved files for input.
583+
pub input_unsaved_files: Vec<clang::UnsavedFile>,
584+
576585
/// Generate a dummy C/C++ file that includes the header and has dummy uses
577586
/// of all types defined therein. See the `uses` module for more.
578587
pub dummy_uses: Option<String>,
@@ -662,6 +671,7 @@ impl Default for BindgenOptions {
662671
raw_lines: vec![],
663672
clang_args: vec![],
664673
input_header: None,
674+
input_unsaved_files: vec![],
665675
dummy_uses: None,
666676
parse_callbacks: None,
667677
codegen_config: CodegenConfig::all(),
@@ -754,6 +764,10 @@ impl<'ctx> Bindings<'ctx> {
754764
options.clang_args.push(h.clone())
755765
}
756766

767+
for f in options.input_unsaved_files.iter() {
768+
options.clang_args.push(f.name.to_str().unwrap().to_owned())
769+
}
770+
757771
let mut context = BindgenContext::new(options);
758772
try!(parse(&mut context));
759773

tests/tests.rs

Lines changed: 18 additions & 1 deletion
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;
@@ -32,6 +32,7 @@ fn compare_generated_header(header: &PathBuf,
3232
Err(_) => "".to_string(),
3333
};
3434

35+
3536
let mut buffer = String::new();
3637
{
3738
if let Ok(expected_file) = fs::File::open(&expected) {
@@ -144,3 +145,19 @@ macro_rules! test_header {
144145

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

0 commit comments

Comments
 (0)