use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class CppLinkActionBuilder method createLTOArtifacts.
private Iterable<LTOBackendArtifacts> createLTOArtifacts(PathFragment ltoOutputRootPrefix, NestedSet<LibraryToLink> uniqueLibraries) {
Set<Artifact> compiled = new LinkedHashSet<>();
for (LibraryToLink lib : uniqueLibraries) {
Iterables.addAll(compiled, lib.getLTOBitcodeFiles());
}
// This flattens the set of object files, so for M binaries and N .o files,
// this is O(M*N). If we had a nested set of .o files, we could have O(M + N) instead.
Map<PathFragment, Artifact> allBitcode = new HashMap<>();
for (LibraryToLink lib : uniqueLibraries) {
if (!lib.containsObjectFiles()) {
continue;
}
for (Artifact a : lib.getObjectFiles()) {
if (compiled.contains(a)) {
allBitcode.put(a.getExecPath(), a);
}
}
}
for (LinkerInput input : objectFiles) {
if (this.ltoBitcodeFiles.contains(input.getArtifact())) {
allBitcode.put(input.getArtifact().getExecPath(), input.getArtifact());
}
}
ImmutableList.Builder<LTOBackendArtifacts> ltoOutputs = ImmutableList.builder();
for (Artifact a : allBitcode.values()) {
LTOBackendArtifacts ltoArtifacts = new LTOBackendArtifacts(ltoOutputRootPrefix, a, allBitcode, ruleContext, configuration, linkArtifactFactory);
ltoOutputs.add(ltoArtifacts);
}
return ltoOutputs.build();
}
use of com.google.devtools.build.lib.actions.Artifact 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.actions.Artifact in project bazel by bazelbuild.
the class CppModel method createCompileActionTemplate.
private Artifact createCompileActionTemplate(AnalysisEnvironment env, CppSource source, CppCompileActionBuilder builder, Iterable<ArtifactCategory> outputCategories) {
Artifact sourceArtifact = source.getSource();
Artifact outputFiles = CppHelper.getCompileOutputTreeArtifact(ruleContext, sourceArtifact);
// TODO(rduan): Dotd file output is not supported yet.
builder.setOutputs(outputFiles, null);
setupCompileBuildVariables(builder, /* usePic=*/
false, /*ccRelativeName=*/
null, /*autoFdoImportPath=*/
null, /*gcnoFile=*/
null, /*dwoFile=*/
null, builder.getContext().getCppModuleMap(), source.getBuildVariables());
semantics.finalizeCompileActionBuilder(ruleContext, builder);
CppCompileActionTemplate actionTemplate = new CppCompileActionTemplate(sourceArtifact, outputFiles, builder, cppConfiguration, outputCategories, ruleContext.getActionOwner());
env.registerAction(actionTemplate);
return outputFiles;
}
use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class CppModel method createSourceAction.
private Collection<Artifact> createSourceAction(String outputName, CcCompilationOutputs.Builder result, AnalysisEnvironment env, Artifact sourceArtifact, CppCompileActionBuilder builder, ArtifactCategory outputCategory, CppModuleMap cppModuleMap, boolean addObject, boolean enableCoverage, boolean generateDwo, boolean generateDotd, Map<String, String> sourceSpecificBuildVariables) {
ImmutableList.Builder<Artifact> directOutputs = new ImmutableList.Builder<>();
PathFragment ccRelativeName = semantics.getEffectiveSourcePath(sourceArtifact);
if (cppConfiguration.isLipoOptimization()) {
// TODO(bazel-team): we shouldn't be needing this, merging context with the binary
// is a superset of necessary information.
LipoContextProvider lipoProvider = Preconditions.checkNotNull(CppHelper.getLipoContextProvider(ruleContext), outputName);
builder.setContext(CppCompilationContext.mergeForLipo(lipoProvider.getLipoContext(), context));
}
boolean generatePicAction = getGeneratePicActions();
boolean generateNoPicAction = getGenerateNoPicActions();
Preconditions.checkState(generatePicAction || generateNoPicAction);
if (fake) {
boolean usePic = !generateNoPicAction;
createFakeSourceAction(outputName, result, env, builder, outputCategory, addObject, ccRelativeName, sourceArtifact.getExecPath(), usePic, generateDotd);
} else {
// generate .pic.o, .pic.d, .pic.gcno instead of .o, .d, .gcno.)
if (generatePicAction) {
String picOutputBase = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.PIC_FILE, outputName);
CppCompileActionBuilder picBuilder = copyAsPicBuilder(builder, picOutputBase, outputCategory, generateDotd);
String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, picOutputBase);
Artifact gcnoFile = enableCoverage ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName, configuration) : null;
Artifact dwoFile = generateDwo ? getDwoFile(picBuilder.getOutputFile()) : null;
setupCompileBuildVariables(picBuilder, /*usePic=*/
true, ccRelativeName, sourceArtifact.getExecPath(), gcnoFile, dwoFile, cppModuleMap, sourceSpecificBuildVariables);
if (maySaveTemps) {
result.addTemps(createTempsActions(sourceArtifact, outputName, picBuilder, /*usePic=*/
true, /*generateDotd=*/
generateDotd, ccRelativeName));
}
picBuilder.setGcnoFile(gcnoFile);
picBuilder.setDwoFile(dwoFile);
semantics.finalizeCompileActionBuilder(ruleContext, picBuilder);
CppCompileAction picAction = picBuilder.buildAndValidate(ruleContext);
env.registerAction(picAction);
directOutputs.add(picAction.getOutputFile());
if (addObject) {
result.addPicObjectFile(picAction.getOutputFile());
if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
result.addLTOBitcodeFile(picAction.getOutputFile());
}
}
if (dwoFile != null) {
// Host targets don't produce .dwo files.
result.addPicDwoFile(dwoFile);
}
if (cppConfiguration.isLipoContextCollector() && !generateNoPicAction) {
result.addLipoScannable(picAction);
}
}
if (generateNoPicAction) {
Artifact noPicOutputFile = CppHelper.getCompileOutputArtifact(ruleContext, CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, outputCategory, outputName), configuration);
builder.setOutputs(ruleContext, outputCategory, outputName, generateDotd);
String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, outputName);
// Create non-PIC compile actions
Artifact gcnoFile = !cppConfiguration.isLipoOptimization() && enableCoverage ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName, configuration) : null;
Artifact noPicDwoFile = generateDwo ? getDwoFile(noPicOutputFile) : null;
setupCompileBuildVariables(builder, /*usePic=*/
false, ccRelativeName, sourceArtifact.getExecPath(), gcnoFile, noPicDwoFile, cppModuleMap, sourceSpecificBuildVariables);
if (maySaveTemps) {
result.addTemps(createTempsActions(sourceArtifact, outputName, builder, /*usePic=*/
false, /*generateDotd*/
generateDotd, ccRelativeName));
}
builder.setGcnoFile(gcnoFile);
builder.setDwoFile(noPicDwoFile);
semantics.finalizeCompileActionBuilder(ruleContext, builder);
CppCompileAction compileAction = builder.buildAndValidate(ruleContext);
env.registerAction(compileAction);
Artifact objectFile = compileAction.getOutputFile();
directOutputs.add(objectFile);
if (addObject) {
result.addObjectFile(objectFile);
if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
result.addLTOBitcodeFile(objectFile);
}
}
if (noPicDwoFile != null) {
// Host targets don't produce .dwo files.
result.addDwoFile(noPicDwoFile);
}
if (cppConfiguration.isLipoContextCollector()) {
result.addLipoScannable(compileAction);
}
}
}
return directOutputs.build();
}
use of com.google.devtools.build.lib.actions.Artifact 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;
}
Aggregations