Home IOS Development Introduction to SPM artifact bundles

Introduction to SPM artifact bundles

Introduction to SPM artifact bundles


Binary targets and fashionable Swift packages

Swift 5.6 launched various new options for the Swift Package deal Supervisor infrastructure. We had been already in a position to outline binary targets, and use xcframeworks as binary goal dependencies for our apps. They work nice in case you are concentrating on Apple platforms, however sadly the xcframework format is just not suitable with Linux distributions, to not point out the Home windows working system.

That is the place artifact bundles might help. In case you are growing apps for a number of platforms now you can create an artifact bundle, place all of the suitable variants into this new construction and SPM can select the precise one primarily based in your structure. 💪

Earlier than we really dive in to our predominant matter, I will shortly present you create an xcframework and ship it as a binary goal by way of SPM.

XCFrameworks and SPM

Earlier than the introduction of the brand new format we needed to fiddle with FAT binaries to assist a number of platforms. I’ve a deep dive article about frameworks and instruments that you need to use to assemble a FAT binary, however I now not suggest it since XCFrameworks are right here to remain. 🔨

With a purpose to construct an XCFramework, it’s a must to use Xcode and a course of could be very easy. You simply have to pick out the Framework sort beneath the iOS tab if you create a brand new challenge. Be at liberty to call it, add your Swift supply code and that is it.

You possibly can construct this challenge utilizing the command line for a number of platforms by way of the next script.

# construct for iOS gadgets
xcodebuild archive 
  -scheme MySDK 
  -sdk iphoneos 
  -archivePath "construct/ios_devices.xcarchive" 
# construct for iOS simulators
xcodebuild archive 
  -scheme MySDK 
  -sdk iphonesimulator 
  -archivePath "construct/ios_simulators.xcarchive" 

# construct for macOS gadgets
xcodebuild archive 
  -sdk macosx MACOSX_DEPLOYMENT_TARGET=11.0 
  -arch x86_64 -arch arm64 
  -scheme "MySDK" 
  -archivePath "construct/macos_devices.xcarchive" SKIP_INSTALL=NO

# mix the slices and create the xcframework file
xcodebuild -create-xcframework 
  -framework construct/ios_devices.xcarchive/Merchandise/Library/Frameworks/MySDK.framework 
  -framework construct/ios_simulators.xcarchive/Merchandise/Library/Frameworks/MySDK.framework 
  -framework construct/macos_devices.xcarchive/Merchandise/Library/Frameworks/MySDK.framework 
  -output MySDK.xcframework

You possibly can even construct variations for Catalyst and different working methods, if you perform a little search you’ll be able to simply work out the required parameters and configuration. Lengthy story quick, it’s extremely straightforward to create an xcframework output together with all type of platform slices for particular gadgets. 😊

Now if you wish to use this XCFramework, you’ll be able to merely drag and drop it to your Xcode challenge and it ought to work with out additional points (if it incorporates the mandatory slices). Alternatively you need to use Swift package deal supervisor and create a binary goal an hook up your exterior framework bundle by way of SPM. That is how a quite simple configuration file appears like.

import PackageDescription

let package deal = Package deal(
    identify: "MySDK",
    merchandise: [
        .library(name: "MySDK", targets: ["MySDK"]),
    dependencies: [
    targets: [
        .binaryTarget(name: "MySDK", path: "./MySDK.xcframework")

In your challenge you need to use the library product as a typical dependency, and the underlying binary goal will deal with importing the mandatory header information and linking the precise library. The one drawback with this method is that it’s macOS (or to be much more exact Apple OS solely).

Say hi there to artifact bundles for Swift PM

All proper, so XCFrameworks cannot be used beneath Linux, however folks like to write down command line scripts in Swift and use them for server aspect initiatives. In some instances these scripts (or plugins), wish to name exterior scripts that aren’t put in on the system by default. That is the place artifact bundles might help, as a result of it makes potential to ship a number of variations of the identical executable binary file. 🤔

Artifact bundles should not a alternative for xcframeworks, however extra like an addition, or enchancment because the proposal title signifies this, for the Swift package deal supervisor plugin structure. They permit us to ship precompiled binary information for a number of platforms, this manner plugin authors do not should compile these instruments from supply and the plugin execution time could be closely decreased.

There’s a nice weblog publish about wrapping the SwiftLint executable in an artifact bundle, so I do not actually need to get into the small print this time, as a result of it is fairly simple. The proposal itself helps loads to grasp the essential setup, additionally the older binary dependencies proposal incorporates some associated information good job Swift staff. 👍

I might like to present an honorable point out to Karim Alweheshy, who’s actively working with the brand new Swift package deal supervisor plugin infrastructure, he has an incredible repository on GitHub that demos artifact bundles so please have a look if in case you have time. 🙏

Anyway, I will present you wrap an executable into an artifact bundle. At present there is no solution to wrap libraries into artifact bundles, that is going to be added afterward.

# create a easy hi there world executable challenge
mkdir MyApp
cd $_
swift package deal init --type=executable

# construct the challenge utilizing launch config
swift construct -c launch

# copy the binary
cp $(swift construct --show-bin-path -c launch)/MyApp ./myapp

# init a brand new instance challenge
mkdir MyPluginExample
cd $_
swift package deal init 

mkdir myapp.artifactbundle
cd $_
mkdir myapp-1.0.0-macos
cd $_
mkdir bin

Now the file construction is prepared, we must always create a brand new information.json file beneath the artifactbundle listing with the next contents. It will describe your bundle with the out there binary variants, you’ll be able to check out the proposals for the out there triplets variations.

    "schemaVersion": "1.0",
    "artifacts": {
        "myapp": {
            "model": "1.0.0",
            "sort": "executable",
            "variants": [
                    "path": "myapp-1.0.0-macos/bin/myapp",
                    "supportedTriples": ["x86_64-apple-macosx", "arm64-apple-macosx"]

Copy the myapp binary beneath the myapp-1.0.0-macos/bin/myapp location, and eventually we will make a quite simple command plugin to take advangate of this newly added device.

import PackagePlugin
import Basis

struct MyDistCommandPlugin: CommandPlugin {
    func performCommand(context: PluginContext, arguments: [String]) throws {
        let myAppTool = strive context.device(named: "myapp")
        let myAppToolURL = URL(fileURLWithPath: myAppTool.path.string)

        let course of = strive Course of.run(myAppToolURL, arguments: [])
        course of.waitUntilExit()

Watch out with the paths and file names, I used lowercase letters for every thing on this instance, I like to recommend to observe this sample if you create your artifact bundle binaries.

swift package deal plugin --list
# ‘hi there’ (plugin ‘HelloCommand’ in package deal ‘MyPluginExample’)
swift package deal hi there
# Whats up, world!

That is it, now we have a working artifact bundle with a customized made executable out there for macOS. We are able to use this artifact bundle as a dependency for a plugin and run the device through the use of the plugin APIs. I might actually love to have the ability to cross compile Swift libraries and executable information afterward, this might make the event / deployment workflow a bit easier. Anyway, artifact bundles are a pleasant little addition, I actually like the best way you’ll be able to ship binaries for a number of platforms and I hope that we’re going to have the ability to share libraries as nicely in a similar way. 😊



Please enter your comment!
Please enter your name here