use of com.google.devtools.build.lib.analysis.AnalysisEnvironment in project bazel by bazelbuild.
the class CppModel method createCcLinkActions.
/**
* Constructs the C++ linker actions. It generally generates two actions, one for a static library
* and one for a dynamic library. If PIC is required for shared libraries, but not for binaries,
* it additionally creates a third action to generate a PIC static library.
*
* <p>For dynamic libraries, this method can additionally create an interface shared library that
* can be used for linking, but doesn't contain any executable code. This increases the number of
* cache hits for link actions. Call {@link #setAllowInterfaceSharedObjects(boolean)} to enable
* this behavior.
*
* @throws RuleErrorException
*/
public CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs, Iterable<Artifact> nonCodeLinkerInputs) throws RuleErrorException, InterruptedException {
// For now only handle static links. Note that the dynamic library link below ignores linkType.
// TODO(bazel-team): Either support non-static links or move this check to setLinkType().
Preconditions.checkState(linkType.staticness() == Staticness.STATIC, "can only handle static links");
CcLinkingOutputs.Builder result = new CcLinkingOutputs.Builder();
if (cppConfiguration.isLipoContextCollector()) {
// because it needs some data that's not available at this point.
return result.build();
}
AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
boolean usePicForBinaries = CppHelper.usePic(ruleContext, true);
boolean usePicForSharedLibs = CppHelper.usePic(ruleContext, false);
// Create static library (.a). The linkType only reflects whether the library is alwayslink or
// not. The PIC-ness is determined by whether we need to use PIC or not. There are three cases
// for (usePicForSharedLibs usePicForBinaries):
//
// (1) (false false) -> no pic code
// (2) (true false) -> shared libraries as pic, but not binaries
// (3) (true true) -> both shared libraries and binaries as pic
//
// In case (3), we always need PIC, so only create one static library containing the PIC object
// files. The name therefore does not match the content.
//
// Presumably, it is done this way because the .a file is an implicit output of every cc_library
// rule, so we can't use ".pic.a" that in the always-PIC case.
// If the crosstool is configured to select an output artifact, we use that selection.
// Otherwise, we use linux defaults.
Artifact linkedArtifact = getLinkedArtifact(linkType);
PathFragment labelName = new PathFragment(ruleContext.getLabel().getName());
String libraryIdentifier = ruleContext.getPackageDirectory().getRelative(labelName.replaceName("lib" + labelName.getBaseName())).getPathString();
CppLinkAction maybePicAction = newLinkActionBuilder(linkedArtifact).addObjectFiles(ccOutputs.getObjectFiles(usePicForBinaries)).addNonCodeInputs(nonCodeLinkerInputs).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(linkType).setLinkStaticness(LinkStaticness.FULLY_STATIC).addActionInputs(linkActionInputs).setLibraryIdentifier(libraryIdentifier).addVariablesExtensions(variablesExtensions).setFeatureConfiguration(featureConfiguration).build();
env.registerAction(maybePicAction);
if (linkType != LinkTargetType.EXECUTABLE) {
result.addStaticLibrary(maybePicAction.getOutputLibrary());
}
// one contains the PIC code, so the names match the content.
if (!usePicForBinaries && usePicForSharedLibs) {
LinkTargetType picLinkType = (linkType == LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY) ? LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY : LinkTargetType.PIC_STATIC_LIBRARY;
// If the crosstool is configured to select an output artifact, we use that selection.
// Otherwise, we use linux defaults.
Artifact picArtifact = getLinkedArtifact(picLinkType);
CppLinkAction picAction = newLinkActionBuilder(picArtifact).addObjectFiles(ccOutputs.getObjectFiles(true)).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(picLinkType).setLinkStaticness(LinkStaticness.FULLY_STATIC).addActionInputs(linkActionInputs).setLibraryIdentifier(libraryIdentifier).addVariablesExtensions(variablesExtensions).setFeatureConfiguration(featureConfiguration).build();
env.registerAction(picAction);
if (linkType != LinkTargetType.EXECUTABLE) {
result.addPicStaticLibrary(picAction.getOutputLibrary());
}
}
if (!createDynamicLibrary) {
return result.build();
}
// Create dynamic library.
Artifact soImpl;
String mainLibraryIdentifier;
if (soImplArtifact == null) {
// If the crosstool is configured to select an output artifact, we use that selection.
// Otherwise, we use linux defaults.
soImpl = getLinkedArtifact(LinkTargetType.DYNAMIC_LIBRARY);
mainLibraryIdentifier = libraryIdentifier;
} else {
// This branch is only used for vestigial Google-internal rules where the name of the output
// file is explicitly specified in the BUILD file and as such, is platform-dependent. Thus,
// we just hardcode some reasonable logic to compute the library identifier and hope that this
// will eventually go away.
soImpl = soImplArtifact;
mainLibraryIdentifier = FileSystemUtils.removeExtension(soImpl.getRootRelativePath().getPathString());
}
List<String> sonameLinkopts = ImmutableList.of();
Artifact soInterface = null;
if (cppConfiguration.useInterfaceSharedObjects() && allowInterfaceSharedObjects) {
soInterface = CppHelper.getLinuxLinkedArtifact(ruleContext, configuration, LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, linkedArtifactNameSuffix);
sonameLinkopts = ImmutableList.of("-Wl,-soname=" + SolibSymlinkAction.getDynamicLibrarySoname(soImpl.getRootRelativePath(), false));
}
// Should we also link in any libraries that this library depends on?
// That is required on some systems...
CppLinkActionBuilder linkActionBuilder = newLinkActionBuilder(soImpl).setInterfaceOutput(soInterface).addObjectFiles(ccOutputs.getObjectFiles(usePicForSharedLibs)).addNonCodeInputs(ccOutputs.getHeaderTokenFiles()).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(LinkTargetType.DYNAMIC_LIBRARY).setLinkStaticness(LinkStaticness.DYNAMIC).addActionInputs(linkActionInputs).setLibraryIdentifier(mainLibraryIdentifier).addLinkopts(linkopts).addLinkopts(sonameLinkopts).setRuntimeInputs(ArtifactCategory.DYNAMIC_LIBRARY, ccToolchain.getDynamicRuntimeLinkMiddleman(), ccToolchain.getDynamicRuntimeLinkInputs()).setFeatureConfiguration(featureConfiguration).addVariablesExtensions(variablesExtensions);
if (!ccOutputs.getLtoBitcodeFiles().isEmpty() && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
linkActionBuilder.setLTOIndexing(true);
linkActionBuilder.setUsePicForLTOBackendActions(usePicForSharedLibs);
// If support is ever added for generating a dwp file for shared
// library targets (e.g. when linkstatic=0), then this should change
// to generate dwo files when cppConfiguration.useFission(),
// and the dwp generating action for the shared library should
// include all of the resulting dwo files.
linkActionBuilder.setUseFissionForLTOBackendActions(false);
CppLinkAction indexAction = linkActionBuilder.build();
env.registerAction(indexAction);
linkActionBuilder.setLTOIndexing(false);
}
CppLinkAction action = linkActionBuilder.build();
env.registerAction(action);
if (linkType == LinkTargetType.EXECUTABLE) {
return result.build();
}
LibraryToLink dynamicLibrary = action.getOutputLibrary();
LibraryToLink interfaceLibrary = action.getInterfaceOutputLibrary();
if (interfaceLibrary == null) {
interfaceLibrary = dynamicLibrary;
}
// mangled name only.
if (neverLink) {
result.addDynamicLibrary(interfaceLibrary);
result.addExecutionDynamicLibrary(dynamicLibrary);
} else {
Artifact libraryLink = SolibSymlinkAction.getDynamicLibrarySymlink(ruleContext, interfaceLibrary.getArtifact(), false, false, ruleContext.getConfiguration());
result.addDynamicLibrary(LinkerInputs.solibLibraryToLink(libraryLink, interfaceLibrary.getArtifact(), libraryIdentifier));
Artifact implLibraryLink = SolibSymlinkAction.getDynamicLibrarySymlink(ruleContext, dynamicLibrary.getArtifact(), false, false, ruleContext.getConfiguration());
result.addExecutionDynamicLibrary(LinkerInputs.solibLibraryToLink(implLibraryLink, dynamicLibrary.getArtifact(), libraryIdentifier));
}
return result.build();
}
use of com.google.devtools.build.lib.analysis.AnalysisEnvironment in project bazel by bazelbuild.
the class CppModel method createCcCompileActions.
/**
* Constructs the C++ compiler actions. It generally creates one action for every specified source
* file. It takes into account LIPO, fake-ness, coverage, and PIC, in addition to using the
* settings specified on the current object. This method should only be called once.
*/
public CcCompilationOutputs createCcCompileActions() {
CcCompilationOutputs.Builder result = new CcCompilationOutputs.Builder();
Preconditions.checkNotNull(context);
AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
if (shouldProvideHeaderModules()) {
Collection<Artifact> modules = createModuleAction(result, context.getCppModuleMap());
if (featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
for (Artifact module : modules) {
createModuleCodegenAction(result, module);
}
}
} else if (context.getVerificationModuleMap() != null) {
Collection<Artifact> modules = createModuleAction(result, context.getVerificationModuleMap());
for (Artifact module : modules) {
result.addHeaderTokenFile(module);
}
}
for (CppSource source : sourceFiles) {
Artifact sourceArtifact = source.getSource();
Label sourceLabel = source.getLabel();
String outputName = FileSystemUtils.removeExtension(semantics.getEffectiveSourcePath(sourceArtifact)).getPathString();
CppCompileActionBuilder builder = initializeCompileAction(sourceArtifact, sourceLabel);
builder.setSemantics(semantics);
if (!sourceArtifact.isTreeArtifact()) {
switch(source.getType()) {
case HEADER:
createHeaderAction(outputName, result, env, builder, CppFileTypes.mustProduceDotdFile(sourceArtifact));
break;
case CLIF_INPUT_PROTO:
createClifMatchAction(outputName, result, env, builder);
break;
default:
boolean bitcodeOutput = featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename());
createSourceAction(outputName, result, env, sourceArtifact, builder, ArtifactCategory.OBJECT_FILE, context.getCppModuleMap(), /*addObject=*/
true, isCodeCoverageEnabled(), /*generateDwo=*/
cppConfiguration.useFission() && !bitcodeOutput, CppFileTypes.mustProduceDotdFile(sourceArtifact), source.getBuildVariables());
break;
}
} else {
switch(source.getType()) {
case HEADER:
Artifact headerTokenFile = createCompileActionTemplate(env, source, builder, ImmutableList.of(ArtifactCategory.GENERATED_HEADER, ArtifactCategory.PROCESSED_HEADER));
result.addHeaderTokenFile(headerTokenFile);
break;
case SOURCE:
Artifact objectFile = createCompileActionTemplate(env, source, builder, ImmutableList.of(ArtifactCategory.OBJECT_FILE));
result.addObjectFile(objectFile);
break;
default:
throw new IllegalStateException("Encountered invalid source types when creating CppCompileActionTemplates");
}
}
}
compilationOutputs = result.build();
return compilationOutputs;
}
use of com.google.devtools.build.lib.analysis.AnalysisEnvironment in project bazel by bazelbuild.
the class CrosstoolCompilationSupport method registerHeaderScanningActions.
private void registerHeaderScanningActions(Info info, ObjcProvider objcProvider, CompilationArtifacts compilationArtifacts) {
// PIC is not used for Obj-C builds, if that changes this method will need to change
if (!isHeaderThinningEnabled() || info.getCcCompilationOutputs().getObjectFiles(false).isEmpty()) {
return;
}
ImmutableList.Builder<ObjcHeaderThinningInfo> headerThinningInfos = ImmutableList.builder();
AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
for (Artifact objectFile : info.getCcCompilationOutputs().getObjectFiles(false)) {
ActionAnalysisMetadata generatingAction = analysisEnvironment.getLocalGeneratingAction(objectFile);
if (generatingAction instanceof CppCompileAction) {
CppCompileAction action = (CppCompileAction) generatingAction;
Artifact sourceFile = action.getSourceFile();
if (!sourceFile.isTreeArtifact() && SOURCES_FOR_HEADER_THINNING.matches(sourceFile.getFilename())) {
headerThinningInfos.add(new ObjcHeaderThinningInfo(sourceFile, intermediateArtifacts.headersListFile(sourceFile), action.getCompilerOptions()));
}
}
}
registerHeaderScanningActions(headerThinningInfos.build(), objcProvider, compilationArtifacts);
}
use of com.google.devtools.build.lib.analysis.AnalysisEnvironment in project bazel by bazelbuild.
the class FdoSupport method configureCompilation.
/**
* Configures a compile action builder by setting up command line options and
* auxiliary inputs according to the FDO configuration. This method does
* nothing If FDO is disabled.
*/
@ThreadSafe
public void configureCompilation(CppCompileActionBuilder builder, CcToolchainFeatures.Variables.Builder buildVariables, RuleContext ruleContext, PathFragment sourceName, PathFragment sourceExecPath, boolean usePic, FeatureConfiguration featureConfiguration, FdoSupportProvider fdoSupportProvider) {
// It is a bug if this method is called with useLipo if lipo is disabled. However, it is legal
// if is is called with !useLipo, even though lipo is enabled.
LipoContextProvider lipoInputProvider = CppHelper.getLipoContextProvider(ruleContext);
Preconditions.checkArgument(lipoInputProvider == null || lipoMode != LipoMode.OFF);
// FDO is disabled -> do nothing.
if ((fdoInstrument == null) && (fdoRoot == null)) {
return;
}
if (featureConfiguration.isEnabled(CppRuleClasses.FDO_INSTRUMENT)) {
buildVariables.addStringVariable("fdo_instrument_path", fdoInstrument.getPathString());
}
// Optimization phase
if (fdoRoot != null) {
AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
// Declare dependency on contents of zip file.
if (env.getSkyframeEnv().valuesMissing()) {
return;
}
Iterable<Artifact> auxiliaryInputs = getAuxiliaryInputs(ruleContext, sourceName, sourceExecPath, usePic, lipoInputProvider, fdoSupportProvider);
builder.addMandatoryInputs(auxiliaryInputs);
if (!Iterables.isEmpty(auxiliaryInputs)) {
if (featureConfiguration.isEnabled(CppRuleClasses.AUTOFDO)) {
buildVariables.addStringVariable("fdo_profile_path", getAutoProfilePath(fdoProfile, fdoRootExecPath).getPathString());
}
if (featureConfiguration.isEnabled(CppRuleClasses.FDO_OPTIMIZE)) {
if (fdoMode == FdoMode.LLVM_FDO) {
buildVariables.addStringVariable("fdo_profile_path", getLLVMProfilePath(fdoProfile, fdoRootExecPath).getPathString());
} else {
buildVariables.addStringVariable("fdo_profile_path", fdoRootExecPath.getPathString());
}
}
}
}
}
use of com.google.devtools.build.lib.analysis.AnalysisEnvironment in project bazel by bazelbuild.
the class CppModel method createModuleCodegenAction.
private void createModuleCodegenAction(CcCompilationOutputs.Builder result, Artifact module) {
if (fake) {
// If we find one, support needs to be added here.
return;
}
String outputName = semantics.getEffectiveSourcePath(module).getPathString();
// TODO(djasper): Make this less hacky after refactoring how the PIC/noPIC actions are created.
boolean pic = module.getFilename().contains(".pic.");
// TODO(djasper): Investigate whether we need to use a label separate from that of the module
// map. It is used for per-file-copts.
CppCompileActionBuilder builder = initializeCompileAction(module, Label.parseAbsoluteUnchecked(context.getCppModuleMap().getName()));
builder.setSemantics(semantics);
builder.setPicMode(pic);
builder.setOutputs(ruleContext, ArtifactCategory.OBJECT_FILE, outputName, CppFileTypes.mustProduceDotdFile(module));
PathFragment ccRelativeName = semantics.getEffectiveSourcePath(module);
String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, outputName);
// TODO(djasper): This is now duplicated. Refactor the various create..Action functions.
Artifact gcnoFile = isCodeCoverageEnabled() && !cppConfiguration.isLipoOptimization() ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName, configuration) : null;
boolean generateDwo = cppConfiguration.useFission();
Artifact dwoFile = generateDwo ? getDwoFile(builder.getOutputFile()) : null;
setupCompileBuildVariables(builder, /*usePic=*/
pic, ccRelativeName, module.getExecPath(), gcnoFile, dwoFile, builder.getContext().getCppModuleMap(), ImmutableMap.<String, String>of());
builder.setGcnoFile(gcnoFile);
builder.setDwoFile(dwoFile);
semantics.finalizeCompileActionBuilder(ruleContext, builder);
CppCompileAction compileAction = builder.build();
AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
env.registerAction(compileAction);
Artifact objectFile = compileAction.getOutputFile();
if (pic) {
result.addPicObjectFile(objectFile);
} else {
result.addObjectFile(objectFile);
}
}
Aggregations