Do not wrap object files in `--start-lib/--end-lib` for nodeps libraries
When linking a nodeps dynamic library that contains object files produced from tree artifact sources, the library may not contain any references to the symbols in those files. In this case, when wrapping the files in `--start-lib/--end-lib`, they may end up being dropped by the linker, which results in missing symbols compared to a build with `--dynamic_mode=off`.
This is fixed by not wrapping object files into `--start-lib/--end-lib` for the nodeps dynamic library link action.
Fixes bazelbuild/rules_cc#230
Closes #23084.
PiperOrigin-RevId: 667945814
Change-Id: Iec148ad1b86626bb5263fecc9b98b0db89f81ad6
diff --git a/src/test/shell/bazel/cc_integration_test.sh b/src/test/shell/bazel/cc_integration_test.sh
index ac8f5e6..dee00cd 100755
--- a/src/test/shell/bazel/cc_integration_test.sh
+++ b/src/test/shell/bazel/cc_integration_test.sh
@@ -1993,4 +1993,89 @@
"@@$WORKSPACE_NAME//a:a" || fail "build failed"
}
+function test_tree_artifact_sources_in_no_deps_library() {
+ mkdir -p pkg
+ cat > pkg/BUILD <<'EOF'
+load("generate.bzl", "generate_source")
+sh_binary(
+ name = "generate_tool",
+ srcs = ["generate.sh"],
+)
+
+generate_source(
+ name = "generated_source",
+ tool = ":generate_tool",
+ output_dir = "generated",
+)
+
+cc_library(
+ name = "hello_world",
+ srcs = [":generated_source"],
+ hdrs = [":generated_source"],
+)
+
+cc_test(
+ name = "testCodegen",
+ srcs = ["testCodegen.cpp"],
+ deps = [":hello_world"],
+)
+EOF
+ cat > pkg/generate.bzl <<'EOF'
+def _generate_source_impl(ctx):
+ output_dir = ctx.attr.output_dir
+ files = ctx.actions.declare_directory(output_dir)
+
+ ctx.actions.run(
+ inputs = [],
+ outputs = [files],
+ arguments = [files.path],
+ executable = ctx.executable.tool
+ )
+
+ return [
+ DefaultInfo(files = depset([files]))
+ ]
+
+
+generate_source = rule(
+ implementation = _generate_source_impl,
+ attrs = {
+ "output_dir": attr.string(),
+ "tool": attr.label(executable = True, cfg = "exec")
+ }
+)
+EOF
+ cat > pkg/generate.sh <<'EOF2'
+#!/bin/bash
+
+OUTPUT_DIR=$1
+
+cat << EOF > $OUTPUT_DIR/test.hpp
+#pragma once
+void hello_world();
+EOF
+
+
+cat << EOF > $OUTPUT_DIR/test.cpp
+#include "test.hpp"
+#include <cstdio>
+void hello_world()
+{
+ puts("Hello World!");
+}
+EOF
+EOF2
+ chmod +x pkg/generate.sh
+ cat > pkg/testCodegen.cpp <<'EOF'
+#include "pkg/generated/test.hpp"
+
+int main() {
+ hello_world();
+ return 0;
+}
+EOF
+
+ bazel build //pkg:testCodegen &> "$TEST_log" || fail "Build failed"
+}
+
run_suite "cc_integration_test"
diff --git a/tools/cpp/unix_cc_toolchain_config.bzl b/tools/cpp/unix_cc_toolchain_config.bzl
index 5a75893..dcfdea5 100644
--- a/tools/cpp/unix_cc_toolchain_config.bzl
+++ b/tools/cpp/unix_cc_toolchain_config.bzl
@@ -970,11 +970,77 @@
],
)
+ libraries_to_link_common_flag_groups = [
+ flag_group(
+ flags = ["-Wl,-whole-archive"],
+ expand_if_true =
+ "libraries_to_link.is_whole_archive",
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "static_library",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.object_files}"],
+ iterate_over = "libraries_to_link.object_files",
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file_group",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "object_file",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "interface_library",
+ ),
+ ),
+ flag_group(
+ flags = ["%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "static_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-l%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "dynamic_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-l:%{libraries_to_link.name}"],
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "versioned_dynamic_library",
+ ),
+ ),
+ flag_group(
+ flags = ["-Wl,-no-whole-archive"],
+ expand_if_true = "libraries_to_link.is_whole_archive",
+ expand_if_equal = variable_with_value(
+ name = "libraries_to_link.type",
+ value = "static_library",
+ ),
+ ),
+ ]
+
libraries_to_link_feature = feature(
name = "libraries_to_link",
flag_sets = [
flag_set(
- actions = all_link_actions + lto_index_actions,
+ actions = [
+ ACTION_NAMES.cpp_link_executable,
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ] + lto_index_actions,
flag_groups = [
flag_group(
iterate_over = "libraries_to_link",
@@ -986,66 +1052,7 @@
value = "object_file_group",
),
),
- flag_group(
- flags = ["-Wl,-whole-archive"],
- expand_if_true =
- "libraries_to_link.is_whole_archive",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "static_library",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.object_files}"],
- iterate_over = "libraries_to_link.object_files",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "interface_library",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "static_library",
- ),
- ),
- flag_group(
- flags = ["-l%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "dynamic_library",
- ),
- ),
- flag_group(
- flags = ["-l:%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "versioned_dynamic_library",
- ),
- ),
- flag_group(
- flags = ["-Wl,-no-whole-archive"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "static_library",
- ),
- ),
+ ] + libraries_to_link_common_flag_groups + [
flag_group(
flags = ["-Wl,--end-lib"],
expand_if_equal = variable_with_value(
@@ -1062,6 +1069,22 @@
),
],
),
+ # Object file groups may contain symbols that aren't referenced in the same target that
+ # produces the object files and must thus not be wrapped in --start-lib/--end-lib when
+ # linking a nodeps dynamic library.
+ flag_set(
+ actions = [ACTION_NAMES.cpp_link_nodeps_dynamic_library],
+ flag_groups = [
+ flag_group(
+ iterate_over = "libraries_to_link",
+ flag_groups = libraries_to_link_common_flag_groups,
+ ),
+ flag_group(
+ flags = ["-Wl,@%{thinlto_param_file}"],
+ expand_if_true = "thinlto_param_file",
+ ),
+ ],
+ ),
],
)