我可以编译 swift 代码使得 public 是内部的,反之亦然吗?

Can I compile swift code such that public is internal, and vice versa?

我正在创建一个小型可嵌入 swift 库。我希望这个库既可以作为常规 swiftpm 包使用,也可以作为内部实现细节 copy/pasted 进入另一个库的单个文件。
我想这样做是为了解决“传递依赖”问题——例如给定:

现在有来自 MyApp -> BigLib:v2 -> SmallLib:v1

的传递依赖

但是如果 MyApp 也想引用 SmallLib:v2 怎么办?我们最终会遇到 SmallLib 的 v1 和 v2 都被引用的情况,据我所知,这在 Swift/Xcode/SwiftPM 世界中是做不到的。

我的想法是,如果我的SmallLib可以在BigLib项目里面copy/pasted并且做成internal,那么从MyApp这样的外部代码来看呢将不复存在,不会有冲突。

这让我想到了在 C++ 中我会(ab)使用预处理器并执行如下操作的部分:

#if !defined(SMALLLIB_EMBEDDED)
#define SMALLLIB_PUBLIC public
#else
#define SMALLLIB_PUBLIC internal
#endif

SMALLLIB_PUBLIC protocol SmallProtocol {
   ...
}

在这样的方案下,BigLib 可以定义 SMALLLIB_EMBEDDED 编译器标志,使 SmallLib 的东西成为非 public,一切都会好起来的。

这样的事情在swift可以实现吗?

或者还有其他方法可以解决传递依赖问题吗?

要获得此行为,最好的办法可能是使用 5.3+ 编译器中隐藏的 @_spi 功能。将它添加到语言中的 PR 是 here.

你需要做的是用 @_spi(public) 或你想要的任何标识符标记每个类型和函数,然后那些复制它的人将能够访问它们,只有那些导入你的模块的人 @_spi(public) import SmallLib 并且您应该能够访问所有这些成员。

当然,这是一个没有经过进化的隐藏功能,这意味着它在成为正式版本之前可能至少会发生一些变化。