You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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"]),
    ]
)

现在碰到两个麻烦:

  1. 我明确想让IndependentTarget完全独立,不依赖任何外部包,但实际在这个Target的Demo.swift里居然能导入并使用SwiftyJSON。
  2. 第一次跑swift build会报错,但之后再运行又正常了。

请问该怎么配置IndependentTarget,才能让它彻底访问不到其他Target的依赖?


解决方案

这其实是Swift Package Manager(SPM)的默认行为搞的鬼——顶级dependencies里声明的包,默认会对所有Target开放可见性,哪怕某个Target没显式声明依赖它。要解决这个问题,我们需要把依赖的可见性严格限制在需要它的Target上,同时清理缓存解决构建的奇怪问题。

1. 给依赖添加私有作用域,限制可见性

修改Package.swiftMultiTargetTest的依赖声明,给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,就能得到干净的构建状态了。

验证效果

修改完成后,你再去IndependentTargetDemo.swift里尝试导入SwiftyJSON,编译器会直接报错提示"No such module 'SwiftyJSON'",这就说明我们的配置生效了——IndependentTarget现在彻底无法访问其他Target的依赖了。

内容的提问来源于stack exchange,提问作者Mukesh

火山引擎 最新活动