我如何使用 Swift Pacakge Manager 从 C 语言目标内部 link 到系统模块?
How do I link to a system module from inside a C language target with Swift Pacakge Manager?
我想在 Swift 中实现 Bullet 物理的 C 包装器。基本上我的计划是实现一个 C 语言目标,它包装了我在 bullet 中使用的必要功能,并在我的 swift 代码中依赖于这个 C 目标。问题是,我无法从 C 语言目标中找到项目符号 headers。
我最初的方法是创建 3 个由 Swift 包管理器管理的模块:一个系统模块(项目符号)、一个 C 语言目标(包装器)和一个 Swift 模块(客户端代码)。
我的系统模块是这样的:
Package.swift:
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "Cbullet",
pkgConfig: "bullet",
providers: [
.Brew("bullet")
]
)
module.modulemap:
module ClibBullet [system] {
header "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletCollisionCommon.h"
header "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletDynamicsCommon.h"
link "bullet"
export *
}
另外两个模块属于同一个包:
Package.swift
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
func localModulesPath(_ moduleName: String) -> String {
return "../\(moduleName)"
}
let package = Package(
name: "Physics",
products: [
.library(
name: "Physics",
targets: ["Physics"]),
],
dependencies: [
.package(url: localModulesPath("Cbullet"), .branch("master")),
],
targets: [
.target(
name: "CBulletWrapper",
dependencies: []),
.target(
name: "Physics",
dependencies: ["CBulletWrapper"]),
]
)
在我的 CBulletWrapper.cpp
实现文件中,我尝试像这样包含 Cbullet headers:
#include <Cbullet/btBulletCollisionCommon.h>
#include <Cbullet/btBulletDynamicsCommon.h>
但是我得到一个错误:
"btBulletCollisionCommon.h" file not found
我也试过从它们的显式路径中包含项目符号 headers:
#include "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletDynamicsCommon.h"
但是 btBulletDynamicsCommon.h
中的所有导入都出现 file not found
错误(例如 #include "LinearMath/btVector3.h"
所以问题是,从 Swift Pacakage Manager 构建的 C 语言目标内部 link 到系统库的正确方法是什么?
查看 "Proposed Solution" 下的 Swift Package Manager C Language Target Support Proposal:
- If the include directory includes any file named "module.modulemap", then those will be presumed to define the modules for the target, and no module maps will be synthesized.
我认为你最好的选择是:
在你的C语言目标源文件夹的include文件夹中添加一个module.modulemap文件( CBulletWrapper),其中包括引用系统 (Brew) 提供的库所必需的 header 和 link 语句。可能是这样的:
module CBulletWrapper [system] {
// This is the umbrella header (also in your "include" folder) for your existing wrapper implementation code which itself includes the "bullet" header files
header "CBulletWrapper.h"
//Link to the "bullet" library file in the Brew location (absolute path)
link "/full/path/to/brew/library/libbullet.a"
//Re-Export all included modules to packages that include this "CBulletWrapper" module
export *
}
- 完全忽略现有的外部系统模块 (Cbullet) 依赖项(在 "Physics" 包的 Package.swift 文件中)
注意:据我所知,无法从 "Cbullet" 系统模块包的 Package.swift[=35 中实现 "pkgConfig"、"providers" 声明=] 在您的 "Physics" 模块的 Package.swift 文件中。这个问题似乎在以下提案中得到解决:Package Manager System Library Targets.
我最近用这种方法运气不错。此外,您还节省了维护外部系统模块映射包存储库的额外工作(如果它不与其他项目共享)。如果您稍后需要 link 将额外的外部 C 库添加到主 "Physics" 包中,这将使开发变得更加容易:只需添加另一个 C 语言目标及其自己的 module.modulemap 和 thin/thick 包装器代码。
我想在 Swift 中实现 Bullet 物理的 C 包装器。基本上我的计划是实现一个 C 语言目标,它包装了我在 bullet 中使用的必要功能,并在我的 swift 代码中依赖于这个 C 目标。问题是,我无法从 C 语言目标中找到项目符号 headers。
我最初的方法是创建 3 个由 Swift 包管理器管理的模块:一个系统模块(项目符号)、一个 C 语言目标(包装器)和一个 Swift 模块(客户端代码)。
我的系统模块是这样的:
Package.swift:
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "Cbullet",
pkgConfig: "bullet",
providers: [
.Brew("bullet")
]
)
module.modulemap:
module ClibBullet [system] {
header "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletCollisionCommon.h"
header "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletDynamicsCommon.h"
link "bullet"
export *
}
另外两个模块属于同一个包:
Package.swift
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
func localModulesPath(_ moduleName: String) -> String {
return "../\(moduleName)"
}
let package = Package(
name: "Physics",
products: [
.library(
name: "Physics",
targets: ["Physics"]),
],
dependencies: [
.package(url: localModulesPath("Cbullet"), .branch("master")),
],
targets: [
.target(
name: "CBulletWrapper",
dependencies: []),
.target(
name: "Physics",
dependencies: ["CBulletWrapper"]),
]
)
在我的 CBulletWrapper.cpp
实现文件中,我尝试像这样包含 Cbullet headers:
#include <Cbullet/btBulletCollisionCommon.h>
#include <Cbullet/btBulletDynamicsCommon.h>
但是我得到一个错误:
"btBulletCollisionCommon.h" file not found
我也试过从它们的显式路径中包含项目符号 headers:
#include "/usr/local/Cellar/bullet/2.86.1_1/include/bullet/btBulletDynamicsCommon.h"
但是 btBulletDynamicsCommon.h
中的所有导入都出现 file not found
错误(例如 #include "LinearMath/btVector3.h"
所以问题是,从 Swift Pacakage Manager 构建的 C 语言目标内部 link 到系统库的正确方法是什么?
查看 "Proposed Solution" 下的 Swift Package Manager C Language Target Support Proposal:
- If the include directory includes any file named "module.modulemap", then those will be presumed to define the modules for the target, and no module maps will be synthesized.
我认为你最好的选择是:
在你的C语言目标源文件夹的include文件夹中添加一个module.modulemap文件( CBulletWrapper),其中包括引用系统 (Brew) 提供的库所必需的 header 和 link 语句。可能是这样的:
module CBulletWrapper [system] { // This is the umbrella header (also in your "include" folder) for your existing wrapper implementation code which itself includes the "bullet" header files header "CBulletWrapper.h" //Link to the "bullet" library file in the Brew location (absolute path) link "/full/path/to/brew/library/libbullet.a" //Re-Export all included modules to packages that include this "CBulletWrapper" module export * }
- 完全忽略现有的外部系统模块 (Cbullet) 依赖项(在 "Physics" 包的 Package.swift 文件中)
注意:据我所知,无法从 "Cbullet" 系统模块包的 Package.swift[=35 中实现 "pkgConfig"、"providers" 声明=] 在您的 "Physics" 模块的 Package.swift 文件中。这个问题似乎在以下提案中得到解决:Package Manager System Library Targets.
我最近用这种方法运气不错。此外,您还节省了维护外部系统模块映射包存储库的额外工作(如果它不与其他项目共享)。如果您稍后需要 link 将额外的外部 C 库添加到主 "Physics" 包中,这将使开发变得更加容易:只需添加另一个 C 语言目标及其自己的 module.modulemap 和 thin/thick 包装器代码。