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 now not suggest it since XCFrameworks are right here to remain. 🔨


To be able to construct an XCFramework, you need to use Xcode and a course of may be very easy. You simply have to pick out the Framework sort underneath the iOS tab while you create a brand new venture. Be at liberty to call it, add your Swift supply code and that is it.


You possibly can construct this venture utilizing the command line for a number of platforms through the next script.



xcodebuild archive 
  -scheme MySDK 
  -sdk iphoneos 
  -archivePath "construct/ios_devices.xcarchive" 
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES 
  SKIP_INSTALL=NO
  

xcodebuild archive 
  -scheme MySDK 
  -sdk iphonesimulator 
  -archivePath "construct/ios_simulators.xcarchive" 
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES 
  SKIP_INSTALL=NO


xcodebuild archive 
  -sdk macosx MACOSX_DEPLOYMENT_TARGET=11.0 
  -arch x86_64 -arch arm64 
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES 
  -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 possibly can even construct variations for Catalyst and different working techniques, if you perform a little search you may simply work out the required parameters and configuration. Lengthy story quick, it is very simple to create an xcframework output together with all sort of platform slices for particular gadgets. 😊


Now if you wish to use this XCFramework, you may merely drag and drop it to your Xcode venture 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 through SPM. That is how a quite simple configuration file appears to be like like.



import PackageDescription

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


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

Say hey to artifact bundles for Swift PM


All proper, so XCFrameworks cannot be used underneath Linux, however folks like to put in writing command line scripts in Swift and use them for server facet initiatives. In some instances 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 may help, as a result of it makes doable to ship a number of variations of the identical executable binary file. 🤔


Artifact bundles usually are 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 recordsdata for a number of platforms, this manner plugin authors do not must compile these instruments from supply and the plugin execution time could be closely decreased.


There’s a nice weblog submit 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 easy. The proposal itself helps so much to know the fundamental setup, additionally the older binary dependencies proposal incorporates some associated information good job Swift workforce. 👍


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


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



mkdir MyApp
cd $_
swift package deal init --type=executable


swift construct -c launch


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



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 should always create a brand new information.json file underneath the artifactbundle listing with the next contents. This can describe your bundle with the obtainable binary variants, you may 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 underneath the myapp-1.0.0-macos/bin/myapp location, and at last we will make a quite simple command plugin to take advangate of this newly added device.


import PackagePlugin
import Basis

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

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


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


swift package deal plugin --list
# ‘hey’ (plugin ‘HelloCommandin package deal ‘MyPluginExample’)
swift package deal hey
# Good day, world!


That is it, now we have got 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 recordsdata 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 may 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. 😊




Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles