autocxx_parser/
file_locations.rs1use proc_macro2::TokenStream;
10use quote::quote;
11use std::{fs::File, path::PathBuf};
12
13use crate::{multi_bindings::MultiBindings, IncludeCppConfig};
14
15pub enum FileLocationStrategy {
30 Custom(PathBuf),
31 FromAutocxxRsFile(PathBuf),
32 FromAutocxxRs(PathBuf),
33 FromOutDir(PathBuf),
34 FromAutocxxRsJsonArchive(PathBuf),
35 UnknownMaybeFromOutdir,
36}
37
38static BUILD_DIR_NAME: &str = "autocxx-build-dir";
39static RS_DIR_NAME: &str = "rs";
40static AUTOCXX_RS: &str = "AUTOCXX_RS";
41static AUTOCXX_RS_FILE: &str = "AUTOCXX_RS_FILE";
42static AUTOCXX_RS_JSON_ARCHIVE: &str = "AUTOCXX_RS_JSON_ARCHIVE";
43
44impl FileLocationStrategy {
45 pub fn new() -> Self {
46 match std::env::var_os(AUTOCXX_RS_JSON_ARCHIVE) {
47 Some(of) => FileLocationStrategy::FromAutocxxRsJsonArchive(PathBuf::from(of)),
48 None => match std::env::var_os(AUTOCXX_RS_FILE) {
49 Some(of) => FileLocationStrategy::FromAutocxxRsFile(PathBuf::from(of)),
50 None => match std::env::var_os(AUTOCXX_RS) {
51 None => match std::env::var_os("OUT_DIR") {
52 None => FileLocationStrategy::UnknownMaybeFromOutdir,
53 Some(od) => FileLocationStrategy::FromOutDir(PathBuf::from(od)),
54 },
55 Some(acrs) => FileLocationStrategy::FromAutocxxRs(PathBuf::from(acrs)),
56 },
57 },
58 }
59 }
60
61 pub fn new_custom(gen_dir: PathBuf) -> Self {
62 FileLocationStrategy::Custom(gen_dir)
63 }
64
65 pub fn make_include(&self, config: &IncludeCppConfig) -> TokenStream {
69 match self {
70 FileLocationStrategy::FromAutocxxRs(custom_dir) => {
71 let fname = config.get_rs_filename();
72 let fname = custom_dir.join(fname).to_str().unwrap().to_string();
73 quote! {
74 include!( #fname );
75 }
76 }
77 FileLocationStrategy::Custom(_) => panic!("Should never happen in the macro"),
78 FileLocationStrategy::UnknownMaybeFromOutdir | FileLocationStrategy::FromOutDir(_) => {
79 let fname = config.get_rs_filename();
80 let fname = format!("/{BUILD_DIR_NAME}/{RS_DIR_NAME}/{fname}");
81 quote! {
87 include!(concat!(env!("OUT_DIR"), #fname));
88 }
89 }
90 FileLocationStrategy::FromAutocxxRsFile(fname) => {
91 let fname = fname
92 .to_str()
93 .expect("AUTOCXX_RS_FILE environment variable contained non-UTF8 characters");
94 quote! {
95 include!( #fname );
96 }
97 }
98 FileLocationStrategy::FromAutocxxRsJsonArchive(fnames) => {
99 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()));
100 let multi_bindings: MultiBindings = serde_json::from_reader(archive)
101 .unwrap_or_else(|_| {
102 panic!("Unable to interpret {} as JSON", fnames.to_string_lossy())
103 });
104 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))
105 }
106 }
107 }
108
109 fn get_gen_dir(&self, suffix: &str) -> PathBuf {
110 let root = match self {
111 FileLocationStrategy::Custom(gen_dir)
112 | FileLocationStrategy::FromAutocxxRs(gen_dir) => gen_dir.clone(),
113 FileLocationStrategy::FromOutDir(out_dir) => out_dir.join(BUILD_DIR_NAME),
114 FileLocationStrategy::UnknownMaybeFromOutdir => {
115 panic!("Could not determine OUT_DIR or AUTOCXX_RS dir")
116 }
117 FileLocationStrategy::FromAutocxxRsFile(_) => {
118 panic!("It's invalid to set AUTOCXX_RS_FILE during the codegen phase.")
119 }
120 FileLocationStrategy::FromAutocxxRsJsonArchive(_) => {
121 panic!("It's invalid to set AUTOCXX_RS_JSON_ARCHIVE during the codegen phase.")
122 }
123 };
124 root.join(suffix)
125 }
126
127 pub fn get_rs_dir(&self) -> PathBuf {
129 self.get_gen_dir(RS_DIR_NAME)
130 }
131
132 pub fn get_include_dir(&self) -> PathBuf {
134 self.get_gen_dir("include")
135 }
136
137 pub fn get_cxx_dir(&self) -> PathBuf {
139 self.get_gen_dir("cxx")
140 }
141
142 pub fn set_cargo_env_vars_for_build(&self) {
145 if let FileLocationStrategy::Custom(_) = self {
146 println!(
147 "cargo:rustc-env={}={}",
148 AUTOCXX_RS,
149 self.get_rs_dir().to_str().unwrap()
150 );
151 }
152 }
153}
154
155impl Default for FileLocationStrategy {
156 fn default() -> Self {
157 Self::new()
158 }
159}