如何在Swift Package Manager中按OS平台为Target设置不同源文件
Swift Package Manager 跨平台源文件配置方案
针对你需要为Linux和Windows平台设置专属源文件的需求,目前SPM的sources参数本身不支持像linkerSettings那样的.when()语法,但有两种可行的实现方式:
一、通过条件编译动态组装sources数组
直接在Package.swift里利用Swift的平台条件编译指令,动态拼接通用源文件和对应平台的专属源文件列表:
// 先定义跨平台通用的源文件 var myToolSources: [String] = [ "Sources/MyTool/Common/Network.swift", "Sources/MyTool/Common/Utils.swift" ] // 根据当前编译平台添加专属源文件 #if os(Linux) myToolSources.append(contentsOf: [ "Sources/MyTool/Linux/OpenSSLWrappers.swift" ]) #elseif os(Windows) myToolSources.append(contentsOf: [ "Sources/MyTool/Windows/Win32APIs.swift" ]) #endif let package = Package( name: "MyProject", targets: [ .target( name: "MyTool", dependencies: ["Utility"], sources: myToolSources, linkerSettings: [ .linkLibrary("openssl", .when(platforms: [.linux])), ] ), // 其他 target 配置... ] )
这种方式能保持单个target的结构,同时自动根据编译平台筛选源文件。
二、拆分平台专属Target
如果平台差异较大,更推荐把代码拆分成通用核心Target和平台专属Target,结构更清晰:
let package = Package( name: "MyProject", targets: [ // 通用核心Target,只放跨平台代码 .target( name: "MyToolCore", sources: [ "Sources/MyToolCore/CommonLogic.swift", "Sources/MyToolCore/DataModels.swift" ] ), // Linux专属Target,依赖核心Target .target( name: "MyToolLinux", dependencies: ["MyToolCore"], sources: [ "Sources/MyToolLinux/LinuxSpecificImpl.swift" ], linkerSettings: [ .linkLibrary("openssl") ] ), // Windows专属Target,依赖核心Target .target( name: "MyToolWindows", dependencies: ["MyToolCore"], sources: [ "Sources/MyToolWindows/WindowsSpecificImpl.swift" ] ), // 条件选择依赖的平台Target,生成最终可执行文件 #if os(Linux) .executableTarget( name: "MyTool", dependencies: ["MyToolLinux"] ) #elseif os(Windows) .executableTarget( name: "MyTool", dependencies: ["MyToolWindows"] ) #endif ] )
这种方案把平台代码完全隔离,便于维护不同平台的实现细节,也能避免跨平台编译时的冗余代码。
内容的提问来源于stack exchange,提问作者Felix F Xu
相关产品推荐
相关产品推荐

