Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,22 @@ def _args_map_bin_dir(file):
"""
return "/".join(file.path.split("/", 3)[:3])

def dlltool_path_from_linker_path(linker_path):
"""Derives the path to `dlltool`, which MinGW ships next to the linker.

Args:
linker_path (str): Path to the cc_toolchain's linker executable.

Returns:
str: The derived path, or None if `linker_path` has no directory component.
"""
sep = max(linker_path.rfind("/"), linker_path.rfind("\\"))
if sep < 0:
return None

suffix = linker_path[-4:].lower()
return "{}dlltool{}".format(linker_path[:sep + 1], suffix if suffix == ".exe" else "")

def construct_arguments(
*,
ctx,
Expand Down Expand Up @@ -1291,6 +1307,17 @@ def construct_arguments(
# If linker_type is not explicitly set, infer from which linker is actually being used
ld_is_direct_driver = False

# gcc runs dlltool internally when acting as the linker, but rustc drives the linker directly so
# it needs dlltool's path: apply outside the link-emit gate below since rlib compiles need it too.
if cc_toolchain and toolchain.target_os == "windows" and toolchain.target_abi != "msvc":
linker_path = cc_common.get_tool_for_action(
feature_configuration = feature_configuration,
action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
)
dlltool_path = dlltool_path_from_linker_path(linker_path)
if dlltool_path:
rustc_flags.add(dlltool_path, format = "--codegen=dlltool=%s")

# Link!
if ("link" in emit and crate_info.type not in ["rlib", "lib"]) or add_flags_for_binary:
# Rust's built-in linker can handle linking wasm files. We don't want to attempt to use the cc
Expand Down
34 changes: 31 additions & 3 deletions test/unit/windows_lib_name/windows_lib_name_test.bzl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Analysistests for Windows-specific library naming and link flags."""
"""Tests for Windows-specific library naming, link flags, and dlltool derivation."""

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")
load("//rust/private:rustc.bzl", "dlltool_path_from_linker_path", "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")
Expand Down Expand Up @@ -125,6 +125,30 @@ def _symlink_name_windows_msvc_test_impl(ctx):

symlink_name_windows_msvc_test = analysistest.make(_symlink_name_windows_msvc_test_impl)

def _dlltool_path_from_linker_path_test_impl(ctx):
env = unittest.begin(ctx)

# Cross-compiling from a Unix host (e.g. llvm-mingw or a Debian mingw-w64 package):
asserts.equals(
env,
"/usr/x86_64-w64-mingw32/bin/dlltool",
dlltool_path_from_linker_path("/usr/x86_64-w64-mingw32/bin/x86_64-w64-mingw32-gcc"),
)

# Windows-style linker path (native MinGW toolchain):
asserts.equals(
env,
"C:\\mingw64\\bin\\dlltool.exe",
dlltool_path_from_linker_path("C:\\mingw64\\bin\\GCC.EXE"),
)

# No directory component: nothing to derive from:
asserts.equals(env, None, dlltool_path_from_linker_path("gcc"))

return unittest.end(env)

dlltool_path_from_linker_path_test = unittest.make(_dlltool_path_from_linker_path_test_impl)

def _define_targets():
portable_link_flags_probe(
name = "portable_link_flags_windows_gnu_probe",
Expand Down Expand Up @@ -172,6 +196,9 @@ def windows_lib_name_test_suite(name):
name = "symlink_name_windows_msvc_test",
target_under_test = ":symlink_windows_msvc_probe",
)
dlltool_path_from_linker_path_test(
name = "dlltool_path_from_linker_path_test",
)

native.test_suite(
name = name,
Expand All @@ -180,5 +207,6 @@ def windows_lib_name_test_suite(name):
":portable_link_flags_windows_msvc_test",
":symlink_name_windows_gnu_test",
":symlink_name_windows_msvc_test",
":dlltool_path_from_linker_path_test",
],
)
Loading