Esempio n. 1
0
 @Override
 protected void internalExecute(ActionExecutionContext actionExecutionContext)
     throws ExecException, InterruptedException {
   EventHandler reporter = actionExecutionContext.getExecutor().getEventHandler();
   checkInputsForDirectories(reporter, actionExecutionContext.getMetadataHandler());
   super.internalExecute(actionExecutionContext);
   checkOutputsForDirectories(reporter);
 }
Esempio n. 2
0
 @Override
 public void execute(ActionExecutionContext actionExecutionContext)
     throws ActionExecutionException, InterruptedException {
   actionExecutionContext
       .getExecutor()
       .getContext(SymlinkTreeActionContext.class)
       .createSymlinks(this, actionExecutionContext, shExecutable);
 }
Esempio n. 3
0
  /**
   * Ensure the runfiles tree exists and is consistent with the TestAction's manifest
   * ($0.runfiles_manifest), bringing it into consistency if not. The contents of the output file
   * $0.runfiles/MANIFEST, if it exists, are used a proxy for the set of existing symlinks, to avoid
   * the need for recursion.
   */
  private static void updateLocalRunfilesDirectory(
      TestRunnerAction testAction,
      Path runfilesDir,
      ActionExecutionContext actionExecutionContext,
      BinTools binTools,
      ImmutableMap<String, String> shellEnvironment,
      boolean enableRunfiles)
      throws ExecException, InterruptedException {
    Executor executor = actionExecutionContext.getExecutor();

    TestTargetExecutionSettings execSettings = testAction.getExecutionSettings();
    try {
      // Avoid rebuilding the runfiles directory if the manifest in it matches the input manifest,
      // implying the symlinks exist and are already up to date.
      if (Arrays.equals(
          runfilesDir.getRelative("MANIFEST").getMD5Digest(),
          execSettings.getInputManifest().getPath().getMD5Digest())) {
        return;
      }
    } catch (IOException e1) {
      // Ignore it - we will just try to create runfiles directory.
    }

    executor
        .getEventHandler()
        .handle(
            Event.progress(
                "Building runfiles directory for '"
                    + execSettings.getExecutable().prettyPrint()
                    + "'."));

    new SymlinkTreeHelper(execSettings.getInputManifest().getPath(), runfilesDir, false)
        .createSymlinks(
            testAction, actionExecutionContext, binTools, shellEnvironment, enableRunfiles);

    executor.getEventHandler().handle(Event.progress(testAction.getProgressMessage()));
  }
Esempio n. 4
0
  @Override
  @ThreadCompatible
  public void execute(ActionExecutionContext actionExecutionContext)
      throws ActionExecutionException, InterruptedException {
    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);
    NestedSet<Artifact> discoveredInputs =
        discoverInputsFromDotdFiles(
            executor.getExecRoot(), scanningContext.getArtifactResolver(), reply);
    reply = null; // Clear in-memory .d files early.

    // Even cc_fake_binary rules need to properly declare their dependencies...
    // In fact, they need to declare their dependencies even more than cc_binary rules do.
    // CcCommonConfiguredTarget passes in an empty set of declaredIncludeDirs,
    // so this check below will only allow inclusion of header files that are explicitly
    // listed in the "srcs" of the cc_fake_binary or in the "srcs" of a cc_library that it
    // 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);
                        // Once -c and -o options are added into action_config, the argument of
                        // getArgv(outputFile.getExecPath()) won't be used anymore. There will
                        // always be
                        // -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;
                      }
                    }));

    // Write the command needed to build the real .o file to the fake .o file.
    // Generate a command to ensure that the output directory exists; otherwise
    // 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);
    }
  }