一个 Swift 包,允许你在 Package.swift
文件中定义配置设置——这样工具就可以将所有配置集中在一个地方。
工具开发者使用此依赖项来获取他们的配置设置。
在你的 Package.swift
文件中插入配置的最快方法是将 PackageConfig
添加到你的依赖项中
.package(url: "https://github.com/shibapm/PackageConfig.git", from: "0.13.0")
并将配置添加到你的 Package.swift
文件的底部
例如:
#if canImport(PackageConfig)
import PackageConfig
let config = PackageConfiguration([
"komondor": [
"pre-push": "swift test",
"pre-commit": [
"swift test",
"swift run swiftformat .",
"swift run swiftlint autocorrect --path Sources/",
"git add .",
],
],
"rocket": [
"after": [
"push",
],
],
]).write()
#endif
PackageConfig
还提供了创建你自己的配置类型的可能性
运行这行命令来为你生成 PackageConfigs
目标的空源文件。
swift run package-config
第一次运行时,它应该返回一个错误 error: no target named 'PackageConfigs'
。
现在你可以像这样在 Package.swift
的目标列表中任何位置列出所有需要的包配置。
// PackageConfig parses PackageConfigs target in Package.swift to extract list of dylibs to link when compiling Package.swift with configurations
.target(name: "PackageConfigs", dependencies: [
"ExampleConfig" // some executable configuration definition dylib
])
在 Package.swift
文件的最底部
#if canImport(ExampleConfig) // example config dynamic library
import ExampleConfig
// invoking write is mandatory, otherwise the config won't be written // thanks captain obvious
let exampleConfig = ExampleConfig(value: "example value").write()
#endif
如果多个依赖项使用 PackageConfig
,请务必将它们各自包裹在
#if canImport(SomeLibraryConfig)
import SomeLibraryConfig
let someLibraryConfig = SomeLibraryConfig().write()
#endif
请务必调用 Config
的 write
方法,否则这将无法工作。
然后,为了使用可执行文件,用户需要在与其项目 Package.swift
相同的目录中运行此命令
swift run package-config # compiles PackageConfigs target, expecting to find a dylib in `.build` directory for each of the listed libraries configs
swift run example # runs your library executable
为了演示,假设你的库名为 Example,那么 Package.swift
文件会是这样的:
let package = Package(
name: "Example",
products: [
// notice that product with your library config should be dynamic library in order to produce dylib and allow PackageConfig to link it when building Package.swift
.library(name: "ExampleConfig", type: .dynamic, targets: ["ExampleConfig"]),
//
.executable(name: "example", targets: ["Example"]),
],
dependencies: [
.package(url: "https://github.com/shibapm/PackageConfig.git", from: "0.0.2"),
],
targets: [
.target(name: "ExampleConfig", dependencies: ["PackageConfig"]),
.target(name: "Example", dependencies: ["ExampleConfig"]),
]
)
在你的 ExampleConfig
目标中,按如下方式定义 ExampleConfig
:
import PackageConfig
// it must be public for you to use in your executable target
// also you must conform to `Codable` and `PackageConfig`
public struct ExampleConfig: Codable, PackageConfig {
// here can be whatever you want as long as your config can stay `Codable`
let value: String
// here you must define your config fileName which will be used to write and read it to/from temporary directory
public static var fileName: String { return "example-config.json" }
// public init is also a requirement
public init(value: String) {
self.value = value
}
}
然后,例如在可执行的 Example
目标的 main.swift
文件中,你可以像这样加载你的配置:
import ExampleConfig
do {
let config = try ExampleConfig.load()
print(config)
} catch {
print(error)
}
由于 YourConfig
目标是一个动态库,你务必确保每次使用 PackageConfig
的 read
或 write
方法时都已构建它。当从终端构建时,只需运行 swift build
即可完成此操作。
0.0.1
为 Package.swift
文件暴露一个配置
#if canImport(PackageConfig)
import PackageConfig
let config = PackageConfig([
"danger" : ["disable"],
"linter": ["rules": ["allowSomething"]]
]).write()
#endif
这可能就是所有内容了,所以如果在一两个月内没有什么重大变化,我将在本次发布后发布 v1 版本。
当你调用 YourPackage.load()
时,它将使用 swiftc
编译当前目录下的 Package.swift
文件。
在编译过程中,它将尝试链接在 PackageConfigs
目标中列出的动态库列表。
编译完成后,PackageConfig 将运行,并且当 YourPackage.write()
被调用时,你的包配置 JSON 将被写入临时目录。
之后,它将尝试读取 JSON 并将其解码,如同它是 YourPackage
类型,然后将其提供回你调用 load
方法的位置。
使用 SPM 的 verbose 模式
~/d/p/o/i/s/PackageConfig $ swift build --verbose
并获取第一个沙箱之后的内容。然后我将最后一个参数更改为 -fileno 1
,它就打印了 JSON。
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc --driver-mode=swift -L /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 -lPackageDescription -suppress-warnings -swift-version 4.2 -I /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4_2 -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk /Users/ortatherox/dev/projects/orta/ios/spm/PackageConfig/Package.swift -fileno 1
{"errors": [], "package": {"cLanguageStandard": null, "cxxLanguageStandard": null, "dependencies": [], "name": "PackageConfig", "products": [{"name": "PackageConfig", "product_type": "library", "targets": ["PackageConfig"], "type": null}], "targets": [{"dependencies": [], "exclude": [], "name": "PackageConfig", "path": null, "publicHeadersPath": null, "sources": null, "type": "regular"}, {"dependencies": [{"name": "PackageConfig", "type": "byname"}], "exclude": [], "name": "PackageConfigTests", "path": null, "publicHeadersPath": null, "sources": null, "type": "test"}]}}
我运行以下命令:
swift build; env DEBUG="*" swift run package-config-example
如果你不使用 fish
swift build; DEBUG="*" swift run package-config-example