150
|
1 .. index:: modularize
|
|
2
|
|
3 ==================================
|
|
4 Modularize 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
|
|
13 provides the consistent definitions required to use modules. For example, it
|
|
14 detects whether the same entity (say, a NULL macro or size_t typedef) is
|
|
15 defined in multiple headers or whether a header produces different definitions
|
|
16 under different circumstances. These conditions cause modules built from the
|
|
17 headers to behave poorly, and should be fixed before introducing a module
|
|
18 map.
|
|
19
|
|
20 :program:`modularize` also has an assistant mode option for generating
|
|
21 a module map file based on the provided header list. The generated file
|
|
22 is a functional module map that can be used as a starting point for a
|
|
23 module.map file.
|
|
24
|
|
25 Getting Started
|
|
26 ===============
|
|
27
|
|
28 To build from source:
|
|
29
|
|
30 1. 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
|
|
34 2. `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
|
|
42 Before continuing, take a look at :doc:`ModularizeUsage` to see how to invoke
|
|
43 modularize.
|
|
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
|
|
49 What Modularize Checks
|
|
50 ======================
|
|
51
|
|
52 Modularize 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
|
|
62 Modularize will do normal C/C++ parsing, reporting normal errors and warnings,
|
|
63 but 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
|
|
71 The latter might be followed by messages like the following::
|
|
72
|
|
73 note: '(symbol)' in (file) at (row):(column) not always provided
|
|
74
|
|
75 Checks will also be performed for macro expansions, defined(macro)
|
|
76 expressions, and preprocessor conditional directives that evaluate
|
|
77 inconsistently, 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
|
|
99 Checks will also be performed for '#include' directives that are
|
|
100 nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks,
|
|
101 and 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
|
|
114 Module Map Coverage Check
|
|
115 =========================
|
|
116
|
|
117 The coverage check uses the Clang library to read and parse the
|
|
118 module map file. Starting at the module map file directory, or just the
|
|
119 include paths, if specified, it will collect the names of all the files it
|
|
120 considers headers (no extension, .h, or .inc--if you need more, modify the
|
|
121 isHeader function). It then compares the headers against those referenced
|
|
122 in the module map, either explicitly named, or implicitly named via an
|
|
123 umbrella directory or umbrella file, as parsed by the ModuleMap object.
|
|
124 If headers are found which are not referenced or covered by an umbrella
|
|
125 directory or file, warning messages will be produced, and this program
|
|
126 will return an error code of 1. If no problems are found, an error code of
|
|
127 0 is returned.
|
|
128
|
|
129 Note that in the case of umbrella headers, this tool invokes the compiler
|
|
130 to preprocess the file, and uses a callback to collect the header files
|
|
131 included by the umbrella header or any of its nested includes. If any
|
|
132 front end options are needed for these compiler invocations, these
|
|
133 can be included on the command line after the module map file argument.
|
|
134
|
|
135 Warning message have the form:
|
|
136
|
|
137 warning: module.modulemap does not account for file: Level3A.h
|
|
138
|
|
139 Note that for the case of the module map referencing a file that does
|
|
140 not exist, the module map parser in Clang will (at the time of this
|
|
141 writing) display an error message.
|
|
142
|
|
143 To limit the checks :program:`modularize` does to just the module
|
|
144 map coverage check, use the ``-coverage-check-only option``.
|
|
145
|
|
146 For example::
|
|
147
|
|
148 modularize -coverage-check-only module.modulemap
|
|
149
|
|
150 .. _module-map-generation:
|
|
151
|
|
152 Module Map Generation
|
|
153 =====================
|
|
154
|
|
155 If you specify the ``-module-map-path=<module map file>``,
|
|
156 :program:`modularize` will output a module map based on the input header list.
|
|
157 A module will be created for each header. Also, if the header in the header
|
|
158 list is a partial path, a nested module hierarchy will be created in which a
|
|
159 module will be created for each subdirectory component in the header path,
|
|
160 with the header itself represented by the innermost module. If other headers
|
|
161 use the same subdirectories, they will be enclosed in these same modules also.
|
|
162
|
|
163 For 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
|
|
173 The 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
|
236
|
178
|
150
|
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
|
|
210 An optional ``-root-module=<root-name>`` option can be used to cause a root module
|
|
211 to be created which encloses all the modules.
|
|
212
|
|
213 An optional ``-problem-files-list=<problem-file-name>`` can be used to input
|
|
214 a list of files to be excluded, perhaps as a temporary stop-gap measure until
|
|
215 problem headers can be fixed.
|
|
216
|
|
217 For 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
|
236
|
222
|
150
|
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
|
|
256 Note that headers with dependents will be ignored with a warning, as the
|
|
257 Clang module mechanism doesn't support headers the rely on other headers
|
|
258 to be included first.
|
|
259
|
|
260 The module map format defines some keywords which can't be used in module
|
|
261 names. If a header has one of these names, an underscore ('_') will be
|
|
262 prepended to the name. For example, if the header name is ``header.h``,
|
|
263 because ``header`` is a keyword, the module name will be ``_header``.
|
|
264 For a list of the module map keywords, please see:
|
|
265 `Lexical structure <https://clang.llvm.org/docs/Modules.html#lexical-structure>`_
|