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

Max Howell max.howell at apple.com
Thu Mar 3 13:37:45 CST 2016


My feeling here is the module name for an import can be different per module. This requires compiler support.

This package A imports B as C and package D imports B as E but C and E are both still B. The build artifacts are separately named.

> On Mar 2, 2016, at 8:26 AM, orta therox via swift-build-dev <swift-build-dev at swift.org> wrote:
> 
> Also, how would this deal with transitive dependencies?
> 
>  E.g. for the example below, if you included a library that had AFNetworking as a dependency, which would expect it to use the official name inside itself. Would it be able to access the original un-namespaced version of the library which would be separate from the top level namespace’d version? 
> 
> -- 
> 
> [ ·/ ]	    Orta Therox
> 
>> w/ Artsy
>> CocoaPods / CocoaDocs / GIFs.app
>> @orta / orta.github.com
> 
>> On Mar 2, 2016, at 11:09 AM, Kostiantyn Koval via swift-build-dev <swift-build-dev at swift.org> wrote:
>> 
>> This looks good but I have 1 concern
>> With this functionality the users of a package can change the package name given by author, to own custom.
>> 
>> Example:
>> let package = Package(
>>   name: “MyApp”
>>   dependencies: [
>>       .Package(url: "https://github.com/Alamofire/Alamofire", localName: “Network")
>>   ]
>> )
>> 
>> //App.Swift
>> import Network 
>>>> 
>> When reading this code it’s not clear that Network is just name alias for Alamofire without looking at Manifest.swift file.
>> 
>>> On 01 Mar 2016, at 21:44, Joe Groff via swift-build-dev <swift-build-dev at swift.org> wrote:
>>> 
>>> This looks like a great user model. There's an implementation question, however, about what the "ABI" name of a package's module ought to be. Right now, we mangle the module name into all of the symbols exported by that module's library, which would be problematic under this scheme. If you have a dependency diamond where two modules both transitively require the same version of the same third module, but with different names:
>>> 
>>> // module A
>>> dependencies: [
>>>     .Package(url: "https://github.com/erica/SwiftString.git", majorVersion: 1, localName: "SadunString")
>>> ]
>>> // module B
>>> dependencies: [
>>>     .Package(url: "https://github.com/erica/SwiftString.git", majorVersion: 1, localName: "EricaString")
>>> ]
>>> 
>>> then we would want to build and link one libSwiftString.1.dylib (or .a) for both. Using the "home" module name is potentially problematic on systems with flat dynamic linker namespaces (everything except Darwin, AFAIK), since even though we've avoided a source-level clash between competing SwiftStrings, we could still have ABI-level symbol collisions.
>>> 
>>> -Joe
>>> 
>>>>> 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> wrote:
>>>>> 
>>>>> Yup!
>>>>> 
>>>>>  - Daniel
>>>>> 
>>>>>> On Feb 29, 2016, at 8:53 AM, Erica Sadun <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
>>>> 
>>>> Looking forward to feedback, questions, and corrections. -- E
>>>> 
>>>> 
>>>> Disambiguating SPM Naming Conflicts
>>>> Proposal: TBD
>>>> Author(s): Erica Sadun
>>>> Status: TBD
>>>> Review manager: TBD
>>>> 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?" thread.
>>>> 
>>>> 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.
>>>> 
>>>> 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.
>>>> 
>>>> 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",
>>>>                  majorVersion: 1),
>>>>     .Package(url: "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",
>>>>                  majorVersion: 1, localName: "SadunString"), // import SadunString
>>>>     .Package(url: "https://github.com/bob/SwiftString.git",
>>>>                  majorVersion: 1, localName: "BobString"), // import BobString
>>>>     .Package(url: https://github.com/erica/SwiftCollections.git",
>>>>                  majorVersion: 1), // import SwiftCollections
>>>>     ]
>>>> )
>>>> 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.
>>> 
>>> _______________________________________________
>>> 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
> 
> _______________________________________________
> 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-build-dev/attachments/20160303/2840271a/attachment.html>


More information about the swift-build-dev mailing list