Ejemplo n.º 1
0
  /**
   * Analyzes the specified targets using Skyframe as the driving framework.
   *
   * @return the configured targets that should be built along with a WalkableGraph of the analysis.
   */
  public SkyframeAnalysisResult configureTargets(
      EventHandler eventHandler,
      List<ConfiguredTargetKey> values,
      List<AspectValueKey> aspectKeys,
      EventBus eventBus,
      boolean keepGoing)
      throws InterruptedException, ViewCreationFailedException {
    enableAnalysis(true);
    EvaluationResult<ActionLookupValue> result;
    try {
      result = skyframeExecutor.configureTargets(eventHandler, values, aspectKeys, keepGoing);
    } finally {
      enableAnalysis(false);
    }
    ImmutableMap<Action, ConflictException> badActions = skyframeExecutor.findArtifactConflicts();

    Collection<AspectValue> goodAspects = Lists.newArrayListWithCapacity(values.size());
    NestedSetBuilder<Package> packages = NestedSetBuilder.stableOrder();
    for (AspectValueKey aspectKey : aspectKeys) {
      AspectValue value = (AspectValue) result.get(AspectValue.key(aspectKey));
      if (value == null) {
        // Skip aspects that couldn't be applied to targets.
        continue;
      }
      goodAspects.add(value);
      packages.addTransitive(value.getTransitivePackages());
    }

    // Filter out all CTs that have a bad action and convert to a list of configured targets. This
    // code ensures that the resulting list of configured targets has the same order as the incoming
    // list of values, i.e., that the order is deterministic.
    Collection<ConfiguredTarget> goodCts = Lists.newArrayListWithCapacity(values.size());
    for (ConfiguredTargetKey value : values) {
      ConfiguredTargetValue ctValue =
          (ConfiguredTargetValue) result.get(ConfiguredTargetValue.key(value));
      if (ctValue == null) {
        continue;
      }
      goodCts.add(ctValue.getConfiguredTarget());
      packages.addTransitive(ctValue.getTransitivePackages());
    }

    if (!result.hasError() && badActions.isEmpty()) {
      setDeserializedArtifactOwners();
      return new SkyframeAnalysisResult(
          /*hasLoadingError=*/ false,
          /*hasAnalysisError=*/ false,
          ImmutableList.copyOf(goodCts),
          result.getWalkableGraph(),
          ImmutableList.copyOf(goodAspects),
          LoadingPhaseRunner.collectPackageRoots(packages.build().toCollection()));
    }

    // --nokeep_going so we fail with an exception for the first error.
    // TODO(bazel-team): We might want to report the other errors through the event bus but
    // for keeping this code in parity with legacy we just report the first error for now.
    if (!keepGoing) {
      for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
        ConflictException ex = bad.getValue();
        try {
          ex.rethrowTyped();
        } catch (MutableActionGraph.ActionConflictException ace) {
          ace.reportTo(eventHandler);
          String errorMsg =
              "Analysis of target '"
                  + bad.getKey().getOwner().getLabel()
                  + "' failed; build aborted";
          throw new ViewCreationFailedException(errorMsg);
        } catch (ArtifactPrefixConflictException apce) {
          eventHandler.handle(Event.error(apce.getMessage()));
        }
        throw new ViewCreationFailedException(ex.getMessage());
      }

      Map.Entry<SkyKey, ErrorInfo> error = result.errorMap().entrySet().iterator().next();
      SkyKey topLevel = error.getKey();
      ErrorInfo errorInfo = error.getValue();
      assertSaneAnalysisError(errorInfo, topLevel);
      skyframeExecutor
          .getCyclesReporter()
          .reportCycles(errorInfo.getCycleInfo(), topLevel, eventHandler);
      Throwable cause = errorInfo.getException();
      Preconditions.checkState(
          cause != null || !Iterables.isEmpty(errorInfo.getCycleInfo()), errorInfo);
      String errorMsg = null;
      if (topLevel.argument() instanceof ConfiguredTargetKey) {
        errorMsg =
            "Analysis of target '"
                + ConfiguredTargetValue.extractLabel(topLevel)
                + "' failed; build aborted";
      } else if (topLevel.argument() instanceof AspectValueKey) {
        AspectValueKey aspectKey = (AspectValueKey) topLevel.argument();
        errorMsg = "Analysis of aspect '" + aspectKey.getDescription() + "' failed; build aborted";
      } else {
        assert false;
      }
      if (cause instanceof ActionConflictException) {
        ((ActionConflictException) cause).reportTo(eventHandler);
      }
      throw new ViewCreationFailedException(errorMsg);
    }

    boolean hasLoadingError = false;
    // --keep_going : We notify the error and return a ConfiguredTargetValue
    for (Map.Entry<SkyKey, ErrorInfo> errorEntry : result.errorMap().entrySet()) {
      // Only handle errors of configured targets, not errors of top-level aspects.
      // TODO(ulfjack): this is quadratic - if there are a lot of CTs, this could be rather slow.
      if (!values.contains(errorEntry.getKey().argument())) {
        continue;
      }
      SkyKey errorKey = errorEntry.getKey();
      ConfiguredTargetKey label = (ConfiguredTargetKey) errorKey.argument();
      Label topLevelLabel = label.getLabel();
      ErrorInfo errorInfo = errorEntry.getValue();
      assertSaneAnalysisError(errorInfo, errorKey);

      skyframeExecutor
          .getCyclesReporter()
          .reportCycles(errorInfo.getCycleInfo(), errorKey, eventHandler);
      Exception cause = errorInfo.getException();
      Label analysisRootCause = null;
      if (cause instanceof ConfiguredValueCreationException) {
        ConfiguredValueCreationException ctCause = (ConfiguredValueCreationException) cause;
        for (Label rootCause : ctCause.getRootCauses()) {
          hasLoadingError = true;
          eventBus.post(new LoadingFailureEvent(topLevelLabel, rootCause));
        }
        analysisRootCause = ctCause.getAnalysisRootCause();
      } else if (!Iterables.isEmpty(errorInfo.getCycleInfo())) {
        analysisRootCause =
            maybeGetConfiguredTargetCycleCulprit(topLevelLabel, errorInfo.getCycleInfo());
      } else if (cause instanceof ActionConflictException) {
        ((ActionConflictException) cause).reportTo(eventHandler);
      }
      eventHandler.handle(
          Event.warn(
              "errors encountered while analyzing target '"
                  + topLevelLabel
                  + "': it will not be built"));
      if (analysisRootCause != null) {
        eventBus.post(
            new AnalysisFailureEvent(
                LabelAndConfiguration.of(topLevelLabel, label.getConfiguration()),
                analysisRootCause));
      }
    }

    Collection<Exception> reportedExceptions = Sets.newHashSet();
    for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
      ConflictException ex = bad.getValue();
      try {
        ex.rethrowTyped();
      } catch (MutableActionGraph.ActionConflictException ace) {
        ace.reportTo(eventHandler);
        eventHandler.handle(
            Event.warn(
                "errors encountered while analyzing target '"
                    + bad.getKey().getOwner().getLabel()
                    + "': it will not be built"));
      } catch (ArtifactPrefixConflictException apce) {
        if (reportedExceptions.add(apce)) {
          eventHandler.handle(Event.error(apce.getMessage()));
        }
      }
    }

    if (!badActions.isEmpty()) {
      // In order to determine the set of configured targets transitively error free from action
      // conflict issues, we run a post-processing update() that uses the bad action map.
      EvaluationResult<PostConfiguredTargetValue> actionConflictResult =
          skyframeExecutor.postConfigureTargets(eventHandler, values, keepGoing, badActions);

      goodCts = Lists.newArrayListWithCapacity(values.size());
      for (ConfiguredTargetKey value : values) {
        PostConfiguredTargetValue postCt =
            actionConflictResult.get(PostConfiguredTargetValue.key(value));
        if (postCt != null) {
          goodCts.add(postCt.getCt());
        }
      }
    }
    setDeserializedArtifactOwners();
    return new SkyframeAnalysisResult(
        hasLoadingError,
        result.hasError() || !badActions.isEmpty(),
        ImmutableList.copyOf(goodCts),
        result.getWalkableGraph(),
        ImmutableList.copyOf(goodAspects),
        LoadingPhaseRunner.collectPackageRoots(packages.build().toCollection()));
  }
Ejemplo n.º 2
0
  /**
   * Analyzes the specified targets using Skyframe as the driving framework.
   *
   * @return the configured targets that should be built along with a WalkableGraph of the analysis.
   */
  public SkyframeAnalysisResult configureTargets(
      List<ConfiguredTargetKey> values,
      List<AspectKey> aspectKeys,
      EventBus eventBus,
      boolean keepGoing)
      throws InterruptedException, ViewCreationFailedException {
    enableAnalysis(true);
    EvaluationResult<ActionLookupValue> result;
    try {
      result = skyframeExecutor.configureTargets(values, aspectKeys, keepGoing);
    } finally {
      enableAnalysis(false);
    }
    ImmutableMap<Action, ConflictException> badActions = skyframeExecutor.findArtifactConflicts();

    Collection<AspectValue> goodAspects = Lists.newArrayListWithCapacity(values.size());
    for (AspectKey aspectKey : aspectKeys) {
      AspectValue value = (AspectValue) result.get(AspectValue.key(aspectKey));
      if (value == null) {
        // Skip aspects that couldn't be applied to targets.
        continue;
      }
      goodAspects.add(value);
    }

    // Filter out all CTs that have a bad action and convert to a list of configured targets. This
    // code ensures that the resulting list of configured targets has the same order as the incoming
    // list of values, i.e., that the order is deterministic.
    Collection<ConfiguredTarget> goodCts = Lists.newArrayListWithCapacity(values.size());
    for (ConfiguredTargetKey value : values) {
      ConfiguredTargetValue ctValue =
          (ConfiguredTargetValue) result.get(ConfiguredTargetValue.key(value));
      if (ctValue == null) {
        continue;
      }
      goodCts.add(ctValue.getConfiguredTarget());
    }

    if (!result.hasError() && badActions.isEmpty()) {
      setDeserializedArtifactOwners();
      return new SkyframeAnalysisResult(
          ImmutableList.copyOf(goodCts),
          result.getWalkableGraph(),
          ImmutableList.copyOf(goodAspects));
    }

    // --nokeep_going so we fail with an exception for the first error.
    // TODO(bazel-team): We might want to report the other errors through the event bus but
    // for keeping this code in parity with legacy we just report the first error for now.
    if (!keepGoing) {
      for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
        ConflictException ex = bad.getValue();
        try {
          ex.rethrowTyped();
        } catch (MutableActionGraph.ActionConflictException ace) {
          ace.reportTo(skyframeExecutor.getReporter());
          String errorMsg =
              "Analysis of target '"
                  + bad.getKey().getOwner().getLabel()
                  + "' failed; build aborted";
          throw new ViewCreationFailedException(errorMsg);
        } catch (ArtifactPrefixConflictException apce) {
          skyframeExecutor.getReporter().handle(Event.error(apce.getMessage()));
        }
        throw new ViewCreationFailedException(ex.getMessage());
      }

      Map.Entry<SkyKey, ErrorInfo> error = result.errorMap().entrySet().iterator().next();
      SkyKey topLevel = error.getKey();
      ErrorInfo errorInfo = error.getValue();
      assertSaneAnalysisError(errorInfo, topLevel);
      skyframeExecutor
          .getCyclesReporter()
          .reportCycles(errorInfo.getCycleInfo(), topLevel, skyframeExecutor.getReporter());
      Throwable cause = errorInfo.getException();
      Preconditions.checkState(
          cause != null || !Iterables.isEmpty(errorInfo.getCycleInfo()), errorInfo);
      String errorMsg =
          "Analysis of target '"
              + ConfiguredTargetValue.extractLabel(topLevel)
              + "' failed; build aborted";
      if (cause instanceof ActionConflictException) {
        ((ActionConflictException) cause).reportTo(skyframeExecutor.getReporter());
      }
      throw new ViewCreationFailedException(errorMsg);
    }

    // --keep_going : We notify the error and return a ConfiguredTargetValue
    for (Map.Entry<SkyKey, ErrorInfo> errorEntry : result.errorMap().entrySet()) {
      if (values.contains(errorEntry.getKey().argument())) {
        SkyKey errorKey = errorEntry.getKey();
        ConfiguredTargetKey label = (ConfiguredTargetKey) errorKey.argument();
        ErrorInfo errorInfo = errorEntry.getValue();
        assertSaneAnalysisError(errorInfo, errorKey);

        skyframeExecutor
            .getCyclesReporter()
            .reportCycles(errorInfo.getCycleInfo(), errorKey, skyframeExecutor.getReporter());
        // We try to get the root cause key first from ErrorInfo rootCauses. If we don't have one
        // we try to use the cycle culprit if the error is a cycle. Otherwise we use the top-level
        // error key.
        Label root;
        if (!Iterables.isEmpty(errorEntry.getValue().getRootCauses())) {
          SkyKey culprit =
              Preconditions.checkNotNull(
                  Iterables.getFirst(errorEntry.getValue().getRootCauses(), null));
          root = ((ConfiguredTargetKey) culprit.argument()).getLabel();
        } else {
          root = maybeGetConfiguredTargetCycleCulprit(errorInfo.getCycleInfo());
        }
        Exception cause = errorInfo.getException();
        if (cause instanceof ActionConflictException) {
          ((ActionConflictException) cause).reportTo(skyframeExecutor.getReporter());
        }
        skyframeExecutor
            .getReporter()
            .handle(
                Event.warn(
                    "errors encountered while analyzing target '"
                        + label.getLabel()
                        + "': it will not be built"));
        eventBus.post(
            new AnalysisFailureEvent(
                LabelAndConfiguration.of(label.getLabel(), label.getConfiguration()), root));
      }
    }

    Collection<Exception> reportedExceptions = Sets.newHashSet();
    for (Map.Entry<Action, ConflictException> bad : badActions.entrySet()) {
      ConflictException ex = bad.getValue();
      try {
        ex.rethrowTyped();
      } catch (MutableActionGraph.ActionConflictException ace) {
        ace.reportTo(skyframeExecutor.getReporter());
        skyframeExecutor
            .getReporter()
            .handle(
                Event.warn(
                    "errors encountered while analyzing target '"
                        + bad.getKey().getOwner().getLabel()
                        + "': it will not be built"));
      } catch (ArtifactPrefixConflictException apce) {
        if (reportedExceptions.add(apce)) {
          skyframeExecutor.getReporter().handle(Event.error(apce.getMessage()));
        }
      }
    }

    if (!badActions.isEmpty()) {
      // In order to determine the set of configured targets transitively error free from action
      // conflict issues, we run a post-processing update() that uses the bad action map.
      EvaluationResult<PostConfiguredTargetValue> actionConflictResult =
          skyframeExecutor.postConfigureTargets(values, keepGoing, badActions);

      goodCts = Lists.newArrayListWithCapacity(values.size());
      for (ConfiguredTargetKey value : values) {
        PostConfiguredTargetValue postCt =
            actionConflictResult.get(PostConfiguredTargetValue.key(value));
        if (postCt != null) {
          goodCts.add(postCt.getCt());
        }
      }
    }
    setDeserializedArtifactOwners();
    return new SkyframeAnalysisResult(
        ImmutableList.copyOf(goodCts),
        result.getWalkableGraph(),
        ImmutableList.copyOf(goodAspects));
  }