My apologies for not responding sooner.
There are several benefits to custom modulemaps, the simplest being that you can define which other frameworks your library links to so your users don't have to manually link to to system libraries themselves. (see also: http://clang.llvm.org/docs/Modules.html#link-declaration)
In general the default auto-generated modulemap is useful for flat, or simpler frameworks. But when different framework components are produced by different teams, or a framework is consuming another internally-produced dependency, using custom module maps can be useful I find.
In my project, my teams are producing multiple frameworks that all depend on a common "Core" framework. This core framework itself is composed of two different libraries, because one of them is reused within different projects at my company (and not just created solely for this project). However, we don't want to expose it to the users of our public framework. For example:
- ServiceCore.framework
- ServiceKnowledge.framework <Depends upon ServiceCore.framework>
- KnowledgeCore <Public APIs>
Private <Private APIs>
- KnowledgeUI <Public APIs>
Private <Private APIs>
- Etc...
The private capabilities of the core framework are used directly not only by the other frameworks that depend upon it, but by our internal testing infrastructure. Furthermore, the frameworks that depend upon the Core functionality also use submodules for two main reasons:
- Forces our developers to separate out core API-only functionality from UI functionality to make the interfaces cleaner;
- Exposing private frameworks again for use in testing, and for interaction between the UI and Core submodules.
As a result, our public modulemap file looks something like this:
| framework module ServiceCore { |
| umbrella header "ServiceCore.h" |
| export * |
| module * { export * } |
| |
| framework module ServiceCommon { |
| umbrella header "ServiceCommon.h" |
| export * |
| module * { export * } |
| } |
| |
| link framework "UIKit" |
| link framework "SystemConfiguration" |
| link framework "CoreGraphics" |
| link "System" |
| link "sqlite3" |
| link "z" |
| |
| use AnalyticsCommon |
| } |
You can see how the submodule exposes its umbrella header. Since they're exported, a simple "@import ServiceCore" will also import the submodules. Also, you can see how it indicates which system frameworks it uses, so they will automatically be imported and linked by Xcode for you. Additionally, you can add "use" declarations to tell Xcode which associated frameworks are "safe" to cross-reference, without getting cross-framework import errors.
The private modulemap file looks something like this:
| explicit framework module ServiceCore.ServiceCommon.Private { |
| umbrella header "ServiceCommon/Private.h" |
| export * |
| module * { export * } |
| } |
| |
| explicit framework module ServiceCore.OfflineCaching { |
| umbrella header "OfflineCaching/OfflineCaching.h" |
| export * |
| module * { export * } |
| } |
Those are marked as explicit framework modules, meaning they have to be manually imported to be accessible. Before shipping the frameworks, we strip these modulemap and private header files, but while used internally, it allows our developers to reference dependent classes safely.
I hope that helps.