Skip to content

Commit 290a629

Browse files
authored
Use Cargo's target information when possible (#1225)
* Reduce the need for the host target triple * Use Cargo's target information when possible rustc's target triples generally only have a vague resemblance to each other and to the information needed by `cc`. Let's instead prefer `CARGO_CFG_*` variables when available, since these contain the information directly from the compiler itself. In the cases where it isn't available (i.e. when running outside of a build script), we fall back to parsing the target triple, but instead of doing it in an ad-hoc fashion with string manipulation, we do it in a more structured fashion up front. * Remove unnecessary derive * Use pre-generated target information * Use Cow<'static, str> in Target * Remove redundant test * Redo from_cargo_environment_variables to be more error resilient * Fix after merge * Appease clippy * Add support for targets within MSRV * Fix test * Fix a few more tests * Properly match previous behaviour * Update to Rust 2024-10-25 * Use a `const` and binary search instead of a match * Fix formatting
1 parent c07ab0e commit 290a629

File tree

12 files changed

+3655
-450
lines changed

12 files changed

+3655
-450
lines changed

.github/workflows/regenerate-target-info.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ jobs:
1919
git checkout -b regenerate-target-info-${{ github.run_id }}
2020
2121
- name: Install rust
22+
# Install both MSRV and current nightly
2223
run: |
23-
rustup toolchain install stable nightly --no-self-update --profile minimal
24+
rustup toolchain install 1.63 stable nightly --no-self-update --profile minimal
2425
2526
- name: Create lockfile
2627
run: cargo update
27-
28+
2829
- uses: Swatinem/rust-cache@v2
2930
with:
3031
cache-all-crates: 'true'

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
target
1+
/target
22
Cargo.lock
33
.idea
44
*.iml

dev-tools/gen-target-info/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod target_specs;
22
pub use target_specs::*;
33

44
mod read;
5-
pub use read::get_target_specs_from_json;
5+
pub use read::*;
66

77
mod write;
88
pub use write::*;

dev-tools/gen-target-info/src/main.rs

+49-31
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,70 @@
1-
use gen_target_info::{get_target_specs_from_json, write_target_tuple_mapping, RustcTargetSpecs};
2-
use std::{collections::BTreeMap, fs::File, io::Write as _};
1+
use std::io::Write as _;
2+
use std::{fs::File, io::BufRead};
3+
4+
use gen_target_info::{
5+
get_target_spec_from_msrv, get_target_specs_from_json, get_targets_msrv, RustcTargetSpecs,
6+
};
37

48
const PRELUDE: &str = r#"//! This file is generated code. Please edit the generator
59
//! in dev-tools/gen-target-info if you need to make changes.
610
711
"#;
812

9-
fn generate_riscv_arch_mapping(f: &mut File, target_specs: &RustcTargetSpecs) {
10-
let riscv_target_mapping = target_specs
11-
.0
12-
.iter()
13-
.filter_map(|(target, target_spec)| {
14-
let arch = target.split_once('-').unwrap().0;
15-
(arch.contains("riscv") && arch != target_spec.arch)
16-
.then_some((arch, &*target_spec.arch))
17-
})
18-
.collect::<BTreeMap<_, _>>();
19-
write_target_tuple_mapping(f, "RISCV_ARCH_MAPPING", &riscv_target_mapping);
20-
}
13+
fn generate_target_mapping(f: &mut File, target_specs: &RustcTargetSpecs) -> std::io::Result<()> {
14+
writeln!(f, "use super::Target;")?;
15+
writeln!(f, "use std::borrow::Cow;")?;
16+
writeln!(f)?;
17+
writeln!(f, "pub(crate) const LIST: &[(&str, Target)] = &[")?;
18+
19+
for (triple, spec) in &target_specs.0 {
20+
let full_arch = triple.split_once('-').unwrap().0;
21+
let arch = &spec.arch;
22+
let vendor = spec.vendor.as_deref().unwrap_or("unknown");
23+
let os = spec.os.as_deref().unwrap_or("none");
24+
let env = spec.env.as_deref().unwrap_or("");
25+
let abi = spec.abi.as_deref().unwrap_or("");
26+
27+
writeln!(f, " (")?;
28+
writeln!(f, " {triple:?},")?;
29+
writeln!(f, " Target {{")?;
30+
writeln!(f, " full_arch: Cow::Borrowed({full_arch:?}),")?;
31+
writeln!(f, " arch: Cow::Borrowed({arch:?}),")?;
32+
writeln!(f, " vendor: Cow::Borrowed({vendor:?}),")?;
33+
writeln!(f, " os: Cow::Borrowed({os:?}),")?;
34+
writeln!(f, " env: Cow::Borrowed({env:?}),")?;
35+
writeln!(f, " abi: Cow::Borrowed({abi:?}),")?;
36+
writeln!(f, " }},")?;
37+
writeln!(f, " ),")?;
38+
}
39+
40+
writeln!(f, "];")?;
2141

22-
fn generate_windows_triple_mapping(f: &mut File, target_specs: &RustcTargetSpecs) {
23-
let windows_target_mapping = target_specs
24-
.0
25-
.iter()
26-
.filter_map(|(target, target_spec)| {
27-
let rust_target_parts = target.splitn(4, '-').collect::<Vec<_>>();
28-
let os = *rust_target_parts.get(2)?;
29-
(os.contains("windows") && target != &*target_spec.llvm_target)
30-
.then_some((&**target, &*target_spec.llvm_target))
31-
})
32-
.collect::<BTreeMap<_, _>>();
33-
write_target_tuple_mapping(f, "WINDOWS_TRIPLE_MAPPING", &windows_target_mapping);
42+
Ok(())
3443
}
3544

3645
fn main() {
37-
let target_specs = get_target_specs_from_json();
46+
// Primarily use information from nightly.
47+
let mut target_specs = get_target_specs_from_json();
48+
// Next, read from MSRV to support old, removed targets.
49+
for target_triple in get_targets_msrv().lines() {
50+
let target_triple = target_triple.unwrap();
51+
let target_triple = target_triple.trim();
52+
target_specs
53+
.0
54+
.entry(target_triple.to_string())
55+
.or_insert_with(|| get_target_spec_from_msrv(target_triple));
56+
}
3857

3958
// Open file to write to
4059
let manifest_dir = env!("CARGO_MANIFEST_DIR");
4160

42-
let path = format!("{manifest_dir}/../../src/target_info.rs");
43-
let mut f = File::create(path).expect("failed to create src/target_info.rs");
61+
let path = format!("{manifest_dir}/../../src/target/generated.rs");
62+
let mut f = File::create(path).expect("failed to create src/target/generated.rs");
4463

4564
f.write_all(PRELUDE.as_bytes()).unwrap();
4665

4766
// Start generating
48-
generate_riscv_arch_mapping(&mut f, &target_specs);
49-
generate_windows_triple_mapping(&mut f, &target_specs);
67+
generate_target_mapping(&mut f, &target_specs).unwrap();
5068

5169
// Flush the data onto disk
5270
f.flush().unwrap();

dev-tools/gen-target-info/src/read.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,44 @@
11
use std::process;
22

3-
use crate::RustcTargetSpecs;
3+
use crate::{RustcTargetSpecs, TargetSpec};
4+
5+
pub fn get_targets_msrv() -> Vec<u8> {
6+
let mut cmd = process::Command::new("rustc");
7+
cmd.args(["+1.63", "--print", "target-list"]);
8+
cmd.stdout(process::Stdio::piped());
9+
cmd.stderr(process::Stdio::inherit());
10+
11+
let process::Output { status, stdout, .. } = cmd.output().unwrap();
12+
13+
if !status.success() {
14+
panic!("{:?} failed with non-zero exit status: {}", cmd, status)
15+
}
16+
17+
stdout
18+
}
19+
20+
pub fn get_target_spec_from_msrv(target: &str) -> TargetSpec {
21+
let mut cmd = process::Command::new("rustc");
22+
cmd.args([
23+
"+1.63",
24+
"-Zunstable-options",
25+
"--print",
26+
"target-spec-json",
27+
"--target",
28+
target,
29+
]);
30+
cmd.env("RUSTC_BOOTSTRAP", "1");
31+
cmd.stdout(process::Stdio::piped());
32+
cmd.stderr(process::Stdio::inherit());
33+
34+
let process::Output { status, stdout, .. } = cmd.output().unwrap();
35+
36+
if !status.success() {
37+
panic!("{:?} failed with non-zero exit status: {}", cmd, status)
38+
}
39+
40+
serde_json::from_slice(&stdout).unwrap()
41+
}
442

543
pub fn get_target_specs_from_json() -> RustcTargetSpecs {
644
let mut cmd = process::Command::new("rustc");
@@ -9,8 +47,9 @@ pub fn get_target_specs_from_json() -> RustcTargetSpecs {
947
"-Zunstable-options",
1048
"--print",
1149
"all-target-specs-json",
12-
])
13-
.stdout(process::Stdio::piped());
50+
]);
51+
cmd.stdout(process::Stdio::piped());
52+
cmd.stderr(process::Stdio::inherit());
1453

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

dev-tools/gen-target-info/src/target_specs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub struct TargetSpec {
2121
pub os: Option<String>,
2222
/// `apple`, `pc`
2323
pub vendor: Option<String>,
24+
pub env: Option<String>,
25+
pub abi: Option<String>,
2426
pub pre_link_args: Option<PreLinkArgs>,
2527
}
2628

0 commit comments

Comments
 (0)