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

Daniel Dunbar daniel at zuster.org
Fri Jul 8 17:09:27 CDT 2016


On Thu, Jul 7, 2016 at 2:02 PM, Kostiantyn Koval via swift-build-dev <
swift-build-dev at swift.org> wrote:

> Hi
> Thanks for the proposal, looks very nice.
>
> The *Package.swift* manifest files is very string typed already, (package
> name, url, target names, etc) and and think that is ok in our case.
>
> We can make a type for external dependency that would have 2
> properties: package and target.
> That could help expressing a External dependency.
>
> 3. Target(name: "FooLibrary", dependencies: ["FooCore", External(package:
> “SomePackage”, target: "ExternalTarget"])
>

I like this general direction... we would need to outline the exact
semantics (presumably `package` here is required to refer to a package
named in the overall package dependencies).

or
> 2. Target(name: "FooLibrary", dependencies: ["FooCore"],
> externalDependencies: Dependency(package: “SomePackage”, target:
> "ExternalTarget”])
>
> Idea:
> - How about making 2 types of targets in the Package, public and private
>

I'm less in favor of this, I think an attribute of the target is more
appropriate than a separate group. An attribute is more true to the actual
model the objects are defining, and I think in practice this will be more
annoying to the organization of targets than it is helpful. For example,
for many packages the right answer is to have *one* public target which is
the clean stable API you are trying to vend, so it doesn't add much value
to have other categories. For another, for complex packages with many
internal modules, the public/private nature may be driven by the layering
discipline of the project and only tangentially fall into the
public/private categories based on what the developers care to expose. If
you look at SwiftPM's manifest, for example, having two arrays would be
more annoying than helpful if we wanted to expose, say, libc, Basic and
Commands but not any of the others.

 - Daniel


> import PackageDescription
> let package = Package(
>    name: "FooLibrary",
>    targets: [
>        Target(name: "FooLibrary”),
>    privateTargets: [	Target(name: "SampleCLI”)
>    ])
>
> By keeping private and public targets separate it would be easier for
> package author to organise them and don’t mix theirs dependencies, like in
> the example below
>
>        Target(name: "FooLibrary", dependencies: ["FooCore"]), // Error FooCore is private.
>
>
> Thanks
> - Kostiantyn
>
> On 07 Jul 2016, at 20:45, Ankit Agarwal via swift-build-dev <
> swift-build-dev at swift.org> wrote:
>
> Hi,
>
> Thanks for feedback. I agree that specifying external dependencies with
> targets would be great.
> I think the only thing issue is to figure out is how to specify them. Some
> thoughts:
>
> Note: Currently target name has to be unique across all the targets in the
> package (including its dependencies).
>
> 1. Target(name: "FooLibrary", dependencies: ["FooCore", "ExternalTarget"])
>
> pro: This is probably the easiest way to specify the external dependency
> it. It fits perfectly into the current semantics and just needs to be
> implemented for external deps.
> con: No way to know which targets are external dependencies by just
> looking at manifest file. No way to know from which package that dep is
> coming from.
>
> 2. Target(name: "FooLibrary", dependencies: ["FooCore"],
> externalDependencies: ["ExternalTarget"])
>
> pro: Explicitly mentions what all external deps the target relies on.
> con: Doesn't mention which package contains that external dep.
>
> 3. Target(name: "FooLibrary", dependencies: ["FooCore",
> "SomePackage.ExternalTarget"])
>
> pro: Mentions which package + target the external dependency belongs to.
> con: is probably too verbose and stringly typed.
>
> 4. Target(name: "FooLibrary", dependencies: ["FooCore"],
> externalDependencies: [("SomePackage", "ExternalTarget")])
>
> pro: Mentions which package + target the external dependency belongs to.
> con: verbose and stringly typed.
>
> Would love some feedback or another way to better express the external
> deps, will update the proposal then.
>
> Thanks!
>
> On Thu, Jul 7, 2016 at 9:35 PM, Anders Bertelrud <anders at apple.com> wrote:
>
>> Hello Ankit,
>>
>> Thanks a lot for taking the initiative for this!  This looks like a great
>> start.
>>
>> I think what we will eventually want to do is to let package authors
>> express the "role" of each target, which would then allow expression of
>> such things as build-time vs run-time dependencies.  For example, in some
>> cases there may be a dependency on a build tool (that generates code or
>> formats resources in some way) and that affects such things as the platform
>> and architectures for which the target should be built.
>>
>> But that can all be added in the future.  I like the direction
>> represented by this proposal, and I think it represents a good improvement
>> on its own.  I do agree with other comments that it would be a great
>> addition to let dependencies be specified at the target level, not just the
>> package level.  That would be in scope for inclusion in this proposal.
>>
>> Thanks!
>>
>> Anders
>>
>> On 2016-07-07, at 05.26, Ankit Agarwal via swift-build-dev <
>> swift-build-dev at swift.org> wrote:
>>
>> Hi swift packagers,
>>
>> I am proposing access control to package targets.
>>
>> Link:
>> https://github.com/aciidb0mb3r/swift-evolution/blob/swiftpm-module-access-control/proposals/xxxx-swiftpm-target-access-control.md
>>
>> Feedback appreciated!
>>
>> SwiftPM Target Access Control
>>
>>    - Proposal: SE-XXXX
>>    <https://github.com/apple/swift-evolution/blob/master/proposals/xxxx-swiftpm-target-access-control.md>
>>    - Author: Ankit Aggarwal <https://github.com/aciidb0mb3r>
>>    - Status: In Discussion
>>    - Review manager: TBD
>>
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#introduction>
>> Introduction
>>
>> This proposal aims to address two issues:
>>
>>    1.
>>
>>    Control over the targets exposed (and built) when a SwiftPM package
>>    is used as a dependency.
>>    2.
>>
>>    Import (and build) selected targets of a dependency.
>>
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#motivation>
>> Motivation
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#1-control-over-exposed-targets>1.
>> 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
>> package.
>>
>> As a concrete example: Vapor has a target called Development
>> <https://github.com/qutheory/vapor/tree/master/Sources/Development>.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#2-import-selected-targets>2.
>> 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.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#proposed-solution>Proposed
>> Solution
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#1-control-over-exposed-targets-1>1.
>> 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.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#2-import-selected-targets-1>2.
>> 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.
>> }
>>
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#detailed-design>Detailed
>> Design
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#1-control-over-exposed-targets-2>1.
>> 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 importable.
>>
>> 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.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#2-import-selected-targets-2>2.
>> 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: [
>>        .Package(
>>            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.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#impact-on-existing-code>Impact
>> on Existing Code
>>
>> There will be no impact on existing code as these features are additive.
>>
>> <https://github.com/aciidb0mb3r/swift-evolution/tree/swiftpm-module-access-control#alternatives-considered>Alternatives
>> Considered
>> None at this time.
>>
>> --
>> Ankit
>>
>>
>>
>> _______________________________________________
>> swift-build-dev mailing list
>> swift-build-dev at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-build-dev
>>
>>
>>
>
>
> --
> Ankit
>
> _______________________________________________
> swift-build-dev mailing list
> swift-build-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-build-dev
>
>
>
> _______________________________________________
> swift-build-dev mailing list
> swift-build-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-build-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160708/4a4005c8/attachment.html>


More information about the swift-evolution mailing list