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; }
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; }
private StepExecutionResult generateSources(ExecutionContext context, Path workingDirectory) throws IOException, InterruptedException { MakeCleanDirectoryStep mkDir = new MakeCleanDirectoryStep(filesystem, ocamlContext.getGeneratedSourceDir()); StepExecutionResult mkDirExecutionResult = mkDir.execute(context); if (!mkDirExecutionResult.isSuccess()) { return mkDirExecutionResult; } for (SourcePath yaccSource : ocamlContext.getYaccInput()) { SourcePath output = ocamlContext.getYaccOutput(ImmutableSet.of(yaccSource)).get(0); OCamlYaccStep yaccStep = new OCamlYaccStep( workingDirectory, resolver, new OCamlYaccStep.Args( ocamlContext.getYaccCompiler().get(), resolver.getAbsolutePath(output), resolver.getAbsolutePath(yaccSource))); StepExecutionResult yaccExecutionResult = yaccStep.execute(context); if (!yaccExecutionResult.isSuccess()) { return yaccExecutionResult; } } for (SourcePath lexSource : ocamlContext.getLexInput()) { SourcePath output = ocamlContext.getLexOutput(ImmutableSet.of(lexSource)).get(0); OCamlLexStep lexStep = new OCamlLexStep( workingDirectory, resolver, new OCamlLexStep.Args( ocamlContext.getLexCompiler().get(), resolver.getAbsolutePath(output), resolver.getAbsolutePath(lexSource))); StepExecutionResult lexExecutionResult = lexStep.execute(context); if (!lexExecutionResult.isSuccess()) { return lexExecutionResult; } } return StepExecutionResult.SUCCESS; }
@Override public StepExecutionResult execute(ExecutionContext context) throws IOException, InterruptedException { if (hasGeneratedSources) { StepExecutionResult genExecutionResult = generateSources(context, filesystem.getRootPath()); if (!genExecutionResult.isSuccess()) { return genExecutionResult; } } StepExecutionResult depToolExecutionResult = depToolStep.execute(context); if (!depToolExecutionResult.isSuccess()) { return depToolExecutionResult; } // 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(), ocamlContext.getSourcePathResolver().getAllAbsolutePaths(ocamlContext.getMLInput())); ImmutableList.Builder<Path> nativeLinkerInputs = ImmutableList.builder(); if (!bytecodeOnly) { StepExecutionResult mlCompileNativeExecutionResult = executeMLNativeCompilation( context, filesystem.getRootPath(), sortedInput, nativeLinkerInputs); if (!mlCompileNativeExecutionResult.isSuccess()) { return mlCompileNativeExecutionResult; } } ImmutableList.Builder<Path> bytecodeLinkerInputs = ImmutableList.builder(); StepExecutionResult mlCompileBytecodeExecutionResult = executeMLBytecodeCompilation( context, filesystem.getRootPath(), sortedInput, bytecodeLinkerInputs); if (!mlCompileBytecodeExecutionResult.isSuccess()) { return mlCompileBytecodeExecutionResult; } ImmutableList.Builder<Path> cLinkerInputs = ImmutableList.builder(); StepExecutionResult cCompileExecutionResult = executeCCompilation(context, cLinkerInputs); if (!cCompileExecutionResult.isSuccess()) { return cCompileExecutionResult; } ImmutableList<Path> cObjects = cLinkerInputs.build(); if (!bytecodeOnly) { nativeLinkerInputs.addAll(cObjects); StepExecutionResult nativeLinkExecutionResult = executeNativeLinking(context, nativeLinkerInputs.build()); if (!nativeLinkExecutionResult.isSuccess()) { return nativeLinkExecutionResult; } } bytecodeLinkerInputs.addAll(cObjects); StepExecutionResult bytecodeLinkExecutionResult = executeBytecodeLinking(context, bytecodeLinkerInputs.build()); if (!bytecodeLinkExecutionResult.isSuccess()) { return bytecodeLinkExecutionResult; } 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 StepExecutionResult.SUCCESS; } }