예제 #1
0
  private StepExecutionResult executeCCompilation(
      ExecutionContext context, ImmutableList.Builder<Path> linkerInputs)
      throws IOException, InterruptedException {

    ImmutableList.Builder<String> cCompileFlags = ImmutableList.builder();
    cCompileFlags.addAll(ocamlContext.getCCompileFlags());
    cCompileFlags.addAll(ocamlContext.getCommonCFlags());

    CxxPreprocessorInput cxxPreprocessorInput = ocamlContext.getCxxPreprocessorInput();

    for (SourcePath cSrc : ocamlContext.getCInput()) {
      Path outputPath = ocamlContext.getCOutput(resolver.getAbsolutePath(cSrc));
      linkerInputs.add(outputPath);
      Step compileStep =
          new OCamlCCompileStep(
              resolver,
              filesystem.getRootPath(),
              new OCamlCCompileStep.Args(
                  cCompilerEnvironment,
                  cCompiler,
                  ocamlContext.getOcamlCompiler().get(),
                  ocamlContext.getOCamlInteropIncludesDir(),
                  outputPath,
                  cSrc,
                  cCompileFlags.build(),
                  cxxPreprocessorInput.getIncludes()));
      StepExecutionResult compileExecutionResult = compileStep.execute(context);
      if (!compileExecutionResult.isSuccess()) {
        return compileExecutionResult;
      }
    }
    return StepExecutionResult.SUCCESS;
  }
예제 #2
0
  private int executeCCompilation(
      ExecutionContext context, ImmutableList.Builder<Path> linkerInputs)
      throws IOException, InterruptedException {

    ImmutableList.Builder<String> cCompileFlags = ImmutableList.builder();
    cCompileFlags.addAll(ocamlContext.getCCompileFlags());
    cCompileFlags.addAll(ocamlContext.getCommonCFlags());

    CxxPreprocessorInput cxxPreprocessorInput = ocamlContext.getCxxPreprocessorInput();

    for (SourcePath cSrc : ocamlContext.getCInput()) {
      Path outputPath = ocamlContext.getCOutput(resolver.getAbsolutePath(cSrc));
      linkerInputs.add(outputPath);
      Step compileStep =
          new OCamlCCompileStep(
              resolver,
              filesystem.getRootPath(),
              new OCamlCCompileStep.Args(
                  cCompilerEnvironment,
                  cCompiler,
                  ocamlContext.getOcamlCompiler().get(),
                  outputPath,
                  cSrc,
                  cCompileFlags.build(),
                  ImmutableMap.copyOf(cxxPreprocessorInput.getIncludes().getNameToPathMap())));
      int compileExitCode = compileStep.execute(context);
      if (compileExitCode != 0) {
        return compileExitCode;
      }
    }
    return 0;
  }
예제 #3
0
  @Test
  public void flagsArePropagated() throws Exception {
    BuildRuleResolver resolver =
        new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
    BuildTarget target = BuildTargetFactory.newInstance("//foo:bar");
    BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build();
    Archive archive =
        Archive.from(
            target,
            params,
            new SourcePathResolver(resolver),
            DEFAULT_ARCHIVER,
            ImmutableList.of("-foo"),
            DEFAULT_RANLIB,
            ImmutableList.of("-bar"),
            Archive.Contents.NORMAL,
            DEFAULT_OUTPUT,
            ImmutableList.of(new FakeSourcePath("simple.o")));

    ImmutableList<Step> steps =
        archive.getBuildSteps(FakeBuildContext.NOOP_CONTEXT, new FakeBuildableContext());
    Step archiveStep = FluentIterable.from(steps).filter(ArchiveStep.class).first().get();
    assertThat(
        archiveStep.getDescription(TestExecutionContext.newInstance()), containsString("-foo"));

    Step ranlibStep = FluentIterable.from(steps).filter(RanlibStep.class).first().get();
    assertThat(
        ranlibStep.getDescription(TestExecutionContext.newInstance()), containsString("-bar"));
  }
  @Test
  public void testGetBuildStepsWhenThereAreNoClassesToDex()
      throws IOException, InterruptedException {
    JavaLibrary javaLibrary = createMock(JavaLibrary.class);
    expect(javaLibrary.getClassNamesToHashes())
        .andReturn(ImmutableSortedMap.<String, HashCode>of());

    BuildContext context = createMock(BuildContext.class);
    FakeBuildableContext buildableContext = new FakeBuildableContext();
    ProjectFilesystem projectFilesystem = createMock(ProjectFilesystem.class);

    replayAll();

    BuildTarget buildTarget = BuildTargetFactory.newInstance("//foo:bar");
    BuildRuleParams params =
        new FakeBuildRuleParamsBuilder(buildTarget).setProjectFilesystem(projectFilesystem).build();
    DexProducedFromJavaLibrary preDex =
        new DexProducedFromJavaLibrary(
            params, new SourcePathResolver(new BuildRuleResolver()), javaLibrary);
    List<Step> steps = preDex.getBuildSteps(context, buildableContext);

    verifyAll();
    resetAll();

    expect(projectFilesystem.resolve(Paths.get("buck-out/gen/foo")))
        .andReturn(Paths.get("/home/user/buck-out/gen/foo"));
    expect(projectFilesystem.resolve(Paths.get("buck-out/gen/foo/bar.dex.jar")))
        .andReturn(Paths.get("/home/user/buck-out/gen/foo/bar.dex.jar"));
    replayAll();

    ExecutionContext executionContext = TestExecutionContext.newBuilder().build();

    MoreAsserts.assertSteps(
        "Do not generate a .dex.jar file.",
        ImmutableList.of(
            String.format("rm -f %s", Paths.get("/home/user/buck-out/gen/foo/bar.dex.jar")),
            String.format("mkdir -p %s", Paths.get("/home/user/buck-out/gen/foo")),
            "record_empty_dx"),
        steps,
        executionContext);

    verifyAll();
    resetAll();

    replayAll();

    Step recordArtifactAndMetadataStep = steps.get(2);
    assertThat(recordArtifactAndMetadataStep.getShortName(), startsWith("record_"));
    int exitCode = recordArtifactAndMetadataStep.execute(executionContext);
    assertEquals(0, exitCode);

    verifyAll();
  }
예제 #5
0
    @Override
    public void scale(double factor, Path source, Path destination, ExecutionContext context)
        throws IOException, InterruptedException {
      Step convertStep =
          new BashStep(
              workingDirectory,
              "convert",
              "-adaptive-resize",
              (int) (factor * 100) + "%",
              Escaper.escapeAsBashString(source),
              Escaper.escapeAsBashString(destination));

      if (0 != convertStep.execute(context)) {
        throw new HumanReadableException("Cannot scale " + source + " to " + destination);
      }
    }
예제 #6
0
 private StepExecutionResult executeMLBytecodeCompilation(
     ExecutionContext context,
     Path workingDirectory,
     ImmutableList<Path> sortedInput,
     ImmutableList.Builder<Path> linkerInputs)
     throws IOException, InterruptedException {
   MakeCleanDirectoryStep mkDir =
       new MakeCleanDirectoryStep(filesystem, ocamlContext.getCompileBytecodeOutputDir());
   StepExecutionResult mkDirExecutionResult = mkDir.execute(context);
   if (!mkDirExecutionResult.isSuccess()) {
     return mkDirExecutionResult;
   }
   for (Path inputOutput : sortedInput) {
     String inputFileName = inputOutput.getFileName().toString();
     String outputFileName =
         inputFileName
             .replaceFirst(OCamlCompilables.OCAML_ML_REGEX, OCamlCompilables.OCAML_CMO)
             .replaceFirst(OCamlCompilables.OCAML_RE_REGEX, OCamlCompilables.OCAML_CMO)
             .replaceFirst(OCamlCompilables.OCAML_MLI_REGEX, OCamlCompilables.OCAML_CMI)
             .replaceFirst(OCamlCompilables.OCAML_REI_REGEX, OCamlCompilables.OCAML_CMI);
     Path outputPath = ocamlContext.getCompileBytecodeOutputDir().resolve(outputFileName);
     if (!outputFileName.endsWith(OCamlCompilables.OCAML_CMI)) {
       linkerInputs.add(outputPath);
     }
     final ImmutableList<String> compileFlags =
         getCompileFlags(/* isBytecode */ true, /* excludeDeps */ false);
     Step compileBytecodeStep =
         new OCamlMLCompileStep(
             workingDirectory,
             resolver,
             new OCamlMLCompileStep.Args(
                 filesystem.getAbsolutifier(),
                 cCompilerEnvironment,
                 cCompiler,
                 ocamlContext.getOcamlBytecodeCompiler().get(),
                 ocamlContext.getOCamlInteropIncludesDir(),
                 outputPath,
                 inputOutput,
                 compileFlags));
     StepExecutionResult compileExecutionResult = compileBytecodeStep.execute(context);
     if (!compileExecutionResult.isSuccess()) {
       return compileExecutionResult;
     }
   }
   return StepExecutionResult.SUCCESS;
 }
예제 #7
0
  @Override
  public int execute(ExecutionContext context) throws IOException, InterruptedException {
    if (hasGeneratedSources) {
      int genExitCode = generateSources(context, filesystem.getRootPath());
      if (genExitCode != 0) {
        return genExitCode;
      }
    }

    int depToolExitCode = depToolStep.execute(context);
    if (depToolExitCode != 0) {
      return depToolExitCode;
    }

    // OCaml requires module A to be present in command line to ocamlopt or ocamlc before
    // module B if B depends on A. In OCaml circular dependencies are prohibited, so all
    // dependency relations among modules form DAG. Topologically sorting this graph satisfies the
    // requirement.
    //
    // To get the DAG we launch ocamldep tool which provides the direct dependency information, like
    // module A depends on modules B, C, D.
    ImmutableList<Path> sortedInput = sortDependency(depToolStep.getStdout());
    ImmutableList.Builder<Path> linkerInputs = ImmutableList.builder();
    int mlCompileExitCode =
        executeMLCompilation(context, filesystem.getRootPath(), sortedInput, linkerInputs);
    if (mlCompileExitCode != 0) {
      return mlCompileExitCode;
    }

    ImmutableList.Builder<Path> bytecodeLinkerInputs = ImmutableList.builder();
    int mlCompileBytecodeExitCode =
        executeMLCompileBytecode(
            context, filesystem.getRootPath(), sortedInput, bytecodeLinkerInputs);
    if (mlCompileBytecodeExitCode != 0) {
      return mlCompileBytecodeExitCode;
    }

    ImmutableList.Builder<Path> cLinkerInputs = ImmutableList.builder();
    int cCompileExitCode = executeCCompilation(context, cLinkerInputs);
    if (cCompileExitCode != 0) {
      return cCompileExitCode;
    }

    ImmutableList<Path> cObjects = cLinkerInputs.build();

    linkerInputs.addAll(cObjects);
    int nativeLinkExitCode = executeLinking(context, linkerInputs.build());
    if (nativeLinkExitCode != 0) {
      return nativeLinkExitCode;
    }

    bytecodeLinkerInputs.addAll(cObjects);
    int bytecodeExitCode = executeBytecodeLinking(context, bytecodeLinkerInputs.build());
    if (bytecodeExitCode != 0) {
      return bytecodeExitCode;
    }

    if (!ocamlContext.isLibrary()) {
      Step debugLauncher =
          new OCamlDebugLauncherStep(
              filesystem,
              resolver,
              new OCamlDebugLauncherStep.Args(
                  ocamlContext.getOcamlDebug().get(),
                  ocamlContext.getBytecodeOutput(),
                  ocamlContext.getOCamlInput(),
                  ocamlContext.getBytecodeIncludeFlags()));
      return debugLauncher.execute(context);
    } else {
      return 0;
    }
  }
  @Test
  public void testGetBuildStepsWhenThereAreClassesToDex() throws IOException, InterruptedException {
    SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
    FakeJavaLibrary javaLibraryRule =
        new FakeJavaLibrary(BuildTargetFactory.newInstance("//foo:bar"), pathResolver) {
          @Override
          public ImmutableSortedMap<String, HashCode> getClassNamesToHashes() {
            return ImmutableSortedMap.of("com/example/Foo", HashCode.fromString("cafebabe"));
          }

          @Override
          public Sha1HashCode getAbiKey() {
            return Sha1HashCode.of("f7f34ed13b881c6c6f663533cde4a436ea84435e");
          }
        };
    javaLibraryRule.setOutputFile("buck-out/gen/foo/bar.jar");

    BuildContext context = createMock(BuildContext.class);
    FakeBuildableContext buildableContext = new FakeBuildableContext();

    replayAll();

    ProjectFilesystem filesystem = FakeProjectFilesystem.createJavaOnlyFilesystem("/home/user");
    createFiles(filesystem, "buck-out/gen/foo/bar#dex.dex.jar", "buck-out/gen/foo/bar.jar");

    BuildTarget buildTarget = BuildTargetFactory.newInstance("//foo:bar#dex");
    BuildRuleParams params =
        new FakeBuildRuleParamsBuilder(buildTarget).setProjectFilesystem(filesystem).build();
    DexProducedFromJavaLibrary preDex =
        new DexProducedFromJavaLibrary(params, pathResolver, javaLibraryRule);
    List<Step> steps = preDex.getBuildSteps(context, buildableContext);

    verifyAll();
    resetAll();

    AndroidPlatformTarget androidPlatformTarget = createMock(AndroidPlatformTarget.class);
    expect(androidPlatformTarget.getDxExecutable()).andReturn(Paths.get("/usr/bin/dx"));

    replayAll();

    ExecutionContext executionContext =
        TestExecutionContext.newBuilder()
            .setAndroidPlatformTargetSupplier(Suppliers.ofInstance(androidPlatformTarget))
            .build();

    String expectedDxCommand =
        String.format(
            "%s --dex --no-optimize --force-jumbo --output %s %s",
            Paths.get("/usr/bin/dx"),
            Paths.get("/home/user/buck-out/gen/foo/bar#dex.dex.jar"),
            Paths.get("/home/user/buck-out/gen/foo/bar.jar"));
    MoreAsserts.assertSteps(
        "Generate bar.dex.jar.",
        ImmutableList.of(
            String.format("rm -f %s", Paths.get("/home/user/buck-out/gen/foo/bar#dex.dex.jar")),
            String.format("mkdir -p %s", Paths.get("/home/user/buck-out/gen/foo")),
            "estimate_linear_alloc",
            "(cd /home/user && " + expectedDxCommand + ")",
            "zip-scrub buck-out/gen/foo/bar#dex.dex.jar",
            "record_dx_success"),
        steps,
        executionContext);

    verifyAll();
    resetAll();

    replayAll();

    ((EstimateLinearAllocStep) steps.get(2)).setLinearAllocEstimateForTesting(250);
    Step recordArtifactAndMetadataStep = steps.get(5);
    int exitCode = recordArtifactAndMetadataStep.execute(executionContext);
    assertEquals(0, exitCode);
    assertEquals(
        "The generated .dex.jar file should be in the set of recorded artifacts.",
        ImmutableSet.of(Paths.get("buck-out/gen/foo/bar#dex.dex.jar")),
        buildableContext.getRecordedArtifacts());

    buildableContext.assertContainsMetadataMapping(
        DexProducedFromJavaLibrary.LINEAR_ALLOC_KEY_ON_DISK_METADATA, "250");

    verifyAll();
  }