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>&amp;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&lt;&amp;Path&gt;</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&lt;&amp;str&gt;</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&lt;&amp;str&gt;</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