Swift 包管理器 C-interop:Non-system 个库
Swift Package Manager C-interop: Non-system libraries
我如何使用 Swift 包管理器来包含 C 代码(在我的例子中,一个 .c
文件和一个 header 文件)没有 要求用户将我的 C 库安装到 /usr/local/lib
?
我曾想在包含 header + lib 的主包的子目录中创建一个包,并使用相对路径,最后使用 swift build -Xlinker ./relative/path/to/mylib
构建,但是我没有解决依赖关系的任何成功,因为它应该是一个独立的 git 存储库。错误信息是:
error: failed to clone; fatal: repository '/absolute/path/to/mylib' does not exist
此外,我不清楚使用 -Xlinker
标志是否是正确的方法。
我不能将桥接 header 与纯 SwiftPM 方法一起使用,安装我的库 system-wide 似乎有点过分而且不太便携。
有什么想法吗?
我已经在 github 的 this project 中做到了。它通过将 pthread_once_t
包装在 C 中并将其 re-exposing 替换为 swift 来替换它。这是一个有趣的练习,可以绕过 Swift 试图限制你的东西,因为 pthread_once_t
和 dispatch_once
不能直接使用。
这是 Package.swift
文件的精简版:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Once",
products: [
.library(
name: "Once",
targets: ["OnceC", "Once"]),
],
dependencies: [
],
targets: [
.target(
name: "OnceC",
dependencies: [],
path: "Sources/OnceC"),
.target(
name: "Once",
dependencies: ["OnceC"],
path: "Sources/Swift"),
.testTarget(
name: "OnceTests",
dependencies: ["Once"]),
]
)
您可以轻松地将产品库替换为可执行文件。主要部分是产品的目标需要包含构建所需的 C 和 Swift 目标。
然后在您的目标部分中,使 swift 目标将 C 目标列为依赖项。
您可以在 SwiftPM Usage.md here
中了解有关 C 目标所需布局的更多信息
C 语言目标
C 语言目标类似于 Swift 目标,除了 C 语言
库应该包含一个名为 include
的目录来保存 public headers。
要允许 Swift 目标导入 C 语言目标,请添加一个目标
清单文件中的依赖项。 Swift 包管理器将
为这些的每个 C 语言库目标自动生成模块映射
3 例:
如果include/Foo/Foo.h
存在且Foo
是目录下的唯一目录
包含目录然后 include/Foo/Foo.h
成为保护伞 header.
如果 include/Foo.h
存在且 include
不包含其他子目录,则
include/Foo.h
变伞header.
否则如果include
目录只包含header个文件而没有其他
子目录,它成为伞目录。
如果布局复杂 include
,可以自定义 module.modulemap
include
内提供。 SwiftPM无法生成会报错
a modulemap w.r.t 上面的规则。
对于可执行目标,只允许一个有效的 C 语言主文件,即它
main.c
和 main.cpp
在同一个目标中是无效的。
唯一重要的事情是,一旦 C 代码被编译为兼容模块,您如何实际执行 #import
。如果您使用 import/Foo/Foo.h
组织,则需要使用 #include <Foo/Foo.h>
,如果您使用 import/Foo.h
,则可以使用 #import "Foo.h"
.
我如何使用 Swift 包管理器来包含 C 代码(在我的例子中,一个 .c
文件和一个 header 文件)没有 要求用户将我的 C 库安装到 /usr/local/lib
?
我曾想在包含 header + lib 的主包的子目录中创建一个包,并使用相对路径,最后使用 swift build -Xlinker ./relative/path/to/mylib
构建,但是我没有解决依赖关系的任何成功,因为它应该是一个独立的 git 存储库。错误信息是:
error: failed to clone; fatal: repository '/absolute/path/to/mylib' does not exist
此外,我不清楚使用 -Xlinker
标志是否是正确的方法。
我不能将桥接 header 与纯 SwiftPM 方法一起使用,安装我的库 system-wide 似乎有点过分而且不太便携。
有什么想法吗?
我已经在 github 的 this project 中做到了。它通过将 pthread_once_t
包装在 C 中并将其 re-exposing 替换为 swift 来替换它。这是一个有趣的练习,可以绕过 Swift 试图限制你的东西,因为 pthread_once_t
和 dispatch_once
不能直接使用。
这是 Package.swift
文件的精简版:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Once",
products: [
.library(
name: "Once",
targets: ["OnceC", "Once"]),
],
dependencies: [
],
targets: [
.target(
name: "OnceC",
dependencies: [],
path: "Sources/OnceC"),
.target(
name: "Once",
dependencies: ["OnceC"],
path: "Sources/Swift"),
.testTarget(
name: "OnceTests",
dependencies: ["Once"]),
]
)
您可以轻松地将产品库替换为可执行文件。主要部分是产品的目标需要包含构建所需的 C 和 Swift 目标。
然后在您的目标部分中,使 swift 目标将 C 目标列为依赖项。
您可以在 SwiftPM Usage.md here
中了解有关 C 目标所需布局的更多信息C 语言目标
C 语言目标类似于 Swift 目标,除了 C 语言
库应该包含一个名为 include
的目录来保存 public headers。
要允许 Swift 目标导入 C 语言目标,请添加一个目标 清单文件中的依赖项。 Swift 包管理器将 为这些的每个 C 语言库目标自动生成模块映射 3 例:
如果
include/Foo/Foo.h
存在且Foo
是目录下的唯一目录 包含目录然后include/Foo/Foo.h
成为保护伞 header.如果
include/Foo.h
存在且include
不包含其他子目录,则include/Foo.h
变伞header.否则如果
include
目录只包含header个文件而没有其他 子目录,它成为伞目录。
如果布局复杂 include
,可以自定义 module.modulemap
include
内提供。 SwiftPM无法生成会报错
a modulemap w.r.t 上面的规则。
对于可执行目标,只允许一个有效的 C 语言主文件,即它
main.c
和 main.cpp
在同一个目标中是无效的。
唯一重要的事情是,一旦 C 代码被编译为兼容模块,您如何实际执行 #import
。如果您使用 import/Foo/Foo.h
组织,则需要使用 #include <Foo/Foo.h>
,如果您使用 import/Foo.h
,则可以使用 #import "Foo.h"
.