/*
* Copyright 2016-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.swift;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import static org.junit.Assume.assumeTrue;
import com.facebook.buck.apple.AppleDescriptions;
import com.facebook.buck.apple.AppleNativeIntegrationTestUtils;
import com.facebook.buck.apple.ApplePlatform;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.InternalFlavor;
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.environment.Platform;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.CoreMatchers;
import org.junit.Rule;
import org.junit.Test;
public class SwiftIOSBundleIntegrationTest {
@Rule public TemporaryPaths tmp = new TemporaryPaths();
@Test
public void simpleApplicationBundle() throws Exception {
assumeThat(
AppleNativeIntegrationTestUtils.isSwiftAvailable(ApplePlatform.IPHONESIMULATOR), is(true));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(
this, "simple_swift_application_bundle", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
BuildTarget target = workspace.newBuildTarget("//:DemoApp#iphonesimulator-x86_64,no-debug");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
workspace.verify(
Paths.get("DemoApp_output.expected"),
BuildTargets.getGenPath(
filesystem,
BuildTarget.builder(target)
.addFlavors(AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR)
.build(),
"%s"));
Path appPath =
workspace.getPath(
BuildTargets.getGenPath(
filesystem,
BuildTarget.builder(target)
.addFlavors(AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR)
.build(),
"%s")
.resolve(target.getShortName() + ".app"));
assertTrue(Files.exists(appPath.resolve(target.getShortName())));
}
@Test
public void swiftWithSwiftDependenciesBuildsSomething() throws Exception {
assumeThat(
AppleNativeIntegrationTestUtils.isSwiftAvailable(ApplePlatform.IPHONESIMULATOR), is(true));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_swift", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
BuildTarget target = workspace.newBuildTarget("//:parent");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
target = workspace.newBuildTarget("//:libparent");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
target = workspace.newBuildTarget("//:ios-sos#iphonesimulator-x86_64,no-debug");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
Path appPath =
workspace.getPath(
BuildTargets.getGenPath(
filesystem,
BuildTarget.builder(target)
.addFlavors(AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR)
.build(),
"%s")
.resolve(target.getShortName() + ".app"));
assertTrue(Files.exists(appPath.resolve(target.getShortName())));
}
@Test
public void swiftLibraryWhenLinkStyleIsNotSharedDoesNotProduceDylib() throws Exception {
assumeTrue(Platform.detect() == Platform.MACOS);
assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_swift", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
BuildTarget parentDynamicTarget =
BuildTargetFactory.newInstance("//:ios-parent-dynamic")
.withAppendedFlavors(InternalFlavor.of("iphonesimulator-x86_64"));
ProjectWorkspace.ProcessResult result =
workspace.runBuckCommand(
"build", parentDynamicTarget.getFullyQualifiedName(), "--config", "cxx.cflags=-g");
result.assertSuccess();
Path binaryOutput =
workspace.resolve(BuildTargets.getGenPath(filesystem, parentDynamicTarget, "%s"));
assertThat(Files.exists(binaryOutput), CoreMatchers.is(true));
assertThat(
workspace.runCommand("file", binaryOutput.toString()).getStdout().get(),
containsString("executable"));
assertThat(
workspace.runCommand("otool", "-hv", binaryOutput.toString()).getStdout().get(),
containsString("X86_64"));
assertThat(
workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
not(containsString("libdep1.dylib")));
Path dep1Output =
tmp.getRoot()
.resolve(filesystem.getBuckPaths().getGenDir())
.resolve("iosdep1#iphonesimulator-x86_64,swift-compile")
.resolve("libiosdep1.dylib");
assertThat(Files.notExists(dep1Output), CoreMatchers.is(true));
}
@Test
public void swiftLibraryWhenLinkStyleIsSharedShouldProduceDylib() throws Exception {
assumeTrue(Platform.detect() == Platform.MACOS);
assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_swift", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
BuildTarget parentDynamicTarget =
BuildTargetFactory.newInstance("//:ios-parent-dynamic")
.withAppendedFlavors(InternalFlavor.of("iphonesimulator-x86_64"));
ProjectWorkspace.ProcessResult result =
workspace.runBuckCommand(
"build", parentDynamicTarget.getFullyQualifiedName(), "--config", "cxx.cflags=-g");
result.assertSuccess();
Path binaryOutput =
workspace.resolve(BuildTargets.getGenPath(filesystem, parentDynamicTarget, "%s"));
assertThat(Files.exists(binaryOutput), CoreMatchers.is(true));
assertThat(
workspace.runCommand("file", binaryOutput.toString()).getStdout().get(),
containsString("executable"));
assertThat(
workspace.runCommand("otool", "-hv", binaryOutput.toString()).getStdout().get(),
containsString("X86_64"));
assertThat(
workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
containsString("libiosdep1.dylib"));
Path parentOutput =
tmp.getRoot()
.resolve(filesystem.getBuckPaths().getGenDir())
.resolve("ios-parent-dynamic#iphonesimulator-x86_64,swift-compile")
.resolve("ios_parent_dynamic.swiftmodule");
assertThat(Files.exists(parentOutput), CoreMatchers.is(true));
BuildTarget iosdep1Target =
BuildTargetFactory.newInstance("//:iosdep1")
.withAppendedFlavors(InternalFlavor.of("iphonesimulator-x86_64"));
Path iosdep1TargetOutput =
workspace.resolve(BuildTargets.getGenPath(filesystem, iosdep1Target, "%s"));
assertThat(
Files.exists(iosdep1TargetOutput.resolve("libiosdep1.dylib")), CoreMatchers.is(true));
}
@Test
public void testSwiftSharedLibraryCustomSoname() throws Exception {
assumeTrue(Platform.detect() == Platform.MACOS);
assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_swift", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
ProjectWorkspace.ProcessResult result =
workspace.runBuckCommand(
"build", ":dep1-soname#iphonesimulator-x86_64,shared", "--config", "cxx.cflags=-g");
result.assertSuccess();
Path binaryOutput =
tmp.getRoot()
.resolve(filesystem.getBuckPaths().getGenDir())
.resolve("dep1-soname#iphonesimulator-x86_64")
.resolve("custom-soname");
assertThat(Files.exists(binaryOutput), CoreMatchers.is(true));
assertThat(
workspace.runCommand("file", binaryOutput.toString()).getStdout().get(),
containsString("shared library"));
assertThat(
workspace.runCommand("otool", "-hv", binaryOutput.toString()).getStdout().get(),
containsString("X86_64"));
assertThat(
workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
containsString("@rpath/custom-soname"));
assertThat(
workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
not(containsString("@rpath/dep1-soname")));
}
@Test
public void testSwiftPreferredLinkage() throws Exception {
assumeTrue(Platform.detect() == Platform.MACOS);
assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_swift", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
workspace.replaceFileContents(
"BUCK",
"preferred_linkage = 'any', # iosdep1 preferred_linkage anchor",
"preferred_linkage = 'static'");
ProjectWorkspace.ProcessResult result =
workspace.runBuckCommand(
"build", ":ios-parent-dynamic#iphonesimulator-x86_64", "--config", "cxx.cflags=-g");
result.assertSuccess();
Path binaryOutput =
tmp.getRoot()
.resolve(filesystem.getBuckPaths().getGenDir())
.resolve("ios-parent-dynamic#iphonesimulator-x86_64");
assertThat(Files.exists(binaryOutput), CoreMatchers.is(true));
Path dep1Output =
tmp.getRoot()
.resolve(filesystem.getBuckPaths().getGenDir())
.resolve("iosdep1#iphonesimulator-x86_64")
.resolve("libiosdep1.dylib");
assertThat(Files.exists(dep1Output), CoreMatchers.is(false));
assertThat(
workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
not(containsString("libiosdep1.dylib")));
assertThat(
workspace.runCommand("nm", binaryOutput.toString()).getStdout().orElse(""),
containsString("baz"));
}
@Test
public void swiftDependsOnObjCRunsAndPrintsMessage() throws Exception {
assumeThat(
AppleNativeIntegrationTestUtils.isSwiftAvailable(ApplePlatform.IPHONESIMULATOR), is(true));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "swift_on_objc", tmp);
workspace.setUp();
ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
BuildTarget target = workspace.newBuildTarget("//:binary#iphonesimulator-x86_64");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
target = workspace.newBuildTarget("//:bundle#iphonesimulator-x86_64,no-debug");
workspace.runBuckCommand("build", target.getFullyQualifiedName()).assertSuccess();
Path appPath =
workspace.getPath(
BuildTargets.getGenPath(
filesystem,
BuildTarget.builder(target)
.addFlavors(AppleDescriptions.NO_INCLUDE_FRAMEWORKS_FLAVOR)
.build(),
"%s")
.resolve(target.getShortName() + ".app"));
assertTrue(Files.exists(appPath.resolve(target.getShortName())));
}
}