Thursday, February 23, 2023
HomeiOS DevelopmentIntroduction to SPM artifact bundles

Introduction to SPM artifact bundles

XCFrameworks and SPM

Earlier than the introduction of the brand new format we needed to fiddle with FAT binaries to help 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 not suggest it since XCFrameworks are right here to remain. ????

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

You’ll be able to construct this mission utilizing the command line for a number of platforms through the next script.

xcodebuild archive 
  -scheme MySDK 
  -sdk iphoneos 
  -archivePath "construct/ios_devices.xcarchive" 

xcodebuild archive 
  -scheme MySDK 
  -sdk iphonesimulator 
  -archivePath "construct/ios_simulators.xcarchive" 

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

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’ll be able to even construct variations for Catalyst and different working programs, 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 simple 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 mission and it ought to work with out additional points (if it comprises the mandatory slices). Alternatively you need to use Swift bundle supervisor and create a binary goal an hook up your exterior framework bundle through SPM. That is how a quite simple configuration file appears like.

import PackageDescription

let bundle = Bundle(
    title: "MySDK",
    merchandise: [
        .library(name: "MySDK", targets: ["MySDK"]),
    dependencies: [
    targets: [
        .binaryTarget(name: "MySDK", path: "./MySDK.xcframework")

In your mission you need to use the library product as a normal dependency, and the underlying binary goal will handle 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 good day 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 circumstances these scripts (or plugins), want to name exterior scripts that aren’t put in on the system by default. That is the place artifact bundles can assist, as a result of it makes potential to ship a number of variations of the identical executable binary file. ????

Artifact bundles aren’t a substitute for xcframeworks, however extra like an addition, or enchancment because the proposal title signifies this, for the Swift bundle supervisor plugin structure. They permit us to ship precompiled binary information for a number of platforms, this manner plugin authors do not must compile these instruments from supply and the plugin execution time might be closely diminished.

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

I would like to provide an honorable point out to Karim Alweheshy, who’s actively working with the brand new Swift bundle supervisor plugin infrastructure, he has an wonderful repository on GitHub that demos artifact bundles so please have a look when you’ve got time. ????

Anyway, I’ll present you methods to wrap an executable into an artifact bundle. Presently there is not any solution to wrap libraries into artifact bundles, that is going to be added in a while.

mkdir MyApp
cd $_
swift bundle init --type=executable

swift construct -c launch

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

mkdir MyPluginExample
cd $_
swift bundle init 

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

Now the file construction is prepared, we should always create a brand new data.json file beneath the artifactbundle listing with the next contents. This may describe your bundle with the obtainable binary variants, you’ll be able to check out the proposals for the obtainable 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, arguments: [])
        course of.waitUntilExit()

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

swift bundle plugin --list
# ‘good day’ (plugin ‘HelloCommandin bundle ‘MyPluginExample’)
swift bundle good day
# Hiya, world!

That is it, now we have a working artifact bundle with a customized made executable obtainable for macOS. We will use this artifact bundle as a dependency for a plugin and run the device through the use of the plugin APIs. I would actually love to have the ability to cross compile Swift libraries and executable information in a while, this might make the event / deployment workflow a bit simpler. Anyway, artifact bundles are a pleasant little addition, I actually like the way in which 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 effectively similarly. ????


Most Popular