Skip to content

Commit

Permalink
Merge pull request #1353 from hermit-os/hermit-c
Browse files Browse the repository at this point in the history
feat(xtask): allow different `pwd` and relative paths
  • Loading branch information
mkroening authored Aug 13, 2024
2 parents 148314a + 84d06c8 commit 64b9008
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 86 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition = "2021"
anyhow = "1.0"
clap = { version = "4", features = ["derive"] }
goblin = { version = "0.8", default-features = false, features = ["archive", "elf32", "elf64", "std"] }
llvm-tools = "0.1"
sysinfo = "0.31"
ureq = "2"
wait-timeout = "0.2"
Expand Down
11 changes: 7 additions & 4 deletions xtask/src/arch.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use anyhow::Result;
use clap::ValueEnum;
use xshell::cmd;

/// Target architecture.
#[derive(ValueEnum, Clone, Copy, PartialEq, Eq, Debug)]
Expand All @@ -20,9 +19,13 @@ impl Arch {
}

pub fn install(&self) -> Result<()> {
let sh = crate::sh()?;
let triple = self.triple();
cmd!(sh, "rustup target add {triple}").run()?;
let mut rustup = crate::rustup();
rustup.args(["target", "add", self.triple()]);

eprintln!("$ {rustup:?}");
let status = rustup.status()?;
assert!(status.success());

Ok(())
}

Expand Down
6 changes: 3 additions & 3 deletions xtask/src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl Archive {
};

let all_symbols = {
let nm = crate::binutil("nm")?;
let nm = crate::binutil("nm").unwrap();
let stdout = cmd!(sh, "{nm} --export-symbols {archive}").output()?.stdout;
String::from_utf8(stdout)?
};
Expand All @@ -73,7 +73,7 @@ impl Archive {
let rename_path = archive.with_extension("redefine-syms");
sh.write_file(&rename_path, symbol_renames)?;

let objcopy = crate::binutil("objcopy")?;
let objcopy = crate::binutil("objcopy").unwrap();
cmd!(sh, "{objcopy} --redefine-syms={rename_path} {archive}").run()?;

sh.remove_path(&rename_path)?;
Expand All @@ -86,7 +86,7 @@ impl Archive {
let archive = self.as_ref();
let file = file.as_ref();

let ar = crate::binutil("ar")?;
let ar = crate::binutil("ar").unwrap();
cmd!(sh, "{ar} qL {archive} {file}").run()?;

Ok(())
Expand Down
46 changes: 31 additions & 15 deletions xtask/src/artifact.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::path::{Path, PathBuf};
use std::path::{self, PathBuf};

use clap::Args;

use crate::arch::Arch;
use crate::archive::Archive;
use crate::ci;

#[derive(Args)]
pub struct Artifact {
Expand All @@ -15,6 +16,10 @@ pub struct Artifact {
#[arg(long, id = "DIRECTORY")]
pub target_dir: Option<PathBuf>,

/// Copy final artifacts to this directory
#[arg(long, id = "PATH")]
pub artifact_dir: Option<PathBuf>,

/// Build artifacts in release mode, with optimizations.
#[arg(short, long)]
pub release: bool,
Expand All @@ -38,16 +43,21 @@ impl Artifact {
}
}

pub fn target_dir(&self) -> &Path {
self.target_dir
.as_deref()
.unwrap_or_else(|| Path::new("target"))
pub fn target_dir(&self) -> PathBuf {
if let Some(target_dir) = &self.target_dir {
return path::absolute(target_dir).unwrap();
}

crate::project_root().join("target")
}

pub fn builtins_target_dir(&self) -> PathBuf {
self.target_dir().join("hermit-builtins")
}

pub fn builtins_archive(&self) -> Archive {
[
"hermit-builtins".as_ref(),
self.target_dir(),
self.builtins_target_dir().as_path(),
self.arch.hermit_triple().as_ref(),
"release".as_ref(),
"libhermit_builtins.a".as_ref(),
Expand All @@ -59,7 +69,7 @@ impl Artifact {

pub fn build_archive(&self) -> Archive {
[
self.target_dir(),
self.target_dir().as_path(),
self.arch.triple().as_ref(),
self.profile_path_component().as_ref(),
"libhermit.a".as_ref(),
Expand All @@ -69,22 +79,28 @@ impl Artifact {
.into()
}

pub fn dist_archive(&self) -> Archive {
fn artifact_dir(&self) -> PathBuf {
if let Some(artifact_dir) = &self.artifact_dir {
return path::absolute(artifact_dir).unwrap();
}

[
self.target_dir(),
self.target_dir().as_path(),
self.arch.name().as_ref(),
self.profile_path_component().as_ref(),
"libhermit.a".as_ref(),
]
.iter()
.collect::<PathBuf>()
.into()
.collect()
}

pub fn dist_archive(&self) -> Archive {
self.artifact_dir().join("libhermit.a").into()
}

pub fn ci_image(&self, package: &str) -> PathBuf {
[
"..".as_ref(),
self.target_dir(),
ci::parent_root(),
"target".as_ref(),
self.arch.hermit_triple().as_ref(),
self.profile_path_component().as_ref(),
package.as_ref(),
Expand Down
60 changes: 43 additions & 17 deletions xtask/src/binutil.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,48 @@
use std::io;
use std::path::PathBuf;
use std::sync::LazyLock;

use anyhow::{anyhow, Result};
pub fn binutil(name: &str) -> Option<PathBuf> {
static LLVM_TOOLS: LazyLock<LlvmTools> = LazyLock::new(|| LlvmTools::new().unwrap());

pub fn binutil(name: &str) -> Result<PathBuf> {
LLVM_TOOLS.tool(name)
}

struct LlvmTools {
bin: PathBuf,
}

impl LlvmTools {
pub fn new() -> io::Result<Self> {
let mut rustc = crate::rustc();
rustc.args(["--print", "sysroot"]);

eprintln!("$ {rustc:?}");
let output = rustc.output()?;
assert!(output.status.success());

let sysroot = String::from_utf8(output.stdout).unwrap();
let rustlib = [sysroot.trim_end(), "lib", "rustlib"]
.iter()
.collect::<PathBuf>();

let example_exe = exe("objdump");
for entry in rustlib.read_dir()? {
let bin = entry?.path().join("bin");
if bin.join(&example_exe).exists() {
return Ok(Self { bin });
}
}
unreachable!()
}

pub fn tool(&self, name: &str) -> Option<PathBuf> {
let path = self.bin.join(exe(name));
path.exists().then_some(path)
}
}

fn exe(name: &str) -> String {
let exe_suffix = std::env::consts::EXE_SUFFIX;
let exe = format!("llvm-{name}{exe_suffix}");

let path = llvm_tools::LlvmTools::new()
.map_err(|err| match err {
llvm_tools::Error::NotFound => anyhow!(
"Could not find llvm-tools component\n\
\n\
Maybe the rustup component `llvm-tools` is missing? Install it through: `rustup component add llvm-tools`"
),
err => anyhow!("{err:?}"),
})?
.tool(&exe)
.ok_or_else(|| anyhow!("could not find {exe}"))?;

Ok(path)
format!("llvm-{name}{exe_suffix}")
}
22 changes: 15 additions & 7 deletions xtask/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::env::{self, VarError};

use anyhow::Result;
use clap::Args;
use xshell::cmd;

use crate::cargo_build::CargoBuild;

Expand Down Expand Up @@ -34,13 +33,17 @@ impl Build {
};

eprintln!("Building kernel");
cmd!(sh, "cargo")
let mut cargo = crate::cargo();
cargo
.args(careful)
.arg("build")
.env("CARGO_ENCODED_RUSTFLAGS", self.cargo_encoded_rustflags()?)
.args(self.cargo_build.artifact.arch.cargo_args())
.args(self.cargo_build.cargo_build_args())
.run()?;
.args(self.cargo_build.cargo_build_args());

eprintln!("$ {cargo:?}");
let status = cargo.status()?;
assert!(status.success());

let build_archive = self.cargo_build.artifact.build_archive();
let dist_archive = self.cargo_build.artifact.dist_archive();
Expand All @@ -56,11 +59,16 @@ impl Build {
self.export_syms()?;

eprintln!("Building hermit-builtins");
cmd!(sh, "cargo build --release")
let mut cargo = crate::cargo();
cargo
.args(["build", "--release"])
.arg("--manifest-path=hermit-builtins/Cargo.toml")
.args(self.cargo_build.artifact.arch.builtins_cargo_args())
.args(self.cargo_build.target_dir_args())
.run()?;
.args(self.cargo_build.builtins_target_dir_arg());

eprintln!("$ {cargo:?}");
let status = cargo.status()?;
assert!(status.success());

eprintln!("Exporting hermit-builtins symbols");
let builtins = self.cargo_build.artifact.builtins_archive();
Expand Down
17 changes: 15 additions & 2 deletions xtask/src/cargo_build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ffi::OsString;

use clap::Args;

use crate::artifact::Artifact;
Expand Down Expand Up @@ -35,16 +37,27 @@ impl CargoBuild {
}

pub fn target_dir_args(&self) -> Vec<String> {
if let Some(target_dir) = &self.artifact.target_dir {
if self.artifact.target_dir.is_some() {
vec![
"--target-dir".to_string(),
target_dir.to_str().unwrap().to_string(),
self.artifact
.target_dir()
.into_os_string()
.into_string()
.unwrap(),
]
} else {
vec![]
}
}

pub fn builtins_target_dir_arg(&self) -> [OsString; 2] {
[
OsString::from("--target-dir"),
self.artifact.builtins_target_dir().into_os_string(),
]
}

fn release_args(&self) -> &'static [&'static str] {
if self.artifact.release {
&["--release"]
Expand Down
34 changes: 2 additions & 32 deletions xtask/src/ci/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::env;
use std::path::PathBuf;
use std::process::Command;

use anyhow::Result;
use clap::Args;
Expand All @@ -25,7 +23,7 @@ impl Build {
eprintln!("::group::cargo build")
}

let mut cargo = cargo();
let mut cargo = crate::cargo();

if self.package.contains("rftrace") {
cargo.env(
Expand All @@ -35,7 +33,7 @@ impl Build {
};

cargo
.current_dir("..")
.current_dir(super::parent_root())
.arg("build")
.args(self.cargo_build.artifact.arch.ci_cargo_args())
.args(self.cargo_build.cargo_build_args())
Expand All @@ -56,31 +54,3 @@ impl Build {
self.cargo_build.artifact.ci_image(&self.package)
}
}

fn cargo() -> Command {
let cargo = {
let exe = format!("cargo{}", env::consts::EXE_SUFFIX);
// On windows, the userspace toolchain ends up in front of the rustup proxy in $PATH.
// To reach the rustup proxy nonetheless, we explicitly query $CARGO_HOME.
let mut cargo_home = PathBuf::from(env::var_os("CARGO_HOME").unwrap());
cargo_home.push("bin");
cargo_home.push(&exe);
if cargo_home.exists() {
cargo_home
} else {
PathBuf::from(exe)
}
};

let mut cargo = Command::new(cargo);

// Remove rust-toolchain-specific environment variables from kernel cargo
cargo.env_remove("LD_LIBRARY_PATH");
env::vars()
.filter(|(key, _value)| key.starts_with("CARGO") || key.starts_with("RUST"))
.for_each(|(key, _value)| {
cargo.env_remove(&key);
});

cargo
}
6 changes: 6 additions & 0 deletions xtask/src/ci/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use anyhow::Result;
use clap::Subcommand;

Expand Down Expand Up @@ -29,3 +31,7 @@ impl Ci {
fn in_ci() -> bool {
std::env::var_os("CI") == Some("true".into())
}

pub fn parent_root() -> &'static Path {
crate::project_root().parent().unwrap()
}
2 changes: 1 addition & 1 deletion xtask/src/ci/qemu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ fn check_rftrace(image: &Path) -> Result<()> {
let sh = crate::sh()?;
let image_name = image.file_name().unwrap().to_str().unwrap();

let nm = crate::binutil("nm")?;
let nm = crate::binutil("nm").unwrap();
let symbols = cmd!(sh, "{nm} --numeric-sort {image}").output()?.stdout;
sh.write_file(format!("shared/tracedir/{image_name}.sym"), symbols)?;

Expand Down
Loading

0 comments on commit 64b9008

Please sign in to comment.