Java tutorial
/* * Copyright 2014-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.ocaml; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.rules.RuleKeyAppendable; import com.facebook.buck.rules.RuleKeyObjectSink; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.Tool; import com.facebook.buck.shell.Shell; import com.facebook.buck.step.ExecutionContext; import com.facebook.buck.step.Step; import com.facebook.buck.step.StepExecutionResult; import com.facebook.buck.step.fs.WriteFileStep; import com.facebook.buck.util.MoreIterables; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; /** * OCaml linking step. Dependencies and inputs should be topologically ordered */ public class OcamlDebugLauncherStep implements Step { private final ProjectFilesystem filesystem; private final SourcePathResolver resolver; private final Args args; public OcamlDebugLauncherStep(ProjectFilesystem filesystem, SourcePathResolver resolver, Args args) { this.filesystem = filesystem; this.resolver = resolver; this.args = args; } @Override public StepExecutionResult execute(ExecutionContext context) throws InterruptedException, IOException { String debugCmdStr = getDebugCmd(); String debugLauncherScript = getDebugLauncherScript(debugCmdStr); WriteFileStep writeFile = new WriteFileStep(filesystem, debugLauncherScript, args.getOutput(), /* executable */ true); return writeFile.execute(context); } private String getDebugLauncherScript(String debugCmdStr) { ImmutableList.Builder<String> debugFile = ImmutableList.builder(); debugFile.add("#!/bin/sh"); debugFile.add(debugCmdStr); return Joiner.on("\n").join(debugFile.build()); } private String getDebugCmd() { ImmutableList.Builder<String> debugCmd = ImmutableList.builder(); debugCmd.add("rlwrap"); debugCmd.addAll(args.ocamlDebug.getCommandPrefix(resolver)); Iterable<String> includesBytecodeDirs = FluentIterable.from(args.ocamlInput) .transformAndConcat(new Function<OcamlLibrary, Iterable<String>>() { @Override public Iterable<String> apply(OcamlLibrary input) { return input.getBytecodeIncludeDirs(); } }); ImmutableList<String> includesBytecodeFlags = ImmutableList.copyOf(MoreIterables .zipAndConcat(Iterables.cycle(OcamlCompilables.OCAML_INCLUDE_FLAG), includesBytecodeDirs)); debugCmd.addAll(includesBytecodeFlags); debugCmd.addAll(args.bytecodeIncludeFlags); debugCmd.add(args.bytecodeOutput.toString()); return Shell.shellQuoteJoin(debugCmd.build(), " ") + " $@"; } @Override public String getShortName() { return "OCaml debug launcher"; } @Override public String getDescription(ExecutionContext context) { return getShortName(); } public static class Args implements RuleKeyAppendable { public final Tool ocamlDebug; public final Path bytecodeOutput; public final ImmutableList<OcamlLibrary> ocamlInput; public final ImmutableList<String> bytecodeIncludeFlags; public Args(Tool ocamlDebug, Path bytecodeOutput, List<OcamlLibrary> ocamlInput, List<String> bytecodeIncludeFlags) { this.ocamlDebug = ocamlDebug; this.bytecodeOutput = bytecodeOutput; this.ocamlInput = ImmutableList.copyOf(ocamlInput); this.bytecodeIncludeFlags = ImmutableList.copyOf(bytecodeIncludeFlags); } public Path getOutput() { return Paths.get(bytecodeOutput.toString() + ".debug"); } @Override public void appendToRuleKey(RuleKeyObjectSink sink) { sink.setReflectively("ocamlDebug", ocamlDebug) .setReflectively("bytecodeOutput", bytecodeOutput.toString()) .setReflectively("flags", bytecodeIncludeFlags); } } }