about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--build_system/src/clone_gcc.rs79
-rw-r--r--build_system/src/config.rs13
-rw-r--r--build_system/src/main.rs19
-rw-r--r--build_system/src/prepare.rs4
-rw-r--r--build_system/src/test.rs17
-rw-r--r--build_system/src/utils.rs61
6 files changed, 157 insertions, 36 deletions
diff --git a/build_system/src/clone_gcc.rs b/build_system/src/clone_gcc.rs
new file mode 100644
index 00000000000..aee46afaeb0
--- /dev/null
+++ b/build_system/src/clone_gcc.rs
@@ -0,0 +1,79 @@
+use crate::config::ConfigInfo;
+use crate::utils::{git_clone, run_command_with_output};
+
+use std::path::{Path, PathBuf};
+
+fn show_usage() {
+    println!(
+        r#"
+`clone-gcc` command help:
+
+    --out-path         : Location where the GCC repository will be cloned (default: `./gcc`)"#
+    );
+    ConfigInfo::show_usage();
+    println!("    --help                 : Show this help");
+}
+
+#[derive(Default)]
+struct Args {
+    out_path: PathBuf,
+    config_info: ConfigInfo,
+}
+
+impl Args {
+    fn new() -> Result<Option<Self>, String> {
+        let mut command_args = Self::default();
+
+        let mut out_path = None;
+
+        // We skip binary name and the `clone-gcc` command.
+        let mut args = std::env::args().skip(2);
+
+        while let Some(arg) = args.next() {
+            match arg.as_str() {
+                "--out-path" => match args.next() {
+                    Some(path) if !path.is_empty() => out_path = Some(path),
+                    _ => {
+                        return Err("Expected an argument after `--out-path`, found nothing".into())
+                    }
+                },
+                "--help" => {
+                    show_usage();
+                    return Ok(None);
+                }
+                arg => {
+                    if !command_args.config_info.parse_argument(arg, &mut args)? {
+                        return Err(format!("Unknown option {}", arg));
+                    }
+                }
+            }
+        }
+        command_args.out_path = match out_path {
+            Some(p) => p.into(),
+            None => PathBuf::from("./gcc"),
+        };
+        return Ok(Some(command_args));
+    }
+}
+
+pub fn run() -> Result<(), String> {
+    let Some(args) = Args::new()? else {
+        return Ok(());
+    };
+
+    let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
+    if result.ran_clone {
+        let gcc_commit = args.config_info.get_gcc_commit()?;
+        println!("Checking out GCC commit `{}`...", gcc_commit);
+        run_command_with_output(
+            &[&"git", &"checkout", &gcc_commit],
+            Some(Path::new(&result.repo_dir)),
+        )?;
+    } else {
+        println!(
+            "There is already a GCC folder in `{}`, leaving things as is...",
+            args.out_path.display()
+        );
+    }
+    Ok(())
+}
diff --git a/build_system/src/config.rs b/build_system/src/config.rs
index f6f03937018..c633ee57d4a 100644
--- a/build_system/src/config.rs
+++ b/build_system/src/config.rs
@@ -192,9 +192,7 @@ impl ConfigInfo {
         command
     }
 
-    fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
-        let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
-
+    pub fn get_gcc_commit(&self) -> Result<String, String> {
         let commit_hash_file = self.compute_path("libgccjit.version");
         let content = fs::read_to_string(&commit_hash_file).map_err(|_| {
             format!(
@@ -212,7 +210,14 @@ impl ConfigInfo {
                 commit,
             ));
         }
-        let output_dir = output_dir.join(commit);
+        Ok(commit.to_string())
+    }
+
+    fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
+        let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
+        let commit = self.get_gcc_commit()?;
+
+        let output_dir = output_dir.join(&commit);
         if !output_dir.is_dir() {
             std::fs::create_dir_all(&output_dir).map_err(|err| {
                 format!(
diff --git a/build_system/src/main.rs b/build_system/src/main.rs
index 18dc4b21a96..48ffbc7a907 100644
--- a/build_system/src/main.rs
+++ b/build_system/src/main.rs
@@ -4,6 +4,7 @@ use std::process;
 mod build;
 mod cargo;
 mod clean;
+mod clone_gcc;
 mod config;
 mod info;
 mod prepare;
@@ -27,19 +28,21 @@ fn usage() {
         "\
 Available commands for build_system:
 
-    cargo    : Run cargo command
-    clean    : Run clean command
-    prepare  : Run prepare command
-    build    : Run build command
-    test     : Run test command
-    info:    : Run info command
-    --help   : Show this message"
+    cargo     : Run cargo command
+    clean     : Run clean command
+    prepare   : Run prepare command
+    build     : Run build command
+    test      : Run test command
+    info      : Run info command
+    clone-gcc : Run clone-gcc command
+    --help    : Show this message"
     );
 }
 
 pub enum Command {
     Cargo,
     Clean,
+    CloneGcc,
     Prepare,
     Build,
     Test,
@@ -58,6 +61,7 @@ fn main() {
         Some("build") => Command::Build,
         Some("test") => Command::Test,
         Some("info") => Command::Info,
+        Some("clone-gcc") => Command::CloneGcc,
         Some("--help") => {
             usage();
             process::exit(0);
@@ -77,6 +81,7 @@ fn main() {
         Command::Build => build::run(),
         Command::Test => test::run(),
         Command::Info => info::run(),
+        Command::CloneGcc => clone_gcc::run(),
     } {
         eprintln!("Command failed to run: {e}");
         process::exit(1);
diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs
index 66f440f5355..4ea334ad8b9 100644
--- a/build_system/src/prepare.rs
+++ b/build_system/src/prepare.rs
@@ -1,6 +1,6 @@
 use crate::rustc_info::get_rustc_path;
 use crate::utils::{
-    cargo_install, git_clone, remove_file, run_command, run_command_with_output, walk_dir,
+    cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir,
 };
 
 use std::fs;
@@ -152,7 +152,7 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
 where
     F: Fn(&Path) -> Result<(), String>,
 {
-    let clone_result = git_clone(repo_url, Some(&Path::new(crate::BUILD_DIR)), false)?;
+    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);
     }
diff --git a/build_system/src/test.rs b/build_system/src/test.rs
index 17b1868502a..470bb2431d5 100644
--- a/build_system/src/test.rs
+++ b/build_system/src/test.rs
@@ -1,7 +1,7 @@
 use crate::build;
 use crate::config::{Channel, ConfigInfo};
 use crate::utils::{
-    get_toolchain, git_clone, remove_file, run_command, run_command_with_env,
+    get_toolchain, git_clone, git_clone_root_dir, remove_file, run_command, run_command_with_env,
     run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
 };
 
@@ -487,15 +487,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
     );
     let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust");
     // If the repository was already cloned, command will fail, so doesn't matter.
-    let _ = run_command_with_output_and_env(
-        &[
-            &"git",
-            &"clone",
-            &"https://github.com/rust-lang/rust.git",
-            &rust_dir_path,
-        ],
-        None,
-        Some(env),
+    let _ = git_clone(
+        "https://github.com/rust-lang/rust.git",
+        Some(&rust_dir_path),
+        false,
     );
     let rust_dir: Option<&Path> = Some(&rust_dir_path);
     run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?;
@@ -720,7 +715,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
 
     let run_tests = |projects_path, iter: &mut dyn Iterator<Item = &&str>| -> Result<(), String> {
         for project in iter {
-            let clone_result = git_clone(project, Some(projects_path), true)?;
+            let clone_result = git_clone_root_dir(project, projects_path, true)?;
             let repo_path = Path::new(&clone_result.repo_dir);
             run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?;
             run_cargo_command(&[&"test"], Some(repo_path), env, args)?;
diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs
index 33dcd9ef700..d9c13fd143d 100644
--- a/build_system/src/utils.rs
+++ b/build_system/src/utils.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fmt::Debug;
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::{Command, ExitStatus, Output};
 
 fn get_command_inner(
@@ -254,20 +254,12 @@ pub struct CloneResult {
     pub repo_dir: String,
 }
 
-pub fn git_clone(
+fn git_clone_inner(
     to_clone: &str,
-    dest: Option<&Path>,
+    dest: &Path,
     shallow_clone: bool,
+    repo_name: String,
 ) -> Result<CloneResult, String> {
-    let repo_name = to_clone.split('/').last().unwrap();
-    let repo_name = match repo_name.strip_suffix(".git") {
-        Some(n) => n.to_string(),
-        None => repo_name.to_string(),
-    };
-
-    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,
@@ -289,6 +281,51 @@ pub fn git_clone(
     })
 }
 
+fn get_repo_name(url: &str) -> String {
+    let repo_name = url.split('/').last().unwrap();
+    match repo_name.strip_suffix(".git") {
+        Some(n) => n.to_string(),
+        None => repo_name.to_string(),
+    }
+}
+
+pub fn git_clone(
+    to_clone: &str,
+    dest: Option<&Path>,
+    shallow_clone: bool,
+) -> Result<CloneResult, String> {
+    let repo_name = get_repo_name(to_clone);
+    let tmp: PathBuf;
+
+    let dest = match dest {
+        Some(dest) => dest,
+        None => {
+            tmp = repo_name.clone().into();
+            &tmp
+        }
+    };
+    git_clone_inner(to_clone, dest, shallow_clone, repo_name)
+}
+
+/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
+/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
+/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
+/// `a/b`.
+pub fn git_clone_root_dir(
+    to_clone: &str,
+    dest_parent_dir: &Path,
+    shallow_clone: bool,
+) -> Result<CloneResult, String> {
+    let repo_name = get_repo_name(to_clone);
+
+    git_clone_inner(
+        to_clone,
+        &dest_parent_dir.join(&repo_name),
+        shallow_clone,
+        repo_name,
+    )
+}
+
 pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
 where
     P: AsRef<Path>,