首页 > 解决方案 > Swift 包和`#if canImport(...)`。它是如何工作的?

问题描述

原谅模糊的标题。

我正在尝试构建一个包来帮助我使用第三方云存储 API(例如 Firebase 存储)、添加Combine支持等。这个包与 CloudKit 做同样的事情。一切都编译得很好,但是当我将包模块导入我的一个单独项目时,该模块显然缺少一些公共符号......

具体来说,包裹在#if canImport(FirebaseStorage)条件中的那些。由于 Firebase 还不支持 SwiftPM,这部分包的行为与包项目本身的预期一样;它只是跳过编译整个位。我认为可以导入此模块的客户端项目可以很好地编译它。

旁白:我正在尝试做的事情看起来像是可选依赖项。我不想导入 Firebase 来使用这个包的其他功能。我已经考虑将包拆分为单独的子包,每个子包都取决于我要使用的特定第三方库。反正我可能会这样做。但问题仍然是 Firebase 还不支持 SwiftPM(尽管我听说它们很接近)。

我的问题与此类似。我的客户项目似乎没有看到条件符号,尽管它可以导入Firebase并且FirebaseStorage很好!我的意思是生成的模块头完全丢失了它们,从而阻止了我的客户端项目在我使用它们时进行编译。

在我看来,编译条件永远不会离开包自己的依赖目标范围。是这样吗?还是我错过了一些明显的东西?我一直认为 Swift Packages 只是将 Swift 源文件导入并编译到命名模块中,但现在我认为并非如此。

有没有办法将代码构建到仅当客户端可以导入尚不支持 SwiftPM 的第三方模块时才能编译的 Swift 包?还是条件编译不能那样工作?

编辑:这是关于条件编译的 Swift 文档,供参考。

标签: swiftconditional-compilationswift-package-manager

解决方案


(2020年4月经验回答)

看起来我只是误解了编译顺序。

导入我的打包模块(我们称之为CloudStorage)在客户端项目中声明了对该模块的依赖关系。在客户端项目可以使用它的其他依赖CloudStorage项进行编译之前,需要在没有主项目的依赖项的情况下进行编译。由于CloudStorage对这些依赖项一无所知,因此canImport这些依赖项的计算结果为 false。

这可能在更高版本的 Swift 中发生了变化。我还没有再试一次。


推荐阅读