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

Kostiantyn Koval konstantin.koval1 at gmail.com
Thu Jul 7 15:02:23 CDT 2016


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"])
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

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 <mailto: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 <mailto: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 <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:
>> 
>> Control over the targets exposed (and built) when a SwiftPM package is used as a dependency.
>> 
>> 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 <mailto:swift-build-dev at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-build-dev <https://lists.swift.org/mailman/listinfo/swift-build-dev>
> 
> 
> 
> 
> -- 
> Ankit
> 
> _______________________________________________
> swift-build-dev mailing list
> swift-build-dev at swift.org <mailto:swift-build-dev at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-build-dev <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/20160707/a24a5172/attachment.html>


More information about the swift-evolution mailing list