[swift-build-dev] Namespacing SPM modules (was Re: [swift-dev] Right list?)

Daniel Dunbar daniel_dunbar at apple.com
Thu Mar 3 02:30:47 CST 2016


Thanks for writing this up!

One problem with this proposal as it stands is that it conflates the package name with the module name. The package can contain multiple modules, so "importAs" on the package is ambiguous except for single module packages (and even then, it is weird, because it is naming a module, but in the context where the package is being named).

We eventually need a way for packages to specify what modules they actually export, at which point it would probably be possible to specify this as a rename of the exported module names.

To make this a concrete proposal, I think it would also need to clarify exactly how we would implement the feature. The most straightforward way that I can see would require either SwiftPM specific hacks (which I wouldn't want to see go in), or some level of compiler support. We already need more compiler support for module specification stuff (e.g., to enforce dependencies), so it is possible it could tack on to what we need there, but none of that work has been designed yet.

These two issues bring up a related problem:
 - We have packages, and we have modules, and both have names.
 - Substantial packages may be composed of a significant number of modules, only some of which are exported. For example, "LLVM" could be a package which exported an "LLVM" module (the client API), but internally had things like "Support".
 - The collision likelihood for package-internal module names is quite a bit higher than for packages (because there are likely to be more of them, and because they are implementation details).

One possible direction to take this is that we should gain explicit Swift language support for the concept of package namespaces. It could take the same form as imports, where the package component of the namespace is only required when there are ambiguities.

If we had such a feature, then a package-level rename would probably make complete sense (retaining your current proposal), and we would probably be able to implement it in the package manager (for the most part; I still see problems if a package tree had multiple sources which referred by name to the package being renamed).

 - Daniel

> On Feb 29, 2016, at 10:42 AM, Erica Sadun <erica at ericasadun.com> wrote:
> 
> 
>> On Feb 29, 2016, at 9:59 AM, Daniel Dunbar <daniel_dunbar at apple.com <mailto:daniel_dunbar at apple.com>> wrote:
>> 
>> Yup!
>> 
>>  - Daniel
>> 
>>> On Feb 29, 2016, at 8:53 AM, Erica Sadun <erica at ericasadun.com <mailto:erica at ericasadun.com>> wrote:
>>> 
>>> I'll try writing up a proposal. Does everything work the same for swift-build-dev as -evolution?
>>> 
>>> -- E
> 
> 
> First draft: https://gist.github.com/erica/c6553a5f6f35e7462074 <https://gist.github.com/erica/c6553a5f6f35e7462074>
> 
> Looking forward to feedback, questions, and corrections. -- E
> 
> 
> Disambiguating SPM Naming Conflicts
> 
> Proposal: TBD
> Author(s): Erica Sadun <http://github.com/erica>
> Status: TBD
> Review manager: TBD
>  <https://gist.github.com/erica/c6553a5f6f35e7462074#introduction>Introduction
> 
> I propose to modify Swift's SPM PackageDescription to allow developers to assign local module names to avoid module conflicts. Namespacing supports a decentralized packaging ecosystem that handles the rare case of name overlaps without requiring a central package registry.
> 
> This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in the "Right List? <http://article.gmane.org/gmane.comp.lang.swift.devel/1149>" thread.
> 
>  <https://gist.github.com/erica/c6553a5f6f35e7462074#motivation>Motivation
> 
> Swift offers a built in mechanism for distinguishing symbol conflicts. When working with NSView, I take care to differentiate Swift.print, which outputs text to the console or stream from NSView's  print, which creates a print job. Swift does not yet offer a solution for conflicting module names.
> 
> Like many other Swift developers, I have spent considerable time building utility packages. Mine use obvious names like SwiftString and SwiftCollections. Simple clear naming is a hallmark of Swift design. At the same time, this style introduces the possibility of package name conflicts. 
> 
> import SwiftString // mine
> import SwiftString // someone else's. oops.
> My SwiftString or StringUtility package can't be used alongside someone else's SwiftString or StringUtilitypackage. Moving back to Cocoa-style ESSwiftString namespacing feels ugly and antithetical to Swift design. Swift should encourage recognizable, easy-to-understand module names.
> 
>  <https://gist.github.com/erica/c6553a5f6f35e7462074#original-design>Original Design
> 
> I first considered namespacing using reverse domain naming in Package declarations. This offers a traditional approach to identify a module's source:
> 
> import PackageDescription
> 
> let package = Package(
>     name:   "SwiftString"
>     origin: "org.sadun"
> )
> Reverse domain names
> 
> are relatively short
> are already well established for Apple app distribution
> do not rely on a web address that may change should the repo move
> are less likely to conflict with user names across repo hosts 
> However concise, using reverse domain names bring unnecessary verbiage to name conflicts. Consider the following example.
> 
> import org.sadun.SwiftString
> import com.other.SwiftString
> 
> ...
> 
> // Use my implementation of countSyllables
> let count = org.sadun.SwiftString.countSyllables(myString)
> In this example, org.sadun.SwiftString.countSyllables places a burden both on writing and reading code. Surely there has to be a better solution.
> 
> Adapting import statements resolves symbols but has negative side effects:
> 
> import org.sadun.SwiftString as SadunString
> import com.other.SwiftString as OtherString
> 
> ...
> 
> // Use my implementation of countSyllables
> let count = SadunString.countSyllables(myString)
> This approach requires Swift language modification
> Import redeclarations may be required across multiple files
> Joe Groff suggested a simpler approach: allow package manifests to take responsibility for mapping dependencies to source-level module names.
> 
>  <https://gist.github.com/erica/c6553a5f6f35e7462074#revised-design>Revised Design
> 
> Under the revised solution, renaming occurs when declaring dependencies. This is what package descriptions looks like under the current system:
> 
> import PackageDescription
> let package = Package (
>     name: "myutility",
>     dependencies: [
>     .Package(url: "https://github.com/erica/SwiftString.git <https://github.com/erica/SwiftString.git>",
>                  majorVersion: 1),
>     .Package(url: "https://github.com/bob/SwiftString.git <https://github.com/bob/SwiftString.git>",
>                  majorVersion: 1),
>     ]
> )
> Under this proposal, the Package dependency gains an optional localName parameter. When localName is omitted, a package imports as the name declared in Package.name.
> 
> import PackageDescription
> let package = Package (
>     name: "myutility",
>     dependencies: [
>     .Package(url: "https://github.com/erica/SwiftString.git <https://github.com/erica/SwiftString.git>",
>                  majorVersion: 1, localName: "SadunString"), // import SadunString
>     .Package(url: "https://github.com/bob/SwiftString.git <https://github.com/bob/SwiftString.git>",
>                  majorVersion: 1, localName: "BobString"), // import BobString
>     .Package(url: https://github.com/erica/SwiftCollections.git <https://github.com/erica/SwiftCollections.git>",
>                  majorVersion: 1), // import SwiftCollections
>     ]
> )
>  <https://gist.github.com/erica/c6553a5f6f35e7462074#alternatives-considered>Alternatives Considered
> 
> Swift names should be as simple and elegant as possible without overlapping with built-in keywords. Other suggestions brought up in-discussion included:
> 
> Using GitHub or Bitbucket usernames as namespacing prefixes, e.g. erica.SwiftString. This would not be resilient across cross-repo username conflicts.
> Using repo URLs to resolve namespacing conflicts. This would be fragile if repos moved and does not address local module name resolution.
> Introducing a registration index for packages.
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-build-dev/attachments/20160303/3b0feb89/attachment.html>


More information about the swift-build-dev mailing list