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
14 changes: 11 additions & 3 deletions rust/platform/triple_mappings.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,12 @@ _SYSTEM_TO_STDLIB_LINKFLAGS = {
"wasi": [],
"wasip1": [],
"wasip2": [],
"windows": ["advapi32.lib", "ws2_32.lib", "userenv.lib", "Bcrypt.lib"],
"windows": {
# see https://github.com/rust-lang/rust/blob/c4aa646f15e40bd3e64ddb5017b7b89b3646ac99/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs#L14-L23
"gnu": ["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"],
"gnullvm": ["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"],
"msvc": ["advapi32.lib", "ws2_32.lib", "userenv.lib", "Bcrypt.lib"],
},
}

def cpu_arch_to_constraints(cpu_arch, *, system = None):
Expand Down Expand Up @@ -404,8 +409,11 @@ def system_to_staticlib_ext(system):
def system_to_binary_ext(system):
return _SYSTEM_TO_BINARY_EXT[system]

def system_to_stdlib_linkflags(system):
return _SYSTEM_TO_STDLIB_LINKFLAGS[system]
def system_to_stdlib_linkflags(target_triple):
val = _SYSTEM_TO_STDLIB_LINKFLAGS[target_triple.system]
if type(val) == "list":
return val
return val[target_triple.abi]

def triple_to_constraint_set(target_triple):
"""Returns a set of constraints for a given platform triple
Expand Down
2 changes: 1 addition & 1 deletion rust/private/repository_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ def BUILD_for_rust_toolchain(
str: A rendered template of a `rust_toolchain` declaration
"""
if stdlib_linkflags == None:
stdlib_linkflags = ", ".join(['"%s"' % x for x in system_to_stdlib_linkflags(target_triple.system)])
stdlib_linkflags = ", ".join(['"%s"' % x for x in system_to_stdlib_linkflags(target_triple)])

rustfmt_label = None
if include_rustfmt:
Expand Down
51 changes: 25 additions & 26 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,9 @@ def _symlink_for_ambiguous_lib(actions, toolchain, crate_info, lib):

# Take the absolute value of hash() since it could be negative.
path_hash = abs(hash(lib.path))
lib_name = get_lib_name_for_windows(lib) if toolchain.target_os.startswith("windows") else get_lib_name_default(lib)
lib_name = get_lib_name_for_windows(lib) if toolchain.target_abi == "msvc" else get_lib_name_default(lib)

if toolchain.target_os.startswith("windows"):
if toolchain.target_abi == "msvc":
prefix = ""
extension = ".lib"
elif lib_name.endswith(".pic"):
Expand Down Expand Up @@ -1495,7 +1495,7 @@ def rustc_compile_action(
pdb_file = None
dsym_folder = None
if crate_info.type in ("cdylib", "bin") and not experimental_use_cc_common_link:
if toolchain.target_os == "windows" and compilation_mode.strip_level == "none":
if toolchain.target_abi == "msvc" and compilation_mode.strip_level == "none":
pdb_file = ctx.actions.declare_file(crate_info.output.basename[:-len(crate_info.output.extension)] + "pdb", sibling = crate_info.output)
action_outputs.append(pdb_file)
elif toolchain.target_os in ["macos", "darwin"]:
Expand Down Expand Up @@ -2200,7 +2200,7 @@ def _get_crate_dirname(crate):
"""
return crate.output.dirname

def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows = False, for_darwin = False, flavor_msvc = False):
def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_darwin = False, flavor_msvc = False):
artifact = get_preferred_artifact(lib, use_pic)
if ambiguous_libs and artifact.path in ambiguous_libs:
artifact = ambiguous_libs[artifact.path]
Expand Down Expand Up @@ -2240,17 +2240,11 @@ def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows
):
return [] if for_darwin else ["-lstatic=%s" % get_lib_name(artifact)]

if for_windows:
if flavor_msvc:
return [
"-lstatic=%s" % get_lib_name(artifact),
"-Clink-arg={}".format(artifact.basename),
]
else:
return [
"-lstatic=%s" % get_lib_name(artifact),
"-Clink-arg=-l{}".format(artifact.basename),
]
if flavor_msvc:
return [
"-lstatic=%s" % get_lib_name(artifact),
"-Clink-arg={}".format(artifact.basename),
]
else:
return [
"-lstatic=%s" % get_lib_name(artifact),
Expand Down Expand Up @@ -2281,7 +2275,8 @@ def _make_link_flags_windows(make_link_flags_args, flavor_msvc, use_direct_drive
("-Clink-arg=%s--no-whole-archive" % prefix),
])
elif include_link_flags:
ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_for_windows, for_windows = True, flavor_msvc = flavor_msvc))
get_lib_name = get_lib_name_for_windows if flavor_msvc else get_lib_name_default
ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, flavor_msvc = flavor_msvc))
_add_user_link_flags(ret, linker_input)
return ret

Expand Down Expand Up @@ -2361,19 +2356,19 @@ def _get_make_link_flag_funcs(target_os, target_abi, use_direct_link_driver):
- callable: The function for producing link args.
- callable: The function for formatting link library names.
"""

get_lib_name = get_lib_name_default

if target_os == "windows":
make_link_flags_windows_msvc = _make_link_flags_windows_msvc_direct if use_direct_link_driver else _make_link_flags_windows_msvc_indirect
make_link_flags_windows_gnu = _make_link_flags_windows_gnu_direct if use_direct_link_driver else _make_link_flags_windows_gnu_indirect
make_link_flags = make_link_flags_windows_msvc if target_abi == "msvc" else make_link_flags_windows_gnu
get_lib_name = get_lib_name_for_windows
if target_abi == "msvc":
make_link_flags = _make_link_flags_windows_msvc_direct if use_direct_link_driver else _make_link_flags_windows_msvc_indirect
get_lib_name = get_lib_name_for_windows
else:
make_link_flags = _make_link_flags_windows_gnu_direct if use_direct_link_driver else _make_link_flags_windows_gnu_indirect
elif target_os.startswith(("mac", "darwin", "ios")):
make_link_flags_darwin = _make_link_flags_darwin_direct if use_direct_link_driver else _make_link_flags_darwin_indirect
make_link_flags = make_link_flags_darwin
get_lib_name = get_lib_name_default
make_link_flags = _make_link_flags_darwin_direct if use_direct_link_driver else _make_link_flags_darwin_indirect
else:
make_link_flags_default = _make_link_flags_default_direct if use_direct_link_driver else _make_link_flags_default_indirect
make_link_flags = make_link_flags_default
get_lib_name = get_lib_name_default
make_link_flags = _make_link_flags_default_direct if use_direct_link_driver else _make_link_flags_default_indirect

return (make_link_flags, get_lib_name)

Expand Down Expand Up @@ -2703,3 +2698,7 @@ no_std = rule(
},
implementation = _no_std_impl,
)

# Test-only exports for private helpers.
portable_link_flags_for_testing = _portable_link_flags
symlink_for_ambiguous_lib_for_testing = _symlink_for_ambiguous_lib
3 changes: 3 additions & 0 deletions test/unit/windows_lib_name/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
load(":windows_lib_name_test.bzl", "windows_lib_name_test_suite")

windows_lib_name_test_suite(name = "windows_lib_name_test_suite")
185 changes: 185 additions & 0 deletions test/unit/windows_lib_name/windows_lib_name_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
"""Analysistests for Windows-specific library naming and link flags."""

load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")

# buildifier: disable=bzl-visibility
load("//rust/private:rustc.bzl", "portable_link_flags_for_testing", "symlink_for_ambiguous_lib_for_testing")

# buildifier: disable=bzl-visibility
load("//rust/private:utils.bzl", "get_lib_name_default", "get_lib_name_for_windows")

# buildifier: disable=provider-params
LinkFlagsInfo = provider(fields = {"flags": "List[str]"})

# buildifier: disable=provider-params
SymlinkInfo = provider(fields = {"symlink": "File"})

def _portable_link_flags_probe_impl(ctx):
lib_artifact = ctx.actions.declare_file(ctx.attr.lib_basename)
ctx.actions.write(lib_artifact, "", is_executable = False)
library_to_link = struct(
static_library = lib_artifact,
pic_static_library = None,
dynamic_library = None,
interface_library = None,
alwayslink = False,
)

get_lib_name = get_lib_name_for_windows if ctx.attr.flavor_msvc else get_lib_name_default
flags = portable_link_flags_for_testing(
lib = library_to_link,
use_pic = False,
ambiguous_libs = {},
get_lib_name = get_lib_name,
for_windows = True,
flavor_msvc = ctx.attr.flavor_msvc,
)

return [
DefaultInfo(files = depset([])),
LinkFlagsInfo(flags = flags),
]

portable_link_flags_probe = rule(
implementation = _portable_link_flags_probe_impl,
attrs = {
"flavor_msvc": attr.bool(default = False),
"lib_basename": attr.string(mandatory = True),
},
)

def _symlink_probe_impl(ctx):
lib_artifact = ctx.actions.declare_file(ctx.attr.lib_basename)
ctx.actions.write(lib_artifact, "", is_executable = False)
crate_output = ctx.actions.declare_file("crate.rlib")
ctx.actions.write(crate_output, "", is_executable = False)
symlink = symlink_for_ambiguous_lib_for_testing(
ctx.actions,
toolchain = struct(target_abi = ctx.attr.target_abi),
crate_info = struct(output = crate_output),
lib = lib_artifact,
)

return [
SymlinkInfo(symlink = symlink),
DefaultInfo(files = depset([symlink])),
]

symlink_probe = rule(
implementation = _symlink_probe_impl,
attrs = {
"lib_basename": attr.string(mandatory = True),
"target_abi": attr.string(mandatory = True),
},
)

def _portable_link_flags_windows_gnu_test_impl(ctx):
env = analysistest.begin(ctx)
flags = analysistest.target_under_test(env)[LinkFlagsInfo].flags

asserts.equals(
env,
["-lstatic=foo.dll", "-Clink-arg=-lfoo.dll"],
flags,
)
return analysistest.end(env)

portable_link_flags_windows_gnu_test = analysistest.make(
_portable_link_flags_windows_gnu_test_impl,
)

def _portable_link_flags_windows_msvc_test_impl(ctx):
env = analysistest.begin(ctx)
flags = analysistest.target_under_test(env)[LinkFlagsInfo].flags

asserts.equals(
env,
["-lstatic=libfoo.dll", "-Clink-arg=libfoo.dll.lib"],
flags,
)
return analysistest.end(env)

portable_link_flags_windows_msvc_test = analysistest.make(
_portable_link_flags_windows_msvc_test_impl,
)

def _symlink_name_windows_gnu_test_impl(ctx):
env = analysistest.begin(ctx)
symlink = analysistest.target_under_test(env)[SymlinkInfo].symlink

asserts.true(env, symlink.basename.startswith("libfoo.dll-"))
asserts.true(env, symlink.basename.endswith(".a"))
asserts.false(env, symlink.basename.startswith("liblib"))

return analysistest.end(env)

symlink_name_windows_gnu_test = analysistest.make(_symlink_name_windows_gnu_test_impl)

def _symlink_name_windows_msvc_test_impl(ctx):
env = analysistest.begin(ctx)
symlink = analysistest.target_under_test(env)[SymlinkInfo].symlink

asserts.true(env, symlink.basename.startswith("native_dep-"))
asserts.true(env, symlink.basename.endswith(".lib"))

return analysistest.end(env)

symlink_name_windows_msvc_test = analysistest.make(_symlink_name_windows_msvc_test_impl)

def _define_targets():
portable_link_flags_probe(
name = "portable_link_flags_windows_gnu_probe",
flavor_msvc = False,
lib_basename = "libfoo.dll.a",
)
portable_link_flags_probe(
name = "portable_link_flags_windows_msvc_probe",
flavor_msvc = True,
lib_basename = "libfoo.dll.lib",
)

symlink_probe(
name = "symlink_windows_gnu_probe",
lib_basename = "libfoo.dll.a",
target_abi = "gnu",
)
symlink_probe(
name = "symlink_windows_msvc_probe",
lib_basename = "native_dep.lib",
target_abi = "msvc",
)

def windows_lib_name_test_suite(name):
"""Entry-point macro for Windows library naming tests.

Args:
name: test suite name
"""
_define_targets()

portable_link_flags_windows_gnu_test(
name = "portable_link_flags_windows_gnu_test",
target_under_test = ":portable_link_flags_windows_gnu_probe",
)
portable_link_flags_windows_msvc_test(
name = "portable_link_flags_windows_msvc_test",
target_under_test = ":portable_link_flags_windows_msvc_probe",
)
symlink_name_windows_gnu_test(
name = "symlink_name_windows_gnu_test",
target_under_test = ":symlink_windows_gnu_probe",
)
symlink_name_windows_msvc_test(
name = "symlink_name_windows_msvc_test",
target_under_test = ":symlink_windows_msvc_probe",
)

native.test_suite(
name = name,
tests = [
":portable_link_flags_windows_gnu_test",
":portable_link_flags_windows_msvc_test",
":symlink_name_windows_gnu_test",
":symlink_name_windows_msvc_test",
],
)
3 changes: 3 additions & 0 deletions test/unit/windows_stdlib/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
load(":windows_stdlib_test.bzl", "windows_stdlib_test_suite")

windows_stdlib_test_suite(name = "windows_stdlib_test_suite")
Loading