/* * 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.cxx.CxxHeaders; import com.facebook.buck.rules.RuleKeyAppendable; import com.facebook.buck.rules.RuleKeyObjectSink; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.Tool; import com.facebook.buck.shell.ShellStep; import com.facebook.buck.step.ExecutionContext; import com.facebook.buck.util.MoreIterables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import java.nio.file.Path; import java.util.Optional; /** Compilation step for C interoperability files. */ public class OcamlCCompileStep extends ShellStep { private final SourcePathResolver resolver; private final Args args; OcamlCCompileStep(SourcePathResolver resolver, Path workingDirectory, Args args) { super(workingDirectory); this.resolver = resolver; this.args = args; } @Override public String getShortName() { return "OCaml C compile"; } @Override protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) { ImmutableList.Builder<String> cmd = ImmutableList.<String>builder() .addAll(args.ocamlCompiler.getCommandPrefix(resolver)) .addAll(OcamlCompilables.DEFAULT_OCAML_FLAGS); if (args.stdlib.isPresent()) { cmd.add("-nostdlib", OcamlCompilables.OCAML_INCLUDE_FLAG, args.stdlib.get()); } return cmd.add("-cc", args.cCompiler.get(0)) .addAll( MoreIterables.zipAndConcat( Iterables.cycle("-ccopt"), args.cCompiler.subList(1, args.cCompiler.size()))) .add("-c") .add("-annot") .add("-bin-annot") .add("-o", args.output.toString()) .add("-ccopt", "-Wall") .add("-ccopt", "-Wextra") .add("-ccopt", String.format("-o %s", args.output.toString())) .addAll(args.flags) .add(resolver.getAbsolutePath(args.input).toString()) .build(); } @Override public ImmutableMap<String, String> getEnvironmentVariables(ExecutionContext context) { return args.environment; } public static class Args implements RuleKeyAppendable { public final ImmutableMap<String, String> environment; public final Tool ocamlCompiler; public final ImmutableList<String> cCompiler; public final ImmutableList<String> flags; public final Optional<String> stdlib; public final Path output; public final SourcePath input; public final ImmutableList<CxxHeaders> includes; public Args( ImmutableMap<String, String> environment, ImmutableList<String> cCompiler, Tool ocamlCompiler, Optional<String> stdlib, Path output, SourcePath input, ImmutableList<String> flags, ImmutableList<CxxHeaders> includes) { this.environment = environment; this.cCompiler = cCompiler; this.ocamlCompiler = ocamlCompiler; this.stdlib = stdlib; this.output = output; this.input = input; this.flags = flags; this.includes = includes; } @Override public void appendToRuleKey(RuleKeyObjectSink sink) { sink.setReflectively("cCompiler", cCompiler); sink.setReflectively("ocamlCompiler", ocamlCompiler); sink.setReflectively("stdlib", stdlib); sink.setReflectively("output", output.toString()); sink.setReflectively("input", input); sink.setReflectively("flags", flags); sink.setReflectively("includes", includes); } } }