From ac55bf5afc5df708abddb4dfa0284690fdca593e Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Mon, 24 Nov 2025 20:55:03 -0500 Subject: [PATCH 1/3] Add runtime_libs as rust compile action inputs --- rust/private/rustc.bzl | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 48be035043..064de499ae 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -727,10 +727,18 @@ def collect_inputs( if linker_script: nolinkstamp_compile_direct_inputs.append(linker_script) + if crate_info.type in ["dylib", "cdylib"]: + # For shared libraries we want to link C++ runtime library dynamically + # (for example libstdc++.so or libc++.so). + runtime_libs = cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration) + else: + runtime_libs = cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration) + nolinkstamp_compile_inputs = depset( nolinkstamp_compile_direct_inputs + additional_transitive_inputs, transitive = [ + runtime_libs, linker_depset, crate_info.srcs, transitive_crate_outputs, @@ -2253,36 +2261,22 @@ def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate args.add_all(make_link_flags_args, map_each = make_link_flags) - args.add_all(linkstamp_outs, before_each = "-C", format_each = "link-args=%s") + args.add_all(linkstamp_outs, format_each = "-Clink-args=%s") if crate_type in ["dylib", "cdylib"]: # For shared libraries we want to link C++ runtime library dynamically # (for example libstdc++.so or libc++.so). - args.add_all( - cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration), - map_each = _get_dirname, - format_each = "-Lnative=%s", - ) + runtime_libs = cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration) + args.add_all(runtime_libs, map_each = _get_dirname, format_each = "-Lnative=%s") if include_link_flags: - args.add_all( - cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration), - map_each = get_lib_name, - format_each = "-ldylib=%s", - ) + args.add_all(runtime_libs, map_each = get_lib_name, format_each = "-ldylib=%s") else: # For all other crate types we want to link C++ runtime library statically # (for example libstdc++.a or libc++.a). - args.add_all( - cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), - map_each = _get_dirname, - format_each = "-Lnative=%s", - ) + runtime_libs = cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration) + args.add_all(runtime_libs, map_each = _get_dirname, format_each = "-Lnative=%s") if include_link_flags: - args.add_all( - cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration), - map_each = get_lib_name, - format_each = "-lstatic=%s", - ) + args.add_all(runtime_libs, map_each = get_lib_name, format_each = "-lstatic=%s") def _get_dirname(file): """A helper function for `_add_native_link_flags`. From fcc8d3553341ac76f05faee286161cef42ff0541 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 25 Nov 2025 15:11:19 -0500 Subject: [PATCH 2/3] Add test --- .../unit/cc_toolchain_runtime_lib/BUILD.bazel | 3 + .../cc_toolchain_runtime_lib_test.bzl | 150 ++++++++++++++++++ test/unit/cc_toolchain_runtime_lib/dummy.a | 0 test/unit/cc_toolchain_runtime_lib/dummy.so | 0 test/unit/cc_toolchain_runtime_lib/empty | 0 5 files changed, 153 insertions(+) create mode 100644 test/unit/cc_toolchain_runtime_lib/BUILD.bazel create mode 100644 test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl create mode 100644 test/unit/cc_toolchain_runtime_lib/dummy.a create mode 100644 test/unit/cc_toolchain_runtime_lib/dummy.so create mode 100644 test/unit/cc_toolchain_runtime_lib/empty diff --git a/test/unit/cc_toolchain_runtime_lib/BUILD.bazel b/test/unit/cc_toolchain_runtime_lib/BUILD.bazel new file mode 100644 index 0000000000..fd0c5d508a --- /dev/null +++ b/test/unit/cc_toolchain_runtime_lib/BUILD.bazel @@ -0,0 +1,3 @@ +load(":cc_toolchain_runtime_lib_test.bzl", "runtime_libs_test") + +runtime_libs_test(name = "runtime_libs_test") diff --git a/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl b/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl new file mode 100644 index 0000000000..6b1d3c294d --- /dev/null +++ b/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl @@ -0,0 +1,150 @@ +""" +Tests for handling of cc_toolchain's static_runtime_lib/dynamic_runtime_lib. +""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "feature") +load("@rules_cc//cc:defs.bzl", "cc_toolchain") +load("@rules_cc//cc/common:cc_common.bzl", "cc_common") +load("//rust:defs.bzl", "rust_shared_library", "rust_static_library") + +def _test_cc_config_impl(ctx): + config_info = cc_common.create_cc_toolchain_config_info( + ctx = ctx, + toolchain_identifier = "test-cc-toolchain", + host_system_name = "unknown", + target_system_name = "unknown", + target_cpu = "unknown", + target_libc = "unknown", + compiler = "unknown", + abi_version = "unknown", + abi_libc_version = "unknown", + features = [ + feature(name = "static_link_cpp_runtimes", enabled = True), + ], + ) + return config_info + +test_cc_config = rule( + implementation = _test_cc_config_impl, + provides = [CcToolchainConfigInfo], +) + +def _with_extra_toolchain_transition_impl(_settings, attr): + return {"//command_line_option:extra_toolchains": [attr.extra_toolchain]} + +with_extra_toolchain_transition = transition( + implementation = _with_extra_toolchain_transition_impl, + inputs = [], + outputs = ["//command_line_option:extra_toolchains"], +) + +DepActionsInfo = provider( + "Contains information about dependencies actions.", + fields = {"actions": "List[Action]"}, +) + +def _with_extra_toolchain_impl(ctx): + return [ + DepActionsInfo(actions = ctx.attr.target[0].actions), + ] + +with_extra_toolchain = rule( + implementation = _with_extra_toolchain_impl, + attrs = { + "extra_toolchain": attr.label(), + "target": attr.label(cfg = with_extra_toolchain_transition), + }, +) + +def _inputs_analysis_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + action = tut[DepActionsInfo].actions[0] + inputs = action.inputs.to_list() + for expected in ctx.attr.expected_inputs: + asserts.true( + env, + any([input.path.endswith("/" + expected) for input in inputs]), + "error: expected '{}' to be in inputs: '{}'".format(expected, inputs), + ) + + return analysistest.end(env) + +inputs_analysis_test = analysistest.make( + impl = _inputs_analysis_test_impl, + doc = """An analysistest to examine the inputs of a library target.""", + attrs = { + "expected_inputs": attr.string_list(), + }, +) + +def runtime_libs_test(name): + """Produces test shared and static library targets that are set up to use a custom cc_toolchain with custom runtime libs. + + Args: + name: The name of the test target. + """ + + test_cc_config( + name = "%s/cc_toolchain_config" % name, + ) + cc_toolchain( + name = "%s/test_cc_toolchain_impl" % name, + all_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":%s/cc_toolchain_config" % name, + toolchain_identifier = "dummy_wasm32_cc", + static_runtime_lib = ":dummy.a", + dynamic_runtime_lib = ":dummy.so", + ) + native.toolchain( + name = "%s/test_cc_toolchain" % name, + toolchain = ":%s/test_cc_toolchain_impl" % name, + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", + ) + + rust_shared_library( + name = "%s/__shared_library" % name, + edition = "2018", + srcs = ["lib.rs"], + tags = ["manual", "nobuild"], + ) + + with_extra_toolchain( + name = "%s/_shared_library" % name, + extra_toolchain = ":%s/test_cc_toolchain" % name, + target = "%s/__shared_library" % name, + tags = ["manual"], + ) + + inputs_analysis_test( + name = "%s/shared_library" % name, + target_under_test = "%s/_shared_library" % name, + expected_inputs = ["dummy.so"], + ) + + rust_static_library( + name = "%s/__static_library" % name, + edition = "2018", + srcs = ["lib.rs"], + tags = ["manual", "nobuild"], + ) + + with_extra_toolchain( + name = "%s/_static_library" % name, + extra_toolchain = ":%s/test_cc_toolchain" % name, + target = "%s/__static_library" % name, + tags = ["manual"], + ) + + inputs_analysis_test( + name = "%s/static_library" % name, + target_under_test = "%s/_static_library" % name, + expected_inputs = ["dummy.a"], + ) diff --git a/test/unit/cc_toolchain_runtime_lib/dummy.a b/test/unit/cc_toolchain_runtime_lib/dummy.a new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/unit/cc_toolchain_runtime_lib/dummy.so b/test/unit/cc_toolchain_runtime_lib/dummy.so new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/unit/cc_toolchain_runtime_lib/empty b/test/unit/cc_toolchain_runtime_lib/empty new file mode 100644 index 0000000000..e69de29bb2 From deb6664bea82aadcdd797fe8608187f87baa0f16 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 25 Nov 2025 15:40:45 -0500 Subject: [PATCH 3/3] mnemonic --- .../cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl b/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl index 6b1d3c294d..ff804cb03e 100644 --- a/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl +++ b/test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl @@ -3,7 +3,7 @@ Tests for handling of cc_toolchain's static_runtime_lib/dynamic_runtime_lib. """ load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") -load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "feature") +load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "feature") load("@rules_cc//cc:defs.bzl", "cc_toolchain") load("@rules_cc//cc/common:cc_common.bzl", "cc_common") load("//rust:defs.bzl", "rust_shared_library", "rust_static_library") @@ -61,6 +61,7 @@ def _inputs_analysis_test_impl(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) action = tut[DepActionsInfo].actions[0] + asserts.equals(env, action.mnemonic, "Rustc") inputs = action.inputs.to_list() for expected in ctx.attr.expected_inputs: asserts.true(