blob: 1f8e775058fa2a1245fcad803d7e6ab6ec513c79 [file] [log] [blame]
// 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.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
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;
import net.starlark.java.eval.EvalException;
// LINT.IfChange
/** 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 --linkopt or linkopts attribute. */
USER_LINK_FLAGS("user_link_flags"),
/** 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"),
/** 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"),
/** Path to the fdo instrument. */
FDO_INSTRUMENT_PATH("fdo_instrument_path"),
/** 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"),
/** The name of the runtime solib symlink of the shared library. */
RUNTIME_SOLIB_NAME("runtime_solib_name");
private final String variableName;
LinkBuildVariables(String variableName) {
this.variableName = variableName;
}
public String getVariableName() {
return variableName;
}
public static CcToolchainVariables.Builder setupLtoIndexingVariables(
PathFragment binDirectoryPath,
String thinltoParamFile,
String thinltoMergedObjectFile,
CcToolchainProvider ccToolchainProvider,
FeatureConfiguration featureConfiguration,
PathFragment ltoOutputRootPrefix,
PathFragment ltoObjRootPrefix)
throws EvalException {
CcToolchainVariables.Builder buildVariables = CcToolchainVariables.builder();
// This is a lto-indexing action and we want it to populate param file.
buildVariables.addStringVariable(
THINLTO_INDEXING_PARAM_FILE.getVariableName(), thinltoParamFile);
// TODO(b/33846234): Remove once all the relevant crosstools don't depend on the variable.
buildVariables.addStringVariable("thinlto_optional_params_file", "=" + thinltoParamFile);
// Given "fullbitcode_prefix;thinlto_index_prefix;native_object_prefix", replaces
// fullbitcode_prefix with thinlto_index_prefix to generate the index and imports files.
// fullbitcode_prefix is the empty string because we are appending a prefix to the fullbitcode
// instead of replacing it. This argument is passed to the linker.
// The native objects generated after the LTOBackend action are stored in a directory by
// replacing the prefix "fullbitcode_prefix" with "native_object_prefix", and this is used
// when generating the param file in the indexing step, which will be used during the final
// link step.
if (!ltoOutputRootPrefix.equals(ltoObjRootPrefix)) {
buildVariables.addStringVariable(
THINLTO_PREFIX_REPLACE.getVariableName(),
";"
+ binDirectoryPath.getRelative(ltoOutputRootPrefix)
+ "/;"
+ binDirectoryPath.getRelative(ltoObjRootPrefix)
+ "/");
} else {
buildVariables.addStringVariable(
THINLTO_PREFIX_REPLACE.getVariableName(),
";" + binDirectoryPath.getRelative(ltoOutputRootPrefix) + "/");
}
String objectFileExtension =
ccToolchainProvider
.getFeatures()
.getArtifactNameExtensionForCategory(ArtifactCategory.OBJECT_FILE);
if (!featureConfiguration.isEnabled(CppRuleClasses.NO_USE_LTO_INDEXING_BITCODE_FILE)) {
buildVariables.addStringVariable(
THINLTO_OBJECT_SUFFIX_REPLACE.getVariableName(),
Iterables.getOnlyElement(CppFileTypes.LTO_INDEXING_OBJECT_FILE.getExtensions())
+ ";"
+ objectFileExtension);
}
buildVariables.addStringVariable(
THINLTO_MERGED_OBJECT_FILE.getVariableName(), thinltoMergedObjectFile);
buildVariables.addStringVariable(GENERATE_INTERFACE_LIBRARY.getVariableName(), "no");
buildVariables.addStringVariable(INTERFACE_LIBRARY_BUILDER.getVariableName(), "ignored");
buildVariables.addStringVariable(INTERFACE_LIBRARY_INPUT.getVariableName(), "ignored");
buildVariables.addStringVariable(INTERFACE_LIBRARY_OUTPUT.getVariableName(), "ignored");
return buildVariables;
}
public static CcToolchainVariables.Builder setupLinkingVariables(
String outputFile,
String runtimeSolibName,
String thinltoParamFile,
CcToolchainProvider ccToolchainProvider,
FeatureConfiguration featureConfiguration,
String interfaceLibraryBuilder,
String interfaceLibraryOutput,
FdoContext fdoContext)
throws EvalException {
CcToolchainVariables.Builder buildVariables = CcToolchainVariables.builder();
if (thinltoParamFile != null) {
// This is a normal link action and we need to use param file created by lto-indexing.
buildVariables.addStringVariable(
LinkBuildVariables.THINLTO_PARAM_FILE.getVariableName(), thinltoParamFile);
}
// output exec path
buildVariables.addStringVariable(
LinkBuildVariables.OUTPUT_EXECPATH.getVariableName(), outputFile);
buildVariables.addStringVariable(
LinkBuildVariables.RUNTIME_SOLIB_NAME.getVariableName(), runtimeSolibName);
if (!ccToolchainProvider.isToolConfiguration()
&& fdoContext != null
&& featureConfiguration.isEnabled(CppRuleClasses.PROPELLER_OPTIMIZE)
&& fdoContext.getPropellerOptimizeInputFile() != null
&& fdoContext.getPropellerOptimizeInputFile().getLdArtifact() != null) {
buildVariables.addStringVariable(
LinkBuildVariables.PROPELLER_OPTIMIZE_LD_PATH.getVariableName(),
fdoContext.getPropellerOptimizeInputFile().getLdArtifact().getExecPathString());
}
boolean shouldGenerateInterfaceLibrary =
outputFile != null && interfaceLibraryBuilder != null && interfaceLibraryOutput != null;
buildVariables.addStringVariable(
GENERATE_INTERFACE_LIBRARY.getVariableName(),
shouldGenerateInterfaceLibrary ? "yes" : "no");
buildVariables.addStringVariable(
INTERFACE_LIBRARY_BUILDER.getVariableName(),
shouldGenerateInterfaceLibrary ? interfaceLibraryBuilder : "ignored");
buildVariables.addStringVariable(
INTERFACE_LIBRARY_INPUT.getVariableName(),
shouldGenerateInterfaceLibrary ? outputFile : "ignored");
buildVariables.addStringVariable(
INTERFACE_LIBRARY_OUTPUT.getVariableName(),
shouldGenerateInterfaceLibrary ? interfaceLibraryOutput : "ignored");
return buildVariables;
}
public static CcToolchainVariables.Builder setupCommonVariables(
boolean isUsingLinkerNotArchiver,
boolean isCreatingSharedLibrary,
String paramFile,
boolean mustKeepDebug,
CcToolchainProvider ccToolchainProvider,
FeatureConfiguration featureConfiguration,
boolean useTestOnlyFlags,
Iterable<String> userLinkFlags,
FdoContext fdoContext,
NestedSet<String> runtimeLibrarySearchDirectories,
SequenceBuilder librariesToLink,
NestedSet<String> librarySearchDirectories)
throws EvalException {
CcToolchainVariables.Builder buildVariables =
CcToolchainVariables.builder(ccToolchainProvider.getBuildVars());
CppConfiguration cppConfiguration = ccToolchainProvider.getCppConfiguration();
// pic
if (cppConfiguration.forcePic()) {
buildVariables.addStringVariable(FORCE_PIC.getVariableName(), "");
}
if (!mustKeepDebug && cppConfiguration.shouldStripBinaries()) {
buildVariables.addStringVariable(STRIP_DEBUG_SYMBOLS.getVariableName(), "");
}
if (isUsingLinkerNotArchiver
&& CcToolchainProvider.shouldCreatePerObjectDebugInfo(
featureConfiguration, cppConfiguration)) {
buildVariables.addStringVariable(IS_USING_FISSION.getVariableName(), "");
}
if (!cppConfiguration.useCcTestFeature()) {
buildVariables.addBooleanValue(IS_CC_TEST.getVariableName(), useTestOnlyFlags);
}
buildVariables.addStringSequenceVariable(
RUNTIME_LIBRARY_SEARCH_DIRECTORIES.getVariableName(), runtimeLibrarySearchDirectories);
if (librariesToLink != null) {
buildVariables.addCustomBuiltVariable(LIBRARIES_TO_LINK.getVariableName(), librariesToLink);
}
buildVariables.addStringSequenceVariable(
LIBRARY_SEARCH_DIRECTORIES.getVariableName(), librarySearchDirectories);
if (paramFile != null) {
buildVariables.addStringVariable(LINKER_PARAM_FILE.getVariableName(), paramFile);
}
if (featureConfiguration.isEnabled(CppRuleClasses.FDO_INSTRUMENT)) {
Preconditions.checkArgument(fdoContext.getBranchFdoProfile() == null);
String fdoInstrument = cppConfiguration.getFdoInstrument();
Preconditions.checkNotNull(fdoInstrument);
buildVariables.addStringVariable(FDO_INSTRUMENT_PATH.getVariableName(), fdoInstrument);
} else if (featureConfiguration.isEnabled(CppRuleClasses.CS_FDO_INSTRUMENT)) {
String csFdoInstrument = ccToolchainProvider.getCSFdoInstrument();
Preconditions.checkNotNull(csFdoInstrument);
buildVariables.addStringVariable(CS_FDO_INSTRUMENT_PATH.getVariableName(), csFdoInstrument);
}
// For now, silently ignore linkopts if this is a static library
userLinkFlags = isUsingLinkerNotArchiver ? userLinkFlags : ImmutableList.of();
buildVariables.addStringSequenceVariable(
LinkBuildVariables.USER_LINK_FLAGS.getVariableName(),
removePieIfCreatingSharedLibrary(isCreatingSharedLibrary, userLinkFlags));
return buildVariables;
}
private static Iterable<String> removePieIfCreatingSharedLibrary(
boolean isCreatingSharedLibrary, Iterable<String> flags) {
if (isCreatingSharedLibrary) {
return Iterables.filter(
flags,
Predicates.not(
Predicates.or(Predicates.equalTo("-pie"), Predicates.equalTo("-Wl,-pie"))));
} else {
return flags;
}
}
}
// LINT.ThenChange(//src/main/starlark/builtins_bzl/common/cc/link/link_build_variables.bzl)