Skip to content

Commit

Permalink
Parse target triples
Browse files Browse the repository at this point in the history
But keep using a generated LLVM/Clang triple mapping for now.
  • Loading branch information
madsmtm committed Feb 28, 2025
1 parent 9131f33 commit 2529f3c
Show file tree
Hide file tree
Showing 9 changed files with 1,062 additions and 3,804 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/test-rustc-targets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Test nightly `rustc` targets and add issue comment if changed

on:
workflow_dispatch: # Allow running on-demand
schedule:
- cron: '0 3 * * 1,4' # Every Monday and Thursdag
push:
branches:
- 'main'
paths:
- 'dev-tools/gen-target-info/**'

jobs:
regenerate:
if: github.repository_owner == 'rust-lang'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: true

- name: Install current nightly Rust
run: |
rustup toolchain install nightly --no-self-update --profile minimal
rustup default nightly
- run: cargo update
- uses: Swatinem/rust-cache@v2

- name: Test with `RUSTFLAGS=--cfg=rustc_target_test cargo test --lib`
id: test
continue-on-error: true # We want to open an issue if it fails
run: RUSTFLAGS=--cfg=rustc_target_test cargo test --lib 2>&1 | tee test_output.txt

# Added to https://github.com/rust-lang/cc-rs/issues/1426
- name: Add issue comment if test failed
if: steps.test.outcome == 'failure'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh issue comment 1426 --body "
Failed parsing `rustc` target on `$(rustc --version)`.
<details><summary>Test output</summary>
<p>
\`\`\`
$(cat test_output.txt)
\`\`\`
</p>
</details>
" --head $(git branch --show-current)
3 changes: 0 additions & 3 deletions dev-tools/gen-target-info/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,3 @@ pub use target_specs::*;

mod read;
pub use read::*;

mod write;
pub use write::*;
70 changes: 6 additions & 64 deletions dev-tools/gen-target-info/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,18 @@ use gen_target_info::{
get_target_spec_from_msrv, get_target_specs_from_json, get_targets_msrv, RustcTargetSpecs,
};

const PRELUDE: &str = r#"//! This file is generated code. Please edit the generator
//! in dev-tools/gen-target-info if you need to make changes.
const PRELUDE: &str = r#"//! This file is generated code. Please edit the generator in
//! dev-tools/gen-target-info if you need to make changes, or see
//! src/target/llvm.rs if you need to configure a specific LLVM triple.
"#;

fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std::io::Result<()> {
writeln!(f, "use super::TargetInfo;")?;
writeln!(f)?;
writeln!(
f,
"pub(crate) const LIST: &[(&str, TargetInfo<'static>)] = &["
)?;
writeln!(f, "#[rustfmt::skip]")?;
writeln!(f, "pub(crate) const LLVM_TARGETS: &[(&str, &str)] = &[")?;

for (triple, spec) in &target_specs.0 {
let full_arch = triple.split_once('-').unwrap().0;
let arch = &spec.arch;
let vendor = spec.vendor.as_deref().unwrap_or("unknown");
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("");

// FIXME(madsmtm): Unnecessary once we bump MSRV to Rust 1.74
let llvm_target = if spec.llvm_target == "armv7-apple-ios7.0.0" {
"armv7-apple-ios".to_string()
} else if os == "uefi" {
// Override the UEFI LLVM targets.
//
// The rustc mappings (as of 1.82) for the UEFI targets are:
// * i686-unknown-uefi -> i686-unknown-windows-gnu
// * x86_64-unknown-uefi -> x86_64-unknown-windows
// * aarch64-unknown-uefi -> aarch64-unknown-windows
//
// However, in cc-rs all the UEFI targets use
// -windows-gnu. This has been the case since 2021 [1].
// * i686-unknown-uefi -> i686-unknown-windows-gnu
// * x86_64-unknown-uefi -> x86_64-unknown-windows-gnu
// * aarch64-unknown-uefi -> aarch64-unknown-windows-gnu
//
// For now, override the UEFI mapping to keep the behavior
// of cc-rs unchanged.
//
// TODO: as discussed in [2], it may be possible to switch
// to new UEFI targets added to clang, and regardless it
// would be good to have consistency between rustc and
// cc-rs.
//
// [1]: https://github.com/rust-lang/cc-rs/pull/623
// [2]: https://github.com/rust-lang/cc-rs/pull/1264
let arch = if spec.arch == "x86" {
"i686"
} else {
&spec.arch
};
format!("{}-unknown-windows-gnu", arch)
} else {
spec.llvm_target.clone()
};

writeln!(f, " (")?;
writeln!(f, " {triple:?},")?;
writeln!(f, " TargetInfo {{")?;
writeln!(f, " full_arch: {full_arch:?},")?;
writeln!(f, " arch: {arch:?},")?;
writeln!(f, " vendor: {vendor:?},")?;
writeln!(f, " os: {os:?},")?;
writeln!(f, " env: {env:?},")?;
writeln!(f, " abi: {abi:?},")?;
writeln!(f, " llvm_target: {llvm_target:?},")?;
writeln!(f, " }},")?;
writeln!(f, " ),")?;
writeln!(f, " ({triple:?}, {:?}),", spec.llvm_target)?;
}

writeln!(f, "];")?;
Expand Down
18 changes: 0 additions & 18 deletions dev-tools/gen-target-info/src/write.rs

This file was deleted.

22 changes: 15 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2202,14 +2202,14 @@ impl Build {
// So instead, we pass the deployment target with `-m*-version-min=`, and only
// pass it here on visionOS and Mac Catalyst where that option does not exist:
// https://github.com/rust-lang/cc-rs/issues/1383
let clang_target = if target.os == "visionos" || target.abi == "macabi" {
Cow::Owned(
target.versioned_llvm_target(&self.apple_deployment_target(target)),
)
let version = if target.os == "visionos" || target.abi == "macabi" {
Some(self.apple_deployment_target(target))
} else {
Cow::Borrowed(target.llvm_target)
None
};

let clang_target =
target.llvm_target(&self.get_raw_target()?, version.as_deref());
cmd.push_cc_arg(format!("--target={clang_target}").into());
}
}
Expand All @@ -2235,7 +2235,13 @@ impl Build {
// <https://github.com/microsoft/STL/pull/4741>.
cmd.push_cc_arg("-arch:SSE2".into());
} else {
cmd.push_cc_arg(format!("--target={}", target.llvm_target).into());
cmd.push_cc_arg(
format!(
"--target={}",
target.llvm_target(&self.get_raw_target()?, None)
)
.into(),
);
}
} else if target.full_arch == "i586" {
cmd.push_cc_arg("-arch:IA32".into());
Expand Down Expand Up @@ -3520,7 +3526,9 @@ impl Build {

fn get_target(&self) -> Result<TargetInfo<'_>, Error> {
match &self.target {
Some(t) if Some(&**t) != self.getenv_unwrap_str("TARGET").ok().as_deref() => t.parse(),
Some(t) if Some(&**t) != self.getenv_unwrap_str("TARGET").ok().as_deref() => {
TargetInfo::from_rustc_target(t)
}
// Fetch target information from environment if not set, or if the
// target was the same as the TARGET environment variable, in
// case the user did `build.target(&env::var("TARGET").unwrap())`.
Expand Down
90 changes: 0 additions & 90 deletions src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
//!
//! See the `target-lexicon` crate for a more principled approach to this.
use std::str::FromStr;

use crate::{Error, ErrorKind};

mod apple;
mod generated;
mod llvm;
Expand Down Expand Up @@ -43,90 +39,4 @@ pub(crate) struct TargetInfo<'a> {
///
/// This is the same as the value of `cfg!(target_abi)`.
pub abi: &'a str,
/// The unversioned LLVM/Clang target triple.
///
/// NOTE: You should never need to match on this explicitly, use the other
/// fields on [`TargetInfo`] instead.
pub llvm_target: &'a str,
}

impl FromStr for TargetInfo<'_> {
type Err = Error;

/// This will fail when using a custom target triple unknown to `rustc`.
fn from_str(target_triple: &str) -> Result<Self, Error> {
if let Ok(index) =
generated::LIST.binary_search_by_key(&target_triple, |(target_triple, _)| target_triple)
{
let (_, info) = &generated::LIST[index];
Ok(info.clone())
} else {
Err(Error::new(
ErrorKind::UnknownTarget,
format!(
"unknown target `{target_triple}`.
NOTE: `cc-rs` only supports a fixed set of targets when not in a build script.
- If adding a new target, you will need to fork of `cc-rs` until the target
has landed on nightly and the auto-generated list has been updated. See also
the `rustc` dev guide on adding a new target:
https://rustc-dev-guide.rust-lang.org/building/new-target.html
- If using a custom target, prefer to upstream it to `rustc` if possible,
otherwise open an issue with `cc-rs`:
https://github.com/rust-lang/cc-rs/issues/new
"
),
))
}
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use super::TargetInfo;

// Test tier 1 targets
#[test]
fn tier1() {
let targets = [
"aarch64-unknown-linux-gnu",
"aarch64-apple-darwin",
"i686-pc-windows-gnu",
"i686-pc-windows-msvc",
"i686-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
];

for target in targets {
// Check that it parses
let _ = TargetInfo::from_str(target).unwrap();
}
}

// Various custom target triples not (or no longer) known by `rustc`
#[test]
fn cannot_parse_extra() {
let targets = [
"aarch64-unknown-none-gnu",
"aarch64-uwp-windows-gnu",
"arm-frc-linux-gnueabi",
"arm-unknown-netbsd-eabi",
"armv7neon-unknown-linux-gnueabihf",
"armv7neon-unknown-linux-musleabihf",
"thumbv7-unknown-linux-gnueabihf",
"thumbv7-unknown-linux-musleabihf",
"x86_64-rumprun-netbsd",
"x86_64-unknown-linux",
];

for target in targets {
// Check that it does not parse
let _ = TargetInfo::from_str(target).unwrap_err();
}
}
}
Loading

0 comments on commit 2529f3c

Please sign in to comment.