use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.
the class CcCommon method getHeaders.
/**
* Returns the files from headers and does some sanity checks. Note that this method reports
* warnings to the {@link RuleContext} as a side effect, and so should only be called once for any
* given rule.
*/
public static List<Pair<Artifact, Label>> getHeaders(RuleContext ruleContext) {
Map<Artifact, Label> map = Maps.newLinkedHashMap();
for (TransitiveInfoCollection target : ruleContext.getPrerequisitesIf("hdrs", Mode.TARGET, FileProvider.class)) {
FileProvider provider = target.getProvider(FileProvider.class);
for (Artifact artifact : provider.getFilesToBuild()) {
if (CppRuleClasses.DISALLOWED_HDRS_FILES.matches(artifact.getFilename())) {
ruleContext.attributeWarning("hdrs", "file '" + artifact.getFilename() + "' from target '" + target.getLabel() + "' is not allowed in hdrs");
continue;
}
Label oldLabel = map.put(artifact, target.getLabel());
if (oldLabel != null && !oldLabel.equals(target.getLabel())) {
ruleContext.attributeWarning("hdrs", String.format("Artifact '%s' is duplicated (through '%s' and '%s')", artifact.getExecPathString(), oldLabel, target.getLabel()));
}
}
}
ImmutableList.Builder<Pair<Artifact, Label>> result = ImmutableList.builder();
for (Map.Entry<Artifact, Label> entry : map.entrySet()) {
result.add(Pair.of(entry.getKey(), entry.getValue()));
}
return result.build();
}
use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.
the class CppHelper method mergeToolchainDependentContext.
/**
* Merges the STL and toolchain contexts into context builder. The STL is automatically determined
* using the ":stl" attribute.
*/
public static void mergeToolchainDependentContext(RuleContext ruleContext, CcToolchainProvider toolchain, Builder contextBuilder) {
if (ruleContext.getRule().getAttributeDefinition(":stl") != null) {
TransitiveInfoCollection stl = ruleContext.getPrerequisite(":stl", Mode.TARGET);
if (stl != null) {
// TODO(bazel-team): Clean this up.
contextBuilder.addSystemIncludeDir(stl.getLabel().getPackageIdentifier().getPathUnderExecRoot().getRelative("gcc3"));
CppCompilationContext provider = stl.getProvider(CppCompilationContext.class);
if (provider == null) {
ruleContext.ruleError("Unable to merge the STL '" + stl.getLabel() + "' and toolchain contexts");
return;
}
contextBuilder.mergeDependentContext(provider);
}
}
if (toolchain != null) {
contextBuilder.mergeDependentContext(toolchain.getCppCompilationContext());
}
}
use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.
the class NativeLibs method fromLinkedNativeDeps.
public static NativeLibs fromLinkedNativeDeps(RuleContext ruleContext, String nativeDepsFileName, Multimap<String, TransitiveInfoCollection> depsByArchitecture, Map<String, CcToolchainProvider> toolchainMap, Map<String, BuildConfiguration> configurationMap) throws InterruptedException {
Map<String, Iterable<Artifact>> result = new LinkedHashMap<>();
String nativeDepsLibraryBasename = null;
for (Map.Entry<String, Collection<TransitiveInfoCollection>> entry : depsByArchitecture.asMap().entrySet()) {
CcLinkParams linkParams = AndroidCommon.getCcLinkParamsStore(entry.getValue(), ImmutableList.of("-Wl,-soname=lib" + ruleContext.getLabel().getName())).get(/* linkingStatically */
true, /* linkShared */
true);
Artifact nativeDepsLibrary = NativeDepsHelper.linkAndroidNativeDepsIfPresent(ruleContext, linkParams, configurationMap.get(entry.getKey()), toolchainMap.get(entry.getKey()));
ImmutableList.Builder<Artifact> librariesBuilder = ImmutableList.builder();
if (nativeDepsLibrary != null) {
librariesBuilder.add(nativeDepsLibrary);
nativeDepsLibraryBasename = nativeDepsLibrary.getExecPath().getBaseName();
}
librariesBuilder.addAll(filterUniqueSharedLibraries(ruleContext, nativeDepsLibrary, linkParams.getLibraries()));
ImmutableList<Artifact> libraries = librariesBuilder.build();
if (!libraries.isEmpty()) {
result.put(entry.getKey(), libraries);
}
}
if (result.isEmpty()) {
return NativeLibs.EMPTY;
} else if (nativeDepsLibraryBasename == null) {
return new NativeLibs(ImmutableMap.copyOf(result), null);
} else {
// The native deps name file must be the only file in its directory because ApkBuilder does
// not have an option to add a particular file to the .apk, only one to add every file in a
// particular directory.
Artifact nativeDepsName = ruleContext.getUniqueDirectoryArtifact("nativedeps_filename", nativeDepsFileName, ruleContext.getBinOrGenfilesDirectory());
ruleContext.registerAction(FileWriteAction.create(ruleContext, nativeDepsName, nativeDepsLibraryBasename, false));
return new NativeLibs(ImmutableMap.copyOf(result), nativeDepsName);
}
}
use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.
the class CcToolchain method create.
@Override
public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException, InterruptedException {
TransitiveInfoCollection lipoContextCollector = ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK);
if (lipoContextCollector != null && lipoContextCollector.getProvider(LipoContextProvider.class) == null) {
ruleContext.ruleError("--lipo_context must point to a cc_binary or a cc_test rule");
return null;
}
CppConfiguration cppConfiguration = Preconditions.checkNotNull(ruleContext.getFragment(CppConfiguration.class));
Path fdoZip = ruleContext.getConfiguration().getCompilationMode() == CompilationMode.OPT ? cppConfiguration.getFdoZip() : null;
SkyKey fdoKey = FdoSupportValue.key(cppConfiguration.getLipoMode(), fdoZip, cppConfiguration.getFdoInstrument());
SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv();
FdoSupportValue fdoSupport;
try {
fdoSupport = (FdoSupportValue) skyframeEnv.getValueOrThrow(fdoKey, FdoException.class, IOException.class);
} catch (FdoException | IOException e) {
ruleContext.ruleError("cannot initialize FDO: " + e.getMessage());
return null;
}
if (skyframeEnv.valuesMissing()) {
return null;
}
final Label label = ruleContext.getLabel();
final NestedSet<Artifact> crosstool = ruleContext.getPrerequisite("all_files", Mode.HOST).getProvider(FileProvider.class).getFilesToBuild();
final NestedSet<Artifact> crosstoolMiddleman = getFiles(ruleContext, "all_files");
final NestedSet<Artifact> compile = getFiles(ruleContext, "compiler_files");
final NestedSet<Artifact> strip = getFiles(ruleContext, "strip_files");
final NestedSet<Artifact> objcopy = getFiles(ruleContext, "objcopy_files");
final NestedSet<Artifact> link = getFiles(ruleContext, "linker_files");
final NestedSet<Artifact> dwp = getFiles(ruleContext, "dwp_files");
final NestedSet<Artifact> libcLink = inputsForLibc(ruleContext);
String purposePrefix = Actions.escapeLabel(label) + "_";
String runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(label);
final PathFragment runtimeSolibDir = ruleContext.getConfiguration().getBinFragment().getRelative(runtimeSolibDirBase);
// Static runtime inputs.
TransitiveInfoCollection staticRuntimeLibDep = selectDep(ruleContext, "static_runtime_libs", cppConfiguration.getStaticRuntimeLibsLabel());
final NestedSet<Artifact> staticRuntimeLinkInputs;
final Artifact staticRuntimeLinkMiddleman;
if (cppConfiguration.supportsEmbeddedRuntimes()) {
staticRuntimeLinkInputs = staticRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild();
} else {
staticRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
if (!staticRuntimeLinkInputs.isEmpty()) {
NestedSet<Artifact> staticRuntimeLinkMiddlemanSet = CompilationHelper.getAggregatingMiddleman(ruleContext, purposePrefix + "static_runtime_link", staticRuntimeLibDep);
staticRuntimeLinkMiddleman = staticRuntimeLinkMiddlemanSet.isEmpty() ? null : Iterables.getOnlyElement(staticRuntimeLinkMiddlemanSet);
} else {
staticRuntimeLinkMiddleman = null;
}
Preconditions.checkState((staticRuntimeLinkMiddleman == null) == staticRuntimeLinkInputs.isEmpty());
// Dynamic runtime inputs.
TransitiveInfoCollection dynamicRuntimeLibDep = selectDep(ruleContext, "dynamic_runtime_libs", cppConfiguration.getDynamicRuntimeLibsLabel());
NestedSet<Artifact> dynamicRuntimeLinkSymlinks;
List<Artifact> dynamicRuntimeLinkInputs = new ArrayList<>();
Artifact dynamicRuntimeLinkMiddleman;
if (cppConfiguration.supportsEmbeddedRuntimes()) {
NestedSetBuilder<Artifact> dynamicRuntimeLinkSymlinksBuilder = NestedSetBuilder.stableOrder();
for (Artifact artifact : dynamicRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild()) {
if (CppHelper.SHARED_LIBRARY_FILETYPES.matches(artifact.getFilename())) {
dynamicRuntimeLinkInputs.add(artifact);
dynamicRuntimeLinkSymlinksBuilder.add(SolibSymlinkAction.getCppRuntimeSymlink(ruleContext, artifact, runtimeSolibDirBase, ruleContext.getConfiguration()));
}
}
dynamicRuntimeLinkSymlinks = dynamicRuntimeLinkSymlinksBuilder.build();
} else {
dynamicRuntimeLinkSymlinks = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
if (!dynamicRuntimeLinkInputs.isEmpty()) {
List<Artifact> dynamicRuntimeLinkMiddlemanSet = CppHelper.getAggregatingMiddlemanForCppRuntimes(ruleContext, purposePrefix + "dynamic_runtime_link", dynamicRuntimeLinkInputs, runtimeSolibDirBase, ruleContext.getConfiguration());
dynamicRuntimeLinkMiddleman = dynamicRuntimeLinkMiddlemanSet.isEmpty() ? null : Iterables.getOnlyElement(dynamicRuntimeLinkMiddlemanSet);
} else {
dynamicRuntimeLinkMiddleman = null;
}
Preconditions.checkState((dynamicRuntimeLinkMiddleman == null) == dynamicRuntimeLinkSymlinks.isEmpty());
CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext);
CppModuleMap moduleMap = createCrosstoolModuleMap(ruleContext);
if (moduleMap != null) {
contextBuilder.setCppModuleMap(moduleMap);
}
final CppCompilationContext context = contextBuilder.build();
boolean supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN);
boolean supportsHeaderParsing = ruleContext.attributes().get("supports_header_parsing", BOOLEAN);
NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.compileOrder();
coverageEnvironment.add(Pair.of("COVERAGE_GCOV_PATH", cppConfiguration.getGcovExecutable().getPathString()));
if (cppConfiguration.getFdoInstrument() != null) {
coverageEnvironment.add(Pair.of("FDO_DIR", cppConfiguration.getFdoInstrument().getPathString()));
}
CcToolchainProvider provider = new CcToolchainProvider(cppConfiguration, crosstool, fullInputsForCrosstool(ruleContext, crosstoolMiddleman), compile, strip, objcopy, fullInputsForLink(ruleContext, link), ruleContext.getPrerequisiteArtifact("$interface_library_builder", Mode.HOST), dwp, libcLink, staticRuntimeLinkInputs, staticRuntimeLinkMiddleman, dynamicRuntimeLinkSymlinks, dynamicRuntimeLinkMiddleman, runtimeSolibDir, context, supportsParamFiles, supportsHeaderParsing, getBuildVariables(ruleContext), getBuiltinIncludes(ruleContext), coverageEnvironment.build(), ruleContext.getPrerequisiteArtifact("$link_dynamic_library_tool", Mode.HOST), getEnvironment(ruleContext));
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext).add(CcToolchainProvider.class, provider).add(FdoSupportProvider.class, fdoSupport.getFdoSupport().createFdoSupportProvider(ruleContext)).setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build()).add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));
// If output_license is specified on the cc_toolchain rule, override the transitive licenses
// with that one. This is necessary because cc_toolchain is used in the target configuration,
// but it is sort-of-kind-of a tool, but various parts of it are linked into the output...
// ...so we trust the judgment of the author of the cc_toolchain rule to figure out what
// licenses should be propagated to C++ targets.
// TODO(elenairina): Remove this and use Attribute.Builder.useOutputLicenses() on the
// :cc_toolchain attribute instead.
final License outputLicense = ruleContext.getRule().getToolOutputLicense(ruleContext.attributes());
if (outputLicense != null && outputLicense != License.NO_LICENSE) {
final NestedSet<TargetLicense> license = NestedSetBuilder.create(Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense));
LicensesProvider licensesProvider = new LicensesProvider() {
@Override
public NestedSet<TargetLicense> getTransitiveLicenses() {
return license;
}
@Override
public TargetLicense getOutputLicenses() {
return new TargetLicense(label, outputLicense);
}
@Override
public boolean hasOutputLicenses() {
return true;
}
};
builder.add(LicensesProvider.class, licensesProvider);
}
return builder.build();
}
use of com.google.devtools.build.lib.analysis.TransitiveInfoCollection in project bazel by bazelbuild.
the class CcToolchain method getFiles.
private NestedSet<Artifact> getFiles(RuleContext context, String attribute) {
TransitiveInfoCollection dep = context.getPrerequisite(attribute, Mode.HOST);
MiddlemanProvider middlemanProvider = dep.getProvider(MiddlemanProvider.class);
// filesToBuild (e.g. if it is a simple input file)
return middlemanProvider != null ? middlemanProvider.getMiddlemanArtifact() : dep.getProvider(FileProvider.class).getFilesToBuild();
}
Aggregations