diff --git a/src/splat.rs b/src/splat.rs index 4832013..5ceec9c 100644 --- a/src/splat.rs +++ b/src/splat.rs @@ -1,5 +1,6 @@ use crate::{Arch, Ctx, Error, Path, PathBuf, PayloadKind, Variant}; use anyhow::Context as _; +use camino::Utf8Path; use rayon::prelude::*; use std::collections::BTreeMap; @@ -79,6 +80,17 @@ pub(crate) fn prep_splat( }) } +/// Get the Windows SDK version from the .msi filename. +fn find_sdk_version(sdk_filename: &Utf8Path) -> String { + sdk_filename + .as_str() + .chars() + .skip_while(|ch| ch != &'_') + .skip(1) + .take_while(|ch| ch != &'_') + .collect() +} + pub(crate) fn splat( config: &SplatConfig, roots: &SplatRoots, @@ -492,6 +504,49 @@ pub(crate) fn splat( }) .collect_into_vec(&mut results); + match item.payload.kind { + PayloadKind::SdkLibs => { + // Symlink sdk/lib/{sdkversion} -> sdk/lib, regardless of filesystem case sensitivity. + let sdk_version = find_sdk_version(&item.payload.filename); + let mut versioned_linkname = roots.sdk.clone(); + versioned_linkname.push("lib"); + versioned_linkname.push(sdk_version); + symlink(".", &versioned_linkname)?; + + // https://github.com/llvm/llvm-project/blob/release/14.x/clang/lib/Driver/ToolChains/MSVC.cpp#L1102 + if config.enable_symlinks { + let mut title_case = roots.sdk.clone(); + title_case.push("Lib"); + if !title_case.exists() { + symlink("lib", &title_case)?; + } + } + } + PayloadKind::SdkHeaders => { + // Symlink sdk/include/{sdkversion} -> sdk/include, regardless of filesystem case sensitivity. + let sdk_version = find_sdk_version(&item.payload.filename); + let mut versioned_linkname = roots.sdk.clone(); + versioned_linkname.push("include"); + versioned_linkname.push(sdk_version); + + // Desktop and Store variants both have an include dir, + // but we only need to create this symlink once. + if !versioned_linkname.exists() { + symlink(".", &versioned_linkname)?; + } + + // https://github.com/llvm/llvm-project/blob/release/14.x/clang/lib/Driver/ToolChains/MSVC.cpp#L1340-L1346 + if config.enable_symlinks { + let mut title_case = roots.sdk.clone(); + title_case.push("Include"); + if !title_case.exists() { + symlink("include", &title_case)?; + } + } + } + _ => (), + }; + item.progress.finish_with_message("📦 splatted"); let headers = results.into_iter().collect::, _>>()?; diff --git a/tests/compiles.rs b/tests/compiles.rs index 3f02f6f..edf732b 100644 --- a/tests/compiles.rs +++ b/tests/compiles.rs @@ -52,6 +52,10 @@ fn verify_compiles() { ) .unwrap(); + if xwin::Path::new("tests/xwin-test/target").exists() { + std::fs::remove_dir_all("tests/xwin-test/target").expect("failed to remove target dir"); + } + let mut cmd = std::process::Command::new("cargo"); cmd.args(&[ "build", @@ -76,4 +80,41 @@ fn verify_compiles() { cmd.envs(cc_env); assert!(cmd.status().unwrap().success()); + + // Ignore the /vctoolsdir /winsdkdir test below on CI since it fails, I'm assuming + // due to the clang version in GHA being outdated, but don't have the will to + // look into it now + if std::env::var("CI").is_ok() { + return; + } + + std::fs::remove_dir_all("tests/xwin-test/target").expect("failed to remove target dir"); + + let mut cmd = std::process::Command::new("cargo"); + cmd.args(&[ + "build", + "--target", + "x86_64-pc-windows-msvc", + "--manifest-path", + "tests/xwin-test/Cargo.toml", + ]); + + let includes = format!( + "-Wno-unused-command-line-argument -fuse-ld=lld-link /vctoolsdir {0}/crt /winsdkdir {0}/sdk", + output_dir + ); + let libs = format!("-C linker=lld-link -Lnative={0}/crt/lib/x86_64 -Lnative={0}/sdk/lib/um/x86_64 -Lnative={0}/sdk/lib/ucrt/x86_64", output_dir); + + let cc_env = [ + ("CC_x86_64_pc_windows_msvc", "clang-cl"), + ("CXX_x86_64_pc_windows_msvc", "clang-cl"), + ("AR_x86_64_pc_windows_msvc", "llvm-lib"), + ("CFLAGS_x86_64_pc_windows_msvc", &includes), + ("CXXFLAGS_x86_64_pc_windows_msvc", &includes), + ("RUSTFLAGS", &libs), + ]; + + cmd.envs(cc_env); + + assert!(cmd.status().unwrap().success()); } diff --git a/tests/expected.txt b/tests/expected.txt index 6382a45..0a1e33a 100644 --- a/tests/expected.txt +++ b/tests/expected.txt @@ -422,6 +422,9 @@ crt/lib/x86_64/vccorlib.lib @ 88dff09680406ce8 crt/lib/x86_64/vcomp.lib @ 290001f1cf8658dc crt/lib/x86_64/vcruntime.lib @ 13fe902a335d605f crt/lib/x86_64/wsetargv.obj @ 887c6f64baebe131 +sdk/Include => include +sdk/Lib => lib +sdk/include/10.0.20348 => . sdk/include/cppwinrt/LICENSE.txt @ d824dd57cab041e7 sdk/include/cppwinrt/license.txt => LICENSE.txt sdk/include/cppwinrt/winrt/Windows.AI.MachineLearning.h => windows.ai.machinelearning.h @@ -7249,6 +7252,7 @@ sdk/include/winrt/wrl/module.h @ d0a209cfdd29d5c9 sdk/include/winrt/wrl/wrappers/corewrappers.h @ aa2b216bc669030e sdk/include/winrt/wrl.h @ 7f6c2dca3e863bbc sdk/include/winrt/wsdevlicensing.h => Wsdevlicensing.h +sdk/lib/10.0.20348 => . sdk/lib/ucrt/x86_64/libucrt.lib @ bd614cab0015a4e sdk/lib/ucrt/x86_64/ucrt.lib @ 8140b809879bb580 sdk/lib/um/x86_64/ACLUI.lib => AclUI.Lib