Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework GNU -m flags #1269

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions dev-tools/gen-target-info/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std
let os = spec.os.as_deref().unwrap_or("none");
let env = spec.env.as_deref().unwrap_or("");
let abi = spec.abi.as_deref().unwrap_or("");
let features = spec.cfgs.target_features.join(",");

let unversioned_llvm_target = if spec.llvm_target.contains("apple") {
// Remove deployment target information from LLVM target triples (we
Expand Down Expand Up @@ -84,6 +85,15 @@ fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std
f,
" unversioned_llvm_target: {unversioned_llvm_target:?},"
)?;
// NOTE: Features are generated from nightly versions, which will
// result in unstable values being output here as well. That is
// probably desirable since:
// 1. They're only used when `cc` is used outside a build script, and
// then we can't do feature detection, so we have to pick either
// the stable or the nightly representation.
// 2. The nightly representation is much more feature-ful, and `cc`'s
// conversion is going to be best-effort anyhow.
writeln!(f, " features: {features:?},")?;
writeln!(f, " }},")?;
writeln!(f, " ),")?;
}
Expand Down
38 changes: 34 additions & 4 deletions dev-tools/gen-target-info/src/read.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
use std::process;
use std::{io::BufRead, process};

use crate::{RustcTargetSpecs, TargetSpec};
use crate::{Cfgs, RustcTargetSpecs, TargetSpec};

fn get_cfgs(version: &str, target: &str) -> Cfgs {
let mut cmd = process::Command::new("rustc");
cmd.args([
version,
"-Zunstable-options",
"--print",
"cfg",
"--target",
target,
]);
cmd.env("RUSTC_BOOTSTRAP", "1");
cmd.stdout(process::Stdio::piped());
cmd.stderr(process::Stdio::inherit());

let process::Output { status, stdout, .. } = cmd.output().unwrap();

if !status.success() {
panic!("{:?} failed with non-zero exit status: {}", cmd, status)
}

let cfgs: Vec<String> = stdout.lines().map(|line| line.unwrap()).collect();
Cfgs::parse(&cfgs)
}

pub fn get_targets_msrv() -> Vec<u8> {
let mut cmd = process::Command::new("rustc");
Expand Down Expand Up @@ -37,7 +61,9 @@ pub fn get_target_spec_from_msrv(target: &str) -> TargetSpec {
panic!("{:?} failed with non-zero exit status: {}", cmd, status)
}

serde_json::from_slice(&stdout).unwrap()
let mut spec: TargetSpec = serde_json::from_slice(&stdout).unwrap();
spec.cfgs = get_cfgs("+1.63", target);
spec
}

pub fn get_target_specs_from_json() -> RustcTargetSpecs {
Expand All @@ -57,5 +83,9 @@ pub fn get_target_specs_from_json() -> RustcTargetSpecs {
panic!("{:?} failed with non-zero exit status: {}", cmd, status)
}

serde_json::from_slice(&stdout).unwrap()
let mut specs: RustcTargetSpecs = serde_json::from_slice(&stdout).unwrap();
for (target, spec) in &mut specs.0 {
spec.cfgs = get_cfgs("+nightly", target);
}
specs
}
48 changes: 48 additions & 0 deletions dev-tools/gen-target-info/src/target_specs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ pub struct TargetSpec {
pub vendor: Option<String>,
pub env: Option<String>,
pub abi: Option<String>,
pub target_pointer_width: String,
pub pre_link_args: Option<PreLinkArgs>,
#[serde(skip)]
pub cfgs: Cfgs,
}

#[derive(Debug, Deserialize)]
Expand All @@ -32,3 +35,48 @@ pub struct RustcTargetSpecs(
/// First field in the tuple is the rustc target
pub BTreeMap<String, TargetSpec>,
);

/// Potentially useful values from:
/// <https://doc.rust-lang.org/reference/conditional-compilation.html>
/// That are not directly / easily exposed in `TargetSpec`.
#[derive(Debug, Default)]
pub struct Cfgs {
pub target_features: Vec<String>,
pub target_families: Vec<String>,
pub target_endian: String,
pub target_atomics: Vec<String>,
pub target_thread_local: bool,
}

impl Cfgs {
pub fn parse(cfgs: &[String]) -> Self {
let mut target_features = vec![];
let mut target_families = vec![];
let mut target_endian = None;
let mut target_atomics = vec![];
let mut target_thread_local = false;
for cfg in cfgs {
let (name, value) = cfg
.split_once('=')
.map(|(n, v)| (n.trim(), Some(v.trim().trim_matches('"'))))
.unwrap_or((cfg.trim(), None));

match (name, value) {
("target_feature", Some(value)) => target_features.push(value.to_string()),
("target_family", Some(value)) => target_families.push(value.to_string()),
("target_endian", Some(value)) => target_endian = Some(value.to_string()),
("target_has_atomic", Some(value)) => target_atomics.push(value.to_string()),
("target_thread_local", None) => target_thread_local = true,
_ => {} // Ignore the rest
}
}

Self {
target_features,
target_families,
target_endian: target_endian.expect("must have target_endian cfg"),
target_atomics,
target_thread_local,
}
}
}
203 changes: 14 additions & 189 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,10 @@ impl Build {
/// When enabled on systems that support dynamic linking, this prevents
/// linking with the shared libraries.
///
/// If not specified, this falls back to:
/// - `-Ctarget-features=+crt-static` when compiling in a build script.
/// - A target-specific default.
///
/// # Example
///
/// ```no_run
Expand Down Expand Up @@ -1301,6 +1305,9 @@ impl Build {
/// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools.
///
/// This option defaults to `false`, and affect only msvc targets.
///
/// If not specified, this falls back to `-Ctarget-features=+crt-static`
/// when compiling in a build script.
pub fn static_crt(&mut self, static_crt: bool) -> &mut Build {
self.static_crt = Some(static_crt);
self
Expand Down Expand Up @@ -1944,18 +1951,10 @@ impl Build {
ToolFamily::Msvc { .. } => {
cmd.push_cc_arg("-nologo".into());

let crt_flag = match self.static_crt {
Some(true) => "-MT",
Some(false) => "-MD",
None => {
let features = self.getenv("CARGO_CFG_TARGET_FEATURE");
let features = features.as_deref().unwrap_or_default();
if features.to_string_lossy().contains("crt-static") {
"-MT"
} else {
"-MD"
}
}
let crt_flag = if self.static_crt.unwrap_or_else(|| target.crt_static()) {
"-MT"
} else {
"-MD"
};
cmd.push_cc_arg(crt_flag.into());

Expand Down Expand Up @@ -2042,16 +2041,6 @@ impl Build {
family.add_force_frame_pointer(cmd);
}

if !cmd.is_like_msvc() {
if target.arch == "x86" {
cmd.args.push("-m32".into());
} else if target.abi == "x32" {
cmd.args.push("-mx32".into());
} else if target.arch == "x86_64" || target.arch == "powerpc64" {
cmd.args.push("-m64".into());
}
}

// Target flags
match cmd.family {
ToolFamily::Clang { .. } => {
Expand Down Expand Up @@ -2142,175 +2131,11 @@ impl Build {
cmd.args.push("-finput-charset=utf-8".into());
}

if self.static_flag.is_none() {
let features = self.getenv("CARGO_CFG_TARGET_FEATURE");
let features = features.as_deref().unwrap_or_default();
if features.to_string_lossy().contains("crt-static") {
cmd.args.push("-static".into());
}
}

// armv7 targets get to use armv7 instructions
if (target.full_arch.starts_with("armv7")
|| target.full_arch.starts_with("thumbv7"))
&& (target.os == "linux" || target.vendor == "kmc")
{
cmd.args.push("-march=armv7-a".into());

if target.abi == "eabihf" {
// lowest common denominator FPU
cmd.args.push("-mfpu=vfpv3-d16".into());
}
}

// (x86 Android doesn't say "eabi")
if target.os == "android" && target.full_arch.contains("v7") {
cmd.args.push("-march=armv7-a".into());
cmd.args.push("-mthumb".into());
if !target.full_arch.contains("neon") {
// On android we can guarantee some extra float instructions
// (specified in the android spec online)
// NEON guarantees even more; see below.
cmd.args.push("-mfpu=vfpv3-d16".into());
}
cmd.args.push("-mfloat-abi=softfp".into());
}

if target.full_arch.contains("neon") {
cmd.args.push("-mfpu=neon-vfpv4".into());
}

if target.full_arch == "armv4t" && target.os == "linux" {
cmd.args.push("-march=armv4t".into());
cmd.args.push("-marm".into());
cmd.args.push("-mfloat-abi=soft".into());
}

if target.full_arch == "armv5te" && target.os == "linux" {
cmd.args.push("-march=armv5te".into());
cmd.args.push("-marm".into());
cmd.args.push("-mfloat-abi=soft".into());
}

// For us arm == armv6 by default
if target.full_arch == "arm" && target.os == "linux" {
cmd.args.push("-march=armv6".into());
cmd.args.push("-marm".into());
if target.abi == "eabihf" {
cmd.args.push("-mfpu=vfp".into());
} else {
cmd.args.push("-mfloat-abi=soft".into());
}
}

// We can guarantee some settings for FRC
if target.arch == "arm" && target.vendor == "frc" {
cmd.args.push("-march=armv7-a".into());
cmd.args.push("-mcpu=cortex-a9".into());
cmd.args.push("-mfpu=vfpv3".into());
cmd.args.push("-mfloat-abi=softfp".into());
cmd.args.push("-marm".into());
}

// Turn codegen down on i586 to avoid some instructions.
if target.full_arch == "i586" && target.os == "linux" {
cmd.args.push("-march=pentium".into());
if self.static_flag.is_none() && target.crt_static() {
cmd.args.push("-static".into());
}

// Set codegen level for i686 correctly
if target.full_arch == "i686" && target.os == "linux" {
cmd.args.push("-march=i686".into());
}

// Looks like `musl-gcc` makes it hard for `-m32` to make its way
// all the way to the linker, so we need to actually instruct the
// linker that we're generating 32-bit executables as well. This'll
// typically only be used for build scripts which transitively use
// these flags that try to compile executables.
if target.arch == "x86" && target.env == "musl" {
cmd.args.push("-Wl,-melf_i386".into());
}

if target.arch == "arm" && target.os == "none" && target.abi == "eabihf" {
cmd.args.push("-mfloat-abi=hard".into())
}
if target.full_arch.starts_with("thumb") {
cmd.args.push("-mthumb".into());
}
if target.full_arch.starts_with("thumbv6m") {
cmd.args.push("-march=armv6s-m".into());
}
if target.full_arch.starts_with("thumbv7em") {
cmd.args.push("-march=armv7e-m".into());

if target.abi == "eabihf" {
cmd.args.push("-mfpu=fpv4-sp-d16".into())
}
}
if target.full_arch.starts_with("thumbv7m") {
cmd.args.push("-march=armv7-m".into());
}
if target.full_arch.starts_with("thumbv8m.base") {
cmd.args.push("-march=armv8-m.base".into());
}
if target.full_arch.starts_with("thumbv8m.main") {
cmd.args.push("-march=armv8-m.main".into());

if target.abi == "eabihf" {
cmd.args.push("-mfpu=fpv5-sp-d16".into())
}
}
if target.full_arch.starts_with("armebv7r") | target.full_arch.starts_with("armv7r")
{
if target.full_arch.starts_with("armeb") {
cmd.args.push("-mbig-endian".into());
} else {
cmd.args.push("-mlittle-endian".into());
}

// ARM mode
cmd.args.push("-marm".into());

// R Profile
cmd.args.push("-march=armv7-r".into());

if target.abi == "eabihf" {
// lowest common denominator FPU
// (see Cortex-R4 technical reference manual)
cmd.args.push("-mfpu=vfpv3-d16".into())
}
}
if target.full_arch.starts_with("armv7a") {
cmd.args.push("-march=armv7-a".into());

if target.abi == "eabihf" {
// lowest common denominator FPU
cmd.args.push("-mfpu=vfpv3-d16".into());
}
}
if target.arch == "riscv32" || target.arch == "riscv64" {
// get the 32i/32imac/32imc/64gc/64imac/... part
let arch = &target.full_arch[5..];
if arch.starts_with("64") {
if matches!(target.os, "linux" | "freebsd" | "netbsd") {
cmd.args.push(("-march=rv64gc").into());
cmd.args.push("-mabi=lp64d".into());
} else {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=lp64".into());
}
} else if arch.starts_with("32") {
if target.os == "linux" {
cmd.args.push(("-march=rv32gc").into());
cmd.args.push("-mabi=ilp32d".into());
} else {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=ilp32".into());
}
} else {
cmd.args.push("-mcmodel=medany".into());
}
}
cmd.args.extend(target.gnu_arch_flags());
}
}

Expand Down
Loading