导入 Swift 包管理器依赖项时出现 'no such module' 错误

Getting 'no such module' error when importing a Swift Package Manager dependency

我是 运行 Xcode 11 Beta 4。 我正在使用 CocoaPods,并希望将我的依赖项之一与 Swift 包管理器一起用作静态库而不是框架。 在使用 Xcode 11 创建的新项目上,可以成功导入依赖项,但在我现有的 CocoaPods 工作区上,却没有。

我认为这可能相关,但我也在 Xcode 中收到此 link 警告:

directory not found for option '-L/Users/username/Library/Developer/Xcode/DerivedData/App-axanznliwntexmdfdskitsxlfypz/Build/Products/Release-iphoneos

报警后我去查看目录是否存在,确实存在。 除了 CocoaPods 的存在之外,我在新创建的项目和我的旧项目之间找不到任何有意义的区别。

不胜感激。

事实证明,Swift 包管理器隐式依赖于项目的配置名称。我把它们放在 live/qa 而不是 Release/Debug,将它们改回去解决了这个问题。很奇怪,但我希望它能为你省去一些麻烦,亲爱的 reader。

在解决这个问题整整一周之后,我开发了一个使用方案和预操作的解决方法。

我有一个名为 "Beta" 的配置,所以 Xcode 无法编译 SPM 依赖项。我意识到 Xcode 将 SPM 依赖项编译为 Swift 模块并将文件添加到 DeriverData 的 Build/Products/Release-iphoneos 文件夹中。

所以我在 Xcode 中创建了一个方案,并在构建预操作中添加了这个 运行 脚本:

cp -f -R "${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/" "${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/"

此脚本 运行 在构建过程之前,将 Xcode 默认生成的文件和模块复制到 Release-iphoneos 文件夹到配置文件夹,Beta-iphoneos,就我而言。

将 Release-iphoneos 中的内容复制到您的 $configuration$-iphoneos 文件夹后 Xcode 应该可以正确编译、构建和 运行 您的项目。

根据@AlexandreMorgado 的回答,似乎最好在编译源代码之前的构建阶段运行 此脚本。然后存档的时候就可以了

if [ -d "${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/" ] && [ "${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/" != "${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/" ] 
then
  cp -f -R "${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/" "${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/"
fi

为了保持增量构建工作,我必须像这样指定 "Fix SPM" 构建阶段的输出文件:

清除派生数据解决了我的问题。我有 Microsoft Azure Devops CI 管道,要清除派生数据我必须编辑 Xcode 构建任务并在“操作”字段中添加此命令:clean.

在通过 Swift 包管理器添加库(在我的例子中是 FASwiftUI 之后,我不得不将它添加到

项目设置 -> 常规 -> 我的目标 -> Frameworks, Libraries, and Embedded Content

在导入语句中可见。

我没有为它添加任何脚本。

我刚刚 运行 遇到了类似的问题,发现我的方案引用了旧配置,即不再存在的配置。一旦我将它们更新为正确的配置,构建就成功了。

(我在最初 post 一年多后才发表此评论。可能我 运行 的内容与最初报道的内容完全不同。不过,我花了很多时间花了很长时间来追踪问题,所以我想留下一张纸条,可能会节省其他人的时间。)

对我有用的方法:我删除了 import WebMIDIKit 行并重新添加了它。

我刚刚 运行 从命令行 运行 xcodebuild 遇到了类似的问题。我正在传递 CONFIGURATION_BUILD_DIR=build 但发现它需要是 绝对路径: CONFIGURATION_BUILD_DIR=$(pwd)/build 解决了问题。

解决方案

let package = Package(
    name: "PackageName",
    dependencies: [
       // YOU MUST ADD THE DEPENDENCY BOTH HERE [1] AND BELOW [2]
      .package(url: "https://github.com/mattmaddux/FASwiftUI", from: "1.0.4")
    ],
    targets: [
        .target(
            name: "PackageName",
            /*[2]*/ dependencies: ["FASwiftUI"], // [2] <<<--------- Added here as well
    ]
)

说明

我正在开发一个 Swift 包,它必须向任何导入它的人提供 FontAwesome 图标。

我的 SwiftUI 预览 canvas.

中显示“没有这样的模块 'FASwiftUI'”

我通过将“FASwiftUI”添加到 BOTH 包的依赖项数组 AS WELL AS 目标本身 .

中的依赖项数组

完整Package.swift 文件

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "PackageName",
    platforms: [
        .macOS(.v11),
        .iOS(.v14)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "PackageName",
            targets: ["PackageName"])
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/nalexn/ViewInspector", from: "0.8.1"),
        .package(url: "https://github.com/mattmaddux/FASwiftUI", from: "1.0.4")
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "PackageName",
            dependencies: ["FASwiftUI"], // <<<--------- Added this here
            resources: [
                .process("Assets")
            ]
        ),
        .testTarget(
            name: "PackageNameTests",
            dependencies: ["PackageName", "ViewInspector"])
    ]
)

根据@sliwinski.lukas的回答,在我的例子中,${CONFIGURATION} 正在输出“Release”,所以它只是复制 Release 文件夹本身,这并不好。我只是硬编码了我的配置名称,并翻转了 Release 和 MyConfiguration,它就起作用了。我将以下代码放在“构建阶段”选项卡中的“编译源代码”之前:

cp -f -R "${SYMROOT}/MyConfiguration${EFFECTIVE_PLATFORM_NAME}/" "${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/" || true

同样重要的是,我必须将它添加到使用 SPM 的项目中,而不是在主应用程序中。

我可以更清楚地了解你的困境吗...

我正在开发一个相当大的 iOS 应用程序(6680 个文件),其结果由许多框架和混合包的 podfiles、swift 包、遗留 ObjC 代码(仍然数量超过更新的 Swift 东西)。

每当我们处理 swift 包时,我们都需要将它们包装在框架中,因为当我们的远程 (Jenkins) 构建系统吞噬所有内容以生成二进制文件以进行内部质量检查时,它会简化 podfile 和依赖项解析 &最终,企业和 AppStore 发布。

今天早些时候,我正在处理一个这样的 swift 包装在框架中的包,上面列出的所有问题都让我感到震惊。

在存储、推送可用代码然后将我存储的框架包装器重新应用到 swift 包之后,我使用了不同于打开项目工作区的路径,其中收集了一堆项目和目标。

打开单独的框架包装器似乎已将 XCode (13.3.1) 踢入提交状态,此时,目标设置“框架、库和可嵌入”部分实际上能够显示 swift 包的“Foo”二进制文件。添加它,然后一切都很好。

因此,如果您仍然遇到问题,请尝试通过打开较小的小块来简化问题。或者开始制作这些包装器框架(如果可能的话),这样您就可以在将它们集成到 XC 的盘子上之前实际管理更小的部分。