diff --git a/crates/tools/gnu/Cargo.toml b/crates/tools/gnu/Cargo.toml index 037a495cba..a5a1c1720c 100644 --- a/crates/tools/gnu/Cargo.toml +++ b/crates/tools/gnu/Cargo.toml @@ -6,3 +6,4 @@ publish = false [dependencies] lib = { package = "tool_lib", path = "../lib" } +which = "4" diff --git a/crates/tools/gnu/readme.md b/crates/tools/gnu/readme.md index f4a4d7b317..d8f9c3a60a 100644 --- a/crates/tools/gnu/readme.md +++ b/crates/tools/gnu/readme.md @@ -1,21 +1,8 @@ The Windows umbrella lib (targeting GNU tooling) is generated using the following steps: 0. Ensure MSYS2 MinGW environment is installed (https://www.mingw-w64.org/downloads/) -1. Ensure `~\.cargo\config` has the following blocks to override toolchain defaults (customize paths as needed): - - ```toml - [target.i686-pc-windows-gnu] - linker = "C:\\msys64\\mingw32\\bin\\i686-w64-mingw32-gcc.exe" - ar = "C:\\msys64\\mingw32\\bin\\ar.exe" - - [target.x86_64-pc-windows-gnu] - linker = "C:\\msys64\\mingw64\\bin\\x86_64-w64-mingw32-gcc.exe" - ar = "C:\\msys64\\mingw64\\bin\\ar.exe" - ``` - -1. Open `MSYS2 MinGW 32-bit` +1. Open `MSYS2 MinGW 64-bit` 2. Execute: `pacman -Syuu --noconfirm` (repeat until no further updates available) 3. Repeat step 1 if needed 4. Navigate to crate root -5. Execute: `PATH=$USERPROFILE/.cargo/bin:$PATH cargo run -p tool_gnu --target i686-pc-windows-gnu` -6. Repeat steps 1-5, using the `MSYS MinGW 64-bit` environment and `x86_64-pc-windows-gnu` target +5. Execute: `PATH=$USERPROFILE/.cargo/bin:$PATH cargo run -p tool_gnu -- all` diff --git a/crates/tools/gnu/src/main.rs b/crates/tools/gnu/src/main.rs index 91b5c3a4ad..911ce86119 100644 --- a/crates/tools/gnu/src/main.rs +++ b/crates/tools/gnu/src/main.rs @@ -1,28 +1,37 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::io::prelude::*; fn main() { - let mut cmd = std::process::Command::new("where"); - cmd.arg("dlltool.exe"); - - let output = cmd.output().unwrap(); - - if !output.status.success() { - println!("dlltool.exe not found"); - return; + for cmd in ["dlltool", "ar", "objcopy"] { + if which::which(cmd).is_err() { + eprintln!("Could not find {}. Is it in your $PATH?", cmd); + return; + } + } + + const ALL_PLATFORMS: [&str; 2] = ["x86_64_gnu", "i686_gnu"]; + let mut platforms = BTreeSet::new(); + for platform in std::env::args().skip(1) { + if ALL_PLATFORMS.contains(&&*platform) { + platforms.insert(platform); + } else if platform == "all" { + platforms.extend(ALL_PLATFORMS.iter().map(|s| s.to_string())); + } else { + eprintln!("Unknown platform: {}", platform); + return; + } } - - let output = unsafe { core::str::from_utf8_unchecked(&output.stdout) }; - - let platform = if output.contains("mingw64") { - "x86_64_gnu" - } else if output.contains("mingw32") { - "i686_gnu" - } else { - println!("mingw not found"); + if platforms.is_empty() { + eprintln!("Please specify at least one platform or use 'all' argument"); return; }; + for platform in platforms { + build_platform(&platform); + } +} + +fn build_platform(platform: &str) { println!("Platform: {}", platform); let libraries = lib::libraries(); @@ -81,6 +90,19 @@ EXPORTS cmd.arg(format!("{}.def", library)); cmd.arg("-l"); cmd.arg(format!("lib{}.a", library)); + cmd.arg("-m"); + cmd.arg(match platform { + "i686_gnu" => "i386", + "x86_64_gnu" => "i386:x86-64", + _ => unreachable!(), + }); + // Work around https://sourceware.org/bugzilla/show_bug.cgi?id=29497 + cmd.arg("-f"); + cmd.arg(match platform { + "i686_gnu" => "--32", + "x86_64_gnu" => "--64", + _ => unreachable!(), + }); // Ensure consistency in the prefixes used by dlltool. cmd.arg("-t"); if library.contains('.') {