private static ExecutableInfo getExecutableToDebug()

in golang/src/com/google/idea/blaze/golang/run/BlazeGoRunConfigurationRunner.java [271:382]


  private static ExecutableInfo getExecutableToDebug(ExecutionEnvironment env)
      throws ExecutionException {
    BlazeCommandRunConfiguration configuration =
        BlazeCommandRunConfigurationRunner.getConfiguration(env);
    Project project = configuration.getProject();
    BlazeProjectData blazeProjectData =
        BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
    if (blazeProjectData == null) {
      throw new ExecutionException("Not synced yet, please sync project");
    }
    Label label = getSingleTarget(configuration);

    SaveUtil.saveAllFiles();
    // Explicitly create local build helper, because the debuggable script is expected to be present
    // locally
    try (BuildResultHelper buildResultHelper =
        BuildResultHelperProvider.createForLocalBuild(project)) {
      ImmutableList.Builder<String> flags = ImmutableList.builder();
      if (Blaze.getBuildSystem(project) == BuildSystem.Blaze) {
        // $ go tool compile
        //   -N    disable optimizations
        //   -l    disable inlining
        flags.add("--gc_goopt=-N").add("--gc_goopt=-l");
      } else {
        // bazel build adds these flags themselves with -c dbg
        // https://github.com/bazelbuild/rules_go/issues/741
        flags.add("--compilation_mode=dbg");
      }

      Optional<Path> scriptPath = Optional.empty();
      if (scriptPathEnabled.getValue()) {
        try {
          scriptPath = Optional.of(BlazeBeforeRunCommandHelper.createScriptPathFile());
          flags.add("--script_path=" + scriptPath.get());
        } catch (IOException e) {
          // Could still work without script path.
          // Script path is only needed to parse arguments from target.
          logger.warn("Failed to create script path file. Target arguments will not be parsed.", e);
        }
      }

      ListenableFuture<BuildResult> buildOperation =
          BlazeBeforeRunCommandHelper.runBlazeCommand(
              scriptPath.isPresent() ? BlazeCommandName.RUN : BlazeCommandName.BUILD,
              configuration,
              buildResultHelper,
              flags.build(),
              ImmutableList.of("--dynamic_mode=off", "--test_sharding_strategy=disabled"),
              BlazeInvocationContext.runConfigContext(
                  ExecutorType.fromExecutor(env.getExecutor()), configuration.getType(), true),
              "Building debug binary");

      try {
        BuildResult result = buildOperation.get();
        if (result.outOfMemory()) {
          throw new ExecutionException("Out of memory while trying to build debug target");
        } else if (result.status == Status.BUILD_ERROR) {
          throw new ExecutionException("Build error while trying to build debug target");
        } else if (result.status == Status.FATAL_ERROR) {
          throw new ExecutionException(
              String.format(
                  "Fatal error (%d) while trying to build debug target", result.exitCode));
        }
      } catch (InterruptedException | CancellationException e) {
        buildOperation.cancel(true);
        throw new RunCanceledByUserException();
      } catch (java.util.concurrent.ExecutionException e) {
        throw new ExecutionException(e);
      }
      if (scriptPath.isPresent()) {
        if (!Files.exists(scriptPath.get())) {
          throw new ExecutionException(
              String.format(
                  "No debugger executable script path file produced. Expected file at: %s",
                  scriptPath.get()));
        }
        WorkspaceRoot workspaceRoot = WorkspaceRoot.fromProject(project);
        BlazeInfo blazeInfo =
            BlazeProjectDataManager.getInstance(project).getBlazeProjectData().getBlazeInfo();
        return parseScriptPathFile(workspaceRoot, blazeInfo.getExecutionRoot(), scriptPath.get());
      } else {
        List<File> candidateFiles;
        try {
          candidateFiles =
              BlazeArtifact.getLocalFiles(
                      buildResultHelper.getBuildArtifactsForTarget(label, file -> true))
                  .stream()
                  .filter(File::canExecute)
                  .collect(Collectors.toList());
        } catch (GetArtifactsException e) {
          throw new ExecutionException(
              String.format(
                  "Failed to get output artifacts when building %s: %s", label, e.getMessage()));
        }
        if (candidateFiles.isEmpty()) {
          throw new ExecutionException(
              String.format("No output artifacts found when building %s", label));
        }
        File binary = findExecutable(label, candidateFiles);
        if (binary == null) {
          throw new ExecutionException(
              String.format(
                  "More than 1 executable was produced when building %s; "
                      + "don't know which one to debug",
                  label));
        }
        LocalFileSystem.getInstance().refreshIoFiles(ImmutableList.of(binary));
        File workingDir = getWorkingDirectory(WorkspaceRoot.fromProject(project), binary);
        return new ExecutableInfo(binary, workingDir, ImmutableList.of(), ImmutableMap.of());
      }
    }
  }