autocxx: Support multiple AUTOCXX_RS_JSON_ARCHIVE entries
Backport of https://github.com/google/autocxx/pull/1147.
Change-Id: I1657b15cff87110a177eecf49944eabc9b628c89
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/third_party/autocxx/gen/cmd/src/main.rs b/third_party/autocxx/gen/cmd/src/main.rs
index 8b109c3..f8db241 100644
--- a/third_party/autocxx/gen/cmd/src/main.rs
+++ b/third_party/autocxx/gen/cmd/src/main.rs
@@ -74,7 +74,11 @@
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/third_party/autocxx/gen/cmd/tests/cmd_test.rs b/third_party/autocxx/gen/cmd/tests/cmd_test.rs
index 7e455a2..6fd3382 100644
--- a/third_party/autocxx/gen/cmd/tests/cmd_test.rs
+++ b/third_party/autocxx/gen/cmd/tests/cmd_test.rs
@@ -147,6 +147,58 @@
}
#[test]
+fn test_gen_archive_first_entry() -> Result<(), Box<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
+ 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<dyn std::error::Error>> {
let tmp_dir = tempdir()?;
diff --git a/third_party/autocxx/integration-tests/src/lib.rs b/third_party/autocxx/integration-tests/src/lib.rs
index 352c8ab..f4667d5 100644
--- a/third_party/autocxx/integration-tests/src/lib.rs
+++ b/third_party/autocxx/integration-tests/src/lib.rs
@@ -57,6 +57,9 @@
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<dyn FnOnce(&Path)>),
}
/// API to test building pre-generated files.
@@ -174,6 +177,7 @@
"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/third_party/autocxx/parser/src/file_locations.rs b/third_party/autocxx/parser/src/file_locations.rs
index a113d0f..6b3c58a 100644
--- a/third_party/autocxx/parser/src/file_locations.rs
+++ b/third_party/autocxx/parser/src/file_locations.rs
@@ -95,13 +95,13 @@
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))
}
}
}