275 lines
8.0 KiB
Rust
275 lines
8.0 KiB
Rust
use crate::rustc_info::get_rustc_path;
|
|
use crate::utils::{
|
|
cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir,
|
|
};
|
|
|
|
use std::fs;
|
|
use std::path::Path;
|
|
|
|
fn prepare_libcore(
|
|
sysroot_path: &Path,
|
|
libgccjit12_patches: bool,
|
|
cross_compile: bool,
|
|
) -> Result<(), String> {
|
|
let rustc_path = match get_rustc_path() {
|
|
Some(path) => path,
|
|
None => return Err("`rustc` path not found".to_string()),
|
|
};
|
|
|
|
let parent = match rustc_path.parent() {
|
|
Some(path) => path,
|
|
None => return Err(format!("No parent for `{}`", rustc_path.display())),
|
|
};
|
|
|
|
let rustlib_dir = parent
|
|
.join("../lib/rustlib/src/rust")
|
|
.canonicalize()
|
|
.map_err(|error| format!("Failed to canonicalize path: {:?}", error))?;
|
|
if !rustlib_dir.is_dir() {
|
|
return Err("Please install `rust-src` component".to_string());
|
|
}
|
|
|
|
let sysroot_dir = sysroot_path.join("sysroot_src");
|
|
if sysroot_dir.is_dir() {
|
|
if let Err(error) = fs::remove_dir_all(&sysroot_dir) {
|
|
return Err(format!(
|
|
"Failed to remove `{}`: {:?}",
|
|
sysroot_dir.display(),
|
|
error,
|
|
));
|
|
}
|
|
}
|
|
|
|
let sysroot_library_dir = sysroot_dir.join("library");
|
|
fs::create_dir_all(&sysroot_library_dir).map_err(|error| {
|
|
format!(
|
|
"Failed to create folder `{}`: {:?}",
|
|
sysroot_library_dir.display(),
|
|
error,
|
|
)
|
|
})?;
|
|
|
|
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))?;
|
|
println!("[GIT] add (cwd): `{}`", sysroot_dir.display());
|
|
run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?;
|
|
println!("[GIT] commit (cwd): `{}`", sysroot_dir.display());
|
|
|
|
// 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),
|
|
)?;
|
|
|
|
let mut patches = Vec::new();
|
|
walk_dir(
|
|
"patches",
|
|
|_| Ok(()),
|
|
|file_path: &Path| {
|
|
patches.push(file_path.to_path_buf());
|
|
Ok(())
|
|
},
|
|
)?;
|
|
if cross_compile {
|
|
walk_dir(
|
|
"patches/cross_patches",
|
|
|_| Ok(()),
|
|
|file_path: &Path| {
|
|
patches.push(file_path.to_path_buf());
|
|
Ok(())
|
|
},
|
|
)?;
|
|
}
|
|
if libgccjit12_patches {
|
|
walk_dir(
|
|
"patches/libgccjit12",
|
|
|_| 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",
|
|
&"commit",
|
|
&"--no-gpg-sign",
|
|
&"-m",
|
|
&format!("Patch {}", path.display()),
|
|
],
|
|
Some(&sysroot_dir),
|
|
)?;
|
|
}
|
|
println!("Successfully prepared libcore for building");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// TODO: remove when we can ignore warnings in rustdoc tests.
|
|
fn prepare_rand() -> Result<(), String> {
|
|
// Apply patch for the rand crate.
|
|
let file_path = "patches/crates/0001-Remove-deny-warnings.patch";
|
|
let rand_dir = Path::new("build/rand");
|
|
println!("[GIT] apply `{}`", file_path);
|
|
let path = Path::new("../..").join(file_path);
|
|
run_command_with_output(&[&"git", &"apply", &path], Some(rand_dir))?;
|
|
run_command_with_output(&[&"git", &"add", &"-A"], Some(rand_dir))?;
|
|
run_command_with_output(
|
|
&[
|
|
&"git",
|
|
&"commit",
|
|
&"--no-gpg-sign",
|
|
&"-m",
|
|
&format!("Patch {}", path.display()),
|
|
],
|
|
Some(rand_dir),
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// build with cg_llvm for perf comparison
|
|
fn build_raytracer(repo_dir: &Path) -> Result<(), String> {
|
|
run_command(&[&"cargo", &"build"], Some(repo_dir))?;
|
|
let mv_target = repo_dir.join("raytracer_cg_llvm");
|
|
if mv_target.is_file() {
|
|
remove_file(&mv_target)?;
|
|
}
|
|
run_command(
|
|
&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"],
|
|
Some(repo_dir),
|
|
)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -> Result<(), String>
|
|
where
|
|
F: Fn(&Path) -> Result<(), String>,
|
|
{
|
|
let clone_result = git_clone_root_dir(repo_url, &Path::new(crate::BUILD_DIR), false)?;
|
|
if !clone_result.ran_clone {
|
|
println!("`{}` has already been cloned", clone_result.repo_name);
|
|
}
|
|
let repo_path = Path::new(crate::BUILD_DIR).join(&clone_result.repo_name);
|
|
run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?;
|
|
run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?;
|
|
if let Some(extra) = extra {
|
|
extra(&repo_path)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
struct PrepareArg {
|
|
cross_compile: bool,
|
|
only_libcore: bool,
|
|
libgccjit12_patches: bool,
|
|
}
|
|
|
|
impl PrepareArg {
|
|
fn new() -> Result<Option<Self>, String> {
|
|
let mut only_libcore = false;
|
|
let mut cross_compile = false;
|
|
let mut libgccjit12_patches = false;
|
|
|
|
for arg in std::env::args().skip(2) {
|
|
match arg.as_str() {
|
|
"--only-libcore" => only_libcore = true,
|
|
"--cross" => cross_compile = true,
|
|
"--libgccjit12-patches" => libgccjit12_patches = true,
|
|
"--help" => {
|
|
Self::usage();
|
|
return Ok(None);
|
|
}
|
|
a => return Err(format!("Unknown argument `{a}`")),
|
|
}
|
|
}
|
|
Ok(Some(Self {
|
|
cross_compile,
|
|
only_libcore,
|
|
libgccjit12_patches,
|
|
}))
|
|
}
|
|
|
|
fn usage() {
|
|
println!(
|
|
r#"
|
|
`prepare` command help:
|
|
|
|
--only-libcore : Only setup libcore and don't clone other repositories
|
|
--cross : Apply the patches needed to do cross-compilation
|
|
--libgccjit12-patches : Apply patches needed for libgccjit12
|
|
--help : Show this help"#
|
|
)
|
|
}
|
|
}
|
|
|
|
pub fn run() -> Result<(), String> {
|
|
let args = match PrepareArg::new()? {
|
|
Some(a) => a,
|
|
None => return Ok(()),
|
|
};
|
|
let sysroot_path = Path::new("build_sysroot");
|
|
prepare_libcore(sysroot_path, args.libgccjit12_patches, args.cross_compile)?;
|
|
|
|
if !args.only_libcore {
|
|
cargo_install("hyperfine")?;
|
|
|
|
let to_clone = &[
|
|
(
|
|
"https://github.com/rust-random/rand.git",
|
|
"1f4507a8e1cf8050e4ceef95eeda8f64645b6719",
|
|
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 {
|
|
clone_and_setup(repo_url, checkout_commit, *cb)?;
|
|
}
|
|
|
|
prepare_rand()?;
|
|
}
|
|
|
|
println!("Successfully ran `prepare`");
|
|
Ok(())
|
|
}
|