Scipio Documentation
repository·main·Indexed 17 days ago
https://github.com/giginet/scipioA dependency management tool that uses SwiftPM to resolve dependencies and converts them into portable XCFrameworks to improve build caching and portability. It includes a CLI for preparing dependencies and creating frameworks, as well as ScipioKit for implementing custom build pipelines with advanced configurations, remote cache storage (such as Amazon S3), and custom build flags.
What's inside Scipio
- Scipio is a build tool designed to generate XCFrameworks from Swift Packages. It automates the process of transforming Swift Package Manager (SPM) dependencies into binary XCFrameworks, which can be more easily distributed and integrated into various Xcode projects.
How Scipio works: A hybrid dependency workflow
mainScipio provides a hybrid approach to dependency management to solve the problem of difficult-to-cache Xcode build artifacts while maintaining the ease of SwiftPM.
- Resolve: Use SwiftPM to resolve dependencies and check out repositories.
- Convert: Scipio converts each resolved dependency into a portable
XCFramework.
This allows you to use SwiftPM for dependency resolution but benefit from the portability and caching advantages of XCFrameworks.
Configure custom and remote cache storage
mainUnlike the CLI version which is limited to Project or Local disk caches,
ScipioKitallows you to use remote storage (like Amazon S3 viaScipioS3Storage) or implement your own by conforming to theFrameworkCacheStorageprotocol.Cache Actors
When defining a
FrameworkCachePolicy, you can specify which actors are associated with the storage:consumer: An actor that fetches cache from the storage.producer: An actor that attempts to save build artifacts to the storage.
Multiple Cache Policies
You can chain multiple policies. If a framework is not found in the first storage (e.g., S3), Scipio will attempt to fetch it from the next one (e.g.,
.localDisk). If it is not found anywhere, it will be built and then cached in the storages associated with theproduceractor.import ScipioS3Storage // Using S3 with a consumer actor, and falling back to local disk let s3Storage: some FrameworkCacheStorage = ScipioS3Storage.S3Storage(config: ...) let runner = Runner( mode: .prepareDependencies, options: .init( baseBuildOptions: .init( buildConfiguration: .release, isSimulatorSupported: true ), cachePolicies: [ .init(storage: s3Storage, actors: [.consumer]), .localDisk, ] ) )How the Scipio cache system works
mainScipio uses a cache system to reuse valid build artifacts and avoid unnecessary builds. It achieves this by generating a
VersionFilefor every built framework.When Scipio runs, it compares the existing
VersionFilein the output directory against the current build context. If the following parameters match, the binary is considered valid and the build is skipped:- Revision: The revision of the packages (changes if resolved versions are updated).
- Build Options: The configuration used (e.g.,
buildConfiguration,frameworkType,sdks). - Compiler Version: The Xcode or Swift compiler version used for the build.
If a match is found, Scipio skips the build process for that framework.
Implement a custom build pipeline with ScipioKit
mainWhile the Scipio CLI is suitable for simple tasks,
ScipioKitallows you to build complex build pipelines using Swift code. This enables advanced configurations such as passing custom C/Linker/Swift flags, overriding build options per target, using remote cache storage (like Amazon S3), and implementing custom logic or user interfaces.To implement a build script, create an executable Swift package, add
ScipioKitas a dependency, and use theRunnerclass to execute the build process.import Foundation import ScipioKit @main struct EntryPoint { private static let myPackageDirectory = URL(fileURLWithPath: "/path/to/MyPackage") static func main() async throws { let runner = Runner( mode: .prepareDependencies, options: .init( baseBuildOptions: .init( buildConfiguration: .release, isSimulatorSupported: true ) ) ) try await runner.run( packageDirectory: myPackageDirectory, frameworkOutputDir: .default ) } }Advanced Usage of Scipio
mainFor complex build environments, Scipio provides advanced features including:
- Cache System: Managing how dependencies and build artifacts are stored.
- Build Pipeline: Customizing the sequence of build operations.
- S3 Storage: Using Amazon S3 as a remote storage backend for your cache/artifacts.
- Mergeable Library: Handling specific requirements for mergeable library support.
Basic Usage of Scipio
mainThe basic workflow for using Scipio involves three main steps:
- Installation: Setting up the Scipio tool on your machine.
- Prepare Cache: Preparing all necessary dependencies for your application to ensure build reliability.
- Create Frameworks: Executing the generation of XCFrameworks from your Swift Packages.
Convert a single Swift Package to XCFramework using `create`
mainUse the
scipio createcommand to generate XCFrameworks from an existing Swift Package. Unlike thepreparecommand,createdoes not require you to prepare a new package manifest; it works directly with the existing package structure. This is ideal for converting third-party Swift Packages into XCFrameworks for distribution or easier integration.$ scipio create path/to/swift-packageUse ScipioKit as a Swift Package dependency
mainIf you are implementing a custom build pipeline rather than using the CLI, you can integrateScipioKitas a package dependency in your Swift project.Create a mergeable library with Scipio
mainScipio supports the
mergeableframework type, which allows a framework to switch its linking style via build configuration using metadata. This is useful for distributing packages as mergeable libraries as introduced by Apple in WWDC23.Note: Mergeable frameworks typically result in a binary size approximately 2x larger than standard dynamic frameworks.
$ scipio create path/to/MyPackage --framework-type mergeable --enable-library-evolutionBuild Scipio CLI from source
mainIf you prefer to build Scipio from source, clone the repository and use
swift runto build the release version. After building, you should add the resulting binary to yourPATHto use thescipiocommand directly.$ git clone https://github.com/giginet/Scipio.git $ cd Scipio $ swift run -c release scipio --help # Add reference .build/release/scipio to the PATH variable. $ export PATH=/path/to/scipio:$PATHPrepare all dependencies for your application using `prepare` mode
mainScipio's
preparemode allows you to build all dependencies defined in a Swift Package manifest as XCFrameworks. This is useful for pre-building dependencies to speed up build times or to manage binary dependencies in an Xcode project.Workflow
Create a Dependency Package: Create a new Swift Package (ideally in the same directory as your Xcode project) to act as a manifest for your dependencies.
mkdir MyAppDependencies cd MyAppDependencies swift package initConfigure
Package.swift: Edit the manifest to include your required dependencies.- Platforms: You must specify
platforms(e.g.,.iOS(.v14)) because Scipio uses this to determine which SDKs to build for. - Targets: You must depend on all desired products in a single primary target. Declare all other targets as dependencies of this first target.
- Platforms: You must specify
Run Scipio: Execute the
preparecommand pointing to your package directory.scipio prepare path/to/MyAppDependencies
By default, all generated XCFrameworks are placed in
[PackageRoot]/XCFramework.$ scipio prepare path/to/MyAppDependencies