about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2023-08-19 20:53:47 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2023-08-20 00:49:31 +0200
commitc682e9ca94e3b7d4c1dfcf4686360e7760e8ef9f (patch)
tree0f6da5e1708caed732e9eb536adf7ae6795b6383
parent18d22d56989db6590872cc6791b68cefc8695eab (diff)
downloadrust-c682e9ca94e3b7d4c1dfcf4686360e7760e8ef9f.tar.gz
rust-c682e9ca94e3b7d4c1dfcf4686360e7760e8ef9f.zip
Correctly set path
-rw-r--r--build_system/src/prepare.rs50
-rw-r--r--build_system/src/utils.rs87
2 files changed, 92 insertions, 45 deletions
diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs
index 8e6183be629..9c31b5cb8b3 100644
--- a/build_system/src/prepare.rs
+++ b/build_system/src/prepare.rs
@@ -4,7 +4,7 @@ use crate::utils::{cargo_install, git_clone, run_command, run_command_with_outpu
 use std::fs;
 use std::path::Path;
 
-fn prepare_libcore() -> Result<(), String> {
+fn prepare_libcore(sysroot_path: &Path) -> Result<(), String> {
     let rustc_path = match get_rustc_path() {
         Some(path) => path,
         None => return Err("`rustc` path not found".to_owned()),
@@ -15,14 +15,18 @@ fn prepare_libcore() -> Result<(), String> {
         None => return Err(format!("No parent for `{}`", rustc_path.display())),
     };
 
-    let rustlib_dir = parent.join("../lib/rustlib/src/rust");
+    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());
     }
 
-    let sysroot_dir = Path::new("build_sysroot/sysroot_src");
+    let sysroot_dir = sysroot_path.join("sysroot_src");
     if sysroot_dir.is_dir() {
-        if let Err(e) = fs::remove_dir_all(sysroot_dir) {
+        if let Err(e) = fs::remove_dir_all(&sysroot_dir) {
             return Err(format!("Failed to remove `{}`: {:?}", sysroot_dir.display(), e));
         }
     }
@@ -34,12 +38,12 @@ fn prepare_libcore() -> Result<(), String> {
             sysroot_library_dir.display(),
         ))?;
 
-    run_command(&[&"cp", &"-r", &rustlib_dir, &sysroot_library_dir], None)?;
+    run_command(&[&"cp", &"-r", &rustlib_dir.join("library"), &sysroot_dir], None)?;
 
     println!("[GIT] init (cwd): `{}`", sysroot_dir.display());
-    run_command_with_output(&[&"git", &"init"], Some(&sysroot_dir))?;
+    run_command(&[&"git", &"init"], Some(&sysroot_dir))?;
     println!("[GIT] add (cwd): `{}`", sysroot_dir.display());
-    run_command_with_output(&[&"git", &"add", &"."], Some(&sysroot_dir))?;
+    run_command(&[&"git", &"add", &"."], Some(&sysroot_dir))?;
     println!("[GIT] commit (cwd): `{}`", sysroot_dir.display());
 
     // This is needed on systems where nothing is configured.
@@ -47,11 +51,17 @@ fn prepare_libcore() -> Result<(), String> {
     // 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", &"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(())
+    })?;
+    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))?;
@@ -60,8 +70,7 @@ fn prepare_libcore() -> Result<(), String> {
             &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())],
             Some(&sysroot_dir),
         )?;
-        Ok(())
-    })?;
+    }
     println!("Successfully prepared libcore for building");
     Ok(())
 }
@@ -69,6 +78,11 @@ fn prepare_libcore() -> Result<(), String> {
 // 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() {
+        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))?;
     Ok(())
 }
@@ -82,18 +96,21 @@ where
         println!("`{}` has already been cloned", clone_result.repo_name);
     }
     let repo_path = Path::new(&clone_result.repo_name);
-    run_command(&[&"git", &"checkout", &"--", &"."], Some(repo_path))?;
-    run_command(&[&"git", &"checkout", &checkout_commit], Some(repo_path))?;
+    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(&[&"git", &"am", &s], Some(repo_path))?;
+            run_command_with_output(
+                &[&"git", &"am", &file_path.canonicalize().unwrap()],
+                Some(&repo_path),
+            )?;
         }
         Ok(())
     })?;
     if let Some(extra) = extra {
-        extra(repo_path)?;
+        extra(&repo_path)?;
     }
     Ok(())
 }
@@ -136,7 +153,8 @@ pub fn run() -> Result<(), String> {
         Some(a) => a,
         None => return Ok(()),
     };
-    prepare_libcore()?;
+    let sysroot_path = Path::new("build_sysroot");
+    prepare_libcore(sysroot_path)?;
 
     if !args.only_libcore {
         cargo_install("hyperfine")?;
diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs
index 145f40ec8ae..c350864dbd2 100644
--- a/build_system/src/utils.rs
+++ b/build_system/src/utils.rs
@@ -1,9 +1,10 @@
 use std::ffi::OsStr;
+use std::fmt::Debug;
 use std::fs;
 use std::path::Path;
-use std::process::{Command, Output};
+use std::process::{Command, ExitStatus, Output};
 
-fn run_command_inner(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Command {
+fn get_command_inner(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Command {
     let (cmd, args) = match input {
         [] => panic!("empty command"),
         [cmd, args @ ..] => (cmd, args),
@@ -16,44 +17,67 @@ fn run_command_inner(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Command
     command
 }
 
-pub fn run_command(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Result<Output, String> {
-    run_command_inner(input, cwd).output()
-        .map_err(|e| format!(
-            "Command `{}` failed to run: {e:?}",
+fn check_exit_status(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    exit_status: ExitStatus,
+) -> Result<(), String> {
+    if exit_status.success() {
+        Ok(())
+    } else {
+        Err(format!(
+            "Command `{}`{} exited with status {:?}",
             input.iter()
                 .map(|s| s.as_ref().to_str().unwrap())
                 .collect::<Vec<_>>()
                 .join(" "),
+            cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display()))
+                .unwrap_or_default(),
+            exit_status.code(),
         ))
+    }
+}
+
+fn command_error<D: Debug>(input: &[&dyn AsRef<OsStr>], cwd: &Option<&Path>, error: D) -> String {
+    format!(
+        "Command `{}`{} failed to run: {error:?}",
+        input.iter()
+            .map(|s| s.as_ref().to_str().unwrap())
+            .collect::<Vec<_>>()
+            .join(" "),
+        cwd.as_ref()
+            .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)
+        .output()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, output.status)?;
+    Ok(output)
 }
 
 pub fn run_command_with_output(
     input: &[&dyn AsRef<OsStr>],
     cwd: Option<&Path>,
 ) -> Result<(), String> {
-    run_command_inner(input, cwd).spawn()
-        .map_err(|e| format!(
-            "Command `{}` failed to run: {e:?}",
-            input.iter()
-                .map(|s| s.as_ref().to_str().unwrap())
-                .collect::<Vec<_>>()
-                .join(" "),
-        ))?
+    let exit_status = get_command_inner(input, cwd).spawn()
+        .map_err(|e| command_error(input, &cwd, e))?
         .wait()
-        .map_err(|e| format!(
-            "Failed to wait for command `{}` to run: {e:?}",
-            input.iter()
-                .map(|s| s.as_ref().to_str().unwrap())
-                .collect::<Vec<_>>()
-                .join(" "),
-        ))?;
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, exit_status)?;
     Ok(())
 }
 
 pub fn cargo_install(to_install: &str) -> Result<(), String> {
     let output = run_command(&[&"cargo", &"install", &"--list"], None)?;
 
-    let to_install = format!("{to_install} ");
+    let to_install_needle = format!("{to_install} ");
     // cargo install --list returns something like this:
     //
     // mdbook-toc v0.8.0:
@@ -65,11 +89,14 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> {
     if String::from_utf8(output.stdout)
         .unwrap()
         .lines()
-        .any(|line| line.ends_with(':') && line.starts_with(&to_install))
+        .any(|line| line.ends_with(':') && line.starts_with(&to_install_needle))
     {
         return Ok(());
     }
-    run_command(&[&"cargo", &"install", &to_install], None)?;
+    // We voluntarily ignore this error.
+    if run_command_with_output(&[&"cargo", &"install", &to_install], None).is_err() {
+        println!("Skipping installation of `{to_install}`");
+    }
     Ok(())
 }
 
@@ -85,20 +112,22 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, Str
         None => repo_name.to_owned(),
     };
 
-    let dest = dest.unwrap_or_else(|| Path::new(&repo_name));
+    let dest = dest
+        .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 });
     }
 
-    run_command(&[&"git", &"clone", &to_clone, &dest], None)?;
+    run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None)?;
     Ok(CloneResult { ran_clone: true, repo_name })
 }
 
-pub fn walk_dir<P, D, F>(dir: P, dir_cb: D, file_cb: F) -> Result<(), String>
+pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
 where
     P: AsRef<Path>,
-    D: Fn(&Path) -> Result<(), String>,
-    F: Fn(&Path) -> Result<(), String>,
+    D: FnMut(&Path) -> Result<(), String>,
+    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()))? {