[cfe-dev] RFC: allow modules found via -fmodule-map-file to shadow implicitly discovered modules

Ben Langmuir via cfe-dev cfe-dev at lists.llvm.org
Tue Nov 10 15:39:52 PST 2015

Hey all,


Suppose you’re developing a system library FancyLib that installs a module map file into a default search path, and you’re using implicit module maps.  When you’re developing locally, you will likely end up with multiple versions of your module that are reachable in your search paths:
* The system version /usr/include/FancyLib/module.modulemap
* The local development version ~/…/Build/Products/Debug/FancyLib/module.modulemap

You generally want to use the local version, and ignore the one from the system.  Unfortunately, this currently causes module-redefinition errors if both module map files are ever parsed.  For framework modules, we have been getting away with this because the compiler almost never looks into a framework directory if it has previously looked into a framework directory of the same name.  Sadly the same is not true of non-frameworks.

Proposed change for users

Users developing non-framework system modules would add:

Typically, the “local copy” of the module map file would be to somewhere inside their build products.

Proposed clang changes

The flag -fmodule-map-file already exists in clang, and it causes clang to explicitly parse the specified module map, making any modules defined in that file available for @import (or via auto-import from a #import).

I propose we extend -fmodule-map-file so that modules found by this mechanism are allowed to shadow modules that we found implicitly in header search paths.  When searching for a module by name, we will not consider the shadowed module at all. It will be an error for header search to find a header that is considered part of a shadowed module.

If two modules with the same name are *both* found in the contents of -fmodule-map-file arguments, then it is a redefinition error.  Since these flags are ordered, we could theoretically allow shadowing between them, but I cannot think of a good use-case for this and suspect it would usually be unexpected to users.

If there are two modules with the same name and *neither* of them comes from -fmodule-map-file, then it is a redefinition error just like it is today.

Why not use header search path order to do shadowing?

I originally thought we should just allow modules that come from earlier search paths to shadow modules from later ones.  This would avoid having to use an extra flag -fmodule-map-file, and let us infer the module configuration “for free”, since users are already accustomed to setting up their header search paths.  However, there are a number of problems with this approach:

* Module map files from “later” search paths are often parsed ahead of module map files from “earlier” paths.  We would either need to eagerly parse module map files from all search paths in order (slow), or we would need to be able to retroactively make a module shadowed (brittle).
* Module map lookup does not know about search paths, so when searching for a module map file by umbrella directory we don't know when we cross search path boundaries
* We would need to lock down the HeaderSearch interface to prevent modifying search path order in the middle of a build (although that might be a generally good thing…)

My patch implementing this is attached for reference.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151110/f96e8627/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fmodule-map-file-shadow.patch
Type: application/octet-stream
Size: 16475 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151110/f96e8627/attachment.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20151110/f96e8627/attachment-0001.html>

More information about the cfe-dev mailing list