/*
* 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 static com.facebook.buck.ocaml.OcamlRuleBuilder.createOcamlLinkTarget;
import static com.facebook.buck.ocaml.OcamlRuleBuilder.createStaticLibraryBuildTarget;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.config.Config;
import com.facebook.buck.config.Configs;
import com.facebook.buck.cxx.CxxBuckConfig;
import com.facebook.buck.cxx.CxxDescriptionEnhancer;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.cxx.CxxPlatformUtils;
import com.facebook.buck.cxx.CxxSourceRuleFactory;
import com.facebook.buck.cxx.CxxSourceRuleFactoryHelper;
import com.facebook.buck.cxx.DefaultCxxPlatforms;
import com.facebook.buck.cxx.HeaderVisibility;
import com.facebook.buck.io.ExecutableFinder;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.rules.DefaultCellPathResolver;
import com.facebook.buck.testutil.integration.BuckBuildLog;
import com.facebook.buck.testutil.integration.ProjectWorkspace;
import com.facebook.buck.testutil.integration.TemporaryPaths;
import com.facebook.buck.testutil.integration.TestDataHelper;
import com.facebook.buck.util.ProcessExecutor;
import com.facebook.buck.util.environment.Architecture;
import com.facebook.buck.util.environment.Platform;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
public class OCamlIntegrationTest {
@Rule public TemporaryPaths tmp = new TemporaryPaths();
@Before
public void checkOcamlIsConfigured() throws InterruptedException, IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot());
Config rawConfig = Configs.createDefaultConfig(filesystem.getRootPath());
BuckConfig buckConfig =
new BuckConfig(
rawConfig,
filesystem,
Architecture.detect(),
Platform.detect(),
ImmutableMap.copyOf(System.getenv()),
new DefaultCellPathResolver(filesystem.getRootPath(), rawConfig));
OcamlBuckConfig ocamlBuckConfig =
new OcamlBuckConfig(
buckConfig,
DefaultCxxPlatforms.build(
Platform.detect(), filesystem, new CxxBuckConfig(buckConfig)));
assumeTrue(ocamlBuckConfig.getOcamlCompiler().isPresent());
assumeTrue(ocamlBuckConfig.getOcamlBytecodeCompiler().isPresent());
assumeTrue(ocamlBuckConfig.getOcamlDepTool().isPresent());
assumeTrue(ocamlBuckConfig.getYaccCompiler().isPresent());
assumeTrue(ocamlBuckConfig.getLexCompiler().isPresent());
}
@Test
public void testHelloOcamlBuild() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//hello_ocaml:hello_ocaml");
BuildTarget binary = createOcamlLinkTarget(target);
BuildTarget lib =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//hello_ocaml:ocamllib");
BuildTarget staticLib = createStaticLibraryBuildTarget(lib);
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary, lib, staticLib);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(staticLib.toString());
workspace.resetBuildLogFile();
// Check that running a build again results in no builds since everything is up to
// date.
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(ImmutableSet.of(binary, target), buildLog.getAllTargets());
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
buildLog.assertTargetHadMatchingRuleKey(target.toString());
workspace.resetBuildLogFile();
// Update the source file.
workspace.replaceFileContents("hello_ocaml/amodule.ml", "v2", "v3");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetHadMatchingRuleKey(staticLib.toString());
workspace.resetBuildLogFile();
// Update the source file.
workspace.replaceFileContents("hello_ocaml/ocamllib/m1.ml", "print me", "print Me");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(staticLib.toString());
workspace.resetBuildLogFile();
// Update the source file.
workspace.replaceFileContents("hello_ocaml/BUCK", "#INSERT_POINT", "'ocamllib/dummy.ml',");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(staticLib.toString());
workspace.resetBuildLogFile();
BuildTarget lib1 =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//hello_ocaml:ocamllib1");
BuildTarget staticLib1 = createStaticLibraryBuildTarget(lib1);
ImmutableSet<BuildTarget> targets1 = ImmutableSet.of(target, binary, lib1, staticLib1);
// We rebuild if lib name changes
workspace.replaceFileContents("hello_ocaml/BUCK", "name = 'ocamllib'", "name = 'ocamllib1'");
workspace.replaceFileContents("hello_ocaml/BUCK", ":ocamllib", ":ocamllib1");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets1));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(staticLib1.toString());
}
@Test
public void testNativePlugin() throws IOException, Exception {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
// Build the plugin
BuildTarget pluginTarget =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_native_plugin:plugin");
workspace.runBuckCommand("build", pluginTarget.toString()).assertSuccess();
// Also build a test binary that we'll use to verify that the .cmxs file
// works
BuildTarget binTarget =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_native_plugin:tester");
workspace.runBuckCommand("build", binTarget.toString()).assertSuccess();
Path ocamlNativePluginDir =
workspace.getDestPath().resolve("buck-out").resolve("gen").resolve("ocaml_native_plugin");
Path pluginCmxsFile = ocamlNativePluginDir.resolve("plugin").resolve("libplugin.cmxs");
Path testerExecutableFile = ocamlNativePluginDir.resolve("tester").resolve("tester");
// Run `./tester /path/to/plugin.cmxs`
String out =
workspace
.runCommand(testerExecutableFile.toString(), pluginCmxsFile.toString())
.getStdout()
.get();
assertEquals("it works!\n", out);
}
@Test
public void testLexAndYaccBuild() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//calc:calc");
BuildTarget binary = createOcamlLinkTarget(target);
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
assertEquals(targets, buildLog.getAllTargets());
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(ImmutableSet.of(binary, target), buildLog.getAllTargets());
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
buildLog.assertTargetHadMatchingRuleKey(target.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("calc/lexer.mll", "The type token", "the type token");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(targets, buildLog.getAllTargets());
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("calc/parser.mly", "the entry point", "The entry point");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(targets, buildLog.getAllTargets());
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
}
@Test
public void testCInteropBuild() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//ctest:ctest");
BuildTarget binary = createOcamlLinkTarget(target);
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
workspace.resetBuildLogFile();
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(ImmutableSet.of(binary, target), buildLog.getAllTargets());
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
buildLog.assertTargetHadMatchingRuleKey(target.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("ctest/ctest.c", "NATIVE PLUS", "Native Plus");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("ctest/BUCK", "#INSERTION_POINT", "compiler_flags=['-noassert']");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents(
"ctest/BUCK", "compiler_flags=['-noassert']", "compiler_flags=[]");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("ctest/BUCK", "compiler_flags=[]", "compiler_flags=[]");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertEquals(ImmutableSet.of(binary, target), buildLog.getAllTargets());
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
buildLog.assertTargetHadMatchingRuleKey(target.toString());
}
@Test
public void testSimpleBuildWithLib() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:plus");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
}
@Test
public void testRootBuildTarget() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:main");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
}
@Test
@Ignore("Redesign test so it does not depend on compiler/platform-specific binary artifacts.")
public void testPrebuiltLibraryBytecodeOnly() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_ext_bc:ocaml_ext");
BuildTarget binary = createOcamlLinkTarget(target);
BuildTarget bytecode = OcamlBuildRulesGenerator.addBytecodeFlavor(binary);
BuildTarget libplus =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_ext_bc:plus");
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, bytecode, libplus);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
assertFalse(buildLog.getAllTargets().contains(binary));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(bytecode.toString());
}
@Test
@Ignore("Redesign test so it does not depend on compiler/platform-specific binary artifacts.")
public void testPrebuiltLibraryMac() throws IOException {
if (Platform.detect() == Platform.MACOS) {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_ext_mac:ocaml_ext");
BuildTarget binary = createOcamlLinkTarget(target);
BuildTarget bytecode = OcamlBuildRulesGenerator.addBytecodeFlavor(binary);
BuildTarget libplus =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//ocaml_ext_mac:plus");
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary, bytecode, libplus);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
for (BuildTarget t : targets) {
assertTrue(
String.format("Expected %s to be built", t.toString()),
buildLog.getAllTargets().contains(t));
}
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
workspace.runBuckCommand("build", target.toString()).assertSuccess();
for (BuildTarget t : targets) {
assertTrue(
String.format("Expected %s to be built", t.toString()),
buildLog.getAllTargets().contains(t));
}
buildLog.assertTargetHadMatchingRuleKey(target.toString());
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("ocaml_ext_mac/BUCK", "libplus_lib", "libplus_lib1");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
}
}
@Test
public void testCppLibraryDependency() throws InterruptedException, IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//clib:clib");
BuildTarget binary = createOcamlLinkTarget(target);
BuildTarget libplus = BuildTargetFactory.newInstance(workspace.getDestPath(), "//clib:plus");
BuildTarget libplusStatic = createStaticLibraryBuildTarget(libplus);
BuildTarget cclib = BuildTargetFactory.newInstance(workspace.getDestPath(), "//clib:cc");
CxxPlatform cxxPlatform =
CxxPlatformUtils.build(new CxxBuckConfig(FakeBuckConfig.builder().build()));
CxxSourceRuleFactory cxxSourceRuleFactory =
CxxSourceRuleFactoryHelper.of(workspace.getDestPath(), cclib, cxxPlatform);
BuildTarget cclibbin =
CxxDescriptionEnhancer.createStaticLibraryBuildTarget(
cclib, cxxPlatform.getFlavor(), CxxSourceRuleFactory.PicType.PDC);
String sourceName = "cc/cc.cpp";
BuildTarget ccObj = cxxSourceRuleFactory.createCompileBuildTarget(sourceName);
BuildTarget headerSymlinkTreeTarget =
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
cclib, HeaderVisibility.PRIVATE, cxxPlatform.getFlavor());
BuildTarget exportedHeaderSymlinkTreeTarget =
CxxDescriptionEnhancer.createHeaderSymlinkTreeTarget(
cclib,
HeaderVisibility.PUBLIC,
CxxPlatformUtils.getHeaderModeForDefaultPlatform(tmp.getRoot()).getFlavor());
workspace.runBuckCommand("build", target.toString()).assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally(binary.toString());
buildLog.assertTargetBuiltLocally(libplusStatic.toString());
buildLog.assertTargetBuiltLocally(cclibbin.toString());
buildLog.assertTargetBuiltLocally(ccObj.toString());
buildLog.assertTargetBuiltLocally(headerSymlinkTreeTarget.toString());
buildLog.assertTargetBuiltLocally(exportedHeaderSymlinkTreeTarget.toString());
workspace.resetBuildLogFile();
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
buildLog.assertTargetHadMatchingRuleKey(binary.toString());
buildLog.assertTargetHadMatchingRuleKey(target.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents("clib/cc/cc.cpp", "Hi there", "hi there");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally(binary.toString());
buildLog.assertTargetBuiltLocally(libplusStatic.toString());
buildLog.assertTargetBuiltLocally(cclibbin.toString());
buildLog.assertTargetBuiltLocally(ccObj.toString());
}
@Test
public void testConfigWarningsFlags() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "config_warnings_flags", tmp);
workspace.setUp();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:unused_var");
BuildTarget binary = createOcamlLinkTarget(target);
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary);
workspace.runBuckCommand("build", target.toString()).assertFailure();
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetCanceled(target.toString());
buildLog.assertTargetCanceled(binary.toString());
workspace.resetBuildLogFile();
workspace.replaceFileContents(".buckconfig", "warnings_flags=+a", "");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
}
@Test
public void testConfigInteropIncludes() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "config_interop_includes", tmp);
workspace.setUp();
Path ocamlc =
new ExecutableFinder(Platform.detect())
.getExecutable(Paths.get("ocamlc"), ImmutableMap.copyOf(System.getenv()));
ProcessExecutor.Result result = workspace.runCommand(ocamlc.toString(), "-where");
assertEquals(0, result.getExitCode());
String stdlibPath = result.getStdout().get();
BuildTarget target = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:test");
BuildTarget binary = createOcamlLinkTarget(target);
ImmutableSet<BuildTarget> targets = ImmutableSet.of(target, binary);
// Points somewhere with no stdlib in it, so fails to find Pervasives
workspace.runBuckCommand("build", target.toString()).assertFailure();
BuckBuildLog buildLog = workspace.getBuildLog();
assertThat(buildLog.getAllTargets(), Matchers.hasItems(targets.toArray(new BuildTarget[0])));
buildLog.assertTargetCanceled(target.toString());
buildLog.assertTargetCanceled(binary.toString());
workspace.resetBuildLogFile();
// Point to the real stdlib (from `ocamlc -where`)
workspace.replaceFileContents(
".buckconfig", "interop.includes=lib", "interop.includes=" + stdlibPath);
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
workspace.resetBuildLogFile();
// Remove the config, should default to a valid place
workspace.replaceFileContents(".buckconfig", "interop.includes=" + stdlibPath, "");
workspace.runBuckCommand("build", target.toString()).assertSuccess();
buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally(target.toString());
buildLog.assertTargetBuiltLocally(binary.toString());
}
@Test
public void testGenruleDependency() throws IOException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "ocaml", tmp);
workspace.setUp();
BuildTarget binary =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//generated:binary");
BuildTarget generated =
BuildTargetFactory.newInstance(workspace.getDestPath(), "//generated:generated");
ImmutableSet<BuildTarget> targets = ImmutableSet.of(binary, generated);
// Build the binary.
workspace.runBuckCommand("build", binary.toString()).assertSuccess();
// Make sure the generated target is built as well.
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(binary.toString());
}
@Test
public void testCompilerFlagsDependency() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "compiler_flag_macros", tmp);
workspace.setUp();
String ocamlVersion = this.getOcamlVersion(workspace);
assumeTrue("Installed ocaml is too old for this test", "4.02.0".compareTo(ocamlVersion) <= 0);
BuildTarget binary = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:main");
BuildTarget lib = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:lib");
BuildTarget helper = BuildTargetFactory.newInstance(workspace.getDestPath(), "//:test");
ImmutableSet<BuildTarget> targets = ImmutableSet.of(binary, lib, helper);
// Build the binary.
workspace.runBuckCommand("build", binary.toString()).assertSuccess();
// Make sure the helper target is built as well.
BuckBuildLog buildLog = workspace.getBuildLog();
assertTrue(buildLog.getAllTargets().containsAll(targets));
buildLog.assertTargetBuiltLocally(binary.toString());
// Make sure the ppx flag worked
String out = workspace.runBuckCommand("run", binary.toString()).getStdout();
assertEquals("42!\n", out);
}
private String getOcamlVersion(ProjectWorkspace workspace)
throws IOException, InterruptedException {
Path ocamlc =
new ExecutableFinder(Platform.detect())
.getExecutable(Paths.get("ocamlc"), ImmutableMap.copyOf(System.getenv()));
ProcessExecutor.Result result = workspace.runCommand(ocamlc.toString(), "-version");
assertEquals(0, result.getExitCode());
return result.getStdout().get();
}
}