print_cxx_include_dirs/
lib.rs1use std::env::{self, ArgsOs};
8use std::fs::{self, File};
9use std::io::{self, ErrorKind, Write};
10use std::os::raw::c_int;
11use std::panic;
12use std::path::Path;
13
14#[no_mangle]
15pub extern "C" fn main() -> c_int {
16 panic::catch_unwind(do_main).unwrap_or(1)
17}
18
19fn do_main() -> c_int {
20 let out_dir = env::var_os("OUT_DIR").unwrap();
21 let out_dir = Path::new(&out_dir);
22 let args_os = env::args_os();
23 match if args_os.len() <= 1 {
24 do_compile(out_dir)
25 } else {
26 do_print(out_dir, args_os)
27 } {
28 Ok(()) => 0,
29 Err(err) => {
30 let _ = writeln!(io::stderr(), "{}", err);
31 1
32 }
33 }
34}
35
36fn do_compile(out_dir: &Path) -> io::Result<()> {
37 let include_dirs = out_dir.join("include-dirs");
38 if let Err(err) = fs::remove_file(include_dirs) {
39 if err.kind() != ErrorKind::NotFound {
40 return Err(err);
41 }
42 }
43
44 let current_exe = env::current_exe()?;
45
46 let bridge_rs = out_dir.join("bridge.rs");
47 fs::write(&bridge_rs, "#[cxx::bridge] mod ffi {}")?;
48 cxx_build::bridge(&bridge_rs)
49 .compiler(¤t_exe)
50 .archiver(¤t_exe)
51 .cargo_metadata(false)
52 .compile("unused");
53
54 Ok(())
55}
56
57fn do_print(out_dir: &Path, mut args_os: ArgsOs) -> io::Result<()> {
58 let include_dirs = out_dir.join("include-dirs");
59 let mut file = match File::options()
60 .read(true)
61 .write(true)
62 .create_new(true)
63 .open(include_dirs)
64 {
65 Ok(file) => file,
66 Err(err) if err.kind() == ErrorKind::AlreadyExists => return Ok(()),
67 Err(err) => return Err(err),
68 };
69
70 while let Some(arg) = args_os.next() {
71 if arg == "-I" {
72 let include_dir = args_os.next().unwrap();
73 let include_dir = Path::new(&include_dir);
74 if !include_dir.starts_with(out_dir) {
75 let include_dir = include_dir.to_str().unwrap();
76 assert!(!include_dir.contains('\n'));
77 writeln!(file, "{}", include_dir)?;
78 }
79 }
80 }
81
82 let main_rs = out_dir.join("main.rs");
83 fs::write(&main_rs, MAIN_RS)?;
84
85 writeln!(
86 io::stdout(),
87 "cargo:rustc-env=PRINT_CXX_INCLUDE_DIRS={}",
88 main_rs.to_str().unwrap(),
89 )
90}
91
92const MAIN_RS: &str = "\
93fn main() {
94 let _ = std::io::Write::write_all(
95 &mut std::io::stdout(),
96 include_bytes!(concat!(env!(\"OUT_DIR\"), \"/include-dirs\")),
97 );
98}
99";