Add -install_name when linking shared libraries on macOS
This change exposes the name of the solib symlink available at runtime
to link actions and uses that name to set the `-install_name` of shared
libraries on macOS. Exposing the runtime solib name to link actions
allows us to remove the need for the cc_wrapper script that patched the
binary on macOS (which relied on the fact that the runtime solibs are
symlinks locally, which is not true in all cases).
Updates #7415
Closes #12304.
PiperOrigin-RevId: 342033474
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
index 3ee5e21..8e8dd9c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
@@ -302,6 +302,7 @@
isUsingLinkerNotArchiver,
/* binDirectoryPath= */ null,
convertFromNoneable(outputFile, /* defaultValue= */ null),
+ /* runtimeSolibName= */ null,
isCreatingSharedLibrary,
convertFromNoneable(paramFile, /* defaultValue= */ null),
/* thinltoParamFile= */ null,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index f42bfeb..91bd2ee 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -753,4 +753,9 @@
public boolean generateLlvmLCov() {
return cppOptions.generateLlvmLcov;
}
+
+ @Override
+ public boolean macosSetInstallName() {
+ return cppOptions.macosSetInstallName;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index 289d7f7..4c76509 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -872,6 +872,8 @@
getLinkType().linkerOrArchiver().equals(LinkerOrArchiver.LINKER),
configuration.getBinDirectory(repositoryName).getExecPath(),
output.getExecPathString(),
+ SolibSymlinkAction.getDynamicLibrarySoname(
+ output.getRootRelativePath(), /* preserveName= */ false),
linkType.equals(LinkTargetType.DYNAMIC_LIBRARY),
paramFile != null ? paramFile.getExecPathString() : null,
thinltoParamFile != null ? thinltoParamFile.getExecPathString() : null,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
index 5233e77..c0e9073 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java
@@ -1036,6 +1036,20 @@
help = "If enabled, give distinguishing mnemonic to header processing actions")
public boolean useCppCompileHeaderMnemonic;
+ @Option(
+ name = "incompatible_macos_set_install_name",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
+ effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
+ metadataTags = {
+ OptionMetadataTag.INCOMPATIBLE_CHANGE,
+ OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES
+ },
+ help =
+ "Whether to explicitly set `-install_name` when creating dynamic libraries. "
+ + "See https://github.com/bazelbuild/bazel/issues/12370")
+ public boolean macosSetInstallName;
+
/** See {@link #targetLibcTopLabel} documentation. * */
@Override
public FragmentOptions getNormalized() {
@@ -1124,6 +1138,8 @@
host.experimentalStarlarkCcImport = experimentalStarlarkCcImport;
+ host.macosSetInstallName = macosSetInstallName;
+
return host;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java
index 8180a32..8477ece 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariables.java
@@ -82,7 +82,9 @@
/** Path to the context sensitive fdo instrument. */
CS_FDO_INSTRUMENT_PATH("cs_fdo_instrument_path"),
/** Path to the Propeller Optimize linker profile artifact */
- PROPELLER_OPTIMIZE_LD_PATH("propeller_optimize_ld_path");
+ PROPELLER_OPTIMIZE_LD_PATH("propeller_optimize_ld_path"),
+ /** The name of the runtime solib symlink of the shared library. */
+ RUNTIME_SOLIB_NAME("runtime_solib_name");
private final String variableName;
@@ -98,6 +100,7 @@
boolean isUsingLinkerNotArchiver,
PathFragment binDirectoryPath,
String outputFile,
+ String runtimeSolibName,
boolean isCreatingSharedLibrary,
String paramFile,
String thinltoParamFile,
@@ -166,6 +169,10 @@
buildVariables.addStringVariable(OUTPUT_EXECPATH.getVariableName(), outputFile);
}
+ if (runtimeSolibName != null && !isLtoIndexing) {
+ buildVariables.addStringVariable(RUNTIME_SOLIB_NAME.getVariableName(), runtimeSolibName);
+ }
+
if (isLtoIndexing) {
if (thinltoParamFile != null) {
// This is a lto-indexing action and we want it to populate param file.
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CppConfigurationApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CppConfigurationApi.java
index bf65a92..32f11dd 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CppConfigurationApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CppConfigurationApi.java
@@ -77,4 +77,12 @@
+ " )<br/>"
+ ")</pre>")
Label customMalloc();
+
+ @StarlarkMethod(
+ name = "do_not_use_macos_set_install_name",
+ structField = true,
+ // Only for migration purposes. Intentionally not documented.
+ documented = false,
+ doc = "Accessor for <code>--incompatible_macos_set_install_name</code>.")
+ boolean macosSetInstallName();
}
diff --git a/src/test/shell/bazel/cpp_darwin_integration_test.sh b/src/test/shell/bazel/cpp_darwin_integration_test.sh
index c9f0f71..e26d2a9 100755
--- a/src/test/shell/bazel/cpp_darwin_integration_test.sh
+++ b/src/test/shell/bazel/cpp_darwin_integration_test.sh
@@ -123,5 +123,42 @@
return 0
}
+function test_cc_test_with_explicit_install_name() {
+ mkdir -p cpp
+ cat > cpp/BUILD <<EOF
+cc_library(
+ name = "foo",
+ srcs = ["foo.cc"],
+ hdrs = ["foo.h"],
+)
+cc_test(
+ name = "test",
+ srcs = ["test.cc"],
+ deps = [":foo"],
+)
+EOF
+ cat > cpp/foo.h <<EOF
+ int foo();
+EOF
+ cat > cpp/foo.cc <<EOF
+ int foo() { return 0; }
+EOF
+ cat > cpp/test.cc <<EOF
+ #include "cpp/foo.h"
+ int main() {
+ return foo();
+ }
+EOF
+
+ bazel test --incompatible_macos_set_install_name //cpp:test || \
+ fail "bazel test //cpp:test failed"
+ # Ensure @rpath is correctly set in the binary.
+ ./bazel-bin/cpp/test || \
+ fail "//cpp:test workspace execution failed, expected return 0, got $?"
+ cd bazel-bin
+ ./cpp/test || \
+ fail "//cpp:test execution failed, expected 0, but $?"
+}
+
run_suite "Tests for Bazel's C++ rules on Darwin"
diff --git a/tools/osx/crosstool/cc_toolchain_config.bzl b/tools/osx/crosstool/cc_toolchain_config.bzl
index d222c75..3bd3c4b 100644
--- a/tools/osx/crosstool/cc_toolchain_config.bzl
+++ b/tools/osx/crosstool/cc_toolchain_config.bzl
@@ -6061,6 +6061,27 @@
],
)
+ set_install_name = feature(
+ name = "set_install_name",
+ enabled = ctx.fragments.cpp.do_not_use_macos_set_install_name,
+ flag_sets = [
+ flag_set(
+ actions = [
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+ ],
+ flag_groups = [
+ flag_group(
+ flags = [
+ "-Wl,-install_name,@rpath/%{runtime_solib_name}",
+ ],
+ expand_if_available = "runtime_solib_name",
+ ),
+ ],
+ ),
+ ],
+ )
+
if (ctx.attr.cpu == "ios_arm64" or
ctx.attr.cpu == "ios_arm64e" or
ctx.attr.cpu == "ios_armv7" or
@@ -6145,6 +6166,7 @@
compiler_input_flags_feature,
compiler_output_flags_feature,
objcopy_embed_flags_feature,
+ set_install_name,
]
elif (ctx.attr.cpu == "darwin_x86_64" or
ctx.attr.cpu == "darwin_arm64" or
@@ -6224,6 +6246,7 @@
supports_dynamic_linker_feature,
objcopy_embed_flags_feature,
dynamic_linking_mode_feature,
+ set_install_name,
]
elif (ctx.attr.cpu == "armeabi-v7a"):
features = [
@@ -6300,6 +6323,7 @@
compiler_output_flags_feature,
supports_pic_feature,
objcopy_embed_flags_feature,
+ set_install_name,
]
else:
fail("Unreachable")
@@ -6402,4 +6426,5 @@
},
provides = [CcToolchainConfigInfo],
executable = True,
+ fragments = ["cpp"],
)