libc-rs/build.rs
gnzlbg a17a91cdbf Fix build on all platforms
This PR fixes the build on all platforms and all Rust version down to the
minimum Rust version supported by libc: Rust 1.13.0.

The `build.rs` is extended with logic to detect the newer Rust features used by
`libc` since Rust 1.13.0:

* Rust 1.19.0: `untagged_unions`. APIs using untagged unions are gated on
  `cfg(libc_unions)` and not available on older Rust versions.

* Rust 1.25.0: `repr(align)`. Because `repr(align)` cannot be parsed by older
  Rust versions, all uses of `repr(align)` are split into `align.rs` and
  `no_align.rs` modules, which are gated on the `cfg(libc_align)` at the top
  level. These modules sometimes contain macros that are expanded at the top
  level to avoid privacy issues (`pub(crate)` is not available in older Rust
  versions). Closes #1242 .

* Rust : `const` `mem::size_of`. These uses are worked around with hardcoded
  constants on older Rust versions.

Also, `repr(packed)` structs cannot automatically `derive()` some traits like
`Debug`. These have been moved into `s_no_extra_traits!` and the lint of missing
`Debug` implementations on public items is silenced for these. We can manually
implement the `extra_traits` for these in a follow up PR. This is tracked
in #1243. Also, `extra_traits` does not enable `align` manually anymore.

Since `f64::to_bits` is not available in older Rust versions, its usage
has been replaced with a `transmute` to an `u64` which is what that method
does under the hood.

Closes #1232 .
2019-02-07 13:44:32 +01:00

66 lines
1.9 KiB
Rust

use std::env;
use std::process::Command;
use std::str;
fn main() {
let rustc_minor_ver =
rustc_minor_version().expect("Failed to get rustc version");
let rustc_dep_of_std =
std::env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
let align_cargo_feature = std::env::var("CARGO_FEATURE_ALIGN").is_ok();
// Rust >= 1.15 supports private module use:
if rustc_minor_ver >= 15 || rustc_dep_of_std {
println!("cargo:rustc-cfg=libc_priv_mod_use");
}
// Rust >= 1.19 supports unions:
if rustc_minor_ver >= 19 || rustc_dep_of_std {
println!("cargo:rustc-cfg=libc_union");
}
// Rust >= 1.24 supports const mem::size_of:
if rustc_minor_ver >= 24 || rustc_dep_of_std {
println!("cargo:rustc-cfg=libc_const_size_of");
}
// Rust >= 1.25 supports repr(align):
if rustc_minor_ver >= 25 || rustc_dep_of_std || align_cargo_feature {
println!("cargo:rustc-cfg=libc_align");
}
// Rust >= 1.30 supports `core::ffi::c_void`, so libc can just re-export it.
// Otherwise, it defines an incompatible type to retaining
// backwards-compatibility.
if rustc_minor_ver >= 30 || rustc_dep_of_std {
println!("cargo:rustc-cfg=libc_core_cvoid");
}
// Rust >= 1.33 supports repr(packed(N))
if rustc_minor_ver >= 33 || rustc_dep_of_std {
println!("cargo:rustc-cfg=libc_packedN");
}
}
fn rustc_minor_version() -> Option<u32> {
macro_rules! otry {
($e:expr) => {
match $e {
Some(e) => e,
None => return None,
}
};
}
let rustc = otry!(env::var_os("RUSTC"));
let output = otry!(Command::new(rustc).arg("--version").output().ok());
let version = otry!(str::from_utf8(&output.stdout).ok());
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
otry!(pieces.next()).parse().ok()
}