Swift Package Manager在Linux下无源码如何加载Swift动态库.so文件
Swift 完全支持类似 C++ 的「共享库 + 接口文件」调用方案,对应的 Swift 接口文件就是你编译生成的 .swiftmodule,具体实现步骤如下:
1. 修正库项目的 Package.swift 配置
你当前的配置存在两处问题,会影响动态库的生成和调用:
- 动态库需要显式指定
type: .dynamic,否则 SwiftPM 默认会生成静态库 - 产品绑定的 target 名和实际定义的 target 名不匹配,需要统一为
LibraryName
修正后的代码示例:
import PackageDescription let package = Package( name: "LibraryName", products: [ .library( name: "LibraryName", type: .dynamic, targets: ["LibraryName"]), ], targets: [ .target( name: "LibraryName", dependencies: []), ] )
执行 swift build 后就能得到符合要求的动态库产物。
2. 整理库产物到统一目录
建议单独新建目录存放库文件,方便后续主项目引用,示例目录结构:
swift_libs/ ├── lib/ # 存放.so动态库文件 │ └── libLibraryName.so └── modules/ # 存放Swift模块接口文件 ├── LibraryName.swiftdoc ├── LibraryName.swiftsourceinfo └── LibraryName.swiftmodule
3. 配置主项目的 Package.swift
不需要使用 binaryTarget,直接通过 unsafeFlags 传入模块搜索路径和链接参数即可,示例配置:
import PackageDescription let package = Package( name: "你的主项目名", targets: [ .target( name: "你的主项目Target名", swiftSettings: [ // 替换为你本地modules目录的绝对/相对路径,告诉编译器去哪找Swift模块 .unsafeFlags(["-I", "/path/to/swift_libs/modules"]) ], linkerSettings: [ // 替换为你本地lib目录的绝对/相对路径,告诉链接器去哪找.so文件 .unsafeFlags(["-L", "/path/to/swift_libs/lib"]), // 链接对应的动态库,不需要加lib前缀和.so后缀 .linkedLibrary("LibraryName") ] ) ] )
4. 配置运行环境
Linux 系统默认不会加载自定义目录的动态库,运行程序前需要先把库所在路径加入环境变量:
export LD_LIBRARY_PATH=/path/to/swift_libs/lib:$LD_LIBRARY_PATH
如果是在 CLion 中运行,直接在运行配置的「环境变量」栏添加上述变量即可,同时需要在 CLion 的 Swift 编译器配置中加上模块搜索路径,避免 IDE 报找不到 LibraryName 模块的错误。
注意事项
- 你已经了解 ABI 兼容问题,确保库项目和主项目使用完全相同版本的 Swift 编译器编译,否则会出现链接失败或运行时崩溃
- 若需要暴露接口给 C/C++ 调用,可以在库代码中用
@_cdecl标记函数,编译时会自动生成对应的 C 头文件,可实现和 C/C++ 项目的无缝对接
内容的提问来源于stack exchange,提问作者kks21199
相关产品推荐
相关产品推荐

