use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class FakeCppCompileAction method execute.
@Override
@ThreadCompatible
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException {
setModuleFileFlags();
Executor executor = actionExecutionContext.getExecutor();
// First, do a normal compilation, to generate the ".d" file. The generated object file is built
// to a temporary location (tempOutputFile) and ignored afterwards.
LOG.info("Generating " + getDotdFile());
CppCompileActionContext context = executor.getContext(actionContext);
CppCompileActionContext.Reply reply = null;
try {
// We delegate stdout/stderr to nowhere, i.e. same as redirecting to /dev/null.
reply = context.execWithReply(this, actionExecutionContext.withFileOutErr(new FileOutErr()));
} catch (ExecException e) {
// We ignore failures here (other than capturing the Distributor reply).
// The compilation may well fail (that's the whole point of negative compilation tests).
// We execute it here just for the side effect of generating the ".d" file.
reply = context.getReplyFromException(e, this);
if (reply == null) {
// This can only happen if the ExecException does not come from remote execution.
throw e.toActionExecutionException("Fake C++ Compilation of rule '" + getOwner().getLabel() + "'", executor.getVerboseFailures(), this);
}
}
IncludeScanningContext scanningContext = executor.getContext(IncludeScanningContext.class);
Path execRoot = executor.getExecRoot();
NestedSet<Artifact> discoveredInputs;
if (getDotdFile() == null) {
discoveredInputs = NestedSetBuilder.<Artifact>stableOrder().build();
} else {
HeaderDiscovery.Builder discoveryBuilder = new HeaderDiscovery.Builder().setAction(this).setDotdFile(getDotdFile()).setSourceFile(getSourceFile()).setSpecialInputsHandler(specialInputsHandler).setDependencySet(processDepset(execRoot, reply)).setPermittedSystemIncludePrefixes(getPermittedSystemIncludePrefixes(execRoot)).setAllowedDerivedinputsMap(getAllowedDerivedInputsMap());
if (cppSemantics.needsIncludeValidation()) {
discoveryBuilder.shouldValidateInclusions();
}
discoveredInputs = discoveryBuilder.build().discoverInputsFromDotdFiles(execRoot, scanningContext.getArtifactResolver());
}
// Clear in-memory .d files early.
reply = null;
// depends on.
try {
validateInclusions(discoveredInputs, actionExecutionContext.getArtifactExpander(), executor.getEventHandler());
} catch (ActionExecutionException e) {
// TODO(bazel-team): (2009) make this into an error, once most of the current warnings
// are fixed.
executor.getEventHandler().handle(Event.warn(getOwner().getLocation(), e.getMessage() + ";\n this warning may eventually become an error"));
}
updateActionInputs(discoveredInputs);
// Generate a fake ".o" file containing the command line needed to generate
// the real object file.
LOG.info("Generating " + outputFile);
// A cc_fake_binary rule generates fake .o files and a fake target file,
// which merely contain instructions on building the real target. We need to
// be careful to use a new set of output file names in the instructions, as
// to not overwrite the fake output files when someone tries to follow the
// instructions. As the real compilation is executed by the test from its
// runfiles directory (where writing is forbidden), we patch the command
// line to write to $TEST_TMPDIR instead.
final String outputPrefix = "$TEST_TMPDIR/";
String argv = Joiner.on(' ').join(Iterables.transform(getArgv(outputFile.getExecPath()), new Function<String, String>() {
@Override
public String apply(String input) {
String result = ShellEscaper.escapeString(input);
// -c <tempOutputFile>, but here it has to be outputFile, so we replace it.
if (input.equals(tempOutputFile.getPathString())) {
result = outputPrefix + ShellEscaper.escapeString(outputFile.getExecPathString());
}
if (input.equals(outputFile.getExecPathString()) || input.equals(getDotdFile().getSafeExecPath().getPathString())) {
result = outputPrefix + ShellEscaper.escapeString(input);
}
return result;
}
}));
// the compilation would fail.
try {
// Ensure that the .d file and .o file are siblings, so that the "mkdir" below works for
// both.
Preconditions.checkState(outputFile.getExecPath().getParentDirectory().equals(getDotdFile().getSafeExecPath().getParentDirectory()));
FileSystemUtils.writeContent(outputFile.getPath(), ISO_8859_1, outputFile.getPath().getBaseName() + ": " + "mkdir -p " + outputPrefix + "$(dirname " + outputFile.getExecPath() + ")" + " && " + argv + "\n");
} catch (IOException e) {
throw new ActionExecutionException("failed to create fake compile command for rule '" + getOwner().getLabel() + ": " + e.getMessage(), this, false);
}
}
use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class NativeLibs method filterUniqueSharedLibraries.
private static Iterable<Artifact> filterUniqueSharedLibraries(RuleContext ruleContext, Artifact linkedLibrary, NestedSet<? extends LinkerInput> libraries) {
Map<String, Artifact> basenames = new HashMap<>();
Set<Artifact> artifacts = new HashSet<>();
if (linkedLibrary != null) {
basenames.put(linkedLibrary.getExecPath().getBaseName(), linkedLibrary);
}
for (LinkerInput linkerInput : libraries) {
String name = linkerInput.getArtifact().getFilename();
if (!(CppFileTypes.SHARED_LIBRARY.matches(name) || CppFileTypes.VERSIONED_SHARED_LIBRARY.matches(name))) {
// This is not a shared library and will not be loaded by Android, so skip it.
continue;
}
Artifact artifact = linkerInput.getOriginalLibraryArtifact();
if (!artifacts.add(artifact)) {
// We have already reached this library, e.g., through a different solib symlink.
continue;
}
String basename = artifact.getExecPath().getBaseName();
Artifact oldArtifact = basenames.put(basename, artifact);
if (oldArtifact != null) {
// There may be name collisions in the libraries which were provided, so
// check for this at this step.
ruleContext.ruleError("Each library in the transitive closure must have a unique basename to avoid " + "name collisions when packaged into an apk, but two libraries have the basename '" + basename + "': " + artifact.prettyPrint() + " and " + oldArtifact.prettyPrint() + ((oldArtifact == linkedLibrary) ? " (the library compiled for this target)" : ""));
}
}
return artifacts;
}
use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class CppCompileAction method discoverInputsStage2.
@Override
public Iterable<Artifact> discoverInputsStage2(SkyFunction.Environment env) throws ActionExecutionException, InterruptedException {
if (this.usedModules == null) {
return null;
}
Map<Artifact, SkyKey> skyKeys = new HashMap<>();
for (Artifact artifact : this.usedModules) {
skyKeys.put(artifact, ActionLookupValue.key((ActionLookupKey) artifact.getArtifactOwner()));
}
Map<SkyKey, SkyValue> skyValues = env.getValues(skyKeys.values());
Set<Artifact> additionalModules = Sets.newLinkedHashSet();
for (Artifact artifact : this.usedModules) {
SkyKey skyKey = skyKeys.get(artifact);
ActionLookupValue value = (ActionLookupValue) skyValues.get(skyKey);
Preconditions.checkNotNull(value, "Owner %s of %s not in graph %s", artifact.getArtifactOwner(), artifact, skyKey);
CppCompileAction action = (CppCompileAction) value.getGeneratingAction(artifact);
for (Artifact input : action.getInputs()) {
if (CppFileTypes.CPP_MODULE.matches(input.getFilename())) {
additionalModules.add(input);
}
}
}
ImmutableSet.Builder<Artifact> topLevelModules = ImmutableSet.builder();
for (Artifact artifact : this.usedModules) {
if (!additionalModules.contains(artifact)) {
topLevelModules.add(artifact);
}
}
this.topLevelModules = topLevelModules.build();
this.additionalInputs = new ImmutableList.Builder<Artifact>().addAll(this.additionalInputs).addAll(additionalModules).build();
this.usedModules = null;
return additionalModules;
}
use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class CppCompileAction method computeKey.
@Override
public String computeKey() {
Fingerprint f = new Fingerprint();
f.addUUID(actionClassId);
f.addStringMap(getEnvironment());
f.addStringMap(executionInfo);
// For the argv part of the cache key, ignore all compiler flags that explicitly denote module
// file (.pcm) inputs. Depending on input discovery, some of the unused ones are removed from
// the command line. However, these actually don't have an influence on the compile itself and
// so ignoring them for the cache key calculation does not affect correctness. The compile
// itself is fully determined by the input source files and module maps.
// A better long-term solution would be to make the compiler to find them automatically and
// never hand in the .pcm files explicitly on the command line in the first place.
f.addStrings(cppCompileCommandLine.getArgv(getInternalOutputFile(), null));
/*
* getArgv() above captures all changes which affect the compilation
* command and hence the contents of the object file. But we need to
* also make sure that we reexecute the action if any of the fields
* that affect whether validateIncludes() will report an error or warning
* have changed, otherwise we might miss some errors.
*/
f.addPaths(context.getDeclaredIncludeDirs());
f.addPaths(context.getDeclaredIncludeWarnDirs());
for (Artifact declaredIncludeSrc : context.getDeclaredIncludeSrcs()) {
f.addPath(declaredIncludeSrc.getExecPath());
}
// mark the boundary between input types
f.addInt(0);
for (Artifact input : getMandatoryInputs()) {
f.addPath(input.getExecPath());
}
f.addInt(0);
for (Artifact input : prunableInputs) {
f.addPath(input.getExecPath());
}
return f.hexDigestAndReset();
}
use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.
the class CppCompileAction method getAllowedDerivedInputsMap.
protected Map<PathFragment, Artifact> getAllowedDerivedInputsMap() {
Map<PathFragment, Artifact> allowedDerivedInputMap = new HashMap<>();
addToMap(allowedDerivedInputMap, mandatoryInputs);
addToMap(allowedDerivedInputMap, prunableInputs);
addToMap(allowedDerivedInputMap, getDeclaredIncludeSrcs());
addToMap(allowedDerivedInputMap, context.getTransitiveCompilationPrerequisites());
addToMap(allowedDerivedInputMap, context.getTransitiveModules(usePic));
Artifact artifact = getSourceFile();
if (!artifact.isSourceArtifact()) {
allowedDerivedInputMap.put(artifact.getExecPath(), artifact);
}
return allowedDerivedInputMap;
}
Aggregations