1.. index:: modularize
2
3==================================
4Modularize User's Manual
5==================================
6
7.. toctree::
8   :hidden:
9
10   ModularizeUsage
11
12:program:`modularize` is a standalone tool that checks whether a set of headers
13provides the consistent definitions required to use modules. For example, it
14detects whether the same entity (say, a NULL macro or size_t typedef) is
15defined in multiple headers or whether a header produces different definitions
16under different circumstances. These conditions cause modules built from the
17headers to behave poorly, and should be fixed before introducing a module
18map.
19
20:program:`modularize` also has an assistant mode option for generating
21a module map file based on the provided header list. The generated file
22is a functional module map that can be used as a starting point for a
23module.map file.
24
25Getting Started
26===============
27
28To build from source:
29
301. Read `Getting Started with the LLVM System`_ and `Clang Tools
31   Documentation`_ for information on getting sources for LLVM, Clang, and
32   Clang Extra Tools.
33
342. `Getting Started with the LLVM System`_ and `Building LLVM with CMake`_ give
35   directions for how to build. With sources all checked out into the
36   right place the LLVM build will build Clang Extra Tools and their
37   dependencies automatically.
38
39   * If using CMake, you can also use the ``modularize`` target to build
40     just the modularize tool and its dependencies.
41
42Before continuing, take a look at :doc:`ModularizeUsage` to see how to invoke
43modularize.
44
45.. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html
46.. _Building LLVM with CMake: https://llvm.org/docs/CMake.html
47.. _Clang Tools Documentation: https://clang.llvm.org/docs/ClangTools.html
48
49What Modularize Checks
50======================
51
52Modularize will check for the following:
53
54* Duplicate global type and variable definitions
55* Duplicate macro definitions
56* Macro instances, 'defined(macro)', or #if, #elif, #ifdef, #ifndef conditions
57  that evaluate differently in a header
58* #include directives inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks
59* Module map header coverage completeness (in the case of a module map input
60  only)
61
62Modularize will do normal C/C++ parsing, reporting normal errors and warnings,
63but will also report special error messages like the following::
64
65  error: '(symbol)' defined at multiple locations:
66     (file):(row):(column)
67     (file):(row):(column)
68
69  error: header '(file)' has different contents depending on how it was included
70
71The latter might be followed by messages like the following::
72
73  note: '(symbol)' in (file) at (row):(column) not always provided
74
75Checks will also be performed for macro expansions, defined(macro)
76expressions, and preprocessor conditional directives that evaluate
77inconsistently, and can produce error messages like the following::
78
79   (...)/SubHeader.h:11:5:
80  #if SYMBOL == 1
81      ^
82  error: Macro instance 'SYMBOL' has different values in this header,
83         depending on how it was included.
84    'SYMBOL' expanded to: '1' with respect to these inclusion paths:
85      (...)/Header1.h
86        (...)/SubHeader.h
87  (...)/SubHeader.h:3:9:
88  #define SYMBOL 1
89          ^
90  Macro defined here.
91    'SYMBOL' expanded to: '2' with respect to these inclusion paths:
92      (...)/Header2.h
93          (...)/SubHeader.h
94  (...)/SubHeader.h:7:9:
95  #define SYMBOL 2
96          ^
97  Macro defined here.
98
99Checks will also be performed for '#include' directives that are
100nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks,
101and can produce error message like the following::
102
103  IncludeInExtern.h:2:3:
104  #include "Empty.h"
105  ^
106  error: Include directive within extern "C" {}.
107  IncludeInExtern.h:1:1:
108  extern "C" {
109  ^
110  The "extern "C" {}" block is here.
111
112.. _module-map-coverage:
113
114Module Map Coverage Check
115=========================
116
117The coverage check uses the Clang library to read and parse the
118module map file. Starting at the module map file directory, or just the
119include paths, if specified, it will collect the names of all the files it
120considers headers (no extension, .h, or .inc--if you need more, modify the
121isHeader function). It then compares the headers against those referenced
122in the module map, either explicitly named, or implicitly named via an
123umbrella directory or umbrella file, as parsed by the ModuleMap object.
124If headers are found which are not referenced or covered by an umbrella
125directory or file, warning messages will be produced, and this program
126will return an error code of 1. If no problems are found, an error code of
1270 is returned.
128
129Note that in the case of umbrella headers, this tool invokes the compiler
130to preprocess the file, and uses a callback to collect the header files
131included by the umbrella header or any of its nested includes. If any
132front end options are needed for these compiler invocations, these
133can be included on the command line after the module map file argument.
134
135Warning message have the form:
136
137  warning: module.modulemap does not account for file: Level3A.h
138
139Note that for the case of the module map referencing a file that does
140not exist, the module map parser in Clang will (at the time of this
141writing) display an error message.
142
143To limit the checks :program:`modularize` does to just the module
144map coverage check, use the ``-coverage-check-only option``.
145
146For example::
147
148  modularize -coverage-check-only module.modulemap
149
150.. _module-map-generation:
151
152Module Map Generation
153=====================
154
155If you specify the ``-module-map-path=<module map file>``,
156:program:`modularize` will output a module map based on the input header list.
157A module will be created for each header. Also, if the header in the header
158list is a partial path, a nested module hierarchy will be created in which a
159module will be created for each subdirectory component in the header path,
160with the header itself represented by the innermost module. If other headers
161use the same subdirectories, they will be enclosed in these same modules also.
162
163For example, for the header list::
164
165  SomeTypes.h
166  SomeDecls.h
167  SubModule1/Header1.h
168  SubModule1/Header2.h
169  SubModule2/Header3.h
170  SubModule2/Header4.h
171  SubModule2.h
172
173The following module map will be generated::
174
175  // Output/NoProblemsAssistant.txt
176  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
177       -root-module=Root NoProblemsAssistant.modularize
178
179  module SomeTypes {
180    header "SomeTypes.h"
181    export *
182  }
183  module SomeDecls {
184    header "SomeDecls.h"
185    export *
186  }
187  module SubModule1 {
188    module Header1 {
189      header "SubModule1/Header1.h"
190      export *
191    }
192    module Header2 {
193      header "SubModule1/Header2.h"
194      export *
195    }
196  }
197  module SubModule2 {
198    module Header3 {
199      header "SubModule2/Header3.h"
200      export *
201    }
202    module Header4 {
203      header "SubModule2/Header4.h"
204      export *
205    }
206    header "SubModule2.h"
207    export *
208  }
209
210An optional ``-root-module=<root-name>`` option can be used to cause a root module
211to be created which encloses all the modules.
212
213An optional ``-problem-files-list=<problem-file-name>`` can be used to input
214a list of files to be excluded, perhaps as a temporary stop-gap measure until
215problem headers can be fixed.
216
217For example, with the same header list from above::
218
219  // Output/NoProblemsAssistant.txt
220  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
221       -root-module=Root NoProblemsAssistant.modularize
222
223  module Root {
224    module SomeTypes {
225      header "SomeTypes.h"
226      export *
227    }
228    module SomeDecls {
229      header "SomeDecls.h"
230      export *
231    }
232    module SubModule1 {
233      module Header1 {
234        header "SubModule1/Header1.h"
235        export *
236      }
237      module Header2 {
238        header "SubModule1/Header2.h"
239        export *
240      }
241    }
242    module SubModule2 {
243      module Header3 {
244        header "SubModule2/Header3.h"
245        export *
246      }
247      module Header4 {
248        header "SubModule2/Header4.h"
249        export *
250      }
251      header "SubModule2.h"
252      export *
253    }
254  }
255
256Note that headers with dependents will be ignored with a warning, as the
257Clang module mechanism doesn't support headers the rely on other headers
258to be included first.
259
260The module map format defines some keywords which can't be used in module
261names. If a header has one of these names, an underscore ('_') will be
262prepended to the name. For example, if the header name is ``header.h``,
263because ``header`` is a keyword, the module name will be ``_header``.
264For a list of the module map keywords, please see:
265`Lexical structure <https://clang.llvm.org/docs/Modules.html#lexical-structure>`_
266