[cfe-dev] RFC: Supporting private module maps for non-framework headers

Argyrios Kyrtzidis kyrtzidis at apple.com
Mon Nov 10 16:00:14 PST 2014


Hi all,

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. 

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.
We propose to make the following changes to Clang’s module mechanism:

- 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.
- 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:

module MyModule {
 <…>
}

while an extension is this:

module MyModule.SomethingPrivate {
 <…>
}

An extension is a nested module with any depth.
We can reuse the “extern module” syntax to indicate that we are extending a module whose definition is in a different module map:

extern module MyModule
module MyModule.SomethingPrivate {
 <…>
}

- 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.

- 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.
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.

- 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.

- A module definition inside a private extension will be disallowed. The rationale is that otherwise it will be a very common mistake for users to write

module.modulemap:
module Foo {
  <public headers>
}

module.private.modulemap:
module Foo {
  <private headers>
}

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.


Let me know what you think!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141110/0623ba36/attachment.html>


More information about the cfe-dev mailing list