Skip to content

Commit

Permalink
rust_stdlib_filegroup: update to support srcs from another package (#…
Browse files Browse the repository at this point in the history
…2735)

The `rust_stdlib_filegroup` rule would sometimes break when passing
`.rlib`-s originating from another package to `srcs`.
The root cause is the logic inside it that creates `.a` -> `.rlib`
symlinks, where the `.a` symlink is declared sibling of the `.rlib`.
Bazel only allows symlink siblings to be in the same package as the
rule.

This updates the logic to detect this and create an intermediary `.rlib`
under the rule's package, allowing the `.a` to be symlinked to that.

---------

Co-authored-by: scentini <[email protected]>
  • Loading branch information
krasimirgg and scentini authored Jul 23, 2024
1 parent 4a530aa commit 64a4b52
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 3 deletions.
2 changes: 1 addition & 1 deletion rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1616,7 +1616,7 @@ def establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_co
# bazel hard-codes a check for endswith((".a", ".pic.a",
# ".lib")) in create_library_to_link, so we work around that
# by creating a symlink to the .rlib with a .a extension.
dot_a = make_static_lib_symlink(ctx.actions, crate_info.output)
dot_a = make_static_lib_symlink(ctx.label.package, ctx.actions, crate_info.output)

# TODO(hlopko): handle PIC/NOPIC correctly
library_to_link = cc_common.create_library_to_link(
Expand Down
16 changes: 15 additions & 1 deletion rust/private/utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ def dedent(doc_string):
block = " " * space_count
return "\n".join([line.replace(block, "", 1).rstrip() for line in lines])

def make_static_lib_symlink(actions, rlib_file):
def make_static_lib_symlink(ctx_package, actions, rlib_file):
"""Add a .a symlink to an .rlib file.
The name of the symlink is derived from the <name> of the <name>.rlib file as follows:
Expand All @@ -432,17 +432,31 @@ def make_static_lib_symlink(actions, rlib_file):
* `crateb.rlib` is `libcrateb.a`.
Args:
ctx_package (string): The rule's context package name.
actions (actions): The rule's context actions object.
rlib_file (File): The file to symlink, which must end in .rlib.
Returns:
The symlink's File.
"""

if not rlib_file.basename.endswith(".rlib"):
fail("file is not an .rlib: ", rlib_file.basename)
basename = rlib_file.basename[:-5]
if not basename.startswith("lib"):
basename = "lib" + basename

# The .a symlink below is created as a sibling to the .rlib file.
# Bazel doesn't allow creating a symlink outside of the rule's package,
# so if the .rlib file comes from a different package, first symlink it
# to the rule's package. The name of the new .rlib symlink is derived
# as the name of the original .rlib relative to its package.
if rlib_file.owner.package != ctx_package:
new_path = rlib_file.short_path.removeprefix(rlib_file.owner.package).removeprefix("/")
new_rlib_file = actions.declare_file(new_path)
actions.symlink(output = new_rlib_file, target_file = rlib_file)
rlib_file = new_rlib_file

dot_a = actions.declare_file(basename + ".a", sibling = rlib_file)
actions.symlink(output = dot_a, target_file = rlib_file)
return dot_a
Expand Down
2 changes: 1 addition & 1 deletion rust/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def _rust_stdlib_filegroup_impl(ctx):
#
# alloc depends on the allocator_library if it's configured, but we
# do that later.
dot_a_files = [make_static_lib_symlink(ctx.actions, f) for f in std_rlibs]
dot_a_files = [make_static_lib_symlink(ctx.label.package, ctx.actions, f) for f in std_rlibs]

alloc_files = [f for f in dot_a_files if "alloc" in f.basename and "std" not in f.basename]
between_alloc_and_core_files = [f for f in dot_a_files if "compiler_builtins" in f.basename]
Expand Down
11 changes: 11 additions & 0 deletions test/unit/toolchain/subpackage/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
genrule(
name = "dummy_rlib",
outs = ["core.rlib"],
cmd = "touch $@",
)

filegroup(
name = "std_libs_srcs",
srcs = [":dummy_rlib"],
visibility = ["//test/unit/toolchain:__subpackages__"],
)
27 changes: 27 additions & 0 deletions test/unit/toolchain/toolchain_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,26 @@ def _toolchain_location_expands_linkflags_impl(ctx):

return analysistest.end(env)

def _std_libs_support_srcs_outside_package_test_impl(ctx):
env = analysistest.begin(ctx)
tut = analysistest.target_under_test(env)
actions = analysistest.target_actions(env)

symlinks = [a for a in actions if a.mnemonic == "Symlink"]
asserts.equals(env, 2, len(symlinks))

rlib_symlink = symlinks[0].outputs.to_list()[0]
asserts.equals(env, tut.label.package + "/core.rlib", rlib_symlink.short_path)

a_symlink = symlinks[1].outputs.to_list()[0]
asserts.equals(env, tut.label.package + "/libcore.a", a_symlink.short_path)

return analysistest.end(env)

toolchain_specifies_target_triple_test = analysistest.make(_toolchain_specifies_target_triple_test_impl)
toolchain_specifies_target_json_test = analysistest.make(_toolchain_specifies_target_json_test_impl)
toolchain_location_expands_linkflags_test = analysistest.make(_toolchain_location_expands_linkflags_impl)
std_libs_support_srcs_outside_package_test = analysistest.make(_std_libs_support_srcs_outside_package_test_impl)

def _define_test_targets():
native.filegroup(
Expand All @@ -61,6 +78,11 @@ def _define_test_targets():
srcs = [":stdlib_srcs"],
)

rust_stdlib_filegroup(
name = "std_libs_with_srcs_outside_package",
srcs = ["//test/unit/toolchain/subpackage:std_libs_srcs"],
)

native.filegroup(
name = "target_json",
srcs = ["toolchain-test-triple.json"],
Expand Down Expand Up @@ -166,6 +188,10 @@ def toolchain_test_suite(name):
name = "toolchain_location_expands_linkflags_test",
target_under_test = ":rust_location_expand_toolchain",
)
std_libs_support_srcs_outside_package_test(
name = "std_libs_support_srcs_outside_package_test",
target_under_test = ":std_libs_with_srcs_outside_package",
)

native.test_suite(
name = name,
Expand All @@ -174,5 +200,6 @@ def toolchain_test_suite(name):
":toolchain_specifies_target_json_test",
":toolchain_specifies_inline_target_json_test",
":toolchain_location_expands_linkflags_test",
":std_libs_support_srcs_outside_package_test",
],
)

0 comments on commit 64a4b52

Please sign in to comment.