diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e749aeba85..aafce1f410 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -126,10 +126,12 @@ jobs: cargo clippy -p sample_spellchecker && cargo clippy -p sample_uiautomation && cargo clippy -p sample_xml && + cargo clippy -p windows_aarch64_gnullvm && cargo clippy -p windows_aarch64_msvc && cargo clippy -p windows_i686_gnu && cargo clippy -p windows_i686_msvc && cargo clippy -p windows_x86_64_gnu && + cargo clippy -p windows_x86_64_gnullvm && cargo clippy -p windows_x86_64_msvc && cargo clippy -p test_agile && cargo clippy -p test_agile_reference && @@ -184,6 +186,7 @@ jobs: cargo clippy -p test_winrt && cargo clippy -p tool_bindings && 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/cross-compile.yml b/.github/workflows/cross-compile.yml index 844a284f59..16a05211bf 100644 --- a/.github/workflows/cross-compile.yml +++ b/.github/workflows/cross-compile.yml @@ -8,6 +8,7 @@ on: env: RUSTFLAGS: -Dwarnings + LLVM-MINGW-TOOLCHAIN-NAME: llvm-mingw-20220323-ucrt-ubuntu-18.04-x86_64 jobs: test: @@ -27,7 +28,7 @@ jobs: # image: [macos-latest, ubuntu-latest] version: [stable, nightly] - target: [x86_64-pc-windows-gnu] + target: [x86_64-pc-windows-gnu, aarch64-pc-windows-gnullvm, x86_64-pc-windows-gnullvm] runs-on: ${{ matrix.image }} steps: @@ -36,6 +37,13 @@ jobs: - name: Add toolchain target run: rustup target add ${{ matrix.target }} + if: contains(matrix.target, 'gnullvm') == false + + - name: Add nightly toolchain with rust-src + run: | + rustup default ${{ matrix.version }} + rustup component add rust-src + if: startsWith(matrix.image, 'ubuntu-') && contains(matrix.target, 'gnullvm') && matrix.version == 'nightly' - name: Install gcc-mingw-w64-x86-64 run: sudo apt-get install -y gcc-mingw-w64-x86-64 @@ -45,6 +53,26 @@ jobs: run: brew install mingw-w64 if: startsWith(matrix.image, 'macos-') && matrix.target == 'x86_64-pc-windows-gnu' + - name: LLVM MinGW toolchain cache configuration + id: cache-llvm-mingw-toolchain + uses: actions/cache@v3 + if: startsWith(matrix.image, 'ubuntu-') && contains(matrix.target, 'gnullvm') && matrix.version == 'nightly' + with: + path: ${{ env.LLVM-MINGW-TOOLCHAIN-NAME }} + key: ${{ env.LLVM-MINGW-TOOLCHAIN-NAME }} + + - name: Install LLVM MinGW toolchain + if: startsWith(matrix.image, 'ubuntu-') && contains(matrix.target, 'gnullvm') && matrix.version == 'nightly' && steps.cache-llvm-mingw-toolchain.outputs.cache-hit != 'true' + run: | + curl -L -o ${{ env.LLVM-MINGW-TOOLCHAIN-NAME }}.tar.xz https://github.com/mstorsjo/llvm-mingw/releases/download/20220323/${{ env.LLVM-MINGW-TOOLCHAIN-NAME }}.tar.xz + tar -xf ${{ env.LLVM-MINGW-TOOLCHAIN-NAME }}.tar.xz + echo "${{ env.LLVM-MINGW-TOOLCHAIN-NAME }}/bin" >> $GITHUB_PATH + + - name: Add LLVM MinGW toolchain to PATH + if: startsWith(matrix.image, 'ubuntu-') && contains(matrix.target, 'gnullvm') && matrix.version == 'nightly' + run: | + echo "${{ env.LLVM-MINGW-TOOLCHAIN-NAME }}/bin" >> $GITHUB_PATH + - name: Test shell: pwsh run: | @@ -52,3 +80,13 @@ jobs: if (-Not (Resolve-Path "target/*/debug/deps/test_win32-*.exe" | Test-Path)) { throw "Failed to find test_win32 executable." } + if: contains(matrix.target, 'gnullvm') == false + + - name: Test with build-std + shell: pwsh + run: | + cargo test --no-run --target ${{ matrix.target }} -Z build-std -p test_win32 + if (-Not (Resolve-Path "target/*/debug/deps/test_win32-*.exe" | Test-Path)) { + throw "Failed to find test_win32 executable." + } + if: startsWith(matrix.image, 'ubuntu-') && contains(matrix.target, 'gnullvm') && matrix.version == 'nightly' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d65c4a4c9a..93f86e7ccf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -109,10 +109,12 @@ jobs: cargo test --target ${{ matrix.target }} -p sample_spellchecker && cargo test --target ${{ matrix.target }} -p sample_uiautomation && cargo test --target ${{ matrix.target }} -p sample_xml && + cargo test --target ${{ matrix.target }} -p windows_aarch64_gnullvm && cargo test --target ${{ matrix.target }} -p windows_aarch64_msvc && cargo test --target ${{ matrix.target }} -p windows_i686_gnu && cargo test --target ${{ matrix.target }} -p windows_i686_msvc && cargo test --target ${{ matrix.target }} -p windows_x86_64_gnu && + cargo test --target ${{ matrix.target }} -p windows_x86_64_gnullvm && cargo test --target ${{ matrix.target }} -p windows_x86_64_msvc && cargo test --target ${{ matrix.target }} -p test_agile && cargo test --target ${{ matrix.target }} -p test_agile_reference && @@ -168,6 +170,7 @@ jobs: cargo test --target ${{ matrix.target }} -p test_winrt && cargo test --target ${{ matrix.target }} -p tool_bindings && 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/libs/sys/Cargo.toml b/crates/libs/sys/Cargo.toml index 7db1b7f981..7121d0968f 100644 --- a/crates/libs/sys/Cargo.toml +++ b/crates/libs/sys/Cargo.toml @@ -33,6 +33,9 @@ windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" [target.aarch64-uwp-windows-msvc.dependencies] windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" } +[target.aarch64-pc-windows-gnullvm.dependencies] +windows_aarch64_gnullvm = { path = "../../targets/aarch64_gnullvm", version = "0.39.0" } + [target.i686-pc-windows-gnu.dependencies] windows_i686_gnu = { path = "../../targets/i686_gnu", version = "0.39.0" } @@ -45,6 +48,9 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } [target.x86_64-uwp-windows-gnu.dependencies] windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } +[target.x86_64-pc-windows-gnullvm.dependencies] +windows_x86_64_gnullvm = { path = "../../targets/x86_64_gnullvm", version = "0.39.0" } + [features] default = [] deprecated = [] diff --git a/crates/libs/windows/Cargo.toml b/crates/libs/windows/Cargo.toml index bc389f0402..cb4f17726e 100644 --- a/crates/libs/windows/Cargo.toml +++ b/crates/libs/windows/Cargo.toml @@ -33,6 +33,9 @@ windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" [target.aarch64-uwp-windows-msvc.dependencies] windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" } +[target.aarch64-pc-windows-gnullvm.dependencies] +windows_aarch64_gnullvm = { path = "../../targets/aarch64_gnullvm", version = "0.39.0" } + [target.i686-pc-windows-gnu.dependencies] windows_i686_gnu = { path = "../../targets/i686_gnu", version = "0.39.0" } @@ -45,6 +48,9 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } [target.x86_64-uwp-windows-gnu.dependencies] windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } +[target.x86_64-pc-windows-gnullvm.dependencies] +windows_x86_64_gnullvm = { path = "../../targets/x86_64_gnullvm", version = "0.39.0" } + [dependencies] windows-implement = { path = "../implement", version = "0.39.0", optional = true } windows-interface = { path = "../interface", version = "0.39.0", optional = true } diff --git a/crates/targets/aarch64_gnullvm/Cargo.toml b/crates/targets/aarch64_gnullvm/Cargo.toml new file mode 100644 index 0000000000..ec8ebcb433 --- /dev/null +++ b/crates/targets/aarch64_gnullvm/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "windows_aarch64_gnullvm" +version = "0.39.0" +authors = ["Microsoft"] +edition = "2018" +license = "MIT OR Apache-2.0" +description = "Code gen support for the windows crate" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff --git a/crates/targets/aarch64_gnullvm/build.rs b/crates/targets/aarch64_gnullvm/build.rs new file mode 100644 index 0000000000..8c8f98f5ec --- /dev/null +++ b/crates/targets/aarch64_gnullvm/build.rs @@ -0,0 +1,10 @@ +fn main() { + let target = std::env::var("TARGET").unwrap(); + if target != "aarch64-pc-windows-gnullvm" { + return; + } + + let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + + println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); +} diff --git a/crates/targets/aarch64_gnullvm/lib/libwindows.a b/crates/targets/aarch64_gnullvm/lib/libwindows.a new file mode 100644 index 0000000000..6e771720a1 Binary files /dev/null and b/crates/targets/aarch64_gnullvm/lib/libwindows.a differ diff --git a/crates/targets/aarch64_gnullvm/src/lib.rs b/crates/targets/aarch64_gnullvm/src/lib.rs new file mode 100644 index 0000000000..0c9ac1ac8e --- /dev/null +++ b/crates/targets/aarch64_gnullvm/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/crates/targets/x86_64_gnullvm/Cargo.toml b/crates/targets/x86_64_gnullvm/Cargo.toml new file mode 100644 index 0000000000..a024fba981 --- /dev/null +++ b/crates/targets/x86_64_gnullvm/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "windows_x86_64_gnullvm" +version = "0.39.0" +authors = ["Microsoft"] +edition = "2018" +license = "MIT OR Apache-2.0" +description = "Code gen support for the windows crate" +repository = "https://github.com/microsoft/windows-rs" + +[package.metadata.docs.rs] +default-target = "x86_64-pc-windows-msvc" +targets = [] diff --git a/crates/targets/x86_64_gnullvm/build.rs b/crates/targets/x86_64_gnullvm/build.rs new file mode 100644 index 0000000000..ea83354fad --- /dev/null +++ b/crates/targets/x86_64_gnullvm/build.rs @@ -0,0 +1,10 @@ +fn main() { + let target = std::env::var("TARGET").unwrap(); + if target != "x86_64-pc-windows-gnullvm" { + return; + } + + let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + + println!("cargo:rustc-link-search=native={}", std::path::Path::new(&dir).join("lib").display()); +} diff --git a/crates/targets/x86_64_gnullvm/lib/libwindows.a b/crates/targets/x86_64_gnullvm/lib/libwindows.a new file mode 100644 index 0000000000..57b3dd97a8 Binary files /dev/null and b/crates/targets/x86_64_gnullvm/lib/libwindows.a differ diff --git a/crates/targets/x86_64_gnullvm/src/lib.rs b/crates/targets/x86_64_gnullvm/src/lib.rs new file mode 100644 index 0000000000..0c9ac1ac8e --- /dev/null +++ b/crates/targets/x86_64_gnullvm/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/crates/tools/gnullvm/Cargo.toml b/crates/tools/gnullvm/Cargo.toml new file mode 100644 index 0000000000..76732c0f2c --- /dev/null +++ b/crates/tools/gnullvm/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tool_gnullvm" +version = "0.0.0" +edition = "2018" +publish = false + +[dependencies] +lib = { package = "tool_lib", path = "../lib" } diff --git a/crates/tools/gnullvm/readme.md b/crates/tools/gnullvm/readme.md new file mode 100644 index 0000000000..48752c888f --- /dev/null +++ b/crates/tools/gnullvm/readme.md @@ -0,0 +1,8 @@ +The Windows umbrella lib (targeting mingw-w64 LLVM tooling) is generated using the following steps: + +0. Ensure MSYS2 MinGW environment is installed (https://www.mingw-w64.org/downloads/) +1. Execute: `C:\msys64\clang64.exe` +2. Execute: `pacman -Syuu --noconfirm` (repeat until no further updates available) +3. Execute `pacman --needed -S mingw-w64-clang-x86_64-toolchain` +4. Navigate to crate root +5. Execute: `PATH=$(cygpath -u $USERPROFILE)/.cargo/bin:$PATH cargo +nightly run -p tool_gnullvm --target x86_64-pc-windows-gnullvm -Z build-std -- all` diff --git a/crates/tools/gnullvm/src/main.rs b/crates/tools/gnullvm/src/main.rs new file mode 100644 index 0000000000..69acd3df42 --- /dev/null +++ b/crates/tools/gnullvm/src/main.rs @@ -0,0 +1,106 @@ +use std::collections::BTreeMap; +use std::io::prelude::*; + +fn main() { + let mut cmd = std::process::Command::new("where"); + cmd.arg("llvm-dlltool.exe"); + + let output = cmd.output().unwrap(); + + if !output.status.success() { + println!("llvm-dlltool.exe not found"); + return; + } + + let target = std::env::args().collect::>(); + 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(); +} diff --git a/crates/tools/sys/src/main.rs b/crates/tools/sys/src/main.rs index 1d7778ad58..2a66465c93 100644 --- a/crates/tools/sys/src/main.rs +++ b/crates/tools/sys/src/main.rs @@ -73,6 +73,9 @@ windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" [target.aarch64-uwp-windows-msvc.dependencies] windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" } +[target.aarch64-pc-windows-gnullvm.dependencies] +windows_aarch64_gnullvm = { path = "../../targets/aarch64_gnullvm", version = "0.39.0" } + [target.i686-pc-windows-gnu.dependencies] windows_i686_gnu = { path = "../../targets/i686_gnu", version = "0.39.0" } @@ -85,6 +88,9 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } [target.x86_64-uwp-windows-gnu.dependencies] windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } +[target.x86_64-pc-windows-gnullvm.dependencies] +windows_x86_64_gnullvm = { path = "../../targets/x86_64_gnullvm", version = "0.39.0" } + [features] default = [] deprecated = [] diff --git a/crates/tools/windows/src/main.rs b/crates/tools/windows/src/main.rs index ab23bb4171..5f2c08c640 100644 --- a/crates/tools/windows/src/main.rs +++ b/crates/tools/windows/src/main.rs @@ -71,6 +71,9 @@ windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" [target.aarch64-uwp-windows-msvc.dependencies] windows_aarch64_msvc = { path = "../../targets/aarch64_msvc", version = "0.39.0" } +[target.aarch64-pc-windows-gnullvm.dependencies] +windows_aarch64_gnullvm = { path = "../../targets/aarch64_gnullvm", version = "0.39.0" } + [target.i686-pc-windows-gnu.dependencies] windows_i686_gnu = { path = "../../targets/i686_gnu", version = "0.39.0" } @@ -83,6 +86,9 @@ windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } [target.x86_64-uwp-windows-gnu.dependencies] windows_x86_64_gnu = { path = "../../targets/x86_64_gnu", version = "0.39.0" } +[target.x86_64-pc-windows-gnullvm.dependencies] +windows_x86_64_gnullvm = { path = "../../targets/x86_64_gnullvm", version = "0.39.0" } + [dependencies] windows-implement = { path = "../implement", version = "0.39.0", optional = true } windows-interface = { path = "../interface", version = "0.39.0", optional = true } diff --git a/docs/publish.cmd b/docs/publish.cmd index ac8f65acaf..82e5cea883 100644 --- a/docs/publish.cmd +++ b/docs/publish.cmd @@ -1,7 +1,9 @@ +cargo publish -p windows_aarch64_gnullvm cargo publish -p windows_aarch64_msvc cargo publish -p windows_i686_gnu cargo publish -p windows_i686_msvc cargo publish -p windows_x86_64_gnu +cargo publish -p windows_x86_64_gnullvm cargo publish -p windows_x86_64_msvc cargo publish -p windows-tokens cargo publish -p windows-metadata