use of com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider in project bazel by bazelbuild.
the class CcIncLibrary method create.
@Override
public ConfiguredTarget create(final RuleContext ruleContext) throws RuleErrorException, InterruptedException {
CcToolchainProvider ccToolchain = CppHelper.getToolchain(ruleContext, ":cc_toolchain");
FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext, ccToolchain);
PathFragment packageFragment = ruleContext.getPackageDirectory();
// The rule needs a unique location for the include directory, which doesn't conflict with any
// other rule. For that reason, the include directory is at:
// configuration/package_name/_/target_name
// And then the symlink is placed at:
// configuration/package_name/_/target_name/package_name
// So that these inclusions can be resolved correctly:
// #include "package_name/a.h"
//
// The target of the symlink is:
// package_name/targetPrefix/
// All declared header files must be below that directory.
String expandedIncSymlinkAttr = ruleContext.attributes().get("prefix", Type.STRING);
// We use an additional "_" directory here to avoid conflicts between this and previous Blaze
// versions. Previous Blaze versions created a directory symlink; the new version does not
// detect that the output directory isn't a directory, and tries to put the symlinks into what
// is actually a symlink into the source tree.
PathFragment includeDirectory = new PathFragment("_").getRelative(ruleContext.getTarget().getName());
Root configIncludeDirectory = ruleContext.getConfiguration().getIncludeDirectory(ruleContext.getRule().getRepository());
PathFragment includePath = configIncludeDirectory.getExecPath().getRelative(packageFragment).getRelative(includeDirectory);
Path includeRoot = configIncludeDirectory.getPath().getRelative(packageFragment).getRelative(includeDirectory);
// For every source artifact, we compute a virtual artifact that is below the include directory.
// These are used for include checking.
PathFragment prefixFragment = packageFragment.getRelative(expandedIncSymlinkAttr);
if (!prefixFragment.isNormalized()) {
ruleContext.attributeWarning("prefix", "should not contain '.' or '..' elements");
}
ImmutableSortedMap.Builder<Artifact, Artifact> virtualArtifactMapBuilder = ImmutableSortedMap.orderedBy(Artifact.EXEC_PATH_COMPARATOR);
prefixFragment = prefixFragment.normalize();
ImmutableList<Artifact> hdrs = ruleContext.getPrerequisiteArtifacts("hdrs", Mode.TARGET).list();
for (Artifact src : hdrs) {
// All declared header files must start with package/targetPrefix.
if (!src.getRootRelativePath().startsWith(prefixFragment)) {
ruleContext.attributeError("hdrs", src + " does not start with '" + prefixFragment.getPathString() + "'");
return null;
}
// Remove the targetPrefix from within the exec path of the source file, and prepend the
// unique directory prefix, e.g.:
// third_party/foo/1.2/bar/a.h -> third_party/foo/name/third_party/foo/bar/a.h
PathFragment suffix = src.getRootRelativePath().relativeTo(prefixFragment);
PathFragment virtualPath = includeDirectory.getRelative(packageFragment).getRelative(suffix);
// These virtual artifacts have the symlink action as generating action.
Artifact virtualArtifact = ruleContext.getPackageRelativeArtifact(virtualPath, configIncludeDirectory);
virtualArtifactMapBuilder.put(virtualArtifact, src);
}
ImmutableSortedMap<Artifact, Artifact> virtualArtifactMap = virtualArtifactMapBuilder.build();
ruleContext.registerAction(new CreateIncSymlinkAction(ruleContext.getActionOwner(), virtualArtifactMap, includeRoot));
FdoSupportProvider fdoSupport = CppHelper.getFdoSupport(ruleContext, ":cc_toolchain");
CcLibraryHelper.Info info = new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport).addIncludeDirs(Arrays.asList(includePath)).addPublicHeaders(virtualArtifactMap.keySet()).addDeps(ruleContext.getPrerequisites("deps", Mode.TARGET)).build();
// cc_inc_library doesn't compile any file - no compilation outputs available.
InstrumentedFilesProvider instrumentedFilesProvider = new CcCommon(ruleContext).getInstrumentedFilesProvider(new ArrayList<Artifact>(), /*withBaselineCoverage=*/
true);
return new RuleConfiguredTargetBuilder(ruleContext).addProviders(info.getProviders()).addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider()).addOutputGroups(info.getOutputGroups()).add(InstrumentedFilesProvider.class, instrumentedFilesProvider).add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY)).build();
}
use of com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider in project bazel by bazelbuild.
the class CcLibrary method init.
public static void init(CppSemantics semantics, RuleContext ruleContext, RuleConfiguredTargetBuilder targetBuilder, LinkTargetType linkType, boolean neverLink, boolean linkStatic, boolean collectLinkstamp, boolean addDynamicRuntimeInputArtifactsToRunfiles) throws RuleErrorException, InterruptedException {
final CcCommon common = new CcCommon(ruleContext);
CcToolchainProvider ccToolchain = common.getToolchain();
FdoSupportProvider fdoSupport = common.getFdoSupport();
FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext, ccToolchain);
PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);
semantics.validateAttributes(ruleContext);
if (ruleContext.hasErrors()) {
return;
}
CcLibraryHelper helper = new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport).fromCommon(common).addLinkopts(common.getLinkopts()).addSources(common.getSources()).addPublicHeaders(common.getHeaders()).enableCcNativeLibrariesProvider().enableCompileProviders().enableInterfaceSharedObjects().setGenerateLinkActionsIfEmpty(ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE).setLinkType(linkType).setNeverLink(neverLink).addPrecompiledFiles(precompiledFiles);
if (collectLinkstamp) {
helper.addLinkstamps(ruleContext.getPrerequisites("linkstamp", Mode.TARGET));
}
Artifact soImplArtifact = null;
boolean supportsDynamicLinker = ruleContext.getFragment(CppConfiguration.class).supportsDynamicLinker();
// TODO(djasper): This is hacky. We should actually try to figure out whether we generate
// ccOutputs.
boolean createDynamicLibrary = !linkStatic && supportsDynamicLinker && (appearsToHaveObjectFiles(ruleContext.attributes()) || featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN));
if (ruleContext.getRule().isAttrDefined("outs", Type.STRING_LIST)) {
List<String> outs = ruleContext.attributes().get("outs", Type.STRING_LIST);
if (outs.size() > 1) {
ruleContext.attributeError("outs", "must be a singleton list");
} else if (outs.size() == 1) {
PathFragment soImplFilename = new PathFragment(ruleContext.getLabel().getName());
soImplFilename = soImplFilename.replaceName(outs.get(0));
if (!soImplFilename.getPathString().endsWith(".so")) {
// Sanity check.
ruleContext.attributeError("outs", "file name must end in '.so'");
}
if (createDynamicLibrary) {
soImplArtifact = ruleContext.getBinArtifact(soImplFilename);
}
}
}
if (ruleContext.getRule().isAttrDefined("srcs", BuildType.LABEL_LIST)) {
ruleContext.checkSrcsSamePackage(true);
}
if (ruleContext.getRule().isAttrDefined("textual_hdrs", BuildType.LABEL_LIST)) {
helper.addPublicTextualHeaders(ruleContext.getPrerequisiteArtifacts("textual_hdrs", Mode.TARGET).list());
}
if (common.getLinkopts().contains("-static")) {
ruleContext.attributeWarning("linkopts", "Using '-static' here won't work. " + "Did you mean to use 'linkstatic=1' instead?");
}
helper.setCreateDynamicLibrary(createDynamicLibrary);
helper.setDynamicLibrary(soImplArtifact);
// which only happens when some rule explicitly depends on the dynamic library.
if (!createDynamicLibrary && !supportsDynamicLinker) {
Artifact solibArtifact = CppHelper.getLinuxLinkedArtifact(ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(), ImmutableList.of(solibArtifact), "Toolchain does not support dynamic linking"));
} else if (!createDynamicLibrary && ruleContext.attributes().isConfigurable("srcs")) {
// If "srcs" is configurable, the .so output is always declared because the logic that
// determines implicit outs doesn't know which value of "srcs" will ultimately get chosen.
// Here, where we *do* have the correct value, it may not contain any source files to
// generate an .so with. If that's the case, register a fake generating action to prevent
// a "no generating action for this artifact" error.
Artifact solibArtifact = CppHelper.getLinuxLinkedArtifact(ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(), ImmutableList.of(solibArtifact), "configurable \"srcs\" triggers an implicit .so output " + "even though there are no sources to compile in this configuration"));
}
/*
* Add the libraries from srcs, if any. For static/mostly static
* linking we setup the dynamic libraries if there are no static libraries
* to choose from. Path to the libraries will be mangled to avoid using
* absolute path names on the -rpath, but library filenames will be
* preserved (since some libraries might have SONAME tag) - symlink will
* be created to the parent directory instead.
*
* For compatibility with existing BUILD files, any ".a" or ".lo" files listed in
* srcs are assumed to be position-independent code, or at least suitable for
* inclusion in shared libraries, unless they end with ".nopic.a" or ".nopic.lo".
*
* Note that some target platforms do not require shared library code to be PIC.
*/
Iterable<LibraryToLink> staticLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.STATIC_LIBRARY, precompiledFiles.getStaticLibraries());
Iterable<LibraryToLink> alwayslinkLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, precompiledFiles.getAlwayslinkStaticLibraries());
Iterable<LibraryToLink> picStaticLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.STATIC_LIBRARY, precompiledFiles.getPicStaticLibraries());
Iterable<LibraryToLink> picAlwayslinkLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, precompiledFiles.getPicAlwayslinkLibraries());
helper.addStaticLibraries(staticLibrariesFromSrcs);
helper.addStaticLibraries(alwayslinkLibrariesFromSrcs);
helper.addPicStaticLibraries(picStaticLibrariesFromSrcs);
helper.addPicStaticLibraries(picAlwayslinkLibrariesFromSrcs);
helper.addDynamicLibraries(Iterables.transform(precompiledFiles.getSharedLibraries(), new Function<Artifact, LibraryToLink>() {
@Override
public LibraryToLink apply(Artifact library) {
return LinkerInputs.solibLibraryToLink(common.getDynamicLibrarySymlink(library, true), library, CcLinkingOutputs.libraryIdentifierOf(library));
}
}));
CcLibraryHelper.Info info = helper.build();
/*
* We always generate a static library, even if there aren't any source files.
* This keeps things simpler by avoiding special cases when making use of the library.
* For example, this is needed to ensure that building a library with "bazel build"
* will also build all of the library's "deps".
* However, we only generate a dynamic library if there are source files.
*/
// For now, we don't add the precompiled libraries to the files to build.
CcLinkingOutputs linkedLibraries = info.getCcLinkingOutputsExcludingPrecompiledLibraries();
NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getStaticLibraries()));
filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getPicStaticLibraries()));
filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getDynamicLibraries()));
filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getExecutionDynamicLibraries()));
CcLinkingOutputs linkingOutputs = info.getCcLinkingOutputs();
if (!featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
warnAboutEmptyLibraries(ruleContext, info.getCcCompilationOutputs(), linkStatic);
}
NestedSet<Artifact> filesToBuild = filesBuilder.build();
Runfiles staticRunfiles = collectRunfiles(ruleContext, linkingOutputs, ccToolchain, neverLink, addDynamicRuntimeInputArtifactsToRunfiles, true);
Runfiles sharedRunfiles = collectRunfiles(ruleContext, linkingOutputs, ccToolchain, neverLink, addDynamicRuntimeInputArtifactsToRunfiles, false);
List<Artifact> instrumentedObjectFiles = new ArrayList<>();
instrumentedObjectFiles.addAll(info.getCcCompilationOutputs().getObjectFiles(false));
instrumentedObjectFiles.addAll(info.getCcCompilationOutputs().getObjectFiles(true));
InstrumentedFilesProvider instrumentedFilesProvider = common.getInstrumentedFilesProvider(instrumentedObjectFiles, /*withBaselineCoverage=*/
true);
CppHelper.maybeAddStaticLinkMarkerProvider(targetBuilder, ruleContext);
targetBuilder.setFilesToBuild(filesToBuild).addProviders(info.getProviders()).addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider()).addOutputGroups(info.getOutputGroups()).addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider).addProvider(RunfilesProvider.class, RunfilesProvider.withData(staticRunfiles, sharedRunfiles)).addProvider(CppRunfilesProvider.class, new CppRunfilesProvider(staticRunfiles, sharedRunfiles)).addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, collectHiddenTopLevelArtifacts(ruleContext, info.getCcCompilationOutputs())).addOutputGroup(CcLibraryHelper.HIDDEN_HEADER_TOKENS, CcLibraryHelper.collectHeaderTokens(ruleContext, info.getCcCompilationOutputs()));
}
use of com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider in project bazel by bazelbuild.
the class SkylarkIntegrationTest method testInstrumentedFilesProviderWithCodeCoverageEnabled.
@Test
public void testInstrumentedFilesProviderWithCodeCoverageEnabled() throws Exception {
scratch.file("test/skylark/extension.bzl", "def custom_rule_impl(ctx):", " return struct(instrumented_files=struct(", " extensions = ['txt'],", " source_attributes = ['attr1'],", " dependency_attributes = ['attr2']))", "", "custom_rule = rule(implementation = custom_rule_impl,", " attrs = {", " 'attr1': attr.label_list(mandatory = True, allow_files=True),", " 'attr2': attr.label_list(mandatory = True)})");
scratch.file("test/skylark/BUILD", "load('/test/skylark/extension', 'custom_rule')", "", "java_library(name='jl', srcs = [':A.java'])", "custom_rule(name = 'cr', attr1 = [':a.txt', ':a.random'], attr2 = [':jl'])");
useConfiguration("--collect_code_coverage");
ConfiguredTarget target = getConfiguredTarget("//test/skylark:cr");
assertEquals("//test/skylark:cr", target.getLabel().toString());
InstrumentedFilesProvider provider = target.getProvider(InstrumentedFilesProvider.class);
assertWithMessage("InstrumentedFilesProvider should be set.").that(provider).isNotNull();
assertThat(ActionsTestUtil.baseArtifactNames(provider.getInstrumentedFiles())).containsExactly("a.txt", "A.java");
}
use of com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider in project bazel by bazelbuild.
the class SkylarkRuleConfiguredTargetBuilder method parseProviderKeys.
private static void parseProviderKeys(SkylarkClassObject provider, Boolean isDefaultProvider, RuleContext ruleContext, Location loc, Artifact executable, Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes, RuleConfiguredTargetBuilder builder) throws EvalException {
Runfiles statelessRunfiles = null;
Runfiles dataRunfiles = null;
Runfiles defaultRunfiles = null;
for (String key : provider.getKeys()) {
if (key.equals("files")) {
// If we specify files_to_build we don't have the executable in it by default.
builder.setFilesToBuild(cast("files", provider, SkylarkNestedSet.class, Artifact.class, loc).getSet(Artifact.class));
} else if (key.equals("runfiles")) {
statelessRunfiles = cast("runfiles", provider, Runfiles.class, loc);
} else if (key.equals("data_runfiles")) {
dataRunfiles = cast("data_runfiles", provider, Runfiles.class, loc);
} else if (key.equals("default_runfiles")) {
defaultRunfiles = cast("default_runfiles", provider, Runfiles.class, loc);
} else if (key.equals("output_groups")) {
addOutputGroups(provider.getValue(key), loc, builder);
} else if (key.equals("instrumented_files")) {
SkylarkClassObject insStruct = cast("instrumented_files", provider, SkylarkClassObject.class, loc);
Location insLoc = insStruct.getCreationLoc();
FileTypeSet fileTypeSet = FileTypeSet.ANY_FILE;
if (insStruct.getKeys().contains("extensions")) {
@SuppressWarnings("unchecked") List<String> exts = cast("extensions", insStruct, SkylarkList.class, String.class, insLoc);
if (exts.isEmpty()) {
fileTypeSet = FileTypeSet.NO_FILE;
} else {
FileType[] fileTypes = new FileType[exts.size()];
for (int i = 0; i < fileTypes.length; i++) {
fileTypes[i] = FileType.of(exts.get(i));
}
fileTypeSet = FileTypeSet.of(fileTypes);
}
}
List<String> dependencyAttributes = Collections.emptyList();
if (insStruct.getKeys().contains("dependency_attributes")) {
dependencyAttributes = cast("dependency_attributes", insStruct, SkylarkList.class, String.class, insLoc);
}
List<String> sourceAttributes = Collections.emptyList();
if (insStruct.getKeys().contains("source_attributes")) {
sourceAttributes = cast("source_attributes", insStruct, SkylarkList.class, String.class, insLoc);
}
InstrumentationSpec instrumentationSpec = new InstrumentationSpec(fileTypeSet).withSourceAttributes(sourceAttributes.toArray(new String[0])).withDependencyAttributes(dependencyAttributes.toArray(new String[0]));
InstrumentedFilesProvider instrumentedFilesProvider = InstrumentedFilesCollector.collect(ruleContext, instrumentationSpec, InstrumentedFilesCollector.NO_METADATA_COLLECTOR, Collections.<Artifact>emptySet());
builder.addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider);
} else if (registeredProviderTypes.containsKey(key)) {
Class<? extends TransitiveInfoProvider> providerType = registeredProviderTypes.get(key);
TransitiveInfoProvider providerField = cast(key, provider, providerType, loc);
builder.addProvider(providerType, providerField);
} else if (isDefaultProvider) {
// Custom keys are not allowed for default providers
throw new EvalException(loc, "Invalid key for default provider: " + key);
} else if (key.equals("providers")) {
Iterable iterable = cast(key, provider, Iterable.class, loc);
for (Object o : iterable) {
SkylarkClassObject declaredProvider = SkylarkType.cast(o, SkylarkClassObject.class, loc, "The value of 'providers' should be a sequence of declared providers");
builder.addSkylarkDeclaredProvider(declaredProvider, loc);
}
} else if (!key.equals("executable")) {
// We handled executable already.
builder.addSkylarkTransitiveInfo(key, provider.getValue(key), loc);
}
}
addSimpleProviders(builder, ruleContext, loc, executable, statelessRunfiles, dataRunfiles, defaultRunfiles, (isDefaultProvider ? provider : null));
}
use of com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider in project bazel by bazelbuild.
the class CcBinary method addTransitiveInfoProviders.
private static void addTransitiveInfoProviders(RuleContext ruleContext, CppConfiguration cppConfiguration, CcCommon common, RuleConfiguredTargetBuilder builder, NestedSet<Artifact> filesToBuild, CcCompilationOutputs ccCompilationOutputs, CppCompilationContext cppCompilationContext, CcLinkingOutputs linkingOutputs, DwoArtifactsCollector dwoArtifacts, TransitiveLipoInfoProvider transitiveLipoInfo, boolean fake) {
List<Artifact> instrumentedObjectFiles = new ArrayList<>();
instrumentedObjectFiles.addAll(ccCompilationOutputs.getObjectFiles(false));
instrumentedObjectFiles.addAll(ccCompilationOutputs.getObjectFiles(true));
InstrumentedFilesProvider instrumentedFilesProvider = common.getInstrumentedFilesProvider(instrumentedObjectFiles, !TargetUtils.isTestRule(ruleContext.getRule()) && !fake);
NestedSet<Artifact> headerTokens = CcLibraryHelper.collectHeaderTokens(ruleContext, ccCompilationOutputs);
NestedSet<Artifact> filesToCompile = ccCompilationOutputs.getFilesToCompile(cppConfiguration.isLipoContextCollector(), cppConfiguration.processHeadersInDependencies(), CppHelper.usePic(ruleContext, false));
builder.setFilesToBuild(filesToBuild).addProvider(CppCompilationContext.class, cppCompilationContext).addProvider(TransitiveLipoInfoProvider.class, transitiveLipoInfo).addProvider(CcExecutionDynamicLibrariesProvider.class, new CcExecutionDynamicLibrariesProvider(collectExecutionDynamicLibraryArtifacts(ruleContext, linkingOutputs.getExecutionDynamicLibraries()))).addProvider(CcNativeLibraryProvider.class, new CcNativeLibraryProvider(collectTransitiveCcNativeLibraries(ruleContext, linkingOutputs.getDynamicLibraries()))).addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider).addProvider(CppDebugFileProvider.class, new CppDebugFileProvider(dwoArtifacts.getDwoArtifacts(), dwoArtifacts.getPicDwoArtifacts())).addOutputGroup(OutputGroupProvider.TEMP_FILES, getTemps(cppConfiguration, ccCompilationOutputs)).addOutputGroup(OutputGroupProvider.FILES_TO_COMPILE, filesToCompile).addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, headerTokens).addOutputGroup(OutputGroupProvider.COMPILATION_PREREQUISITES, CcCommon.collectCompilationPrerequisites(ruleContext, cppCompilationContext));
CppHelper.maybeAddStaticLinkMarkerProvider(builder, ruleContext);
}
Aggregations