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

2016-07-13 Thread Ankit Agarwal via swift-evolution
On Wed, Jul 13, 2016 at 9:27 PM, Anders Bertelrud  wrote:

> Thanks for taking the initiative for this, Ankit.  It's a very welcome
> improvement.
>
> Comments inline.
>
> On 2016-07-12, at 11.15, Ankit Agarwal via swift-build-dev <
> swift-build-...@swift.org> wrote:
>
> To mark a target as exported/public I propose PackageDescription's Target 
> gains
> a flags property which would be a Set of the following Flag enum declared
> inside Target class:
>
> public enum Flag {
> /// Makes the target public or "exported" for other packages to use.
> case public}
>
> The Flag enum will be flexible in case we need to add more attributes in
> future as opposed to a boolean property to mark the public nature of the
> target.
>
> I would prefer that this be a boolean parameter rather than a generic
> `flags` parameter, since it makes the manifest read more naturally, and,
> importantly, is no less extensible than an enum.  Additional parameters
> with default values can as easily be added as more enum cases can, and in
> either case, a manifest written to assume the existence of `public` will be
> equally incompatible with older versions of the package manager.
>
> So, for example:
>
> let package = Package(
>name: "FooLibrary",
>targets: [
>Target(name: "FooLibrary", public: true),
>Target(name: "SampleCLI", dependencies: ["FooLibrary"]),
>])
>
> We can keep some obvious defaults for targets which can be implicitly
> public for e.g.
>
>1. Package has only one target.
>2. Target with same name as package.
>
> I'm a bit wary of magic here.  I think it would be clearer to have the
> manifest declare what is public and what is not.  With magic naming
> conventions it's too easy to accidentally change semantics just by renaming
> a target.
>

I agree that we should avoid too much magic, I think you missed the
sentence below those examples in the proposal where I mentioned that we
should avoid those instead. However as Daniel mentioned we don't want to
overcomplicate the manifest for simple packages and for beginners, keeping
that in mind we updated the proposed solution which you can find on the
proposal link (
https://github.com/aciidb0mb3r/swift-evolution/blob/swiftpm-module-access-control/proposals/-swiftpm-target-access-control.md
)


> I propose that enum Target.Dependency gains a new case External(package:
> String, target: String) to declare dependency on an external package's
> target.
>
> Since it's the same fundamental kind of dependency in either case, would
> it be better to have `package` be an optional parameter to Target?
>
> So that `Target(name: "Foo")` is local but `Target(name: "Foo", package:
> "Bar")` external?  That would seem more logical.
>
>
I like `Target(name: "Foo", package: "Bar")` but I prefer package name is
stated before the target name `Target(package: "Foo", name: "Bar")` but
then this gets weird and `Target(package:target)` is also weird so I chose
`External(package:target)` instead. However if people prefer
`Target(name:package)` more then I am fine with it.

-- 
Ankit
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-07-13 Thread Anders Bertelrud via swift-evolution
Thanks for taking the initiative for this, Ankit.  It's a very welcome 
improvement.

Comments inline.

On 2016-07-12, at 11.15, Ankit Agarwal via swift-build-dev 
 wrote:
> To mark a target as exported/public I propose PackageDescription's Target 
> gains a flags property which would be a Set of the following Flag enum 
> declared inside Target class:
> 
> public enum Flag {
> /// Makes the target public or "exported" for other packages to use.
> case public
> }
> The Flag enum will be flexible in case we need to add more attributes in 
> future as opposed to a boolean property to mark the public nature of the 
> target.
> 
I would prefer that this be a boolean parameter rather than a generic `flags` 
parameter, since it makes the manifest read more naturally, and, importantly, 
is no less extensible than an enum.  Additional parameters with default values 
can as easily be added as more enum cases can, and in either case, a manifest 
written to assume the existence of `public` will be equally incompatible with 
older versions of the package manager.

So, for example:

let package = Package(
   name: "FooLibrary",
   targets: [
   Target(name: "FooLibrary", public: true),
   Target(name: "SampleCLI", dependencies: ["FooLibrary"]),
   ])
> We can keep some obvious defaults for targets which can be implicitly public 
> for e.g. 
> 
> Package has only one target.
> Target with same name as package.
I'm a bit wary of magic here.  I think it would be clearer to have the manifest 
declare what is public and what is not.  With magic naming conventions it's too 
easy to accidentally change semantics just by renaming a target.
> I propose that enum Target.Dependency gains a new case External(package: 
> String, target: String) to declare dependency on an external package's target.
> 
Since it's the same fundamental kind of dependency in either case, would it be 
better to have `package` be an optional parameter to Target?

So that `Target(name: "Foo")` is local but `Target(name: "Foo", package: 
"Bar")` external?  That would seem more logical.

Anders


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-07-13 Thread Daniel Dunbar via swift-evolution

> On Jul 13, 2016, at 1:56 AM, Honza Dvorsky  wrote:
> 
> Very happy to see this proposal, thanks Ankit for pushing it forward! I can't 
> wait to be able to hide many example executables in my packages, as I've been 
> getting a steady stream of complaints from people being annoyed about the 
> polluted compilation log and slower compilation times.
> 
> However I'm leaning towards keeping the default module visibility to public, 
> not private. I appreciate all the arguments that compare targets with code in 
> Swift, where the default is internal - and it makes sense. But the more 
> pragmatic side of me feels that it might become a piece of boilerplate we'll 
> have to write in our manifests for a long time, without much benefit (but 
> with regret). And adding magic to sometimes export by default (single module 
> packages or modules matching the packages name) IMO just complicates the 
> conceptual model of how SwiftPM treats package manifests. I think we should 
> be very careful with adding such nonlinear behaviors (where e.g. adding 
> another module suddenly breaks the package's visible targets), and in this 
> case I don't believe it's justified. (That's while completely ignoring the 
> fact that such a change would break 100% of packages out there, which could 
> be a toll on the good will the project seems to have right now. Not that we 
> should never make breaking changes, I just feel we should give a good reason 
> we're making them, potentially to allow a new feature. Which is not the case 
> here.) 

I agree, this is a big concern of mine as well.

Ankit and I discussed this at length last night and he has updated the proposal 
here:
  
https://github.com/aciidb0mb3r/swift-evolution/blob/swiftpm-module-access-control/proposals/-swiftpm-target-access-control.md
 


> That's my two cents. :)
> 
> Overall I'm enthusiastic about this proposal, it will solve a few real issues 
> I'm having with my projects! 
> 
> While I don't think we should add this to the proposal - it might be very 
> useful to add a mode to SwiftPM that dumps the module visibility information. 
> I think that should be added regardless of what the default visibility ends 
> up being.

I agree. I would like a `swift package describe` which shows how the convention 
system and manifest are causing the package to be interpreted. It would show 
things like the targets, dependencies, etc.

 - Daniel

> Something like:
> $ swift package show-target-visibility
> Found 3 modules
> 
> Public:
> Foo
> 
> Private:
> PrivateBar
> ExampleFoo
> 
> - Honza
> 
> On Tue, Jul 12, 2016 at 8:16 PM Ankit Agarwal via swift-build-dev 
> > wrote:
> I have updated the proposal accommodating recent discussion
> 
> Link: 
> https://github.com/aciidb0mb3r/swift-evolution/blob/swiftpm-module-access-control/proposals/-swiftpm-target-access-control.md
>  
> 
> 
> SwiftPM Target Access Control
> Proposal: SE- 
> 
> Author: Ankit Aggarwal 
> Status: In Discussion
> Review manager: TBD
> Introduction
> This proposal aims to address two issues:
> 
> Control over the targets exposed (and built) when a SwiftPM package is used 
> as a dependency i.e. the targets which are exported and can be used in other 
> packages.
> 
> Specify external target dependencies of a target.
> 
> swift-evolution thread 
> 
> Motivation
> 1. Control over exposed targets:
> 
> SwiftPM allows multiple targets (or modules) inside a package. Most of the 
> time package author will want to provide one (or more) stable public/exported 
> target which should be utilised by other packages. We should actively 
> discourage use of targets which are not meant to be imported by other 
> packages.
> 
> Additionally 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 compilation time for 
> the user of the package which can be avoided.
> 
> As a concrete example: Vapor has a target called Development 
> .
> 
> 2. Specify external target dependencies of a target:
> 
> Currently all the targets of an external dependency are implicitly built and 
> exposed to the user package. This works well for one target package but 
> becomes unclear which targets are using which target of an external 
> dependency.
> 
> Moreover user 

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

2016-07-12 Thread Ankit Agarwal via swift-evolution
I have updated the proposal accommodating recent discussion

Link:
https://github.com/aciidb0mb3r/swift-evolution/blob/swiftpm-module-access-control/proposals/-swiftpm-target-access-control.md

SwiftPM Target Access Control

   - Proposal: SE-
   

   - Author: Ankit Aggarwal 
   - Status: *In Discussion*
   - Review manager: TBD

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 i.e. the targets which are exported and can be used in
   other packages.
   2.

   Specify external target dependencies of a target.

swift-evolution thread

Motivation1. Control over exposed targets:

SwiftPM allows multiple targets (or modules) inside a package. Most of the
time package author will want to provide one (or more) stable
public/exported target which should be utilised by other packages. We
should actively discourage use of targets which are not meant to be
imported by other packages.

Additionally 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 compilation time
for the user of the package which can be avoided.

As a concrete example: Vapor has a target called Development
.
2. Specify external target dependencies of a target:

Currently all the targets of an external dependency are implicitly built
and exposed to the user package. This works well for one target package but
becomes unclear which targets are using which target of an external
dependency.

Moreover user of a package may only be interested in few targets of a
dependency instead of all the exposed targets. Currently there is no way to
state this in Package.swift.

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

I propose that all targets should by default be private/unexported. Authors
should explicitly mark the targets they want to expose as exported/public.

To mark a target as exported/public I propose PackageDescription's Target gains
a flags property which would be a Set of the following Flag enum declared
inside Target class:

public enum Flag {
/// Makes the target public or "exported" for other packages to use.
case public}

The Flag enum will be flexible in case we need to add more attributes in
future as opposed to a boolean property to mark the public nature of the
target.

exported is also a choice instead of public which matches the semantics
here. However public is equally clear in current context.

We can keep some obvious defaults for targets which can be implicitly
public for e.g.

   1. Package has only one target.
   2. Target with same name as package.

Or have all targets be public (the current behaviour) until some target
uses the public flag assuming full control over all the exported target.
This has an advantage that only larger projects which cares about this need
to maintain it.

However I believe private by default and explicit public declaration is the
right way to go here to avoid the misuse of packages/targets which are not
intended to act as a dependency and the public targets will become obvious
(and documented) in the manifest file.

It should be noted that this behaviour cannot be enforced by the compiler
right now and there is no way to stop symbols from other modules from
leaking out. For e.g. there could be a type used in the public interface
which belongs to a private target.

Dependencies of the public targets will also leak and can be imported since
they'll become transitive dependency of some target.

Hopefully we can enforce this using compiler feature in future.

Swift compiler might gain support for package-level namespaces and access
control in future to solve problems like module name collision i.e. two
packages have modules with same name. At that point we will probably need
to rethink the manifest file.
2. Specify external target dependencies of a target:

I propose that enum Target.Dependency gains a new case External(package:
String, target: String) to declare dependency on an external package's
target. The enum would look like this after modification:

/// The description for an individual target or package
dependency.public enum Dependency {
/// A dependency on a target in the same project.
case Target(name: String)
/// A dependency on a target in a external package.
case External(package: String, target: String)}

Note that the package name is not *really* needed (at least currently)
because 

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

2016-07-11 Thread Daniel Dunbar via swift-evolution

> On Jul 11, 2016, at 8:30 AM, Ankit Agarwal via swift-build-dev 
>  wrote:
> 
>  
> 1. One major reason for wanting control over which targets are exported are 
> so packages can control which parts of their API is supported for external 
> use. This is very important to large projects undergoing active development 
> while also trying to support a well-defined, semantically versioned API.
> 
> 2. In keeping with #1, and the design of the Swift language, I think the 
> right default is for a module to be private/unexported. This is basically for 
> the same reasons as `internal` is the default access control modifier in 
> Swift. This also relates to the discussion below.
> 
> I agree keeping things unexported/internal will make sure a certain module is 
> not being used as a dependency when it shouldn't. I also think the default 
> behaviour of a dependency package being exposed to every target should be 
> discontinued with this proposal and each target which wants to use a certain 
> external dependency should require explicit declaration. This will make the 
> manifest file clearer as to which target exactly depends on what.
> However it might break all currently packages (which is probably okay) but it 
> might also get confusing for beginners that why their package is not 
> compiling after declaring the external package. We can probably provide a 
> useful warning when an external package is declared but there is no reference 
> of it in any of the targets.

Ya, there are pros/cons here, probably a good start is to just have the 
proposal articulate each of them and pick the one that looks best after that.

Another choice would be to have some more subtle default (like export single 
module packages by default, or export all root targets (ones with no 
dependents) by default, or export the eponymous target). The latter two seem 
like relatives ok defaults to me, but its much less obvious to have a more 
complex defaulting strategy.

Yet another choice would be to separate the declaration of the public modules 
from any individual target, and keep the default that they be all exported, but 
if a target chooses to explicitly define a list of exported ones, then that 
project adopts full control. This has the advantage that only larger projects 
which care about the distinction need worry about the maintenance of the list.

> 3. If we are going to add this via a new Target attribute, I suggest we do so 
> using a `flags` parameter and accompanying enumeration. This will be equally 
> readable, I think, but more extensible over time. 
> 4. Technically, this proposal is defining two new few features, the 
> public/private exported/imported part and the ability for packages to depend 
> on specific targets. They are related problems, but the proposals (and 
> implementation) are otherwise somewhat orthogonal. I'm fine combining them 
> into one proposal, but if it appears that one part is going to require much 
> more design or discussion than the other (or that the combined discussion is 
> too large) we might consider breaking them up.
> 
> 
> I agree.
>  
> There is a larger thing we need to consider with regard to the public/private 
> part of the proposal, and that is its relation to hypothetical future support 
> for package-level namespaces, whereby I mean Swift language support for a new 
> level of namespace (and accompanying access control support in some form) for 
> an entire Package. There are several reasons I think that we will ultimately 
> need such a thing, the most major of which is the module-name collision 
> problem (two packages that want to use a shared common name for a module) 
> that cannot be resolved by SwiftPM without language support. Since such a 
> feature is purely hypothetical at this point, I don't think we need to block 
> forward progress in SwiftPM on it, but I do think we should discuss the 
> consequences.
> 
> Some examples of how these things might be related:
> 
> 1. The choice of `public/private` is probably wrong when viewed as a language 
> feature, since they already having existing meanings and `internal` would be 
> a more accurate name within the context of an individual Package. I think we 
> should include some discussion of the best names if we reuse modifier names, 
> or if there is a good argument for finding alternate names 
> ("exported/unexported"?).
> 
> if things are going to be private/internal/unexported by default, I think we 
> only need to define the public/exported name. Exported seems like the correct 
> name for this behaviour and is well known however I think public is also 
> equally clear (and simple) here.

I agree picking the public name is somewhat nicer, and could go either way on 
the name.

> 2. Suppose Swift added support for a `package` namespace and access control 
> modifier. This might make it somewhat awkward if we had tied expectations of 
> what targets in an external dependency were built 

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

2016-07-11 Thread Ankit Agarwal via swift-evolution
> 1. One major reason for wanting control over which targets are exported
> are so packages can control which parts of their API is supported for
> external use. This is very important to large projects undergoing active
> development while also trying to support a well-defined, semantically
> versioned API.
>
> 2. In keeping with #1, and the design of the Swift language, I think the
> right default is for a module to be private/unexported. This is basically
> for the same reasons as `internal` is the default access control modifier
> in Swift. This also relates to the discussion below.
>

I agree keeping things unexported/internal will make sure a certain module
is not being used as a dependency when it shouldn't. I also think the
default behaviour of a dependency package being exposed to every target
should be discontinued with this proposal and each target which wants to
use a certain external dependency should require explicit declaration. This
will make the manifest file clearer as to which target exactly depends on
what.
However it might break all currently packages (which is probably okay) but
it might also get confusing for beginners that why their package is not
compiling after declaring the external package. We can probably provide a
useful warning when an external package is declared but there is no
reference of it in any of the targets.


> 3. If we are going to add this via a new Target attribute, I suggest we do
> so using a `flags` parameter and accompanying enumeration. This will be
> equally readable, I think, but more extensible over time.
>
4. Technically, this proposal is defining two new few features, the
> public/private exported/imported part and the ability for packages to
> depend on specific targets. They are related problems, but the proposals
> (and implementation) are otherwise somewhat orthogonal. I'm fine combining
> them into one proposal, but if it appears that one part is going to require
> much more design or discussion than the other (or that the combined
> discussion is too large) we might consider breaking them up.
>
>
I agree.


> There is a larger thing we need to consider with regard to the
> public/private part of the proposal, and that is its relation to
> hypothetical future support for package-level namespaces, whereby I mean
> Swift language support for a new level of namespace (and accompanying
> access control support in some form) for an entire Package. There are
> several reasons I think that we will ultimately need such a thing, the most
> major of which is the module-name collision problem (two packages that want
> to use a shared common name for a module) that cannot be resolved by
> SwiftPM without language support. Since such a feature is purely
> hypothetical at this point, I don't think we need to block forward progress
> in SwiftPM on it, but I do think we should discuss the consequences.
>
> Some examples of how these things might be related:
>
> 1. The choice of `public/private` is probably wrong when viewed as a
> language feature, since they already having existing meanings and
> `internal` would be a more accurate name within the context of an
> individual Package. I think we should include some discussion of the best
> names if we reuse modifier names, or if there is a good argument for
> finding alternate names ("exported/unexported"?).
>

if things are going to be private/internal/unexported by default, I think
we only need to define the public/exported name. Exported seems like the
correct name for this behaviour and is well known however I think public is
also equally clear (and simple) here.


> 2. Suppose Swift added support for a `package` namespace and access
> control modifier. This might make it somewhat awkward if we had tied
> expectations of what targets in an external dependency were built to a
> *manifest*-level construct.
>

If such a feature is added to swift it would probably require to rethink
the manifest file but I agree we should try to minimize the damage if
possible.


>
> 3. We should call out that public/private in this sense ultimately won't
> have any enforcement by the compiler. If a public target exposes a type
> declared in a private module implicitly (say via a return value), there
> won't be any error, even though it breaks the encapsulation this feature
> would partially be intended to provide. Similarly, nothing will prevent a
> target from importing a private module from an external dependency if was
> already a transitive dependency of some other public target.
>

In the current draft proposal I mentioned private target's dependency can
only be another private target for the same reason but I think the approach
of having dependencies providing one (or more) well maintained exported
target makes more sense. True as of now we cannot enforce this and modules
can and will leak out. Maybe we can implement some form of enforcer or
checker using SourceKit in future.

-- 
Ankit

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

2016-07-08 Thread Daniel Dunbar via swift-evolution
Some minor points:

1. One major reason for wanting control over which targets are exported are
so packages can control which parts of their API is supported for external
use. This is very important to large projects undergoing active development
while also trying to support a well-defined, semantically versioned API.

2. In keeping with #1, and the design of the Swift language, I think the
right default is for a module to be private/unexported. This is basically
for the same reasons as `internal` is the default access control modifier
in Swift. This also relates to the discussion below.

3. If we are going to add this via a new Target attribute, I suggest we do
so using a `flags` parameter and accompanying enumeration. This will be
equally readable, I think, but more extensible over time.

4. Technically, this proposal is defining two new few features, the
public/private exported/imported part and the ability for packages to
depend on specific targets. They are related problems, but the proposals
(and implementation) are otherwise somewhat orthogonal. I'm fine combining
them into one proposal, but if it appears that one part is going to require
much more design or discussion than the other (or that the combined
discussion is too large) we might consider breaking them up.

There is a larger thing we need to consider with regard to the
public/private part of the proposal, and that is its relation to
hypothetical future support for package-level namespaces, whereby I mean
Swift language support for a new level of namespace (and accompanying
access control support in some form) for an entire Package. There are
several reasons I think that we will ultimately need such a thing, the most
major of which is the module-name collision problem (two packages that want
to use a shared common name for a module) that cannot be resolved by
SwiftPM without language support. Since such a feature is purely
hypothetical at this point, I don't think we need to block forward progress
in SwiftPM on it, but I do think we should discuss the consequences.

Some examples of how these things might be related:

1. The choice of `public/private` is probably wrong when viewed as a
language feature, since they already having existing meanings and
`internal` would be a more accurate name within the context of an
individual Package. I think we should include some discussion of the best
names if we reuse modifier names, or if there is a good argument for
finding alternate names ("exported/unexported"?).

2. Suppose Swift added support for a `package` namespace and access control
modifier. This might make it somewhat awkward if we had tied expectations
of what targets in an external dependency were built to a *manifest*-level
construct.

3. We should call out that public/private in this sense ultimately won't
have any enforcement by the compiler. If a public target exposes a type
declared in a private module implicitly (say via a return value), there
won't be any error, even though it breaks the encapsulation this feature
would partially be intended to provide. Similarly, nothing will prevent a
target from importing a private module from an external dependency if was
already a transitive dependency of some other public target.

It would be good to try and work through some of these issues and lay out
pros & cons as well as other strategies we could use to mitigate them. In
the short term I think we will need to accept and implement some form of
this proposal, so this doesn't mean working out what a full solution would
look like, let's just make sure we aren't (unknowingly) painting ourselves
into a corner.

 - Daniel


On Thu, Jul 7, 2016 at 6:26 AM, Ankit Agarwal via swift-build-dev <
swift-build-...@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/-swiftpm-target-access-control.md
>
> Feedback appreciated!
>
> SwiftPM Target Access Control
>
>- Proposal: SE-
>
> 
>- Author: Ankit Aggarwal 
>- Status: In Discussion
>- Review manager: TBD
>
>
> 
> 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.
>
>
> 
> Motivation
> 1.
> Control over exposed targets:
>
> SwiftPM allows multiple targets (or modules) inside a package. Packages
> usually contain 

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

2016-07-08 Thread Daniel Dunbar via swift-evolution
On Thu, Jul 7, 2016 at 2:02 PM, Kostiantyn Koval via swift-build-dev <
swift-build-...@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-...@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  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
>> 

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

2016-07-07 Thread Kostiantyn Koval via swift-evolution
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 
>  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  > 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 
>> > 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/-swiftpm-target-access-control.md
>>  
>> 
>> 
>> Feedback appreciated!
>> 
>> SwiftPM Target Access Control
>> 
>> Proposal: SE- 
>> 
>> Author: Ankit Aggarwal 
>> Status: In Discussion
>> Review manager: TBD
>>  
>> 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 

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

2016-07-07 Thread Ankit Agarwal via swift-evolution
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  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-...@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/-swiftpm-target-access-control.md
>
> Feedback appreciated!
>
> SwiftPM Target Access Control
>
>- Proposal: SE-
>
> 
>- Author: Ankit Aggarwal 
>- Status: In Discussion
>- Review manager: TBD
>
>
> 
> 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.
>
>
> 
> Motivation
> 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
> .
>
> 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.
>
> Proposed
> Solution
> 1.
> Control over exposed 

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

2016-07-07 Thread Anders Bertelrud via swift-evolution
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 
>  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/-swiftpm-target-access-control.md
>  
> 
> 
> Feedback appreciated!
> 
> SwiftPM Target Access Control
> 
> Proposal: SE- 
> 
> Author: Ankit Aggarwal 
> Status: In Discussion
> Review manager: TBD
>  
> 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.
> 
>  
> Motivation
> 
>  
> 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 
> .
> 
>  
> 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.
> 
>  
> Proposed
>  Solution
> 
>  
> 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.
> 
>  
> 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.
> }
>  
> Detailed
>  Design
> 
>  
> 1.
>  Control over exposed targets:
> 
> Consider a package with following structure: 
> 
> ├── Package.swift
> └── Sources
> ├── FooLibrary
> │   └── Foo.swift

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

2016-07-07 Thread Daniel Dunbar via swift-evolution
Thanks for writing this up, I definitely want us to figure out how to
handle this problem.

One thing I would like to see addressed alongside this is the ability to
specify the dependency on a SwiftPM target level, since that is usually
where the dependency lies (one target imports another) and not necessarily
at the package level.  What do you think?

 - Daniel

On Thursday, July 7, 2016, Ankit Agarwal via swift-build-dev <
swift-build-...@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/-swiftpm-target-access-control.md
>
> Feedback appreciated!
>
> SwiftPM Target Access Control
>
>- Proposal: SE-
>
> 
>- Author: Ankit Aggarwal 
>- Status: In Discussion
>- Review manager: TBD
>
>
> 
> 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.
>
>
> 
> Motivation
> 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
> .
>
> 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.
>
> Proposed
> Solution
> 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.
>
> 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.
> }
>
>
> Detailed
> Design
> 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: [
>