Swift Package Manager:如何限制Target跨Target访问依赖
问题:Swift Package中如何限制Target无法访问其他Target的依赖
我有如下Package.swift文件:
import PackageDescription let package = Package( name: "MultiTargetTest", products: [ .executable( name: "MultiTargetTest", targets: ["MultiTargetTest"]), ], dependencies: [ .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0") ], targets: [ .target( name: "MultiTargetTest", dependencies: ["SwiftyJSON", "IndependentTarget"]), .target( name: "IndependentTarget", dependencies: []), .testTarget( name: "MultiTargetTestTests", dependencies: ["MultiTargetTest"]), ] )
现在碰到两个麻烦:
- 我明确想让
IndependentTarget完全独立,不依赖任何外部包,但实际在这个Target的Demo.swift里居然能导入并使用SwiftyJSON。 - 第一次跑
swift build会报错,但之后再运行又正常了。
请问该怎么配置IndependentTarget,才能让它彻底访问不到其他Target的依赖?
解决方案
这其实是Swift Package Manager(SPM)的默认行为搞的鬼——顶级dependencies里声明的包,默认会对所有Target开放可见性,哪怕某个Target没显式声明依赖它。要解决这个问题,我们需要把依赖的可见性严格限制在需要它的Target上,同时清理缓存解决构建的奇怪问题。
1. 给依赖添加私有作用域,限制可见性
修改Package.swift里MultiTargetTest的依赖声明,给SwiftyJSON加上scope: .private,这样它就只会对MultiTargetTest可见,其他Target碰不到:
.target( name: "MultiTargetTest", dependencies: [ // 给SwiftyJSON添加私有作用域,仅当前Target可访问 .product(name: "SwiftyJSON", package: "SwiftyJSON", scope: .private), "IndependentTarget" ]),
2. 清理SPM缓存,解决首次构建报错
第一次构建报错后续正常的问题,大概率是缓存残留导致的状态不一致。执行下面的命令彻底清理缓存:
swift package clean rm -rf .build
之后再重新执行swift build,就能得到干净的构建状态了。
验证效果
修改完成后,你再去IndependentTarget的Demo.swift里尝试导入SwiftyJSON,编译器会直接报错提示"No such module 'SwiftyJSON'",这就说明我们的配置生效了——IndependentTarget现在彻底无法访问其他Target的依赖了。
内容的提问来源于stack exchange,提问作者Mukesh




