diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs index 8b109c302..f8db241a8 100644 --- a/gen/cmd/src/main.rs +++ b/gen/cmd/src/main.rs @@ -74,7 +74,11 @@ filenames, then you should use instead of --gen-rs-include and you will need to give AUTOCXX_RS_JSON_ARCHIVE when building the Rust code. -The output filename is named gen.rs.json. +The output filename is named gen.rs.json. AUTOCXX_RS_JSON_ARCHIVE should be set +to the path to gen.rs.json. It may optionally have multiple paths separated the +way as the PATH environment variable for the current platform, see +[`std::env::split_paths`] for details. The first path which is successfully +opened will be used. This teaches rustc (and the autocxx macro) that all the different Rust bindings for multiple different autocxx macros have been archived into this single file. diff --git a/gen/cmd/tests/cmd_test.rs b/gen/cmd/tests/cmd_test.rs index 7e455a2af..6fd3382ab 100644 --- a/gen/cmd/tests/cmd_test.rs +++ b/gen/cmd/tests/cmd_test.rs @@ -146,6 +146,58 @@ fn test_gen_archive() -> Result<(), Box> { Ok(()) } +#[test] +fn test_gen_archive_first_entry() -> Result<(), Box> { + let tmp_dir = tempdir()?; + base_test(&tmp_dir, RsGenMode::Archive, |_| {})?; + File::create(tmp_dir.path().join("cxx.h")) + .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?; + let r = build_from_folder( + tmp_dir.path(), + &tmp_dir.path().join("demo/main.rs"), + vec![tmp_dir.path().join("gen.rs.json")], + &["gen0.cc"], + RsFindMode::Custom(Box::new(|path: &Path| { + std::env::set_var( + "AUTOCXX_RS_JSON_ARCHIVE", + std::env::join_paths([&path.join("gen.rs.json"), Path::new("/nonexistent")]) + .unwrap(), + ) + })), + ); + if KEEP_TEMPDIRS { + println!("Tempdir: {:?}", tmp_dir.into_path().to_str()); + } + r.unwrap(); + Ok(()) +} + +#[test] +fn test_gen_archive_second_entry() -> Result<(), Box> { + let tmp_dir = tempdir()?; + base_test(&tmp_dir, RsGenMode::Archive, |_| {})?; + File::create(tmp_dir.path().join("cxx.h")) + .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?; + let r = build_from_folder( + tmp_dir.path(), + &tmp_dir.path().join("demo/main.rs"), + vec![tmp_dir.path().join("gen.rs.json")], + &["gen0.cc"], + RsFindMode::Custom(Box::new(|path: &Path| { + std::env::set_var( + "AUTOCXX_RS_JSON_ARCHIVE", + std::env::join_paths([Path::new("/nonexistent"), &path.join("gen.rs.json")]) + .unwrap(), + ) + })), + ); + if KEEP_TEMPDIRS { + println!("Tempdir: {:?}", tmp_dir.into_path().to_str()); + } + r.unwrap(); + Ok(()) +} + #[test] fn test_gen_multiple_in_archive() -> Result<(), Box> { let tmp_dir = tempdir()?; diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 352c8ab5b..f4667d523 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -57,6 +57,9 @@ pub enum RsFindMode { AutocxxRs, AutocxxRsArchive, AutocxxRsFile, + /// This just calls the callback instead of setting any environment variables. The callback + /// receives the path to the temporary directory. + Custom(Box), } /// API to test building pre-generated files. @@ -174,6 +177,7 @@ impl LinkableTryBuilder { "AUTOCXX_RS_FILE", self.temp_dir.path().join("gen0.include.rs"), ), + RsFindMode::Custom(f) => f(self.temp_dir.path()), }; std::panic::catch_unwind(|| { let test_cases = trybuild::TestCases::new(); diff --git a/parser/src/file_locations.rs b/parser/src/file_locations.rs index a113d0fde..6b3c58a2d 100644 --- a/parser/src/file_locations.rs +++ b/parser/src/file_locations.rs @@ -95,13 +95,13 @@ impl FileLocationStrategy { include!( #fname ); } } - FileLocationStrategy::FromAutocxxRsJsonArchive(fname) => { - let archive = File::open(fname).unwrap_or_else(|_| panic!("Unable to open {}. This may mean you didn't run the codegen tool (autocxx_gen) before building the Rust code.", fname.to_string_lossy())); + FileLocationStrategy::FromAutocxxRsJsonArchive(fnames) => { + let archive = std::env::split_paths(fnames).flat_map(File::open).next().unwrap_or_else(|| panic!("Unable to open any of the paths listed in {}. This may mean you didn't run the codegen tool (autocxx_gen) before building the Rust code.", fnames.to_string_lossy())); let multi_bindings: MultiBindings = serde_json::from_reader(archive) .unwrap_or_else(|_| { - panic!("Unable to interpret {} as JSON", fname.to_string_lossy()) + panic!("Unable to interpret {} as JSON", fnames.to_string_lossy()) }); - multi_bindings.get(config).unwrap_or_else(|err| panic!("Unable to find a suitable set of bindings within the JSON archive {} ({}). This likely means that the codegen tool hasn't been rerun since some changes in your include_cpp! macro.", fname.to_string_lossy(), err)) + multi_bindings.get(config).unwrap_or_else(|err| panic!("Unable to find a suitable set of bindings within the JSON archive {} ({}). This likely means that the codegen tool hasn't been rerun since some changes in your include_cpp! macro.", fnames.to_string_lossy(), err)) } } }