在项目中为多个目标和平台使用 Swift Package?

101

我有一个包含多个目标的项目,例如iOS应用程序、watchOS应用程序和一些框架。如何将同一个Swift Package分配给所有目标?Xcode只允许我选择一个:

SPM1

如果我再尝试添加 Swift Package 以便将其分配给我的项目中的另一个目标,我会收到错误提示:

SPM2

这该怎么做才是正确的?下面是Swift Package的软件包清单,需要在那边做些什么或者我在Xcode中需要做些不同的事情吗?

import PackageDescription

let package = Package(
    name: "Alamofire",
    platforms: [
        .macOS(.v10_12),
        .iOS(.v10),
        .tvOS(.v10),
        .watchOS(.v3)
    ],
    products: [
        .library(
            name: "Alamofire",
            targets: ["Alamofire"])
    ],
    targets: [
        .target(
            name: "Alamofire",
            path: "Source")
    ],
    swiftLanguageVersions: [.v5]
)

1
我的当前解决方法是将从常见的Swift Package依赖项生成的Xcode项目拖放添加为iOS和macOS顶级项目的子项目。 (...仍在使用Xcode 10)...有关方法的讨论,请参见Vapor服务器和配套iOS应用程序示例 - l --marc l
1
这是苹果犯下的一个巨大疏忽。两年过去了,Swift 包管理器在 Xcode 的默认项目类型——多平台应用中仍然无法启动。 - Steve
6个回答

156

我遇到了同样的问题,只找到了这两个解决方案:

首先,在第一个目标中添加该软件包:

Add package

那么,第一种选择是前往其他目标的“常规”选项卡,在“框架、库和嵌入式内容”中按下“+”,选择包并按“添加”:

Adding package in General tab

另一个选项是构建阶段并在“链接二进制文件与库”中重复类似的方式:

Build Phases

Select package

目前,我只知道这些选项,希望未来苹果能够改进并提供多选功能。


8
我遇到了一个错误:"Swift包产品_被链接为静态库...这将导致库代码的重复。"据我所见,唯一的区别是我的目标之一是扩展程序。 - XmasRights
1
这将在多个目标中复制所有符号。不好。 - user187676
1
我相信第一个选项(常规选项卡)是您应该执行此操作的方式 - 在那里生成的配置与从SPM设置工具中进行初始目标时生成的配置完全相同。 - bplattenburg
2
对我来说,它在Xcode 14.1上不起作用,但在Xcode 14.0上运行良好。 - 2Grey
@ManishGupta,你在没有编辑项目文件的情况下找到它了吗? - BlackM
显示剩余3条评论

6
除了解决方案diego-carrera 提供的外,我还需要重置 Swift 包缓存,以便在框架对话框中所有目标都可以使用该包。

在 Xcode 中:文件 -> Swift 包 -> 重置包缓存。


4

在尝试将新的Numerics软件包添加到我的项目中时,我遇到了同样的问题。该项目包含一个名为CreativeCoding的iOS目标和一个名为mandelbrot的Mac命令行目标。

我按照Xcode的常规方式向第一个目标添加了该软件包。然后我退出了Xcode并在编辑器(当然是vi)中打开了project.pbxproj文件。 然后,我找到了我的CreativeCoding目标,从packageProductDependencies容器中复制了包含新的Numerics软件包(Numerics、ComplexModule、RealModule)的3行,并将它们粘贴到我的mandelbrot命令行目标的packageProductDependencies容器中。

/* Begin PBXNativeTarget section */
            8B083F4B24F0B40000A225C8 /* CreativeCoding */ = {
                    isa = PBXNativeTarget;
                    buildConfigurationList = 8B083F6024F0B40200A225C8 /* Build configuration list for PBXNativeTarget "CreativeCoding" */;
                    buildPhases = (
                            8B083F4824F0B40000A225C8 /* Sources */,
                            8B083F4924F0B40000A225C8 /* Frameworks */,
                            8B083F4A24F0B40000A225C8 /* Resources */,
                    );
                    buildRules = (
                    );
                    dependencies = (
                    );
                    name = CreativeCoding;
                    packageProductDependencies = (
                            8B22BD29263E328B00867530 /* ComplexModule */,
                            8B22BD2B263E328B00867530 /* RealModule */,
                            8B22BD2D263E328B00867530 /* Numerics */,
                    );
                    productName = CreativeCoding;
                    productReference = 8B083F4C24F0B40000A225C8 /* CreativeCoding.app */;
                    productType = "com.apple.product-type.application";
            };
            8BE83F4F26213D1C00663AC9 /* mandelbrot */ = {
                    isa = PBXNativeTarget;
                    buildConfigurationList = 8BE83F5626213D1D00663AC9 /* Build configuration list for PBXNativeTarget "mandelbrot" */;
                    buildPhases = (
                            8BE83F4C26213D1C00663AC9 /* Sources */,
                            8BE83F4D26213D1C00663AC9 /* Frameworks */,
                            8BE83F4E26213D1C00663AC9 /* CopyFiles */,
                    );
                    buildRules = (
                    );
                    dependencies = (
                    );
                    name = mandelbrot;
                    packageProductDependencies = (
                            8BB120942622CCB8008EDAB0 /* ArgumentParser */,
                            8B22BD29263E328B00867530 /* ComplexModule */,
                            8B22BD2B263E328B00867530 /* RealModule */,
                            8B22BD2D263E328B00867530 /* Numerics */,
                    );
                    productName = mandlebrot;

如果你已经在第二个目标上安装了ArgumentParser软件包,那么对我来说可能会更容易,因为我只需要将这3行新代码添加到第二个目标上。但你也可以做同样的事情,并向第二个目标添加临时软件包。

然后,我像平常一样进入Xcode并构建了这两个目标,结果成功了。


2
对我来说,问题出在Xcode 14.2版本上。我无法看到想要添加到目标中的框架,但是升级到最新的Xcode 14.3.1解决了这个问题。我成功地看到了我想要添加到第二个目标的Swift Package,并成功地添加了它。
我使用了Diego在https://dev59.com/qlMH5IYBdhLWcg3w6VUv#58079416中提供的答案来添加缺失的框架。

哇,差点就放弃了,谢谢你的提醒。 - Evan Anger
呼,差点放弃了,谢谢你的呼唤。 - undefined

1
如果您在添加依赖项后添加了新目标,则必须从项目中删除依赖项,然后再将其添加回来。否则,库将不会显示在框架选择器中。
很让人恼火的是,Xcode 在使用 Swift 包管理器时唯一可靠的事情就是崩溃。因此,请确保备份项目,因为它可能会处于一种状态,仅打开它就会导致 Xcode 崩溃。

0
使用Xcode 12,您只需选择第二个目标并添加依赖项(Swift Package)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接