<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 10, 2014 at 4:00 PM, Argyrios Kyrtzidis <span dir="ltr"><<a href="mailto:kyrtzidis@apple.com" target="_blank">kyrtzidis@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Hi all,</div><div><br></div><div>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>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></div></blockquote><div><br></div><div>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><br></div><div>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><br></div><div>module MyModule {</div><div>  <...></div><div>  extern module SomethingPrivate "/usr/local/include/module.private.map"</div><div>}</div><div><br></div><div>(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><br></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">We propose to make the following changes to Clang’s module mechanism:<br><br>- 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>- 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><br>module MyModule {<br> <…><br>}<br><br>while an extension is this:<br><br>module MyModule.SomethingPrivate {<br> <…><br>}<br><br>An extension is a nested module with any depth.<br>We can reuse the “extern module” syntax to indicate that we are extending a module whose definition is in a different module map:<div><br></div><div>extern module MyModule</div><div>module MyModule.SomethingPrivate {<br> <…><br>}<br></div><div><br>- 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><br>- 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>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><br>- 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><br></div><div>- A module definition inside a private extension will be disallowed. The rationale is that otherwise <span>it will be a very common mistake for users to write</span></div><div style="margin:0px;min-height:14px"><br></div><div style="margin:0px"><b>module.modulemap:</b></div><div style="margin:0px">module Foo {</div><div style="margin:0px">  <public headers></div><div style="margin:0px">}</div><div style="margin:0px;min-height:14px"><br></div><div style="margin:0px"><b>module.private.modulemap:</b></div><div style="margin:0px">module Foo {</div><div style="margin:0px">  <private headers></div><div style="margin:0px">}</div><div style="margin:0px;min-height:14px"><br></div><div style="margin:0px">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"><br></div><div style="margin:0px"><br></div><div style="margin:0px">Let me know what you think!</div></div></blockquote></div><br></div></div>