<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></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 Nov 10, 2014, at 7:48 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 10, 2014 at 4:00 PM, Argyrios Kyrtzidis <span dir="ltr" class=""><<a href="mailto:kyrtzidis@apple.com" target="_blank" class="">kyrtzidis@apple.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">Hi all,</div><div class=""><br class=""></div><div class="">For frameworks Clang currently supports adding a separate module map file for the private headers of the framework. It looks specifically for the presence of ‘module.private.modulemap’ inside the .framework and parses both the public and the private module maps when it processes its module. We would like to extend support for private module maps for non-framework headers as well. </div><br class="">In the Darwin platform, the public SDK headers are located in '/usr/include', while the associated private SDK headers are located in '/usr/local/include’. '/usr/local/include’ comes before '/usr/include’ in the header search paths.<br class=""></div></blockquote><div class=""><br class=""></div><div class="">I worry that this will be fragile. If for any reason we look in /usr/include but not in /usr/local/include, we'll not load the private extension map and things will probably go quite badly from that point onwards. If the presence of the /usr/local/include headers is a fundamental part of a /usr/include module, then it seems better to me to specify that within the /usr/include module map.</div><div class=""><br class=""></div><div class="">So here's one possibility: allow 'extern module' declarations to be nested within other modules, then write your /usr/include module map as:</div><div class=""><br class=""></div><div class="">module MyModule {</div><div class="">  <...></div><div class="">  extern module SomethingPrivate "/usr/local/include/module.private.map"</div><div class="">}</div></div></div></div></div></blockquote><div><br class=""></div><div>This has drawbacks:</div><div><br class=""></div><div>- Details of the private SDK, “leak out” to the public one. It should work similar to frameworks, in that the public SDK remains the same irrespective if there is or not a private API, and the private API is a straight addition on top of the public one without needing to modify something in the public SDK.</div><div>- It is a bit weak as guarantee anyway because the public module map must necessarily function even when the extension map is missing, which means pointing at the wrong path or missing the private map when you really need it will not be detected.</div><div>- Flexibility to extend a module from any path may be valuable for testing.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">(in addition to the other changes you suggest here). Then only allow a module to be extended if the extension is listed via an 'extern module' in the definition of the module.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">We propose to make the following changes to Clang’s module mechanism:<br class=""><br class="">- When looking up a module through the search paths, in addition to ‘module.modulemap’ also lookup for a standalone ‘module.private.modulemap’ file. I will refer to this as the "private extension" module map.<br class="">- When parsing a private extension map allow extending a module that was not defined before, without providing the full definition. To clarify, I refer to a module definition as this:<br class=""><br class="">module MyModule {<br class=""> <…><br class="">}<br class=""><br class="">while an extension is this:<br class=""><br class="">module MyModule.SomethingPrivate {<br class=""> <…><br class="">}<br class=""><br class="">An extension is a nested module with any depth.<br class="">We can reuse the “extern module” syntax to indicate that we are extending a module whose definition is in a different module map:<div class=""><br class=""></div><div class="">extern module MyModule</div><div class="">module MyModule.SomethingPrivate {<br class=""> <…><br class="">}<br class=""></div><div class=""><br class="">- After parsing the private extension map, we are still missing the module definition so module lookup will continue looking in the following header search paths. If the module we are looking for is not found then Clang will a emit a “module not found” error.<br class=""><br class="">- It may seem backwards that module search will find and parse the private extension ahead of the public one, but it is actually advantageous because this allows us to continue searching only until we find the module definition, at which point we will stop looking. If module search worked the other way then, after we had the module definition, we would need to always keep looking through the rest of the search paths in case there is a private extension map that we need to take into account, or treat certain paths specially and only look for private extensions in those.<br class="">By finding the extension map early on, we keep the current semantics of doing the minimal search necessary to find and complete the module definition, without treating any particular search path specially.<br class=""><br class="">- After Clang finds and parses the public module map for ‘MyModule’, the module definition will be complete. Clang will keep track that there is a private extension map associated with the module and it will pass the paths of both the public module map and the private extension one to the module building invocation. This will result in one module file containing both the public and private APIs, similar to what we do with frameworks.</div><div class=""><br class=""></div><div class="">- A module definition inside a private extension will be disallowed. The rationale is that otherwise <span class="">it will be a very common mistake for users to write</span></div><div style="margin:0px;min-height:14px" class=""><br class=""></div><div style="margin:0px" class=""><b class="">module.modulemap:</b></div><div style="margin:0px" class="">module Foo {</div><div style="margin:0px" class="">  <public headers></div><div style="margin:0px" class="">}</div><div style="margin:0px;min-height:14px" class=""><br class=""></div><div style="margin:0px" class=""><b class="">module.private.modulemap:</b></div><div style="margin:0px" class="">module Foo {</div><div style="margin:0px" class="">  <private headers></div><div style="margin:0px" class="">}</div><div style="margin:0px;min-height:14px" class=""><br class=""></div><div style="margin:0px" class="">and then be left scratching their heads wondering why things are broken (things missing, headers included textually, etc.). Being more strict in private extension maps will be beneficial.</div><div style="margin:0px" class=""><br class=""></div><div style="margin:0px" class=""><br class=""></div><div style="margin:0px" class="">Let me know what you think!</div></div></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></body></html>