如何使用Swift包管理器包含C代码(在我的例子中,单个.c
文件和头文件),无需要求用户将我的C库安装到/usr/local/lib
?
我原本想在我的主包的子目录中创建一个包含头+ lib的子包,并使用相对路径,最后用swift build -Xlinker ./relative/path/to/mylib
构建,但是我没有成功解决依赖关系它应该是一个独立的git存储库。错误信息是:
error: failed to clone; fatal: repository '/absolute/path/to/mylib' does not exist
此外,我不清楚使用-Xlinker
标志是否是正确的方法。
我不能使用带有纯SwiftPM方法的桥接头,并且在系统范围内安装我的库似乎有点矫枉过正,也不是非常便携。
有什么想法吗?
答案 0 :(得分:6)
我在github上的this project中完成了这个。它通过将其包装在C中并将其重新暴露给swift来替换@echo off
goto run_tests
:stripquotes
FOR /F "tokens=1,*" %%A IN ('echo.%*') DO set %%~A=%%~B
goto :EOF
:test
call :stripquotes mynewvar %*
echo DEBUG: mynewvar is now %mynewvar%
start "" "%mynewvar%\app.exe" "par am 1" param2 "par am 3"
goto :EOF
:run_tests
set OpenOCD_bin_Path=c:\foo bar\baz
call :test %OpenOCD_bin_Path%
set OpenOCD_bin_Path="c:\foo bar\baz"
call :test %OpenOCD_bin_Path%
。这是一个有趣的练习,可以解决Swift试图限制你进入的问题,因为pthread_once_t
并且pthread_once_t
无法直接使用。
以下是dispatch_once
文件的精简版本:
Package.swift
您可以使用可执行文件轻松替换产品库。主要部分是产品的目标需要包含构建所需的C和Swift目标。
然后在目标部分中,使swift目标将C目标列为依赖项。
您可以在SwiftPM Usage.md here
中详细了解C目标所需的布局 C语言目标与Swift目标类似,但C语言除外
库应包含名为// 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"]),
]
)
的目录以保存公共标头。
要允许Swift目标导入C语言目标,请添加目标 清单文件中的依赖项。 Swift Package Manager会 自动为每个C语言库目标生成一个模块映射 3例:
如果include
存在且include/Foo/Foo.h
是唯一的目录
包含目录,然后Foo
成为伞形标题。
如果include/Foo/Foo.h
存在且include/Foo.h
不包含其他子目录
include
成为保护伞标题。
否则,如果include/Foo.h
目录只包含头文件而不包含其他文件
子目录,它成为伞状目录。
如果出现复杂的include
布局,则可以使用自定义include
在module.modulemap
内提供。如果无法生成,SwiftPM将会出错
一个模块映射,符合上述规则。
对于可执行目标,只允许一个有效的C语言主文件,即它
<{1}}和include
位于同一目标中无效。
唯一重要的一点是,在将C代码编译为兼容模块后,如何在C代码中实际执行main.c
。如果您使用main.cpp
组织,则需要使用#import
,如果使用import/Foo/Foo.h
,则可以使用#include <Foo/Foo.h>
。