Skip to content

Commit

Permalink
Merge pull request #5 from RalfJung/json
Browse files Browse the repository at this point in the history
support target.json files
  • Loading branch information
RalfJung authored Dec 28, 2022
2 parents 58fc1c9 + a8f6887 commit 0c06b2c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 43 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
Expand All @@ -30,12 +30,12 @@ jobs:
name: Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.64.0
components: rustfmt, clippy
- name: rustfmt
run: cargo fmt --check
- name: clippy
run: cargo clippy -- -D warnings
run: cargo clippy --all-targets -- -D warnings
19 changes: 14 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub enum SysrootConfig {
/// Information about a to-be-created sysroot.
pub struct SysrootBuilder {
sysroot_dir: PathBuf,
target: String,
target: OsString,
config: SysrootConfig,
mode: BuildMode,
rustflags: Vec<OsString>,
Expand All @@ -116,10 +116,10 @@ const HASH_FILE_NAME: &str = ".rustc-build-sysroot-hash";
impl SysrootBuilder {
/// Prepare to create a new sysroot in the given folder (that folder should later be passed to
/// rustc via `--sysroot`), for the given target.
pub fn new(sysroot_dir: &Path, target: &str) -> Self {
pub fn new(sysroot_dir: &Path, target: impl Into<OsString>) -> Self {
SysrootBuilder {
sysroot_dir: sysroot_dir.to_owned(),
target: target.to_owned(),
target: target.into(),
config: SysrootConfig::WithStd {
std_features: vec![],
},
Expand Down Expand Up @@ -166,11 +166,19 @@ impl SysrootBuilder {
self
}

fn target_name(&self) -> &OsStr {
let path = Path::new(&self.target);
// If this is a filename, the name is obtained by stripping directory and extension.
// That will also work fine for built-in target names.
path.file_stem()
.expect("target name must contain a file name")
}

fn target_dir(&self) -> PathBuf {
self.sysroot_dir
.join("lib")
.join("rustlib")
.join(&self.target)
.join(&self.target_name())
}

/// Computes the hash for the sysroot, so that we know whether we have to rebuild.
Expand Down Expand Up @@ -210,6 +218,7 @@ impl SysrootBuilder {
);
}
let target_lib_dir = self.target_dir().join("lib");
let target_name = self.target_name().to_owned();
let cargo = self.cargo.take().unwrap_or_else(|| {
Command::new(env::var_os("CARGO").unwrap_or_else(|| OsString::from("cargo")))
});
Expand Down Expand Up @@ -332,7 +341,7 @@ path = {src_dir_workspace_std:?}
let staging_dir =
TempDir::new_in(&self.sysroot_dir).context("failed to create staging dir")?;
let out_dir = build_target_dir
.join(&self.target)
.join(&target_name)
.join("release")
.join("deps");
for entry in fs::read_dir(&out_dir).context("failed to read cargo out dir")? {
Expand Down
107 changes: 72 additions & 35 deletions tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::path::Path;
use std::fs;
use std::process::{self, Command};

use rustc_version::VersionMeta;
use tempfile::TempDir;
use tempfile::tempdir;

use rustc_build_sysroot::*;

Expand All @@ -15,24 +15,30 @@ fn run(cmd: &mut Command) {
.success());
}

fn test_sysroot_build(target: &str, mode: BuildMode, src_dir: &Path, rustc_version: &VersionMeta) {
let sysroot_dir = TempDir::new().unwrap();
SysrootBuilder::new(sysroot_dir.path(), target)
.build_mode(mode)
.rustc_version(rustc_version.clone())
.cargo({
let mut cmd = Command::new("cargo");
cmd.stdout(process::Stdio::null());
cmd.stderr(process::Stdio::null());
cmd
})
.build_from_source(src_dir)
.unwrap();
fn build_sysroot(b: SysrootBuilder) {
let src_dir = rustc_sysroot_src(Command::new("rustc")).unwrap();
b.cargo({
let mut cmd = Command::new("cargo");
cmd.stdout(process::Stdio::null());
cmd.stderr(process::Stdio::null());
cmd
})
.build_from_source(&src_dir)
.unwrap();
}

fn test_sysroot_build(target: &str, mode: BuildMode, rustc_version: &VersionMeta) {
let sysroot_dir = tempdir().unwrap();
build_sysroot(
SysrootBuilder::new(sysroot_dir.path(), target)
.build_mode(mode)
.rustc_version(rustc_version.clone()),
);

let crate_name = "rustc-build-sysroot-test-crate";
let crate_dir = TempDir::new().unwrap();
let crate_dir = tempdir().unwrap();
run(Command::new("cargo")
.args(&["new", crate_name])
.args(["new", crate_name])
.current_dir(&crate_dir));
let crate_dir = crate_dir.path().join(crate_name);
run(Command::new("cargo")
Expand All @@ -44,7 +50,7 @@ fn test_sysroot_build(target: &str, mode: BuildMode, src_dir: &Path, rustc_versi
"RUSTFLAGS",
format!("--sysroot {}", sysroot_dir.path().display()),
));
if mode == BuildMode::Build && target == &rustc_version.host {
if mode == BuildMode::Build && target == rustc_version.host {
run(Command::new("cargo")
.arg("run")
.current_dir(&crate_dir)
Expand All @@ -58,41 +64,72 @@ fn test_sysroot_build(target: &str, mode: BuildMode, src_dir: &Path, rustc_versi
#[test]
fn host() {
let rustc_version = VersionMeta::for_command(Command::new("rustc")).unwrap();
let src_dir = rustc_sysroot_src(Command::new("rustc")).unwrap();

for mode in [BuildMode::Build, BuildMode::Check] {
test_sysroot_build(&rustc_version.host, mode, &src_dir, &rustc_version);
test_sysroot_build(&rustc_version.host, mode, &rustc_version);
}
}

#[test]
fn cross() {
let rustc_version = VersionMeta::for_command(Command::new("rustc")).unwrap();
let src_dir = rustc_sysroot_src(Command::new("rustc")).unwrap();

for target in [
"i686-unknown-linux-gnu",
"aarch64-apple-darwin",
"i686-pc-windows-msvc",
] {
test_sysroot_build(target, BuildMode::Check, &src_dir, &rustc_version);
test_sysroot_build(target, BuildMode::Check, &rustc_version);
}
}

#[test]
fn no_std() {
let src_dir = rustc_sysroot_src(Command::new("rustc")).unwrap();
let sysroot_dir = tempdir().unwrap();
build_sysroot(
SysrootBuilder::new(sysroot_dir.path(), "thumbv7em-none-eabihf")
.build_mode(BuildMode::Check)
.sysroot_config(SysrootConfig::NoStd),
);
}

#[test]
fn json_target() {
// Example taken from https://book.avr-rust.com/005.1-the-target-specification-json-file.html
let target = r#"{
"arch": "avr",
"cpu": "atmega328p",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"env": "",
"executables": true,
"linker": "avr-gcc",
"linker-flavor": "gcc",
"linker-is-gnu": true,
"llvm-target": "avr-unknown-unknown",
"no-compiler-rt": true,
"os": "unknown",
"position-independent-executables": false,
"exe-suffix": ".elf",
"eh-frame-header": false,
"pre-link-args": {
"gcc": ["-mmcu=atmega328p"]
},
"late-link-args": {
"gcc": ["-lgcc"]
},
"target-c-int-width": "16",
"target-endian": "little",
"target-pointer-width": "16",
"vendor": "unknown"
}"#;

let sysroot_dir = tempdir().unwrap();
let target_file = sysroot_dir.path().join("mytarget.json");
fs::write(&target_file, target).unwrap();

let sysroot_dir = TempDir::new().unwrap();
SysrootBuilder::new(sysroot_dir.path(), "thumbv7em-none-eabihf")
.build_mode(BuildMode::Check)
.sysroot_config(SysrootConfig::NoStd)
.cargo({
let mut cmd = Command::new("cargo");
cmd.stdout(process::Stdio::null());
cmd.stderr(process::Stdio::null());
cmd
})
.build_from_source(&src_dir)
.unwrap();
build_sysroot(
SysrootBuilder::new(sysroot_dir.path(), &target_file)
.build_mode(BuildMode::Check)
.sysroot_config(SysrootConfig::NoStd),
);
}

0 comments on commit 0c06b2c

Please sign in to comment.