Skip to content

Commit

Permalink
Merge pull request rust-lang#15 from GuillaumeGomez/add-rustc-command
Browse files Browse the repository at this point in the history
Add rustc command to build system
  • Loading branch information
antoyo authored Apr 7, 2024
2 parents 75f0ab5 + 2a99110 commit c7f1d5d
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 100 deletions.
8 changes: 7 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ error: failed to copy bitcode to object file: No such file or directory (os erro

### Rustc

> You should prefer using the Cargo method.
If you want to run `rustc` directly, you can do so with:

```bash
$ ./y.sh rustc my_crate.rs
```

You can do the same manually (although we don't recommend it):

```bash
$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
Expand Down
97 changes: 0 additions & 97 deletions build_system/src/cargo.rs

This file was deleted.

8 changes: 6 additions & 2 deletions build_system/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use std::env;
use std::process;

mod build;
mod cargo;
mod clean;
mod clone_gcc;
mod config;
mod info;
mod prepare;
mod rust_tools;
mod rustc_info;
mod test;
mod utils;
Expand All @@ -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
Expand All @@ -45,6 +46,7 @@ pub enum Command {
CloneGcc,
Prepare,
Build,
Rustc,
Test,
Info,
}
Expand All @@ -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,
Expand All @@ -75,7 +78,8 @@ fn main() {
};

if let Err(e) = match command {
Command::Cargo => cargo::run(),
Command::Cargo => rust_tools::run_cargo(),
Command::Rustc => rust_tools::run_rustc(),
Command::Clean => clean::run(),
Command::Prepare => prepare::run(),
Command::Build => build::run(),
Expand Down
125 changes: 125 additions & 0 deletions build_system/src/rust_tools.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use crate::config::ConfigInfo;
use crate::utils::{
get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info,
rustc_version_info,
};

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::PathBuf;

fn args(command: &str) -> Result<Option<Vec<String>>, String> {
// 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);
}
let args = std::env::args().skip(2).collect::<Vec<_>>();
if args.is_empty() {
return Err(format!(
"Expected at least one argument for `{}` subcommand, found none",
command
));
}
Ok(Some(args))
}

fn usage(command: &str) {
println!(
r#"
`{}` command help:
[args] : Arguments to be passed to the cargo command
--help : Show this help
"#,
command,
)
}

struct RustcTools {
env: HashMap<String, String>,
args: Vec<String>,
toolchain: String,
config: ConfigInfo,
}

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 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);
}

// 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 }))
}
}

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(&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(())
}

0 comments on commit c7f1d5d

Please sign in to comment.