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 should use to assemble a FAT binary, however I now not advocate it since XCFrameworks are right here to remain. πŸ”¨


In an effort to construct an XCFramework, you need to use Xcode and a course of could be very easy. You simply have to pick the Framework sort beneath the iOS tab once you create a brand new challenge. Be happy to call it, add your Swift supply code and that is it.


You’ll be able to 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’ll be able to even construct variations for Catalyst and different working techniques, if you perform a little search you’ll be able to simply determine 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 units. 😊


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 comprises the mandatory slices). Alternatively you should 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 seems to be like.

See also  android - My SingleChildScrollView doesn't work on Container what's improper?



import PackageDescription

let package deal = 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 deal with importing the mandatory header information and linking the precise library. The one drawback with this strategy 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 individuals like to write down command line scripts in Swift and use them for server aspect tasks. In some circumstances 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 help, as a result of it makes doable to ship a number of variations of the identical executable binary file. πŸ€”


Artifact bundles aren’t 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 fashion plugin authors do not should compile these instruments from supply and the plugin execution time might 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 main points this time, as a result of it is fairly simple. The proposal itself helps rather a lot to grasp the fundamental setup, additionally the older binary dependencies proposal comprises some associated information good job Swift staff. πŸ‘

See also  c++ - ReactNative iOS sendEventWithName trigger "RCTCallableJSModules shouldn't be set"


I might like to offer an honorable point out to Karim Alweheshy, who’s actively working with the brand new Swift package deal supervisor plugin infrastructure, he has an wonderful repository on GitHub that demos artifact bundles so please have a look you probably have time. πŸ™


Anyway, I will 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 afterward.



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 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 at last we’ll make a quite simple command plugin to take advangate of this newly added instrument.


import PackagePlugin
import Basis

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

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


See also  ios - Undefined Symbols Utilizing Structure z86_64 XCode (AppDelegate.h file)

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


swift package deal plugin --list
# β€˜hi there’ (plugin β€˜HelloCommand’ in package deal β€˜MyPluginExample’)
swift package deal hi there
# Hey, world!


That is it, now we have got a working artifact bundle with a customized made executable obtainable for macOS. We are able to use this artifact bundle as a dependency for a plugin and run the instrument by utilizing 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 less difficult. 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 in a similar way. 😊




Leave a Reply