You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Package本地依赖配置异常:测试目标无法识别子包

Swift Package本地依赖链接问题:同一XCWorkspace下多包重构测试与构建错误

问题背景

我正在将现有Swift Package拆分为多个包,把原Parent包(实际为Trenches_Engine)的代码迁移至同一XCWorkspace中的Child包(实际为Math)。将所需代码设为public并在调用处添加import Child后,主目标可正常构建,但运行Parent的测试时出现链接错误:

Undefined symbol: protocol descriptor for Child.SomeProtocol
Undefined symbol: (extension in Child):Child.SomeProtocol.method(param: CoreGraphics.CGFloat) -> CoreGraphics.CGFloat
Undefined symbol: static (extension in Child):Swift.Double.computedProperty.getter : Swift.Double

尝试操作及衍生问题

  • 先将Child目标添加至Parent的构建方案,勾选“Test”和“Run”选项
  • 随后尝试在Parent的Package.swift中为测试目标添加Child依赖:
targets: [
    .target(
        name: "Parent",
        dependencies: [],
        resources: [.process("Resources")]),
    .testTarget(
        name: "ParentTests",
        dependencies: ["Parent"/*, "Child"*/]),  // <-- 注释内为添加的内容
]

此时错误变为:

product 'Child' required by package 'Parent' target 'ParentTests' not found.

尽管项目显示构建成功,但运行测试时弹出提示:

There are no test bundles available to test.
Ensure that all package dependencies have resolved and that there are no missing test bundles in the active scheme or test plan.

我曾尝试将包托管至GitHub,但引发更多问题。现在想简化流程,重点想了解如何在工作区中正确将Child包作为本地依赖链接至Parent包? 此外,构建Parent所属的宿主App时也出现类似错误。

相关代码

Parent包(Trenches_Engine)的Package.swift

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

import PackageDescription

let package = Package(
    name: "Trenches_Engine",
    platforms: [
        .iOS(.v14)
    ],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "Trenches_Engine",
            targets: ["Trenches_Engine"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    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: "Trenches_Engine",
            dependencies: [],
            resources: [.process("Resources")]),
        .testTarget(
            name: "Trenches_EngineTests",
            dependencies: ["Trenches_Engine", "Math"]),
    ]
)

Child包(Math)的Package.swift

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

import PackageDescription

let package = Package(
    name: "Math",
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "Math",
            targets: ["Math"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
    ],
    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: "Math",
            dependencies: []),
        .testTarget(
            name: "MathTests",
            dependencies: ["Math"]),
    ]
)

Math包内未被识别的协议/扩展代码

import CoreGraphics

/// This protocol provides `random` and `random:min:max` methods that return CGFloat.
public protocol CanRandom { }

// TODO: Replace this with new random methods...
public extension CanRandom {
    
    /// This method returns a random CGFloat without any setup parameters.
    ///
    /// - Returns: CGFloat(Float(arc4random()) / 0xFFFFFFFF)
    func random() -> CGFloat { CGFloat(Float(arc4random()) / 0xFFFFFFFF) }
    
    /// This method returns a random CGFloat, within the range defined by parameters.
    ///
    /// - Parameter min: The floor of acceptable range of random numbers.
    /// - Parameter max: The ceiling of acceptable range of random numbers.
    ///
    /// - Returns: random() * (max - min) + min
    func random(min: CGFloat, max: CGFloat) -> CGFloat {
        random() * (max - min) + min
    }
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:55:21