Migrate build.sh script to rust
This commit is contained in:
parent
71febd94f4
commit
eedf1b6cb4
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -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
|
||||
|
||||
|
2
.github/workflows/stdarch.yml
vendored
2
.github/workflows/stdarch.yml
vendored
@ -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
|
||||
|
@ -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:
|
||||
|
67
build.sh
67
build.sh
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
121
build_system/src/config.rs
Normal 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,
|
||||
})
|
||||
}
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)?;
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user