Fix Windows GNU staticlib output naming (#4231)
## Summary
Make Rust static-library naming ABI-aware on Windows.
Rust emits `lib<crate>.a` for the GNU and GNULLVM Windows ABIs, while
MSVC emits `<crate>.lib`. The generated Rust toolchain currently selects
`.lib` from the operating system alone, and `determine_lib_name` removes
the `lib` prefix for every Windows static library. As a result, Bazel
declares an output different from the file emitted by rustc for Windows
GNU-like targets.
This change passes the target ABI through repository and toolchain
generation, selects `.a` for Windows GNU/GNULLVM static libraries, and
preserves their `lib` prefix. MSVC behavior and Windows dynamic-library
naming remain unchanged.
Regression coverage exercises the extension mapping, rendered toolchain
metadata, final GNU/GNULLVM/MSVC static-library names, and the unchanged
GNU `cdylib` name.
diff --git a/rust/platform/triple_mappings.bzl b/rust/platform/triple_mappings.bzl
index 7be462f..d6657c0 100644
--- a/rust/platform/triple_mappings.bzl
+++ b/rust/platform/triple_mappings.bzl
@@ -435,7 +435,9 @@
def system_to_dylib_ext(system):
return _SYSTEM_TO_DYLIB_EXT[system]
-def system_to_staticlib_ext(system):
+def system_to_staticlib_ext(system, abi = None):
+ if system == "windows" and abi in ("gnu", "gnullvm"):
+ return ".a"
return _SYSTEM_TO_STATICLIB_EXT[system]
def system_to_binary_ext(system):
diff --git a/rust/private/repository_utils.bzl b/rust/private/repository_utils.bzl
index e28165c..f8001cb 100644
--- a/rust/private/repository_utils.bzl
+++ b/rust/private/repository_utils.bzl
@@ -114,7 +114,7 @@
"""
content = [_build_file_for_compiler_template.format(
binary_ext = system_to_binary_ext(target_triple.system),
- staticlib_ext = system_to_staticlib_ext(target_triple.system),
+ staticlib_ext = system_to_staticlib_ext(target_triple.system, target_triple.abi),
dylib_ext = system_to_dylib_ext(target_triple.system),
target_triple = target_triple.str,
)]
@@ -123,7 +123,7 @@
content.append(
_build_file_for_linker_template.format(
binary_ext = system_to_binary_ext(target_triple.system),
- staticlib_ext = system_to_staticlib_ext(target_triple.system),
+ staticlib_ext = system_to_staticlib_ext(target_triple.system, target_triple.abi),
dylib_ext = system_to_dylib_ext(target_triple.system),
target_triple = target_triple.str,
),
@@ -330,7 +330,7 @@
"""
return _build_file_for_stdlib_template.format(
binary_ext = system_to_binary_ext(target_triple.system),
- staticlib_ext = system_to_staticlib_ext(target_triple.system),
+ staticlib_ext = system_to_staticlib_ext(target_triple.system, target_triple.abi),
dylib_ext = system_to_dylib_ext(target_triple.system),
target_triple = target_triple.str,
)
@@ -462,7 +462,7 @@
return _build_file_for_rust_toolchain_template.format(
toolchain_name = name,
binary_ext = system_to_binary_ext(target_triple.system),
- staticlib_ext = system_to_staticlib_ext(target_triple.system),
+ staticlib_ext = system_to_staticlib_ext(target_triple.system, target_triple.abi),
dylib_ext = system_to_dylib_ext(target_triple.system),
allocator_library = repr(allocator_library_label),
global_allocator_library = repr(global_allocator_library_label),
diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl
index e54e513..476651a 100644
--- a/rust/private/utils.bzl
+++ b/rust/private/utils.bzl
@@ -863,7 +863,11 @@
"please file an issue!").format(crate_type))
prefix = "lib"
- if toolchain.target_triple and toolchain.target_os == "windows" and crate_type not in ("lib", "rlib"):
+ if (toolchain.target_triple and
+ toolchain.target_os == "windows" and
+ crate_type not in ("lib", "rlib") and
+ (crate_type != "staticlib" or
+ toolchain.target_abi not in ("gnu", "gnullvm"))):
prefix = ""
if toolchain.target_arch in ("wasm32", "wasm64") and crate_type == "cdylib":
prefix = ""
diff --git a/test/unit/platform_triple/platform_triple_test.bzl b/test/unit/platform_triple/platform_triple_test.bzl
index 0248782..ff69c4c 100644
--- a/test/unit/platform_triple/platform_triple_test.bzl
+++ b/test/unit/platform_triple/platform_triple_test.bzl
@@ -169,11 +169,22 @@
return unittest.end(env)
+def _windows_staticlib_ext_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ asserts.equals(env, ".a", system_to_staticlib_ext("windows", "gnu"))
+ asserts.equals(env, ".a", system_to_staticlib_ext("windows", "gnullvm"))
+ asserts.equals(env, ".lib", system_to_staticlib_ext("windows", "msvc"))
+ asserts.equals(env, ".lib", system_to_staticlib_ext("windows"))
+
+ return unittest.end(env)
+
construct_platform_triple_test = unittest.make(_construct_platform_triple_test_impl)
construct_minimal_platform_triple_test = unittest.make(_construct_minimal_platform_triple_test_impl)
supported_platform_triples_test = unittest.make(_supported_platform_triples_test_impl)
construct_known_triples_test = unittest.make(_construct_known_triples_test_impl)
wasm_staticlib_ext_test = unittest.make(_wasm_staticlib_ext_test_impl)
+windows_staticlib_ext_test = unittest.make(_windows_staticlib_ext_test_impl)
def platform_triple_test_suite(name, **kwargs):
"""Define a test suite for testing the `triple` constructor
@@ -197,6 +208,9 @@
wasm_staticlib_ext_test(
name = "wasm_staticlib_ext_test",
)
+ windows_staticlib_ext_test(
+ name = "windows_staticlib_ext_test",
+ )
native.test_suite(
name = name,
@@ -206,6 +220,7 @@
":supported_platform_triples_test",
":construct_known_triples_test",
":wasm_staticlib_ext_test",
+ ":windows_staticlib_ext_test",
],
**kwargs
)
diff --git a/test/unit/windows_lib_name/windows_lib_name_test.bzl b/test/unit/windows_lib_name/windows_lib_name_test.bzl
index 83d2726..a854247 100644
--- a/test/unit/windows_lib_name/windows_lib_name_test.bzl
+++ b/test/unit/windows_lib_name/windows_lib_name_test.bzl
@@ -1,12 +1,12 @@
"""Analysistests for Windows-specific library naming and link flags."""
-load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts", "unittest")
# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "portable_link_flags", "symlink_for_ambiguous_lib")
# buildifier: disable=bzl-visibility
-load("//rust/private:utils.bzl", "get_lib_name_default", "get_lib_name_for_windows")
+load("//rust/private:utils.bzl", "determine_lib_name", "get_lib_name_default", "get_lib_name_for_windows")
# buildifier: disable=provider-params
LinkFlagsInfo = provider(fields = {"flags": "List[str]"})
@@ -125,6 +125,72 @@
symlink_name_windows_msvc_test = analysistest.make(_symlink_name_windows_msvc_test_impl)
+def _windows_toolchain(abi, staticlib_ext):
+ return struct(
+ dylib_ext = ".dll",
+ staticlib_ext = staticlib_ext,
+ target_abi = abi,
+ target_arch = "x86_64",
+ target_os = "windows",
+ target_triple = "x86_64-pc-windows-{}".format(abi),
+ )
+
+def _staticlib_name_windows_gnu_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ actual = determine_lib_name(
+ name = "native_dep",
+ crate_type = "staticlib",
+ toolchain = _windows_toolchain("gnu", ".a"),
+ )
+
+ asserts.equals(env, "libnative_dep.a", actual)
+ return unittest.end(env)
+
+staticlib_name_windows_gnu_test = unittest.make(_staticlib_name_windows_gnu_test_impl)
+
+def _staticlib_name_windows_gnullvm_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ actual = determine_lib_name(
+ name = "native_dep",
+ crate_type = "staticlib",
+ toolchain = _windows_toolchain("gnullvm", ".a"),
+ )
+
+ asserts.equals(env, "libnative_dep.a", actual)
+ return unittest.end(env)
+
+staticlib_name_windows_gnullvm_test = unittest.make(_staticlib_name_windows_gnullvm_test_impl)
+
+def _staticlib_name_windows_msvc_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ actual = determine_lib_name(
+ name = "native_dep",
+ crate_type = "staticlib",
+ toolchain = _windows_toolchain("msvc", ".lib"),
+ )
+
+ asserts.equals(env, "native_dep.lib", actual)
+ return unittest.end(env)
+
+staticlib_name_windows_msvc_test = unittest.make(_staticlib_name_windows_msvc_test_impl)
+
+def _cdylib_name_windows_gnu_test_impl(ctx):
+ env = unittest.begin(ctx)
+
+ actual = determine_lib_name(
+ name = "native_dep",
+ crate_type = "cdylib",
+ toolchain = _windows_toolchain("gnu", ".a"),
+ )
+
+ asserts.equals(env, "native_dep.dll", actual)
+ return unittest.end(env)
+
+cdylib_name_windows_gnu_test = unittest.make(_cdylib_name_windows_gnu_test_impl)
+
def _define_targets():
portable_link_flags_probe(
name = "portable_link_flags_windows_gnu_probe",
@@ -172,6 +238,18 @@
name = "symlink_name_windows_msvc_test",
target_under_test = ":symlink_windows_msvc_probe",
)
+ staticlib_name_windows_gnu_test(
+ name = "staticlib_name_windows_gnu_test",
+ )
+ staticlib_name_windows_gnullvm_test(
+ name = "staticlib_name_windows_gnullvm_test",
+ )
+ staticlib_name_windows_msvc_test(
+ name = "staticlib_name_windows_msvc_test",
+ )
+ cdylib_name_windows_gnu_test(
+ name = "cdylib_name_windows_gnu_test",
+ )
native.test_suite(
name = name,
@@ -180,5 +258,9 @@
":portable_link_flags_windows_msvc_test",
":symlink_name_windows_gnu_test",
":symlink_name_windows_msvc_test",
+ ":staticlib_name_windows_gnu_test",
+ ":staticlib_name_windows_gnullvm_test",
+ ":staticlib_name_windows_msvc_test",
+ ":cdylib_name_windows_gnu_test",
],
)
diff --git a/test/unit/windows_stdlib/windows_stdlib_test.bzl b/test/unit/windows_stdlib/windows_stdlib_test.bzl
index d8c9978..67125e2 100644
--- a/test/unit/windows_stdlib/windows_stdlib_test.bzl
+++ b/test/unit/windows_stdlib/windows_stdlib_test.bzl
@@ -63,9 +63,19 @@
)
asserts.true(
env,
+ 'staticlib_ext = ".lib",' in rendered_msvc,
+ "MSVC toolchain should render a .lib staticlib extension:\n%s" % rendered_msvc,
+ )
+ asserts.true(
+ env,
'stdlib_linkflags = ["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"],' in rendered_gnu,
"GNU toolchain should render -l stdlib linkflags:\n%s" % rendered_gnu,
)
+ asserts.true(
+ env,
+ 'staticlib_ext = ".a",' in rendered_gnu,
+ "GNU toolchain should render a .a staticlib extension:\n%s" % rendered_gnu,
+ )
return analysistest.end(env)