133d722a9Sopenharmony_ciuse std::fmt::{self, Debug}; 233d722a9Sopenharmony_ciuse std::marker::PhantomData; 333d722a9Sopenharmony_ciuse std::path::Path; 433d722a9Sopenharmony_ci 533d722a9Sopenharmony_ci/// Build configuration. See [CFG]. 633d722a9Sopenharmony_cipub struct Cfg<'a> { 733d722a9Sopenharmony_ci /// See [`CFG.include_prefix`][CFG#cfginclude_prefix]. 833d722a9Sopenharmony_ci pub include_prefix: &'a str, 933d722a9Sopenharmony_ci /// See [`CFG.exported_header_dirs`][CFG#cfgexported_header_dirs]. 1033d722a9Sopenharmony_ci pub exported_header_dirs: Vec<&'a Path>, 1133d722a9Sopenharmony_ci /// See [`CFG.exported_header_prefixes`][CFG#cfgexported_header_prefixes]. 1233d722a9Sopenharmony_ci pub exported_header_prefixes: Vec<&'a str>, 1333d722a9Sopenharmony_ci /// See [`CFG.exported_header_links`][CFG#cfgexported_header_links]. 1433d722a9Sopenharmony_ci pub exported_header_links: Vec<&'a str>, 1533d722a9Sopenharmony_ci /// See [`CFG.doxygen`][CFG#cfgdoxygen]. 1633d722a9Sopenharmony_ci pub doxygen: bool, 1733d722a9Sopenharmony_ci marker: PhantomData<*const ()>, // !Send + !Sync 1833d722a9Sopenharmony_ci} 1933d722a9Sopenharmony_ci 2033d722a9Sopenharmony_ci/// Global configuration of the current build. 2133d722a9Sopenharmony_ci/// 2233d722a9Sopenharmony_ci/// <br> 2333d722a9Sopenharmony_ci/// 2433d722a9Sopenharmony_ci/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>&str</strong></div> 2533d722a9Sopenharmony_ci/// 2633d722a9Sopenharmony_ci/// ## **`CFG.include_prefix`** 2733d722a9Sopenharmony_ci/// 2833d722a9Sopenharmony_ci/// The prefix at which C++ code from your crate as well as directly dependent 2933d722a9Sopenharmony_ci/// crates can access the code generated during this build. 3033d722a9Sopenharmony_ci/// 3133d722a9Sopenharmony_ci/// By default, the `include_prefix` is equal to the name of the current crate. 3233d722a9Sopenharmony_ci/// That means if your crate is called `demo` and has Rust source files in a 3333d722a9Sopenharmony_ci/// *src/* directory and maybe some handwritten C++ header files in an 3433d722a9Sopenharmony_ci/// *include/* directory, then the current crate as well as downstream crates 3533d722a9Sopenharmony_ci/// might include them as follows: 3633d722a9Sopenharmony_ci/// 3733d722a9Sopenharmony_ci/// ``` 3833d722a9Sopenharmony_ci/// # const _: &str = stringify! { 3933d722a9Sopenharmony_ci/// // include one of the handwritten headers: 4033d722a9Sopenharmony_ci/// #include "demo/include/wow.h" 4133d722a9Sopenharmony_ci/// 4233d722a9Sopenharmony_ci/// // include a header generated from Rust cxx::bridge: 4333d722a9Sopenharmony_ci/// #include "demo/src/lib.rs.h" 4433d722a9Sopenharmony_ci/// # }; 4533d722a9Sopenharmony_ci/// ``` 4633d722a9Sopenharmony_ci/// 4733d722a9Sopenharmony_ci/// By modifying `CFG.include_prefix` we can substitute a prefix that is 4833d722a9Sopenharmony_ci/// different from the crate name if desired. Here we'll change it to 4933d722a9Sopenharmony_ci/// `"path/to"` which will make import paths take the form 5033d722a9Sopenharmony_ci/// `"path/to/include/wow.h"` and `"path/to/src/lib.rs.h"`. 5133d722a9Sopenharmony_ci/// 5233d722a9Sopenharmony_ci/// ```no_run 5333d722a9Sopenharmony_ci/// // build.rs 5433d722a9Sopenharmony_ci/// 5533d722a9Sopenharmony_ci/// use cxx_build::CFG; 5633d722a9Sopenharmony_ci/// 5733d722a9Sopenharmony_ci/// fn main() { 5833d722a9Sopenharmony_ci/// CFG.include_prefix = "path/to"; 5933d722a9Sopenharmony_ci/// 6033d722a9Sopenharmony_ci/// cxx_build::bridge("src/lib.rs") 6133d722a9Sopenharmony_ci/// .file("src/demo.cc") // probably contains `#include "path/to/src/lib.rs.h"` 6233d722a9Sopenharmony_ci/// /* ... */ 6333d722a9Sopenharmony_ci/// .compile("demo"); 6433d722a9Sopenharmony_ci/// } 6533d722a9Sopenharmony_ci/// ``` 6633d722a9Sopenharmony_ci/// 6733d722a9Sopenharmony_ci/// Note that cross-crate imports are only made available between **direct 6833d722a9Sopenharmony_ci/// dependencies**. Another crate must directly depend on your crate in order to 6933d722a9Sopenharmony_ci/// #include its headers; a transitive dependency is not sufficient. 7033d722a9Sopenharmony_ci/// Additionally, headers from a direct dependency are only importable if the 7133d722a9Sopenharmony_ci/// dependency's Cargo.toml manifest contains a `links` key. If not, its headers 7233d722a9Sopenharmony_ci/// will not be importable from outside of the same crate. 7333d722a9Sopenharmony_ci/// 7433d722a9Sopenharmony_ci/// <br> 7533d722a9Sopenharmony_ci/// 7633d722a9Sopenharmony_ci/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&Path></strong></div> 7733d722a9Sopenharmony_ci/// 7833d722a9Sopenharmony_ci/// ## **`CFG.exported_header_dirs`** 7933d722a9Sopenharmony_ci/// 8033d722a9Sopenharmony_ci/// A vector of absolute paths. The current crate, directly dependent crates, 8133d722a9Sopenharmony_ci/// and further crates to which this crate's headers are exported (see below) 8233d722a9Sopenharmony_ci/// will be able to `#include` headers from these directories. 8333d722a9Sopenharmony_ci/// 8433d722a9Sopenharmony_ci/// Adding a directory to `exported_header_dirs` is similar to adding it to the 8533d722a9Sopenharmony_ci/// current build via the `cc` crate's [`Build::include`][cc::Build::include], 8633d722a9Sopenharmony_ci/// but *also* makes the directory available to downstream crates that want to 8733d722a9Sopenharmony_ci/// `#include` one of the headers from your crate. If the dir were added only 8833d722a9Sopenharmony_ci/// using `Build::include`, the downstream crate including your header would 8933d722a9Sopenharmony_ci/// need to manually add the same directory to their own build as well. 9033d722a9Sopenharmony_ci/// 9133d722a9Sopenharmony_ci/// When using `exported_header_dirs`, your crate must also set a `links` key 9233d722a9Sopenharmony_ci/// for itself in Cargo.toml. See [*the `links` manifest key*][links]. The 9333d722a9Sopenharmony_ci/// reason is that Cargo imposes no ordering on the execution of build scripts 9433d722a9Sopenharmony_ci/// without a `links` key, which means the downstream crate's build script might 9533d722a9Sopenharmony_ci/// execute before yours decides what to put into `exported_header_dirs`. 9633d722a9Sopenharmony_ci/// 9733d722a9Sopenharmony_ci/// [links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key 9833d722a9Sopenharmony_ci/// 9933d722a9Sopenharmony_ci/// ### Example 10033d722a9Sopenharmony_ci/// 10133d722a9Sopenharmony_ci/// One of your crate's headers wants to include a system library, such as 10233d722a9Sopenharmony_ci/// `#include "Python.h"`. 10333d722a9Sopenharmony_ci/// 10433d722a9Sopenharmony_ci/// ```no_run 10533d722a9Sopenharmony_ci/// // build.rs 10633d722a9Sopenharmony_ci/// 10733d722a9Sopenharmony_ci/// use cxx_build::CFG; 10833d722a9Sopenharmony_ci/// use std::path::PathBuf; 10933d722a9Sopenharmony_ci/// 11033d722a9Sopenharmony_ci/// fn main() { 11133d722a9Sopenharmony_ci/// let python3 = pkg_config::probe_library("python3").unwrap(); 11233d722a9Sopenharmony_ci/// let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path); 11333d722a9Sopenharmony_ci/// CFG.exported_header_dirs.extend(python_include_paths); 11433d722a9Sopenharmony_ci/// 11533d722a9Sopenharmony_ci/// cxx_build::bridge("src/bridge.rs").compile("demo"); 11633d722a9Sopenharmony_ci/// } 11733d722a9Sopenharmony_ci/// ``` 11833d722a9Sopenharmony_ci/// 11933d722a9Sopenharmony_ci/// ### Example 12033d722a9Sopenharmony_ci/// 12133d722a9Sopenharmony_ci/// Your crate wants to rearrange the headers that it exports vs how they're 12233d722a9Sopenharmony_ci/// laid out locally inside the crate's source directory. 12333d722a9Sopenharmony_ci/// 12433d722a9Sopenharmony_ci/// Suppose the crate as published contains a file at `./include/myheader.h` but 12533d722a9Sopenharmony_ci/// wants it available to downstream crates as `#include "foo/v1/public.h"`. 12633d722a9Sopenharmony_ci/// 12733d722a9Sopenharmony_ci/// ```no_run 12833d722a9Sopenharmony_ci/// // build.rs 12933d722a9Sopenharmony_ci/// 13033d722a9Sopenharmony_ci/// use cxx_build::CFG; 13133d722a9Sopenharmony_ci/// use std::path::Path; 13233d722a9Sopenharmony_ci/// use std::{env, fs}; 13333d722a9Sopenharmony_ci/// 13433d722a9Sopenharmony_ci/// fn main() { 13533d722a9Sopenharmony_ci/// let out_dir = env::var_os("OUT_DIR").unwrap(); 13633d722a9Sopenharmony_ci/// let headers = Path::new(&out_dir).join("headers"); 13733d722a9Sopenharmony_ci/// CFG.exported_header_dirs.push(&headers); 13833d722a9Sopenharmony_ci/// 13933d722a9Sopenharmony_ci/// // We contain `include/myheader.h` locally, but 14033d722a9Sopenharmony_ci/// // downstream will use `#include "foo/v1/public.h"` 14133d722a9Sopenharmony_ci/// let foo = headers.join("foo").join("v1"); 14233d722a9Sopenharmony_ci/// fs::create_dir_all(&foo).unwrap(); 14333d722a9Sopenharmony_ci/// fs::copy("include/myheader.h", foo.join("public.h")).unwrap(); 14433d722a9Sopenharmony_ci/// 14533d722a9Sopenharmony_ci/// cxx_build::bridge("src/bridge.rs").compile("demo"); 14633d722a9Sopenharmony_ci/// } 14733d722a9Sopenharmony_ci/// ``` 14833d722a9Sopenharmony_ci/// 14933d722a9Sopenharmony_ci/// <p style="margin:0"><br><br></p> 15033d722a9Sopenharmony_ci/// 15133d722a9Sopenharmony_ci/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&str></strong></div> 15233d722a9Sopenharmony_ci/// 15333d722a9Sopenharmony_ci/// ## **`CFG.exported_header_prefixes`** 15433d722a9Sopenharmony_ci/// 15533d722a9Sopenharmony_ci/// Vector of strings. These each refer to the `include_prefix` of one of your 15633d722a9Sopenharmony_ci/// direct dependencies, or a prefix thereof. They describe which of your 15733d722a9Sopenharmony_ci/// dependencies participate in your crate's C++ public API, as opposed to 15833d722a9Sopenharmony_ci/// private use by your crate's implementation. 15933d722a9Sopenharmony_ci/// 16033d722a9Sopenharmony_ci/// As a general rule, if one of your headers `#include`s something from one of 16133d722a9Sopenharmony_ci/// your dependencies, you need to put that dependency's `include_prefix` into 16233d722a9Sopenharmony_ci/// `CFG.exported_header_prefixes` (*or* their `links` key into 16333d722a9Sopenharmony_ci/// `CFG.exported_header_links`; see below). On the other hand if only your C++ 16433d722a9Sopenharmony_ci/// implementation files and *not* your headers are importing from the 16533d722a9Sopenharmony_ci/// dependency, you do not export that dependency. 16633d722a9Sopenharmony_ci/// 16733d722a9Sopenharmony_ci/// The significance of exported headers is that if downstream code (crate ) 16833d722a9Sopenharmony_ci/// contains an `#include` of a header from your crate (ℬ) and your header 16933d722a9Sopenharmony_ci/// contains an `#include` of something from your dependency (), the exported 17033d722a9Sopenharmony_ci/// dependency becomes available during the downstream crate 's build. 17133d722a9Sopenharmony_ci/// Otherwise the downstream crate doesn't know about and wouldn't be able 17233d722a9Sopenharmony_ci/// to find what header your header is referring to, and would fail to build. 17333d722a9Sopenharmony_ci/// 17433d722a9Sopenharmony_ci/// When using `exported_header_prefixes`, your crate must also set a `links` 17533d722a9Sopenharmony_ci/// key for itself in Cargo.toml. 17633d722a9Sopenharmony_ci/// 17733d722a9Sopenharmony_ci/// ### Example 17833d722a9Sopenharmony_ci/// 17933d722a9Sopenharmony_ci/// Suppose you have a crate with 5 direct dependencies and the `include_prefix` 18033d722a9Sopenharmony_ci/// for each one are: 18133d722a9Sopenharmony_ci/// 18233d722a9Sopenharmony_ci/// - "crate0" 18333d722a9Sopenharmony_ci/// - "group/api/crate1" 18433d722a9Sopenharmony_ci/// - "group/api/crate2" 18533d722a9Sopenharmony_ci/// - "group/api/contrib/crate3" 18633d722a9Sopenharmony_ci/// - "detail/crate4" 18733d722a9Sopenharmony_ci/// 18833d722a9Sopenharmony_ci/// Your header involves types from the first four so we re-export those as part 18933d722a9Sopenharmony_ci/// of your public API, while crate4 is only used internally by your cc file not 19033d722a9Sopenharmony_ci/// your header, so we do not export: 19133d722a9Sopenharmony_ci/// 19233d722a9Sopenharmony_ci/// ```no_run 19333d722a9Sopenharmony_ci/// // build.rs 19433d722a9Sopenharmony_ci/// 19533d722a9Sopenharmony_ci/// use cxx_build::CFG; 19633d722a9Sopenharmony_ci/// 19733d722a9Sopenharmony_ci/// fn main() { 19833d722a9Sopenharmony_ci/// CFG.exported_header_prefixes = vec!["crate0", "group/api"]; 19933d722a9Sopenharmony_ci/// 20033d722a9Sopenharmony_ci/// cxx_build::bridge("src/bridge.rs") 20133d722a9Sopenharmony_ci/// .file("src/impl.cc") 20233d722a9Sopenharmony_ci/// .compile("demo"); 20333d722a9Sopenharmony_ci/// } 20433d722a9Sopenharmony_ci/// ``` 20533d722a9Sopenharmony_ci/// 20633d722a9Sopenharmony_ci/// <p style="margin:0"><br><br></p> 20733d722a9Sopenharmony_ci/// 20833d722a9Sopenharmony_ci/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>Vec<&str></strong></div> 20933d722a9Sopenharmony_ci/// 21033d722a9Sopenharmony_ci/// ## **`CFG.exported_header_links`** 21133d722a9Sopenharmony_ci/// 21233d722a9Sopenharmony_ci/// Vector of strings. These each refer to the `links` attribute ([*the `links` 21333d722a9Sopenharmony_ci/// manifest key*][links]) of one of your crate's direct dependencies. 21433d722a9Sopenharmony_ci/// 21533d722a9Sopenharmony_ci/// This achieves an equivalent result to `CFG.exported_header_prefixes` by 21633d722a9Sopenharmony_ci/// re-exporting a dependency as part of your crate's public API, except with 21733d722a9Sopenharmony_ci/// finer grained control for cases when multiple crates might be sharing the 21833d722a9Sopenharmony_ci/// same `include_prefix` and you'd like to export some but not others. Links 21933d722a9Sopenharmony_ci/// attributes are guaranteed to be unique identifiers by Cargo. 22033d722a9Sopenharmony_ci/// 22133d722a9Sopenharmony_ci/// When using `exported_header_links`, your crate must also set a `links` key 22233d722a9Sopenharmony_ci/// for itself in Cargo.toml. 22333d722a9Sopenharmony_ci/// 22433d722a9Sopenharmony_ci/// ### Example 22533d722a9Sopenharmony_ci/// 22633d722a9Sopenharmony_ci/// ```no_run 22733d722a9Sopenharmony_ci/// // build.rs 22833d722a9Sopenharmony_ci/// 22933d722a9Sopenharmony_ci/// use cxx_build::CFG; 23033d722a9Sopenharmony_ci/// 23133d722a9Sopenharmony_ci/// fn main() { 23233d722a9Sopenharmony_ci/// CFG.exported_header_links.push("git2"); 23333d722a9Sopenharmony_ci/// 23433d722a9Sopenharmony_ci/// cxx_build::bridge("src/bridge.rs").compile("demo"); 23533d722a9Sopenharmony_ci/// } 23633d722a9Sopenharmony_ci/// ``` 23733d722a9Sopenharmony_ci/// 23833d722a9Sopenharmony_ci/// <p style="margin:0"><br><br></p> 23933d722a9Sopenharmony_ci/// 24033d722a9Sopenharmony_ci/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;opacity:.73"><strong>bool</strong></div> 24133d722a9Sopenharmony_ci/// 24233d722a9Sopenharmony_ci/// ## **`CFG.doxygen`** 24333d722a9Sopenharmony_ci/// 24433d722a9Sopenharmony_ci/// Boolean. Whether to propagate Rust documentation from inside the cxx::bridge 24533d722a9Sopenharmony_ci/// module as Doxygen-style comments in the generated C++ header. 24633d722a9Sopenharmony_ci/// 24733d722a9Sopenharmony_ci/// Documentation on the following are supported: 24833d722a9Sopenharmony_ci/// 24933d722a9Sopenharmony_ci/// - shared structs, and fields of shared structs 25033d722a9Sopenharmony_ci/// - shared enums, and their variants 25133d722a9Sopenharmony_ci/// - extern "Rust" opaque types 25233d722a9Sopenharmony_ci/// - extern "Rust" functions, including methods/member functions 25333d722a9Sopenharmony_ci/// 25433d722a9Sopenharmony_ci/// ### Example 25533d722a9Sopenharmony_ci/// 25633d722a9Sopenharmony_ci/// ```no_run 25733d722a9Sopenharmony_ci/// // build.rs 25833d722a9Sopenharmony_ci/// 25933d722a9Sopenharmony_ci/// use cxx_build::CFG; 26033d722a9Sopenharmony_ci/// 26133d722a9Sopenharmony_ci/// fn main() { 26233d722a9Sopenharmony_ci/// CFG.doxygen = true; 26333d722a9Sopenharmony_ci/// 26433d722a9Sopenharmony_ci/// cxx_build::bridge("src/bridge.rs").compile("demo"); 26533d722a9Sopenharmony_ci/// } 26633d722a9Sopenharmony_ci/// ``` 26733d722a9Sopenharmony_ci/// 26833d722a9Sopenharmony_ci/// ```rust 26933d722a9Sopenharmony_ci/// // src/bridge.rs 27033d722a9Sopenharmony_ci/// 27133d722a9Sopenharmony_ci/// #[cxx::bridge] 27233d722a9Sopenharmony_ci/// mod ffi { 27333d722a9Sopenharmony_ci/// /// documentation of MyStruct 27433d722a9Sopenharmony_ci/// pub struct MyStruct { 27533d722a9Sopenharmony_ci/// /// documentation of the struct field 27633d722a9Sopenharmony_ci/// lol: String, 27733d722a9Sopenharmony_ci/// } 27833d722a9Sopenharmony_ci/// 27933d722a9Sopenharmony_ci/// extern "Rust" { 28033d722a9Sopenharmony_ci/// /// documentation of MyType 28133d722a9Sopenharmony_ci/// type MyType; 28233d722a9Sopenharmony_ci/// 28333d722a9Sopenharmony_ci/// /// function documentation 28433d722a9Sopenharmony_ci/// fn asdf() -> bool; 28533d722a9Sopenharmony_ci/// } 28633d722a9Sopenharmony_ci/// } 28733d722a9Sopenharmony_ci/// # 28833d722a9Sopenharmony_ci/// # pub struct MyType; 28933d722a9Sopenharmony_ci/// # fn asdf() -> bool { true } 29033d722a9Sopenharmony_ci/// # fn main() {} 29133d722a9Sopenharmony_ci/// ``` 29233d722a9Sopenharmony_ci/// 29333d722a9Sopenharmony_ci/// With `CFG.doxygen` enabled, the generated C++ header through which 29433d722a9Sopenharmony_ci/// downstream C++ code will be able to access these shared structs and extern 29533d722a9Sopenharmony_ci/// "Rust" signatures will have the Rust documentation comments propagated as 29633d722a9Sopenharmony_ci/// Doxygen-style comments: 29733d722a9Sopenharmony_ci/// 29833d722a9Sopenharmony_ci/// ```cpp 29933d722a9Sopenharmony_ci/// /// documentation of MyStruct 30033d722a9Sopenharmony_ci/// struct MyStruct final { 30133d722a9Sopenharmony_ci/// /// documentation of the struct field 30233d722a9Sopenharmony_ci/// ::rust::String lol; 30333d722a9Sopenharmony_ci/// … 30433d722a9Sopenharmony_ci/// }; 30533d722a9Sopenharmony_ci/// ``` 30633d722a9Sopenharmony_ci/// 30733d722a9Sopenharmony_ci/// Otherwise by default (without `CFG.doxygen`) they'll just be `//` comments. 30833d722a9Sopenharmony_ci#[cfg(doc)] 30933d722a9Sopenharmony_cipub static mut CFG: Cfg = Cfg { 31033d722a9Sopenharmony_ci include_prefix: "", 31133d722a9Sopenharmony_ci exported_header_dirs: Vec::new(), 31233d722a9Sopenharmony_ci exported_header_prefixes: Vec::new(), 31333d722a9Sopenharmony_ci exported_header_links: Vec::new(), 31433d722a9Sopenharmony_ci doxygen: false, 31533d722a9Sopenharmony_ci marker: PhantomData, 31633d722a9Sopenharmony_ci}; 31733d722a9Sopenharmony_ci 31833d722a9Sopenharmony_ciimpl<'a> Debug for Cfg<'a> { 31933d722a9Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 32033d722a9Sopenharmony_ci let Self { 32133d722a9Sopenharmony_ci include_prefix, 32233d722a9Sopenharmony_ci exported_header_dirs, 32333d722a9Sopenharmony_ci exported_header_prefixes, 32433d722a9Sopenharmony_ci exported_header_links, 32533d722a9Sopenharmony_ci doxygen, 32633d722a9Sopenharmony_ci marker: _, 32733d722a9Sopenharmony_ci } = self; 32833d722a9Sopenharmony_ci formatter 32933d722a9Sopenharmony_ci .debug_struct("Cfg") 33033d722a9Sopenharmony_ci .field("include_prefix", include_prefix) 33133d722a9Sopenharmony_ci .field("exported_header_dirs", exported_header_dirs) 33233d722a9Sopenharmony_ci .field("exported_header_prefixes", exported_header_prefixes) 33333d722a9Sopenharmony_ci .field("exported_header_links", exported_header_links) 33433d722a9Sopenharmony_ci .field("doxygen", doxygen) 33533d722a9Sopenharmony_ci .finish() 33633d722a9Sopenharmony_ci } 33733d722a9Sopenharmony_ci} 33833d722a9Sopenharmony_ci 33933d722a9Sopenharmony_ci#[cfg(not(doc))] 34033d722a9Sopenharmony_cipub use self::r#impl::Cfg::CFG; 34133d722a9Sopenharmony_ci 34233d722a9Sopenharmony_ci#[cfg(not(doc))] 34333d722a9Sopenharmony_cimod r#impl { 34433d722a9Sopenharmony_ci use crate::intern::{intern, InternedString}; 34533d722a9Sopenharmony_ci use crate::syntax::map::UnorderedMap as Map; 34633d722a9Sopenharmony_ci use crate::vec::{self, InternedVec as _}; 34733d722a9Sopenharmony_ci use once_cell::sync::Lazy; 34833d722a9Sopenharmony_ci use std::cell::RefCell; 34933d722a9Sopenharmony_ci use std::fmt::{self, Debug}; 35033d722a9Sopenharmony_ci use std::marker::PhantomData; 35133d722a9Sopenharmony_ci use std::ops::{Deref, DerefMut}; 35233d722a9Sopenharmony_ci use std::sync::{PoisonError, RwLock}; 35333d722a9Sopenharmony_ci 35433d722a9Sopenharmony_ci struct CurrentCfg { 35533d722a9Sopenharmony_ci include_prefix: InternedString, 35633d722a9Sopenharmony_ci exported_header_dirs: Vec<InternedString>, 35733d722a9Sopenharmony_ci exported_header_prefixes: Vec<InternedString>, 35833d722a9Sopenharmony_ci exported_header_links: Vec<InternedString>, 35933d722a9Sopenharmony_ci doxygen: bool, 36033d722a9Sopenharmony_ci } 36133d722a9Sopenharmony_ci 36233d722a9Sopenharmony_ci impl CurrentCfg { 36333d722a9Sopenharmony_ci fn default() -> Self { 36433d722a9Sopenharmony_ci let include_prefix = crate::env_os("CARGO_PKG_NAME") 36533d722a9Sopenharmony_ci .map(|pkg| intern(&pkg.to_string_lossy())) 36633d722a9Sopenharmony_ci .unwrap_or_default(); 36733d722a9Sopenharmony_ci let exported_header_dirs = Vec::new(); 36833d722a9Sopenharmony_ci let exported_header_prefixes = Vec::new(); 36933d722a9Sopenharmony_ci let exported_header_links = Vec::new(); 37033d722a9Sopenharmony_ci let doxygen = false; 37133d722a9Sopenharmony_ci CurrentCfg { 37233d722a9Sopenharmony_ci include_prefix, 37333d722a9Sopenharmony_ci exported_header_dirs, 37433d722a9Sopenharmony_ci exported_header_prefixes, 37533d722a9Sopenharmony_ci exported_header_links, 37633d722a9Sopenharmony_ci doxygen, 37733d722a9Sopenharmony_ci } 37833d722a9Sopenharmony_ci } 37933d722a9Sopenharmony_ci } 38033d722a9Sopenharmony_ci 38133d722a9Sopenharmony_ci static CURRENT: Lazy<RwLock<CurrentCfg>> = Lazy::new(|| RwLock::new(CurrentCfg::default())); 38233d722a9Sopenharmony_ci 38333d722a9Sopenharmony_ci thread_local! { 38433d722a9Sopenharmony_ci // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved, 38533d722a9Sopenharmony_ci // we can delete this thread local side table and instead make each CFG 38633d722a9Sopenharmony_ci // instance directly own the associated super::Cfg. 38733d722a9Sopenharmony_ci // 38833d722a9Sopenharmony_ci // #[allow(const_item_mutation)] 38933d722a9Sopenharmony_ci // pub const CFG: Cfg = Cfg { 39033d722a9Sopenharmony_ci // cfg: AtomicPtr::new(ptr::null_mut()), 39133d722a9Sopenharmony_ci // }; 39233d722a9Sopenharmony_ci // pub struct Cfg { 39333d722a9Sopenharmony_ci // cfg: AtomicPtr<super::Cfg>, 39433d722a9Sopenharmony_ci // } 39533d722a9Sopenharmony_ci // 39633d722a9Sopenharmony_ci static CONST_DEREFS: RefCell<Map<Handle, Box<super::Cfg<'static>>>> = RefCell::default(); 39733d722a9Sopenharmony_ci } 39833d722a9Sopenharmony_ci 39933d722a9Sopenharmony_ci #[derive(Eq, PartialEq, Hash)] 40033d722a9Sopenharmony_ci struct Handle(*const Cfg<'static>); 40133d722a9Sopenharmony_ci 40233d722a9Sopenharmony_ci impl<'a> Cfg<'a> { 40333d722a9Sopenharmony_ci fn current() -> super::Cfg<'a> { 40433d722a9Sopenharmony_ci let current = CURRENT.read().unwrap_or_else(PoisonError::into_inner); 40533d722a9Sopenharmony_ci let include_prefix = current.include_prefix.str(); 40633d722a9Sopenharmony_ci let exported_header_dirs = current.exported_header_dirs.vec(); 40733d722a9Sopenharmony_ci let exported_header_prefixes = current.exported_header_prefixes.vec(); 40833d722a9Sopenharmony_ci let exported_header_links = current.exported_header_links.vec(); 40933d722a9Sopenharmony_ci let doxygen = current.doxygen; 41033d722a9Sopenharmony_ci super::Cfg { 41133d722a9Sopenharmony_ci include_prefix, 41233d722a9Sopenharmony_ci exported_header_dirs, 41333d722a9Sopenharmony_ci exported_header_prefixes, 41433d722a9Sopenharmony_ci exported_header_links, 41533d722a9Sopenharmony_ci doxygen, 41633d722a9Sopenharmony_ci marker: PhantomData, 41733d722a9Sopenharmony_ci } 41833d722a9Sopenharmony_ci } 41933d722a9Sopenharmony_ci 42033d722a9Sopenharmony_ci const fn handle(self: &Cfg<'a>) -> Handle { 42133d722a9Sopenharmony_ci Handle(<*const Cfg>::cast(self)) 42233d722a9Sopenharmony_ci } 42333d722a9Sopenharmony_ci } 42433d722a9Sopenharmony_ci 42533d722a9Sopenharmony_ci // Since super::Cfg is !Send and !Sync, all Cfg are thread local and will 42633d722a9Sopenharmony_ci // drop on the same thread where they were created. 42733d722a9Sopenharmony_ci pub enum Cfg<'a> { 42833d722a9Sopenharmony_ci Mut(super::Cfg<'a>), 42933d722a9Sopenharmony_ci CFG, 43033d722a9Sopenharmony_ci } 43133d722a9Sopenharmony_ci 43233d722a9Sopenharmony_ci impl<'a> Debug for Cfg<'a> { 43333d722a9Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 43433d722a9Sopenharmony_ci if let Cfg::Mut(cfg) = self { 43533d722a9Sopenharmony_ci Debug::fmt(cfg, formatter) 43633d722a9Sopenharmony_ci } else { 43733d722a9Sopenharmony_ci Debug::fmt(&Cfg::current(), formatter) 43833d722a9Sopenharmony_ci } 43933d722a9Sopenharmony_ci } 44033d722a9Sopenharmony_ci } 44133d722a9Sopenharmony_ci 44233d722a9Sopenharmony_ci impl<'a> Deref for Cfg<'a> { 44333d722a9Sopenharmony_ci type Target = super::Cfg<'a>; 44433d722a9Sopenharmony_ci 44533d722a9Sopenharmony_ci fn deref(&self) -> &Self::Target { 44633d722a9Sopenharmony_ci if let Cfg::Mut(cfg) = self { 44733d722a9Sopenharmony_ci cfg 44833d722a9Sopenharmony_ci } else { 44933d722a9Sopenharmony_ci let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg { 45033d722a9Sopenharmony_ci &mut **derefs 45133d722a9Sopenharmony_ci .borrow_mut() 45233d722a9Sopenharmony_ci .entry(self.handle()) 45333d722a9Sopenharmony_ci .or_insert_with(|| Box::new(Cfg::current())) 45433d722a9Sopenharmony_ci }); 45533d722a9Sopenharmony_ci unsafe { &mut *cfg } 45633d722a9Sopenharmony_ci } 45733d722a9Sopenharmony_ci } 45833d722a9Sopenharmony_ci } 45933d722a9Sopenharmony_ci 46033d722a9Sopenharmony_ci impl<'a> DerefMut for Cfg<'a> { 46133d722a9Sopenharmony_ci fn deref_mut(&mut self) -> &mut Self::Target { 46233d722a9Sopenharmony_ci if let Cfg::CFG = self { 46333d722a9Sopenharmony_ci CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle())); 46433d722a9Sopenharmony_ci *self = Cfg::Mut(Cfg::current()); 46533d722a9Sopenharmony_ci } 46633d722a9Sopenharmony_ci match self { 46733d722a9Sopenharmony_ci Cfg::Mut(cfg) => cfg, 46833d722a9Sopenharmony_ci Cfg::CFG => unreachable!(), 46933d722a9Sopenharmony_ci } 47033d722a9Sopenharmony_ci } 47133d722a9Sopenharmony_ci } 47233d722a9Sopenharmony_ci 47333d722a9Sopenharmony_ci impl<'a> Drop for Cfg<'a> { 47433d722a9Sopenharmony_ci fn drop(&mut self) { 47533d722a9Sopenharmony_ci if let Cfg::Mut(cfg) = self { 47633d722a9Sopenharmony_ci let super::Cfg { 47733d722a9Sopenharmony_ci include_prefix, 47833d722a9Sopenharmony_ci exported_header_dirs, 47933d722a9Sopenharmony_ci exported_header_prefixes, 48033d722a9Sopenharmony_ci exported_header_links, 48133d722a9Sopenharmony_ci doxygen, 48233d722a9Sopenharmony_ci marker: _, 48333d722a9Sopenharmony_ci } = cfg; 48433d722a9Sopenharmony_ci let mut current = CURRENT.write().unwrap_or_else(PoisonError::into_inner); 48533d722a9Sopenharmony_ci current.include_prefix = intern(include_prefix); 48633d722a9Sopenharmony_ci current.exported_header_dirs = vec::intern(exported_header_dirs); 48733d722a9Sopenharmony_ci current.exported_header_prefixes = vec::intern(exported_header_prefixes); 48833d722a9Sopenharmony_ci current.exported_header_links = vec::intern(exported_header_links); 48933d722a9Sopenharmony_ci current.doxygen = *doxygen; 49033d722a9Sopenharmony_ci } else { 49133d722a9Sopenharmony_ci CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle())); 49233d722a9Sopenharmony_ci } 49333d722a9Sopenharmony_ci } 49433d722a9Sopenharmony_ci } 49533d722a9Sopenharmony_ci} 496