xref: /rust-libc-0.2.174/build.rs (revision 4e7a6411)
150783355STrevor Gross use std::process::{Command, Output};
2da089f78STrevor Gross use std::{env, str};
379c80c4eSIsaac Woods 
4f8a12ee0SPietro Albini // List of cfgs this build script is allowed to set. The list is needed to support check-cfg, as we
5f8a12ee0SPietro Albini // need to know all the possible cfgs that this script will set. If you need to set another cfg
6f8a12ee0SPietro Albini // make sure to add it to this list as well.
7a598506fSYuri Astrakhan const ALLOWED_CFGS: &[&str] = &[
8e7a9c4a7SKleis Auke Wolthuizen     "emscripten_old_stat_abi",
9022a4398SSergio Gasquez     "espidf_time32",
10f8a12ee0SPietro Albini     "freebsd10",
11f8a12ee0SPietro Albini     "freebsd11",
12f8a12ee0SPietro Albini     "freebsd12",
13f8a12ee0SPietro Albini     "freebsd13",
14f8a12ee0SPietro Albini     "freebsd14",
152dc04b82SDavid Carlier     "freebsd15",
16aed5b564SOla x Nilsson     // Corresponds to `_FILE_OFFSET_BITS=64` in glibc
17aed5b564SOla x Nilsson     "gnu_file_offset_bits64",
18*4e7a6411SOla x Nilsson     // Corresponds to `_TIME_BITS=64` in glibc
19*4e7a6411SOla x Nilsson     "gnu_time_bits64",
205d2b17f3STrevor Gross     // FIXME(ctest): this config shouldn't be needed but ctest can't parse `const extern fn`
215d2b17f3STrevor Gross     "libc_const_extern_fn",
22f8a12ee0SPietro Albini     "libc_deny_warnings",
23f8a12ee0SPietro Albini     "libc_thread_local",
24ac6739c5SAlex Crichton     "libc_ctest",
2511079fd0SOla x Nilsson     // Corresponds to `__USE_TIME_BITS64` in UAPI
2611079fd0SOla x Nilsson     "linux_time_bits64",
2728e6ae29STrevor Gross     "musl_v1_2_3",
28f8a12ee0SPietro Albini ];
29f8a12ee0SPietro Albini 
30e74f7354SPietro Albini // Extra values to allow for check-cfg.
31a598506fSYuri Astrakhan const CHECK_CFG_EXTRA: &[(&str, &[&str])] = &[
329de4a5cfSJan Sommer     (
339de4a5cfSJan Sommer         "target_os",
34c2e03d56SHuang Qi         &[
35bb10d5f7S王宇逸             "switch", "aix", "ohos", "hurd", "rtems", "visionos", "nuttx", "cygwin",
36c2e03d56SHuang Qi         ],
379de4a5cfSJan Sommer     ),
3808f84149SFlorian Bartels     (
3908f84149SFlorian Bartels         "target_env",
4008f84149SFlorian Bartels         &["illumos", "wasi", "aix", "ohos", "nto71_iosock", "nto80"],
4108f84149SFlorian Bartels     ),
423d77fc68SDirreke     (
433d77fc68SDirreke         "target_arch",
443d77fc68SDirreke         &["loongarch64", "mips32r6", "mips64r6", "csky"],
453d77fc68SDirreke     ),
46e74f7354SPietro Albini ];
47e74f7354SPietro Albini 
main()4879c80c4eSIsaac Woods fn main() {
4945e1681dSYuki Okushi     // Avoid unnecessary re-building.
5045e1681dSYuki Okushi     println!("cargo:rerun-if-changed=build.rs");
5145e1681dSYuki Okushi 
52674cc1f4STrevor Gross     let (rustc_minor_ver, _is_nightly) = rustc_minor_nightly();
533fa021d7SJoe Richey     let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
544f1966f5Sgnzlbg     let libc_ci = env::var("LIBC_CI").is_ok();
55aed5b564SOla x Nilsson     let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
56aed5b564SOla x Nilsson     let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
57aed5b564SOla x Nilsson     let target_ptr_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap_or_default();
58aed5b564SOla x Nilsson     let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
59a17a91cdSgnzlbg 
60874e5277SYuki Okushi     // The ABI of libc used by std is backward compatible with FreeBSD 12.
613843c7dbSgnzlbg     // The ABI of libc from crates.io is backward compatible with FreeBSD 11.
624f1966f5Sgnzlbg     //
634f1966f5Sgnzlbg     // On CI, we detect the actual FreeBSD version and match its ABI exactly,
644f1966f5Sgnzlbg     // running tests to ensure that the ABI is correct.
65e13cde2dSTrevor Gross     println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_FREEBSD_VERSION");
66e13cde2dSTrevor Gross     // Allow overriding the default version for testing
67e13cde2dSTrevor Gross     let which_freebsd = if let Ok(version) = env::var("RUST_LIBC_UNSTABLE_FREEBSD_VERSION") {
68e13cde2dSTrevor Gross         let vers = version.parse().unwrap();
69e13cde2dSTrevor Gross         println!("cargo:warning=setting FreeBSD version to {vers}");
70e13cde2dSTrevor Gross         vers
71e13cde2dSTrevor Gross     } else if libc_ci {
729e43d14eSRalf Jung         which_freebsd().unwrap_or(11)
739e43d14eSRalf Jung     } else if rustc_dep_of_std {
749e43d14eSRalf Jung         12
759e43d14eSRalf Jung     } else {
769e43d14eSRalf Jung         11
779e43d14eSRalf Jung     };
78e13cde2dSTrevor Gross 
799e43d14eSRalf Jung     match which_freebsd {
809e43d14eSRalf Jung         x if x < 10 => panic!("FreeBSD older than 10 is not supported"),
819e43d14eSRalf Jung         10 => set_cfg("freebsd10"),
829e43d14eSRalf Jung         11 => set_cfg("freebsd11"),
839e43d14eSRalf Jung         12 => set_cfg("freebsd12"),
849e43d14eSRalf Jung         13 => set_cfg("freebsd13"),
859e43d14eSRalf Jung         14 => set_cfg("freebsd14"),
869e43d14eSRalf Jung         _ => set_cfg("freebsd15"),
877437d0a6Sgnzlbg     }
887437d0a6Sgnzlbg 
8992db93cfSKleis Auke Wolthuizen     match emcc_version_code() {
90e7a9c4a7SKleis Auke Wolthuizen         Some(v) if (v < 30142) => set_cfg("emscripten_old_stat_abi"),
91e7a9c4a7SKleis Auke Wolthuizen         // Non-Emscripten or version >= 3.1.42.
92e7a9c4a7SKleis Auke Wolthuizen         _ => (),
9363b0d673SKleis Auke Wolthuizen     }
9463b0d673SKleis Auke Wolthuizen 
95a485516eSReagan Bohan     let musl_v1_2_3 = env::var("RUST_LIBC_UNSTABLE_MUSL_V1_2_3").is_ok();
96a485516eSReagan Bohan     println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_MUSL_V1_2_3");
97a485516eSReagan Bohan     // loongarch64 and ohos have already updated
98a485516eSReagan Bohan     if musl_v1_2_3 || target_os == "loongarch64" || target_env == "ohos" {
99a485516eSReagan Bohan         // FIXME(musl): enable time64 api as well
100a485516eSReagan Bohan         set_cfg("musl_v1_2_3");
101a485516eSReagan Bohan     }
102c5b74654SOla x Nilsson     let linux_time_bits64 = env::var("RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64").is_ok();
103c5b74654SOla x Nilsson     println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64");
10411079fd0SOla x Nilsson     if linux_time_bits64 {
10511079fd0SOla x Nilsson         set_cfg("linux_time_bits64");
10611079fd0SOla x Nilsson     }
107aed5b564SOla x Nilsson     println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS");
108*4e7a6411SOla x Nilsson     println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_GNU_TIME_BITS");
109aed5b564SOla x Nilsson     if target_env == "gnu"
110aed5b564SOla x Nilsson         && target_os == "linux"
111aed5b564SOla x Nilsson         && target_ptr_width == "32"
112aed5b564SOla x Nilsson         && target_arch != "riscv32"
113aed5b564SOla x Nilsson         && target_arch != "x86_64"
114aed5b564SOla x Nilsson     {
115*4e7a6411SOla x Nilsson         match env::var("RUST_LIBC_UNSTABLE_GNU_TIME_BITS") {
116*4e7a6411SOla x Nilsson             Ok(val) if val == "64" => {
117aed5b564SOla x Nilsson                 set_cfg("gnu_file_offset_bits64");
118*4e7a6411SOla x Nilsson                 set_cfg("linux_time_bits64");
119*4e7a6411SOla x Nilsson                 set_cfg("gnu_time_bits64");
120aed5b564SOla x Nilsson             }
121*4e7a6411SOla x Nilsson             Ok(val) if val != "32" => {
122*4e7a6411SOla x Nilsson                 panic!("RUST_LIBC_UNSTABLE_GNU_TIME_BITS may only be set to '32' or '64'")
123*4e7a6411SOla x Nilsson             }
124*4e7a6411SOla x Nilsson             _ => {
125*4e7a6411SOla x Nilsson                 match env::var("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS") {
126*4e7a6411SOla x Nilsson                     Ok(val) if val == "64" => {
127*4e7a6411SOla x Nilsson                         set_cfg("gnu_file_offset_bits64");
128aed5b564SOla x Nilsson                     }
129aed5b564SOla x Nilsson                     Ok(val) if val != "32" => {
130aed5b564SOla x Nilsson                         panic!("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS may only be set to '32' or '64'")
131aed5b564SOla x Nilsson                     }
132aed5b564SOla x Nilsson                     _ => {}
133aed5b564SOla x Nilsson                 }
134*4e7a6411SOla x Nilsson             }
135*4e7a6411SOla x Nilsson         }
136*4e7a6411SOla x Nilsson     }
1373241ec58Sgnzlbg     // On CI: deny all warnings
1383241ec58Sgnzlbg     if libc_ci {
13988b7f0d9SPietro Albini         set_cfg("libc_deny_warnings");
1403241ec58Sgnzlbg     }
1413241ec58Sgnzlbg 
1423fa021d7SJoe Richey     // #[thread_local] is currently unstable
143df34d17bSJoe Richey     if rustc_dep_of_std {
14488b7f0d9SPietro Albini         set_cfg("libc_thread_local");
1453fa021d7SJoe Richey     }
146b0ba2de7SAaron Hill 
1475d2b17f3STrevor Gross     // Set unconditionally when ctest is not being invoked.
1485d2b17f3STrevor Gross     set_cfg("libc_const_extern_fn");
1495d2b17f3STrevor Gross 
150e7dcb974STrevor Gross     // Since Rust 1.80, configuration that isn't recognized by default needs to be provided to
151e7dcb974STrevor Gross     // avoid warnings.
152e7dcb974STrevor Gross     if rustc_minor_ver >= 80 {
153b636da0aSPietro Albini         for cfg in ALLOWED_CFGS {
15407bb6bfeSUrgau             if rustc_minor_ver >= 75 {
155d716b809SYuri Astrakhan                 println!("cargo:rustc-check-cfg=cfg({cfg})");
15607bb6bfeSUrgau             } else {
157d716b809SYuri Astrakhan                 println!("cargo:rustc-check-cfg=values({cfg})");
158b636da0aSPietro Albini             }
15907bb6bfeSUrgau         }
160d63eedc3SPietro Albini         for &(name, values) in CHECK_CFG_EXTRA {
161e74f7354SPietro Albini             let values = values.join("\",\"");
16207bb6bfeSUrgau             if rustc_minor_ver >= 75 {
163d716b809SYuri Astrakhan                 println!("cargo:rustc-check-cfg=cfg({name},values(\"{values}\"))");
16407bb6bfeSUrgau             } else {
165d716b809SYuri Astrakhan                 println!("cargo:rustc-check-cfg=values({name},\"{values}\")");
166e74f7354SPietro Albini             }
167b636da0aSPietro Albini         }
168576f7781SYuki Okushi     }
16907bb6bfeSUrgau }
17079c80c4eSIsaac Woods 
17150783355STrevor Gross /// Run `rustc --version` and capture the output, adjusting arguments as needed if `clippy-driver`
17250783355STrevor Gross /// is used instead.
rustc_version_cmd(is_clippy_driver: bool) -> Output17350783355STrevor Gross fn rustc_version_cmd(is_clippy_driver: bool) -> Output {
17450783355STrevor Gross     let rustc = env::var_os("RUSTC").expect("Failed to get rustc version: missing RUSTC env");
17550783355STrevor Gross 
176abcb8f87STrevor Gross     let mut cmd = match env::var_os("RUSTC_WRAPPER") {
177abcb8f87STrevor Gross         Some(ref wrapper) if wrapper.is_empty() => Command::new(rustc),
17850783355STrevor Gross         Some(wrapper) => {
17950783355STrevor Gross             let mut cmd = Command::new(wrapper);
18050783355STrevor Gross             cmd.arg(rustc);
18150783355STrevor Gross             if is_clippy_driver {
18250783355STrevor Gross                 cmd.arg("--rustc");
18350783355STrevor Gross             }
18450783355STrevor Gross 
18550783355STrevor Gross             cmd
18650783355STrevor Gross         }
18750783355STrevor Gross         None => Command::new(rustc),
18850783355STrevor Gross     };
18950783355STrevor Gross 
19050783355STrevor Gross     cmd.arg("--version");
19150783355STrevor Gross 
192bdfe8759STrevor Gross     let output = cmd.output().expect("Failed to get rustc version");
19350783355STrevor Gross 
194a598506fSYuri Astrakhan     assert!(
195a598506fSYuri Astrakhan         output.status.success(),
19650783355STrevor Gross         "failed to run rustc: {}",
19750783355STrevor Gross         String::from_utf8_lossy(output.stderr.as_slice())
19850783355STrevor Gross     );
19950783355STrevor Gross 
20050783355STrevor Gross     output
20150783355STrevor Gross }
20250783355STrevor Gross 
20350783355STrevor Gross /// Return the minor version of `rustc`, as well as a bool indicating whether or not the version
20450783355STrevor Gross /// is a nightly.
rustc_minor_nightly() -> (u32, bool)20540c19428Sbjorn3 fn rustc_minor_nightly() -> (u32, bool) {
20679c80c4eSIsaac Woods     macro_rules! otry {
20779c80c4eSIsaac Woods         ($e:expr) => {
20879c80c4eSIsaac Woods             match $e {
20979c80c4eSIsaac Woods                 Some(e) => e,
21040c19428Sbjorn3                 None => panic!("Failed to get rustc version"),
21179c80c4eSIsaac Woods             }
21279c80c4eSIsaac Woods         };
21379c80c4eSIsaac Woods     }
21479c80c4eSIsaac Woods 
21550783355STrevor Gross     let mut output = rustc_version_cmd(false);
216570d8926SNathaniel 
21750783355STrevor Gross     if otry!(str::from_utf8(&output.stdout).ok()).starts_with("clippy") {
21850783355STrevor Gross         output = rustc_version_cmd(true);
21952808cefSJacob Hoffman-Andrews     }
22052808cefSJacob Hoffman-Andrews 
22179c80c4eSIsaac Woods     let version = otry!(str::from_utf8(&output.stdout).ok());
22250783355STrevor Gross 
22379c80c4eSIsaac Woods     let mut pieces = version.split('.');
22479c80c4eSIsaac Woods 
225a598506fSYuri Astrakhan     assert_eq!(
226a598506fSYuri Astrakhan         pieces.next(),
227a598506fSYuri Astrakhan         Some("rustc 1"),
228a598506fSYuri Astrakhan         "Failed to get rustc version"
229a598506fSYuri Astrakhan     );
23079c80c4eSIsaac Woods 
231476b6759SAaron Hill     let minor = pieces.next();
232f10ee11fSAaron Hill 
233f10ee11fSAaron Hill     // If `rustc` was built from a tarball, its version string
234f10ee11fSAaron Hill     // will have neither a git hash nor a commit date
235f10ee11fSAaron Hill     // (e.g. "rustc 1.39.0"). Treat this case as non-nightly,
236f10ee11fSAaron Hill     // since a nightly build should either come from CI
237f10ee11fSAaron Hill     // or a git checkout
238f10ee11fSAaron Hill     let nightly_raw = otry!(pieces.next()).split('-').nth(1);
239a598506fSYuri Astrakhan     let nightly = nightly_raw.map_or(false, |raw| {
240a598506fSYuri Astrakhan         raw.starts_with("dev") || raw.starts_with("nightly")
241a598506fSYuri Astrakhan     });
242476b6759SAaron Hill     let minor = otry!(otry!(minor).parse().ok());
243476b6759SAaron Hill 
24440c19428Sbjorn3     (minor, nightly)
24579c80c4eSIsaac Woods }
2467437d0a6Sgnzlbg 
which_freebsd() -> Option<i32>2477437d0a6Sgnzlbg fn which_freebsd() -> Option<i32> {
248b8ac8c8aSEduardo Sánchez Muñoz     let output = Command::new("freebsd-version").output().ok()?;
2497437d0a6Sgnzlbg     if !output.status.success() {
2507437d0a6Sgnzlbg         return None;
2517437d0a6Sgnzlbg     }
2527437d0a6Sgnzlbg 
253bdfe8759STrevor Gross     let stdout = String::from_utf8(output.stdout).ok()?;
2547437d0a6Sgnzlbg 
2557437d0a6Sgnzlbg     match &stdout {
2563843c7dbSgnzlbg         s if s.starts_with("10") => Some(10),
2577437d0a6Sgnzlbg         s if s.starts_with("11") => Some(11),
2587437d0a6Sgnzlbg         s if s.starts_with("12") => Some(12),
2594a74f1e0SLuca Pizzamiglio         s if s.starts_with("13") => Some(13),
26065b16d94SYuki Okushi         s if s.starts_with("14") => Some(14),
2612dc04b82SDavid Carlier         s if s.starts_with("15") => Some(15),
2627437d0a6Sgnzlbg         _ => None,
2637437d0a6Sgnzlbg     }
2647437d0a6Sgnzlbg }
26588b7f0d9SPietro Albini 
emcc_version_code() -> Option<u64>26692db93cfSKleis Auke Wolthuizen fn emcc_version_code() -> Option<u64> {
2671e47c9cfSGuus Waals     let emcc = if cfg!(target_os = "windows") {
2681e47c9cfSGuus Waals         "emcc.bat"
2691e47c9cfSGuus Waals     } else {
2701e47c9cfSGuus Waals         "emcc"
2711e47c9cfSGuus Waals     };
2721e47c9cfSGuus Waals 
2731e47c9cfSGuus Waals     let output = Command::new(emcc).arg("-dumpversion").output().ok()?;
27463b0d673SKleis Auke Wolthuizen     if !output.status.success() {
27563b0d673SKleis Auke Wolthuizen         return None;
27663b0d673SKleis Auke Wolthuizen     }
27763b0d673SKleis Auke Wolthuizen 
278bdfe8759STrevor Gross     let version = String::from_utf8(output.stdout).ok()?;
279c4245923SKleis Auke Wolthuizen 
280c4245923SKleis Auke Wolthuizen     // Some Emscripten versions come with `-git` attached, so split the
281c4245923SKleis Auke Wolthuizen     // version string also on the `-` char.
282bdfe8759STrevor Gross     let mut pieces = version.trim().split(['.', '-']);
28363b0d673SKleis Auke Wolthuizen 
28492db93cfSKleis Auke Wolthuizen     let major = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
28592db93cfSKleis Auke Wolthuizen     let minor = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
28692db93cfSKleis Auke Wolthuizen     let patch = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
28763b0d673SKleis Auke Wolthuizen 
28892db93cfSKleis Auke Wolthuizen     Some(major * 10000 + minor * 100 + patch)
28963b0d673SKleis Auke Wolthuizen }
29063b0d673SKleis Auke Wolthuizen 
set_cfg(cfg: &str)29188b7f0d9SPietro Albini fn set_cfg(cfg: &str) {
292a598506fSYuri Astrakhan     assert!(
293a598506fSYuri Astrakhan         ALLOWED_CFGS.contains(&cfg),
294a598506fSYuri Astrakhan         "trying to set cfg {cfg}, but it is not in ALLOWED_CFGS",
295a598506fSYuri Astrakhan     );
296d716b809SYuri Astrakhan     println!("cargo:rustc-cfg={cfg}");
29788b7f0d9SPietro Albini }
298