Skip to content

Commit

Permalink
Use rustc's knowledge of LLVM/Clang target triples (#1252)
Browse files Browse the repository at this point in the history
* Rename Target -> TargetInfo

* Add LLVM target triple to TargetInfo

* Remove AppleOs wrapper struct

* Simplify SDK name lookup code

* Fix passing --target to Clang

Use the same LLVM target triple as rustc does

* Don't pass `--target` twice on Windows

* Simplify LLVM target triple version removal

* Appease clippy

* Fix naming mistake

* Simplify
  • Loading branch information
madsmtm authored Nov 2, 2024
1 parent 290a629 commit 9c663ca
Show file tree
Hide file tree
Showing 9 changed files with 764 additions and 479 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/regenerate-target-info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr create --base main --title "Update src/target_info.rs" --body "Automatically regenerated in CI"
gh pr create --base main --title "Update src/target/generated.rs" --body "Automatically regenerated in CI"
25 changes: 22 additions & 3 deletions dev-tools/gen-target-info/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const PRELUDE: &str = r#"//! This file is generated code. Please edit the genera
"#;

fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std::io::Result<()> {
writeln!(f, "use super::Target;")?;
writeln!(f, "use super::TargetInfo;")?;
writeln!(f, "use std::borrow::Cow;")?;
writeln!(f)?;
writeln!(f, "pub(crate) const LIST: &[(&str, Target)] = &[")?;
writeln!(f, "pub(crate) const LIST: &[(&str, TargetInfo)] = &[")?;

for (triple, spec) in &target_specs.0 {
let full_arch = triple.split_once('-').unwrap().0;
Expand All @@ -24,15 +24,34 @@ fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std
let env = spec.env.as_deref().unwrap_or("");
let abi = spec.abi.as_deref().unwrap_or("");

// Remove deployment target information from LLVM target triples (we
// will add this in another part of CC).
//
// FIXME(madsmtm): Should become unnecessary after
// https://github.com/rust-lang/rust/pull/131037
let unversioned_llvm_target = if spec.llvm_target.contains("apple") {
let mut components = spec.llvm_target.split("-").collect::<Vec<_>>();

components[2] = components[2].trim_end_matches(|c: char| c.is_numeric() || c == '.');

components.join("-")
} else {
spec.llvm_target.clone()
};

writeln!(f, " (")?;
writeln!(f, " {triple:?},")?;
writeln!(f, " Target {{")?;
writeln!(f, " TargetInfo {{")?;
writeln!(f, " full_arch: Cow::Borrowed({full_arch:?}),")?;
writeln!(f, " arch: Cow::Borrowed({arch:?}),")?;
writeln!(f, " vendor: Cow::Borrowed({vendor:?}),")?;
writeln!(f, " os: Cow::Borrowed({os:?}),")?;
writeln!(f, " env: Cow::Borrowed({env:?}),")?;
writeln!(f, " abi: Cow::Borrowed({abi:?}),")?;
writeln!(
f,
" unversioned_llvm_target: Cow::Borrowed({unversioned_llvm_target:?}),"
)?;
writeln!(f, " }},")?;
writeln!(f, " ),")?;
}
Expand Down
232 changes: 51 additions & 181 deletions src/lib.rs

Large diffs are not rendered by default.

31 changes: 21 additions & 10 deletions src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ use std::{borrow::Cow, env, str::FromStr};

use crate::{Error, ErrorKind};

mod apple;
mod generated;
mod llvm;

/// The parts of `rustc`'s target triple.
/// Information specific to a `rustc` target.
///
/// See <https://doc.rust-lang.org/cargo/appendix/glossary.html#target>.
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Target {
pub(crate) struct TargetInfo {
/// The full architecture, including the subarchitecture.
///
/// This differs from `cfg!(target_arch)`, which only specifies the
Expand All @@ -38,9 +40,11 @@ pub(crate) struct Target {
///
/// This is the same as the value of `cfg!(target_abi)`.
pub abi: Cow<'static, str>,
/// The unversioned LLVM/Clang target triple.
unversioned_llvm_target: Cow<'static, str>,
}

impl Target {
impl TargetInfo {
pub fn from_cargo_environment_variables() -> Result<Self, Error> {
// `TARGET` must be present.
//
Expand Down Expand Up @@ -90,7 +94,7 @@ impl Target {
// back back to data from the known set of target triples instead.
//
// See discussion in #1225 for further details.
let fallback_target = Target::from_str(&target_triple).ok();
let fallback_target = TargetInfo::from_str(&target_triple).ok();
let ft = fallback_target.as_ref();
let arch = cargo_env("CARGO_CFG_TARGET_ARCH", ft.map(|t| t.arch.clone()))?;
let vendor = cargo_env("CARGO_CFG_TARGET_VENDOR", ft.map(|t| t.vendor.clone()))?;
Expand All @@ -102,27 +106,34 @@ impl Target {
let abi = cargo_env("CARGO_CFG_TARGET_ABI", ft.map(|t| t.abi.clone()))
.unwrap_or(Cow::Borrowed(""));

// Prefer `rustc`'s LLVM target triple information.
let unversioned_llvm_target = match fallback_target {
Some(ft) => ft.unversioned_llvm_target,
None => llvm::guess_llvm_target_triple(full_arch, &vendor, &os, &env, &abi).into(),
};

Ok(Self {
full_arch: full_arch.to_string().into(),
arch,
vendor,
os,
env,
abi,
unversioned_llvm_target,
})
}
}

impl FromStr for Target {
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 (_, target) = &generated::LIST[index];
Ok(target.clone())
let (_, info) = &generated::LIST[index];
Ok(info.clone())
} else {
Err(Error::new(
ErrorKind::InvalidTarget,
Expand All @@ -136,7 +147,7 @@ impl FromStr for Target {
mod tests {
use std::str::FromStr;

use super::Target;
use super::TargetInfo;

// Test tier 1 targets
#[test]
Expand All @@ -155,7 +166,7 @@ mod tests {

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

Expand All @@ -177,7 +188,7 @@ mod tests {

for target in targets {
// Check that it does not parse
let _ = Target::from_str(target).unwrap_err();
let _ = TargetInfo::from_str(target).unwrap_err();
}
}
}
19 changes: 19 additions & 0 deletions src/target/apple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use super::TargetInfo;

impl TargetInfo {
pub(crate) fn apple_sdk_name(&self) -> &'static str {
match (&*self.os, &*self.abi) {
("macos", "") => "macosx",
("ios", "") => "iphoneos",
("ios", "sim") => "iphonesimulator",
("ios", "macabi") => "macosx",
("tvos", "") => "appletvos",
("tvos", "sim") => "appletvsimulator",
("watchos", "") => "watchos",
("watchos", "sim") => "watchsimulator",
("visionos", "") => "xros",
("visionos", "sim") => "xrsimulator",
(os, _) => panic!("invalid Apple target OS {}", os),
}
}
}
Loading

0 comments on commit 9c663ca

Please sign in to comment.