| use std::{env, process}; |
| |
| mod abi_test; |
| mod build; |
| mod clean; |
| mod clippy; |
| mod clone_gcc; |
| mod config; |
| mod fmt; |
| mod fuzz; |
| mod info; |
| mod prepare; |
| mod rust_tools; |
| mod rustc_info; |
| mod test; |
| mod todo; |
| mod utils; |
| const BUILD_DIR: &str = "build"; |
| |
| macro_rules! arg_error { |
| ($($err:tt)*) => {{ |
| eprintln!($($err)*); |
| eprintln!(); |
| usage(); |
| std::process::exit(1); |
| }}; |
| } |
| |
| macro_rules! commands_decl { |
| ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { |
| enum Command { |
| $($variant),+ |
| } |
| |
| impl<'a> From<Option<&'a str>> for Command { |
| fn from(arg: Option<&'a str>) -> Self { |
| match arg { |
| $(Some($doc_name) => Self::$variant,)+ |
| Some("--help") => { |
| usage(); |
| process::exit(0); |
| } |
| Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), |
| Some(command) => arg_error!("Unknown command {}", command), |
| None => { |
| usage(); |
| process::exit(0); |
| } |
| } |
| } |
| } |
| |
| fn usage() { |
| println!("\ |
| rustc_codegen_gcc build system |
| |
| Usage: build_system [command] [options] |
| |
| Options: |
| --help : Displays this help message. |
| |
| Commands:", |
| ); |
| let mut commands = vec![$(($doc_name, $doc),)+]; |
| let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); |
| |
| commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); |
| for (name, doc) in commands { |
| let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::<String>(); |
| eprintln!(" {name}{spacing}: {doc}."); |
| } |
| } |
| } |
| } |
| |
| commands_decl! { |
| Cargo: "cargo" => "Executes a cargo command", |
| Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", |
| Clippy: "clippy" => "Runs clippy", |
| CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", |
| Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", |
| Build: "build" => "Compiles the project", |
| Rustc: "rustc" => "Compiles the program using the GCC compiler", |
| Test: "test" => "Runs tests for the project", |
| Info: "info" => "Displays information about the build environment and project configuration", |
| Fmt: "fmt" => "Runs rustfmt", |
| Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", |
| AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", |
| CheckTodo: "check-todo" => "Checks todo in the project", |
| } |
| |
| fn main() { |
| if env::var("RUST_BACKTRACE").is_err() { |
| unsafe { |
| env::set_var("RUST_BACKTRACE", "1"); |
| } |
| } |
| |
| if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { |
| Command::Cargo => rust_tools::run_cargo(), |
| Command::Rustc => rust_tools::run_rustc(), |
| Command::Clean => clean::run(), |
| Command::Prepare => prepare::run(), |
| Command::Build => build::run(), |
| Command::Test => test::run(), |
| Command::Info => info::run(), |
| Command::CloneGcc => clone_gcc::run(), |
| Command::Fmt => fmt::run(), |
| Command::Fuzz => fuzz::run(), |
| Command::AbiTest => abi_test::run(), |
| Command::Clippy => clippy::run(), |
| Command::CheckTodo => todo::run(), |
| } { |
| eprintln!("Command failed to run: {e}"); |
| // CI needs to tell a build system error apart from the test failures some suites expect. |
| let exit_code = |
| if e == test::TESTS_FAILED_ERROR { test::TESTS_FAILED_EXIT_CODE } else { 1 }; |
| process::exit(exit_code); |
| } |
| } |