From 91d1d88017870c822977d0d5bceb18b40d1be11a Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Fri, 9 Jul 2021 14:48:18 +0200 Subject: [PATCH 01/10] update static library naming mixed rust+cc deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes static library naming issues that cause the build of a rust_binary that depends on a cc_library that itself depends on a rust_library to fail. Consider a rust_binary that depends on a cc_library that itself depends on a rust_library: ``` . ├── bin.rs ├── BUILD └── lib.rs ``` ```rust // bin.rs fn main() { println!("hi"); } ``` ```rust // lib.rs: empty ``` ```bazel load("@rules_rust//rust:defs.bzl", "rust_benchmark", "rust_binary", "rust_library") rust_library( name = "rust_lib", srcs = ["lib.rs"], ) cc_library( name = "cc_lib", srcs = [], deps = [":rust_lib"], ) rust_binary( name = "bin", srcs = ["bin.rs"], deps = [":cc_lib"], ) ``` Running `bazel build //project:bin` runs into linker errors like: ``` /usr/bin/ld.gold: error: cannot find -lrust_lib /usr/bin/ld.gold: error: cannot find -lrustc_std_workspace_alloc-1ff59d4f23b10626 ``` This is because the linker expects the static library corresponding to `-lname` to be named `libname.a`. Also Bazel CC link actions get confused by static library names that have multiple dots, e.g., end in "libcrate.rlib.a", so updated the scripts to produce them as "libcrate-rlib.a" instead. --- rust/private/rustc.bzl | 2 +- rust/toolchain.bzl | 18 ++++++++++++------ test/unit/stdlib_ordering/stdlib_ordering.bzl | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index ea5ba025b0..c962904dd7 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -635,7 +635,7 @@ def establish_cc_info(ctx, crate_info, toolchain, cc_toolchain, feature_configur # 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 = ctx.actions.declare_file(crate_info.name + ".a", sibling = crate_info.output) + dot_a = ctx.actions.declare_file("lib" + crate_info.name + ".a", sibling = crate_info.output) ctx.actions.symlink(output = dot_a, target_file = crate_info.output) # TODO(hlopko): handle PIC/NOPIC correctly diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 95c42591bb..9c8b12f8b1 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -3,18 +3,24 @@ load("//rust/private:common.bzl", "rust_common") load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain") -def _make_dota(ctx, file): - """Add a symlink for a file that ends in .a, so it can be used as a staticlib. +def _make_dota(ctx, rlib_file, postfix = ""): + """Add a .a symlink to an .rlib file, so it can be used as a staticlib. + + The name of the symlink for crate.rlib is crate.a. Args: ctx (ctx): The rule's context object. - file (File): The file to symlink. + rlib_file (File): The file to symlink, which must end in .rlib. + postfix (string): A postfix to append to the symlink name. Returns: The symlink's File. """ - dot_a = ctx.actions.declare_file(file.basename + ".a", sibling = file) - ctx.actions.symlink(output = dot_a, target_file = file) + if not rlib_file.basename.endswith(".rlib"): + fail("file is not an .rlib: ", rlib_file.basename) + basename = rlib_file.basename[:-5] + dot_a = ctx.actions.declare_file(basename + postfix + ".a", sibling = rlib_file) + ctx.actions.symlink(output = dot_a, target_file = rlib_file) return dot_a def _rust_stdlib_filegroup_impl(ctx): @@ -35,7 +41,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_dota(ctx, f) for f in std_rlibs] + dot_a_files = [_make_dota(ctx, f, postfix = "-rlib") 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] diff --git a/test/unit/stdlib_ordering/stdlib_ordering.bzl b/test/unit/stdlib_ordering/stdlib_ordering.bzl index 645943f39e..d181328b5a 100644 --- a/test/unit/stdlib_ordering/stdlib_ordering.bzl +++ b/test/unit/stdlib_ordering/stdlib_ordering.bzl @@ -30,7 +30,7 @@ def _libstd_ordering_test_impl(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) libs = [lib.static_library for li in tut[CcInfo].linking_context.linker_inputs.to_list() for lib in li.libraries] - rlibs = [_categorize_library(lib.basename) for lib in libs if ".rlib" in lib.basename] + rlibs = [_categorize_library(lib.basename) for lib in libs if "-rlib" in lib.basename] set_to_check = _dedup_preserving_order([lib for lib in rlibs if lib != "other"]) asserts.equals(env, ["std", "core", "compiler_builtins", "alloc"], set_to_check) return analysistest.end(env) From 0dc941d58067d4549bd666d9f2dae2778c96d371 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Fri, 9 Jul 2021 15:10:20 +0200 Subject: [PATCH 02/10] don't pass panic_abort if panic_unwind is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes an issue that causes the build of a rust_binary that depends on a cc_library that depends on a rust_library to fail. Consider a rust_binary that depends on a cc_library that itself depends on a rust_library: ``` . ├── bin.rs ├── BUILD └── lib.rs ``` ```rust // bin.rs fn main() { println!("hi"); } ``` ```rust // lib.rs: empty ``` ```bazel load("@rules_rust//rust:defs.bzl", "rust_benchmark", "rust_binary", "rust_library") rust_library( name = "rust_lib", srcs = ["lib.rs"], ) cc_library( name = "cc_lib", srcs = [], deps = [":rust_lib"], ) rust_binary( name = "bin", srcs = ["bin.rs"], deps = [":cc_lib"], ) ``` Running `bazel build //project:bin` runs into linker errors like: /usr/bin/ld.gold: error: bazel-out/k8-fastbuild/bin/external/rust_linux_x86_64/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-5f5ff14665a8d5c5-rlib.a(panic_unwind-5f5ff14665a8d5c5.panic_unwind.p9ngf95o-cgu.0.rcgu.o): multiple definition of '__rust_panic_cleanup' /usr/bin/ld.gold: bazel-out/k8-fastbuild/bin/external/rust_linux_x86_64/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_abort-c6166278e71d9daf-rlib.a(panic_abort-c6166278e71d9daf.panic_abort.4p8k2zko-cgu.0.rcgu.o): previous definition here That's because we're passing both panic_unwind and panic_abort to the linker. The standard library by default depends on panic_unwind. This updates the rules to prefer panic_unwind. It would be nice to have an option for the user to pick the panic runtime similarly to how it could be done upstream: https://rustc-dev-guide.rust-lang.org/panic-implementation.html#step-2-the-panic-runtime --- rust/toolchain.bzl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 9c8b12f8b1..23e9e37894 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -41,6 +41,15 @@ def _rust_stdlib_filegroup_impl(ctx): # # alloc depends on the allocator_library if it's configured, but we # do that later. + # + # The libraries panic_abort and panic_unwind are alternatives. + # The std by default requires panic_unwind. Exclude panic_abort if + # panic_unwind is present. + # TODO: provide a setting to choose between panic_abort and + # panic_unwind. + has_panic_unwind = [f for f in std_rlibs if "panic_unwind" in f.basename] + if has_panic_unwind: + std_rlibs = [f for f in std_rlibs if "panic_abort" not in f.basename] dot_a_files = [_make_dota(ctx, f, postfix = "-rlib") 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] From e91a4259d1f3f52595d72c058d1df062bba77367 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 12 Jul 2021 11:56:42 +0200 Subject: [PATCH 03/10] rename test/unit/stdlib_ordering to /test/unit/stdlib I'll add a additional test case there. --- test/unit/{stdlib_ordering => stdlib}/BUILD.bazel | 0 test/unit/{stdlib_ordering => stdlib}/some_rlib.rs | 0 test/unit/{stdlib_ordering => stdlib}/stdlib_ordering.bzl | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename test/unit/{stdlib_ordering => stdlib}/BUILD.bazel (100%) rename test/unit/{stdlib_ordering => stdlib}/some_rlib.rs (100%) rename test/unit/{stdlib_ordering => stdlib}/stdlib_ordering.bzl (100%) diff --git a/test/unit/stdlib_ordering/BUILD.bazel b/test/unit/stdlib/BUILD.bazel similarity index 100% rename from test/unit/stdlib_ordering/BUILD.bazel rename to test/unit/stdlib/BUILD.bazel diff --git a/test/unit/stdlib_ordering/some_rlib.rs b/test/unit/stdlib/some_rlib.rs similarity index 100% rename from test/unit/stdlib_ordering/some_rlib.rs rename to test/unit/stdlib/some_rlib.rs diff --git a/test/unit/stdlib_ordering/stdlib_ordering.bzl b/test/unit/stdlib/stdlib_ordering.bzl similarity index 100% rename from test/unit/stdlib_ordering/stdlib_ordering.bzl rename to test/unit/stdlib/stdlib_ordering.bzl From c18e3671876b73790291b9d0254cab1bc9da7522 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 12 Jul 2021 12:04:10 +0200 Subject: [PATCH 04/10] add tests --- rust/toolchain.bzl | 3 ++ test/unit/cc_info/cc_info_test.bzl | 1 + test/unit/stdlib/BUILD.bazel | 4 +-- .../{stdlib_ordering.bzl => stdlib.bzl} | 35 ++++++++++++++++--- 4 files changed, 36 insertions(+), 7 deletions(-) rename test/unit/stdlib/{stdlib_ordering.bzl => stdlib.bzl} (56%) diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 23e9e37894..eea64aae37 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -50,6 +50,9 @@ def _rust_stdlib_filegroup_impl(ctx): has_panic_unwind = [f for f in std_rlibs if "panic_unwind" in f.basename] if has_panic_unwind: std_rlibs = [f for f in std_rlibs if "panic_abort" not in f.basename] + + # We add "-rlib" to the names of the standard library static libraries + # to distinguish them from user defined libraries. dot_a_files = [_make_dota(ctx, f, postfix = "-rlib") 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] diff --git a/test/unit/cc_info/cc_info_test.bzl b/test/unit/cc_info/cc_info_test.bzl index 9a947a595f..f0c7341b9e 100644 --- a/test/unit/cc_info/cc_info_test.bzl +++ b/test/unit/cc_info/cc_info_test.bzl @@ -36,6 +36,7 @@ def _assert_cc_info_has_library_to_link(env, tut, type, ccinfo_count): asserts.equals(env, None, library_to_link.resolved_symlink_dynamic_library) asserts.equals(env, None, library_to_link.resolved_symlink_interface_library) asserts.true(env, library_to_link.static_library != None) + asserts.true(env, library_to_link.static_library.basename.startswith("lib" + tut.label.name)) asserts.true(env, library_to_link.pic_static_library != None) asserts.equals(env, library_to_link.static_library, library_to_link.pic_static_library) diff --git a/test/unit/stdlib/BUILD.bazel b/test/unit/stdlib/BUILD.bazel index fb860b0214..3907b2edbf 100644 --- a/test/unit/stdlib/BUILD.bazel +++ b/test/unit/stdlib/BUILD.bazel @@ -1,4 +1,4 @@ -load(":stdlib_ordering.bzl", "stdlib_ordering_suite") +load(":stdlib.bzl", "stdlib_suite") ############################ UNIT TESTS ############################# -stdlib_ordering_suite(name = "stdlib_ordering_suite") +stdlib_suite(name = "stdlib_suite") diff --git a/test/unit/stdlib/stdlib_ordering.bzl b/test/unit/stdlib/stdlib.bzl similarity index 56% rename from test/unit/stdlib/stdlib_ordering.bzl rename to test/unit/stdlib/stdlib.bzl index d181328b5a..69d2b0eb40 100644 --- a/test/unit/stdlib/stdlib_ordering.bzl +++ b/test/unit/stdlib/stdlib.bzl @@ -1,4 +1,4 @@ -"""Unittest to verify ordering of rust stdlib in rust_library() CcInfo""" +"""Unittest to verify contents and ordering of rust stdlib in rust_library() CcInfo""" load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("//rust:defs.bzl", "rust_library") @@ -26,17 +26,37 @@ def _dedup_preserving_order(list): r.append(e) return r +def _stdlibs(tut): + """Given a target, return the list of its standard rust libraries.""" + libs = [lib.static_library for li in tut[CcInfo].linking_context.linker_inputs.to_list() for lib in li.libraries] + stdlibs = [lib for lib in libs if (lib.basename.startswith("lib") and lib.basename.endswith("-rlib.a"))] + return stdlibs + def _libstd_ordering_test_impl(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) - libs = [lib.static_library for li in tut[CcInfo].linking_context.linker_inputs.to_list() for lib in li.libraries] - rlibs = [_categorize_library(lib.basename) for lib in libs if "-rlib" in lib.basename] - set_to_check = _dedup_preserving_order([lib for lib in rlibs if lib != "other"]) + stdlib_categories = [_categorize_library(lib.basename) for lib in _stdlibs(tut)] + set_to_check = _dedup_preserving_order([lib for lib in stdlib_categories if lib != "other"]) asserts.equals(env, ["std", "core", "compiler_builtins", "alloc"], set_to_check) return analysistest.end(env) libstd_ordering_test = analysistest.make(_libstd_ordering_test_impl) +def _libstd_panic_test_impl(ctx): + # The libraries panic_unwind and panic_abort are alternatives. + # Check that they don't occur together. + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + stdlibs = _stdlibs(tut) + has_panic_unwind = [lib for lib in stdlibs if "panic_unwind" in lib.basename] + if has_panic_unwind: + has_panic_abort = [lib for lib in stdlibs if "panic_abort" in lib.basename] + asserts.false(env, has_panic_abort) + + return analysistest.end(env) + +libstd_panic_test = analysistest.make(_libstd_panic_test_impl) + def _native_dep_test(): rust_library( name = "some_rlib", @@ -48,7 +68,12 @@ def _native_dep_test(): target_under_test = ":some_rlib", ) -def stdlib_ordering_suite(name): + libstd_panic_test( + name = "libstd_panic_test", + target_under_test = ":some_rlib", + ) + +def stdlib_suite(name): """Entry-point macro called from the BUILD file. Args: From 472563a744a39d6580de8bc3f8ed8f98f827cf78 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 13 Jul 2021 10:35:28 +0200 Subject: [PATCH 05/10] restrict test assert to only rlibs and libs This should address the Windows buildbot failure. --- test/unit/cc_info/cc_info_test.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/cc_info/cc_info_test.bzl b/test/unit/cc_info/cc_info_test.bzl index f0c7341b9e..32f2385cde 100644 --- a/test/unit/cc_info/cc_info_test.bzl +++ b/test/unit/cc_info/cc_info_test.bzl @@ -36,7 +36,8 @@ def _assert_cc_info_has_library_to_link(env, tut, type, ccinfo_count): asserts.equals(env, None, library_to_link.resolved_symlink_dynamic_library) asserts.equals(env, None, library_to_link.resolved_symlink_interface_library) asserts.true(env, library_to_link.static_library != None) - asserts.true(env, library_to_link.static_library.basename.startswith("lib" + tut.label.name)) + if type in ("rlib", "lib"): + asserts.true(env, library_to_link.static_library.basename.startswith("lib" + tut.label.name)) asserts.true(env, library_to_link.pic_static_library != None) asserts.equals(env, library_to_link.static_library, library_to_link.pic_static_library) From 1d4e87eb32706de7e7e1bf98024a71ebe1bff8da Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 13 Jul 2021 17:40:27 +0200 Subject: [PATCH 06/10] move panic_{unwind,abort} filtering to _make_libstd_and_allocator_ccinfo --- rust/toolchain.bzl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index eea64aae37..afdcdebefb 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -41,15 +41,6 @@ def _rust_stdlib_filegroup_impl(ctx): # # alloc depends on the allocator_library if it's configured, but we # do that later. - # - # The libraries panic_abort and panic_unwind are alternatives. - # The std by default requires panic_unwind. Exclude panic_abort if - # panic_unwind is present. - # TODO: provide a setting to choose between panic_abort and - # panic_unwind. - has_panic_unwind = [f for f in std_rlibs if "panic_unwind" in f.basename] - if has_panic_unwind: - std_rlibs = [f for f in std_rlibs if "panic_abort" not in f.basename] # We add "-rlib" to the names of the standard library static libraries # to distinguish them from user defined libraries. @@ -158,8 +149,17 @@ def _make_libstd_and_allocator_ccinfo(ctx, rust_lib, allocator_library): transitive = [between_alloc_and_core_inputs], order = "topological", ) + + # The libraries panic_abort and panic_unwind are alternatives. + # The std by default requires panic_unwind. + # Exclude panic_abort if panic_unwind is present. + # TODO: Provide a setting to choose between panic_abort and panic_unwind. + filtered_between_core_and_std_files = rust_stdlib_info.between_core_and_std_files + has_panic_unwind = [f for f in filtered_between_core_and_std_files if "panic_unwind" in f.basename] + if has_panic_unwind: + filtered_between_core_and_std_files = [f for f in filtered_between_core_and_std_files if "panic_abort" not in f.basename] between_core_and_std_inputs = depset( - [_ltl(f, ctx, cc_toolchain, feature_configuration) for f in rust_stdlib_info.between_core_and_std_files], + [_ltl(f, ctx, cc_toolchain, feature_configuration) for f in filtered_between_core_and_std_files], transitive = [core_inputs], order = "topological", ) From fbed76f9121851c9eb3a408a2524119035916fb4 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 15 Jul 2021 11:05:05 +0200 Subject: [PATCH 07/10] remove `-rlib` postfix from the names of static library symlinks --- rust/toolchain.bzl | 9 +++------ test/unit/stdlib/stdlib.bzl | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index afdcdebefb..9097828715 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -3,7 +3,7 @@ load("//rust/private:common.bzl", "rust_common") load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain") -def _make_dota(ctx, rlib_file, postfix = ""): +def _make_dota(ctx, rlib_file): """Add a .a symlink to an .rlib file, so it can be used as a staticlib. The name of the symlink for crate.rlib is crate.a. @@ -19,7 +19,7 @@ def _make_dota(ctx, rlib_file, postfix = ""): if not rlib_file.basename.endswith(".rlib"): fail("file is not an .rlib: ", rlib_file.basename) basename = rlib_file.basename[:-5] - dot_a = ctx.actions.declare_file(basename + postfix + ".a", sibling = rlib_file) + dot_a = ctx.actions.declare_file(basename + ".a", sibling = rlib_file) ctx.actions.symlink(output = dot_a, target_file = rlib_file) return dot_a @@ -41,10 +41,7 @@ def _rust_stdlib_filegroup_impl(ctx): # # alloc depends on the allocator_library if it's configured, but we # do that later. - - # We add "-rlib" to the names of the standard library static libraries - # to distinguish them from user defined libraries. - dot_a_files = [_make_dota(ctx, f, postfix = "-rlib") for f in std_rlibs] + dot_a_files = [_make_dota(ctx, 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] diff --git a/test/unit/stdlib/stdlib.bzl b/test/unit/stdlib/stdlib.bzl index 69d2b0eb40..54535c97b5 100644 --- a/test/unit/stdlib/stdlib.bzl +++ b/test/unit/stdlib/stdlib.bzl @@ -29,7 +29,7 @@ def _dedup_preserving_order(list): def _stdlibs(tut): """Given a target, return the list of its standard rust libraries.""" libs = [lib.static_library for li in tut[CcInfo].linking_context.linker_inputs.to_list() for lib in li.libraries] - stdlibs = [lib for lib in libs if (lib.basename.startswith("lib") and lib.basename.endswith("-rlib.a"))] + stdlibs = [lib for lib in libs if (tut.label.name not in lib.basename)] return stdlibs def _libstd_ordering_test_impl(ctx): From 282135a80269eb43edac641a0f3f560d6a41bc3d Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 15 Jul 2021 11:21:09 +0200 Subject: [PATCH 08/10] move _make_dota to utils --- rust/private/rustc.bzl | 4 ++-- rust/private/utils.bzl | 28 ++++++++++++++++++++++++++++ rust/toolchain.bzl | 24 ++---------------------- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index c962904dd7..666ab235f7 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -27,6 +27,7 @@ load( "find_cc_toolchain", "get_lib_name", "get_preferred_artifact", + "make_static_lib", "relativize", ) @@ -635,8 +636,7 @@ def establish_cc_info(ctx, crate_info, toolchain, cc_toolchain, feature_configur # 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 = ctx.actions.declare_file("lib" + crate_info.name + ".a", sibling = crate_info.output) - ctx.actions.symlink(output = dot_a, target_file = crate_info.output) + dot_a = make_static_lib(ctx, crate_info.output) # TODO(hlopko): handle PIC/NOPIC correctly library_to_link = cc_common.create_library_to_link( diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl index 30b8aee1c2..9b7f58410b 100644 --- a/rust/private/utils.bzl +++ b/rust/private/utils.bzl @@ -296,3 +296,31 @@ def dedent(doc_string): # Remove the leading block of spaces from the current line block = " " * space_count return "\n".join([line.replace(block, "", 1).rstrip() for line in lines]) + +def make_static_lib(ctx, rlib_file): + """Add a .a symlink to an .rlib file, so it can be used as a staticlib. + + The name of the symlink is derived from the of the .rlib file as follows: + * `.a`, if starts with `lib` + * `lib.a`, otherwise. + + For example, the name of the symlink for + * `libcratea.rlib` is `libcratea.a` + * `crateb.rlib` is `libcrateb.a`. + + Args: + ctx (ctx): The rule's context object. + rlib_file (File): The file to symlink, which must end in .rlib. + postfix (string): A postfix to append to the symlink name. + + 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 + dot_a = ctx.actions.declare_file(basename + ".a", sibling = rlib_file) + ctx.actions.symlink(output = dot_a, target_file = rlib_file) + return dot_a diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 9097828715..9443fa8b01 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -1,27 +1,7 @@ """The rust_toolchain rule definition and implementation.""" load("//rust/private:common.bzl", "rust_common") -load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain") - -def _make_dota(ctx, rlib_file): - """Add a .a symlink to an .rlib file, so it can be used as a staticlib. - - The name of the symlink for crate.rlib is crate.a. - - Args: - ctx (ctx): The rule's context object. - rlib_file (File): The file to symlink, which must end in .rlib. - postfix (string): A postfix to append to the symlink name. - - 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] - dot_a = ctx.actions.declare_file(basename + ".a", sibling = rlib_file) - ctx.actions.symlink(output = dot_a, target_file = rlib_file) - return dot_a +load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain", "make_static_lib") def _rust_stdlib_filegroup_impl(ctx): rust_lib = ctx.files.srcs @@ -41,7 +21,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_dota(ctx, f) for f in std_rlibs] + dot_a_files = [make_static_lib(ctx, 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] From 01e82794783edc47c3e4ed6fa6a3c2b73a108bd8 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 15 Jul 2021 11:24:35 +0200 Subject: [PATCH 09/10] remove postfix argument docstring --- rust/private/utils.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl index 9b7f58410b..7ce5e940b0 100644 --- a/rust/private/utils.bzl +++ b/rust/private/utils.bzl @@ -311,7 +311,6 @@ def make_static_lib(ctx, rlib_file): Args: ctx (ctx): The rule's context object. rlib_file (File): The file to symlink, which must end in .rlib. - postfix (string): A postfix to append to the symlink name. Returns: The symlink's File. From 5a36d52d98267006c97396102141261403a08ac9 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 20 Jul 2021 10:53:10 +0200 Subject: [PATCH 10/10] update formatting; pass actions instead of context --- rust/private/rustc.bzl | 4 ++-- rust/private/utils.bzl | 10 +++++----- rust/toolchain.bzl | 26 ++++++++++++++++++++------ test/unit/stdlib/stdlib.bzl | 6 +++++- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 666ab235f7..abbd20f7ad 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -27,7 +27,7 @@ load( "find_cc_toolchain", "get_lib_name", "get_preferred_artifact", - "make_static_lib", + "make_static_lib_symlink", "relativize", ) @@ -636,7 +636,7 @@ def establish_cc_info(ctx, crate_info, toolchain, cc_toolchain, feature_configur # 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(ctx, crate_info.output) + dot_a = make_static_lib_symlink(ctx.actions, crate_info.output) # TODO(hlopko): handle PIC/NOPIC correctly library_to_link = cc_common.create_library_to_link( diff --git a/rust/private/utils.bzl b/rust/private/utils.bzl index 7ce5e940b0..e0591d3af1 100644 --- a/rust/private/utils.bzl +++ b/rust/private/utils.bzl @@ -297,8 +297,8 @@ def dedent(doc_string): block = " " * space_count return "\n".join([line.replace(block, "", 1).rstrip() for line in lines]) -def make_static_lib(ctx, rlib_file): - """Add a .a symlink to an .rlib file, so it can be used as a staticlib. +def make_static_lib_symlink(actions, rlib_file): + """Add a .a symlink to an .rlib file. The name of the symlink is derived from the of the .rlib file as follows: * `.a`, if starts with `lib` @@ -309,7 +309,7 @@ def make_static_lib(ctx, rlib_file): * `crateb.rlib` is `libcrateb.a`. Args: - ctx (ctx): The rule's context object. + actions (actions): The rule's context actions object. rlib_file (File): The file to symlink, which must end in .rlib. Returns: @@ -320,6 +320,6 @@ def make_static_lib(ctx, rlib_file): basename = rlib_file.basename[:-5] if not basename.startswith("lib"): basename = "lib" + basename - dot_a = ctx.actions.declare_file(basename + ".a", sibling = rlib_file) - ctx.actions.symlink(output = dot_a, target_file = rlib_file) + dot_a = actions.declare_file(basename + ".a", sibling = rlib_file) + actions.symlink(output = dot_a, target_file = rlib_file) return dot_a diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 9443fa8b01..6ba4400c74 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -1,7 +1,7 @@ """The rust_toolchain rule definition and implementation.""" load("//rust/private:common.bzl", "rust_common") -load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain", "make_static_lib") +load("//rust/private:utils.bzl", "dedent", "find_cc_toolchain", "make_static_lib_symlink") def _rust_stdlib_filegroup_impl(ctx): rust_lib = ctx.files.srcs @@ -21,7 +21,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(ctx, f) for f in std_rlibs] + dot_a_files = [make_static_lib_symlink(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] @@ -132,16 +132,30 @@ def _make_libstd_and_allocator_ccinfo(ctx, rust_lib, allocator_library): # Exclude panic_abort if panic_unwind is present. # TODO: Provide a setting to choose between panic_abort and panic_unwind. filtered_between_core_and_std_files = rust_stdlib_info.between_core_and_std_files - has_panic_unwind = [f for f in filtered_between_core_and_std_files if "panic_unwind" in f.basename] + has_panic_unwind = [ + f + for f in filtered_between_core_and_std_files + if "panic_unwind" in f.basename + ] if has_panic_unwind: - filtered_between_core_and_std_files = [f for f in filtered_between_core_and_std_files if "panic_abort" not in f.basename] + filtered_between_core_and_std_files = [ + f + for f in filtered_between_core_and_std_files + if "panic_abort" not in f.basename + ] between_core_and_std_inputs = depset( - [_ltl(f, ctx, cc_toolchain, feature_configuration) for f in filtered_between_core_and_std_files], + [ + _ltl(f, ctx, cc_toolchain, feature_configuration) + for f in filtered_between_core_and_std_files + ], transitive = [core_inputs], order = "topological", ) std_inputs = depset( - [_ltl(f, ctx, cc_toolchain, feature_configuration) for f in rust_stdlib_info.std_files], + [ + _ltl(f, ctx, cc_toolchain, feature_configuration) + for f in rust_stdlib_info.std_files + ], transitive = [between_core_and_std_inputs], order = "topological", ) diff --git a/test/unit/stdlib/stdlib.bzl b/test/unit/stdlib/stdlib.bzl index 54535c97b5..9d83190450 100644 --- a/test/unit/stdlib/stdlib.bzl +++ b/test/unit/stdlib/stdlib.bzl @@ -28,7 +28,11 @@ def _dedup_preserving_order(list): def _stdlibs(tut): """Given a target, return the list of its standard rust libraries.""" - libs = [lib.static_library for li in tut[CcInfo].linking_context.linker_inputs.to_list() for lib in li.libraries] + libs = [ + lib.static_library + for li in tut[CcInfo].linking_context.linker_inputs.to_list() + for lib in li.libraries + ] stdlibs = [lib for lib in libs if (tut.label.name not in lib.basename)] return stdlibs