Search in sources :

Example 6 with BuildConfiguration

use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.

the class DependencyResolver method visitRule.

private void visitRule(TargetAndConfiguration node, BuildConfiguration hostConfig, Iterable<Aspect> aspects, ImmutableMap<Label, ConfigMatchingProvider> configConditions, NestedSetBuilder<Label> rootCauses, OrderedSetMultimap<Attribute, Dependency> outgoingEdges) throws EvalException, InvalidConfigurationException, InconsistentAspectOrderException, InterruptedException {
    Preconditions.checkArgument(node.getTarget() instanceof Rule);
    BuildConfiguration ruleConfig = Preconditions.checkNotNull(node.getConfiguration());
    Rule rule = (Rule) node.getTarget();
    ConfiguredAttributeMapper attributeMap = ConfiguredAttributeMapper.of(rule, configConditions);
    attributeMap.validateAttributes();
    RuleResolver depResolver = new RuleResolver(rule, ruleConfig, aspects, attributeMap, rootCauses, outgoingEdges);
    visitTargetVisibility(node, rootCauses, outgoingEdges.get(null));
    resolveEarlyBoundAttributes(depResolver);
    resolveLateBoundAttributes(depResolver, ruleConfig, hostConfig);
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) Rule(com.google.devtools.build.lib.packages.Rule)

Example 7 with BuildConfiguration

use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.

the class DependencyResolver method resolveLateBoundAttribute.

/**
   * Returns the label dependencies for the given late-bound attribute in this rule.
   *
   * @param rule the rule being evaluated
   * @param attribute the attribute to evaluate
   * @param config the configuration to evaluate the attribute in
   * @param attributeMap mapper to attribute values
   */
private Iterable<Label> resolveLateBoundAttribute(Rule rule, Attribute attribute, BuildConfiguration config, AttributeMap attributeMap) throws EvalException, InterruptedException {
    Preconditions.checkArgument(attribute.isLateBound());
    @SuppressWarnings("unchecked") LateBoundDefault<BuildConfiguration> lateBoundDefault = (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault();
    // TODO(bazel-team): This might be too expensive - can we cache this somehow?
    if (!lateBoundDefault.getRequiredConfigurationFragments().isEmpty()) {
        if (!config.hasAllFragments(lateBoundDefault.getRequiredConfigurationFragments())) {
            return ImmutableList.<Label>of();
        }
    }
    // TODO(bazel-team): We should check if the implementation tries to access an undeclared
    // fragment.
    Object actualValue = lateBoundDefault.resolve(rule, attributeMap, config);
    if (EvalUtils.isNullOrNone(actualValue)) {
        return ImmutableList.<Label>of();
    }
    try {
        ImmutableList.Builder<Label> deps = ImmutableList.builder();
        if (attribute.getType() == BuildType.LABEL) {
            deps.add(rule.getLabel().resolveRepositoryRelative(BuildType.LABEL.cast(actualValue)));
        } else if (attribute.getType() == BuildType.LABEL_LIST) {
            for (Label label : BuildType.LABEL_LIST.cast(actualValue)) {
                deps.add(rule.getLabel().resolveRepositoryRelative(label));
            }
        } else {
            throw new IllegalStateException(String.format("Late bound attribute '%s' is not a label or a label list", attribute.getName()));
        }
        return deps.build();
    } catch (ClassCastException e) {
        // From either of the cast calls above.
        throw new EvalException(rule.getLocation(), String.format("When computing the default value of %s, expected '%s', got '%s'", attribute.getName(), attribute.getType(), EvalUtils.getDataTypeName(actualValue, true)));
    }
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) ImmutableList(com.google.common.collect.ImmutableList) Label(com.google.devtools.build.lib.cmdline.Label) LateBoundDefault(com.google.devtools.build.lib.packages.Attribute.LateBoundDefault) EvalException(com.google.devtools.build.lib.syntax.EvalException)

Example 8 with BuildConfiguration

use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.

the class DependencyResolver method resolveLateBoundAttributes.

/**
   * Resolves the dependencies for all late-bound attributes in this rule.
   *
   * <p>Late-bound attributes need special handling because they require configuration
   * transitions to determine their values.
   *
   * <p>In other words, the normal process of dependency resolution is:
   * <ol>
   *   <li>Find every label value in the rule's attributes</li>
   *   <li>Apply configuration transitions over each value to get its dep configuration
   *   <li>Return each value with its dep configuration</li>
   * </ol>
   *
   * This doesn't work for late-bound attributes because you can't get their values without
   * knowing the configuration first. And that configuration may not be the owning rule's
   * configuration. Specifically, {@link LateBoundDefault#useHostConfiguration()} switches to the
   * host config and late-bound split attributes branch into multiple split configs.
   *
   * <p>This method implements that logic and makes sure the normal configuration
   * transition logic mixes with it cleanly.
   *
   * @param depResolver the resolver for this rule's deps
   * @param ruleConfig the rule's configuration
   * @param hostConfig the equivalent host configuration
   */
private void resolveLateBoundAttributes(RuleResolver depResolver, BuildConfiguration ruleConfig, BuildConfiguration hostConfig) throws EvalException, InvalidConfigurationException, InconsistentAspectOrderException, InterruptedException {
    ConfiguredAttributeMapper attributeMap = depResolver.attributeMap;
    for (AttributeAndOwner attributeAndOwner : depResolver.attributes) {
        Attribute attribute = attributeAndOwner.attribute;
        if (!attribute.isLateBound() || !attribute.getCondition().apply(attributeMap)) {
            continue;
        }
        @SuppressWarnings("unchecked") LateBoundDefault<BuildConfiguration> lateBoundDefault = (LateBoundDefault<BuildConfiguration>) attribute.getLateBoundDefault();
        Collection<BuildOptions> splitOptions = getSplitOptions(depResolver.rule, attribute, ruleConfig);
        if (!splitOptions.isEmpty()) {
            // Late-bound attribute with a split transition:
            // Since we want to get the same results as BuildConfiguration.evaluateTransition (but
            // skip it since we've already applied the split), we want to make sure this logic
            // doesn't do anything differently. evaluateTransition has additional logic
            // for host configs and attributes with configurators. So we check here that neither of
            // of those apply, in the name of keeping the fork as simple as possible.
            Verify.verify(attribute.getConfigurator() == null);
            Verify.verify(!lateBoundDefault.useHostConfiguration());
            Iterable<BuildConfiguration> splitConfigs;
            if (!ruleConfig.useDynamicConfigurations()) {
                splitConfigs = ruleConfig.getSplitConfigurations(attribute.getSplitTransition(depResolver.rule));
            } else {
                splitConfigs = getConfigurations(ruleConfig.fragmentClasses(), splitOptions);
                if (splitConfigs == null) {
                    // Need Skyframe deps.
                    continue;
                }
            }
            for (BuildConfiguration splitConfig : splitConfigs) {
                for (Label dep : resolveLateBoundAttribute(depResolver.rule, attribute, splitConfig, attributeMap)) {
                    // Skip the normal config transition pipeline and directly feed the split config. This
                    // is because the split already had to be applied to determine the attribute's value.
                    // This makes the split logic in the normal pipeline redundant and potentially
                    // incorrect.
                    depResolver.resolveDep(attributeAndOwner, dep, splitConfig);
                }
            }
        } else {
            // Late-bound attribute without a split transition:
            for (Label dep : resolveLateBoundAttribute(depResolver.rule, attribute, lateBoundDefault.useHostConfiguration() ? hostConfig : ruleConfig, attributeMap)) {
                // Process this dep like a normal attribute.
                depResolver.resolveDep(attributeAndOwner, dep);
            }
        }
    }
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) Attribute(com.google.devtools.build.lib.packages.Attribute) BuildOptions(com.google.devtools.build.lib.analysis.config.BuildOptions) Label(com.google.devtools.build.lib.cmdline.Label) LateBoundDefault(com.google.devtools.build.lib.packages.Attribute.LateBoundDefault)

Example 9 with BuildConfiguration

use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.

the class RunCommand method exec.

@Override
public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
    RunOptions runOptions = options.getOptions(RunOptions.class);
    // This list should look like: ["//executable:target", "arg1", "arg2"]
    List<String> targetAndArgs = options.getResidue();
    // The user must at the least specify an executable target.
    if (targetAndArgs.isEmpty()) {
        env.getReporter().handle(Event.error("Must specify a target to run"));
        return ExitCode.COMMAND_LINE_ERROR;
    }
    String targetString = targetAndArgs.get(0);
    List<String> runTargetArgs = targetAndArgs.subList(1, targetAndArgs.size());
    RunUnder runUnder = options.getOptions(BuildConfiguration.Options.class).runUnder;
    OutErr outErr = env.getReporter().getOutErr();
    List<String> targets = (runUnder != null) && (runUnder.getLabel() != null) ? ImmutableList.of(targetString, runUnder.getLabel().toString()) : ImmutableList.of(targetString);
    BuildRequest request = BuildRequest.create(this.getClass().getAnnotation(Command.class).name(), options, env.getRuntime().getStartupOptionsProvider(), targets, outErr, env.getCommandId(), env.getCommandStartTime());
    currentRunUnder = runUnder;
    BuildResult result;
    try {
        result = processRequest(env, request);
    } finally {
        currentRunUnder = null;
    }
    if (!result.getSuccess()) {
        env.getReporter().handle(Event.error("Build failed. Not running target"));
        return result.getExitCondition();
    }
    // Make sure that we have exactly 1 built target (excluding --run_under),
    // and that it is executable.
    // These checks should only fail if keepGoing is true, because we already did
    // validation before the build began.  See {@link #validateTargets()}.
    Collection<ConfiguredTarget> targetsBuilt = result.getSuccessfulTargets();
    ConfiguredTarget targetToRun = null;
    ConfiguredTarget runUnderTarget = null;
    if (targetsBuilt != null) {
        int maxTargets = runUnder != null && runUnder.getLabel() != null ? 2 : 1;
        if (targetsBuilt.size() > maxTargets) {
            env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
            return ExitCode.COMMAND_LINE_ERROR;
        }
        for (ConfiguredTarget target : targetsBuilt) {
            ExitCode targetValidation = fullyValidateTarget(env, target);
            if (!targetValidation.equals(ExitCode.SUCCESS)) {
                return targetValidation;
            }
            if (runUnder != null && target.getLabel().equals(runUnder.getLabel())) {
                if (runUnderTarget != null) {
                    env.getReporter().handle(Event.error(null, "Can't identify the run_under target from multiple options?"));
                    return ExitCode.COMMAND_LINE_ERROR;
                }
                runUnderTarget = target;
            } else if (targetToRun == null) {
                targetToRun = target;
            } else {
                env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
                return ExitCode.COMMAND_LINE_ERROR;
            }
        }
    }
    // Handle target & run_under referring to the same target.
    if ((targetToRun == null) && (runUnderTarget != null)) {
        targetToRun = runUnderTarget;
    }
    if (targetToRun == null) {
        env.getReporter().handle(Event.error(NO_TARGET_MESSAGE));
        return ExitCode.COMMAND_LINE_ERROR;
    }
    Path executablePath = Preconditions.checkNotNull(targetToRun.getProvider(FilesToRunProvider.class).getExecutable().getPath());
    BuildConfiguration configuration = targetToRun.getConfiguration();
    if (configuration == null) {
        // The target may be an input file, which doesn't have a configuration. In that case, we
        // choose any target configuration.
        configuration = result.getBuildConfigurationCollection().getTargetConfigurations().get(0);
    }
    Path workingDir;
    try {
        workingDir = ensureRunfilesBuilt(env, targetToRun);
    } catch (CommandException e) {
        env.getReporter().handle(Event.error("Error creating runfiles: " + e.getMessage()));
        return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
    }
    List<String> args = runTargetArgs;
    FilesToRunProvider provider = targetToRun.getProvider(FilesToRunProvider.class);
    RunfilesSupport runfilesSupport = provider == null ? null : provider.getRunfilesSupport();
    if (runfilesSupport != null && runfilesSupport.getArgs() != null) {
        List<String> targetArgs = runfilesSupport.getArgs();
        if (!targetArgs.isEmpty()) {
            args = Lists.newArrayListWithCapacity(targetArgs.size() + runTargetArgs.size());
            args.addAll(targetArgs);
            args.addAll(runTargetArgs);
        }
    }
    String productName = env.getRuntime().getProductName();
    //
    // We now have a unique executable ready to be run.
    //
    // We build up two different versions of the command to run: one with an absolute path, which
    // we'll actually run, and a prettier one with the long absolute path to the executable
    // replaced with a shorter relative path that uses the symlinks in the workspace.
    PathFragment prettyExecutablePath = OutputDirectoryLinksUtils.getPrettyPath(executablePath, env.getWorkspaceName(), env.getWorkspace(), options.getOptions(BuildRequestOptions.class).getSymlinkPrefix(productName), productName);
    List<String> cmdLine = new ArrayList<>();
    if (runOptions.scriptPath == null) {
        PathFragment processWrapperPath = env.getBlazeWorkspace().getBinTools().getExecPath(PROCESS_WRAPPER);
        Preconditions.checkNotNull(processWrapperPath, PROCESS_WRAPPER + " not found in embedded tools");
        cmdLine.add(env.getExecRoot().getRelative(processWrapperPath).getPathString());
        cmdLine.add("-1");
        cmdLine.add("15");
        cmdLine.add("-");
        cmdLine.add("-");
    }
    List<String> prettyCmdLine = new ArrayList<>();
    // at the start of the command line.
    if (runUnder != null) {
        String runUnderValue = runUnder.getValue();
        if (runUnderTarget != null) {
            // --run_under specifies a target. Get the corresponding executable.
            // This must be an absolute path, because the run_under target is only
            // in the runfiles of test targets.
            runUnderValue = runUnderTarget.getProvider(FilesToRunProvider.class).getExecutable().getPath().getPathString();
            // If the run_under command contains any options, make sure to add them
            // to the command line as well.
            List<String> opts = runUnder.getOptions();
            if (!opts.isEmpty()) {
                runUnderValue += " " + ShellEscaper.escapeJoinAll(opts);
            }
        }
        cmdLine.add(configuration.getShellExecutable().getPathString());
        cmdLine.add("-c");
        cmdLine.add(runUnderValue + " " + executablePath.getPathString() + " " + ShellEscaper.escapeJoinAll(args));
        prettyCmdLine.add(configuration.getShellExecutable().getPathString());
        prettyCmdLine.add("-c");
        prettyCmdLine.add(runUnderValue + " " + prettyExecutablePath.getPathString() + " " + ShellEscaper.escapeJoinAll(args));
    } else {
        cmdLine.add(executablePath.getPathString());
        cmdLine.addAll(args);
        prettyCmdLine.add(prettyExecutablePath.getPathString());
        prettyCmdLine.addAll(args);
    }
    // Add a newline between the blaze output and the binary's output.
    outErr.printErrLn("");
    if (runOptions.scriptPath != null) {
        String unisolatedCommand = CommandFailureUtils.describeCommand(CommandDescriptionForm.COMPLETE_UNISOLATED, cmdLine, null, workingDir.getPathString());
        if (writeScript(env, runOptions.scriptPath, unisolatedCommand)) {
            return ExitCode.SUCCESS;
        } else {
            return ExitCode.RUN_FAILURE;
        }
    }
    env.getReporter().handle(Event.info(null, "Running command line: " + ShellEscaper.escapeJoinAll(prettyCmdLine)));
    com.google.devtools.build.lib.shell.Command command = new CommandBuilder().addArgs(cmdLine).setEnv(env.getClientEnv()).setWorkingDir(workingDir).build();
    try {
        // Restore a raw EventHandler if it is registered. This allows for blaze run to produce the
        // actual output of the command being run even if --color=no is specified.
        env.getReporter().switchToAnsiAllowingHandler();
        // The command API is a little strange in that the following statement
        // will return normally only if the program exits with exit code 0.
        // If it ends with any other code, we have to catch BadExitStatusException.
        command.execute(com.google.devtools.build.lib.shell.Command.NO_INPUT, com.google.devtools.build.lib.shell.Command.NO_OBSERVER, outErr.getOutputStream(), outErr.getErrorStream(), true).getTerminationStatus().getExitCode();
        return ExitCode.SUCCESS;
    } catch (BadExitStatusException e) {
        String message = "Non-zero return code '" + e.getResult().getTerminationStatus().getExitCode() + "' from command: " + e.getMessage();
        env.getReporter().handle(Event.error(message));
        return ExitCode.RUN_FAILURE;
    } catch (AbnormalTerminationException e) {
        // The process was likely terminated by a signal in this case.
        return ExitCode.INTERRUPTED;
    } catch (CommandException e) {
        env.getReporter().handle(Event.error("Error running program: " + e.getMessage()));
        return ExitCode.RUN_FAILURE;
    }
}
Also used : BuildRequestOptions(com.google.devtools.build.lib.buildtool.BuildRequest.BuildRequestOptions) RunUnder(com.google.devtools.build.lib.analysis.config.RunUnder) FilesToRunProvider(com.google.devtools.build.lib.analysis.FilesToRunProvider) ExitCode(com.google.devtools.build.lib.util.ExitCode) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) ArrayList(java.util.ArrayList) BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) RunfilesSupport(com.google.devtools.build.lib.analysis.RunfilesSupport) AbnormalTerminationException(com.google.devtools.build.lib.shell.AbnormalTerminationException) BadExitStatusException(com.google.devtools.build.lib.shell.BadExitStatusException) Path(com.google.devtools.build.lib.vfs.Path) OutErr(com.google.devtools.build.lib.util.io.OutErr) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) CommandException(com.google.devtools.build.lib.shell.CommandException) BuildRequest(com.google.devtools.build.lib.buildtool.BuildRequest) BuildResult(com.google.devtools.build.lib.buildtool.BuildResult) CommandBuilder(com.google.devtools.build.lib.util.CommandBuilder)

Example 10 with BuildConfiguration

use of com.google.devtools.build.lib.analysis.config.BuildConfiguration in project bazel by bazelbuild.

the class ConfiguredTargetFunction method createConfiguredTarget.

@Nullable
private ConfiguredTargetValue createConfiguredTarget(SkyframeBuildView view, Environment env, Target target, BuildConfiguration configuration, OrderedSetMultimap<Attribute, ConfiguredTarget> depValueMap, ImmutableMap<Label, ConfigMatchingProvider> configConditions, NestedSetBuilder<Package> transitivePackages) throws ConfiguredTargetFunctionException, InterruptedException {
    StoredEventHandler events = new StoredEventHandler();
    BuildConfiguration ownerConfig = (configuration == null) ? null : configuration.getArtifactOwnerConfiguration();
    CachingAnalysisEnvironment analysisEnvironment = view.createAnalysisEnvironment(new ConfiguredTargetKey(target.getLabel(), ownerConfig), false, events, env, configuration);
    if (env.valuesMissing()) {
        return null;
    }
    Preconditions.checkNotNull(depValueMap);
    ConfiguredTarget configuredTarget = view.createConfiguredTarget(target, configuration, analysisEnvironment, depValueMap, configConditions);
    events.replayOn(env.getListener());
    if (events.hasErrors()) {
        analysisEnvironment.disable(target);
        throw new ConfiguredTargetFunctionException(new ConfiguredValueCreationException("Analysis of target '" + target.getLabel() + "' failed; build aborted", target.getLabel()));
    }
    Preconditions.checkState(!analysisEnvironment.hasErrors(), "Analysis environment hasError() but no errors reported");
    if (env.valuesMissing()) {
        return null;
    }
    analysisEnvironment.disable(target);
    Preconditions.checkNotNull(configuredTarget, target);
    ImmutableMap<Artifact, ActionAnalysisMetadata> generatingActions;
    // rule implementation).
    try {
        generatingActions = Actions.filterSharedActionsAndThrowActionConflict(analysisEnvironment.getRegisteredActions());
    } catch (ActionConflictException e) {
        throw new ConfiguredTargetFunctionException(e);
    }
    return new ConfiguredTargetValue(configuredTarget, generatingActions, transitivePackages.build());
}
Also used : BuildConfiguration(com.google.devtools.build.lib.analysis.config.BuildConfiguration) StoredEventHandler(com.google.devtools.build.lib.events.StoredEventHandler) ActionConflictException(com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) MergedConfiguredTarget(com.google.devtools.build.lib.analysis.MergedConfiguredTarget) ActionAnalysisMetadata(com.google.devtools.build.lib.actions.ActionAnalysisMetadata) CachingAnalysisEnvironment(com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment) Artifact(com.google.devtools.build.lib.actions.Artifact) Nullable(javax.annotation.Nullable)

Aggregations

BuildConfiguration (com.google.devtools.build.lib.analysis.config.BuildConfiguration)51 ConfiguredTarget (com.google.devtools.build.lib.analysis.ConfiguredTarget)13 Label (com.google.devtools.build.lib.cmdline.Label)12 Artifact (com.google.devtools.build.lib.actions.Artifact)11 ImmutableList (com.google.common.collect.ImmutableList)8 ImmutableMap (com.google.common.collect.ImmutableMap)8 Test (org.junit.Test)8 Attribute (com.google.devtools.build.lib.packages.Attribute)7 BuildOptions (com.google.devtools.build.lib.analysis.config.BuildOptions)6 InvalidConfigurationException (com.google.devtools.build.lib.analysis.config.InvalidConfigurationException)6 Rule (com.google.devtools.build.lib.packages.Rule)6 Target (com.google.devtools.build.lib.packages.Target)6 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)6 SkyKey (com.google.devtools.build.skyframe.SkyKey)6 ArrayList (java.util.ArrayList)6 Map (java.util.Map)6 Nullable (javax.annotation.Nullable)6 Root (com.google.devtools.build.lib.actions.Root)5 TransitiveInfoCollection (com.google.devtools.build.lib.analysis.TransitiveInfoCollection)5 HashMap (java.util.HashMap)5