| // Copyright 2014 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package com.google.devtools.build.lib.rules.cpp; |
| |
| import com.google.common.collect.Iterables; |
| import com.google.devtools.build.lib.actions.ActionInput; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
| import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; |
| import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.SequenceBuilder; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| |
| /** Enum covering all build variables we create for all various {@link CppLinkAction}. */ |
| public enum LinkBuildVariables { |
| /** Entries in the linker runtime search path (usually set by -rpath flag) */ |
| RUNTIME_LIBRARY_SEARCH_DIRECTORIES("runtime_library_search_directories"), |
| /** Entries in the linker search path (usually set by -L flag) */ |
| LIBRARY_SEARCH_DIRECTORIES("library_search_directories"), |
| /** Flags providing files to link as inputs in the linker invocation */ |
| LIBRARIES_TO_LINK("libraries_to_link"), |
| /** Thinlto param file produced by thinlto-indexing action consumed by the final link action. */ |
| THINLTO_PARAM_FILE("thinlto_param_file"), |
| /** Location of def file used on Windows with MSVC */ |
| DEF_FILE_PATH("def_file_path"), |
| /** Location where hinlto should write thinlto_param_file flags when indexing. */ |
| THINLTO_INDEXING_PARAM_FILE("thinlto_indexing_param_file"), |
| |
| THINLTO_PREFIX_REPLACE("thinlto_prefix_replace"), |
| /** |
| * A build variable to let the LTO indexing step know how to map from the minimized bitcode file |
| * to the full bitcode file used by the LTO Backends. |
| */ |
| THINLTO_OBJECT_SUFFIX_REPLACE("thinlto_object_suffix_replace"), |
| /** |
| * A build variable for the path to the merged object file, which is an object file that is |
| * created during the LTO indexing step and needs to be passed to the final link. |
| */ |
| THINLTO_MERGED_OBJECT_FILE("thinlto_merged_object_file"), |
| /** Location of linker param file created by bazel to overcome command line length limit */ |
| LINKER_PARAM_FILE("linker_param_file"), |
| /** execpath of the output of the linker. */ |
| OUTPUT_EXECPATH("output_execpath"), |
| /** "yes"|"no" depending on whether interface library should be generated. */ |
| GENERATE_INTERFACE_LIBRARY("generate_interface_library"), |
| /** Path to the interface library builder tool. */ |
| INTERFACE_LIBRARY_BUILDER("interface_library_builder_path"), |
| /** Input for the interface library ifso builder tool. */ |
| INTERFACE_LIBRARY_INPUT("interface_library_input_path"), |
| /** Path where to generate interface library using the ifso builder tool. */ |
| INTERFACE_LIBRARY_OUTPUT("interface_library_output_path"), |
| /** Linker flags coming from the legacy crosstool fields. */ |
| LEGACY_LINK_FLAGS("legacy_link_flags"), |
| /** Path to which to write symbol counts. */ |
| SYMBOL_COUNTS_OUTPUT("symbol_counts_output"), |
| /** A build variable giving linkstamp paths. */ |
| LINKSTAMP_PATHS("linkstamp_paths"), |
| /** Presence of this variable indicates that PIC code should be generated. */ |
| FORCE_PIC("force_pic"), |
| /** Presence of this variable indicates that the debug symbols should be stripped. */ |
| STRIP_DEBUG_SYMBOLS("strip_debug_symbols"), |
| @Deprecated |
| IS_CC_TEST_LINK_ACTION("is_cc_test_link_action"), |
| @Deprecated |
| IS_NOT_CC_TEST_LINK_ACTION("is_not_cc_test_link_action"), |
| /** Truthy when current action is a cc_test linking action, falsey otherwise. */ |
| IS_CC_TEST("is_cc_test"), |
| /** |
| * Presence of this variable indicates that files were compiled with fission (debug info is in |
| * .dwo files instead of .o files and linker needs to know). |
| */ |
| IS_USING_FISSION("is_using_fission"); |
| |
| private final String variableName; |
| |
| LinkBuildVariables(String variableName) { |
| this.variableName = variableName; |
| } |
| |
| public String getVariableName() { |
| return variableName; |
| } |
| |
| public static CcToolchainVariables setupVariables( |
| boolean isUsingLinkerNotArchiver, |
| BuildConfiguration configuration, |
| Artifact outputArtifact, |
| Artifact paramFile, |
| Artifact thinltoParamFile, |
| Artifact thinltoMergedObjectFile, |
| boolean mustKeepDebug, |
| Artifact symbolCounts, |
| CcToolchainProvider ccToolchainProvider, |
| FeatureConfiguration featureConfiguration, |
| boolean useTestOnlyFlags, |
| boolean isLtoIndexing, |
| Artifact interfaceLibraryBuilder, |
| Artifact interfaceLibraryOutput, |
| PathFragment ltoOutputRootPrefix, |
| ActionInput defFile, |
| FdoSupportProvider fdoSupport, |
| Iterable<String> runtimeLibrarySearchDirectories, |
| SequenceBuilder librariesToLink, |
| Iterable<String> librarySearchDirectories) { |
| CcToolchainVariables.Builder buildVariables = new CcToolchainVariables.Builder(); |
| |
| // symbol counting |
| if (symbolCounts != null) { |
| buildVariables.addStringVariable( |
| SYMBOL_COUNTS_OUTPUT.getVariableName(), symbolCounts.getExecPathString()); |
| } |
| |
| // pic |
| if (ccToolchainProvider.getForcePic()) { |
| buildVariables.addStringVariable(FORCE_PIC.getVariableName(), ""); |
| } |
| |
| if (!mustKeepDebug && ccToolchainProvider.getShouldStripBinaries()) { |
| buildVariables.addStringVariable(STRIP_DEBUG_SYMBOLS.getVariableName(), ""); |
| } |
| |
| if (isUsingLinkerNotArchiver |
| && ccToolchainProvider.shouldCreatePerObjectDebugInfo(featureConfiguration)) { |
| buildVariables.addStringVariable(IS_USING_FISSION.getVariableName(), ""); |
| } |
| |
| if (useTestOnlyFlags) { |
| buildVariables.addIntegerVariable(IS_CC_TEST.getVariableName(), 1); |
| buildVariables.addStringVariable(IS_CC_TEST_LINK_ACTION.getVariableName(), ""); |
| } else { |
| buildVariables.addIntegerVariable(IS_CC_TEST.getVariableName(), 0); |
| buildVariables.addStringVariable(IS_NOT_CC_TEST_LINK_ACTION.getVariableName(), ""); |
| } |
| |
| if (runtimeLibrarySearchDirectories != null) { |
| buildVariables.addStringSequenceVariable( |
| RUNTIME_LIBRARY_SEARCH_DIRECTORIES.getVariableName(), runtimeLibrarySearchDirectories); |
| } |
| |
| buildVariables.addCustomBuiltVariable(LIBRARIES_TO_LINK.getVariableName(), librariesToLink); |
| // TODO(b/72803478): Remove once existing crosstools have been migrated |
| buildVariables.addStringVariable("libs_to_link_dont_emit_objects_for_archiver", ""); |
| |
| buildVariables.addStringSequenceVariable( |
| LIBRARY_SEARCH_DIRECTORIES.getVariableName(), librarySearchDirectories); |
| |
| if (paramFile != null) { |
| buildVariables.addStringVariable( |
| LINKER_PARAM_FILE.getVariableName(), paramFile.getExecPathString()); |
| } |
| |
| // output exec path |
| if (outputArtifact != null && !isLtoIndexing) { |
| buildVariables.addStringVariable( |
| OUTPUT_EXECPATH.getVariableName(), outputArtifact.getExecPathString()); |
| } |
| |
| if (isLtoIndexing) { |
| if (thinltoParamFile != null) { |
| // This is a lto-indexing action and we want it to populate param file. |
| buildVariables.addStringVariable( |
| THINLTO_INDEXING_PARAM_FILE.getVariableName(), thinltoParamFile.getExecPathString()); |
| // TODO(b/33846234): Remove once all the relevant crosstools don't depend on the variable. |
| buildVariables.addStringVariable( |
| "thinlto_optional_params_file", "=" + thinltoParamFile.getExecPathString()); |
| } else { |
| buildVariables.addStringVariable(THINLTO_INDEXING_PARAM_FILE.getVariableName(), ""); |
| // TODO(b/33846234): Remove once all the relevant crosstools don't depend on the variable. |
| buildVariables.addStringVariable("thinlto_optional_params_file", ""); |
| } |
| buildVariables.addStringVariable( |
| THINLTO_PREFIX_REPLACE.getVariableName(), |
| configuration.getBinDirectory().getExecPathString() |
| + ";" |
| + configuration.getBinDirectory().getExecPath().getRelative(ltoOutputRootPrefix)); |
| buildVariables.addStringVariable( |
| THINLTO_OBJECT_SUFFIX_REPLACE.getVariableName(), |
| Iterables.getOnlyElement(CppFileTypes.LTO_INDEXING_OBJECT_FILE.getExtensions()) |
| + ";" |
| + Iterables.getOnlyElement(CppFileTypes.OBJECT_FILE.getExtensions())); |
| if (thinltoMergedObjectFile != null) { |
| buildVariables.addStringVariable( |
| THINLTO_MERGED_OBJECT_FILE.getVariableName(), |
| thinltoMergedObjectFile.getExecPathString()); |
| } |
| } else { |
| if (thinltoParamFile != null) { |
| // This is a normal link action and we need to use param file created by lto-indexing. |
| buildVariables.addStringVariable( |
| THINLTO_PARAM_FILE.getVariableName(), thinltoParamFile.getExecPathString()); |
| } |
| } |
| boolean shouldGenerateInterfaceLibrary = |
| outputArtifact != null |
| && interfaceLibraryBuilder != null |
| && interfaceLibraryOutput != null |
| && !isLtoIndexing; |
| buildVariables.addStringVariable( |
| GENERATE_INTERFACE_LIBRARY.getVariableName(), |
| shouldGenerateInterfaceLibrary ? "yes" : "no"); |
| buildVariables.addStringVariable( |
| INTERFACE_LIBRARY_BUILDER.getVariableName(), |
| shouldGenerateInterfaceLibrary ? interfaceLibraryBuilder.getExecPathString() : "ignored"); |
| buildVariables.addStringVariable( |
| INTERFACE_LIBRARY_INPUT.getVariableName(), |
| shouldGenerateInterfaceLibrary ? outputArtifact.getExecPathString() : "ignored"); |
| buildVariables.addStringVariable( |
| INTERFACE_LIBRARY_OUTPUT.getVariableName(), |
| shouldGenerateInterfaceLibrary ? interfaceLibraryOutput.getExecPathString() : "ignored"); |
| |
| if (defFile != null) { |
| buildVariables.addStringVariable( |
| DEF_FILE_PATH.getVariableName(), defFile.getExecPathString()); |
| } |
| |
| fdoSupport.getFdoSupport().getLinkOptions(featureConfiguration, buildVariables); |
| return buildVariables.build(); |
| } |
| } |