diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff7ff2af71..bced0c464e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -187,7 +187,6 @@ jobs: cargo clippy -p test_window_long && cargo clippy -p test_winrt && cargo clippy -p tool_gnu && - cargo clippy -p tool_gnullvm && cargo clippy -p tool_ilrs && cargo clippy -p tool_lib && cargo clippy -p tool_msvc && diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5cf76096ed..5eca39c87a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -171,7 +171,6 @@ jobs: cargo test --target ${{ matrix.target }} -p test_window_long && cargo test --target ${{ matrix.target }} -p test_winrt && cargo test --target ${{ matrix.target }} -p tool_gnu && - cargo test --target ${{ matrix.target }} -p tool_gnullvm && cargo test --target ${{ matrix.target }} -p tool_ilrs && cargo test --target ${{ matrix.target }} -p tool_lib && cargo test --target ${{ matrix.target }} -p tool_msvc && diff --git a/crates/tools/gnu/readme.md b/crates/tools/gnu/readme.md index d8f9c3a60a..b5091a12b1 100644 --- a/crates/tools/gnu/readme.md +++ b/crates/tools/gnu/readme.md @@ -1,8 +1,9 @@ -The Windows umbrella lib (targeting GNU tooling) is generated using the following steps: +The Windows umbrella lib (targeting GNU and LLVM tooling) is generated using the following steps: 0. Ensure MSYS2 MinGW environment is installed (https://www.mingw-w64.org/downloads/) 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 -- all` +3. Execute: `pacman --needed -S mingw-w64-x86_64-llvm` +4. Repeat step 1 if needed +5. Navigate to crate root +6. 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 911ce86119..5406b33728 100644 --- a/crates/tools/gnu/src/main.rs +++ b/crates/tools/gnu/src/main.rs @@ -2,14 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::io::prelude::*; fn main() { - 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"]; + const ALL_PLATFORMS: [&str; 4] = ["x86_64_gnu", "i686_gnu", "x86_64_gnullvm", "aarch64_gnullvm"]; let mut platforms = BTreeSet::new(); for platform in std::env::args().skip(1) { if ALL_PLATFORMS.contains(&&*platform) { @@ -27,11 +20,19 @@ fn main() { }; for platform in platforms { - build_platform(&platform); + let tools = if platform.ends_with("_gnu") { &["dlltool", "ar", "objcopy"][..] } else { &["llvm-dlltool", "llvm-ar"][..] }; + for tool in tools { + if which::which(tool).is_err() { + eprintln!("Could not find {}. Is it in your $PATH?", tool); + return; + } + } + + build_platform(&platform, tools[0], tools[1]); } } -fn build_platform(platform: &str) { +fn build_platform(platform: &str, dlltool: &str, ar: &str) { println!("Platform: {}", platform); let libraries = lib::libraries(); @@ -40,17 +41,17 @@ fn build_platform(platform: &str) { std::fs::create_dir_all(&output).unwrap(); for (library, functions) in &libraries { - build_library(&output, library, functions, platform); + build_library(&output, dlltool, library, functions, platform); } - build_mri(&output, &libraries); + build_mri(&output, ar, &libraries); for library in libraries.keys() { std::fs::remove_file(output.join(format!("lib{}.a", library))).unwrap(); } } -fn build_library(output: &std::path::Path, library: &str, functions: &BTreeMap, platform: &str) { +fn build_library(output: &std::path::Path, dlltool: &str, library: &str, functions: &BTreeMap, platform: &str) { println!("{}", library); // Note that we don't use set_extension as it confuses PathBuf when the library name includes a period. @@ -79,7 +80,7 @@ EXPORTS drop(def); - let mut cmd = std::process::Command::new("dlltool"); + let mut cmd = std::process::Command::new(dlltool); cmd.current_dir(output); if platform.eq("i686_gnu") { @@ -93,50 +94,55 @@ EXPORTS 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", + "x86_64_gnu" | "x86_64_gnullvm" => "i386:x86-64", + "aarch64_gnullvm" => "arm64", _ => unreachable!(), }); - // Ensure consistency in the prefixes used by dlltool. - cmd.arg("-t"); - if library.contains('.') { - cmd.arg(format!("{}_", library).replace('.', "_").replace('-', "_")); - } else { - cmd.arg(format!("{}_dll_", library).replace('-', "_")); + if dlltool == "dlltool" { + // 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('.') { + cmd.arg(format!("{}_", library).replace('.', "_").replace('-', "_")); + } else { + cmd.arg(format!("{}_dll_", library).replace('-', "_")); + } } cmd.output().unwrap(); - // 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"); - cmd.current_dir(output); - cmd.arg("--remove-section=.bss"); - cmd.arg("--remove-section=.data"); - cmd.arg("--strip-unneeded-symbol=fthunk"); - cmd.arg("--strip-unneeded-symbol=hname"); - cmd.arg("--strip-unneeded-symbol=.file"); - cmd.arg("--strip-unneeded-symbol=.text"); - cmd.arg("--strip-unneeded-symbol=.data"); - cmd.arg("--strip-unneeded-symbol=.bss"); - cmd.arg("--strip-unneeded-symbol=.idata$7"); - cmd.arg("--strip-unneeded-symbol=.idata$5"); - cmd.arg("--strip-unneeded-symbol=.idata$4"); - cmd.arg("tmp.a"); - cmd.arg(format!("lib{}.a", library)); - cmd.output().unwrap(); - - std::fs::remove_file(output.join("tmp.a")).unwrap(); + if dlltool == "dlltool" { + // 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"); + cmd.current_dir(output); + cmd.arg("--remove-section=.bss"); + cmd.arg("--remove-section=.data"); + cmd.arg("--strip-unneeded-symbol=fthunk"); + cmd.arg("--strip-unneeded-symbol=hname"); + cmd.arg("--strip-unneeded-symbol=.file"); + cmd.arg("--strip-unneeded-symbol=.text"); + cmd.arg("--strip-unneeded-symbol=.data"); + cmd.arg("--strip-unneeded-symbol=.bss"); + cmd.arg("--strip-unneeded-symbol=.idata$7"); + cmd.arg("--strip-unneeded-symbol=.idata$5"); + cmd.arg("--strip-unneeded-symbol=.idata$4"); + cmd.arg("tmp.a"); + cmd.arg(format!("lib{}.a", library)); + cmd.output().unwrap(); + + std::fs::remove_file(output.join("tmp.a")).unwrap(); + } std::fs::remove_file(output.join(format!("{}.def", library))).unwrap(); } -fn build_mri(output: &std::path::Path, libraries: &BTreeMap>) { +fn build_mri(output: &std::path::Path, ar: &str, libraries: &BTreeMap>) { let mri_path = output.join("unified.mri"); let mut mri = std::fs::File::create(&mri_path).unwrap(); println!("Generating {}", mri_path.to_string_lossy()); @@ -149,7 +155,7 @@ fn build_mri(output: &std::path::Path, libraries: &BTreeMap>(); - let mut platform_and_target = vec![]; - if target.iter().any(|x| x == "x86_64") || target.iter().any(|x| x == "all") { - platform_and_target.push(("x86_64_gnullvm", "i386:x86-64")); - } - if target.iter().any(|x| x == "aarch64") || target.iter().any(|x| x == "all") { - platform_and_target.push(("aarch64_gnullvm", "arm64")); - } - if platform_and_target.is_empty() { - println!("Please specify at least one architecture or use 'all' argument"); - return; - }; - - let libraries = lib::libraries(); - - for (platform, dlltool_target) in platform_and_target { - let output = std::path::PathBuf::from(format!("crates/targets/{}/lib", platform)); - let _ = std::fs::remove_dir_all(&output); - std::fs::create_dir_all(&output).unwrap(); - - for (library, functions) in &libraries { - build_library(&output, library, functions, dlltool_target); - } - - build_mri(&output, &libraries); - - for library in libraries.keys() { - std::fs::remove_file(output.join(format!("lib{}.a", library))).unwrap(); - } - } -} - -fn build_library(output: &std::path::Path, library: &str, functions: &BTreeMap, dlltool_target: &str) { - println!("{}", library); - - // Note that we don't use set_extension as it confuses PathBuf when the library name includes a period. - let def_path = output.join(format!("{}.def", library)); - let mut def = std::fs::File::create(&def_path).unwrap(); - - def.write_all( - format!( - r#" -LIBRARY {} -EXPORTS -"#, - library - ) - .as_bytes(), - ) - .unwrap(); - - for function in functions.keys() { - def.write_all(format!("{}\n", function).as_bytes()).unwrap(); - } - - drop(def); - - let mut cmd = std::process::Command::new("llvm-dlltool"); - cmd.current_dir(output); - - cmd.arg("-m"); - cmd.arg(dlltool_target); - cmd.arg("-d"); - cmd.arg(format!("{}.def", library)); - cmd.arg("-l"); - cmd.arg(format!("lib{}.a", library)); - cmd.output().unwrap(); - - std::fs::remove_file(output.join(format!("{}.def", library))).unwrap(); -} - -fn build_mri(output: &std::path::Path, libraries: &BTreeMap>) { - let mri_path = output.join("unified.mri"); - let mut mri = std::fs::File::create(&mri_path).unwrap(); - println!("Generating {}", mri_path.to_string_lossy()); - - mri.write_all(b"CREATE libwindows.a\n").unwrap(); - - for library in libraries.keys() { - mri.write_all(format!("ADDLIB lib{}.a\n", library).as_bytes()).unwrap(); - } - - mri.write_all(b"SAVE\nEND\n").unwrap(); - - let mut cmd = std::process::Command::new("llvm-ar"); - cmd.current_dir(output); - cmd.arg("-M"); - cmd.stdin(std::fs::File::open(&mri_path).unwrap()); - cmd.output().unwrap(); - - std::fs::remove_file(&mri_path).unwrap(); -}