<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 3, 2016, at 1:30 AM, Daniel Dunbar &lt;<a href="mailto:daniel_dunbar@apple.com" class="">daniel_dunbar@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Thanks for writing this up!</div></div></blockquote><div><br class=""></div>No worries. Let's get this fixed. &nbsp;I warn you the following rambles a bit, but there's a point to it by the end.</div><div><br class=""></div><div><b class="">State of the art:</b></div><div>So I have two git repos:&nbsp;<a href="https://github.com/erica/SwiftString.git" class="">https://github.com/erica/SwiftString.git</a>&nbsp;and&nbsp;<a href="https://github.com/nudas/SwiftString.git" class="">https://github.com/nudas/SwiftString.git</a></div><div><br class=""></div><div>My package looks like this:</div><div><br class=""></div><div><div><font face="Menlo" class="">import PackageDescription</font></div><div><font face="Menlo" class="">let package = Package (</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; name: "myutility",</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; dependencies: [</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span> &nbsp; &nbsp;.Package(url: "<a href="https://github.com/erica/SwiftString.git" class="">https://github.com/erica/SwiftString.git</a>",</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; majorVersion: 1),</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span> &nbsp; &nbsp;.Package(url: "<a href="https://github.com/nudas/SwiftString.git" class="">https://github.com/nudas/SwiftString.git</a>",</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space:pre">        </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; majorVersion: 1),</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; ]</font></div><div><font face="Menlo" class=""><br class=""></font></div><div><font face="Menlo" class="">)</font></div><div><br class=""></div><div>and of course, make fails:</div><div><br class=""></div></div><div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">% make</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">swift build</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">Cloning Packages/SwiftString</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">Using version 1.0.5 of package SwiftString</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">Cloning Packages/SwiftString</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #5330e1" class="">/usr/bin/git</span> clone --recursive --depth 10 <a href="https://github.com/nudas/SwiftString.git" class="">https://github.com/nudas/SwiftString.git</a> /home/erica/Work/test/Packages/SwiftString</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(195, 55, 32);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">swift-build: </span>Failed to clone <a href="https://github.com/nudas/SwiftString.git" class="">https://github.com/nudas/SwiftString.git</a> to /home/erica/Work/test/Packages/SwiftString</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">Makefile:3: recipe for target 'all' failed</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">make: *** [all] Error 1</div><div class=""><br class=""></div></div><div>This is my starting point, where I am attempting to import two standalone modules, let alone import a package that contains further</div><div>dependencies.&nbsp;</div><div><br class=""></div><div><div>* There are packages. There are modules. Both have names. Neither is distinguished in dependencies or declaration.</div><div>* Packages may be composed of modules or packages, and keeping track of modules can be problematic.</div><div class=""><br class=""></div></div><div><b class="">Tossing ideas out there:</b></div><div><b class=""><br class=""></b></div><div>Change 1: Let modules be declared differently. Instead of&nbsp;</div><div><b class=""><br class=""></b></div><div><span style="font-family: Menlo;" class="">import PackageDescription</span></div><div><div><font face="Menlo" class=""><br class=""></font></div><div><font face="Menlo" class="">let package = Package(</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; name: &nbsp; "SwiftString",</font></div><div><span style="font-family: Menlo;" class="">)</span></div><div><font face="Menlo" class=""><br class=""></font></div><div><b class=""><font face="Menlo" class=""><br class=""></font></b></div><div>allow:</div><div><b class=""><font face="Menlo" class=""><br class=""></font></b></div><div><span style="font-family: Menlo;" class="">import ModuleDescription</span></div><div><div><font face="Menlo" class=""><br class=""></font></div><div><font face="Menlo" class="">let module = Module(</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; name: &nbsp; "SwiftString",</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; origin: "org.sadun.SwiftString"</font></div><div><font face="Menlo" class="">)</font></div><div class=""><br class=""></div><div class="">Let's say there's also <i class="">github/erica/StringUtilities</i>, a package with 2 modules. It could consume the existing Packages and export them as named modules</div></div></div><div><br class=""></div><div><div><div><div style="font-family: Menlo;"><b class="">on github/erica/StringsUtilities</b></div><div><div style="font-family: Palatino;"><font face="Menlo" class="">import PackageDescription</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">let package = Package (</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; origin: "com.sadun.StringsUtilities"</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; name: "myutility",</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; dependencies: [</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;// I'm importing everything as a package and assuming something knows eventually</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;// these are actually modules</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;.Package(url: "<a href="https://github.com/erica/SwiftString.git" class="">https://github.com/erica/SwiftString.git</a>",</font></div><div style="font-family: Palatino;"><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; &nbsp; &nbsp; &nbsp; majorVersion: 1),</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;.</font><span style="font-family: Menlo;" class="">Package</span><font face="Menlo" class="">(url: "<a href="https://github.com/nudas/SwiftString.git" class="">https://github.com/nudas/SwiftString.git</a>",</font></div><div style="font-family: Palatino;"><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;majorVersion: 1),</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;.Package(url: "<a href="http://github.com/erica/SomeStringOtherPackage.git" class="">http://github.com/erica/SomeStringOtherPackage.git</a>",</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; majorVersion: 1), // just throwing some package in there</font></div><div style="font-family: Palatino;"><font face="Menlo" class="">&nbsp; &nbsp; ],</font></div><div style="font-family: Menlo;" class=""><font face="Menlo" class="">)</font></div><div style="font-family: Menlo;" class=""><br class=""></div><div class="">From the consuming side, you attempt to build with:</div><div style="font-family: Menlo;" class=""><font face="Menlo" class=""><br class=""></font></div></div></div></div><div><div><span style="font-family: Menlo;" class="">import PackageDescription</span></div></div><div><font face="Menlo" class="">let package = Package (</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; name: "myutility",</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; dependencies: [</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;.Package(url: "<a href="https://github.com/erica/StringsUtilities" class="">https://github.com/erica/StringsUtilities</a>.git",</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;majorVersion: 1),</font></div><div><span style="font-family: Menlo;" class="">&nbsp; &nbsp;],</span></div><div><span style="font-family: Menlo;" class="">)</span></div></div><div><br class=""></div><div>the build tool places the modules into separate org.sadun.SwiftString and com.foo.SwiftString build paths but still spits out an error:</div><div><br class=""></div><div><span style="font-family: Menlo;" class=""><b class="">org.sadun.SwiftString module name ("SwiftString") conflicts with com.foo.SwiftString ("SwiftString").&nbsp;</b></span></div><div><span style="font-family: Menlo;" class=""><b class="">Cannot build without adding import name overrides.</b></span></div><div><br class=""></div><div>So you hop back in and edit:</div><div><br class=""></div><div><div><div><div><span style="font-family: Menlo;" class="">import PackageDescription</span></div></div><div><font face="Menlo" class="">let package = Package (</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; name: "myutility",</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; dependencies: [</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;.Package(url: "<a href="https://github.com/erica/StringsUtilities" class="">https://github.com/erica/StringsUtilities</a>.git",</font></div><div><font face="Menlo" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;majorVersion: 1),</font></div><div><font face="Menlo" class="">&nbsp; &nbsp; ]</font></div><div><div><span style="font-family: Menlo;" class="">&nbsp; &nbsp; importMappings: [</span></div><div><span style="font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp;.Map(origin: "org.sadun.SwiftString", toName: "SwiftString"),</span></div><div><span style="font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp;.Map(origin: "com.foo.SwiftString", toName: "SwiftString2"),</span></div><div><font face="Menlo" class="">&nbsp; &nbsp; ],</font></div><div class=""><span style="font-family: Menlo;" class="">)</span></div></div><div class=""><span style="font-family: Menlo;" class=""><br class=""></span></div></div></div><div>And fixed?</div><div><br class=""></div><div>-- Erica</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">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).</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">These two issues bring up a related problem:</div><div class="">&nbsp;- We have packages, and we have modules, and both have names.</div><div class="">&nbsp;- 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".</div><div class="">&nbsp;- 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).</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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).</div><div class=""><br class=""></div><div class="">&nbsp;- Daniel</div></div></div></blockquote></div><br class=""></body></html>