Skip to content

Commit c7f1d5d

Browse files
authored
Merge pull request #15 from GuillaumeGomez/add-rustc-command
Add rustc command to build system
2 parents 75f0ab5 + 2a99110 commit c7f1d5d

File tree

4 files changed

+138
-100
lines changed

4 files changed

+138
-100
lines changed

Readme.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,13 @@ error: failed to copy bitcode to object file: No such file or directory (os erro
118118

119119
### Rustc
120120

121-
> You should prefer using the Cargo method.
121+
If you want to run `rustc` directly, you can do so with:
122+
123+
```bash
124+
$ ./y.sh rustc my_crate.rs
125+
```
126+
127+
You can do the same manually (although we don't recommend it):
122128

123129
```bash
124130
$ 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

build_system/src/cargo.rs

-97
This file was deleted.

build_system/src/main.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ use std::env;
22
use std::process;
33

44
mod build;
5-
mod cargo;
65
mod clean;
76
mod clone_gcc;
87
mod config;
98
mod info;
109
mod prepare;
10+
mod rust_tools;
1111
mod rustc_info;
1212
mod test;
1313
mod utils;
@@ -29,6 +29,7 @@ fn usage() {
2929
Available commands for build_system:
3030
3131
cargo : Run cargo command
32+
rustc : Run rustc command
3233
clean : Run clean command
3334
prepare : Run prepare command
3435
build : Run build command
@@ -45,6 +46,7 @@ pub enum Command {
4546
CloneGcc,
4647
Prepare,
4748
Build,
49+
Rustc,
4850
Test,
4951
Info,
5052
}
@@ -56,6 +58,7 @@ fn main() {
5658

5759
let command = match env::args().nth(1).as_deref() {
5860
Some("cargo") => Command::Cargo,
61+
Some("rustc") => Command::Rustc,
5962
Some("clean") => Command::Clean,
6063
Some("prepare") => Command::Prepare,
6164
Some("build") => Command::Build,
@@ -75,7 +78,8 @@ fn main() {
7578
};
7679

7780
if let Err(e) = match command {
78-
Command::Cargo => cargo::run(),
81+
Command::Cargo => rust_tools::run_cargo(),
82+
Command::Rustc => rust_tools::run_rustc(),
7983
Command::Clean => clean::run(),
8084
Command::Prepare => prepare::run(),
8185
Command::Build => build::run(),

build_system/src/rust_tools.rs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use crate::config::ConfigInfo;
2+
use crate::utils::{
3+
get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info,
4+
rustc_version_info,
5+
};
6+
7+
use std::collections::HashMap;
8+
use std::ffi::OsStr;
9+
use std::path::PathBuf;
10+
11+
fn args(command: &str) -> Result<Option<Vec<String>>, String> {
12+
// We skip the binary and the "cargo"/"rustc" option.
13+
if let Some("--help") = std::env::args().skip(2).next().as_deref() {
14+
usage(command);
15+
return Ok(None);
16+
}
17+
let args = std::env::args().skip(2).collect::<Vec<_>>();
18+
if args.is_empty() {
19+
return Err(format!(
20+
"Expected at least one argument for `{}` subcommand, found none",
21+
command
22+
));
23+
}
24+
Ok(Some(args))
25+
}
26+
27+
fn usage(command: &str) {
28+
println!(
29+
r#"
30+
`{}` command help:
31+
32+
[args] : Arguments to be passed to the cargo command
33+
--help : Show this help
34+
"#,
35+
command,
36+
)
37+
}
38+
39+
struct RustcTools {
40+
env: HashMap<String, String>,
41+
args: Vec<String>,
42+
toolchain: String,
43+
config: ConfigInfo,
44+
}
45+
46+
impl RustcTools {
47+
fn new(command: &str) -> Result<Option<Self>, String> {
48+
let Some(args) = args(command)? else { return Ok(None) };
49+
50+
// We first need to go to the original location to ensure that the config setup will go as
51+
// expected.
52+
let current_dir = std::env::current_dir()
53+
.and_then(|path| path.canonicalize())
54+
.map_err(|error| format!("Failed to get current directory path: {:?}", error))?;
55+
let current_exe = std::env::current_exe()
56+
.and_then(|path| path.canonicalize())
57+
.map_err(|error| format!("Failed to get current exe path: {:?}", error))?;
58+
let mut parent_dir =
59+
current_exe.components().map(|comp| comp.as_os_str()).collect::<Vec<_>>();
60+
// We run this script from "build_system/target/release/y", so we need to remove these elements.
61+
for to_remove in &["y", "release", "target", "build_system"] {
62+
if parent_dir.last().map(|part| part == to_remove).unwrap_or(false) {
63+
parent_dir.pop();
64+
} else {
65+
return Err(format!(
66+
"Build script not executed from `build_system/target/release/y` (in path {})",
67+
current_exe.display(),
68+
));
69+
}
70+
}
71+
let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/")));
72+
std::env::set_current_dir(&parent_dir).map_err(|error| {
73+
format!("Failed to go to `{}` folder: {:?}", parent_dir.display(), error)
74+
})?;
75+
76+
let mut env: HashMap<String, String> = std::env::vars().collect();
77+
let mut config = ConfigInfo::default();
78+
config.setup(&mut env, false)?;
79+
let toolchain = get_toolchain()?;
80+
81+
let toolchain_version = rustc_toolchain_version_info(&toolchain)?;
82+
let default_version = rustc_version_info(None)?;
83+
if toolchain_version != default_version {
84+
println!(
85+
"rustc_codegen_gcc is built for {} but the default rustc version is {}.",
86+
toolchain_version.short, default_version.short,
87+
);
88+
println!("Using {}.", toolchain_version.short);
89+
}
90+
91+
// We go back to the original folder since we now have set up everything we needed.
92+
std::env::set_current_dir(&current_dir).map_err(|error| {
93+
format!("Failed to go back to `{}` folder: {:?}", current_dir.display(), error)
94+
})?;
95+
let toolchain = format!("+{}", toolchain);
96+
Ok(Some(Self { toolchain, args, env, config }))
97+
}
98+
}
99+
100+
pub fn run_cargo() -> Result<(), String> {
101+
let Some(mut tools) = RustcTools::new("cargo")? else { return Ok(()) };
102+
let rustflags = tools.env.get("RUSTFLAGS").cloned().unwrap_or_default();
103+
tools.env.insert("RUSTDOCFLAGS".to_string(), rustflags);
104+
let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &tools.toolchain];
105+
for arg in &tools.args {
106+
command.push(arg);
107+
}
108+
if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() {
109+
std::process::exit(1);
110+
}
111+
112+
Ok(())
113+
}
114+
115+
pub fn run_rustc() -> Result<(), String> {
116+
let Some(tools) = RustcTools::new("rustc")? else { return Ok(()) };
117+
let mut command = tools.config.rustc_command_vec();
118+
for arg in &tools.args {
119+
command.push(arg);
120+
}
121+
if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() {
122+
std::process::exit(1);
123+
}
124+
Ok(())
125+
}

0 commit comments

Comments
 (0)