Migrate build.sh script to rust

This commit is contained in:
Guillaume Gomez 2023-09-26 16:09:51 +02:00
parent 71febd94f4
commit eedf1b6cb4
12 changed files with 542 additions and 134 deletions

View File

@ -119,7 +119,7 @@ jobs:
- name: Build
run: |
./y.sh prepare --only-libcore
${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }}
${{ matrix.libgccjit_version.env_extra }} ./y.sh build ${{ matrix.libgccjit_version.extra }}
${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
./clean_all.sh

View File

@ -86,7 +86,7 @@ jobs:
- name: Build
run: |
./y.sh prepare --only-libcore
EMBED_LTO_BITCODE=1 ./build.sh --release --release-sysroot
EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot
cargo test
./clean_all.sh

View File

@ -100,7 +100,7 @@ jobs:
- name: Build
run: |
./y.sh prepare --only-libcore
./build.sh --release --release-sysroot
./y.sh build --release --release-sysroot
cargo test
- name: Clean

View File

@ -66,7 +66,7 @@ Then you can run commands like this:
```bash
$ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking
$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release
$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release
```
To run the tests:

View File

@ -1,67 +0,0 @@
#!/usr/bin/env bash
#set -x
set -e
codegen_channel=debug
sysroot_channel=debug
flags=
while [[ $# -gt 0 ]]; do
case $1 in
--release)
codegen_channel=release
shift
;;
--release-sysroot)
sysroot_channel=release
shift
;;
--no-default-features)
flags="$flags --no-default-features"
shift
;;
--features)
shift
flags="$flags --features $1"
shift
;;
*)
echo "Unknown option $1"
exit 1
;;
esac
done
if [ -f ./gcc_path ]; then
export GCC_PATH=$(cat gcc_path)
else
echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
exit 1
fi
export LD_LIBRARY_PATH="$GCC_PATH"
export LIBRARY_PATH="$GCC_PATH"
if [[ "$codegen_channel" == "release" ]]; then
export CHANNEL='release'
CARGO_INCREMENTAL=1 cargo rustc --release $flags
else
echo $LD_LIBRARY_PATH
export CHANNEL='debug'
cargo rustc $flags
fi
source config.sh
rm -r target/out || true
mkdir -p target/out/gccjit
echo "[BUILD] sysroot"
if [[ "$sysroot_channel" == "release" ]]; then
time ./build_sysroot/build_sysroot.sh --release
else
time ./build_sysroot/build_sysroot.sh
fi

View File

@ -5,9 +5,9 @@
set -e
cd $(dirname "$0")
pushd ../ >/dev/null
pushd ../
source ./config.sh
popd >/dev/null
popd
# Cleanup for previous run
# v Clean target dir except for build scripts and incremental cache

View File

@ -1,3 +1,218 @@
pub fn run() -> Result<(), String> {
use crate::config::set_config;
use crate::utils::{get_gcc_path, run_command_with_env, run_command_with_output, walk_dir};
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
#[derive(Default)]
struct BuildArg {
codegen_release_channel: bool,
sysroot_release_channel: bool,
no_default_features: bool,
features: Vec<String>,
gcc_path: String,
}
impl BuildArg {
fn new() -> Result<Option<Self>, String> {
let gcc_path = get_gcc_path()?;
let mut build_arg = Self {
gcc_path,
..Default::default()
};
let mut args = std::env::args().skip(2);
while let Some(arg) = args.next() {
match arg.as_str() {
"--release" => build_arg.codegen_release_channel = true,
"--release-sysroot" => build_arg.sysroot_release_channel = true,
"--no-default-features" => build_arg.no_default_features = true,
"--features" => {
if let Some(arg) = args.next() {
build_arg.features.push(arg.as_str().into());
} else {
return Err(format!(
"Expected a value after `--features`, found nothing"
));
}
}
"--help" => {
Self::usage();
return Ok(None);
}
a => return Err(format!("Unknown argument `{a}`")),
}
}
Ok(Some(build_arg))
}
fn usage() {
println!(
r#"
`build` command help:
--release : Build codegen in release mode
--release-sysroot : Build sysroot in release mode
--no-default-features : Add `--no-default-features` flag
--features [arg] : Add a new feature [arg]
--help : Show this help
"#
)
}
}
fn build_sysroot(
env: &mut HashMap<String, String>,
release_mode: bool,
target_triple: &str,
) -> Result<(), String> {
std::env::set_current_dir("build_sysroot")
.map_err(|e| format!("Failed to go to `build_sysroot` directory: {e:?}"))?;
// Cleanup for previous run
// v Clean target dir except for build scripts and incremental cache
let _e = walk_dir(
"target",
|dir: &Path| {
for top in &["debug", "release"] {
let _e = fs::remove_dir_all(dir.join(top).join("build"));
let _e = fs::remove_dir_all(dir.join(top).join("deps"));
let _e = fs::remove_dir_all(dir.join(top).join("examples"));
let _e = fs::remove_dir_all(dir.join(top).join("native"));
let _e = walk_dir(
dir.join(top),
|sub_dir: &Path| {
if sub_dir
.file_name()
.map(|s| s.to_str().unwrap().starts_with("libsysroot"))
.unwrap_or(false)
{
let _e = fs::remove_dir_all(sub_dir);
}
Ok(())
},
|file: &Path| {
if file
.file_name()
.map(|s| s.to_str().unwrap().starts_with("libsysroot"))
.unwrap_or(false)
{
let _e = fs::remove_file(file);
}
Ok(())
},
);
}
Ok(())
},
|_| Ok(()),
);
let _e = fs::remove_file("Cargo.lock");
let _e = fs::remove_file("test_target/Cargo.lock");
let _e = fs::remove_dir_all("sysroot");
// Builds libs
let channel = if release_mode {
let rustflags = env
.get(&"RUSTFLAGS".to_owned())
.cloned()
.unwrap_or_default();
env.insert(
"RUSTFLAGS".to_owned(),
format!("{rustflags} -Zmir-opt-level=3"),
);
run_command_with_output(
&[
&"cargo",
&"build",
&"--target",
&target_triple,
&"--release",
],
None,
Some(&env),
)?;
"release"
} else {
run_command_with_output(
&[
&"cargo",
&"build",
&"--target",
&target_triple,
&"--features",
&"compiler_builtins/c",
],
None,
Some(env),
)?;
"debug"
};
// Copy files to sysroot
let sysroot_path = format!("sysroot/lib/rustlib/{target_triple}/lib/");
fs::create_dir_all(&sysroot_path)
.map_err(|e| format!("Failed to create directory `{sysroot_path}`: {e:?}"))?;
let copier = |d: &Path| run_command_with_output(&[&"cp", &"-r", &d, &sysroot_path], None, None);
walk_dir(
&format!("target/{target_triple}/{channel}/deps"),
copier,
copier,
)?;
Ok(())
}
fn build_codegen(args: &BuildArg) -> Result<(), String> {
let mut env = HashMap::new();
let current_dir =
std::env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?;
env.insert(
"RUST_COMPILER_RT_ROOT".to_owned(),
format!("{}", current_dir.join("llvm/compiler-rt").display()),
);
env.insert("LD_LIBRARY_PATH".to_owned(), args.gcc_path.clone());
env.insert("LIBRARY_PATH".to_owned(), args.gcc_path.clone());
let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
if args.codegen_release_channel {
command.push(&"--release");
env.insert("CHANNEL".to_owned(), "release".to_owned());
env.insert("CARGO_INCREMENTAL".to_owned(), "1".to_owned());
} else {
env.insert("CHANNEL".to_owned(), "debug".to_owned());
}
let ref_features = args.features.iter().map(|s| s.as_str()).collect::<Vec<_>>();
for feature in &ref_features {
command.push(feature);
}
run_command_with_env(&command, None, Some(&env))?;
let config = set_config(&mut env, &[], Some(&args.gcc_path))?;
// We voluntarily ignore the error.
let _e = fs::remove_dir_all("target/out");
let gccjit_target = "target/out/gccjit";
fs::create_dir_all(gccjit_target)
.map_err(|e| format!("Failed to create directory `{gccjit_target}`: {e:?}"))?;
println!("[BUILD] sysroot");
build_sysroot(
&mut env,
args.sysroot_release_channel,
&config.target_triple,
)?;
Ok(())
}
pub fn run() -> Result<(), String> {
let args = match BuildArg::new()? {
Some(a) => a,
None => return Ok(()),
};
build_codegen(&args)?;
Ok(())
}

121
build_system/src/config.rs Normal file
View File

@ -0,0 +1,121 @@
use crate::utils::{get_gcc_path, get_os_name, get_rustc_host_triple};
use std::collections::HashMap;
use std::env as std_env;
pub struct ConfigInfo {
pub target_triple: String,
pub rustc_command: Vec<String>,
pub run_wrapper: Option<&'static str>,
}
// Returns the beginning for the command line of rustc.
pub fn set_config(
env: &mut HashMap<String, String>,
test_flags: &[String],
gcc_path: Option<&str>,
) -> Result<ConfigInfo, String> {
env.insert("CARGO_INCREMENTAL".to_owned(), "0".to_owned());
let gcc_path = match gcc_path {
Some(g) => g.to_owned(),
None => get_gcc_path()?,
};
env.insert("GCC_PATH".to_owned(), gcc_path.clone());
let os_name = get_os_name()?;
let dylib_ext = match os_name.as_str() {
"Linux" => "so",
"Darwin" => "dylib",
os => return Err(format!("unsupported OS `{os}`")),
};
let host_triple = get_rustc_host_triple()?;
let mut linker = None;
let mut target_triple = host_triple.as_str();
let mut run_wrapper = None;
// FIXME: handle this with a command line flag?
// let mut target_triple = "m68k-unknown-linux-gnu";
if host_triple != target_triple {
if target_triple == "m68k-unknown-linux-gnu" {
target_triple = "mips-unknown-linux-gnu";
linker = Some("-Clinker=m68k-linux-gcc");
} else if target_triple == "aarch64-unknown-linux-gnu" {
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
linker = Some("-Clinker=aarch64-linux-gnu-gcc");
run_wrapper = Some("qemu-aarch64 -L /usr/aarch64-linux-gnu");
} else {
return Err(format!("unknown non-native platform `{target_triple}`"));
}
}
// Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
// TODO(antoyo): remove when we can handle ThinLTO.
let disable_lto_lfags = "-Clto=off";
let current_dir = std_env::current_dir().map_err(|e| format!("`current_dir` failed: {e:?}"))?;
let cg_backend_path = current_dir
.join("target")
.join(if let Some(channel) = env.get(&"CHANNEL".to_owned()) {
channel.as_str()
} else {
"debug"
})
.join(&format!("librustc_codegen_gcc.{dylib_ext}"));
let sysroot_path = current_dir.join("build_sysroot/sysroot");
let mut rustflags = Vec::new();
if let Some(cg_rustflags) = env.get(&"CG_RUSTFLAGS".to_owned()) {
rustflags.push(cg_rustflags.clone());
}
if let Some(linker) = linker {
rustflags.push(linker.to_owned());
}
rustflags.extend_from_slice(&[
"-Csymbol-mangling-version=v0".to_owned(),
"-Cdebuginfo=2".to_owned(),
disable_lto_lfags.to_owned(),
format!("-Zcodegen-backend={}", cg_backend_path.display()),
"--sysroot".to_owned(),
format!("{}", sysroot_path.display()),
]);
rustflags.extend_from_slice(test_flags);
// FIXME(antoyo): remove once the atomic shim is gone
if os_name == "Darwin" {
rustflags.extend_from_slice(&[
"-Clink-arg=-undefined".to_owned(),
"-Clink-arg=dynamic_lookup".to_owned(),
]);
}
env.insert("RUSTFLAGS".to_owned(), rustflags.join(" "));
// display metadata load errors
env.insert("RUSTC_LOG".to_owned(), "warn".to_owned());
let ld_library_path = format!(
"{target}:{sysroot}:{gcc_path}",
target = current_dir.join("target/out").display(),
sysroot = current_dir
.join(&format!(
"build_sysroot/sysroot/lib/rustlib/{target_triple}/lib"
),)
.display(),
);
env.insert("LD_LIBRARY_PATH".to_owned(), ld_library_path.clone());
env.insert("DYLD_LIBRARY_PATH".to_owned(), ld_library_path);
// NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
// To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
// Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
let path = std::env::var("PATH").unwrap_or_default();
env.insert("PATH".to_owned(), format!("/opt/gcc/bin:{path}"));
let mut rustc_command = vec!["rustc".to_owned()];
rustc_command.extend_from_slice(&rustflags);
rustc_command.extend_from_slice(&[
"-L".to_owned(),
"crate=target/out".to_owned(),
"--out-dir".to_owned(),
"target/out".to_owned(),
]);
Ok(ConfigInfo {
target_triple: target_triple.to_owned(),
rustc_command,
run_wrapper,
})
}

View File

@ -2,6 +2,7 @@
use std::process;
mod build;
mod config;
mod prepare;
mod rustc_info;
mod utils;
@ -16,12 +17,14 @@ macro_rules! arg_error {
}
fn usage() {
println!("\
println!(
"\
Available commands for build_system:
prepare : Run prepare command
build : Run build command
--help : Show this message");
--help : Show this message"
);
}
pub enum Command {

View File

@ -15,11 +15,10 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
None => return Err(format!("No parent for `{}`", rustc_path.display())),
};
let rustlib_dir =
parent
.join("../lib/rustlib/src/rust")
.canonicalize()
.map_err(|e| format!("Failed to canonicalize path: {e:?}"))?;
let rustlib_dir = parent
.join("../lib/rustlib/src/rust")
.canonicalize()
.map_err(|e| format!("Failed to canonicalize path: {e:?}"))?;
if !rustlib_dir.is_dir() {
return Err("Please install `rust-src` component".to_owned());
}
@ -27,18 +26,26 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
let sysroot_dir = sysroot_path.join("sysroot_src");
if sysroot_dir.is_dir() {
if let Err(e) = fs::remove_dir_all(&sysroot_dir) {
return Err(format!("Failed to remove `{}`: {:?}", sysroot_dir.display(), e));
return Err(format!(
"Failed to remove `{}`: {:?}",
sysroot_dir.display(),
e
));
}
}
let sysroot_library_dir = sysroot_dir.join("library");
fs::create_dir_all(&sysroot_library_dir)
.map_err(|e| format!(
fs::create_dir_all(&sysroot_library_dir).map_err(|e| {
format!(
"Failed to create folder `{}`: {e:?}",
sysroot_library_dir.display(),
))?;
)
})?;
run_command(&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], None)?;
run_command(
&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir],
None,
)?;
println!("[GIT] init (cwd): `{}`", sysroot_dir.display());
run_command(&[&"git", &"init"], Some(&sysroot_dir))?;
@ -49,26 +56,52 @@ fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
// This is needed on systems where nothing is configured.
// git really needs something here, or it will fail.
// Even using --author is not enough.
run_command(&[&"git", &"config", &"user.email", &"none@example.com"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"user.name", &"None"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"core.autocrlf", &"false"], Some(&sysroot_dir))?;
run_command(&[&"git", &"config", &"commit.gpgSign", &"false"], Some(&sysroot_dir))?;
run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&sysroot_dir))?;
run_command(
&[&"git", &"config", &"user.email", &"none@example.com"],
Some(&sysroot_dir),
)?;
run_command(
&[&"git", &"config", &"user.name", &"None"],
Some(&sysroot_dir),
)?;
run_command(
&[&"git", &"config", &"core.autocrlf", &"false"],
Some(&sysroot_dir),
)?;
run_command(
&[&"git", &"config", &"commit.gpgSign", &"false"],
Some(&sysroot_dir),
)?;
run_command(
&[&"git", &"commit", &"-m", &"Initial commit", &"-q"],
Some(&sysroot_dir),
)?;
let mut patches = Vec::new();
walk_dir("patches", |_| Ok(()), |file_path: &Path| {
patches.push(file_path.to_path_buf());
Ok(())
})?;
walk_dir(
"patches",
|_| Ok(()),
|file_path: &Path| {
patches.push(file_path.to_path_buf());
Ok(())
},
)?;
patches.sort();
for file_path in patches {
println!("[GIT] apply `{}`", file_path.display());
let path = Path::new("../..").join(file_path);
run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir))?;
run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir))?;
run_command_with_output(&[&"git", &"apply", &path], Some(&sysroot_dir), None)?;
run_command_with_output(&[&"git", &"add", &"-A"], Some(&sysroot_dir), None)?;
run_command_with_output(
&[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())],
&[
&"git",
&"commit",
&"--no-gpg-sign",
&"-m",
&format!("Patch {}", path.display()),
],
Some(&sysroot_dir),
None,
)?;
}
println!("Successfully prepared libcore for building");
@ -83,7 +116,10 @@ fn build_raytracer(repo_dir: &Path) -> Result<(), String> {
std::fs::remove_file(&mv_target)
.map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?;
}
run_command(&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], Some(repo_dir))?;
run_command(
&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"],
Some(repo_dir),
)?;
Ok(())
}
@ -99,16 +135,21 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?;
run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?;
let filter = format!("-{}-", clone_result.repo_name);
walk_dir("crate_patches", |_| Ok(()), |file_path| {
let s = file_path.as_os_str().to_str().unwrap();
if s.contains(&filter) && s.ends_with(".patch") {
run_command_with_output(
&[&"git", &"am", &file_path.canonicalize().unwrap()],
Some(&repo_path),
)?;
}
Ok(())
})?;
walk_dir(
"crate_patches",
|_| Ok(()),
|file_path| {
let s = file_path.as_os_str().to_str().unwrap();
if s.contains(&filter) && s.ends_with(".patch") {
run_command_with_output(
&[&"git", &"am", &file_path.canonicalize().unwrap()],
Some(&repo_path),
None,
)?;
}
Ok(())
},
)?;
if let Some(extra) = extra {
extra(&repo_path)?;
}
@ -128,23 +169,23 @@ fn new() -> Result<Option<Self>, String> {
"--only-libcore" => only_libcore = true,
"--help" => {
Self::usage();
return Ok(None)
return Ok(None);
}
a => return Err(format!("Unknown argument `{a}`")),
}
}
Ok(Some(Self {
only_libcore,
}))
Ok(Some(Self { only_libcore }))
}
fn usage() {
println!(r#"
println!(
r#"
`prepare` command help:
--only-libcore : Only setup libcore and don't clone other repositories
--help : Show this help
"#)
"#
)
}
}
@ -160,9 +201,21 @@ pub fn run() -> Result<(), String> {
cargo_install("hyperfine")?;
let to_clone = &[
("https://github.com/rust-random/rand.git", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", None),
("https://github.com/rust-lang/regex.git", "341f207c1071f7290e3f228c710817c280c8dca1", None),
("https://github.com/ebobby/simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", Some(build_raytracer)),
(
"https://github.com/rust-random/rand.git",
"0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
None,
),
(
"https://github.com/rust-lang/regex.git",
"341f207c1071f7290e3f228c710817c280c8dca1",
None,
),
(
"https://github.com/ebobby/simple-raytracer",
"804a7a21b9e673a482797aa289a18ed480e4d813",
Some(build_raytracer),
),
];
for (repo_url, checkout_commit, cb) in to_clone {

View File

@ -1,10 +1,15 @@
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fmt::Debug;
use std::fs;
use std::path::Path;
use std::process::{Command, ExitStatus, Output};
fn get_command_inner(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Command {
fn get_command_inner(
input: &[&dyn AsRef<OsStr>],
cwd: Option<&Path>,
env: Option<&HashMap<String, String>>,
) -> Command {
let (cmd, args) = match input {
[] => panic!("empty command"),
[cmd, args @ ..] => (cmd, args),
@ -14,6 +19,9 @@ fn get_command_inner(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Command
if let Some(cwd) = cwd {
command.current_dir(cwd);
}
if let Some(env) = env {
command.envs(env.iter().map(|(k, v)| (k.as_str(), v.as_str())));
}
command
}
@ -27,7 +35,8 @@ fn check_exit_status(
} else {
Err(format!(
"Command `{}`{} exited with status {:?}",
input.iter()
input
.iter()
.map(|s| s.as_ref().to_str().unwrap())
.collect::<Vec<_>>()
.join(" "),
@ -41,21 +50,27 @@ fn check_exit_status(
fn command_error<D: Debug>(input: &[&dyn AsRef<OsStr>], cwd: &Option<&Path>, error: D) -> String {
format!(
"Command `{}`{} failed to run: {error:?}",
input.iter()
input
.iter()
.map(|s| s.as_ref().to_str().unwrap())
.collect::<Vec<_>>()
.join(" "),
cwd.as_ref()
.map(|cwd| format!(
" (running in folder `{}`)",
cwd.display(),
))
.map(|cwd| format!(" (running in folder `{}`)", cwd.display(),))
.unwrap_or_default(),
)
}
pub fn run_command(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Result<Output, String> {
let output = get_command_inner(input, cwd)
run_command_with_env(input, cwd, None)
}
pub fn run_command_with_env(
input: &[&dyn AsRef<OsStr>],
cwd: Option<&Path>,
env: Option<&HashMap<String, String>>,
) -> Result<Output, String> {
let output = get_command_inner(input, cwd, env)
.output()
.map_err(|e| command_error(input, &cwd, e))?;
check_exit_status(input, cwd, output.status)?;
@ -65,8 +80,10 @@ pub fn run_command(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Result<Ou
pub fn run_command_with_output(
input: &[&dyn AsRef<OsStr>],
cwd: Option<&Path>,
env: Option<&HashMap<String, String>>,
) -> Result<(), String> {
let exit_status = get_command_inner(input, cwd).spawn()
let exit_status = get_command_inner(input, cwd, env)
.spawn()
.map_err(|e| command_error(input, &cwd, e))?
.wait()
.map_err(|e| command_error(input, &cwd, e))?;
@ -94,12 +111,69 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> {
return Ok(());
}
// We voluntarily ignore this error.
if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() {
if run_command_with_output(&[&"cargo", &"install", &to_install], None, None).is_err() {
println!("Skipping installation of `{to_install}`");
}
Ok(())
}
pub fn get_os_name() -> Result<String, String> {
let output = run_command(&[&"uname"], None)?;
let name = std::str::from_utf8(&output.stdout)
.unwrap_or("")
.trim()
.to_owned();
if !name.is_empty() {
Ok(name)
} else {
Err(format!("Failed to retrieve the OS name"))
}
}
pub fn get_rustc_host_triple() -> Result<String, String> {
let output = run_command(&[&"rustc", &"-vV"], None)?;
let content = std::str::from_utf8(&output.stdout).unwrap_or("");
for line in content.split('\n').map(|line| line.trim()) {
if !line.starts_with("host:") {
continue;
}
return Ok(line.split(':').nth(1).unwrap().trim().to_owned());
}
Err("Cannot find host triple".to_owned())
}
pub fn get_gcc_path() -> Result<String, String> {
let content = match fs::read_to_string("gcc_path") {
Ok(c) => c,
Err(_) => {
return Err(
"Please put the path to your custom build of libgccjit in the file \
`gcc_path`, see Readme.md for details"
.into(),
)
}
};
match content
.split('\n')
.map(|l| l.trim())
.filter(|l| !l.is_empty())
.next()
{
Some(gcc_path) => {
let path = Path::new(gcc_path);
if !path.exists() {
Err(format!(
"Path `{gcc_path}` contained in the `gcc_path` file doesn't exist"
))
} else {
Ok(gcc_path.into())
}
}
None => Err("No path found in `gcc_path` file".into()),
}
}
pub struct CloneResult {
pub ran_clone: bool,
pub repo_name: String,
@ -116,11 +190,17 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, Str
.map(|dest| dest.join(&repo_name))
.unwrap_or_else(|| Path::new(&repo_name).into());
if dest.is_dir() {
return Ok(CloneResult { ran_clone: false, repo_name });
return Ok(CloneResult {
ran_clone: false,
repo_name,
});
}
run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None)?;
Ok(CloneResult { ran_clone: true, repo_name })
run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None, None)?;
Ok(CloneResult {
ran_clone: true,
repo_name,
})
}
pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
@ -130,8 +210,11 @@ pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), St
F: FnMut(&Path) -> Result<(), String>,
{
let dir = dir.as_ref();
for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? {
let entry = entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?;
for entry in
fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))?
{
let entry =
entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?;
let entry_path = entry.path();
if entry_path.is_dir() {
dir_cb(&entry_path)?;

View File

@ -48,7 +48,7 @@ fi
export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
# FIXME(antoyo): remove once the atomic shim is gone
if [[ `uname` == 'Darwin' ]]; then
if [[ unamestr == 'Darwin' ]]; then
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
fi