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 should use to assemble a FAT binary, however I now not advocate it since XCFrameworks are right here to remain. 🔨
With a purpose to construct an XCFramework, you need to use Xcode and a course of could be very easy. You simply have to pick out the Framework kind beneath the iOS tab once 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.
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 programs, if you perform a little search you may simply determine the required parameters and configuration. Lengthy story quick, it’s totally 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 may merely drag and drop it to your Xcode challenge and it ought to work with out additional points (if it accommodates the mandatory slices). Alternatively you should use Swift bundle 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 bundle = Package deal(
title: "MySDK",
merchandise: [
.library(name: "MySDK", targets: ["MySDK"]),
],
dependencies: [
],
targets: [
.binaryTarget(name: "MySDK", path: "./MySDK.xcframework")
]
)
In your challenge you should use the library product as a typical 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 whats up to artifact bundles for Swift PM
All proper, so XCFrameworks cannot be used beneath Linux, however folks like to put in writing command line scripts in Swift and use them for server aspect tasks. 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 may also help, as a result of it makes attainable to ship a number of variations of the identical executable binary file. 🤔
Artifact bundles are usually not 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 should compile these instruments from supply and the plugin execution time may 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 main points this time, as a result of it is fairly easy. The proposal itself helps lots to know the fundamental setup, additionally the older binary dependencies proposal accommodates some associated data good job Swift workforce. 👍
I might like to present 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 if in case you have time. 🙏
Anyway, I will present you tips on how to wrap an executable into an artifact bundle. At present there isn’t any approach to wrap libraries into artifact bundles, that is going to be added afterward.
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 must always create a brand new data.json
file beneath the artifactbundle listing with the next contents. This may describe your bundle with the accessible binary variants, you may check out the proposals for the accessible triplets variations.
{
"schemaVersion": "1.0",
"artifacts": {
"myapp": {
"model": "1.0.0",
"kind": "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 at last we’ll make a quite simple command plugin to take advangate of this newly added device.
import PackagePlugin
import Basis
@most important
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 all the pieces on this instance, I like to recommend to comply with this sample once you create your artifact bundle binaries.
swift bundle plugin --list
# ‘whats up’ (plugin ‘HelloCommand’ in bundle ‘MyPluginExample’)
swift bundle whats up
# Hiya, world!
That is it, now we have a working artifact bundle with a customized made executable accessible 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 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 simpler. Anyway, artifact bundles are a pleasant little addition, I actually like the best way you may ship binaries for a number of platforms and I hope that we’re going to have the ability to share libraries as effectively similarly. 😊