[swift-build-dev] Proposal: SwiftPM Target Access Control

Ankit Agarwal ankit at ankit.im
Thu Jul 7 07:26:17 CDT 2016

Hi swift packagers,

I am proposing access control to package targets.


Feedback appreciated!

SwiftPM Target Access Control

   - Proposal: SE-XXXX
   - Author: Ankit Aggarwal <https://github.com/aciidb0mb3r>
   - Status: In Discussion
   - Review manager: TBD


This proposal aims to address two issues:


   Control over the targets exposed (and built) when a SwiftPM package is
   used as a dependency.

   Import (and build) selected targets of a dependency.

Control over exposed targets:

SwiftPM allows multiple targets (or modules) inside a package. Packages
usually contain sample usage or example targets which are useful during
development or testing of the package but are redundant when the package is
used as a dependency. This increases compile time for the user of the

As a concrete example: Vapor has a target called Development
Import selected targets:

Sometimes user of a package is only interested in few targets of a
dependency instead of all the targets. Currently there is no way to state
this in Package.swift and all the targets are implicitly built and exposed
to the user package.

For e.g.: I would like to use the targets libc, POSIX, Basic of SwiftPM but
don't want other targets to be built or exposed in my package.
Control over exposed targets:

I propose that package authors be able mark the targets they don't want to
be exposed as private i.e. the privatetargets will be built when that
package is root package but not when the package is used as a dependency.

To mark a target as private I propose PackageDescription's Target gains a
isPrivate boolean property which defaults to false.
Import selected targets:

I propose that package user be able to specify the targets they want to
import into their package.

To specify the targets to be import I propose to add an optional string
array property targets in PackageDescription's Package.Dependency which
defaults to nil i.e. all targets.

Instead of an optional string array property an enum can also be used:

enum ImportedTargets {
    case allTargets // Import all the targets, default value.
    case targets([String]) // Import only these targets.

Control over exposed targets:

Consider a package with following structure:

├── Package.swift
└── Sources
    ├── FooLibrary
    │   └── Foo.swift
    └── SampleCLI
        └── main.swift

The manifest with private target could look like:

import PackageDescription
let package = Package(
   name: "FooLibrary",
   targets: [
       Target(name: "FooLibrary"),
       Target(name: "SampleCLI", isPrivate: true),

When this package is used as a dependency only FooLibrary is built and is

Targets can have other targets as dependency inside a package. A private target
should only be a dependency to other private targets. For e.g. A manifest
like this should result in a build failure.

import PackageDescription
let package = Package(
   name: "FooLibrary",
   targets: [
       Target(name: "FooCore", isPrivate: true),
       Target(name: "FooLibrary", dependencies: ["FooCore"]), // Error
FooCore is private.
       Target(name: "SampleCLI", dependencies: ["FooCore"], isPrivate:
true), // Not an error because SampleCLI is private.

Error: FooCore is a private target, it cannot be a dependency to the public
target FooLibrary.
Import selected targets:

Consider a dependency with following manifest file:

import PackageDescription
let package = Package(
   name: "FooLibrary",
   targets: [
       Target(name: "Foo"),
       Target(name: "Bar", dependencies: ["Foo"]),
       Target(name: "Baz"),

To get only the Bar target from the above package, following manifest could
be written:

import PackageDescription
let package = Package(
   name: "FooUser",
   dependencies: [
           url: "../FooLibrary",
           majorVersion: 1,
           targets: ["Bar"])

Note: In this case since Bar depends on Foo, Foo will be also be implicitly
built and be available.

Any target mentioned in targets and not present in the package should
result in build failure.
on Existing Code

There will be no impact on existing code as these features are additive.

None at this time.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-build-dev/attachments/20160707/4a0684c1/attachment.html>

More information about the swift-build-dev mailing list