All Projects → shibapm → Packageconfig

shibapm / Packageconfig

Licence: mit
A Swift Package that allows you to define configuration settings inside a Package.swift

Programming Languages

swift
15916 projects

Labels

Projects that are alternatives of or similar to Packageconfig

BDUIKnit
A Swift Package Manager packed with SwiftUI custom reusable UI components and extensions.
Stars: ✭ 21 (-76.14%)
Mutual labels:  swiftpm
Fiber2d
Cross-platform 2D Game Engine in pure Swift
Stars: ✭ 415 (+371.59%)
Mutual labels:  swiftpm
Sdwebimageswiftui
SwiftUI Image loading and Animation framework powered by SDWebImage
Stars: ✭ 844 (+859.09%)
Mutual labels:  swiftpm
neumorphic-style
🎛 Simple SwiftUI ‘neumorphic’ button style
Stars: ✭ 54 (-38.64%)
Mutual labels:  swiftpm
Keyboardobserving
⌨️A Combine-based way to observe and adjust for Keyboard notifications in SwiftUI
Stars: ✭ 399 (+353.41%)
Mutual labels:  swiftpm
Reflection
DEPRECATED
Stars: ✭ 592 (+572.73%)
Mutual labels:  swiftpm
SwiftUIFormValidator
Declarative form validator for SwiftUI.
Stars: ✭ 34 (-61.36%)
Mutual labels:  swiftpm
Scenekit Scnline
Draw a tube or thick line in SceneKit
Stars: ✭ 49 (-44.32%)
Mutual labels:  swiftpm
Deferred
Work with values that haven't been determined yet.
Stars: ✭ 406 (+361.36%)
Mutual labels:  swiftpm
Imagescout
A Swift implementation of fastimage. Supports PNG, GIF, and JPEG.
Stars: ✭ 940 (+968.18%)
Mutual labels:  swiftpm
Realityui
A Swift Package for creating familiar UI Elements and animations in a RealityKit rendered Augmented Reality or Virtual Reality scene.
Stars: ✭ 275 (+212.5%)
Mutual labels:  swiftpm
Xcglogger
A debug log framework for use in Swift projects. Allows you to log details to the console (and optionally a file), just like you would have with NSLog() or print(), but with additional information, such as the date, function name, filename and line number.
Stars: ✭ 3,710 (+4115.91%)
Mutual labels:  swiftpm
Llvmswift
A Swift wrapper for the LLVM C API (version 9.0.1)
Stars: ✭ 641 (+628.41%)
Mutual labels:  swiftpm
vintage
[UNMAINTED] command-line tool to check for outdated Swift Package Manager dependencies
Stars: ✭ 33 (-62.5%)
Mutual labels:  swiftpm
Rock
With Rock you can easily install CLIs built with Swift Package Manager. Prefer vknabel/Archery and yonaskolb/Mint instead
Stars: ✭ 13 (-85.23%)
Mutual labels:  swiftpm
PackageBuilder
PackageBuilder builds a simple command-line structure by SwiftPM.
Stars: ✭ 27 (-69.32%)
Mutual labels:  swiftpm
Hero
Elegant transition library for iOS & tvOS
Stars: ✭ 20,547 (+23248.86%)
Mutual labels:  swiftpm
Dikit
Dependency Injection Framework for Swift, inspired by KOIN.
Stars: ✭ 77 (-12.5%)
Mutual labels:  swiftpm
Scenekit Bezier Animations
Create animations over Bezier curves of any number of points
Stars: ✭ 35 (-60.23%)
Mutual labels:  swiftpm
Swift Benchmark
A swift library to benchmark code snippets.
Stars: ✭ 659 (+648.86%)
Mutual labels:  swiftpm

PackageConfig

A Swift Package that allows you to define configuration settings inside a Package.swift - this is so that tools can all keep their configs consolidated inside a single place.

Tool builders use this dependency to grab their config settings.

Package Configuration

The fastest way to insert a configuration in your Package.swift is to add PackageConfig to your dependencies

.package(url: "https://github.com/shibapm/PackageConfig.git", from: "0.13.0")

And add the configuration right at the bottom of your Package.swift

e.g.

#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

Custom Configuration Types

PackageConfig offers also the possibility to create your own configuration type

User writes:

Run this line to have empty source for PackageConfigs target generated for you.

swift run package-config

First time it should return an error error: no target named 'PackageConfigs'.

Now you can list all the required package configs anywhere in the list of targets in Package.swift like this.

// 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
])

At the very bottom of the 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
ExampleConfig(value: "example value").write()
#endif

If more than one dependency uses PackageConfig be sure to wrap each in

#if canImport(SomeLibraryConfig)
import SomeLibraryConfig

SomeLibraryConfig().write()
#endif

Be sure to invoke write method of the Config otherwise this won't work.

And then to use executable user would need to run this in the same directory as his/her project 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

Tool-dev writes:

For the sake of example lets assume your library is called Example then Package.swift would look like this:

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"]),
    ]
)

In your ExampleConfig target define ExampleConfig like this.

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
    }
}

Then for example in your main.swift in executable Example target you can load your config like this:

import ExampleConfig

do {
    let config = try ExampleConfig.load()
    print(config)
} catch {
    print(error)
}

Notes for library developers

Since YourConfig target is a dynamic library you must ensure that you have built it everytime when using either read or write methods of PackageConfig. When building from terminal this can be done by just running swift build.


Changelog

  • 0.0.1

    Exposes a config for Package.swift files

    #if canImport(PackageConfig)
    import PackageConfig
    
    let config = PackageConfig([
        "danger" : ["disable"],
        "linter": ["rules": ["allowSomething"]]
    ])
    #endif
    

    This might be everything, so if in a month or two nothing really changes I'll v1 after this release.

How it all works

When you invoke YourPackage.load() it will compile the Package.swift in the current directory using swiftc.

While compiling it will try to link list of dynamic libraries listed in PackageConfigs target.

When it is compiled, PackageConfig will run and when YourPackage.write() is called your package configuration json will be written to temporary directory.

After that it will try to read the json and decode it as if it was YourPackage type, providing it back to where you have invoked load method.

Debugging

How to see the JSON from a Package.swift file

Use SPM with verbose mode:

~/d/p/o/i/s/PackageConfig  $ swift build --verbose

And grab the bit out after the first sandbox. I then changed the final arg to -fileno 1 and it printed the 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"}]}}

How I verify this works

I run this command:

swift build; env DEBUG="*" swift run package-config-example

if you don't use fish:

swift build; DEBUG="*" swift run package-config-example
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].