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

Parse rustc target names #1413

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
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