1#![warn(rust_2018_idioms)]2#![warn(unused_lifetimes)]3#![warn(unreachable_pub)]45use std::path::PathBuf;6use std::{env, process};78use self::utils::Compiler;910mod abi_cafe;11mod bench;12mod build_backend;13mod build_sysroot;14mod config;15mod path;16mod prepare;17mod rustc_info;18mod shared_utils;19mod tests;20mod todo;21mod utils;2223fn usage() {24 eprintln!("{}", include_str!("usage.txt"));25}2627macro_rules! arg_error {28 ($($err:tt)*) => {{29 eprintln!($($err)*);30 usage();31 std::process::exit(1);32 }};33}3435#[derive(PartialEq, Debug)]36enum Command {37 Prepare,38 Build,39 Test,40 AbiCafe,41 Bench,42 CheckTodo,43}4445#[derive(Copy, Clone, Debug)]46enum SysrootKind {47 None,48 Clif,49 Llvm,50}5152#[derive(Clone, Debug)]53enum CodegenBackend {54 Local(PathBuf),55 Builtin(String),56}5758fn main() {59 if env::var_os("RUST_BACKTRACE").is_none() {60 env::set_var("RUST_BACKTRACE", "1");61 }62 env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");6364 let mut args = env::args().skip(1);65 let command = match args.next().as_deref() {66 Some("prepare") => Command::Prepare,67 Some("build") => Command::Build,68 Some("test") => Command::Test,69 Some("abi-cafe") => Command::AbiCafe,70 Some("bench") => Command::Bench,71 Some("check-todo") => Command::CheckTodo,72 Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),73 Some(command) => arg_error!("Unknown command {}", command),74 None => {75 usage();76 process::exit(0);77 }78 };7980 let mut out_dir = std::env::current_dir().unwrap();81 let mut download_dir = None;82 let mut sysroot_kind = SysrootKind::Clif;83 let mut use_unstable_features = true;84 let mut panic_unwind_support = false;85 let mut frozen = false;86 let mut skip_tests = vec![];87 let mut use_backend = None;88 while let Some(arg) = args.next().as_deref() {89 match arg {90 "--out-dir" => {91 out_dir = PathBuf::from(args.next().unwrap_or_else(|| {92 arg_error!("--out-dir requires argument");93 }));94 }95 "--download-dir" => {96 download_dir = Some(PathBuf::from(args.next().unwrap_or_else(|| {97 arg_error!("--download-dir requires argument");98 })));99 }100 "--sysroot" => {101 sysroot_kind = match args.next().as_deref() {102 Some("none") => SysrootKind::None,103 Some("clif") => SysrootKind::Clif,104 Some("llvm") => SysrootKind::Llvm,105 Some(arg) => arg_error!("Unknown sysroot kind {}", arg),106 None => arg_error!("--sysroot requires argument"),107 }108 }109 "--no-unstable-features" => use_unstable_features = false,110 "--panic-unwind-support" => panic_unwind_support = true,111 "--frozen" => frozen = true,112 "--skip-test" => {113 // FIXME check that all passed in tests actually exist114 skip_tests.push(args.next().unwrap_or_else(|| {115 arg_error!("--skip-test requires argument");116 }));117 }118 "--use-backend" => {119 use_backend = Some(match args.next() {120 Some(name) => name,121 None => arg_error!("--use-backend requires argument"),122 });123 }124 flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag),125 arg => arg_error!("Unexpected argument {}", arg),126 }127 }128129 let current_dir = std::env::current_dir().unwrap();130 out_dir = current_dir.join(out_dir);131132 if command == Command::Prepare {133 prepare::prepare(&path::Dirs {134 source_dir: current_dir.clone(),135 download_dir: download_dir136 .map(|dir| current_dir.join(dir))137 .unwrap_or_else(|| out_dir.join("download")),138 build_dir: PathBuf::from("dummy_do_not_use"),139 dist_dir: PathBuf::from("dummy_do_not_use"),140 frozen,141 });142 process::exit(0);143 }144145 if command == Command::CheckTodo {146 todo::run();147 }148149 let rustup_toolchain_name = match (env::var("CARGO"), env::var("RUSTC"), env::var("RUSTDOC")) {150 (Ok(_), Ok(_), Ok(_)) => None,151 (_, Err(_), Err(_)) => Some(rustc_info::get_toolchain_name()),152 vars => {153 eprintln!(154 "If RUSTC or RUSTDOC is set, both need to be set and in addition CARGO needs to be set: {vars:?}"155 );156 process::exit(1);157 }158 };159 let bootstrap_host_compiler = {160 let cargo = rustc_info::get_cargo_path();161 let rustc = rustc_info::get_rustc_path();162 let rustdoc = rustc_info::get_rustdoc_path();163 let triple =164 std::env::var("HOST_TRIPLE").unwrap_or_else(|_| rustc_info::get_host_triple(&rustc));165 Compiler {166 cargo,167 rustc,168 rustdoc,169 rustflags: vec![],170 rustdocflags: vec![],171 triple,172 runner: vec![],173 }174 };175 let target_triple =176 std::env::var("TARGET_TRIPLE").unwrap_or_else(|_| bootstrap_host_compiler.triple.clone());177178 let dirs = path::Dirs {179 source_dir: current_dir.clone(),180 download_dir: download_dir181 .map(|dir| current_dir.join(dir))182 .unwrap_or_else(|| out_dir.join("download")),183 build_dir: out_dir.join("build"),184 dist_dir: out_dir.join("dist"),185 frozen,186 };187188 std::fs::create_dir_all(&dirs.build_dir).unwrap();189190 {191 // Make sure we always explicitly specify the target dir192 let target = dirs.build_dir.join("target_dir_should_be_set_explicitly");193 env::set_var("CARGO_TARGET_DIR", &target);194 let _ = std::fs::remove_file(&target);195 std::fs::File::create(target).unwrap();196 }197198 env::set_var("RUSTC", "rustc_should_be_set_explicitly");199 env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly");200201 let cg_clif_dylib = if let Some(name) = use_backend {202 CodegenBackend::Builtin(name)203 } else {204 CodegenBackend::Local(build_backend::build_backend(205 &dirs,206 &bootstrap_host_compiler,207 use_unstable_features,208 panic_unwind_support,209 ))210 };211 match command {212 Command::Prepare | Command::CheckTodo => {213 // Handled above214 }215 Command::Test => {216 tests::run_tests(217 &dirs,218 sysroot_kind,219 use_unstable_features,220 panic_unwind_support,221 &skip_tests.iter().map(|test| &**test).collect::<Vec<_>>(),222 &cg_clif_dylib,223 &bootstrap_host_compiler,224 rustup_toolchain_name.as_deref(),225 target_triple.clone(),226 );227 }228 Command::AbiCafe => {229 if bootstrap_host_compiler.triple != target_triple {230 eprintln!("Abi-cafe doesn't support cross-compilation");231 process::exit(1);232 }233 abi_cafe::run(234 sysroot_kind,235 &dirs,236 &cg_clif_dylib,237 rustup_toolchain_name.as_deref(),238 &bootstrap_host_compiler,239 panic_unwind_support,240 );241 }242 Command::Build => {243 build_sysroot::build_sysroot(244 &dirs,245 sysroot_kind,246 &cg_clif_dylib,247 &bootstrap_host_compiler,248 rustup_toolchain_name.as_deref(),249 target_triple,250 panic_unwind_support,251 );252 }253 Command::Bench => {254 let compiler = build_sysroot::build_sysroot(255 &dirs,256 sysroot_kind,257 &cg_clif_dylib,258 &bootstrap_host_compiler,259 rustup_toolchain_name.as_deref(),260 target_triple,261 panic_unwind_support,262 );263 bench::benchmark(&dirs, &compiler);264 }265 }266}
Code quality findings 10
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning
correctness
unwrap-usage
let mut out_dir = std::env::current_dir().unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning
correctness
unwrap-usage
let current_dir = std::env::current_dir().unwrap();
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning
correctness
unwrap-usage
std::fs::create_dir_all(&dirs.build_dir).unwrap();
Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning
correctness
discarded-result
let _ = std::fs::remove_file(&target);
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning
correctness
unwrap-usage
std::fs::File::create(target).unwrap();
Info: Including file content directly into the binary at compile time. Ensure this is intended, as it increases binary size and doesn't reflect runtime file changes.
info
maintainability
include-in-binary
eprintln!("{}", include_str!("usage.txt"));
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info
maintainability
println-macro
eprintln!("{}", include_str!("usage.txt"));
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info
maintainability
println-macro
eprintln!($($err)*);
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info
maintainability
println-macro
eprintln!(
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info
maintainability
println-macro
eprintln!("Abi-cafe doesn't support cross-compilation");