Package Manager System Library Targets


This a draft proposal for moving features of system library packages to the target level. Feedback appreciated!

Package Manager System Library Targets


This proposal introduces a new type of target “system library target”, which
moves the current system-module packages feature from package to target level.


The package manager currently supports “system-module packages” which are
intended to adapt a system installed dependency to work with the package
manager. However, this feature is only supported on package declarations,
which mean libraries that need it often need to create a separate repository
containing the system package and refer to it as a dependency.

Our original motivation in forcing system packages to be declared as standalone
packages was to encourage the ecosystem to standardize on them, their names,
their repository locations, and their owners. In practice, this effort did not
work out and it only made the package manager harder to use.


Swift N: The tools version this proposal is implemented in.

Proposed solution

We propose adding a new “system library target”, which would supply the same
metadata needed to adapt system libraries to work with the package manager, but
as a target. This would allow packages to embed these targets with the libraries
that need them.

We propose to deprecate the legacy system-module package declaration for
packages that are only compatible with Swift N or later.

Detailed design

We will add a new factory method for system library target:

extension Target {
    public static func systemLibraryTarget(
        name: String,
        path: String? = nil,
        pkgConfig: String? = nil,
        providers: [SystemPackageProvider]? = nil
    ) -> Target
  • This target factory function will only be available if the tools version of
    the manifest is greater than or equal to Swift N.

  • During dependency resolution, the package manager will emit a deprecation
    warning if there is a legacy system-module package in the package graph and
    the tools version of the root package is greater than or equal to Swift N.

  • Currently, the package manage implicitly assumes a dependency on system-module
    packages when they are included as a dependency. In the new model, for
    consistency with the existing target/product model, clients of a system
    package must also specify explicit dependencies from the targets which use the
    system library.

  • System library targets may be exported from a package as products. To do so,
    they must be exported via a library product with exactly one member target
    i.e. the system library target.


For example, an existing package which defines only a system library adaptor
would be described:

// swift-tools-version:N
import PackageDescription

let package = Package(
    name: "CZLib",
    products: [
        .library(name: "CZLib", targets: ["CZLib"]),
    targets: [
            name: "CZLib",
            pkgConfig: "zlib",
            providers: [

A similar package which exported a Swift interface for zlib might look like the
following example, which is not expressible today without using a separate

// swift-tools-version:N
import PackageDescription

let package = Package(
    name: "ZLib",
    products: [
        .library(name: "ZLib", targets: ["ZLib"]),
    targets: [
            name: "ZLib",
            dependencies: ["CZLib"]),
            name: "CZLib")

In this case, the system library is not an exported product, and would not be
available to other packages.

Impact on existing packages


Alternatives considered



In the Detailed design section, I think systemLibraryTarget should be systemLibrary, to match the later examples.


Love this idea! +1

This is great!

This is how it should have been from the beginning.

1 Like

Big +1 to this.

Sorry! :)

im not salty i just want to see this in the PM as soon as possible lol