Search in sources :

Example 1 with ThreadCompatible

use of com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible in project bazel by bazelbuild.

the class CppLinkAction method executeFake.

// Don't forget to update FAKE_LINK_GUID if you modify this method.
@ThreadCompatible
private void executeFake() throws ActionExecutionException {
    // The uses of getLinkConfiguration in this method may not be consistent with the computed key.
    // I.e., this may be incrementally incorrect.
    final Collection<Artifact> linkstampOutputs = getLinkCommandLine().getLinkstamps().values();
    // Prefix all fake output files in the command line with $TEST_TMPDIR/.
    final String outputPrefix = "$TEST_TMPDIR/";
    List<String> escapedLinkArgv = escapeLinkArgv(linkCommandLine.getRawLinkArgv(), linkstampOutputs, outputPrefix);
    // Write the commands needed to build the real target to the fake target
    // file.
    StringBuilder s = new StringBuilder();
    Joiner.on('\n').appendTo(s, "# This is a fake target file, automatically generated.", "# Do not edit by hand!", "echo $0 is a fake target file and not meant to be executed.", "exit 0", "EOS", "", "makefile_dir=.", "");
    try {
        // Concatenate all the (fake) .o files into the result.
        for (LinkerInput linkerInput : getLinkCommandLine().getLinkerInputs()) {
            Artifact objectFile = linkerInput.getArtifact();
            if ((CppFileTypes.OBJECT_FILE.matches(objectFile.getFilename()) || CppFileTypes.PIC_OBJECT_FILE.matches(objectFile.getFilename())) && linkerInput.isFake()) {
                // (IOException)
                s.append(FileSystemUtils.readContentAsLatin1(objectFile.getPath()));
            }
        }
        s.append(getOutputFile().getBaseName()).append(": ");
        for (Artifact linkstamp : linkstampOutputs) {
            s.append("mkdir -p " + outputPrefix + linkstamp.getExecPath().getParentDirectory() + " && ");
        }
        Joiner.on(' ').appendTo(s, ShellEscaper.escapeAll(linkCommandLine.finalizeAlreadyEscapedWithLinkstampCommands(escapedLinkArgv, outputPrefix)));
        s.append('\n');
        if (getOutputFile().exists()) {
            // (IOException)
            getOutputFile().setWritable(true);
        }
        FileSystemUtils.writeContent(getOutputFile(), ISO_8859_1, s.toString());
        // (IOException)
        getOutputFile().setExecutable(true);
        for (Artifact linkstamp : linkstampOutputs) {
            FileSystemUtils.touchFile(linkstamp.getPath());
        }
    } catch (IOException e) {
        throw new ActionExecutionException("failed to create fake link command for rule '" + getOwner().getLabel() + ": " + e.getMessage(), this, false);
    }
}
Also used : IOException(java.io.IOException) ActionExecutionException(com.google.devtools.build.lib.actions.ActionExecutionException) Artifact(com.google.devtools.build.lib.actions.Artifact) ThreadCompatible(com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)

Example 2 with ThreadCompatible

use of com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible in project bazel by bazelbuild.

the class CppLinkAction method execute.

@Override
@ThreadCompatible
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException {
    if (fake) {
        executeFake();
    } else {
        Executor executor = actionExecutionContext.getExecutor();
        try {
            // Collect input files
            List<ActionInput> allInputs = new ArrayList<>();
            Artifact.addExpandedArtifacts(getMandatoryInputs(), allInputs, actionExecutionContext.getArtifactExpander());
            ImmutableMap<String, String> executionInfo = ImmutableMap.of();
            if (needsToRunOnMac()) {
                executionInfo = ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, "");
            }
            Spawn spawn = new SimpleSpawn(this, ImmutableList.copyOf(getCommandLine()), getEnvironment(), executionInfo, ImmutableList.copyOf(allInputs), getOutputs().asList(), estimateResourceConsumptionLocal());
            executor.getSpawnActionContext(getMnemonic()).exec(spawn, actionExecutionContext);
        } catch (ExecException e) {
            throw e.toActionExecutionException("Linking of rule '" + getOwner().getLabel() + "'", executor.getVerboseFailures(), this);
        }
    }
}
Also used : Executor(com.google.devtools.build.lib.actions.Executor) ActionInput(com.google.devtools.build.lib.actions.ActionInput) SimpleSpawn(com.google.devtools.build.lib.actions.SimpleSpawn) ExecException(com.google.devtools.build.lib.actions.ExecException) ArrayList(java.util.ArrayList) SimpleSpawn(com.google.devtools.build.lib.actions.SimpleSpawn) Spawn(com.google.devtools.build.lib.actions.Spawn) ThreadCompatible(com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)

Example 3 with ThreadCompatible

use of com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible 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);
    }
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) FileOutErr(com.google.devtools.build.lib.util.io.FileOutErr) ExecException(com.google.devtools.build.lib.actions.ExecException) IOException(java.io.IOException) Artifact(com.google.devtools.build.lib.actions.Artifact) Function(com.google.common.base.Function) Executor(com.google.devtools.build.lib.actions.Executor) ActionExecutionException(com.google.devtools.build.lib.actions.ActionExecutionException) ThreadCompatible(com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)

Example 4 with ThreadCompatible

use of com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible in project bazel by bazelbuild.

the class BuildView method update.

@ThreadCompatible
public AnalysisResult update(LoadingResult loadingResult, BuildConfigurationCollection configurations, List<String> aspects, Options viewOptions, TopLevelArtifactContext topLevelOptions, ExtendedEventHandler eventHandler, EventBus eventBus) throws ViewCreationFailedException, InterruptedException {
    LOG.info("Starting analysis");
    pollInterruptedStatus();
    skyframeBuildView.resetEvaluatedConfiguredTargetKeysSet();
    Collection<Target> targets = loadingResult.getTargets();
    eventBus.post(new AnalysisPhaseStartedEvent(targets));
    skyframeBuildView.setConfigurations(configurations);
    // Determine the configurations.
    List<TargetAndConfiguration> topLevelTargetsWithConfigs = nodesForTopLevelTargets(configurations, targets, eventHandler);
    List<ConfiguredTargetKey> topLevelCtKeys = Lists.transform(topLevelTargetsWithConfigs, new Function<TargetAndConfiguration, ConfiguredTargetKey>() {

        @Override
        public ConfiguredTargetKey apply(TargetAndConfiguration node) {
            return new ConfiguredTargetKey(node.getLabel(), node.getConfiguration());
        }
    });
    List<AspectValueKey> aspectKeys = new ArrayList<>();
    for (String aspect : aspects) {
        // Syntax: label%aspect
        int delimiterPosition = aspect.indexOf('%');
        if (delimiterPosition >= 0) {
            // TODO(jfield): For consistency with Skylark loads, the aspect should be specified
            // as an absolute path. Also, we probably need to do at least basic validation of
            // path well-formedness here.
            String bzlFileLoadLikeString = aspect.substring(0, delimiterPosition);
            if (!bzlFileLoadLikeString.startsWith("//") && !bzlFileLoadLikeString.startsWith("@")) {
                // "Legacy" behavior of '--aspects' parameter.
                bzlFileLoadLikeString = new PathFragment("/" + bzlFileLoadLikeString).toString();
                if (bzlFileLoadLikeString.endsWith(".bzl")) {
                    bzlFileLoadLikeString = bzlFileLoadLikeString.substring(0, bzlFileLoadLikeString.length() - ".bzl".length());
                }
            }
            SkylarkImport skylarkImport;
            try {
                skylarkImport = SkylarkImports.create(bzlFileLoadLikeString);
            } catch (SkylarkImportSyntaxException e) {
                throw new ViewCreationFailedException(String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e);
            }
            String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
            for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
                if (!(targetSpec.getTarget() instanceof Rule)) {
                    continue;
                }
                aspectKeys.add(AspectValue.createSkylarkAspectKey(targetSpec.getLabel(), // aspect and the base target while the top-level configuration is untrimmed.
                targetSpec.getConfiguration(), targetSpec.getConfiguration(), skylarkImport, skylarkFunctionName));
            }
        } else {
            final NativeAspectClass aspectFactoryClass = ruleClassProvider.getNativeAspectClassMap().get(aspect);
            if (aspectFactoryClass != null) {
                for (TargetAndConfiguration targetSpec : topLevelTargetsWithConfigs) {
                    if (!(targetSpec.getTarget() instanceof Rule)) {
                        continue;
                    }
                    // For invoking top-level aspects, use the top-level configuration for both the
                    // aspect and the base target while the top-level configuration is untrimmed.
                    BuildConfiguration configuration = targetSpec.getConfiguration();
                    aspectKeys.add(AspectValue.createAspectKey(targetSpec.getLabel(), configuration, new AspectDescriptor(aspectFactoryClass, AspectParameters.EMPTY), configuration));
                }
            } else {
                throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
            }
        }
    }
    skyframeExecutor.injectWorkspaceStatusData(loadingResult.getWorkspaceName());
    SkyframeAnalysisResult skyframeAnalysisResult;
    try {
        skyframeAnalysisResult = skyframeBuildView.configureTargets(eventHandler, topLevelCtKeys, aspectKeys, eventBus, viewOptions.keepGoing, viewOptions.loadingPhaseThreads);
        setArtifactRoots(skyframeAnalysisResult.getPackageRoots());
    } finally {
        skyframeBuildView.clearInvalidatedConfiguredTargets();
    }
    int numTargetsToAnalyze = topLevelTargetsWithConfigs.size();
    int numSuccessful = skyframeAnalysisResult.getConfiguredTargets().size();
    if (0 < numSuccessful && numSuccessful < numTargetsToAnalyze) {
        String msg = String.format("Analysis succeeded for only %d of %d top-level targets", numSuccessful, numTargetsToAnalyze);
        eventHandler.handle(Event.info(msg));
        LOG.info(msg);
    }
    AnalysisResult result = createResult(eventHandler, loadingResult, topLevelOptions, viewOptions, skyframeAnalysisResult);
    LOG.info("Finished analysis");
    return result;
}
Also used : SkylarkImportSyntaxException(com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException) SkyframeAnalysisResult(com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult) ArrayList(java.util.ArrayList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) SkyframeAnalysisResult(com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult) SkylarkImport(com.google.devtools.build.lib.syntax.SkylarkImport) BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) Target(com.google.devtools.build.lib.packages.Target) AspectValueKey(com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey) NativeAspectClass(com.google.devtools.build.lib.packages.NativeAspectClass) AspectDescriptor(com.google.devtools.build.lib.packages.AspectDescriptor) Rule(com.google.devtools.build.lib.packages.Rule) ConfiguredTargetKey(com.google.devtools.build.lib.skyframe.ConfiguredTargetKey) ThreadCompatible(com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)

Example 5 with ThreadCompatible

use of com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible in project bazel by bazelbuild.

the class CppCompileAction method execute.

@Override
@ThreadCompatible
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException {
    setModuleFileFlags();
    Executor executor = actionExecutionContext.getExecutor();
    CppCompileActionContext.Reply reply;
    try {
        reply = executor.getContext(actionContext).execWithReply(this, actionExecutionContext);
    } catch (ExecException e) {
        throw e.toActionExecutionException("C++ compilation of rule '" + getOwner().getLabel() + "'", executor.getVerboseFailures(), this);
    }
    ensureCoverageNotesFilesExist();
    // This is the .d file scanning part.
    IncludeScanningContext scanningContext = executor.getContext(IncludeScanningContext.class);
    Path execRoot = executor.getExecRoot();
    NestedSet<Artifact> discoveredInputs = discoverInputsFromDotdFiles(execRoot, scanningContext.getArtifactResolver(), reply);
    // Clear in-memory .d files early.
    reply = null;
    // Post-execute "include scanning", which modifies the action inputs to match what the compile
    // action actually used by incorporating the results of .d file parsing.
    updateActionInputs(discoveredInputs);
    // HeadersCheckingMode.NONE should only be used for ObjC build actions.
    if (cppSemantics.needsIncludeValidation()) {
        validateInclusions(discoveredInputs, actionExecutionContext.getArtifactExpander(), executor.getEventHandler());
    }
}
Also used : Reply(com.google.devtools.build.lib.rules.cpp.CppCompileActionContext.Reply) Path(com.google.devtools.build.lib.vfs.Path) Executor(com.google.devtools.build.lib.actions.Executor) ExecException(com.google.devtools.build.lib.actions.ExecException) Artifact(com.google.devtools.build.lib.actions.Artifact) ThreadCompatible(com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)

Aggregations

ThreadCompatible (com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible)6 Artifact (com.google.devtools.build.lib.actions.Artifact)4 ActionExecutionException (com.google.devtools.build.lib.actions.ActionExecutionException)3 ExecException (com.google.devtools.build.lib.actions.ExecException)3 Executor (com.google.devtools.build.lib.actions.Executor)3 Path (com.google.devtools.build.lib.vfs.Path)3 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Function (com.google.common.base.Function)1 ActionInput (com.google.devtools.build.lib.actions.ActionInput)1 SimpleSpawn (com.google.devtools.build.lib.actions.SimpleSpawn)1 Spawn (com.google.devtools.build.lib.actions.Spawn)1 BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)1 LabelSyntaxException (com.google.devtools.build.lib.cmdline.LabelSyntaxException)1 RepositoryName (com.google.devtools.build.lib.cmdline.RepositoryName)1 AspectDescriptor (com.google.devtools.build.lib.packages.AspectDescriptor)1 NativeAspectClass (com.google.devtools.build.lib.packages.NativeAspectClass)1 Rule (com.google.devtools.build.lib.packages.Rule)1