Isaac Woods | 79c80c4 | 2018-09-17 19:33:52 +0100 | [diff] [blame] | 1 | use std::env; |
| 2 | use std::process::Command; |
| 3 | use std::str; |
| 4 | |
| 5 | fn main() { |
Joel Galenson | 5068367 | 2021-04-08 10:31:43 -0700 | [diff] [blame] | 6 | // Avoid unnecessary re-building. |
| 7 | println!("cargo:rerun-if-changed=build.rs"); |
| 8 | |
| 9 | let (rustc_minor_ver, is_nightly) = rustc_minor_nightly().expect("Failed to get rustc version"); |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 10 | let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok(); |
| 11 | let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok(); |
Joel Galenson | 5068367 | 2021-04-08 10:31:43 -0700 | [diff] [blame] | 12 | let const_extern_fn_cargo_feature = env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok(); |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 13 | let libc_ci = env::var("LIBC_CI").is_ok(); |
Joel Galenson | 5068367 | 2021-04-08 10:31:43 -0700 | [diff] [blame] | 14 | let target = env::var("TARGET").unwrap(); |
gnzlbg | a17a91c | 2019-02-07 11:37:21 +0100 | [diff] [blame] | 15 | |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 16 | if env::var("CARGO_FEATURE_USE_STD").is_ok() { |
gnzlbg | 4ac26af | 2019-05-24 13:22:03 +0200 | [diff] [blame] | 17 | println!( |
| 18 | "cargo:warning=\"libc's use_std cargo feature is deprecated since libc 0.2.55; \ |
| 19 | please consider using the `std` cargo feature instead\"" |
| 20 | ); |
| 21 | } |
| 22 | |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 23 | // The ABI of libc used by libstd is backward compatible with FreeBSD 10. |
| 24 | // The ABI of libc from crates.io is backward compatible with FreeBSD 11. |
| 25 | // |
| 26 | // On CI, we detect the actual FreeBSD version and match its ABI exactly, |
| 27 | // running tests to ensure that the ABI is correct. |
| 28 | match which_freebsd() { |
| 29 | Some(10) if libc_ci || rustc_dep_of_std => { |
| 30 | println!("cargo:rustc-cfg=freebsd10") |
gnzlbg | 7437d0a | 2019-05-16 14:53:51 +0200 | [diff] [blame] | 31 | } |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 32 | Some(11) if libc_ci => println!("cargo:rustc-cfg=freebsd11"), |
| 33 | Some(12) if libc_ci => println!("cargo:rustc-cfg=freebsd12"), |
| 34 | Some(13) if libc_ci => println!("cargo:rustc-cfg=freebsd13"), |
| 35 | Some(_) | None => println!("cargo:rustc-cfg=freebsd11"), |
| 36 | } |
| 37 | |
| 38 | // On CI: deny all warnings |
| 39 | if libc_ci { |
| 40 | println!("cargo:rustc-cfg=libc_deny_warnings"); |
gnzlbg | 7437d0a | 2019-05-16 14:53:51 +0200 | [diff] [blame] | 41 | } |
| 42 | |
gnzlbg | a17a91c | 2019-02-07 11:37:21 +0100 | [diff] [blame] | 43 | // Rust >= 1.15 supports private module use: |
| 44 | if rustc_minor_ver >= 15 || rustc_dep_of_std { |
| 45 | println!("cargo:rustc-cfg=libc_priv_mod_use"); |
| 46 | } |
| 47 | |
| 48 | // Rust >= 1.19 supports unions: |
| 49 | if rustc_minor_ver >= 19 || rustc_dep_of_std { |
| 50 | println!("cargo:rustc-cfg=libc_union"); |
| 51 | } |
| 52 | |
| 53 | // Rust >= 1.24 supports const mem::size_of: |
| 54 | if rustc_minor_ver >= 24 || rustc_dep_of_std { |
| 55 | println!("cargo:rustc-cfg=libc_const_size_of"); |
| 56 | } |
| 57 | |
| 58 | // Rust >= 1.25 supports repr(align): |
| 59 | if rustc_minor_ver >= 25 || rustc_dep_of_std || align_cargo_feature { |
| 60 | println!("cargo:rustc-cfg=libc_align"); |
| 61 | } |
| 62 | |
| 63 | // Rust >= 1.30 supports `core::ffi::c_void`, so libc can just re-export it. |
| 64 | // Otherwise, it defines an incompatible type to retaining |
| 65 | // backwards-compatibility. |
| 66 | if rustc_minor_ver >= 30 || rustc_dep_of_std { |
| 67 | println!("cargo:rustc-cfg=libc_core_cvoid"); |
| 68 | } |
| 69 | |
Haibo Huang | f49534a | 2020-08-20 03:31:02 -0700 | [diff] [blame] | 70 | // Rust >= 1.33 supports repr(packed(N)) and cfg(target_vendor). |
gnzlbg | a17a91c | 2019-02-07 11:37:21 +0100 | [diff] [blame] | 71 | if rustc_minor_ver >= 33 || rustc_dep_of_std { |
| 72 | println!("cargo:rustc-cfg=libc_packedN"); |
Haibo Huang | f49534a | 2020-08-20 03:31:02 -0700 | [diff] [blame] | 73 | println!("cargo:rustc-cfg=libc_cfg_target_vendor"); |
Isaac Woods | 79c80c4 | 2018-09-17 19:33:52 +0100 | [diff] [blame] | 74 | } |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 75 | |
| 76 | // #[thread_local] is currently unstable |
| 77 | if rustc_dep_of_std { |
| 78 | println!("cargo:rustc-cfg=libc_thread_local"); |
| 79 | } |
| 80 | |
| 81 | if const_extern_fn_cargo_feature { |
| 82 | if !is_nightly || rustc_minor_ver < 40 { |
| 83 | panic!("const-extern-fn requires a nightly compiler >= 1.40") |
| 84 | } |
| 85 | println!("cargo:rustc-cfg=libc_const_extern_fn"); |
| 86 | } |
Joel Galenson | 5068367 | 2021-04-08 10:31:43 -0700 | [diff] [blame] | 87 | |
| 88 | // For unknown reason, libiconv can't be linked by adding #[link(name = iconv)] to |
| 89 | // a macOS-specific struct, so we do the linking here. |
| 90 | if target.contains("-apple-") { |
| 91 | println!("cargo:rustc-link-lib=iconv"); |
| 92 | } |
Isaac Woods | 79c80c4 | 2018-09-17 19:33:52 +0100 | [diff] [blame] | 93 | } |
| 94 | |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 95 | fn rustc_minor_nightly() -> Option<(u32, bool)> { |
Isaac Woods | 79c80c4 | 2018-09-17 19:33:52 +0100 | [diff] [blame] | 96 | macro_rules! otry { |
| 97 | ($e:expr) => { |
| 98 | match $e { |
| 99 | Some(e) => e, |
| 100 | None => return None, |
| 101 | } |
| 102 | }; |
| 103 | } |
| 104 | |
| 105 | let rustc = otry!(env::var_os("RUSTC")); |
| 106 | let output = otry!(Command::new(rustc).arg("--version").output().ok()); |
| 107 | let version = otry!(str::from_utf8(&output.stdout).ok()); |
| 108 | let mut pieces = version.split('.'); |
| 109 | |
| 110 | if pieces.next() != Some("rustc 1") { |
| 111 | return None; |
| 112 | } |
| 113 | |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 114 | let minor = pieces.next(); |
| 115 | |
| 116 | // If `rustc` was built from a tarball, its version string |
| 117 | // will have neither a git hash nor a commit date |
| 118 | // (e.g. "rustc 1.39.0"). Treat this case as non-nightly, |
| 119 | // since a nightly build should either come from CI |
| 120 | // or a git checkout |
| 121 | let nightly_raw = otry!(pieces.next()).split('-').nth(1); |
| 122 | let nightly = nightly_raw |
| 123 | .map(|raw| raw.starts_with("dev") || raw.starts_with("nightly")) |
| 124 | .unwrap_or(false); |
| 125 | let minor = otry!(otry!(minor).parse().ok()); |
| 126 | |
| 127 | Some((minor, nightly)) |
Isaac Woods | 79c80c4 | 2018-09-17 19:33:52 +0100 | [diff] [blame] | 128 | } |
gnzlbg | 7437d0a | 2019-05-16 14:53:51 +0200 | [diff] [blame] | 129 | |
| 130 | fn which_freebsd() -> Option<i32> { |
| 131 | let output = std::process::Command::new("freebsd-version").output().ok(); |
| 132 | if output.is_none() { |
| 133 | return None; |
| 134 | } |
| 135 | let output = output.unwrap(); |
| 136 | if !output.status.success() { |
| 137 | return None; |
| 138 | } |
| 139 | |
| 140 | let stdout = String::from_utf8(output.stdout).ok(); |
| 141 | if stdout.is_none() { |
| 142 | return None; |
| 143 | } |
| 144 | let stdout = stdout.unwrap(); |
| 145 | |
| 146 | match &stdout { |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 147 | s if s.starts_with("10") => Some(10), |
gnzlbg | 7437d0a | 2019-05-16 14:53:51 +0200 | [diff] [blame] | 148 | s if s.starts_with("11") => Some(11), |
| 149 | s if s.starts_with("12") => Some(12), |
Matthew Maurer | e9a2a71 | 2020-01-02 15:36:15 -0800 | [diff] [blame] | 150 | s if s.starts_with("13") => Some(13), |
gnzlbg | 7437d0a | 2019-05-16 14:53:51 +0200 | [diff] [blame] | 151 | _ => None, |
| 152 | } |
| 153 | } |