From de76f2710b350116014883093e04ab3e57f26553 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 17 Aug 2022 10:37:26 +0900 Subject: [PATCH] Don't require two different MinGW environments to build the *_gnu import libraries And at the same time, allow to use MinGW tools on any OS. --- crates/tools/gnu/readme.md | 17 ++-------- crates/tools/gnu/src/main.rs | 65 ++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 36 deletions(-) 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..8b697bca34 100644 --- a/crates/tools/gnu/src/main.rs +++ b/crates/tools/gnu/src/main.rs @@ -1,28 +1,38 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; +use std::process::{Command, Stdio}; 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 Command::new(cmd).stdout(Stdio::null()).stderr(Stdio::null()).spawn().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(); @@ -70,7 +80,7 @@ EXPORTS drop(def); - let mut cmd = std::process::Command::new("dlltool"); + let mut cmd = Command::new("dlltool"); cmd.current_dir(output); if platform.eq("i686_gnu") { @@ -81,6 +91,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('.') { @@ -93,7 +116,7 @@ EXPORTS // Work around lack of determinism in dlltool output, and at the same time remove // unnecessary sections and symbols. std::fs::rename(output.join(format!("lib{}.a", library)), output.join("tmp.a")).unwrap(); - let mut cmd = std::process::Command::new("objcopy"); + let mut cmd = Command::new("objcopy"); cmd.current_dir(output); cmd.arg("--remove-section=.bss"); cmd.arg("--remove-section=.data"); @@ -127,7 +150,7 @@ fn build_mri(output: &std::path::Path, libraries: &BTreeMap