Tuesday, May 5, 2026
HomeiOS DevelopmentThe Swift package deal manifest file

The Swift package deal manifest file

[ad_1]

This text is an entire Swift Package deal Supervisor cheatsheet for the package deal manifest file, utilizing the most recent Swift 5.2 instruments model.

Swift


If you wish to study easy methods to use the Swift Package deal Supervisor it is best to learn my different article, as a result of that’s extra like an introduction for individuals who have by no means labored with SPM but.


Package deal sorts

There are a number of package deal sorts that you could create with the swift package deal init command. You may specify the --type flag with the next values: empty, library, executable, system-module, manifest. You too can outline a customized package deal title via the --name flag.

  • The empty package deal will create the default file construction with out the pattern code information.
  • The library kind will create a reusable library product template.
  • The executable kind will create a Swift utility with an executable product definition within the package deal and a major.swift file as a place to begin.
  • The system-module kind will create a wrapper round a system supplied package deal, equivalent to libxml, we’ll discuss this afterward.
  • The manifest kind will solely create a Package deal.swift file with out the rest.





The Package deal manifest file

Each single SPM mission has this particular file inside it known as Package deal.swift. I already wrote a put up about how the package deal supervisor and the Swift toolchain works behind the scenes, this time we will focus solely on the manifest file itself. Let’s get began. 📦

Each single Package deal.swift file begins with a particular remark line the place you must outline the model of the used Swift instruments. The most recent model is sort of totally different from the older ones.



Subsequent you must import the PackageDescription framework to be able to outline your Swift package deal. This framework incorporates the package deal manifest construction as Swift objects.


import PackageDescription

That is it now you might be prepared to explain the package deal itself. Oh by the best way you'll be able to change the model of the used instruments, you'll be able to learn extra about this within the Package deal Supervisor utilization readme.





Package deal

A package deal is only a bunch of Swift (or different) information. The manifest file is the outline of what and easy methods to construct from these sources. Each single package deal ought to have a reputation, however this isn't enought to truly generate one thing from it. You may solely have precisely one package deal definition contained in the file. That is the shortest and most ineffective one that you could create. 🙈


let package deal = Package deal(title: "myPackage")


The package deal title goes for use if you end up importing packages as dependencies, so title your pacages fastidiously. If you happen to select a reserved title by a system framework there could be points with linking. If there is a battle you must use static linking as an alternative of dynamic. If you happen to generate a mission through the swift package deal generate-xcodeproj command that mission will attempt to hyperlink the whole lot dynamically, however should you open the Package deal.swift file utilizing Xcode 11, the dependencies will likely be linked statically if this was not set explicitly within the product definition part.




Platform

A platform is mainly an working system with a given model that you could assist.


let package deal = Package deal(
    title: "myPackage",
    platforms: [
        .iOS(.v13),         
        .macOS(.v10_15),    
        .tvOS(.v13),        
        .watchOS(.v6),      
    ]
)


If you add a platform you might be placing a constraint on it through the required model. Each single dependency ought to match the requirement of the principle package deal platforms. Lengthy story quick if it's worthwhile to add assist for Apple platforms, it is best to specify a platform flag with a supported model, in any other case SPM will use the oldest deployment goal primarily based on the put in SDK, apart from macOS, that is going to be v10_10. Each package deal has Linux assist by default, you'll be able to't add such restrictions but, however possibly this may change within the close to future, additionally Home windows is coming.





Product

A package deal can have a number of ultimate merchandise (construct artifacts). Presently there are two sorts of construct merchandise: executables and libraries. The executable is a binary that may be executed, for instance this is usually a command line utility. A library is one thing that others can use, it's mainly the general public API product illustration in your targets.



import PackageDescription

let package deal = Package deal(title: "myPackage", merchandise: [
    .library(name: "myPackageLib", targets: ["myPackageLib"]),
    .library(title: "myPackageStaticLib", kind: .static, targets: ["myPackageLib"]),
    .library(title: "myPackageDynLib", kind: .dynamic, targets: ["myPackageLib"]),
    .executable(title: "myPackageCli", targets: ["myPackage"])
], targets: [
    .target(name: "myPackageLib"),
    .target(name: "myPackageCli"),
])


If the library kind is unspecified, the Package deal Supervisor will routinely select it primarily based on the shopper's desire. As I discussed this earlier generated Xcode tasks desire dynamic linking, however should you merely open the manifest file the app will likely be statically linked.





Dependency

Packages can depend on different packages. You may outline your dependencies by specifying a neighborhood path or a repository url with a given model tag. Including a dependency into this part shouldn't be sufficient to make use of it in your targets. You even have so as to add the product supplied by the package deal on the goal stage.

let package deal = Package deal(
    title: "myPackage",
    dependencies: [
        .package(path: "/local/path/to/myOtherPackage"),
        .package(url: "<git-repository-url>", from: "1.0.0"),
        .package(url: "<git-repository-url>", .branch("dev")),
        .package(url: "<git-repository-url>", .exact("1.3.2")),
        .package(url: "<git-repository-url>", .revision("<hash>")),
        .package(url: "<git-repository-url>", .upToNextMajor(from: "1.0.0")),
        .package(url: "<git-repository-url>", .upToNextMinor(from: "1.0.0")),
        .package(url: "<git-repository-url>", "1.0.0"..<"1.3.0"),
    ]
)


The url is usually a GitHub url, happily you'll be able to add non-public repositories as properly by utilizing an ssh key primarily based authentication. Simply use the git@github.com:BinaryBirds/viper-kit.git url format, as an alternative of the HTTP primarily based, if you wish to add non-public packages. 🤫




Goal

A goal is one thing that you could construct, in different phrases it is a construct goal that may end up in a library or an executable. It's best to have at the very least one goal in your mission file in any other case you'll be able to't construct something. A goal ought to all the time have a reputation, each different settings is optionally available.


Settings

There are lots of settings that you should use to configure your goal. Targets can depend upon different targets or merchandise outlined in exterior packages. A goal can have a customized location, you'll be able to specify this by setting the trail attribute. Additionally you'll be able to exclude supply information from the goal or explicitly outline the sources you need to use. Targets can have their very own public headers path and you may present construct settings each for the C, C++ and the Swift language, and compiler flags.


.goal(title: "myPackage",
        dependencies: [
            .target(name: "other"),
            .product(name: "package", package: "package-kit")
        ],
        path: "./Sources/myPackage",
        exclude: ["foo.swift"],
        sources: ["main.swift"],
        publicHeadersPath: "./Sources/myPackage/headers",
        cSettings: [
            .define("DEBUG"),
            .define("DEBUG", .when(platforms: [.iOS, .macOS, .tvOS, .watchOS], configuration: .debug)),
            .outline("DEBUG", to: "yes-please", .when(platforms: [.iOS], configuration: .debug)),
            .headerSearchPath(""),
            .headerSearchPath("", .when(platforms: [.android, .linux, .windows], configuration: .launch)),
            .unsafeFlags(["-D EXAMPLE"]),
            .unsafeFlags(["-D EXAMPLE"], .when(platforms: [.iOS], configuration: .debug)),
        ],
        cxxSettings: [
            
        ],
        swiftSettings: [
            .define("DEBUG"),
            .define("DEBUG", .when(platforms: [.iOS, .macOS, .tvOS, .watchOS], configuration: .debug)),
            .unsafeFlags(["-D EXAMPLE"]),
            .unsafeFlags(["-D EXAMPLE"], .when(platforms: [.iOS], configuration: .debug)),
        ],
        linkerSettings: [
            .linkedFramework("framework"),
            .linkedLibrary("framework", .when(platforms: [.iOS], configuration: .debug)),
            .linkedLibrary("library"),
            .linkedLibrary("library", .when(platforms: [.macOS], configuration: .launch)),
            .unsafeFlags(["-L example"]),
            .unsafeFlags(["-L example"], .when(platforms: [.linux], configuration: .launch)),
        ]),

As you'll be able to see you'll be able to outline preprocessor macros for each single language. You should use the protected instances for fundamental stuff, however there's an unsafeFlags case for the reckless ones. The good factor is that you could assist a platform situation filter together with construct configuration to each single settings because the final param.

Accessible platforms are: .iOS, .macOS, .watchOS, .tvOS, .android, .linux, .home windows
The construct configuration could be .debug or .launch


Take a look at targets

Take a look at targets are used to outline take a look at suites. They can be utilized to unit take a look at different targets utilizing the XCTest framework. They appear to be precisely the identical as common targets.


.testTarget(title: String,
    dependencies: [Target.Dependency],
    path: String?,
    exclude: [String],
    sources: [String]?,
    cSettings: [CSetting]?,
    cxxSettings: [CXXSetting]?,
    swiftSettings: [SwiftSetting]?,
    linkerSettings: [LinkerSetting]?)


I believe the one distinction between a goal and a take a look at goal is that you could run a take a look at goal utilizing the swift take a look at command, however from a structural perspective, they're mainly the identical.




Package deal configs and system libraries

You may wrap an present system library utilizing Swift, the great thing about that is that you should use packages written in C, CPP or different languages. I will present you a fast instance via the superb Kanna(鉋) - XML/HTML parser repository. I am utilizing this software lots, thanks for making it Atsushi Kiwaki. 🙏




#if swift(>=5.2) && !os(Linux)
let pkgConfig: String? = nil
#else
let pkgConfig = "libxml-2.0"
#endif

#if swift(>=5.2)
let suppliers: [SystemPackageProvider] = [
    .apt(["libxml2-dev"])
]
#else
let suppliers: [SystemPackageProvider] = [
    .apt(["libxml2-dev"]),
    .brew(["libxml2"])
]
#endif

let package deal = Package deal(title: "Kanna",
pkgConfig: "",
suppliers: [
  .apt(["libsqlite-dev"]),
  .brew(["sqlite3"])
],
merchandise: [
  .library(name: "Kanna", targets: ["Kanna"])
],
targets: [
.target(name: "myPackage"),
.systemLibrary(name: "libxml2",
               path: "Modules",
               pkgConfig: pkgConfig,
               providers: providers)
])


There's a module definition file on the Modules listing. You will want a module.modulemap file to export a given library, you'll be able to learn extra about Modules on the LLVM web site.


module libxml2 [system] {
    hyperlink "xml2"
    umbrella header "libxml2-kanna.h"
    export *
    module * { export * }
}


You may outline your personal umbrella header and thell the system what to import.





I barely use system libraries, however it is a good reference level. Anyhow, if it's worthwhile to wrap a system library I assume that you will have the required information to make it occur. 😅




Language settings

You too can specify the listing of Swift verisons that the package deal is suitable with. In case you are making a package deal that incorporates C or C++ code you'll be able to inform the compiler to make use of a particular language normal in the course of the construct course of.



swiftLanguageVersions: [.v4, .v4_2, .v5, .version("5.1")],


cLanguageStandard: .c11,


cxxLanguageStandard: .gnucxx11)

You may see all of the at present out there choices within the feedback. I do not know what number of of you utilize these directives, however personally I by no means needed to work with them. I am not writing an excessive amount of code from the C language household these days, however it's nonetheless good that SPM has this selection built-in. 👍



Abstract

The Swift Package deal Supervisor shouldn't be the right software simply but, however it's on a great monitor to turn into the de facto normal by slowly changing CocoaPods and Carthage. There are nonetheless some lacking options which might be necessities for many of the builders. Don't be concerned, SPM will enhance lots within the close to future. For instance the binary dependency and useful resource assist is coming alongside Swift 5.3. You may monitor the package deal evolution course of on the official Swift Evolution dashboard.

You may learn extra in regards to the Package deal Supervisor on the official Swift web site, however it's fairly obsolate. The documentation on Apple's web site can be very outdated, however nonetheless helpful. There's a good readme file on GitHub in regards to the utilization of the Swift Package deal Supervisor, however nothing is up to date continuously. 😢


[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments