Skip to content

Commit 5177889

Browse files
Andrey Pushkaremilio
authored andcommitted
Use absolute paths for unsaved files passed to clang and prepend -include directives to them.
Fixes #1771 Closes #1857
1 parent 9de0d64 commit 5177889

File tree

3 files changed

+178
-2
lines changed

3 files changed

+178
-2
lines changed

src/lib.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,16 @@ impl Builder {
596596
///
597597
/// The file `name` will be added to the clang arguments.
598598
pub fn header_contents(mut self, name: &str, contents: &str) -> Builder {
599+
// Apparently clang relies on having virtual FS correspondent to
600+
// the real one, so we need absolute paths here
601+
let absolute_path = env::current_dir()
602+
.expect("Cannot retrieve current directory")
603+
.join(name)
604+
.to_str()
605+
.expect("Cannot convert current directory name to string")
606+
.to_owned();
599607
self.input_header_contents
600-
.push((name.into(), contents.into()));
608+
.push((absolute_path, contents.into()));
601609
self
602610
}
603611

@@ -2154,7 +2162,10 @@ impl Bindings {
21542162
}
21552163
}
21562164

2157-
for f in options.input_unsaved_files.iter() {
2165+
for (idx, f) in options.input_unsaved_files.iter().enumerate() {
2166+
if idx != 0 || options.input_header.is_some() {
2167+
options.clang_args.push("-include".to_owned());
2168+
}
21582169
options.clang_args.push(f.name.to_str().unwrap().to_owned())
21592170
}
21602171

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
extern "C" {
2+
pub static mut foo: ::std::option::Option<
3+
unsafe extern "C" fn(
4+
x: ::std::os::raw::c_int,
5+
y: ::std::os::raw::c_int,
6+
) -> ::std::os::raw::c_int,
7+
>;
8+
}
9+
extern "C" {
10+
pub fn bar(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
11+
}
12+
extern "C" {
13+
pub fn bar2(b: *const ::std::os::raw::c_char) -> f32;
14+
}
15+
pub type Char = ::std::os::raw::c_char;
16+
pub type SChar = ::std::os::raw::c_schar;
17+
pub type UChar = ::std::os::raw::c_uchar;
18+
#[repr(C)]
19+
#[derive(Debug, Copy, Clone)]
20+
pub struct Test {
21+
pub ch: ::std::os::raw::c_char,
22+
pub u: ::std::os::raw::c_uchar,
23+
pub d: ::std::os::raw::c_schar,
24+
pub cch: ::std::os::raw::c_char,
25+
pub cu: ::std::os::raw::c_uchar,
26+
pub cd: ::std::os::raw::c_schar,
27+
pub Cch: Char,
28+
pub Cu: UChar,
29+
pub Cd: SChar,
30+
pub Ccch: Char,
31+
pub Ccu: UChar,
32+
pub Ccd: SChar,
33+
}
34+
#[test]
35+
fn bindgen_test_layout_Test() {
36+
assert_eq!(
37+
::std::mem::size_of::<Test>(),
38+
12usize,
39+
concat!("Size of: ", stringify!(Test))
40+
);
41+
assert_eq!(
42+
::std::mem::align_of::<Test>(),
43+
1usize,
44+
concat!("Alignment of ", stringify!(Test))
45+
);
46+
assert_eq!(
47+
unsafe { &(*(::std::ptr::null::<Test>())).ch as *const _ as usize },
48+
0usize,
49+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(ch))
50+
);
51+
assert_eq!(
52+
unsafe { &(*(::std::ptr::null::<Test>())).u as *const _ as usize },
53+
1usize,
54+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(u))
55+
);
56+
assert_eq!(
57+
unsafe { &(*(::std::ptr::null::<Test>())).d as *const _ as usize },
58+
2usize,
59+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(d))
60+
);
61+
assert_eq!(
62+
unsafe { &(*(::std::ptr::null::<Test>())).cch as *const _ as usize },
63+
3usize,
64+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(cch))
65+
);
66+
assert_eq!(
67+
unsafe { &(*(::std::ptr::null::<Test>())).cu as *const _ as usize },
68+
4usize,
69+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(cu))
70+
);
71+
assert_eq!(
72+
unsafe { &(*(::std::ptr::null::<Test>())).cd as *const _ as usize },
73+
5usize,
74+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(cd))
75+
);
76+
assert_eq!(
77+
unsafe { &(*(::std::ptr::null::<Test>())).Cch as *const _ as usize },
78+
6usize,
79+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cch))
80+
);
81+
assert_eq!(
82+
unsafe { &(*(::std::ptr::null::<Test>())).Cu as *const _ as usize },
83+
7usize,
84+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cu))
85+
);
86+
assert_eq!(
87+
unsafe { &(*(::std::ptr::null::<Test>())).Cd as *const _ as usize },
88+
8usize,
89+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(Cd))
90+
);
91+
assert_eq!(
92+
unsafe { &(*(::std::ptr::null::<Test>())).Ccch as *const _ as usize },
93+
9usize,
94+
concat!(
95+
"Offset of field: ",
96+
stringify!(Test),
97+
"::",
98+
stringify!(Ccch)
99+
)
100+
);
101+
assert_eq!(
102+
unsafe { &(*(::std::ptr::null::<Test>())).Ccu as *const _ as usize },
103+
10usize,
104+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(Ccu))
105+
);
106+
assert_eq!(
107+
unsafe { &(*(::std::ptr::null::<Test>())).Ccd as *const _ as usize },
108+
11usize,
109+
concat!("Offset of field: ", stringify!(Test), "::", stringify!(Ccd))
110+
);
111+
}

tests/tests.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,60 @@ fn test_multiple_header_calls_in_builder() {
473473
}
474474
}
475475

476+
#[test]
477+
fn test_multiple_header_contents() {
478+
let actual = builder()
479+
.header_contents("test.h", "int foo(const char* a);")
480+
.header_contents("test2.h", "float foo2(const char* b);")
481+
.clang_arg("--target=x86_64-unknown-linux")
482+
.generate()
483+
.unwrap()
484+
.to_string();
485+
486+
let (actual, stderr) = rustfmt(actual);
487+
println!("{}", stderr);
488+
489+
let (expected, _) = rustfmt(
490+
"extern \"C\" {
491+
pub fn foo2(b: *const ::std::os::raw::c_char) -> f32;
492+
}
493+
extern \"C\" {
494+
pub fn foo(a: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int;
495+
}
496+
"
497+
.to_string(),
498+
);
499+
500+
assert_eq!(expected, actual);
501+
}
502+
503+
#[test]
504+
fn test_mixed_header_and_header_contents() {
505+
let actual = builder()
506+
.header(concat!(
507+
env!("CARGO_MANIFEST_DIR"),
508+
"/tests/headers/func_ptr.h"
509+
))
510+
.header(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/headers/char.h"))
511+
.header_contents("test.h", "int bar(const char* a);")
512+
.header_contents("test2.h", "float bar2(const char* b);")
513+
.clang_arg("--target=x86_64-unknown-linux")
514+
.generate()
515+
.unwrap()
516+
.to_string();
517+
518+
let (actual, stderr) = rustfmt(actual);
519+
println!("{}", stderr);
520+
521+
let expected = include_str!(concat!(
522+
env!("CARGO_MANIFEST_DIR"),
523+
"/tests/expectations/tests/test_mixed_header_and_header_contents.rs"
524+
));
525+
let (expected, _) = rustfmt(expected.to_string());
526+
527+
assert_eq!(expected, actual);
528+
}
529+
476530
#[test]
477531
// Doesn't support executing sh file on Windows.
478532
// We may want to implement it in Rust so that we support all systems.

0 commit comments

Comments
 (0)