266 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
.. index:: modularize
 | 
						|
 | 
						|
==================================
 | 
						|
Modularize User's Manual
 | 
						|
==================================
 | 
						|
 | 
						|
.. toctree::
 | 
						|
   :hidden:
 | 
						|
 | 
						|
   ModularizeUsage
 | 
						|
 | 
						|
:program:`modularize` is a standalone tool that checks whether a set of headers
 | 
						|
provides the consistent definitions required to use modules. For example, it
 | 
						|
detects whether the same entity (say, a NULL macro or size_t typedef) is
 | 
						|
defined in multiple headers or whether a header produces different definitions
 | 
						|
under different circumstances. These conditions cause modules built from the
 | 
						|
headers to behave poorly, and should be fixed before introducing a module
 | 
						|
map.
 | 
						|
 | 
						|
:program:`modularize` also has an assistant mode option for generating
 | 
						|
a module map file based on the provided header list. The generated file
 | 
						|
is a functional module map that can be used as a starting point for a
 | 
						|
module.map file.
 | 
						|
 | 
						|
Getting Started
 | 
						|
===============
 | 
						|
 | 
						|
To build from source:
 | 
						|
 | 
						|
1. Read `Getting Started with the LLVM System`_ and `Clang Tools
 | 
						|
   Documentation`_ for information on getting sources for LLVM, Clang, and
 | 
						|
   Clang Extra Tools.
 | 
						|
 | 
						|
2. `Getting Started with the LLVM System`_ and `Building LLVM with CMake`_ give
 | 
						|
   directions for how to build. With sources all checked out into the
 | 
						|
   right place the LLVM build will build Clang Extra Tools and their
 | 
						|
   dependencies automatically.
 | 
						|
 | 
						|
   * If using CMake, you can also use the ``modularize`` target to build
 | 
						|
     just the modularize tool and its dependencies.
 | 
						|
 | 
						|
Before continuing, take a look at :doc:`ModularizeUsage` to see how to invoke
 | 
						|
modularize.
 | 
						|
 | 
						|
.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html
 | 
						|
.. _Building LLVM with CMake: http://llvm.org/docs/CMake.html
 | 
						|
.. _Clang Tools Documentation: http://clang.llvm.org/docs/ClangTools.html
 | 
						|
 | 
						|
What Modularize Checks
 | 
						|
======================
 | 
						|
 | 
						|
Modularize will check for the following:
 | 
						|
 | 
						|
* Duplicate global type and variable definitions
 | 
						|
* Duplicate macro definitions
 | 
						|
* Macro instances, 'defined(macro)', or #if, #elif, #ifdef, #ifndef conditions
 | 
						|
  that evaluate differently in a header
 | 
						|
* #include directives inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks
 | 
						|
* Module map header coverage completeness (in the case of a module map input
 | 
						|
  only)
 | 
						|
 | 
						|
Modularize will do normal C/C++ parsing, reporting normal errors and warnings,
 | 
						|
but will also report special error messages like the following::
 | 
						|
 | 
						|
  error: '(symbol)' defined at multiple locations:
 | 
						|
     (file):(row):(column)
 | 
						|
     (file):(row):(column)
 | 
						|
 | 
						|
  error: header '(file)' has different contents depending on how it was included
 | 
						|
 | 
						|
The latter might be followed by messages like the following::
 | 
						|
 | 
						|
  note: '(symbol)' in (file) at (row):(column) not always provided
 | 
						|
 | 
						|
Checks will also be performed for macro expansions, defined(macro)
 | 
						|
expressions, and preprocessor conditional directives that evaluate
 | 
						|
inconsistently, and can produce error messages like the following::
 | 
						|
 | 
						|
   (...)/SubHeader.h:11:5:
 | 
						|
  #if SYMBOL == 1
 | 
						|
      ^
 | 
						|
  error: Macro instance 'SYMBOL' has different values in this header,
 | 
						|
         depending on how it was included.
 | 
						|
    'SYMBOL' expanded to: '1' with respect to these inclusion paths:
 | 
						|
      (...)/Header1.h
 | 
						|
        (...)/SubHeader.h
 | 
						|
  (...)/SubHeader.h:3:9:
 | 
						|
  #define SYMBOL 1
 | 
						|
          ^
 | 
						|
  Macro defined here.
 | 
						|
    'SYMBOL' expanded to: '2' with respect to these inclusion paths:
 | 
						|
      (...)/Header2.h
 | 
						|
          (...)/SubHeader.h
 | 
						|
  (...)/SubHeader.h:7:9:
 | 
						|
  #define SYMBOL 2
 | 
						|
          ^
 | 
						|
  Macro defined here.
 | 
						|
 | 
						|
Checks will also be performed for '#include' directives that are
 | 
						|
nested inside 'extern "C/C++" {}' or 'namespace (name) {}' blocks,
 | 
						|
and can produce error message like the following::
 | 
						|
 | 
						|
  IncludeInExtern.h:2:3:
 | 
						|
  #include "Empty.h"
 | 
						|
  ^
 | 
						|
  error: Include directive within extern "C" {}.
 | 
						|
  IncludeInExtern.h:1:1:
 | 
						|
  extern "C" {
 | 
						|
  ^
 | 
						|
  The "extern "C" {}" block is here.
 | 
						|
 | 
						|
.. _module-map-coverage:
 | 
						|
 | 
						|
Module Map Coverage Check
 | 
						|
=========================
 | 
						|
 | 
						|
The coverage check uses the Clang library to read and parse the
 | 
						|
module map file. Starting at the module map file directory, or just the
 | 
						|
include paths, if specified, it will collect the names of all the files it
 | 
						|
considers headers (no extension, .h, or .inc--if you need more, modify the
 | 
						|
isHeader function). It then compares the headers against those referenced
 | 
						|
in the module map, either explicitly named, or implicitly named via an
 | 
						|
umbrella directory or umbrella file, as parsed by the ModuleMap object.
 | 
						|
If headers are found which are not referenced or covered by an umbrella
 | 
						|
directory or file, warning messages will be produced, and this program
 | 
						|
will return an error code of 1. If no problems are found, an error code of
 | 
						|
0 is returned.
 | 
						|
 | 
						|
Note that in the case of umbrella headers, this tool invokes the compiler
 | 
						|
to preprocess the file, and uses a callback to collect the header files
 | 
						|
included by the umbrella header or any of its nested includes. If any
 | 
						|
front end options are needed for these compiler invocations, these
 | 
						|
can be included on the command line after the module map file argument.
 | 
						|
 | 
						|
Warning message have the form:
 | 
						|
 | 
						|
  warning: module.modulemap does not account for file: Level3A.h
 | 
						|
 | 
						|
Note that for the case of the module map referencing a file that does
 | 
						|
not exist, the module map parser in Clang will (at the time of this
 | 
						|
writing) display an error message.
 | 
						|
 | 
						|
To limit the checks :program:`modularize` does to just the module
 | 
						|
map coverage check, use the ``-coverage-check-only option``.
 | 
						|
 | 
						|
For example::
 | 
						|
 | 
						|
  modularize -coverage-check-only module.modulemap
 | 
						|
 | 
						|
.. _module-map-generation:
 | 
						|
 | 
						|
Module Map Generation
 | 
						|
=====================
 | 
						|
 | 
						|
If you specify the ``-module-map-path=<module map file>``,
 | 
						|
:program:`modularize` will output a module map based on the input header list.
 | 
						|
A module will be created for each header. Also, if the header in the header
 | 
						|
list is a partial path, a nested module hierarchy will be created in which a
 | 
						|
module will be created for each subdirectory component in the header path,
 | 
						|
with the header itself represented by the innermost module. If other headers
 | 
						|
use the same subdirectories, they will be enclosed in these same modules also.
 | 
						|
 | 
						|
For example, for the header list::
 | 
						|
 | 
						|
  SomeTypes.h
 | 
						|
  SomeDecls.h
 | 
						|
  SubModule1/Header1.h
 | 
						|
  SubModule1/Header2.h
 | 
						|
  SubModule2/Header3.h
 | 
						|
  SubModule2/Header4.h
 | 
						|
  SubModule2.h
 | 
						|
 | 
						|
The following module map will be generated::
 | 
						|
 | 
						|
  // Output/NoProblemsAssistant.txt
 | 
						|
  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
 | 
						|
       -root-module=Root NoProblemsAssistant.modularize
 | 
						|
  
 | 
						|
  module SomeTypes {
 | 
						|
    header "SomeTypes.h"
 | 
						|
    export *
 | 
						|
  }
 | 
						|
  module SomeDecls {
 | 
						|
    header "SomeDecls.h"
 | 
						|
    export *
 | 
						|
  }
 | 
						|
  module SubModule1 {
 | 
						|
    module Header1 {
 | 
						|
      header "SubModule1/Header1.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
    module Header2 {
 | 
						|
      header "SubModule1/Header2.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
  }
 | 
						|
  module SubModule2 {
 | 
						|
    module Header3 {
 | 
						|
      header "SubModule2/Header3.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
    module Header4 {
 | 
						|
      header "SubModule2/Header4.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
    header "SubModule2.h"
 | 
						|
    export *
 | 
						|
  }
 | 
						|
 | 
						|
An optional ``-root-module=<root-name>`` option can be used to cause a root module
 | 
						|
to be created which encloses all the modules.
 | 
						|
 | 
						|
An optional ``-problem-files-list=<problem-file-name>`` can be used to input
 | 
						|
a list of files to be excluded, perhaps as a temporary stop-gap measure until
 | 
						|
problem headers can be fixed.
 | 
						|
 | 
						|
For example, with the same header list from above::
 | 
						|
 | 
						|
  // Output/NoProblemsAssistant.txt
 | 
						|
  // Generated by: modularize -module-map-path=Output/NoProblemsAssistant.txt \
 | 
						|
       -root-module=Root NoProblemsAssistant.modularize
 | 
						|
  
 | 
						|
  module Root {
 | 
						|
    module SomeTypes {
 | 
						|
      header "SomeTypes.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
    module SomeDecls {
 | 
						|
      header "SomeDecls.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
    module SubModule1 {
 | 
						|
      module Header1 {
 | 
						|
        header "SubModule1/Header1.h"
 | 
						|
        export *
 | 
						|
      }
 | 
						|
      module Header2 {
 | 
						|
        header "SubModule1/Header2.h"
 | 
						|
        export *
 | 
						|
      }
 | 
						|
    }
 | 
						|
    module SubModule2 {
 | 
						|
      module Header3 {
 | 
						|
        header "SubModule2/Header3.h"
 | 
						|
        export *
 | 
						|
      }
 | 
						|
      module Header4 {
 | 
						|
        header "SubModule2/Header4.h"
 | 
						|
        export *
 | 
						|
      }
 | 
						|
      header "SubModule2.h"
 | 
						|
      export *
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
Note that headers with dependents will be ignored with a warning, as the
 | 
						|
Clang module mechanism doesn't support headers the rely on other headers
 | 
						|
to be included first.
 | 
						|
 | 
						|
The module map format defines some keywords which can't be used in module
 | 
						|
names. If a header has one of these names, an underscore ('_') will be
 | 
						|
prepended to the name. For example, if the header name is ``header.h``,
 | 
						|
because ``header`` is a keyword, the module name will be ``_header``.
 | 
						|
For a list of the module map keywords, please see:
 | 
						|
`Lexical structure <http://clang.llvm.org/docs/Modules.html#lexical-structure>`_
 |