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
24 changes: 13 additions & 11 deletions rust/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,19 @@ rust = module_extension(
},
)

_RUST_HOST_TOOLS_TAG_ATTRS = {
"name": attr.string(
doc = "The name of the module to create",
default = "rust_host_tools",
),
"version": attr.string(
doc = "The version of Rust to use for tools executed on the Bazel host.",
default = rust_common.default_version,
),
} | _COMMON_TAG_KWARGS

_RUST_HOST_TOOLS_TAG = tag_class(
attrs = {
"name": attr.string(
doc = "The name of the module to create",
default = "rust_host_tools",
),
"version": attr.string(
doc = "The version of Rust to use for tools executed on the Bazel host.",
default = rust_common.default_version,
),
} | _COMMON_TAG_KWARGS,
attrs = _RUST_HOST_TOOLS_TAG_ATTRS,
)

# This is a separate module extension so that only the host tools are
Expand All @@ -312,7 +314,7 @@ def _rust_host_tools_impl(module_ctx):

for mod in module_ctx.modules:
for host_tools in mod.tags.host_tools:
attrs = {key: getattr(host_tools, key) for key in dir(host_tools)}
attrs = {key: getattr(host_tools, key) for key in _RUST_HOST_TOOLS_TAG_ATTRS.keys()}

# Label attrs must be stringified for the repository rule.
for label_attr in ("allocator_library", "global_allocator_library"):
Expand Down
27 changes: 23 additions & 4 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2293,7 +2293,8 @@ def portable_link_flags(
ambiguous_libs,
get_lib_name,
for_darwin = False,
flavor_msvc = False):
flavor_msvc = False,
link_static_library_by_path = False):
"""_summary_

Args:
Expand All @@ -2303,6 +2304,8 @@ def portable_link_flags(
get_lib_name (_type_): _description_
for_darwin (bool, optional): _description_. Defaults to False.
flavor_msvc (bool, optional): _description_. Defaults to False.
link_static_library_by_path (bool, optional): Use the selected static artifact path for the
trailing `-Clink-arg` copy instead of `-l<name>`. Defaults to False.

Returns:
_type_: _description_
Expand Down Expand Up @@ -2352,9 +2355,12 @@ def portable_link_flags(
"-Clink-arg={}".format(artifact.basename),
]
else:
# Rustc may restore dynamic linker mode before appending -Clink-arg
# values, so use the selected archive path where supported.
late_static_link_arg = artifact.path if link_static_library_by_path else "-l{}".format(get_lib_name(artifact))
return [
"-lstatic=%s" % get_lib_name(artifact),
"-Clink-arg=-l{}".format(get_lib_name(artifact)),
"-Clink-arg={}".format(late_static_link_arg),
]
elif _is_dylib(lib):
return [
Expand Down Expand Up @@ -2409,7 +2415,14 @@ def _make_link_flags_darwin(make_link_flags_args, use_direct_driver):
("-Clink-arg=%s%s" % (prefix, get_preferred_artifact(lib, use_pic).path)),
])
elif include_link_flags:
ret.extend(portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default, for_darwin = True))
ret.extend(portable_link_flags(
lib,
use_pic,
ambiguous_libs,
get_lib_name_default,
for_darwin = True,
link_static_library_by_path = True,
))
_add_user_link_flags(ret, linker_input)
return ret

Expand All @@ -2425,7 +2438,13 @@ def _make_link_flags_default(make_link_flags_args, use_direct_driver):
("-Clink-arg=%s--no-whole-archive" % prefix),
])
elif include_link_flags:
ret.extend(portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default))
ret.extend(portable_link_flags(
lib,
use_pic,
ambiguous_libs,
get_lib_name_default,
link_static_library_by_path = True,
))
_add_user_link_flags(ret, linker_input)
return ret

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ def _dependency_linkopts_are_propagated_test_impl(ctx):
# Expect a library's own linkopts to come after the flags we create to link them.
# This is required, because linkopts are ordered and the linker will only apply later ones when resolving symbols required for earlier ones.
# This means that if one of our transitive deps has a linkopt like `-lfoo`, the dep will see the symbols of foo at link time.
_assert_contains_in_order(env, link_action.argv, ["-lstatic=foo_with_linkopts", "-Clink-arg=-lfoo_with_linkopts", "--codegen=link-arg=-L/doesnotexist"])
native_link_arg = _find_arg_with_prefix_and_suffix(
env,
link_action.argv,
"-Clink-arg=",
"/test/linker_inputs_propagation/libfoo_with_linkopts.a",
)
_assert_contains_in_order(env, link_action.argv, ["-lstatic=foo_with_linkopts", native_link_arg, "--codegen=link-arg=-L/doesnotexist"])
return analysistest.end(env)

def _assert_contains_input(env, inputs, name):
Expand All @@ -47,6 +53,13 @@ def _assert_contains_in_order(env, haystack, needle):
return
unittest.fail(env, "Expected {} to contain {}".format(haystack, needle))

def _find_arg_with_prefix_and_suffix(env, haystack, prefix, suffix):
for arg in haystack:
if arg.startswith(prefix) and arg.endswith(suffix):
return arg
unittest.fail(env, "Expected {} to contain an argument starting with {} and ending with {}".format(haystack, prefix, suffix))
return None

def _get_lib_name(ctx, name):
if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]):
return name
Expand Down
74 changes: 30 additions & 44 deletions test/unit/native_deps/native_deps_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ def _assert_bin_dir_structure(env, ctx, bin_dir, toolchain):
"darwin component should start with 'darwin', got '{}'".format(darwin_component),
)

def _native_link_arg(ctx, action, pic_suffix = "", stripped = False):
toolchain = _get_toolchain(ctx)
if toolchain.target_os == "windows":
if toolchain.target_triple.abi == "msvc":
link_arg = "-Clink-arg=native_dep.lib"
else:
link_arg = "-Clink-arg=-lnative_dep.lib"
else:
link_arg = "-Clink-arg={}/test/unit/native_deps/libnative_dep{}.a".format(
_get_bin_dir_from_action(action),
pic_suffix,
)
return link_arg.removeprefix("-Clink-arg=") if stripped else link_arg

def _rlib_has_no_native_libs_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
Expand All @@ -94,78 +108,46 @@ def _cdylib_has_native_libs_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
action = tut.actions[0]
toolchain = _get_toolchain(ctx)
compilation_mode = ctx.var["COMPILATION_MODE"]
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
assert_argv_contains(env, action, "--crate-type=cdylib")
assert_argv_contains(env, action, "-lstatic=native_dep{}".format(pic_suffix))
if toolchain.target_os == "windows":
if toolchain.target_triple.abi == "msvc":
native_link_arg = "-Clink-arg=native_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep{}".format(pic_suffix)
assert_argv_contains(env, action, native_link_arg)
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
assert_argv_contains_prefix(env, action, "--codegen=linker=")
return analysistest.end(env)

def _staticlib_has_native_libs_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
action = tut.actions[0]
toolchain = _get_toolchain(ctx)
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
assert_argv_contains(env, action, "--crate-type=staticlib")
assert_argv_contains(env, action, "-lstatic=native_dep")
if toolchain.target_os == "windows":
if toolchain.target_triple.abi == "msvc":
native_link_arg = "-Clink-arg=native_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep"
assert_argv_contains(env, action, native_link_arg)
assert_argv_contains(env, action, _native_link_arg(ctx, action))
assert_argv_contains_prefix(env, action, "--codegen=linker=")
return analysistest.end(env)

def _proc_macro_has_native_libs_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
action = tut.actions[0]
toolchain = _get_toolchain(ctx)
compilation_mode = ctx.var["COMPILATION_MODE"]
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
assert_argv_contains(env, action, "--crate-type=proc-macro")
assert_argv_contains(env, action, "-lstatic=native_dep{}".format(pic_suffix))
if toolchain.target_os == "windows":
if toolchain.target_triple.abi == "msvc":
native_link_arg = "-Clink-arg=native_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep{}".format(pic_suffix)
assert_argv_contains(env, action, native_link_arg)
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
assert_argv_contains_prefix(env, action, "--codegen=linker=")
return analysistest.end(env)

def _bin_has_native_libs_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
action = tut.actions[0]
toolchain = _get_toolchain(ctx)
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
assert_argv_contains(env, action, "-lstatic=native_dep")
if toolchain.target_os == "windows":
if toolchain.target_triple.abi == "msvc":
native_link_arg = "-Clink-arg=native_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep.lib"
else:
native_link_arg = "-Clink-arg=-lnative_dep"
assert_argv_contains(env, action, native_link_arg)
assert_argv_contains(env, action, _native_link_arg(ctx, action))
assert_argv_contains_prefix(env, action, "--codegen=linker=")
return analysistest.end(env)

Expand Down Expand Up @@ -197,21 +179,22 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):

# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)
native_link_arg = _native_link_arg(ctx, action, stripped = True)

if toolchain.target_os in ["macos", "darwin"]:
if use_cc_linker:
# When using CC linker, args are passed with -Wl, prefix as separate arguments
want = [
"-lstatic=native_dep",
"-lnative_dep",
native_link_arg,
"-Wl,-force_load",
"-Wl,{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
]
else:
# When using rust-lld directly, args are passed without prefix as separate arguments
want = [
"-lstatic=native_dep",
"-lnative_dep",
native_link_arg,
"-force_load",
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
]
Expand Down Expand Up @@ -242,22 +225,23 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
elif toolchain.target_arch == "s390x":
want = [
"-lstatic=native_dep",
native_link_arg,
"link-arg=-Wl,--whole-archive",
"link-arg={}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
"link-arg=-Wl,--no-whole-archive",
]
elif use_cc_linker:
want = [
"-lstatic=native_dep",
"-lnative_dep",
native_link_arg,
"-Wl,--whole-archive",
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
"-Wl,--no-whole-archive",
]
else:
want = [
"-lstatic=native_dep",
"-lnative_dep",
native_link_arg,
"--whole-archive",
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
"--no-whole-archive",
Expand All @@ -280,21 +264,22 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):

compilation_mode = ctx.var["COMPILATION_MODE"]
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
native_link_arg = _native_link_arg(ctx, action, pic_suffix, stripped = True)

if toolchain.target_os in ["macos", "darwin"]:
if use_cc_linker:
# When using CC linker, args are passed with -Wl, prefix as separate arguments
want = [
"-lstatic=native_dep{}".format(pic_suffix),
"-lnative_dep{}".format(pic_suffix),
native_link_arg,
"-Wl,-force_load",
"-Wl,{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
]
else:
# When using rust-lld directly, args are passed without prefix as separate arguments
want = [
"-lstatic=native_dep{}".format(pic_suffix),
"-lnative_dep{}".format(pic_suffix),
native_link_arg,
"-force_load",
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
]
Expand Down Expand Up @@ -324,6 +309,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
elif toolchain.target_arch == "s390x":
want = [
"-lstatic=native_dep{}".format(pic_suffix),
native_link_arg,
"link-arg=-Wl,--whole-archive",
"link-arg={}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
"link-arg=-Wl,--no-whole-archive",
Expand All @@ -332,7 +318,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
# CC linker uses -Wl, prefix but arguments are separate
want = [
"-lstatic=native_dep{}".format(pic_suffix),
"-lnative_dep{}".format(pic_suffix),
native_link_arg,
"-Wl,--whole-archive",
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
"-Wl,--no-whole-archive",
Expand All @@ -341,7 +327,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
# rust-lld doesn't use -Wl, prefix, so flags and path are separate
want = [
"-lstatic=native_dep{}".format(pic_suffix),
"-lnative_dep{}".format(pic_suffix),
native_link_arg,
"--whole-archive",
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
"--no-whole-archive",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ def _proc_macro_does_not_leak_deps_impl(ctx):
else:
native_deps = [arg for arg in rustc_action.argv if arg == "-Clink-arg=-lnative.lib"]
else:
native_deps = [arg for arg in rustc_action.argv if arg == "-Clink-arg=-lnative"]
native_deps = [
arg
for arg in rustc_action.argv
if arg.startswith("-Clink-arg=") and arg.endswith("/test/unit/proc_macro/leaks_deps/native/libnative.a")
]
asserts.equals(env, 1, len(native_deps))

return analysistest.end(env)
Expand Down