build.rs 5.5 KB

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