diff options
author | 2017-01-26 18:21:33 +0000 | |
---|---|---|
committer | 2017-01-26 23:01:54 +0000 | |
commit | e2239cc61ca170ff9a65e1a94c3344d2b272c9e2 (patch) | |
tree | 62ea257ec8447dc07ba51a592cb629e05137b111 /src/main/java/com/google/devtools/build/lib/rules/cpp | |
parent | cd5c691eec541e228fb35884378d74ad4f062d92 (diff) |
Expose rpath entries as a build variable
--
PiperOrigin-RevId: 145688972
MOS_MIGRATED_REVID=145688972
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/cpp')
3 files changed, 157 insertions, 169 deletions
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 64f1db9375..91f05b5022 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 @@ -409,12 +409,12 @@ public class CppConfiguration extends BuildConfiguration.Fragment { this.toolchainIdentifier = toolchain.getToolchainIdentifier(); + this.supportsEmbeddedRuntimes = toolchain.getSupportsEmbeddedRuntimes(); toolchain = addLegacyFeatures(toolchain); this.toolchainFeatures = new CcToolchainFeatures(toolchain); this.supportsGoldLinker = toolchain.getSupportsGoldLinker(); this.supportsStartEndLib = toolchain.getSupportsStartEndLib(); this.supportsInterfaceSharedObjects = toolchain.getSupportsInterfaceSharedObjects(); - this.supportsEmbeddedRuntimes = toolchain.getSupportsEmbeddedRuntimes(); this.supportsFission = toolchain.getSupportsFission(); this.toolchainNeedsPic = toolchain.getNeedsPic(); this.usePicForBinaries = @@ -733,12 +733,12 @@ public class CppConfiguration extends BuildConfiguration.Fragment { if (getTargetLibc().equals("macosx")) { TextFormat.merge( CppLinkActionConfigs.getCppLinkActionConfigs( - CppLinkPlatform.MAC, features, linkerToolPath), + CppLinkPlatform.MAC, features, linkerToolPath, supportsEmbeddedRuntimes), toolchainBuilder); } else { TextFormat.merge( CppLinkActionConfigs.getCppLinkActionConfigs( - CppLinkPlatform.LINUX, features, linkerToolPath), + CppLinkPlatform.LINUX, features, linkerToolPath, supportsEmbeddedRuntimes), toolchainBuilder); } } 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 f99191da6b..f02dea8e87 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 @@ -21,6 +21,7 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.ActionOwner; @@ -63,17 +64,9 @@ import javax.annotation.Nullable; /** Builder class to construct {@link CppLinkAction}s. */ public class CppLinkActionBuilder { - /** A build variable for clang flags that set the root of the linker search path. */ - public static final String RUNTIME_ROOT_FLAGS_VARIABLE = "runtime_root_flags"; - - /** A build variable for entries in the linker search path. */ - public static final String RUNTIME_ROOT_ENTRIES_VARIABLE = "runtime_root_entries"; - - /** - * A build variable for options applying to specific libraries in the linker invocation that - * either identify a library to be linked or add a directory to the runtime library search path. - */ - public static final String LIBOPTS_VARIABLE = "libopts"; + /** A build variable for entries in the linker runtime search path (usually set by -rpath flag) */ + public static final String RUNTIME_LIBRARY_SEARCH_DIRECTORIES_VARIABLE = + "runtime_library_search_directories"; public static final String LIBRARY_SEARCH_DIRECTORIES_VARIABLE = "library_search_directories"; @@ -134,6 +127,12 @@ public class CppLinkActionBuilder { /** A build variable whose presence indicates that this action is a cc_test linking action. */ public static final String IS_CC_TEST_LINK_ACTION_VARIABLE = "is_cc_test_link_action"; + /** + * A (temporary) build variable whose presence indicates that this action is not a cc_test linking + * action. + */ + public static final String IS_NOT_CC_TEST_LINK_ACTION_VARIABLE = "is_not_cc_test_link_action"; + // Builder-only // Null when invoked from tests (e.g. via createTestBuilder). @Nullable private final RuleContext ruleContext; @@ -1197,22 +1196,13 @@ public class CppLinkActionBuilder { } private static class LinkArgCollector { - String rpathRoot; - ImmutableList<String> rpathEntries; - ImmutableSet<String> libopts; + ImmutableSet<String> runtimeLibrarySearchDirectories; ImmutableSet<String> librarySearchDirectories; SequenceBuilder librariesToLink; - public void setRpathRoot(String rPathRoot) { - this.rpathRoot = rPathRoot; - } - - public void setRpathEntries(ImmutableList<String> rpathEntries) { - this.rpathEntries = rpathEntries; - } - - public void setLibopts(ImmutableSet<String> libopts) { - this.libopts = libopts; + public void setRuntimeLibrarySearchDirectories( + ImmutableSet<String> runtimeLibrarySearchDirectories) { + this.runtimeLibrarySearchDirectories = runtimeLibrarySearchDirectories; } public void setLibrariesToLink(SequenceBuilder librariesToLink) { @@ -1223,16 +1213,8 @@ public class CppLinkActionBuilder { this.librarySearchDirectories = librarySearchDirectories; } - public String getRpathRoot() { - return rpathRoot; - } - - public ImmutableList<String> getRpathEntries() { - return rpathEntries; - } - - public ImmutableSet<String> getLibopts() { - return libopts; + public ImmutableSet<String> getRuntimeLibrarySearchDirectories() { + return runtimeLibrarySearchDirectories; } public SequenceBuilder getLibrariesToLink() { @@ -1314,21 +1296,16 @@ public class CppLinkActionBuilder { if (useTestOnlyFlags()) { buildVariables.addStringVariable(IS_CC_TEST_LINK_ACTION_VARIABLE, ""); + } else { + buildVariables.addStringVariable(IS_NOT_CC_TEST_LINK_ACTION_VARIABLE, ""); } - // rpath - if (linkArgCollector.getRpathRoot() != null) { - buildVariables.addStringVariable( - RUNTIME_ROOT_FLAGS_VARIABLE, linkArgCollector.getRpathRoot()); - } - - if (linkArgCollector.getRpathEntries() != null) { + if (linkArgCollector.getRuntimeLibrarySearchDirectories() != null) { buildVariables.addStringSequenceVariable( - RUNTIME_ROOT_ENTRIES_VARIABLE, linkArgCollector.getRpathEntries()); + RUNTIME_LIBRARY_SEARCH_DIRECTORIES_VARIABLE, + linkArgCollector.getRuntimeLibrarySearchDirectories()); } - buildVariables.addStringSequenceVariable(LIBOPTS_VARIABLE, linkArgCollector.getLibopts()); - buildVariables.addCustomBuiltVariable( LIBRARIES_TO_LINK_VARIABLE, linkArgCollector.getLibrariesToLink()); @@ -1416,10 +1393,9 @@ public class CppLinkActionBuilder { * <p>TODO: Factor out of the bazel binary into build variables for crosstool action_configs. */ private void addInputFileLinkOptions(LinkArgCollector linkArgCollector) { - - // Used to collect -L and -Wl,-rpath options, ensuring that each used only once. - ImmutableSet.Builder<String> libOpts = ImmutableSet.builder(); ImmutableSet.Builder<String> librarySearchDirectories = ImmutableSet.builder(); + ImmutableSet.Builder<String> runtimeRpathRoots = ImmutableSet.builder(); + ImmutableSet.Builder<String> rpathRootsForExplicitSoDeps = ImmutableSet.builder(); // List of command line parameters that need to be placed *outside* of // --whole-archive ... --no-whole-archive. @@ -1437,14 +1413,9 @@ public class CppLinkActionBuilder { || (linkType == LinkTargetType.EXECUTABLE && linkStaticness == LinkStaticness.DYNAMIC)); - ImmutableList.Builder<String> runtimeRpathEntries = ImmutableList.builder(); - - String origin = - useTestOnlyFlags && cppConfiguration.supportsExecOrigin() - ? "$EXEC_ORIGIN/" - : "$ORIGIN/"; if (runtimeRpath) { - runtimeRpathEntries.add("-Wl,-rpath," + origin + runtimeSolibName + "/"); + runtimeRpathRoots.add("."); + runtimeRpathRoots.add(runtimeSolibName + "/"); } String rpathRoot; @@ -1462,10 +1433,9 @@ public class CppLinkActionBuilder { // and the second could use $ORIGIN/../_solib_[arch]. But since this is a shared // artifact, both are symlinks to the same place, so // there's no *one* RPATH setting that fits all targets involved in the sharing. - rpathRoot = - "-Wl,-rpath," + origin + ":" + origin + cppConfiguration.getSolibDirectory() + "/"; + rpathRoot = cppConfiguration.getSolibDirectory() + "/"; if (runtimeRpath) { - runtimeRpathEntries.add("-Wl,-rpath," + origin + "../" + runtimeSolibName + "/"); + runtimeRpathRoots.add("../" + runtimeSolibName + "/"); } } else { // For all other links, calculate the relative path from the output file to _solib_[arch] @@ -1473,18 +1443,14 @@ public class CppLinkActionBuilder { // directory. In other words, given blaze-bin/my/package/binary, rpathRoot would be // "../../_solib_[arch]". if (runtimeRpath) { - runtimeRpathEntries.add( - "-Wl,-rpath," - + origin - + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1) + runtimeRpathRoots.add( + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1) + runtimeSolibName + "/"); } rpathRoot = - "-Wl,-rpath," - + origin - + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1) + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1) + cppConfiguration.getSolibDirectory() + "/"; @@ -1492,89 +1458,130 @@ public class CppLinkActionBuilder { // We also retain the $ORIGIN/ path to solibs that are in _solib_<arch>, as opposed to // the package directory) if (runtimeRpath) { - runtimeRpathEntries.add("-Wl,-rpath," + origin + "../" + runtimeSolibName + "/"); + runtimeRpathRoots.add("../" + runtimeSolibName + "/"); } - rpathRoot += ":" + origin; } } - boolean includeSolibDir = false; + Map<Artifact, Artifact> ltoMap = generateLtoMap(); + boolean includeSolibDir = + addLinkerInputs( + librarySearchDirectories, + rpathRootsForExplicitSoDeps, + librariesToLink, + solibDir, + rpathRoot, + ltoMap); + boolean includeRuntimeSolibDir = + addRuntimeLinkerInputs( + librarySearchDirectories, + rpathRootsForExplicitSoDeps, + librariesToLink, + solibDir, + rpathRoot, + ltoMap); + Preconditions.checkState( + ltoMap == null || ltoMap.isEmpty(), "Still have LTO objects left: %s", ltoMap); - Map<Artifact, Artifact> ltoMap = null; - if (!isLTOIndexing && (allLTOArtifacts != null)) { - // TODO(bazel-team): The LTO final link can only work if there are individual .o files on - // the command line. Rather than crashing, this should issue a nice error. We will get - // this by - // 1) moving supports_start_end_lib to a toolchain feature - // 2) having thin_lto require start_end_lib - // As a bonus, we can rephrase --nostart_end_lib as --features=-start_end_lib and get rid - // of a command line option. - - Preconditions.checkState(cppConfiguration.useStartEndLib()); - ltoMap = new HashMap<>(); - for (LTOBackendArtifacts l : allLTOArtifacts) { - ltoMap.put(l.getBitcodeFile(), l.getObjectFile()); - } + ImmutableSet.Builder<String> runtimeLibrarySearchDirectories = ImmutableSet.builder(); + // rpath ordering matters for performance; first add the one where most libraries are found. + if (includeSolibDir) { + runtimeLibrarySearchDirectories.add(rpathRoot); + } + runtimeLibrarySearchDirectories.addAll(rpathRootsForExplicitSoDeps.build()); + if (includeRuntimeSolibDir) { + runtimeLibrarySearchDirectories.addAll(runtimeRpathRoots.build()); } - for (LinkerInput input : linkerInputs) { + linkArgCollector.setLibrarySearchDirectories(librarySearchDirectories.build()); + linkArgCollector.setRuntimeLibrarySearchDirectories(runtimeLibrarySearchDirectories.build()); + linkArgCollector.setLibrariesToLink(librariesToLink); + } + + private Map<Artifact, Artifact> generateLtoMap() { + if (isLTOIndexing || allLTOArtifacts == null) { + return null; + } + // TODO(bazel-team): The LTO final link can only work if there are individual .o files on + // the command line. Rather than crashing, this should issue a nice error. We will get + // this by + // 1) moving supports_start_end_lib to a toolchain feature + // 2) having thin_lto require start_end_lib + // As a bonus, we can rephrase --nostart_end_lib as --features=-start_end_lib and get rid + // of a command line option. + + Preconditions.checkState(cppConfiguration.useStartEndLib()); + Map<Artifact, Artifact> ltoMap = new HashMap<>(); + for (LTOBackendArtifacts l : allLTOArtifacts) { + ltoMap.put(l.getBitcodeFile(), l.getObjectFile()); + } + return ltoMap; + } + + private boolean addRuntimeLinkerInputs( + Builder<String> librarySearchDirectories, + Builder<String> rpathRootsForExplicitSoDeps, + SequenceBuilder librariesToLink, + PathFragment solibDir, + String rpathRoot, + Map<Artifact, Artifact> ltoMap) { + boolean includeRuntimeSolibDir = false; + for (LinkerInput input : runtimeLinkerInputs) { if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY) { PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory(); Preconditions.checkState( - libDir.startsWith(solibDir), + runtimeSolibDir != null && libDir.equals(runtimeSolibDir), "Artifact '%s' is not under directory '%s'.", input.getArtifact(), solibDir); - if (libDir.equals(solibDir)) { - includeSolibDir = true; - } + includeRuntimeSolibDir = true; addDynamicInputLinkOptions( input, librariesToLink, - false, - libOpts, + true, librarySearchDirectories, + rpathRootsForExplicitSoDeps, solibDir, rpathRoot); } else { - addStaticInputLinkOptions(input, librariesToLink, false, ltoMap); + addStaticInputLinkOptions(input, librariesToLink, true, ltoMap); } } + return includeRuntimeSolibDir; + } - boolean includeRuntimeSolibDir = false; - - for (LinkerInput input : runtimeLinkerInputs) { + private boolean addLinkerInputs( + Builder<String> librarySearchDirectories, + Builder<String> rpathEntries, + SequenceBuilder librariesToLink, + PathFragment solibDir, + String rpathRoot, + Map<Artifact, Artifact> ltoMap) { + boolean includeSolibDir = false; + for (LinkerInput input : linkerInputs) { if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY) { PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory(); Preconditions.checkState( - runtimeSolibDir != null && libDir.equals(runtimeSolibDir), + libDir.startsWith(solibDir), "Artifact '%s' is not under directory '%s'.", input.getArtifact(), solibDir); - includeRuntimeSolibDir = true; + if (libDir.equals(solibDir)) { + includeSolibDir = true; + } addDynamicInputLinkOptions( - input, librariesToLink, true, libOpts, librarySearchDirectories, solibDir, rpathRoot); + input, + librariesToLink, + false, + librarySearchDirectories, + rpathEntries, + solibDir, + rpathRoot); } else { - addStaticInputLinkOptions(input, librariesToLink, true, ltoMap); + addStaticInputLinkOptions(input, librariesToLink, false, ltoMap); } } - - // rpath ordering matters for performance; first add the one where most libraries are found. - if (includeSolibDir) { - linkArgCollector.setRpathRoot(rpathRoot); - } - if (includeRuntimeSolibDir) { - linkArgCollector.setRpathEntries(runtimeRpathEntries.build()); - } - - linkArgCollector.setLibopts(libOpts.build()); - linkArgCollector.setLibrarySearchDirectories(librarySearchDirectories.build()); - - linkArgCollector.setLibrariesToLink(librariesToLink); - - if (ltoMap != null) { - Preconditions.checkState(ltoMap.isEmpty(), "Still have LTO objects left: %s", ltoMap); - } + return includeSolibDir; } /** @@ -1586,8 +1593,8 @@ public class CppLinkActionBuilder { LinkerInput input, SequenceBuilder librariesToLink, boolean isRuntimeLinkerInput, - ImmutableSet.Builder<String> libOpts, ImmutableSet.Builder<String> librarySearchDirectories, + ImmutableSet.Builder<String> rpathRootsForExplicitSoDeps, PathFragment solibDir, String rpathRoot) { Preconditions.checkState(input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY); @@ -1604,7 +1611,8 @@ public class CppLinkActionBuilder { commonParent = commonParent.getParentDirectory(); } - libOpts.add(rpathRoot + dotdots + libDir.relativeTo(commonParent).getPathString()); + rpathRootsForExplicitSoDeps.add( + rpathRoot + dotdots + libDir.relativeTo(commonParent).getPathString()); } librarySearchDirectories.add( diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionConfigs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionConfigs.java index d614c3d063..9cb308f4e6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionConfigs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionConfigs.java @@ -32,7 +32,10 @@ public class CppLinkActionConfigs { } public static String getCppLinkActionConfigs( - CppLinkPlatform platform, Set<String> features, String cppLinkDynamicLibraryToolPath) { + CppLinkPlatform platform, + Set<String> features, + String cppLinkDynamicLibraryToolPath, + boolean supportsEmbeddedRuntimes) { String cppDynamicLibraryLinkerTool = ""; if (!features.contains("dynamic_library_linker_tool")) { cppDynamicLibraryLinkerTool = @@ -62,9 +65,8 @@ public class CppLinkActionConfigs { " implies: 'symbol_counts'", " implies: 'linkstamps'", " implies: 'output_execpath_flags_executable'", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'force_pic_flags'", " implies: 'legacy_link_flags'", @@ -82,9 +84,8 @@ public class CppLinkActionConfigs { " implies: 'shared_flag'", " implies: 'linkstamps'", " implies: 'output_execpath_flags'", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'legacy_link_flags'", " implies: 'linker_param_file'", @@ -95,9 +96,8 @@ public class CppLinkActionConfigs { " tool {", " tool_path: 'DUMMY_TOOL'", " }", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'linker_param_file'", "}", @@ -107,9 +107,8 @@ public class CppLinkActionConfigs { " tool {", " tool_path: 'DUMMY_TOOL'", " }", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'linker_param_file'", "}", @@ -119,9 +118,8 @@ public class CppLinkActionConfigs { " tool {", " tool_path: 'DUMMY_TOOL'", " }", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'linker_param_file'", "}", @@ -131,9 +129,8 @@ public class CppLinkActionConfigs { " tool {", " tool_path: 'DUMMY_TOOL'", " }", - " implies: 'runtime_root_flags'", + " implies: 'runtime_library_search_directories'", " implies: 'library_search_directories'", - " implies: 'input_param_flags'", " implies: 'libraries_to_link'", " implies: 'linker_param_file'", "}", @@ -223,9 +220,9 @@ public class CppLinkActionConfigs { " }", "}", "feature {", - " name: 'runtime_root_flags',", + " name: 'runtime_library_search_directories',", " flag_set {", - " expand_if_all_available: 'runtime_root_flags'", + " expand_if_all_available: 'runtime_library_search_directories'", " action: 'c++-link-executable'", " action: 'c++-link-dynamic-library'", " action: 'c++-link-static-library'", @@ -233,19 +230,18 @@ public class CppLinkActionConfigs { " action: 'c++-link-pic-static-library'", " action: 'c++-link-alwayslink-pic-static-library'", " flag_group {", - " flag: '%{runtime_root_flags}'", - " }", - " }", - " flag_set {", - " expand_if_all_available: 'runtime_root_entries'", - " action: 'c++-link-executable'", - " action: 'c++-link-dynamic-library'", - " action: 'c++-link-static-library'", - " action: 'c++-link-alwayslink-static-library'", - " action: 'c++-link-pic-static-library'", - " action: 'c++-link-alwayslink-pic-static-library'", - " flag_group {", - " flag: '%{runtime_root_entries}'", + " iterate_over: 'runtime_library_search_directories'", + " flag_group {", + ifTrue( + supportsEmbeddedRuntimes, + " expand_if_all_available: 'is_cc_test_link_action'", + " flag: ", + " '-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}'", + " }", + " flag_group {", + " expand_if_all_available: 'is_not_cc_test_link_action'"), + " flag: '-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}'", + " }", " }", " }", "}", @@ -266,22 +262,6 @@ public class CppLinkActionConfigs { " }", "}", "feature {", - " name: 'input_param_flags'", - " flag_set {", - " expand_if_all_available: 'libopts'", - " action: 'c++-link-executable'", - " action: 'c++-link-dynamic-library'", - " action: 'c++-link-static-library'", - " action: 'c++-link-alwayslink-static-library'", - " action: 'c++-link-pic-static-library'", - " action: 'c++-link-alwayslink-pic-static-library'", - " flag_group {", - " iterate_over: 'libopts'", - " flag: '%{libopts}'", - " }", - " }", - "}", - "feature {", " name: 'libraries_to_link'", " flag_set {", " expand_if_all_available: 'libraries_to_link'", @@ -500,15 +480,15 @@ public class CppLinkActionConfigs { } private static String ifLinux(CppLinkPlatform platform, String... lines) { - if (platform == CppLinkPlatform.LINUX) { - return Joiner.on("\n").join(lines); - } else { - return ""; - } + return ifTrue(platform == CppLinkPlatform.LINUX, lines); } private static String ifMac(CppLinkPlatform platform, String... lines) { - if (platform == CppLinkPlatform.MAC) { + return ifTrue(platform == CppLinkPlatform.MAC, lines); + } + + private static String ifTrue(boolean condition, String... lines) { + if (condition) { return Joiner.on("\n").join(lines); } else { return ""; |