2024-03-05 19:58:36 +01:00
|
|
|
use crate::config::{Channel, ConfigInfo};
|
|
|
|
use crate::utils::{run_command, run_command_with_output_and_env, walk_dir};
|
2023-10-09 15:53:34 -04:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::ffi::OsStr;
|
|
|
|
use std::fs;
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
struct BuildArg {
|
2023-10-26 17:42:02 -04:00
|
|
|
flags: Vec<String>,
|
2024-03-05 19:58:36 +01:00
|
|
|
config_info: ConfigInfo,
|
2023-10-09 15:53:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BuildArg {
|
|
|
|
fn new() -> Result<Option<Self>, String> {
|
2024-03-05 19:58:36 +01:00
|
|
|
let mut build_arg = Self::default();
|
2023-10-09 15:53:34 -04:00
|
|
|
// We skip binary name and the `build` command.
|
|
|
|
let mut args = std::env::args().skip(2);
|
|
|
|
|
|
|
|
while let Some(arg) = args.next() {
|
|
|
|
match arg.as_str() {
|
|
|
|
"--features" => {
|
|
|
|
if let Some(arg) = args.next() {
|
2023-10-26 17:42:02 -04:00
|
|
|
build_arg.flags.push("--features".to_string());
|
|
|
|
build_arg.flags.push(arg.as_str().into());
|
2023-10-09 15:53:34 -04:00
|
|
|
} else {
|
|
|
|
return Err(
|
|
|
|
"Expected a value after `--features`, found nothing".to_string()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"--help" => {
|
|
|
|
Self::usage();
|
|
|
|
return Ok(None);
|
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
arg => {
|
|
|
|
if !build_arg.config_info.parse_argument(arg, &mut args)? {
|
|
|
|
return Err(format!("Unknown argument `{}`", arg));
|
2023-10-26 17:42:02 -04:00
|
|
|
}
|
|
|
|
}
|
2023-10-09 15:53:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(Some(build_arg))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn usage() {
|
|
|
|
println!(
|
|
|
|
r#"
|
|
|
|
`build` command help:
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
--features [arg] : Add a new feature [arg]"#
|
|
|
|
);
|
|
|
|
ConfigInfo::show_usage();
|
|
|
|
println!(" --help : Show this help");
|
2023-10-09 15:53:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
|
|
|
|
let start_dir = Path::new("build_sysroot");
|
2023-10-09 15:53:34 -04:00
|
|
|
// Cleanup for previous run
|
|
|
|
// Clean target dir except for build scripts and incremental cache
|
|
|
|
let _ = walk_dir(
|
2024-03-05 19:58:36 +01:00
|
|
|
start_dir.join("target"),
|
2023-10-09 15:53:34 -04:00
|
|
|
|dir: &Path| {
|
|
|
|
for top in &["debug", "release"] {
|
|
|
|
let _ = fs::remove_dir_all(dir.join(top).join("build"));
|
|
|
|
let _ = fs::remove_dir_all(dir.join(top).join("deps"));
|
|
|
|
let _ = fs::remove_dir_all(dir.join(top).join("examples"));
|
|
|
|
let _ = fs::remove_dir_all(dir.join(top).join("native"));
|
|
|
|
|
|
|
|
let _ = walk_dir(
|
|
|
|
dir.join(top),
|
|
|
|
|sub_dir: &Path| {
|
|
|
|
if sub_dir
|
|
|
|
.file_name()
|
|
|
|
.map(|filename| filename.to_str().unwrap().starts_with("libsysroot"))
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
|
|
|
let _ = fs::remove_dir_all(sub_dir);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
|file: &Path| {
|
|
|
|
if file
|
|
|
|
.file_name()
|
|
|
|
.map(|filename| filename.to_str().unwrap().starts_with("libsysroot"))
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
|
|
|
let _ = fs::remove_file(file);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
|_| Ok(()),
|
|
|
|
);
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
let _ = fs::remove_file(start_dir.join("Cargo.lock"));
|
|
|
|
let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
|
|
|
|
let _ = fs::remove_dir_all(start_dir.join("sysroot"));
|
2023-10-09 15:53:34 -04:00
|
|
|
|
|
|
|
// Builds libs
|
2024-03-05 19:58:36 +01:00
|
|
|
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
|
|
|
|
if config.sysroot_panic_abort {
|
2023-10-26 17:42:02 -04:00
|
|
|
rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests");
|
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
rustflags.push_str(" -Z force-unstable-if-unmarked");
|
2024-02-21 13:30:04 +01:00
|
|
|
if config.no_default_features {
|
|
|
|
rustflags.push_str(" -Csymbol-mangling-version=v0");
|
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
let mut env = env.clone();
|
|
|
|
|
|
|
|
let mut args: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"build", &"--target", &config.target];
|
|
|
|
|
|
|
|
if config.no_default_features {
|
|
|
|
rustflags.push_str(" -Csymbol-mangling-version=v0");
|
|
|
|
args.push(&"--no-default-features");
|
|
|
|
}
|
|
|
|
|
|
|
|
let channel = if config.sysroot_release_channel {
|
|
|
|
rustflags.push_str(" -Zmir-opt-level=3");
|
|
|
|
args.push(&"--release");
|
2023-10-09 15:53:34 -04:00
|
|
|
"release"
|
|
|
|
} else {
|
|
|
|
"debug"
|
|
|
|
};
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
env.insert("RUSTFLAGS".to_string(), rustflags);
|
|
|
|
run_command_with_output_and_env(&args, Some(start_dir), Some(&env))?;
|
|
|
|
|
2023-10-09 15:53:34 -04:00
|
|
|
// Copy files to sysroot
|
2024-03-05 19:58:36 +01:00
|
|
|
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
|
|
|
|
fs::create_dir_all(&sysroot_path).map_err(|error| {
|
|
|
|
format!(
|
|
|
|
"Failed to create directory `{}`: {:?}",
|
|
|
|
sysroot_path.display(),
|
|
|
|
error
|
|
|
|
)
|
|
|
|
})?;
|
2023-10-09 15:53:34 -04:00
|
|
|
let copier = |dir_to_copy: &Path| {
|
2024-03-05 19:58:36 +01:00
|
|
|
// FIXME: should not use shell command!
|
2023-10-09 15:53:34 -04:00
|
|
|
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
|
|
|
};
|
|
|
|
walk_dir(
|
2024-03-05 19:58:36 +01:00
|
|
|
start_dir.join(&format!("target/{}/{}/deps", config.target_triple, channel)),
|
2023-10-09 15:53:34 -04:00
|
|
|
copier,
|
|
|
|
copier,
|
|
|
|
)?;
|
|
|
|
|
2023-11-19 13:42:13 -05:00
|
|
|
// Copy the source files to the sysroot (Rust for Linux needs this).
|
2024-03-05 19:58:36 +01:00
|
|
|
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
|
|
|
|
fs::create_dir_all(&sysroot_src_path).map_err(|error| {
|
|
|
|
format!(
|
|
|
|
"Failed to create directory `{}`: {:?}",
|
|
|
|
sysroot_src_path.display(),
|
|
|
|
error
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
run_command(
|
|
|
|
&[
|
|
|
|
&"cp",
|
|
|
|
&"-r",
|
|
|
|
&start_dir.join("sysroot_src/library/"),
|
|
|
|
&sysroot_src_path,
|
|
|
|
],
|
|
|
|
None,
|
|
|
|
)?;
|
2023-11-19 13:42:13 -05:00
|
|
|
|
2023-10-09 15:53:34 -04:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
|
2023-10-09 15:53:34 -04:00
|
|
|
let mut env = HashMap::new();
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
env.insert(
|
|
|
|
"LD_LIBRARY_PATH".to_string(),
|
|
|
|
args.config_info.gcc_path.clone(),
|
|
|
|
);
|
|
|
|
env.insert(
|
|
|
|
"LIBRARY_PATH".to_string(),
|
|
|
|
args.config_info.gcc_path.clone(),
|
|
|
|
);
|
|
|
|
|
|
|
|
if args.config_info.no_default_features {
|
|
|
|
env.insert(
|
|
|
|
"RUSTFLAGS".to_string(),
|
|
|
|
"-Csymbol-mangling-version=v0".to_string(),
|
|
|
|
);
|
|
|
|
}
|
2023-10-09 15:53:34 -04:00
|
|
|
|
|
|
|
let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
|
2024-03-05 19:58:36 +01:00
|
|
|
if args.config_info.channel == Channel::Release {
|
2023-10-09 15:53:34 -04:00
|
|
|
command.push(&"--release");
|
|
|
|
env.insert("CHANNEL".to_string(), "release".to_string());
|
|
|
|
env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string());
|
|
|
|
} else {
|
|
|
|
env.insert("CHANNEL".to_string(), "debug".to_string());
|
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
if args.config_info.no_default_features {
|
|
|
|
command.push(&"--no-default-features");
|
|
|
|
}
|
2023-10-26 17:42:02 -04:00
|
|
|
let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
|
|
|
for flag in &flags {
|
|
|
|
command.push(flag);
|
2023-10-09 15:53:34 -04:00
|
|
|
}
|
2023-10-26 17:42:02 -04:00
|
|
|
run_command_with_output_and_env(&command, None, Some(&env))?;
|
2023-10-09 15:53:34 -04:00
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
args.config_info.setup(&mut env, false)?;
|
2023-10-09 15:53:34 -04:00
|
|
|
|
|
|
|
// We voluntarily ignore the error.
|
|
|
|
let _ = fs::remove_dir_all("target/out");
|
|
|
|
let gccjit_target = "target/out/gccjit";
|
|
|
|
fs::create_dir_all(gccjit_target).map_err(|error| {
|
|
|
|
format!(
|
|
|
|
"Failed to create directory `{}`: {:?}",
|
|
|
|
gccjit_target, error
|
|
|
|
)
|
|
|
|
})?;
|
|
|
|
|
|
|
|
println!("[BUILD] sysroot");
|
2024-03-05 19:58:36 +01:00
|
|
|
build_sysroot(&env, &args.config_info)?;
|
2023-10-09 15:53:34 -04:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run() -> Result<(), String> {
|
2024-03-05 19:58:36 +01:00
|
|
|
let mut args = match BuildArg::new()? {
|
2023-10-09 15:53:34 -04:00
|
|
|
Some(args) => args,
|
|
|
|
None => return Ok(()),
|
|
|
|
};
|
2024-03-05 19:58:36 +01:00
|
|
|
args.config_info.setup_gcc_path()?;
|
|
|
|
build_codegen(&mut args)?;
|
2023-10-09 15:53:34 -04:00
|
|
|
Ok(())
|
|
|
|
}
|