Search in sources :

Example 16 with PBXFileReference

use of com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference in project buck by facebook.

the class SchemeGeneratorTest method schemeBuildsAndTestsAppleTestTargets.

@Test
public void schemeBuildsAndTestsAppleTestTargets() throws Exception {
    ImmutableMap.Builder<PBXTarget, Path> targetToProjectPathMapBuilder = ImmutableMap.builder();
    PBXTarget testDepTarget = new PBXNativeTarget("testDep");
    testDepTarget.setGlobalID("testDepGID");
    testDepTarget.setProductReference(new PBXFileReference("libDep.a", "libDep.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testDepTarget.setProductType(ProductType.STATIC_LIBRARY);
    PBXTarget testLibraryTarget = new PBXNativeTarget("testLibrary");
    testLibraryTarget.setGlobalID("testLibraryGID");
    testLibraryTarget.setProductReference(new PBXFileReference("lib.a", "lib.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testLibraryTarget.setProductType(ProductType.STATIC_LIBRARY);
    PBXTarget testTarget = new PBXNativeTarget("test");
    testTarget.setGlobalID("testGID");
    testTarget.setProductReference(new PBXFileReference("test.xctest", "test.xctest", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testTarget.setProductType(ProductType.UNIT_TEST);
    PBXTarget rootTarget = new PBXNativeTarget("root");
    rootTarget.setGlobalID("rootGID");
    rootTarget.setProductReference(new PBXFileReference("root.a", "root.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    rootTarget.setProductType(ProductType.STATIC_LIBRARY);
    Path projectPath = Paths.get("foo/test.xcodeproj/project.pbxproj");
    targetToProjectPathMapBuilder.put(testTarget, projectPath);
    targetToProjectPathMapBuilder.put(testDepTarget, projectPath);
    targetToProjectPathMapBuilder.put(testLibraryTarget, projectPath);
    targetToProjectPathMapBuilder.put(rootTarget, projectPath);
    SchemeGenerator schemeGenerator = new SchemeGenerator(projectFilesystem, Optional.of(rootTarget), ImmutableSet.of(rootTarget), ImmutableSet.of(testDepTarget, testTarget), ImmutableSet.of(testTarget), "TestScheme", Paths.get("_gen/Foo.xcworkspace/scshareddata/xcshemes"), false, /* primaryTargetIsBuildWithBuck */
    false, /* parallelizeBuild */
    Optional.empty(), /* runnablePath */
    Optional.empty(), /* remoteRunnablePath */
    SchemeActionType.DEFAULT_CONFIG_NAMES, targetToProjectPathMapBuilder.build(), XCScheme.LaunchAction.LaunchStyle.AUTO);
    Path schemePath = schemeGenerator.writeScheme();
    String schemeXml = projectFilesystem.readFileIfItExists(schemePath).get();
    System.out.println(schemeXml);
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document scheme = dBuilder.parse(projectFilesystem.newFileInputStream(schemePath));
    XPathFactory xpathFactory = XPathFactory.newInstance();
    XPath buildXpath = xpathFactory.newXPath();
    XPathExpression buildExpr = buildXpath.compile("//BuildAction//BuildableReference/@BlueprintIdentifier");
    NodeList buildNodes = (NodeList) buildExpr.evaluate(scheme, XPathConstants.NODESET);
    List<String> expectedBuildOrdering = ImmutableList.of("rootGID", "testDepGID", "testGID");
    List<String> actualBuildOrdering = Lists.newArrayList();
    for (int i = 0; i < buildNodes.getLength(); i++) {
        actualBuildOrdering.add(buildNodes.item(i).getNodeValue());
    }
    assertThat(actualBuildOrdering, equalTo(expectedBuildOrdering));
    XPath textXpath = xpathFactory.newXPath();
    XPathExpression testExpr = textXpath.compile("//TestAction//TestableReference/BuildableReference/@BlueprintIdentifier");
    NodeList testNodes = (NodeList) testExpr.evaluate(scheme, XPathConstants.NODESET);
    List<String> expectedTestOrdering = ImmutableList.of("testGID");
    List<String> actualTestOrdering = Lists.newArrayList();
    for (int i = 0; i < testNodes.getLength(); i++) {
        actualTestOrdering.add(testNodes.item(i).getNodeValue());
    }
    assertThat(actualTestOrdering, equalTo(expectedTestOrdering));
}
Also used : PBXTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXTarget) XPath(javax.xml.xpath.XPath) Path(java.nio.file.Path) XPath(javax.xml.xpath.XPath) XPathExpression(javax.xml.xpath.XPathExpression) PBXNativeTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) NodeList(org.w3c.dom.NodeList) Document(org.w3c.dom.Document) ImmutableMap(com.google.common.collect.ImmutableMap) XPathFactory(javax.xml.xpath.XPathFactory) DocumentBuilder(javax.xml.parsers.DocumentBuilder) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference) Test(org.junit.Test)

Example 17 with PBXFileReference

use of com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference in project buck by facebook.

the class SchemeGeneratorTest method launchActionShouldNotContainRemoteRunnableWhenNotProvided.

@Test
public void launchActionShouldNotContainRemoteRunnableWhenNotProvided() throws Exception {
    ImmutableMap.Builder<PBXTarget, Path> targetToProjectPathMapBuilder = ImmutableMap.builder();
    PBXTarget rootTarget = new PBXNativeTarget("rootRule");
    rootTarget.setGlobalID("rootGID");
    rootTarget.setProductReference(new PBXFileReference("root.a", "root.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    rootTarget.setProductType(ProductType.STATIC_LIBRARY);
    Path pbxprojectPath = Paths.get("foo/Foo.xcodeproj/project.pbxproj");
    targetToProjectPathMapBuilder.put(rootTarget, pbxprojectPath);
    SchemeGenerator schemeGenerator = new SchemeGenerator(projectFilesystem, Optional.of(rootTarget), ImmutableSet.of(rootTarget), ImmutableSet.of(), ImmutableSet.of(), "TestScheme", Paths.get("_gen/Foo.xcworkspace/scshareddata/xcshemes"), false, /* primaryTargetIsBuildWithBuck */
    false, /* parallelizeBuild */
    Optional.empty(), /* runnablePath */
    Optional.empty(), /* remoteRunnablePath */
    SchemeActionType.DEFAULT_CONFIG_NAMES, targetToProjectPathMapBuilder.build(), XCScheme.LaunchAction.LaunchStyle.AUTO);
    Path schemePath = schemeGenerator.writeScheme();
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document scheme = dBuilder.parse(projectFilesystem.newFileInputStream(schemePath));
    XPathFactory xpathFactory = XPathFactory.newInstance();
    XPath remoteRunnableLaunchActionXPath = xpathFactory.newXPath();
    XPathExpression remoteRunnableLaunchActionExpr = remoteRunnableLaunchActionXPath.compile("//LaunchAction/RemoteRunnable");
    NodeList remoteRunnables = (NodeList) remoteRunnableLaunchActionExpr.evaluate(scheme, XPathConstants.NODESET);
    assertThat(remoteRunnables.getLength(), equalTo(0));
}
Also used : PBXTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXTarget) XPath(javax.xml.xpath.XPath) Path(java.nio.file.Path) XPath(javax.xml.xpath.XPath) XPathExpression(javax.xml.xpath.XPathExpression) PBXNativeTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) NodeList(org.w3c.dom.NodeList) Document(org.w3c.dom.Document) ImmutableMap(com.google.common.collect.ImmutableMap) XPathFactory(javax.xml.xpath.XPathFactory) DocumentBuilder(javax.xml.parsers.DocumentBuilder) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference) Test(org.junit.Test)

Example 18 with PBXFileReference

use of com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference in project buck by facebook.

the class SchemeGeneratorTest method whenProvidedAPrimaryTargetThatIsBuiltWithBuckDoesntBuildDependencies.

@Test
public void whenProvidedAPrimaryTargetThatIsBuiltWithBuckDoesntBuildDependencies() throws Exception {
    ImmutableMap.Builder<PBXTarget, Path> targetToProjectPathMapBuilder = ImmutableMap.builder();
    PBXTarget libraryTarget = new PBXNativeTarget("library");
    libraryTarget.setGlobalID("libraryGID");
    libraryTarget.setProductReference(new PBXFileReference("lib.a", "lib.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    libraryTarget.setProductType(ProductType.STATIC_LIBRARY);
    PBXTarget rootTarget = new PBXNativeTarget("rootRule");
    rootTarget.setGlobalID("rootGID");
    rootTarget.setProductName("Foo");
    String runnablePath = "buck-out/gen/Foo/Foo.app";
    Path pbxprojectPath = Paths.get("foo/Foo.xcodeproj/project.pbxproj");
    targetToProjectPathMapBuilder.put(libraryTarget, pbxprojectPath);
    targetToProjectPathMapBuilder.put(rootTarget, pbxprojectPath);
    SchemeGenerator schemeGenerator = new SchemeGenerator(projectFilesystem, Optional.of(rootTarget), ImmutableSet.of(libraryTarget, rootTarget), ImmutableSet.of(), ImmutableSet.of(), "TestScheme", Paths.get("_gen/Foo.xcworkspace/scshareddata/xcshemes"), true, /* primaryTargetIsBuildWithBuck */
    false, /* parallelizeBuild */
    Optional.of(runnablePath), /* runnablePath */
    Optional.empty(), /* remoteRunnablePath */
    SchemeActionType.DEFAULT_CONFIG_NAMES, targetToProjectPathMapBuilder.build(), XCScheme.LaunchAction.LaunchStyle.AUTO);
    Path schemePath = schemeGenerator.writeScheme();
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document scheme = dBuilder.parse(projectFilesystem.newFileInputStream(schemePath));
    XPathFactory xpathFactory = XPathFactory.newInstance();
    XPath buildActionXpath = xpathFactory.newXPath();
    XPathExpression buildActionExpr = buildActionXpath.compile("//BuildAction//BuildActionEntry");
    NodeList buildActionNodes = (NodeList) buildActionExpr.evaluate(scheme, XPathConstants.NODESET);
    Node libraryNode = null;
    for (int i = 0; i < buildActionNodes.getLength(); i++) {
        Node node = buildActionNodes.item(i);
        if (node.getChildNodes().getLength() != 1) {
            continue;
        }
        Node buildableReference = node.getChildNodes().item(0);
        if (buildableReference.getAttributes().getNamedItem("BlueprintIdentifier").getNodeValue().equals("libraryGID")) {
            libraryNode = node;
            break;
        }
    }
    assertThat(libraryNode, is(notNullValue()));
    assertThat(libraryNode.getAttributes().getNamedItem("buildForRunning").getNodeValue(), equalTo("NO"));
}
Also used : PBXTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXTarget) XPath(javax.xml.xpath.XPath) Path(java.nio.file.Path) XPath(javax.xml.xpath.XPath) XPathExpression(javax.xml.xpath.XPathExpression) PBXNativeTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) Document(org.w3c.dom.Document) ImmutableMap(com.google.common.collect.ImmutableMap) XPathFactory(javax.xml.xpath.XPathFactory) DocumentBuilder(javax.xml.parsers.DocumentBuilder) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference) Test(org.junit.Test)

Example 19 with PBXFileReference

use of com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference in project buck by facebook.

the class SchemeGeneratorTest method schemeWithNoPrimaryRuleCanIncludeTests.

@Test
public void schemeWithNoPrimaryRuleCanIncludeTests() throws Exception {
    ImmutableMap.Builder<PBXTarget, Path> targetToProjectPathMapBuilder = ImmutableMap.builder();
    PBXTarget testLibraryTarget = new PBXNativeTarget("testLibrary");
    testLibraryTarget.setGlobalID("testLibraryGID");
    testLibraryTarget.setProductReference(new PBXFileReference("lib.a", "lib.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testLibraryTarget.setProductType(ProductType.STATIC_LIBRARY);
    PBXTarget testTarget = new PBXNativeTarget("testRule");
    testTarget.setGlobalID("testGID");
    testTarget.setProductReference(new PBXFileReference("test.a", "test.a", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testTarget.setProductType(ProductType.STATIC_LIBRARY);
    PBXTarget testBundleTarget = new PBXNativeTarget("testBundleRule");
    testBundleTarget.setGlobalID("testBundleGID");
    testBundleTarget.setProductReference(new PBXFileReference("test.xctest", "test.xctest", PBXReference.SourceTree.BUILT_PRODUCTS_DIR, Optional.empty()));
    testBundleTarget.setProductType(ProductType.UNIT_TEST);
    Path pbxprojectPath = Paths.get("foo/Foo.xcodeproj/project.pbxproj");
    targetToProjectPathMapBuilder.put(testLibraryTarget, pbxprojectPath);
    targetToProjectPathMapBuilder.put(testTarget, pbxprojectPath);
    targetToProjectPathMapBuilder.put(testBundleTarget, pbxprojectPath);
    SchemeGenerator schemeGenerator = new SchemeGenerator(projectFilesystem, Optional.empty(), ImmutableSet.of(), ImmutableSet.of(testBundleTarget), ImmutableSet.of(testBundleTarget), "TestScheme", Paths.get("_gen/Foo.xcworkspace/scshareddata/xcshemes"), false, /* primaryTargetIsBuildWithBuck */
    false, /* parallelizeBuild */
    Optional.empty(), /* runnablePath */
    Optional.empty(), /* remoteRunnablePath */
    SchemeActionType.DEFAULT_CONFIG_NAMES, targetToProjectPathMapBuilder.build(), XCScheme.LaunchAction.LaunchStyle.AUTO);
    Path schemePath = schemeGenerator.writeScheme();
    String schemeXml = projectFilesystem.readFileIfItExists(schemePath).get();
    System.out.println(schemeXml);
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document scheme = dBuilder.parse(projectFilesystem.newFileInputStream(schemePath));
    XPathFactory xpathFactory = XPathFactory.newInstance();
    XPath buildActionXpath = xpathFactory.newXPath();
    XPathExpression buildActionExpr = buildActionXpath.compile("//BuildAction//BuildableReference/@BlueprintIdentifier");
    NodeList buildActionNodes = (NodeList) buildActionExpr.evaluate(scheme, XPathConstants.NODESET);
    List<String> expectedOrdering = ImmutableList.of("testBundleGID");
    List<String> actualOrdering = Lists.newArrayList();
    for (int i = 0; i < buildActionNodes.getLength(); i++) {
        actualOrdering.add(buildActionNodes.item(i).getNodeValue());
    }
    assertThat(actualOrdering, equalTo(expectedOrdering));
    XPath testActionXpath = xpathFactory.newXPath();
    XPathExpression testActionExpr = testActionXpath.compile("//TestAction//BuildableReference/@BlueprintIdentifier");
    String testActionBlueprintIdentifier = (String) testActionExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(testActionBlueprintIdentifier, equalTo("testBundleGID"));
    XPath launchActionXpath = xpathFactory.newXPath();
    XPathExpression launchActionExpr = launchActionXpath.compile("//LaunchAction//BuildableReference/@BlueprintIdentifier");
    String launchActionBlueprintIdentifier = (String) launchActionExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(launchActionBlueprintIdentifier, equalTo(""));
    XPath launchActionBuildConfigurationXpath = xpathFactory.newXPath();
    XPathExpression launchActionBuildConfigurationExpr = launchActionBuildConfigurationXpath.compile("//LaunchAction//@buildConfiguration");
    String launchActionBuildConfigurationBlueprintIdentifier = (String) launchActionBuildConfigurationExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(launchActionBuildConfigurationBlueprintIdentifier, equalTo("Debug"));
    XPath profileActionXpath = xpathFactory.newXPath();
    XPathExpression profileActionExpr = profileActionXpath.compile("//ProfileAction//BuildableReference/@BlueprintIdentifier");
    String profileActionBlueprintIdentifier = (String) profileActionExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(profileActionBlueprintIdentifier, equalTo(""));
    XPath profileActionBuildConfigurationXpath = xpathFactory.newXPath();
    XPathExpression profileActionBuildConfigurationExpr = profileActionBuildConfigurationXpath.compile("//ProfileAction//@buildConfiguration");
    String profileActionBuildConfigurationBlueprintIdentifier = (String) profileActionBuildConfigurationExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(profileActionBuildConfigurationBlueprintIdentifier, equalTo("Release"));
    XPath analyzeActionBuildConfigurationXpath = xpathFactory.newXPath();
    XPathExpression analyzeActionBuildConfigurationExpr = analyzeActionBuildConfigurationXpath.compile("//AnalyzeAction//@buildConfiguration");
    String analyzeActionBuildConfigurationBlueprintIdentifier = (String) analyzeActionBuildConfigurationExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(analyzeActionBuildConfigurationBlueprintIdentifier, equalTo("Debug"));
    XPath archiveActionBuildConfigurationXpath = xpathFactory.newXPath();
    XPathExpression archiveActionBuildConfigurationExpr = archiveActionBuildConfigurationXpath.compile("//ArchiveAction//@buildConfiguration");
    String archiveActionBuildConfigurationBlueprintIdentifier = (String) archiveActionBuildConfigurationExpr.evaluate(scheme, XPathConstants.STRING);
    assertThat(archiveActionBuildConfigurationBlueprintIdentifier, equalTo("Release"));
}
Also used : PBXTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXTarget) XPath(javax.xml.xpath.XPath) Path(java.nio.file.Path) XPath(javax.xml.xpath.XPath) XPathExpression(javax.xml.xpath.XPathExpression) PBXNativeTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget) DocumentBuilderFactory(javax.xml.parsers.DocumentBuilderFactory) NodeList(org.w3c.dom.NodeList) Document(org.w3c.dom.Document) ImmutableMap(com.google.common.collect.ImmutableMap) XPathFactory(javax.xml.xpath.XPathFactory) DocumentBuilder(javax.xml.parsers.DocumentBuilder) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference) Test(org.junit.Test)

Example 20 with PBXFileReference

use of com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference in project bazel by bazelbuild.

the class XcodeprojGeneration method xcodeproj.

/** Generates a project file. */
public static PBXProject xcodeproj(Path workspaceRoot, Control control, Iterable<PbxReferencesProcessor> postProcessors) {
    checkArgument(control.hasPbxproj(), "Must set pbxproj field on control proto.");
    FileSystem fileSystem = workspaceRoot.getFileSystem();
    XcodeprojPath<Path> outputPath = XcodeprojPath.converter().fromPath(RelativePaths.fromString(fileSystem, control.getPbxproj()));
    NSDictionary projBuildConfigMap = new NSDictionary();
    projBuildConfigMap.put("ARCHS", cpuArchitectures(control.getCpuArchitectureList()));
    projBuildConfigMap.put("VALID_ARCHS", new NSArray(new NSString("armv7"), new NSString("armv7s"), new NSString("arm64"), new NSString("i386"), new NSString("x86_64")));
    projBuildConfigMap.put("CLANG_ENABLE_OBJC_ARC", "YES");
    projBuildConfigMap.put("SDKROOT", "iphoneos");
    projBuildConfigMap.put("IPHONEOS_DEPLOYMENT_TARGET", "7.0");
    projBuildConfigMap.put("GCC_VERSION", "com.apple.compilers.llvm.clang.1_0");
    projBuildConfigMap.put("CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer");
    // Disable bitcode for now.
    // TODO(bazel-team): Need to re-enable once we have real Xcode 7 support.
    projBuildConfigMap.put("ENABLE_BITCODE", "NO");
    for (XcodeprojBuildSetting projectSetting : control.getBuildSettingList()) {
        projBuildConfigMap.put(projectSetting.getName(), projectSetting.getValue());
    }
    PBXProject project = new PBXProject(outputPath.getProjectName());
    project.getMainGroup().setPath(workspaceRoot.toString());
    if (workspaceRoot.isAbsolute()) {
        project.getMainGroup().setSourceTree(SourceTree.ABSOLUTE);
    }
    try {
        project.getBuildConfigurationList().getBuildConfigurationsByName().get(DEFAULT_OPTIONS_NAME).setBuildSettings(projBuildConfigMap);
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    }
    Map<String, TargetInfo> targetInfoByLabel = new HashMap<>();
    List<String> usedTargetNames = new ArrayList<>();
    PBXFileReferences fileReferences = new PBXFileReferences();
    LibraryObjects libraryObjects = new LibraryObjects(fileReferences);
    PBXBuildFiles pbxBuildFiles = new PBXBuildFiles(fileReferences);
    Resources resources = Resources.fromTargetControls(fileSystem, pbxBuildFiles, control.getTargetList());
    Xcdatamodels xcdatamodels = Xcdatamodels.fromTargetControls(fileSystem, pbxBuildFiles, control.getTargetList());
    // We use a hash set for the Project Navigator files so that the same PBXFileReference does not
    // get added twice. Because PBXFileReference uses equality-by-identity semantics, this requires
    // the PBXFileReferences cache to properly return the same reference for functionally-equivalent
    // files.
    Set<PBXReference> projectNavigatorFiles = new LinkedHashSet<>();
    for (TargetControl targetControl : control.getTargetList()) {
        checkArgument(targetControl.hasName(), "TargetControl requires a name: %s", targetControl);
        checkArgument(targetControl.hasLabel(), "TargetControl requires a label: %s", targetControl);
        ProductType productType = productType(targetControl);
        Preconditions.checkArgument((productType != ProductType.APPLICATION) || hasAtLeastOneCompilableSource(targetControl), APP_NEEDS_SOURCE_ERROR);
        PBXSourcesBuildPhase sourcesBuildPhase = new PBXSourcesBuildPhase();
        for (SourceFile source : SourceFile.allSourceFiles(fileSystem, targetControl)) {
            PBXFileReference fileRef = fileReferences.get(FileReference.of(source.path().toString(), SourceTree.GROUP));
            projectNavigatorFiles.add(fileRef);
            if (Equaling.of(source.buildType(), BuildType.NO_BUILD)) {
                continue;
            }
            PBXBuildFile buildFile = new PBXBuildFile(fileRef);
            if (Equaling.of(source.buildType(), BuildType.NON_ARC_BUILD)) {
                buildFile.setSettings(Optional.of(nonArcCompileSettings()));
            }
            sourcesBuildPhase.getFiles().add(buildFile);
        }
        sourcesBuildPhase.getFiles().addAll(xcdatamodels.buildFiles().get(targetControl));
        PBXFileReference productReference = fileReferences.get(productReference(targetControl));
        projectNavigatorFiles.add(productReference);
        NSDictionary targetBuildConfigMap = new NSDictionary();
        // TODO(bazel-team): Stop adding the workspace root automatically once the
        // released version of Bazel starts passing it.
        targetBuildConfigMap.put("USER_HEADER_SEARCH_PATHS", headerSearchPaths(plus(targetControl.getUserHeaderSearchPathList(), "$(WORKSPACE_ROOT)")));
        targetBuildConfigMap.put("HEADER_SEARCH_PATHS", headerSearchPaths(plus(targetControl.getHeaderSearchPathList(), "$(inherited)")));
        targetBuildConfigMap.put("FRAMEWORK_SEARCH_PATHS", frameworkSearchPaths(Iterables.concat(targetControl.getFrameworkList(), targetControl.getFrameworkSearchPathOnlyList())));
        targetBuildConfigMap.put("WORKSPACE_ROOT", workspaceRoot.toString());
        if (targetControl.hasPchPath()) {
            targetBuildConfigMap.put("GCC_PREFIX_HEADER", "$(WORKSPACE_ROOT)/" + targetControl.getPchPath());
        }
        targetBuildConfigMap.put("PRODUCT_NAME", productName(targetControl));
        if (targetControl.hasInfoplist()) {
            targetBuildConfigMap.put("INFOPLIST_FILE", "$(WORKSPACE_ROOT)/" + targetControl.getInfoplist());
        }
        // Double-quotes in copt strings need to be escaped for XCode.
        if (targetControl.getCoptCount() > 0) {
            List<String> escapedCopts = Lists.transform(targetControl.getCoptList(), QUOTE_ESCAPER.asFunction());
            targetBuildConfigMap.put("OTHER_CFLAGS", NSObject.wrap(escapedCopts));
        }
        targetBuildConfigMap.put("OTHER_LDFLAGS", NSObject.wrap(otherLdflags(targetControl)));
        for (XcodeprojBuildSetting setting : targetControl.getBuildSettingList()) {
            String name = setting.getName();
            String value = setting.getValue();
            // TODO(bazel-team): Remove this hack after next Bazel release.
            if (name.equals("CODE_SIGN_ENTITLEMENTS") && !value.startsWith("$")) {
                value = "$(WORKSPACE_ROOT)/" + value;
            }
            targetBuildConfigMap.put(name, value);
        }
        // Note that HFS+ (the Mac filesystem) is usually case insensitive, so we cast all target
        // names to lower case before checking for duplication because otherwise users may end up
        // having duplicated intermediate build directories that can interfere with the build.
        String targetName = targetControl.getName();
        String targetNameInLowerCase = targetName.toLowerCase();
        if (usedTargetNames.contains(targetNameInLowerCase)) {
            // Use the label in the odd case where we have two targets with the same name.
            targetName = targetControl.getLabel();
            targetNameInLowerCase = targetName.toLowerCase();
        }
        checkState(!usedTargetNames.contains(targetNameInLowerCase), "Name (case-insensitive) already exists for target with label/name %s/%s in list: %s", targetControl.getLabel(), targetControl.getName(), usedTargetNames);
        usedTargetNames.add(targetNameInLowerCase);
        PBXNativeTarget target = new PBXNativeTarget(targetName, productType);
        try {
            target.getBuildConfigurationList().getBuildConfigurationsByName().get(DEFAULT_OPTIONS_NAME).setBuildSettings(targetBuildConfigMap);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        target.setProductReference(productReference);
        // We only add frameworks here and not dylibs because of differences in how
        // Xcode 6 and Xcode 7 specify dylibs in the project organizer.
        // (Xcode 6 -> *.dylib, Xcode 7 -> *.tbd)
        PBXFrameworksBuildPhase frameworksPhase = buildFrameworksInfo(libraryObjects, targetControl);
        PBXResourcesBuildPhase resourcesPhase = resources.resourcesBuildPhase(targetControl);
        for (String importedArchive : targetControl.getImportedLibraryList()) {
            PBXFileReference fileReference = fileReferences.get(FileReference.of(importedArchive, SourceTree.GROUP).withExplicitFileType(FILE_TYPE_ARCHIVE_LIBRARY));
            projectNavigatorFiles.add(fileReference);
        }
        project.getTargets().add(target);
        target.getBuildPhases().add(frameworksPhase);
        target.getBuildPhases().add(sourcesBuildPhase);
        target.getBuildPhases().add(resourcesPhase);
        checkState(!Mapping.of(targetInfoByLabel, targetControl.getLabel()).isPresent(), "Mapping already exists for target with label %s in map: %s", targetControl.getLabel(), targetInfoByLabel);
        targetInfoByLabel.put(targetControl.getLabel(), new TargetInfo(targetControl, target, frameworksPhase, resourcesPhase, new PBXBuildFile(productReference), new LocalPBXTargetDependency(new LocalPBXContainerItemProxy(project, target, ProxyType.TARGET_REFERENCE)), targetBuildConfigMap));
    }
    for (HasProjectNavigatorFiles references : ImmutableList.of(pbxBuildFiles, libraryObjects)) {
        Iterables.addAll(projectNavigatorFiles, references.mainGroupReferences());
    }
    Iterable<PBXReference> processedProjectFiles = projectNavigatorFiles;
    for (PbxReferencesProcessor postProcessor : postProcessors) {
        processedProjectFiles = postProcessor.process(processedProjectFiles);
    }
    Iterables.addAll(project.getMainGroup().getChildren(), processedProjectFiles);
    for (TargetInfo targetInfo : targetInfoByLabel.values()) {
        TargetControl targetControl = targetInfo.control;
        for (DependencyControl dependency : targetControl.getDependencyList()) {
            targetInfo.addDependencyInfo(dependency, targetInfoByLabel);
        }
        if (!Equaling.of(ProductType.STATIC_LIBRARY, productType(targetControl)) && !targetControl.getImportedLibraryList().isEmpty()) {
            // We add a script build phase to copy the imported libraries to BUILT_PRODUCT_DIR with
            // unique names before linking them to work around an Xcode issue where imported libraries
            // with duplicated names lead to link errors.
            //
            // Internally Xcode uses linker flag -l{LIBRARY_NAME} to link a particular library and
            // delegates to the linker to locate the actual library using library search paths. So given
            // two imported libraries with the same name: a/b/libfoo.a, c/d/libfoo.a, Xcode uses
            // duplicate linker flag -lfoo to link both of the libraries. Depending on the order of
            // the library search paths, the linker will only be able to locate and link one of the
            // libraries.
            //
            // With this workaround using a script build phase, all imported libraries to link have
            // unique names. For the previous example with a/b/libfoo.a and c/d/libfoo.a, the script
            // build phase will copy them to BUILT_PRODUCTS_DIR with unique names libfoo_b_a.a and
            // libfoo_d_c.a, respectively. The linker flags Xcode uses to link them will be
            // -lfoo_d_c and -lfoo_b_a, with no duplication.
            PBXShellScriptBuildPhase scriptBuildPhase = new PBXShellScriptBuildPhase();
            scriptBuildPhase.setShellScript("for ((i=0; i < ${SCRIPT_INPUT_FILE_COUNT}; i++)) do\n" + "  INPUT_FILE=\"SCRIPT_INPUT_FILE_${i}\"\n" + "  OUTPUT_FILE=\"SCRIPT_OUTPUT_FILE_${i}\"\n" + "  cp -v -f \"${!INPUT_FILE}\" \"${!OUTPUT_FILE}\"\n" + "done");
            for (String importedLibrary : targetControl.getImportedLibraryList()) {
                String uniqueImportedLibrary = uniqueImportedLibraryName(importedLibrary);
                scriptBuildPhase.getInputPaths().add("$(WORKSPACE_ROOT)/" + importedLibrary);
                scriptBuildPhase.getOutputPaths().add("$(BUILT_PRODUCTS_DIR)/" + uniqueImportedLibrary);
                FileReference fileReference = FileReference.of(uniqueImportedLibrary, SourceTree.BUILT_PRODUCTS_DIR).withExplicitFileType(FILE_TYPE_ARCHIVE_LIBRARY);
                targetInfo.frameworksPhase.getFiles().add(pbxBuildFiles.getStandalone(fileReference));
            }
            targetInfo.nativeTarget.getBuildPhases().add(scriptBuildPhase);
        }
    }
    return project;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PBXReference(com.facebook.buck.apple.xcode.xcodeproj.PBXReference) NSArray(com.dd.plist.NSArray) HashMap(java.util.HashMap) NSDictionary(com.dd.plist.NSDictionary) TargetControl(com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.TargetControl) ArrayList(java.util.ArrayList) DependencyControl(com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.DependencyControl) PBXFrameworksBuildPhase(com.facebook.buck.apple.xcode.xcodeproj.PBXFrameworksBuildPhase) NSString(com.dd.plist.NSString) NSString(com.dd.plist.NSString) PBXSourcesBuildPhase(com.facebook.buck.apple.xcode.xcodeproj.PBXSourcesBuildPhase) PBXShellScriptBuildPhase(com.facebook.buck.apple.xcode.xcodeproj.PBXShellScriptBuildPhase) FileSystem(java.nio.file.FileSystem) PBXProject(com.facebook.buck.apple.xcode.xcodeproj.PBXProject) ExecutionException(java.util.concurrent.ExecutionException) XcodeprojBuildSetting(com.google.devtools.build.xcode.xcodegen.proto.XcodeGenProtos.XcodeprojBuildSetting) XcodeprojPath(com.google.devtools.build.xcode.common.XcodeprojPath) Path(java.nio.file.Path) PBXNativeTarget(com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget) PBXBuildFile(com.facebook.buck.apple.xcode.xcodeproj.PBXBuildFile) ProductType(com.facebook.buck.apple.xcode.xcodeproj.PBXTarget.ProductType) PBXResourcesBuildPhase(com.facebook.buck.apple.xcode.xcodeproj.PBXResourcesBuildPhase) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference) PBXFileReference(com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference)

Aggregations

PBXFileReference (com.facebook.buck.apple.xcode.xcodeproj.PBXFileReference)40 Test (org.junit.Test)26 Path (java.nio.file.Path)19 PBXTarget (com.facebook.buck.apple.xcode.xcodeproj.PBXTarget)18 PBXGroup (com.facebook.buck.apple.xcode.xcodeproj.PBXGroup)17 BuildTarget (com.facebook.buck.model.BuildTarget)14 PBXNativeTarget (com.facebook.buck.apple.xcode.xcodeproj.PBXNativeTarget)13 NSString (com.dd.plist.NSString)12 PBXProject (com.facebook.buck.apple.xcode.xcodeproj.PBXProject)12 ImmutableMap (com.google.common.collect.ImmutableMap)12 SourceTreePath (com.facebook.buck.apple.xcode.xcodeproj.SourceTreePath)11 FakeSourcePath (com.facebook.buck.rules.FakeSourcePath)11 SourcePath (com.facebook.buck.rules.SourcePath)10 DocumentBuilder (javax.xml.parsers.DocumentBuilder)10 DocumentBuilderFactory (javax.xml.parsers.DocumentBuilderFactory)10 XPath (javax.xml.xpath.XPath)10 XPathExpression (javax.xml.xpath.XPathExpression)10 XPathFactory (javax.xml.xpath.XPathFactory)10 Document (org.w3c.dom.Document)10 NodeList (org.w3c.dom.NodeList)10