about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-04-05 17:32:19 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-04-06 20:00:21 +0200
commit00ad2634d5ec8f718db5ea1520b6de2375ecf237 (patch)
tree5b0911c4e5413466aa37177549ac50d1d1e6694b
parent5eb8d854d12573a841fd5dba71578656aa69f830 (diff)
downloadrust-00ad2634d5ec8f718db5ea1520b6de2375ecf237.tar.gz
rust-00ad2634d5ec8f718db5ea1520b6de2375ecf237.zip
Add `rustc` command to build system
-rw-r--r--build_system/src/main.rs4
-rw-r--r--build_system/src/rust_tools.rs126
2 files changed, 79 insertions, 51 deletions
diff --git a/build_system/src/main.rs b/build_system/src/main.rs
index 99d466f2b86..1bfba0f9828 100644
--- a/build_system/src/main.rs
+++ b/build_system/src/main.rs
@@ -29,6 +29,7 @@ fn usage() {
 Available commands for build_system:
 
     cargo     : Run cargo command
+    rustc     : Run rustc command
     clean     : Run clean command
     prepare   : Run prepare command
     build     : Run build command
@@ -45,6 +46,7 @@ pub enum Command {
     CloneGcc,
     Prepare,
     Build,
+    Rustc,
     Test,
     Info,
 }
@@ -56,6 +58,7 @@ fn main() {
 
     let command = match env::args().nth(1).as_deref() {
         Some("cargo") => Command::Cargo,
+        Some("rustc") => Command::Rustc,
         Some("clean") => Command::Clean,
         Some("prepare") => Command::Prepare,
         Some("build") => Command::Build,
@@ -76,6 +79,7 @@ fn main() {
 
     if let Err(e) = match command {
         Command::Cargo => rust_tools::run_cargo(),
+        Command::Rustc => rust_tools::run_rustc(),
         Command::Clean => clean::run(),
         Command::Prepare => prepare::run(),
         Command::Build => build::run(),
diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs
index 80885d0c6c7..242fa7ef949 100644
--- a/build_system/src/rust_tools.rs
+++ b/build_system/src/rust_tools.rs
@@ -9,7 +9,7 @@ use std::ffi::OsStr;
 use std::path::PathBuf;
 
 fn args(command: &str) -> Result<Option<Vec<String>>, String> {
-    // We skip the binary and the "cargo" option.
+    // We skip the binary and the "cargo"/"rustc" option.
     if let Some("--help") = std::env::args().skip(2).next().as_deref() {
         usage(command);
         return Ok(None);
@@ -36,66 +36,90 @@ fn usage(command: &str) {
     )
 }
 
-pub fn run_cargo() -> Result<(), String> {
-    let args = match args("cargo")? {
-        Some(a) => a,
-        None => return Ok(()),
-    };
+struct RustcTools {
+    env: HashMap<String, String>,
+    args: Vec<String>,
+    toolchain: String,
+    config: ConfigInfo,
+}
 
-    // We first need to go to the original location to ensure that the config setup will go as
-    // expected.
-    let current_dir = std::env::current_dir()
-        .and_then(|path| path.canonicalize())
-        .map_err(|error| format!("Failed to get current directory path: {:?}", error))?;
-    let current_exe = std::env::current_exe()
-        .and_then(|path| path.canonicalize())
-        .map_err(|error| format!("Failed to get current exe path: {:?}", error))?;
-    let mut parent_dir = current_exe.components().map(|comp| comp.as_os_str()).collect::<Vec<_>>();
-    // We run this script from "build_system/target/release/y", so we need to remove these elements.
-    for to_remove in &["y", "release", "target", "build_system"] {
-        if parent_dir.last().map(|part| part == to_remove).unwrap_or(false) {
-            parent_dir.pop();
-        } else {
-            return Err(format!(
-                "Build script not executed from `build_system/target/release/y` (in path {})",
-                current_exe.display(),
-            ));
+impl RustcTools {
+    fn new(command: &str) -> Result<Option<Self>, String> {
+        let Some(args) = args(command)? else { return Ok(None) };
+
+        // We first need to go to the original location to ensure that the config setup will go as
+        // expected.
+        let current_dir = std::env::current_dir()
+            .and_then(|path| path.canonicalize())
+            .map_err(|error| format!("Failed to get current directory path: {:?}", error))?;
+        let current_exe = std::env::current_exe()
+            .and_then(|path| path.canonicalize())
+            .map_err(|error| format!("Failed to get current exe path: {:?}", error))?;
+        let mut parent_dir =
+            current_exe.components().map(|comp| comp.as_os_str()).collect::<Vec<_>>();
+        // We run this script from "build_system/target/release/y", so we need to remove these elements.
+        for to_remove in &["y", "release", "target", "build_system"] {
+            if parent_dir.last().map(|part| part == to_remove).unwrap_or(false) {
+                parent_dir.pop();
+            } else {
+                return Err(format!(
+                    "Build script not executed from `build_system/target/release/y` (in path {})",
+                    current_exe.display(),
+                ));
+            }
         }
-    }
-    let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/")));
-    std::env::set_current_dir(&parent_dir).map_err(|error| {
-        format!("Failed to go to `{}` folder: {:?}", parent_dir.display(), error)
-    })?;
+        let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/")));
+        std::env::set_current_dir(&parent_dir).map_err(|error| {
+            format!("Failed to go to `{}` folder: {:?}", parent_dir.display(), error)
+        })?;
 
-    let mut env: HashMap<String, String> = std::env::vars().collect();
-    ConfigInfo::default().setup(&mut env, false)?;
-    let toolchain = get_toolchain()?;
+        let mut env: HashMap<String, String> = std::env::vars().collect();
+        let mut config = ConfigInfo::default();
+        config.setup(&mut env, false)?;
+        let toolchain = get_toolchain()?;
 
-    let toolchain_version = rustc_toolchain_version_info(&toolchain)?;
-    let default_version = rustc_version_info(None)?;
-    if toolchain_version != default_version {
-        println!(
-            "rustc_codegen_gcc is built for {} but the default rustc version is {}.",
-            toolchain_version.short, default_version.short,
-        );
-        println!("Using {}.", toolchain_version.short);
-    }
+        let toolchain_version = rustc_toolchain_version_info(&toolchain)?;
+        let default_version = rustc_version_info(None)?;
+        if toolchain_version != default_version {
+            println!(
+                "rustc_codegen_gcc is built for {} but the default rustc version is {}.",
+                toolchain_version.short, default_version.short,
+            );
+            println!("Using {}.", toolchain_version.short);
+        }
 
-    // We go back to the original folder since we now have set up everything we needed.
-    std::env::set_current_dir(&current_dir).map_err(|error| {
-        format!("Failed to go back to `{}` folder: {:?}", current_dir.display(), error)
-    })?;
+        // We go back to the original folder since we now have set up everything we needed.
+        std::env::set_current_dir(&current_dir).map_err(|error| {
+            format!("Failed to go back to `{}` folder: {:?}", current_dir.display(), error)
+        })?;
+        let toolchain = format!("+{}", toolchain);
+        Ok(Some(Self { toolchain, args, env, config }))
+    }
+}
 
-    let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
-    env.insert("RUSTDOCFLAGS".to_string(), rustflags);
-    let toolchain = format!("+{}", toolchain);
-    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &toolchain];
-    for arg in &args {
+pub fn run_cargo() -> Result<(), String> {
+    let Some(mut tools) = RustcTools::new("cargo")? else { return Ok(()) };
+    let rustflags = tools.env.get("RUSTFLAGS").cloned().unwrap_or_default();
+    tools.env.insert("RUSTDOCFLAGS".to_string(), rustflags);
+    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &tools.toolchain];
+    for arg in &tools.args {
         command.push(arg);
     }
-    if run_command_with_output_and_env_no_err(&command, None, Some(&env)).is_err() {
+    if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() {
         std::process::exit(1);
     }
 
     Ok(())
 }
+
+pub fn run_rustc() -> Result<(), String> {
+    let Some(tools) = RustcTools::new("rustc")? else { return Ok(()) };
+    let mut command = tools.config.rustc_command_vec();
+    for arg in &tools.args {
+        command.push(arg);
+    }
+    if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() {
+        std::process::exit(1);
+    }
+    Ok(())
+}