1b1d5af81SChuanqi Xu==================== 2b1d5af81SChuanqi XuStandard C++ Modules 3b1d5af81SChuanqi Xu==================== 4b1d5af81SChuanqi Xu 5b1d5af81SChuanqi Xu.. contents:: 6b1d5af81SChuanqi Xu :local: 7b1d5af81SChuanqi Xu 8b1d5af81SChuanqi XuIntroduction 9b1d5af81SChuanqi Xu============ 10b1d5af81SChuanqi Xu 119263318fSAaron BallmanThe term ``module`` is ambiguous, as it is used to mean multiple things in 129263318fSAaron BallmanClang. For Clang users, a module may refer to an ``Objective-C Module``, 139263318fSAaron Ballman`Clang Module <Modules.html>`_ (also called a ``Clang Header Module``) or a 149263318fSAaron Ballman``C++20 Module`` (or a ``Standard C++ Module``). The implementation of all 159263318fSAaron Ballmanthese kinds of modules in Clang shares a lot of code, but from the perspective 169263318fSAaron Ballmanof users their semantics and command line interfaces are very different. This 179263318fSAaron Ballmandocument is an introduction to the use of C++20 modules in Clang. In the 189263318fSAaron Ballmanremainder of this document, the term ``module`` will refer to Standard C++20 199263318fSAaron Ballmanmodules and the term ``Clang module`` will refer to the Clang Modules 209263318fSAaron Ballmanextension. 21b1d5af81SChuanqi Xu 229263318fSAaron BallmanIn terms of the C++ Standard, modules consist of two components: "Named 239263318fSAaron BallmanModules" or "Header Units". This document covers both. 24b1d5af81SChuanqi Xu 25b1d5af81SChuanqi XuStandard C++ Named modules 26b1d5af81SChuanqi Xu========================== 27b1d5af81SChuanqi Xu 289263318fSAaron BallmanIn order to better understand the compiler's behavior, it is helpful to 299263318fSAaron Ballmanunderstand some terms and definitions for readers who are not familiar with the 309263318fSAaron BallmanC++ feature. This document is not a tutorial on C++; it only introduces 319263318fSAaron Ballmannecessary concepts to better understand use of modules in a project. 32b1d5af81SChuanqi Xu 33b1d5af81SChuanqi XuBackground and terminology 34b1d5af81SChuanqi Xu-------------------------- 35b1d5af81SChuanqi Xu 36b1d5af81SChuanqi XuModule and module unit 37b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~ 38b1d5af81SChuanqi Xu 399263318fSAaron BallmanA module consists of one or more module units. A module unit is a special kind 409263318fSAaron Ballmanof translation unit. A module unit should almost always start with a module 419263318fSAaron Ballmandeclaration. The syntax of the module declaration is: 42b1d5af81SChuanqi Xu 43b1d5af81SChuanqi Xu.. code-block:: c++ 44b1d5af81SChuanqi Xu 45b1d5af81SChuanqi Xu [export] module module_name[:partition_name]; 46b1d5af81SChuanqi Xu 479263318fSAaron BallmanTerms enclosed in ``[]`` are optional. ``module_name`` and ``partition_name`` 489263318fSAaron Ballmanfollow the rules for a C++ identifier, except that they may contain one or more 499263318fSAaron Ballmanperiod (``.``) characters. Note that a ``.`` in the name has no semantic 509263318fSAaron Ballmanmeaning and does not imply any hierarchy. 51b1d5af81SChuanqi Xu 529263318fSAaron BallmanIn this document, module units are classified as: 53b1d5af81SChuanqi Xu 549263318fSAaron Ballman* Primary module interface unit 559263318fSAaron Ballman* Module implementation unit 569263318fSAaron Ballman* Module partition interface unit 579263318fSAaron Ballman* Internal module partition unit 58b1d5af81SChuanqi Xu 59b1d5af81SChuanqi XuA primary module interface unit is a module unit whose module declaration is 609263318fSAaron Ballman``export module module_name;`` where ``module_name`` denotes the name of the 61b1d5af81SChuanqi Xumodule. A module should have one and only one primary module interface unit. 62b1d5af81SChuanqi Xu 63b1d5af81SChuanqi XuA module implementation unit is a module unit whose module declaration is 649263318fSAaron Ballman``module module_name;``. Multiple module implementation units can be declared 659263318fSAaron Ballmanin the same module. 66b1d5af81SChuanqi Xu 679263318fSAaron BallmanA module partition interface unit is a module unit whose module declaration is 68b1d5af81SChuanqi Xu``export module module_name:partition_name;``. The ``partition_name`` should be 69b1d5af81SChuanqi Xuunique within any given module. 70b1d5af81SChuanqi Xu 719263318fSAaron BallmanAn internal module partition unit is a module unit whose module 729263318fSAaron Ballmandeclaration is ``module module_name:partition_name;``. The ``partition_name`` 739263318fSAaron Ballmanshould be unique within any given module. 74b1d5af81SChuanqi Xu 759263318fSAaron BallmanIn this document, we use the following terms: 76b1d5af81SChuanqi Xu 77b1d5af81SChuanqi Xu* A ``module interface unit`` refers to either a ``primary module interface unit`` 789263318fSAaron Ballman or a ``module partition interface unit``. 79b1d5af81SChuanqi Xu 809263318fSAaron Ballman* An ``importable module unit`` refers to either a ``module interface unit`` or 819263318fSAaron Ballman an ``internal module partition unit``. 82b1d5af81SChuanqi Xu 839263318fSAaron Ballman* A ``module partition unit`` refers to either a ``module partition interface unit`` 849263318fSAaron Ballman or an ``internal module partition unit``. 85b1d5af81SChuanqi Xu 869263318fSAaron BallmanBuilt Module Interface 879263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~ 88b1d5af81SChuanqi Xu 899263318fSAaron BallmanA ``Built Module Interface`` (or ``BMI``) is the precompiled result of an 909263318fSAaron Ballmanimportable module unit. 91b1d5af81SChuanqi Xu 92b1d5af81SChuanqi XuGlobal module fragment 93b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~ 94b1d5af81SChuanqi Xu 959263318fSAaron BallmanThe ``global module fragment`` (or ``GMF``) is the code between the ``module;`` 969263318fSAaron Ballmanand the module declaration within a module unit. 97b1d5af81SChuanqi Xu 98b1d5af81SChuanqi Xu 99b1d5af81SChuanqi XuHow to build projects using modules 100b1d5af81SChuanqi Xu----------------------------------- 101b1d5af81SChuanqi Xu 102b1d5af81SChuanqi XuQuick Start 103b1d5af81SChuanqi Xu~~~~~~~~~~~ 104b1d5af81SChuanqi Xu 105b1d5af81SChuanqi XuLet's see a "hello world" example that uses modules. 106b1d5af81SChuanqi Xu 107b1d5af81SChuanqi Xu.. code-block:: c++ 108b1d5af81SChuanqi Xu 109b1d5af81SChuanqi Xu // Hello.cppm 110b1d5af81SChuanqi Xu module; 111b1d5af81SChuanqi Xu #include <iostream> 112b1d5af81SChuanqi Xu export module Hello; 113b1d5af81SChuanqi Xu export void hello() { 114b1d5af81SChuanqi Xu std::cout << "Hello World!\n"; 115b1d5af81SChuanqi Xu } 116b1d5af81SChuanqi Xu 117b1d5af81SChuanqi Xu // use.cpp 118b1d5af81SChuanqi Xu import Hello; 119b1d5af81SChuanqi Xu int main() { 120b1d5af81SChuanqi Xu hello(); 121b1d5af81SChuanqi Xu return 0; 122b1d5af81SChuanqi Xu } 123b1d5af81SChuanqi Xu 1249263318fSAaron BallmanThen, on the command line, invoke Clang like: 125b1d5af81SChuanqi Xu 126b1d5af81SChuanqi Xu.. code-block:: console 127b1d5af81SChuanqi Xu 128b1d5af81SChuanqi Xu $ clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm 1294b99af34SChuanqi Xu $ clang++ -std=c++20 use.cpp -fmodule-file=Hello=Hello.pcm Hello.pcm -o Hello.out 130b1d5af81SChuanqi Xu $ ./Hello.out 131b1d5af81SChuanqi Xu Hello World! 132b1d5af81SChuanqi Xu 133b1d5af81SChuanqi XuIn this example, we make and use a simple module ``Hello`` which contains only a 1349263318fSAaron Ballmanprimary module interface unit named ``Hello.cppm``. 135b1d5af81SChuanqi Xu 1369263318fSAaron BallmanA more complex "hello world" example which uses the 4 kinds of module units is: 137b1d5af81SChuanqi Xu 138b1d5af81SChuanqi Xu.. code-block:: c++ 139b1d5af81SChuanqi Xu 140b1d5af81SChuanqi Xu // M.cppm 141b1d5af81SChuanqi Xu export module M; 142b1d5af81SChuanqi Xu export import :interface_part; 143b1d5af81SChuanqi Xu import :impl_part; 144b1d5af81SChuanqi Xu export void Hello(); 145b1d5af81SChuanqi Xu 146b1d5af81SChuanqi Xu // interface_part.cppm 147b1d5af81SChuanqi Xu export module M:interface_part; 148b1d5af81SChuanqi Xu export void World(); 149b1d5af81SChuanqi Xu 150b1d5af81SChuanqi Xu // impl_part.cppm 151b1d5af81SChuanqi Xu module; 152b1d5af81SChuanqi Xu #include <iostream> 153b1d5af81SChuanqi Xu #include <string> 154b1d5af81SChuanqi Xu module M:impl_part; 155b1d5af81SChuanqi Xu import :interface_part; 156b1d5af81SChuanqi Xu 157b1d5af81SChuanqi Xu std::string W = "World."; 158b1d5af81SChuanqi Xu void World() { 159b1d5af81SChuanqi Xu std::cout << W << std::endl; 160b1d5af81SChuanqi Xu } 161b1d5af81SChuanqi Xu 162b1d5af81SChuanqi Xu // Impl.cpp 163b1d5af81SChuanqi Xu module; 164b1d5af81SChuanqi Xu #include <iostream> 165b1d5af81SChuanqi Xu module M; 166b1d5af81SChuanqi Xu void Hello() { 167b1d5af81SChuanqi Xu std::cout << "Hello "; 168b1d5af81SChuanqi Xu } 169b1d5af81SChuanqi Xu 170b1d5af81SChuanqi Xu // User.cpp 171b1d5af81SChuanqi Xu import M; 172b1d5af81SChuanqi Xu int main() { 173b1d5af81SChuanqi Xu Hello(); 174b1d5af81SChuanqi Xu World(); 175b1d5af81SChuanqi Xu return 0; 176b1d5af81SChuanqi Xu } 177b1d5af81SChuanqi Xu 1789263318fSAaron BallmanThen, back on the command line, invoke Clang with: 179b1d5af81SChuanqi Xu 180b1d5af81SChuanqi Xu.. code-block:: console 181b1d5af81SChuanqi Xu 182b1d5af81SChuanqi Xu # Precompiling the module 183b1d5af81SChuanqi Xu $ clang++ -std=c++20 interface_part.cppm --precompile -o M-interface_part.pcm 184b1d5af81SChuanqi Xu $ clang++ -std=c++20 impl_part.cppm --precompile -fprebuilt-module-path=. -o M-impl_part.pcm 185b1d5af81SChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -fprebuilt-module-path=. -o M.pcm 1864b99af34SChuanqi Xu $ clang++ -std=c++20 Impl.cpp -fprebuilt-module-path=. -c -o Impl.o 187b1d5af81SChuanqi Xu 188b1d5af81SChuanqi Xu # Compiling the user 189b1d5af81SChuanqi Xu $ clang++ -std=c++20 User.cpp -fprebuilt-module-path=. -c -o User.o 190b1d5af81SChuanqi Xu 191b1d5af81SChuanqi Xu # Compiling the module and linking it together 1924b99af34SChuanqi Xu $ clang++ -std=c++20 M-interface_part.pcm -fprebuilt-module-path=. -c -o M-interface_part.o 1934b99af34SChuanqi Xu $ clang++ -std=c++20 M-impl_part.pcm -fprebuilt-module-path=. -c -o M-impl_part.o 1944b99af34SChuanqi Xu $ clang++ -std=c++20 M.pcm -fprebuilt-module-path=. -c -o M.o 195b1d5af81SChuanqi Xu $ clang++ User.o M-interface_part.o M-impl_part.o M.o Impl.o -o a.out 196b1d5af81SChuanqi Xu 197b1d5af81SChuanqi XuWe explain the options in the following sections. 198b1d5af81SChuanqi Xu 199b1d5af81SChuanqi XuHow to enable standard C++ modules 200b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 201b1d5af81SChuanqi Xu 2029263318fSAaron BallmanStandard C++ modules are enabled automatically when the language standard mode 2039263318fSAaron Ballmanis ``-std=c++20`` or newer. 204b1d5af81SChuanqi Xu 205b1d5af81SChuanqi XuHow to produce a BMI 206b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~ 207b1d5af81SChuanqi Xu 2089263318fSAaron BallmanTo generate a BMI for an importable module unit, use either the ``--precompile`` 2099263318fSAaron Ballmanor ``-fmodule-output`` command line options. 210046a9910SChuanqi Xu 2119263318fSAaron BallmanThe ``--precompile`` option generates the BMI as the output of the compilation 2129263318fSAaron Ballmanwith the output path specified using the ``-o`` option. 213046a9910SChuanqi Xu 2149263318fSAaron BallmanThe ``-fmodule-output`` option generates the BMI as a by-product of the 2159263318fSAaron Ballmancompilation. If ``-fmodule-output=`` is specified, the BMI will be emitted to 2169263318fSAaron Ballmanthe specified location. If ``-fmodule-output`` and ``-c`` are specified, the 2179263318fSAaron BallmanBMI will be emitted in the directory of the output file with the name of the 2189263318fSAaron Ballmaninput file with the extension ``.pcm``. Otherwise, the BMI will be emitted in 2199263318fSAaron Ballmanthe working directory with the name of the input file with the extension 220046a9910SChuanqi Xu``.pcm``. 221046a9910SChuanqi Xu 2229263318fSAaron BallmanGenerating BMIs with ``--precompile`` is referred to as two-phase compilation 2239263318fSAaron Ballmanbecause it takes two steps to compile a source file to an object file. 2249263318fSAaron BallmanGenerating BMIs with ``-fmodule-output`` is called one-phase compilation. The 2259263318fSAaron Ballmanone-phase compilation model is simpler for build systems to implement while the 2269263318fSAaron Ballmantwo-phase compilation has the potential to compile faster due to higher 2279263318fSAaron Ballmanparallelism. As an example, if there are two module units ``A`` and ``B``, and 2289263318fSAaron Ballman``B`` depends on ``A``, the one-phase compilation model needs to compile them 2299263318fSAaron Ballmanserially, whereas the two-phase compilation model is able to be compiled as 2309263318fSAaron Ballmansoon as ``A.pcm`` is available, and thus can be compiled simultaneously as the 2319263318fSAaron Ballman``A.pcm`` to ``A.o`` compilation step. 232b1d5af81SChuanqi Xu 2339263318fSAaron BallmanFile name requirements 2349263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~ 235b1d5af81SChuanqi Xu 2369263318fSAaron BallmanBy convention, ``importable module unit`` files should use ``.cppm`` (or 2379263318fSAaron Ballman``.ccm``, ``.cxxm``, or ``.c++m``) as a file extension. 2389263318fSAaron Ballman``Module implementation unit`` files should use ``.cpp`` (or ``.cc``, ``.cxx``, 2399263318fSAaron Ballmanor ``.c++``) as a file extension. 240b1d5af81SChuanqi Xu 2419263318fSAaron BallmanA BMI should use ``.pcm`` as a file extension. The file name of the BMI for a 2429263318fSAaron Ballman``primary module interface unit`` should be ``module_name.pcm``. The file name 2439263318fSAaron Ballmanof a BMI for a ``module partition unit`` should be 2449263318fSAaron Ballman``module_name-partition_name.pcm``. 245b1d5af81SChuanqi Xu 2469263318fSAaron BallmanClang may fail to build the module if different extensions are used. For 2479263318fSAaron Ballmanexample, if the filename of an ``importable module unit`` ends with ``.cpp`` 2489263318fSAaron Ballmaninstead of ``.cppm``, then Clang cannot generate a BMI for the 2499263318fSAaron Ballman``importable module unit`` with the ``--precompile`` option because the 2509263318fSAaron Ballman``--precompile`` option would only run the preprocessor (``-E``). If using a 2519263318fSAaron Ballmandifferent extension than the conventional one for an ``importable module unit`` 2529263318fSAaron Ballmanyou can specify ``-x c++-module`` before the file. For example, 253b1d5af81SChuanqi Xu 254b1d5af81SChuanqi Xu.. code-block:: c++ 255b1d5af81SChuanqi Xu 256b1d5af81SChuanqi Xu // Hello.cpp 257b1d5af81SChuanqi Xu module; 258b1d5af81SChuanqi Xu #include <iostream> 259b1d5af81SChuanqi Xu export module Hello; 260b1d5af81SChuanqi Xu export void hello() { 261b1d5af81SChuanqi Xu std::cout << "Hello World!\n"; 262b1d5af81SChuanqi Xu } 263b1d5af81SChuanqi Xu 264b1d5af81SChuanqi Xu // use.cpp 265b1d5af81SChuanqi Xu import Hello; 266b1d5af81SChuanqi Xu int main() { 267b1d5af81SChuanqi Xu hello(); 268b1d5af81SChuanqi Xu return 0; 269b1d5af81SChuanqi Xu } 270b1d5af81SChuanqi Xu 2719263318fSAaron BallmanIn this example, the extension used by the ``module interface`` is ``.cpp`` 2729263318fSAaron Ballmaninstead of ``.cppm``, so it cannot be compiled like the previous example, but 2739263318fSAaron Ballmanit can be compiled with: 274b1d5af81SChuanqi Xu 275b1d5af81SChuanqi Xu.. code-block:: console 276b1d5af81SChuanqi Xu 277b1d5af81SChuanqi Xu $ clang++ -std=c++20 -x c++-module Hello.cpp --precompile -o Hello.pcm 278b1d5af81SChuanqi Xu $ clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out 279b1d5af81SChuanqi Xu $ ./Hello.out 280b1d5af81SChuanqi Xu Hello World! 281b1d5af81SChuanqi Xu 2829263318fSAaron BallmanModule name requirements 2839263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~ 28404fb3e3dSChuanqi Xu 2859263318fSAaron Ballman.. 28604fb3e3dSChuanqi Xu 2879263318fSAaron Ballman [module.unit]p1: 288de034cf3SChuanqi Xu 289de034cf3SChuanqi Xu All module-names either beginning with an identifier consisting of std followed by zero 29004fb3e3dSChuanqi Xu or more digits or containing a reserved identifier ([lex.name]) are reserved and shall not 29104fb3e3dSChuanqi Xu be specified in a module-declaration; no diagnostic is required. If any identifier in a reserved 29204fb3e3dSChuanqi Xu module-name is a reserved identifier, the module name is reserved for use by C++ implementations; 29304fb3e3dSChuanqi Xu otherwise it is reserved for future standardization. 29404fb3e3dSChuanqi Xu 2959263318fSAaron BallmanTherefore, none of the following names are valid by default: 29604fb3e3dSChuanqi Xu 29704fb3e3dSChuanqi Xu.. code-block:: text 29804fb3e3dSChuanqi Xu 29904fb3e3dSChuanqi Xu std 30004fb3e3dSChuanqi Xu std1 30104fb3e3dSChuanqi Xu std.foo 30204fb3e3dSChuanqi Xu __test 30304fb3e3dSChuanqi Xu // and so on ... 30404fb3e3dSChuanqi Xu 3059263318fSAaron BallmanUsing a reserved module name is strongly discouraged, but 3069263318fSAaron Ballman``-Wno-reserved-module-identifier`` can be used to suppress the warning. 30704fb3e3dSChuanqi Xu 3089263318fSAaron BallmanSpecifying dependent BMIs 3099263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~ 310b1d5af81SChuanqi Xu 3119263318fSAaron BallmanThere are 3 ways to specify a dependent BMI: 3121782e8f9SChuanqi Xu 3139263318fSAaron Ballman1. ``-fprebuilt-module-path=<path/to/directory>``. 3149263318fSAaron Ballman2. ``-fmodule-file=<path/to/BMI>`` (Deprecated). 3159263318fSAaron Ballman3. ``-fmodule-file=<module-name>=<path/to/BMI>``. 3161782e8f9SChuanqi Xu 3179263318fSAaron BallmanThe ``-fprebuilt-module-path`` option specifies the path to search for 3189263318fSAaron Ballmandependent BMIs. Multiple paths may be specified, similar to using ``-I`` to 3199263318fSAaron Ballmanspecify a search path for header files. When importing a module ``M``, the 3209263318fSAaron Ballmancompiler looks for ``M.pcm`` in the directories specified by 3219263318fSAaron Ballman``-fprebuilt-module-path``. Similarly, when importing a partition module unit 3229263318fSAaron Ballman``M:P``, the compiler looks for ``M-P.pcm`` in the directories specified by 3239263318fSAaron Ballman``-fprebuilt-module-path``. 324b1d5af81SChuanqi Xu 3259263318fSAaron BallmanThe ``-fmodule-file=<path/to/BMI>`` option causes the compiler to load the 3269263318fSAaron Ballmanspecified BMI directly. The ``-fmodule-file=<module-name>=<path/to/BMI>`` 3279263318fSAaron Ballmanoption causes the compiler to load the specified BMI for the module specified 3289263318fSAaron Ballmanby ``<module-name>`` when necessary. The main difference is that 3291782e8f9SChuanqi Xu``-fmodule-file=<path/to/BMI>`` will load the BMI eagerly, whereas 3309263318fSAaron Ballman``-fmodule-file=<module-name>=<path/to/BMI>`` will only load the BMI lazily, 3319263318fSAaron Ballmanas will ``-fprebuilt-module-path``. The ``-fmodule-file=<path/to/BMI>`` option 3329263318fSAaron Ballmanfor named modules is deprecated and will be removed in a future version of 3339263318fSAaron BallmanClang. 334b1d5af81SChuanqi Xu 3359263318fSAaron BallmanWhen these options are specified in the same invocation of the compiler, the 3369263318fSAaron Ballman``-fmodule-file=<path/to/BMI>`` option takes precedence over 3379263318fSAaron Ballman``-fmodule-file=<module-name>=<path/to/BMI>``, which takes precedence over 3389263318fSAaron Ballman``-fprebuilt-module-path=<path/to/directory>``. 3391782e8f9SChuanqi Xu 3409263318fSAaron BallmanNote: all dependant BMIs must be specified explicitly, either directly or 3419263318fSAaron Ballmanindirectly dependent BMIs explicitly. See 3429263318fSAaron Ballmanhttps://github.com/llvm/llvm-project/issues/62707 for details. 343a31a6007SChuanqi Xu 3449263318fSAaron BallmanWhen compiling a ``module implementation unit``, the BMI of the corresponding 3459263318fSAaron Ballman``primary module interface unit`` must be specified because a module 3469263318fSAaron Ballmanimplementation unit implicitly imports the primary module interface unit. 347b1d5af81SChuanqi Xu 348b1d5af81SChuanqi Xu [module.unit]p8 349b1d5af81SChuanqi Xu 350b1d5af81SChuanqi Xu A module-declaration that contains neither an export-keyword nor a module-partition implicitly 351b1d5af81SChuanqi Xu imports the primary module interface unit of the module as if by a module-import-declaration. 352b1d5af81SChuanqi Xu 3539263318fSAaron BallmanThe ``-fprebuilt-module-path=<path/to/directory>``, ``-fmodule-file=<path/to/BMI>``, 3549263318fSAaron Ballmanand ``-fmodule-file=<module-name>=<path/to/BMI>`` options may be specified 3559263318fSAaron Ballmanmultiple times. For example, the command line to compile ``M.cppm`` in 3569263318fSAaron Ballmanthe previous example could be rewritten as: 357b1d5af81SChuanqi Xu 358b1d5af81SChuanqi Xu.. code-block:: console 359b1d5af81SChuanqi Xu 3601782e8f9SChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -fmodule-file=M:interface_part=M-interface_part.pcm -fmodule-file=M:impl_part=M-impl_part.pcm -o M.pcm 361b1d5af81SChuanqi Xu 36222043643SChuanqi XuWhen there are multiple ``-fmodule-file=<module-name>=`` options for the same 3639263318fSAaron Ballman``<module-name>``, the last ``-fmodule-file=<module-name>=`` overrides the 3649263318fSAaron Ballmanprevious ``-fmodule-file=<module-name>=`` option. 365b1d5af81SChuanqi Xu 366b1d5af81SChuanqi XuRemember that module units still have an object counterpart to the BMI 367b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 368b1d5af81SChuanqi Xu 3699263318fSAaron BallmanWhile module interfaces resemble traditional header files, they still require 3709263318fSAaron Ballmancompilation. Module units are translation units, and need to be compiled to 3719263318fSAaron Ballmanobject files, which then need to be linked together as the following examples 3729263318fSAaron Ballmanshow. 373b1d5af81SChuanqi Xu 374b1d5af81SChuanqi XuFor example, the traditional compilation processes for headers are like: 375b1d5af81SChuanqi Xu 376b1d5af81SChuanqi Xu.. code-block:: text 377b1d5af81SChuanqi Xu 378b1d5af81SChuanqi Xu src1.cpp -+> clang++ src1.cpp --> src1.o ---, 379b1d5af81SChuanqi Xu hdr1.h --' +-> clang++ src1.o src2.o -> executable 380b1d5af81SChuanqi Xu hdr2.h --, | 381b1d5af81SChuanqi Xu src2.cpp -+> clang++ src2.cpp --> src2.o ---' 382b1d5af81SChuanqi Xu 383b1d5af81SChuanqi XuAnd the compilation process for module units are like: 384b1d5af81SChuanqi Xu 385b1d5af81SChuanqi Xu.. code-block:: text 386b1d5af81SChuanqi Xu 387b1d5af81SChuanqi Xu src1.cpp ----------------------------------------+> clang++ src1.cpp -------> src1.o -, 388b1d5af81SChuanqi Xu (header unit) hdr1.h -> clang++ hdr1.h ... -> hdr1.pcm --' +-> clang++ src1.o mod1.o src2.o -> executable 389b1d5af81SChuanqi Xu mod1.cppm -> clang++ mod1.cppm ... -> mod1.pcm --,--> clang++ mod1.pcm ... -> mod1.o -+ 390b1d5af81SChuanqi Xu src2.cpp ----------------------------------------+> clang++ src2.cpp -------> src2.o -' 391b1d5af81SChuanqi Xu 3929263318fSAaron BallmanAs the diagrams show, we need to compile the BMI from module units to object 3939263318fSAaron Ballmanfiles and then link the object files. (However, this cannot be done for the BMI 3949263318fSAaron Ballmanfrom header units. See the section on :ref:`header units <header-units>` for 3959263318fSAaron Ballmanmore details. 396b1d5af81SChuanqi Xu 3979263318fSAaron BallmanBMIs cannot be shipped in an archive to create a module library. Instead, the 3989263318fSAaron BallmanBMIs(``*.pcm``) are compiled into object files(``*.o``) and those object files 3999263318fSAaron Ballmanare added to the archive instead. 400b1d5af81SChuanqi Xu 401bd576fe3SSharadh Rajaramanclang-cl 402bd576fe3SSharadh Rajaraman~~~~~~~~ 403bd576fe3SSharadh Rajaraman 404bd576fe3SSharadh Rajaraman``clang-cl`` supports the same options as ``clang++`` for modules as detailed above; 405bd576fe3SSharadh Rajaramanthere is no need to prefix these options with ``/clang:``. Note that ``cl.exe`` 406bd576fe3SSharadh Rajaraman`options to emit/consume IFC files <https://devblogs.microsoft.com/cppblog/using-cpp-modules-in-msvc-from-the-command-line-part-1/>` are *not* supported. 407bd576fe3SSharadh RajaramanThe resultant precompiled modules are also not compatible for use with ``cl.exe``. 408bd576fe3SSharadh Rajaraman 409bd576fe3SSharadh RajaramanWe recommend that build system authors use the above-mentioned ``clang++`` options with ``clang-cl`` to build modules. 410bd576fe3SSharadh Rajaraman 4119263318fSAaron BallmanConsistency Requirements 4129263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~ 413b1d5af81SChuanqi Xu 4149263318fSAaron BallmanModules can be viewed as a kind of cache to speed up compilation. Thus, like 4159263318fSAaron Ballmanother caching techniques, it is important to maintain cache consistency which 4169263318fSAaron Ballmanis why Clang does very strict checking for consistency. 417b1d5af81SChuanqi Xu 418b1d5af81SChuanqi XuOptions consistency 419b1d5af81SChuanqi Xu^^^^^^^^^^^^^^^^^^^ 420b1d5af81SChuanqi Xu 4219263318fSAaron BallmanCompiler options related to the language dialect for a module unit and its 4229263318fSAaron Ballmannon-module-unit uses need to be consistent. Consider the following example: 423b1d5af81SChuanqi Xu 424b1d5af81SChuanqi Xu.. code-block:: c++ 425b1d5af81SChuanqi Xu 426b1d5af81SChuanqi Xu // M.cppm 427b1d5af81SChuanqi Xu export module M; 428b1d5af81SChuanqi Xu 429b1d5af81SChuanqi Xu // Use.cpp 430b1d5af81SChuanqi Xu import M; 431b1d5af81SChuanqi Xu 432b1d5af81SChuanqi Xu.. code-block:: console 433b1d5af81SChuanqi Xu 434b1d5af81SChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -o M.pcm 435ba15d186SMark de Wever $ clang++ -std=c++23 Use.cpp -fprebuilt-module-path=. 436b1d5af81SChuanqi Xu 4379263318fSAaron BallmanClang rejects the example due to the inconsistent language standard modes. Not 4389263318fSAaron Ballmanall compiler options are language dialect options, though. For example: 439b1d5af81SChuanqi Xu 440b1d5af81SChuanqi Xu.. code-block:: console 441b1d5af81SChuanqi Xu 442b1d5af81SChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -o M.pcm 443b1d5af81SChuanqi Xu # Inconsistent optimization level. 444b1d5af81SChuanqi Xu $ clang++ -std=c++20 -O3 Use.cpp -fprebuilt-module-path=. 445b1d5af81SChuanqi Xu # Inconsistent debugging level. 446b1d5af81SChuanqi Xu $ clang++ -std=c++20 -g Use.cpp -fprebuilt-module-path=. 447b1d5af81SChuanqi Xu 4489263318fSAaron BallmanAlthough the optimization and debugging levels are inconsistent, these 4499263318fSAaron Ballmancompilations are accepted because the compiler options do not impact the 4509263318fSAaron Ballmanlanguage dialect. 451b1d5af81SChuanqi Xu 4529263318fSAaron BallmanNote that the compiler **currently** doesn't reject inconsistent macro 4539263318fSAaron Ballmandefinitions (this may change in the future). For example: 454b1d5af81SChuanqi Xu 455b1d5af81SChuanqi Xu.. code-block:: console 456b1d5af81SChuanqi Xu 457b1d5af81SChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -o M.pcm 458b1d5af81SChuanqi Xu # Inconsistent optimization level. 459b1d5af81SChuanqi Xu $ clang++ -std=c++20 -O3 -DNDEBUG Use.cpp -fprebuilt-module-path=. 460b1d5af81SChuanqi Xu 4619263318fSAaron BallmanCurrently, Clang accepts the above example, though it may produce surprising 4629263318fSAaron Ballmanresults if the debugging code depends on consistent use of ``NDEBUG`` in other 4639263318fSAaron Ballmantranslation units. 464b1d5af81SChuanqi Xu 465f41f6ea1SChuanqi XuSource Files Consistency 466f41f6ea1SChuanqi Xu^^^^^^^^^^^^^^^^^^^^^^^^ 467f41f6ea1SChuanqi Xu 468f41f6ea1SChuanqi XuClang may open the input files\ :sup:`1`` of a BMI during the compilation. This implies that 469f41f6ea1SChuanqi Xuwhen Clang consumes a BMI, all the input files need to be present in the original path 470f41f6ea1SChuanqi Xuand with the original contents. 471f41f6ea1SChuanqi Xu 472f41f6ea1SChuanqi XuTo overcome these requirements and simplify cases like distributed builds and sandboxed 473f41f6ea1SChuanqi Xubuilds, users can use the ``-fmodules-embed-all-files`` flag to embed all input files 474f41f6ea1SChuanqi Xuinto the BMI so that Clang does not need to open the corresponding file on disk. 475f41f6ea1SChuanqi Xu 476f41f6ea1SChuanqi XuWhen the ``-fmodules-embed-all-files`` flag are enabled, Clang explicitly emits the source 477f41f6ea1SChuanqi Xucode into the BMI file, the contents of the BMI file contain a sufficiently verbose 478f41f6ea1SChuanqi Xurepresentation to reproduce the original source file. 479f41f6ea1SChuanqi Xu 480f41f6ea1SChuanqi Xu:sup:`1`` Input files: The source files which took part in the compilation of the BMI. 481f41f6ea1SChuanqi XuFor example: 482f41f6ea1SChuanqi Xu 483f41f6ea1SChuanqi Xu.. code-block:: c++ 484f41f6ea1SChuanqi Xu 485f41f6ea1SChuanqi Xu // M.cppm 486f41f6ea1SChuanqi Xu module; 487f41f6ea1SChuanqi Xu #include "foo.h" 488f41f6ea1SChuanqi Xu export module M; 489f41f6ea1SChuanqi Xu 490f41f6ea1SChuanqi Xu // foo.h 491f41f6ea1SChuanqi Xu #pragma once 492f41f6ea1SChuanqi Xu #include "bar.h" 493f41f6ea1SChuanqi Xu 494f41f6ea1SChuanqi XuThe ``M.cppm``, ``foo.h`` and ``bar.h`` are input files for the BMI of ``M.cppm``. 495f41f6ea1SChuanqi Xu 4969263318fSAaron BallmanObject definition consistency 4979263318fSAaron Ballman^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4988eea582dSChuanqi Xu 4999263318fSAaron BallmanThe C++ language requires that declarations of the same entity in different 5009263318fSAaron Ballmantranslation units have the same definition, which is known as the One 5019263318fSAaron BallmanDefinition Rule (ODR). Without modules, the compiler cannot perform strong ODR 5029263318fSAaron Ballmanviolation checking because it only sees one translation unit at a time. With 5039263318fSAaron Ballmanthe use of modules, the compiler can perform checks for ODR violations across 5049263318fSAaron Ballmantranslation units. 5058eea582dSChuanqi Xu 5069263318fSAaron BallmanHowever, the current ODR checking mechanisms are not perfect. There are a 5079263318fSAaron Ballmansignificant number of false positive ODR violation diagnostics, where the 5089263318fSAaron Ballmancompiler incorrectly diagnoses two identical declarations as having different 5099263318fSAaron Ballmandefinitions. Further, true positive ODR violations are not always reported. 5108eea582dSChuanqi Xu 5119263318fSAaron BallmanTo give a better user experience, improve compilation performance, and for 5129263318fSAaron Ballmanconsistency with MSVC, ODR checking of declarations in the global module 5139263318fSAaron Ballmanfragment is disabled by default. These checks can be enabled by specifying 5149263318fSAaron Ballman``-Xclang -fno-skip-odr-check-in-gmf`` when compiling. If the check is enabled 5159263318fSAaron Ballmanand you encounter incorrect or missing diagnostics, please report them via the 5169263318fSAaron Ballman`community issue tracker <https://github.com/llvm/llvm-project/issues/>`_. 5178eea582dSChuanqi Xu 518f41f6ea1SChuanqi XuPrivacy Issue 519f41f6ea1SChuanqi Xu------------- 520f41f6ea1SChuanqi Xu 521f41f6ea1SChuanqi XuBMIs are not and should not be treated as an information hiding mechanism. 522f41f6ea1SChuanqi XuThey should always be assumed to contain all the information that was used to 523f41f6ea1SChuanqi Xucreate them, in a recoverable form. 524f41f6ea1SChuanqi Xu 525b1d5af81SChuanqi XuABI Impacts 526b1d5af81SChuanqi Xu----------- 527b1d5af81SChuanqi Xu 5289263318fSAaron BallmanThis section describes the new ABI changes brought by modules. Only changes to 5299263318fSAaron Ballmanthe Itanium C++ ABI are covered. 530e7a8dd9bSChuanqi Xu 5319263318fSAaron BallmanName Mangling 5329263318fSAaron Ballman~~~~~~~~~~~~~ 533e7a8dd9bSChuanqi Xu 5349263318fSAaron BallmanThe declarations in a module unit which are not in the global module fragment 5359263318fSAaron Ballmanhave new linkage names. 536b1d5af81SChuanqi Xu 537b1d5af81SChuanqi XuFor example, 538b1d5af81SChuanqi Xu 539b1d5af81SChuanqi Xu.. code-block:: c++ 540b1d5af81SChuanqi Xu 541b1d5af81SChuanqi Xu export module M; 542b1d5af81SChuanqi Xu namespace NS { 543b1d5af81SChuanqi Xu export int foo(); 544b1d5af81SChuanqi Xu } 545b1d5af81SChuanqi Xu 5469263318fSAaron BallmanThe linkage name of ``NS::foo()`` is ``_ZN2NSW1M3fooEv``. This couldn't be 5479263318fSAaron Ballmandemangled by previous versions of the debugger or demangler. As of LLVM 15.x, 5489263318fSAaron Ballman``llvm-cxxfilt`` can be used to demangle this: 549b1d5af81SChuanqi Xu 550b1d5af81SChuanqi Xu.. code-block:: console 551b1d5af81SChuanqi Xu 552b1d5af81SChuanqi Xu $ llvm-cxxfilt _ZN2NSW1M3fooEv 5539263318fSAaron Ballman NS::foo@M() 554b1d5af81SChuanqi Xu 5559263318fSAaron BallmanThe result should be read as ``NS::foo()`` in module ``M``. 556b1d5af81SChuanqi Xu 5579263318fSAaron BallmanThe ABI implies that something cannot be declared in a module unit and defined 5589263318fSAaron Ballmanin a non-module unit (or vice-versa), as this would result in linking errors. 559b1d5af81SChuanqi Xu 5609263318fSAaron BallmanDespite this, it is possible to implement declarations with a compatible ABI in 5619263318fSAaron Ballmana module unit by using a language linkage specifier because the declarations in 5629263318fSAaron Ballmanthe language linkage specifier are attached to the global module fragment. For 5639263318fSAaron Ballmanexample: 564e264fe89SChuanqi Xu 565e264fe89SChuanqi Xu.. code-block:: c++ 566e264fe89SChuanqi Xu 567e264fe89SChuanqi Xu export module M; 568e264fe89SChuanqi Xu namespace NS { 569e264fe89SChuanqi Xu export extern "C++" int foo(); 570e264fe89SChuanqi Xu } 571e264fe89SChuanqi Xu 572e264fe89SChuanqi XuNow the linkage name of ``NS::foo()`` will be ``_ZN2NS3fooEv``. 573e264fe89SChuanqi Xu 574e7a8dd9bSChuanqi XuModule Initializers 575e7a8dd9bSChuanqi Xu~~~~~~~~~~~~~~~~~~~ 576e7a8dd9bSChuanqi Xu 5779263318fSAaron BallmanAll importable module units are required to emit an initializer function to 5789263318fSAaron Ballmanhandle the dynamic initialization of non-inline variables in the module unit. 5799263318fSAaron BallmanThe importable module unit has to emit the initializer even if there is no 5809263318fSAaron Ballmandynamic initialization; otherwise, the importer may call a nonexistent 5819263318fSAaron Ballmanfunction. The initializer function emits calls to imported modules first 5829263318fSAaron Ballmanfollowed by calls to all to of the dynamic initializers in the current module 5839263318fSAaron Ballmanunit. 584e7a8dd9bSChuanqi Xu 5859263318fSAaron BallmanTranslation units that explicitly or implicitly import a named module must call 5869263318fSAaron Ballmanthe initializer functions of the imported named module within the sequence of 5879263318fSAaron Ballmanthe dynamic initializers in the translation unit. Initializations of entities 5889263318fSAaron Ballmanat namespace scope are appearance-ordered. This (recursively) extends to 5899263318fSAaron Ballmanimported modules at the point of appearance of the import declaration. 590e7a8dd9bSChuanqi Xu 5919263318fSAaron BallmanIf the imported module is known to be empty, the call to its initializer may be 5929263318fSAaron Ballmanomitted. Additionally, if the imported module is known to have already been 5939263318fSAaron Ballmanimported, the call to its initializer may be omitted. 594e7a8dd9bSChuanqi Xu 595e6ecff8dSChuanqi XuReduced BMI 596e6ecff8dSChuanqi Xu----------- 597e6ecff8dSChuanqi Xu 5989263318fSAaron BallmanTo support the two-phase compilation model, Clang puts everything needed to 5999263318fSAaron Ballmanproduce an object into the BMI. However, other consumers of the BMI generally 6009263318fSAaron Ballmandon't need that information. This makes the BMI larger and may introduce 6019263318fSAaron Ballmanunnecessary dependencies for the BMI. To mitigate the problem, Clang has a 6029263318fSAaron Ballmancompiler option to reduce the information contained in the BMI. These two 6039263318fSAaron Ballmanformats are known as Full BMI and Reduced BMI, respectively. 604e6ecff8dSChuanqi Xu 605*411196b9SChuanqi XuUsers can use the ``-fmodules-reduced-bmi`` option to produce a 6069263318fSAaron BallmanReduced BMI. 607e6ecff8dSChuanqi Xu 6089263318fSAaron BallmanFor the one-phase compilation model (CMake implements this model), with 609*411196b9SChuanqi Xu``-fmodules-reduced-bmi``, the generated BMI will be a Reduced 6109263318fSAaron BallmanBMI automatically. (The output path of the BMI is specified by 6119263318fSAaron Ballman``-fmodule-output=`` as usual with the one-phase compilation model). 612e6ecff8dSChuanqi Xu 6139263318fSAaron BallmanIt is also possible to produce a Reduced BMI with the two-phase compilation 614*411196b9SChuanqi Xumodel. When ``-fmodules-reduced-bmi``, ``--precompile``, and 6159263318fSAaron Ballman``-fmodule-output=`` are specified, the generated BMI specified by ``-o`` will 6169263318fSAaron Ballmanbe a full BMI and the BMI specified by ``-fmodule-output=`` will be a Reduced 6179263318fSAaron BallmanBMI. The dependency graph in this case would look like: 618e6ecff8dSChuanqi Xu 619e6ecff8dSChuanqi Xu.. code-block:: none 620e6ecff8dSChuanqi Xu 621e6ecff8dSChuanqi Xu module-unit.cppm --> module-unit.full.pcm -> module-unit.o 622e6ecff8dSChuanqi Xu | 623e6ecff8dSChuanqi Xu -> module-unit.reduced.pcm -> consumer1.cpp 624e6ecff8dSChuanqi Xu -> consumer2.cpp 625e6ecff8dSChuanqi Xu -> ... 626e6ecff8dSChuanqi Xu -> consumer_n.cpp 627e6ecff8dSChuanqi Xu 628*411196b9SChuanqi XuClang does not emit diagnostics when ``-fmodules-reduced-bmi`` is 6299263318fSAaron Ballmanused with a non-module unit. This design permits users of the one-phase 6309263318fSAaron Ballmancompilation model to try using reduced BMIs without needing to modify the build 6319263318fSAaron Ballmansystem. The two-phase compilation module requires build system support. 632e6ecff8dSChuanqi Xu 6339263318fSAaron BallmanIn a Reduced BMI, Clang does not emit unreachable entities from the global 6349263318fSAaron Ballmanmodule fragment, or definitions of non-inline functions and non-inline 6359263318fSAaron Ballmanvariables. This may not be a transparent change. 6369263318fSAaron Ballman 6379263318fSAaron BallmanConsider the following example: 638e6ecff8dSChuanqi Xu 639e6ecff8dSChuanqi Xu.. code-block:: c++ 640e6ecff8dSChuanqi Xu 641e6ecff8dSChuanqi Xu // foo.h 642e6ecff8dSChuanqi Xu namespace N { 643e6ecff8dSChuanqi Xu struct X {}; 644e6ecff8dSChuanqi Xu int d(); 645e6ecff8dSChuanqi Xu int e(); 646e6ecff8dSChuanqi Xu inline int f(X, int = d()) { return e(); } 647e6ecff8dSChuanqi Xu int g(X); 648e6ecff8dSChuanqi Xu int h(X); 649e6ecff8dSChuanqi Xu } 650e6ecff8dSChuanqi Xu 651e6ecff8dSChuanqi Xu // M.cppm 652e6ecff8dSChuanqi Xu module; 653e6ecff8dSChuanqi Xu #include "foo.h" 654e6ecff8dSChuanqi Xu export module M; 655e6ecff8dSChuanqi Xu template<typename T> int use_f() { 656e6ecff8dSChuanqi Xu N::X x; // N::X, N, and :: are decl-reachable from use_f 657e6ecff8dSChuanqi Xu return f(x, 123); // N::f is decl-reachable from use_f, 658e6ecff8dSChuanqi Xu // N::e is indirectly decl-reachable from use_f 659e6ecff8dSChuanqi Xu // because it is decl-reachable from N::f, and 660e6ecff8dSChuanqi Xu // N::d is decl-reachable from use_f 661e6ecff8dSChuanqi Xu // because it is decl-reachable from N::f 662e6ecff8dSChuanqi Xu // even though it is not used in this call 663e6ecff8dSChuanqi Xu } 664e6ecff8dSChuanqi Xu template<typename T> int use_g() { 665e6ecff8dSChuanqi Xu N::X x; // N::X, N, and :: are decl-reachable from use_g 666e6ecff8dSChuanqi Xu return g((T(), x)); // N::g is not decl-reachable from use_g 667e6ecff8dSChuanqi Xu } 668e6ecff8dSChuanqi Xu template<typename T> int use_h() { 669e6ecff8dSChuanqi Xu N::X x; // N::X, N, and :: are decl-reachable from use_h 670e6ecff8dSChuanqi Xu return h((T(), x)); // N::h is not decl-reachable from use_h, but 671e6ecff8dSChuanqi Xu // N::h is decl-reachable from use_h<int> 672e6ecff8dSChuanqi Xu } 673e6ecff8dSChuanqi Xu int k = use_h<int>(); 674e6ecff8dSChuanqi Xu // use_h<int> is decl-reachable from k, so 675e6ecff8dSChuanqi Xu // N::h is decl-reachable from k 676e6ecff8dSChuanqi Xu 677e6ecff8dSChuanqi Xu // M-impl.cpp 678e6ecff8dSChuanqi Xu module M; 679e6ecff8dSChuanqi Xu int a = use_f<int>(); // OK 680e6ecff8dSChuanqi Xu int b = use_g<int>(); // error: no viable function for call to g; 681e6ecff8dSChuanqi Xu // g is not decl-reachable from purview of 682e6ecff8dSChuanqi Xu // module M's interface, so is discarded 683e6ecff8dSChuanqi Xu int c = use_h<int>(); // OK 684e6ecff8dSChuanqi Xu 6859263318fSAaron BallmanIn the above example, the function definition of ``N::g`` is elided from the 6869263318fSAaron BallmanReduced BMI of ``M.cppm``. Then the use of ``use_g<int>`` in ``M-impl.cpp`` 6879263318fSAaron Ballmanfails to instantiate. For such issues, users can add references to ``N::g`` in 6889263318fSAaron Ballmanthe `module purview <https://eel.is/c++draft/module.unit#5>`_ of ``M.cppm`` to 6899263318fSAaron Ballmanensure it is reachable, e.g. ``using N::g;``. 690e6ecff8dSChuanqi Xu 6919263318fSAaron BallmanSupport for Reduced BMIs is still experimental, but it may become the default 6929263318fSAaron Ballmanin the future. The expected roadmap for Reduced BMIs as of Clang 19.x is: 693e6ecff8dSChuanqi Xu 694*411196b9SChuanqi Xu1. ``-fexperimental-modules-reduced-bmi`` was introduced in v19.x 695*411196b9SChuanqi Xu2. For v20.x, ``-fmodules-reduced-bmi`` is introduced as an equivalent non-experimental 696*411196b9SChuanqi Xu option. It is expected to stay opt-in for 1~2 releases, though the period depends 6979263318fSAaron Ballman on user feedback and may be extended. 6989263318fSAaron Ballman3. Finally, ``-fmodules-reduced-bmi`` will be the default. When that time 6999263318fSAaron Ballman comes, the term BMI will refer to the Reduced BMI and the Full BMI will only 7009263318fSAaron Ballman be meaningful to build systems which elect to support two-phase compilation. 701e6ecff8dSChuanqi Xu 7026f710fefSChuanqi XuExperimental Non-Cascading Changes 7036f710fefSChuanqi Xu---------------------------------- 7046f710fefSChuanqi Xu 7056f710fefSChuanqi XuThis section is primarily for build system vendors. For end compiler users, 7066f710fefSChuanqi Xuif you don't want to read it all, this is helpful to reduce recompilations. 7076f710fefSChuanqi XuWe encourage build system vendors and end users try this out and bring feedback. 7086f710fefSChuanqi Xu 7096f710fefSChuanqi XuBefore Clang 19, a change in BMI of any (transitive) dependency would cause the 7106f710fefSChuanqi Xuoutputs of the BMI to change. Starting with Clang 19, changes to non-direct 7116f710fefSChuanqi Xudependencies should not directly affect the output BMI, unless they affect the 7126f710fefSChuanqi Xuresults of the compilations. We expect that there are many more opportunities 7136f710fefSChuanqi Xufor this optimization than we currently have realized and would appreaciate 7146f710fefSChuanqi Xufeedback about missed optimization opportunities. For example, 7156f710fefSChuanqi Xu 7166f710fefSChuanqi Xu.. code-block:: c++ 7176f710fefSChuanqi Xu 7186f710fefSChuanqi Xu // m-partA.cppm 7196f710fefSChuanqi Xu export module m:partA; 7206f710fefSChuanqi Xu 7216f710fefSChuanqi Xu // m-partB.cppm 7226f710fefSChuanqi Xu export module m:partB; 7236f710fefSChuanqi Xu export int getB() { return 44; } 7246f710fefSChuanqi Xu 7256f710fefSChuanqi Xu // m.cppm 7266f710fefSChuanqi Xu export module m; 7276f710fefSChuanqi Xu export import :partA; 7286f710fefSChuanqi Xu export import :partB; 7296f710fefSChuanqi Xu 7306f710fefSChuanqi Xu // useBOnly.cppm 7316f710fefSChuanqi Xu export module useBOnly; 7326f710fefSChuanqi Xu import m; 7336f710fefSChuanqi Xu export int B() { 7346f710fefSChuanqi Xu return getB(); 7356f710fefSChuanqi Xu } 7366f710fefSChuanqi Xu 7376f710fefSChuanqi Xu // Use.cc 7386f710fefSChuanqi Xu import useBOnly; 7396f710fefSChuanqi Xu int get() { 7406f710fefSChuanqi Xu return B(); 7416f710fefSChuanqi Xu } 7426f710fefSChuanqi Xu 7436f710fefSChuanqi XuTo compile the project (for brevity, some commands are omitted.): 7446f710fefSChuanqi Xu 7456f710fefSChuanqi Xu.. code-block:: console 7466f710fefSChuanqi Xu 7476f710fefSChuanqi Xu $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm 7486f710fefSChuanqi Xu $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm 7496f710fefSChuanqi Xu $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=. 7506f710fefSChuanqi Xu $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=. 7516f710fefSChuanqi Xu $ md5sum useBOnly.pcm 7526f710fefSChuanqi Xu 07656bf4a6908626795729295f9608da useBOnly.pcm 7536f710fefSChuanqi Xu 7546f710fefSChuanqi XuIf the interface of ``m-partA.cppm`` is changed to: 7556f710fefSChuanqi Xu 7566f710fefSChuanqi Xu.. code-block:: c++ 7576f710fefSChuanqi Xu 7586f710fefSChuanqi Xu // m-partA.v1.cppm 7596f710fefSChuanqi Xu export module m:partA; 7606f710fefSChuanqi Xu export int getA() { return 43; } 7616f710fefSChuanqi Xu 7626f710fefSChuanqi Xuand the BMI for ``useBOnly`` is recompiled as in: 7636f710fefSChuanqi Xu 7646f710fefSChuanqi Xu.. code-block:: console 7656f710fefSChuanqi Xu 7666f710fefSChuanqi Xu $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm 7676f710fefSChuanqi Xu $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm 7686f710fefSChuanqi Xu $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=. 7696f710fefSChuanqi Xu $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=. 7706f710fefSChuanqi Xu $ md5sum useBOnly.pcm 7716f710fefSChuanqi Xu 07656bf4a6908626795729295f9608da useBOnly.pcm 7726f710fefSChuanqi Xu 7736f710fefSChuanqi Xuthen the contents of ``useBOnly.pcm`` remain unchanged. 7746f710fefSChuanqi XuConsequently, if the build system only bases recompilation decisions on directly imported modules, 7756f710fefSChuanqi Xuit becomes possible to skip the recompilation of ``Use.cc``. 7766f710fefSChuanqi XuIt should be fine because the altered interfaces do not affect ``Use.cc`` in any way; 7776f710fefSChuanqi Xuthe changes do not cascade. 7786f710fefSChuanqi Xu 7796f710fefSChuanqi XuWhen ``Clang`` generates a BMI, it records the hash values of all potentially contributory BMIs 7806f710fefSChuanqi Xufor the BMI being produced. This ensures that build systems are not required to consider 7816f710fefSChuanqi Xutransitively imported modules when deciding whether to recompile. 7826f710fefSChuanqi Xu 7836f710fefSChuanqi XuWhat is considered to be a potential contributory BMIs is currently unspecified. 7846f710fefSChuanqi XuHowever, it is a severe bug for a BMI to remain unchanged following an observable change 7856f710fefSChuanqi Xuthat affects its consumers. 7866f710fefSChuanqi Xu 7876f710fefSChuanqi XuBuild systems may utilize this optimization by doing an update-if-changed operation to the BMI 7886f710fefSChuanqi Xuthat is consumed from the BMI that is output by the compiler. 7896f710fefSChuanqi Xu 7906f710fefSChuanqi XuWe encourage build systems to add an experimental mode that 7916f710fefSChuanqi Xureuses the cached BMI when **direct** dependencies did not change, 7926f710fefSChuanqi Xueven if **transitive** dependencies did change. 7936f710fefSChuanqi Xu 7946f710fefSChuanqi XuGiven there are potential compiler bugs, we recommend that build systems 7956f710fefSChuanqi Xusupport this feature as a configurable option so that users 7966f710fefSChuanqi Xucan go back to the transitive change mode safely at any time. 7976f710fefSChuanqi Xu 7986f710fefSChuanqi XuInteractions with Reduced BMI 7996f710fefSChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8006f710fefSChuanqi Xu 8016f710fefSChuanqi XuWith reduced BMI, non-cascading changes can be more powerful. For example, 8026f710fefSChuanqi Xu 8036f710fefSChuanqi Xu.. code-block:: c++ 8046f710fefSChuanqi Xu 8056f710fefSChuanqi Xu // A.cppm 8066f710fefSChuanqi Xu export module A; 8076f710fefSChuanqi Xu export int a() { return 44; } 8086f710fefSChuanqi Xu 8096f710fefSChuanqi Xu // B.cppm 8106f710fefSChuanqi Xu export module B; 8116f710fefSChuanqi Xu import A; 8126f710fefSChuanqi Xu export int b() { return a(); } 8136f710fefSChuanqi Xu 8146f710fefSChuanqi Xu.. code-block:: console 8156f710fefSChuanqi Xu 816*411196b9SChuanqi Xu $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fmodules-reduced-bmi -o A.o 817*411196b9SChuanqi Xu $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fmodules-reduced-bmi -o B.o -fmodule-file=A=A.pcm 8186f710fefSChuanqi Xu $ md5sum B.pcm 8196f710fefSChuanqi Xu 6c2bd452ca32ab418bf35cd141b060b9 B.pcm 8206f710fefSChuanqi Xu 8216f710fefSChuanqi XuAnd let's change the implementation for ``A.cppm`` into: 8226f710fefSChuanqi Xu 8236f710fefSChuanqi Xu.. code-block:: c++ 8246f710fefSChuanqi Xu 8256f710fefSChuanqi Xu export module A; 8266f710fefSChuanqi Xu int a_impl() { return 99; } 8276f710fefSChuanqi Xu export int a() { return a_impl(); } 8286f710fefSChuanqi Xu 8296f710fefSChuanqi Xuand recompile the example: 8306f710fefSChuanqi Xu 8316f710fefSChuanqi Xu.. code-block:: console 8326f710fefSChuanqi Xu 833*411196b9SChuanqi Xu $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fmodules-reduced-bmi -o A.o 834*411196b9SChuanqi Xu $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fmodules-reduced-bmi -o B.o -fmodule-file=A=A.pcm 8356f710fefSChuanqi Xu $ md5sum B.pcm 8366f710fefSChuanqi Xu 6c2bd452ca32ab418bf35cd141b060b9 B.pcm 8376f710fefSChuanqi Xu 8386f710fefSChuanqi XuWe should find the contents of ``B.pcm`` remains the same. In this case, the build system is 8396f710fefSChuanqi Xuallowed to skip recompilations of TUs which solely and directly depend on module ``B``. 8406f710fefSChuanqi Xu 8416f710fefSChuanqi XuThis only happens with a reduced BMI. With reduced BMIs, we won't record the function body 8426f710fefSChuanqi Xuof ``int b()`` in the BMI for ``B`` so that the module ``A`` doesn't contribute to the BMI of ``B`` 8436f710fefSChuanqi Xuand we have less dependencies. 8446f710fefSChuanqi Xu 8450d6ea6fcSChuanqi XuPerformance Tips 8460d6ea6fcSChuanqi Xu---------------- 8470d6ea6fcSChuanqi Xu 8480d6ea6fcSChuanqi XuReduce duplications 8490d6ea6fcSChuanqi Xu~~~~~~~~~~~~~~~~~~~ 8500d6ea6fcSChuanqi Xu 8519263318fSAaron BallmanWhile it is valid to have duplicated declarations in the global module fragments 8529263318fSAaron Ballmanof different module units, it is not free for Clang to deal with the duplicated 8539263318fSAaron Ballmandeclarations. A translation unit will compile more slowly if there is a lot of 8549263318fSAaron Ballmanduplicated declarations between the translation unit and modules it imports. 8559263318fSAaron BallmanFor example: 8560d6ea6fcSChuanqi Xu 8570d6ea6fcSChuanqi Xu.. code-block:: c++ 8580d6ea6fcSChuanqi Xu 8590d6ea6fcSChuanqi Xu // M-partA.cppm 8600d6ea6fcSChuanqi Xu module; 8610d6ea6fcSChuanqi Xu #include "big.header.h" 8620d6ea6fcSChuanqi Xu export module M:partA; 8630d6ea6fcSChuanqi Xu ... 8640d6ea6fcSChuanqi Xu 8650d6ea6fcSChuanqi Xu // M-partB.cppm 8660d6ea6fcSChuanqi Xu module; 8670d6ea6fcSChuanqi Xu #include "big.header.h" 8680d6ea6fcSChuanqi Xu export module M:partB; 8690d6ea6fcSChuanqi Xu ... 8700d6ea6fcSChuanqi Xu 8710d6ea6fcSChuanqi Xu // other partitions 8720d6ea6fcSChuanqi Xu ... 8730d6ea6fcSChuanqi Xu 8740d6ea6fcSChuanqi Xu // M-partZ.cppm 8750d6ea6fcSChuanqi Xu module; 8760d6ea6fcSChuanqi Xu #include "big.header.h" 8770d6ea6fcSChuanqi Xu export module M:partZ; 8780d6ea6fcSChuanqi Xu ... 8790d6ea6fcSChuanqi Xu 8800d6ea6fcSChuanqi Xu // M.cppm 8810d6ea6fcSChuanqi Xu export module M; 8820d6ea6fcSChuanqi Xu export import :partA; 8830d6ea6fcSChuanqi Xu export import :partB; 8840d6ea6fcSChuanqi Xu ... 8850d6ea6fcSChuanqi Xu export import :partZ; 8860d6ea6fcSChuanqi Xu 8870d6ea6fcSChuanqi Xu // use.cpp 8880d6ea6fcSChuanqi Xu import M; 8890d6ea6fcSChuanqi Xu ... // use declarations from module M. 8900d6ea6fcSChuanqi Xu 8919263318fSAaron BallmanWhen ``big.header.h`` is big enough and there are a lot of partitions, the 8929263318fSAaron Ballmancompilation of ``use.cpp`` may be significantly slower than the following 8939263318fSAaron Ballmanapproach: 8940d6ea6fcSChuanqi Xu 8950d6ea6fcSChuanqi Xu.. code-block:: c++ 8965e601ad3SChuanqi Xu 8970d6ea6fcSChuanqi Xu module; 8980d6ea6fcSChuanqi Xu #include "big.header.h" 8990d6ea6fcSChuanqi Xu export module m:big.header.wrapper; 9000d6ea6fcSChuanqi Xu export ... // export the needed declarations 9010d6ea6fcSChuanqi Xu 9020d6ea6fcSChuanqi Xu // M-partA.cppm 9030d6ea6fcSChuanqi Xu export module M:partA; 9040d6ea6fcSChuanqi Xu import :big.header.wrapper; 9050d6ea6fcSChuanqi Xu ... 9060d6ea6fcSChuanqi Xu 9070d6ea6fcSChuanqi Xu // M-partB.cppm 9080d6ea6fcSChuanqi Xu export module M:partB; 9090d6ea6fcSChuanqi Xu import :big.header.wrapper; 9100d6ea6fcSChuanqi Xu ... 9110d6ea6fcSChuanqi Xu 9120d6ea6fcSChuanqi Xu // other partitions 9130d6ea6fcSChuanqi Xu ... 9140d6ea6fcSChuanqi Xu 9150d6ea6fcSChuanqi Xu // M-partZ.cppm 9160d6ea6fcSChuanqi Xu export module M:partZ; 9170d6ea6fcSChuanqi Xu import :big.header.wrapper; 9180d6ea6fcSChuanqi Xu ... 9190d6ea6fcSChuanqi Xu 9200d6ea6fcSChuanqi Xu // M.cppm 9210d6ea6fcSChuanqi Xu export module M; 9220d6ea6fcSChuanqi Xu export import :partA; 9230d6ea6fcSChuanqi Xu export import :partB; 9240d6ea6fcSChuanqi Xu ... 9250d6ea6fcSChuanqi Xu export import :partZ; 9260d6ea6fcSChuanqi Xu 9270d6ea6fcSChuanqi Xu // use.cpp 9280d6ea6fcSChuanqi Xu import M; 9290d6ea6fcSChuanqi Xu ... // use declarations from module M. 9300d6ea6fcSChuanqi Xu 9319263318fSAaron BallmanReducing the duplication from textual includes is what improves compile-time 9329263318fSAaron Ballmanperformance. 9330d6ea6fcSChuanqi Xu 93488f9ac38SChuanqi XuTo help users to identify such issues, we add a warning ``-Wdecls-in-multiple-modules``. 93588f9ac38SChuanqi XuThis warning is disabled by default and it needs to be explicitly enabled or by ``-Weverything``. 93688f9ac38SChuanqi Xu 9379263318fSAaron BallmanTransitioning to modules 9389263318fSAaron Ballman------------------------ 939c8fab880SChuanqi Xu 9409263318fSAaron BallmanIt is best for new code and libraries to use modules from the start if 9419263318fSAaron Ballmanpossible. However, it may be a breaking change for existing code or libraries 9429263318fSAaron Ballmanto switch to modules. As a result, many existing libraries need to provide 9439263318fSAaron Ballmanboth headers and module interfaces for a while to not break existing users. 944c8fab880SChuanqi Xu 9459263318fSAaron BallmanThis section suggests some suggestions on how to ease the transition process 9469263318fSAaron Ballmanfor existing libraries. **Note that this information is only intended as 9479263318fSAaron Ballmanguidance, rather than as requirements to use modules in Clang.** It presumes 9489263318fSAaron Ballmanthe project is starting with no module-based dependencies. 949c8fab880SChuanqi Xu 950c8fab880SChuanqi XuABI non-breaking styles 951c8fab880SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~ 952c8fab880SChuanqi Xu 953c8fab880SChuanqi Xuexport-using style 954c8fab880SChuanqi Xu^^^^^^^^^^^^^^^^^^ 955c8fab880SChuanqi Xu 956c8fab880SChuanqi Xu.. code-block:: c++ 957c8fab880SChuanqi Xu 958c8fab880SChuanqi Xu module; 959c8fab880SChuanqi Xu #include "header_1.h" 960c8fab880SChuanqi Xu #include "header_2.h" 961c8fab880SChuanqi Xu ... 962c8fab880SChuanqi Xu #include "header_n.h" 963c8fab880SChuanqi Xu export module your_library; 964c8fab880SChuanqi Xu export namespace your_namespace { 965c8fab880SChuanqi Xu using decl_1; 966c8fab880SChuanqi Xu using decl_2; 967c8fab880SChuanqi Xu ... 968c8fab880SChuanqi Xu using decl_n; 969c8fab880SChuanqi Xu } 970c8fab880SChuanqi Xu 9719263318fSAaron BallmanThis example shows how to include all the headers containing declarations which 9729263318fSAaron Ballmanneed to be exported, and uses `using` declarations in an `export` block to 9739263318fSAaron Ballmanproduce the module interface. 974c8fab880SChuanqi Xu 975c8fab880SChuanqi Xuexport extern-C++ style 976c8fab880SChuanqi Xu^^^^^^^^^^^^^^^^^^^^^^^ 977c8fab880SChuanqi Xu 978c8fab880SChuanqi Xu.. code-block:: c++ 979c8fab880SChuanqi Xu 980c8fab880SChuanqi Xu module; 981c8fab880SChuanqi Xu #include "third_party/A/headers.h" 982c8fab880SChuanqi Xu #include "third_party/B/headers.h" 983c8fab880SChuanqi Xu ... 984c8fab880SChuanqi Xu #include "third_party/Z/headers.h" 985c8fab880SChuanqi Xu export module your_library; 986c8fab880SChuanqi Xu #define IN_MODULE_INTERFACE 987c8fab880SChuanqi Xu extern "C++" { 988c8fab880SChuanqi Xu #include "header_1.h" 989c8fab880SChuanqi Xu #include "header_2.h" 990c8fab880SChuanqi Xu ... 991c8fab880SChuanqi Xu #include "header_n.h" 992c8fab880SChuanqi Xu } 993c8fab880SChuanqi Xu 9949263318fSAaron BallmanHeaders (from ``header_1.h`` to ``header_n.h``) need to define the macro: 995c8fab880SChuanqi Xu 996c8fab880SChuanqi Xu.. code-block:: c++ 997c8fab880SChuanqi Xu 998c8fab880SChuanqi Xu #ifdef IN_MODULE_INTERFACE 999c8fab880SChuanqi Xu #define EXPORT export 1000c8fab880SChuanqi Xu #else 1001c8fab880SChuanqi Xu #define EXPORT 1002c8fab880SChuanqi Xu #endif 1003c8fab880SChuanqi Xu 10049263318fSAaron Ballmanand put ``EXPORT`` on the declarations you want to export. 1005c8fab880SChuanqi Xu 10069263318fSAaron BallmanAlso, it is recommended to refactor headers to include third-party headers 10079263318fSAaron Ballmanconditionally: 1008c8fab880SChuanqi Xu 1009c8fab880SChuanqi Xu.. code-block:: c++ 1010c8fab880SChuanqi Xu 1011c8fab880SChuanqi Xu #ifndef IN_MODULE_INTERFACE 1012c8fab880SChuanqi Xu #include "third_party/A/headers.h" 1013c8fab880SChuanqi Xu #endif 1014c8fab880SChuanqi Xu 1015c8fab880SChuanqi Xu #include "header_x.h" 1016c8fab880SChuanqi Xu 1017c8fab880SChuanqi Xu ... 1018c8fab880SChuanqi Xu 10199263318fSAaron BallmanThis can be helpful because it gives better diagnostic messages if the module 10209263318fSAaron Ballmaninterface unit is not properly updated when modifying code. 1021c8fab880SChuanqi Xu 10229263318fSAaron BallmanThis approach works because the declarations with language linkage are attached 10239263318fSAaron Ballmanto the global module. Thus, the ABI of the modular form of the library does not 10249263318fSAaron Ballmanchange. 1025c8fab880SChuanqi Xu 10269263318fSAaron BallmanWhile this style is more involved than the export-using style, it makes it 10279263318fSAaron Ballmaneasier to further refactor the library to other styles. 1028c8fab880SChuanqi Xu 1029c8fab880SChuanqi XuABI breaking style 1030c8fab880SChuanqi Xu~~~~~~~~~~~~~~~~~~ 1031c8fab880SChuanqi Xu 10329263318fSAaron BallmanThe term ``ABI breaking`` may sound like a bad approach. However, this style 10339263318fSAaron Ballmanforces consumers of the library use it in a consistent way. e.g., either always 10349263318fSAaron Ballmaninclude headers for the library or always import modules. The style prevents 10359263318fSAaron Ballmanthe ability to mix includes and imports for the library. 1036c8fab880SChuanqi Xu 10379263318fSAaron BallmanThe pattern for ABI breaking style is similar to the export extern-C++ style. 1038c8fab880SChuanqi Xu 1039c8fab880SChuanqi Xu.. code-block:: c++ 1040c8fab880SChuanqi Xu 1041c8fab880SChuanqi Xu module; 1042c8fab880SChuanqi Xu #include "third_party/A/headers.h" 1043c8fab880SChuanqi Xu #include "third_party/B/headers.h" 1044c8fab880SChuanqi Xu ... 1045c8fab880SChuanqi Xu #include "third_party/Z/headers.h" 1046c8fab880SChuanqi Xu export module your_library; 1047c8fab880SChuanqi Xu #define IN_MODULE_INTERFACE 1048c8fab880SChuanqi Xu #include "header_1.h" 1049c8fab880SChuanqi Xu #include "header_2.h" 1050c8fab880SChuanqi Xu ... 1051c8fab880SChuanqi Xu #include "header_n.h" 1052c8fab880SChuanqi Xu 1053c8fab880SChuanqi Xu #if the number of .cpp files in your project are small 1054c8fab880SChuanqi Xu module :private; 1055c8fab880SChuanqi Xu #include "source_1.cpp" 1056c8fab880SChuanqi Xu #include "source_2.cpp" 1057c8fab880SChuanqi Xu ... 1058c8fab880SChuanqi Xu #include "source_n.cpp" 1059c8fab880SChuanqi Xu #else // the number of .cpp files in your project are a lot 10609263318fSAaron Ballman // Using all the declarations from third-party libraries which are 1061c8fab880SChuanqi Xu // used in the .cpp files. 1062c8fab880SChuanqi Xu namespace third_party_namespace { 1063c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_1; 1064c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_2; 1065c8fab880SChuanqi Xu ... 1066c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_n; 1067c8fab880SChuanqi Xu } 1068c8fab880SChuanqi Xu #endif 1069c8fab880SChuanqi Xu 10709263318fSAaron Ballman(And add `EXPORT` and conditional include to the headers as suggested in the 10719263318fSAaron Ballmanexport extern-C++ style section.) 1072c8fab880SChuanqi Xu 10739263318fSAaron BallmanThe ABI with modules is different and thus we need to compile the source files 10749263318fSAaron Ballmaninto the new ABI. This is done by an additional part of the interface unit: 1075c8fab880SChuanqi Xu 1076c8fab880SChuanqi Xu.. code-block:: c++ 1077c8fab880SChuanqi Xu 1078c8fab880SChuanqi Xu #if the number of .cpp files in your project are small 1079c8fab880SChuanqi Xu module :private; 1080c8fab880SChuanqi Xu #include "source_1.cpp" 1081c8fab880SChuanqi Xu #include "source_2.cpp" 1082c8fab880SChuanqi Xu ... 1083c8fab880SChuanqi Xu #include "source_n.cpp" 1084c8fab880SChuanqi Xu #else // the number of .cpp files in your project are a lot 10859263318fSAaron Ballman // Using all the declarations from third-party libraries which are 1086c8fab880SChuanqi Xu // used in the .cpp files. 1087c8fab880SChuanqi Xu namespace third_party_namespace { 1088c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_1; 1089c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_2; 1090c8fab880SChuanqi Xu ... 1091c8fab880SChuanqi Xu using third_party_decl_used_in_cpp_n; 1092c8fab880SChuanqi Xu } 1093c8fab880SChuanqi Xu #endif 1094c8fab880SChuanqi Xu 10959263318fSAaron BallmanIf the number of source files is small, everything can be put in the private 10969263318fSAaron Ballmanmodule fragment directly (it is recommended to add conditional includes to the 10979263318fSAaron Ballmansource files as well). However, compile time performance will be bad if there 10989263318fSAaron Ballmanare a lot of source files to compile. 1099c8fab880SChuanqi Xu 11009263318fSAaron Ballman**Note that the private module fragment can only be in the primary module 11019263318fSAaron Ballmaninterface unit and the primary module interface unit containing the private 11029263318fSAaron Ballmanmodule fragment should be the only module unit of the corresponding module.** 1103c8fab880SChuanqi Xu 11049263318fSAaron BallmanIn this case, source files (.cpp files) must be converted to module 11059263318fSAaron Ballmanimplementation units: 1106c8fab880SChuanqi Xu 1107c8fab880SChuanqi Xu.. code-block:: c++ 1108c8fab880SChuanqi Xu 1109c8fab880SChuanqi Xu #ifndef IN_MODULE_INTERFACE 1110c8fab880SChuanqi Xu // List all the includes here. 1111c8fab880SChuanqi Xu #include "third_party/A/headers.h" 1112c8fab880SChuanqi Xu ... 1113c8fab880SChuanqi Xu #include "header.h" 1114c8fab880SChuanqi Xu #endif 1115c8fab880SChuanqi Xu 1116c8fab880SChuanqi Xu module your_library; 1117c8fab880SChuanqi Xu 1118c8fab880SChuanqi Xu // Following off should be unchanged. 1119c8fab880SChuanqi Xu ... 1120c8fab880SChuanqi Xu 11219263318fSAaron BallmanThe module implementation unit will import the primary module implicitly. Do 11229263318fSAaron Ballmannot include any headers in the module implementation units as it avoids 11239263318fSAaron Ballmanduplicated declarations between translation units. This is why non-exported 11249263318fSAaron Ballmanusing declarations should be added from third-party libraries in the primary 11259263318fSAaron Ballmanmodule interface unit. 1126c8fab880SChuanqi Xu 11279263318fSAaron BallmanIf the library is provided as ``libyour_library.so``, a modular library (e.g., 11289263318fSAaron Ballman``libyour_library_modules.so``) may also need to be provided for ABI 11299263318fSAaron Ballmancompatibility. 1130c8fab880SChuanqi Xu 11319263318fSAaron BallmanWhat if there are headers only included by the source files 11329263318fSAaron Ballman^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1133c8fab880SChuanqi Xu 11349263318fSAaron BallmanThe above practice may be problematic if there are headers only included by the 11359263318fSAaron Ballmansource files. When using a private module fragment, this issue may be solved by 11369263318fSAaron Ballmanincluding those headers in the private module fragment. While it is OK to solve 11379263318fSAaron Ballmanit by including the implementation headers in the module purview when using 11389263318fSAaron Ballmanimplementation module units, it may be suboptimal because the primary module 11399263318fSAaron Ballmaninterface units now contain entities that do not belong to the interface. 1140c8fab880SChuanqi Xu 11419263318fSAaron BallmanThis can potentially be improved by introducing a module partition 11429263318fSAaron Ballmanimplementation unit. An internal module partition unit is an importable 11439263318fSAaron Ballmanmodule unit which is internal to the module itself. 1144c8fab880SChuanqi Xu 1145c8fab880SChuanqi XuProviding a header to skip parsing redundant headers 1146c8fab880SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1147c8fab880SChuanqi Xu 11489263318fSAaron BallmanMany redeclarations shared between translation units causes Clang to have 11499263318fSAaron Ballmanslower compile-time performance. Further, there are known issues with 11509263318fSAaron Ballman`include after import <https://github.com/llvm/llvm-project/issues/61465>`_. 11519263318fSAaron BallmanEven when that issue is resolved, users may still get slower compilation speed 11529263318fSAaron Ballmanand larger BMIs. For these reasons, it is recommended to not include headers 11539263318fSAaron Ballmanafter importing the corresponding module. However, it is not always easy if the 11549263318fSAaron Ballmanlibrary is included by other dependencies, as in: 1155c8fab880SChuanqi Xu 1156c8fab880SChuanqi Xu.. code-block:: c++ 1157c8fab880SChuanqi Xu 1158c8fab880SChuanqi Xu #include "third_party/A.h" // #include "your_library/a_header.h" 1159c8fab880SChuanqi Xu import your_library; 1160c8fab880SChuanqi Xu 1161c8fab880SChuanqi Xuor 1162c8fab880SChuanqi Xu 1163c8fab880SChuanqi Xu.. code-block:: c++ 1164c8fab880SChuanqi Xu 1165c8fab880SChuanqi Xu import your_library; 1166c8fab880SChuanqi Xu #include "third_party/A.h" // #include "your_library/a_header.h" 1167c8fab880SChuanqi Xu 11689263318fSAaron BallmanFor such cases, it is best if the library providing both module and header 11699263318fSAaron Ballmaninterfaces also provides a header which skips parsing so that the library can 11709263318fSAaron Ballmanbe imported with the following approach that skips redundant redeclarations: 1171c8fab880SChuanqi Xu 1172c8fab880SChuanqi Xu.. code-block:: c++ 1173c8fab880SChuanqi Xu 1174c8fab880SChuanqi Xu import your_library; 1175c8fab880SChuanqi Xu #include "your_library_imported.h" 1176c8fab880SChuanqi Xu #include "third_party/A.h" // #include "your_library/a_header.h" but got skipped 1177c8fab880SChuanqi Xu 11789263318fSAaron BallmanThe implementation of ``your_library_imported.h`` can be a set of controlling 11799263318fSAaron Ballmanmacros or an overall controlling macro if using `#pragma once`. Then headers 11809263318fSAaron Ballmancan be refactored to: 1181c8fab880SChuanqi Xu 1182c8fab880SChuanqi Xu.. code-block:: c++ 1183c8fab880SChuanqi Xu 1184c8fab880SChuanqi Xu #pragma once 1185c8fab880SChuanqi Xu #ifndef YOUR_LIBRARY_IMPORTED 1186c8fab880SChuanqi Xu ... 1187c8fab880SChuanqi Xu #endif 1188c8fab880SChuanqi Xu 11899263318fSAaron BallmanIf the modules imported by the library provide such headers, remember to add 11909263318fSAaron Ballmanthem to ``your_library_imported.h`` too. 1191b014944eSChuanqi Xu 1192c8fab880SChuanqi XuImporting modules 1193c8fab880SChuanqi Xu~~~~~~~~~~~~~~~~~ 1194c8fab880SChuanqi Xu 11959263318fSAaron BallmanWhen there are dependent libraries providing modules, they should be imported 11969263318fSAaron Ballmanin your module as well. Many existing libraries will fall into this category 11979263318fSAaron Ballmanonce the ``std`` module is more widely available. 1198c8fab880SChuanqi Xu 1199c8fab880SChuanqi XuAll dependent libraries providing modules 1200c8fab880SChuanqi Xu^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1201c8fab880SChuanqi Xu 12029263318fSAaron BallmanOf course, most of the complexity disappears if all the dependent libraries 12039263318fSAaron Ballmanprovide modules. 1204c8fab880SChuanqi Xu 12059263318fSAaron BallmanHeaders need to be converted to include third-party headers conditionally. Then, 12069263318fSAaron Ballmanfor the export-using style: 1207c8fab880SChuanqi Xu 1208c8fab880SChuanqi Xu.. code-block:: c++ 1209c8fab880SChuanqi Xu 1210c8fab880SChuanqi Xu module; 1211c8fab880SChuanqi Xu import modules_from_third_party; 1212c8fab880SChuanqi Xu #define IN_MODULE_INTERFACE 1213c8fab880SChuanqi Xu #include "header_1.h" 1214c8fab880SChuanqi Xu #include "header_2.h" 1215c8fab880SChuanqi Xu ... 1216c8fab880SChuanqi Xu #include "header_n.h" 1217c8fab880SChuanqi Xu export module your_library; 1218c8fab880SChuanqi Xu export namespace your_namespace { 1219c8fab880SChuanqi Xu using decl_1; 1220c8fab880SChuanqi Xu using decl_2; 1221c8fab880SChuanqi Xu ... 1222c8fab880SChuanqi Xu using decl_n; 1223c8fab880SChuanqi Xu } 1224c8fab880SChuanqi Xu 12259263318fSAaron Ballmanor, for the export extern-C++ style: 1226c8fab880SChuanqi Xu 1227c8fab880SChuanqi Xu.. code-block:: c++ 1228c8fab880SChuanqi Xu 1229c8fab880SChuanqi Xu export module your_library; 1230c8fab880SChuanqi Xu import modules_from_third_party; 1231c8fab880SChuanqi Xu #define IN_MODULE_INTERFACE 1232c8fab880SChuanqi Xu extern "C++" { 1233c8fab880SChuanqi Xu #include "header_1.h" 1234c8fab880SChuanqi Xu #include "header_2.h" 1235c8fab880SChuanqi Xu ... 1236c8fab880SChuanqi Xu #include "header_n.h" 1237c8fab880SChuanqi Xu } 1238c8fab880SChuanqi Xu 12399263318fSAaron Ballmanor, for the ABI-breaking style, 1240c8fab880SChuanqi Xu 1241c8fab880SChuanqi Xu.. code-block:: c++ 1242c8fab880SChuanqi Xu 1243c8fab880SChuanqi Xu export module your_library; 1244c8fab880SChuanqi Xu import modules_from_third_party; 1245c8fab880SChuanqi Xu #define IN_MODULE_INTERFACE 1246c8fab880SChuanqi Xu #include "header_1.h" 1247c8fab880SChuanqi Xu #include "header_2.h" 1248c8fab880SChuanqi Xu ... 1249c8fab880SChuanqi Xu #include "header_n.h" 1250c8fab880SChuanqi Xu 1251c8fab880SChuanqi Xu #if the number of .cpp files in your project are small 1252c8fab880SChuanqi Xu module :private; 1253c8fab880SChuanqi Xu #include "source_1.cpp" 1254c8fab880SChuanqi Xu #include "source_2.cpp" 1255c8fab880SChuanqi Xu ... 1256c8fab880SChuanqi Xu #include "source_n.cpp" 1257c8fab880SChuanqi Xu #endif 1258c8fab880SChuanqi Xu 12599263318fSAaron BallmanNon-exported ``using`` declarations are unnecessary if using implementation 12609263318fSAaron Ballmanmodule units. Instead, third-party modules can be imported directly in 12619263318fSAaron Ballmanimplementation module units. 1262c8fab880SChuanqi Xu 1263c8fab880SChuanqi XuPartial dependent libraries providing modules 1264c8fab880SChuanqi Xu^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1265c8fab880SChuanqi Xu 12669263318fSAaron BallmanIf the library has to mix the use of ``include`` and ``import`` in its module, 12679263318fSAaron Ballmanthe primary goal is still the removal of duplicated declarations in translation 12689263318fSAaron Ballmanunits as much as possible. If the imported modules provide headers to skip 12699263318fSAaron Ballmanparsing their headers, those should be included after the import. If the 12709263318fSAaron Ballmanimported modules don't provide such a header, one can be made manually for 12719263318fSAaron Ballmanimproved compile time performance. 1272c8fab880SChuanqi Xu 127385b113c3SChuanqi XuReachability of internal partition units 127485b113c3SChuanqi Xu---------------------------------------- 127585b113c3SChuanqi Xu 127685b113c3SChuanqi XuThe internal partition units are sometimes called implementation partition units in other documentation. 127785b113c3SChuanqi XuHowever, the name may be confusing since implementation partition units are not implementation 127885b113c3SChuanqi Xuunits. 127985b113c3SChuanqi Xu 128085b113c3SChuanqi XuAccording to `[module.reach]p1 <https://eel.is/c++draft/module.reach#1>`_ and 128185b113c3SChuanqi Xu`[module.reach]p2 <https://eel.is/c++draft/module.reach#2>`_ (from N4986): 128285b113c3SChuanqi Xu 128385b113c3SChuanqi Xu A translation unit U is necessarily reachable from a point P if U is a module 128485b113c3SChuanqi Xu interface unit on which the translation unit containing P has an interface 128585b113c3SChuanqi Xu dependency, or the translation unit containing P imports U, in either case 128685b113c3SChuanqi Xu prior to P. 128785b113c3SChuanqi Xu 128885b113c3SChuanqi Xu All translation units that are necessarily reachable are reachable. Additional 128985b113c3SChuanqi Xu translation units on which the point within the program has an interface 129085b113c3SChuanqi Xu dependency may be considered reachable, but it is unspecified which are and 129185b113c3SChuanqi Xu under what circumstances. 129285b113c3SChuanqi Xu 129385b113c3SChuanqi XuFor example, 129485b113c3SChuanqi Xu 129585b113c3SChuanqi Xu.. code-block:: c++ 129685b113c3SChuanqi Xu 129785b113c3SChuanqi Xu // a.cpp 129885b113c3SChuanqi Xu import B; 129985b113c3SChuanqi Xu int main() 130085b113c3SChuanqi Xu { 130185b113c3SChuanqi Xu g<void>(); 130285b113c3SChuanqi Xu } 130385b113c3SChuanqi Xu 130485b113c3SChuanqi Xu // b.cppm 130585b113c3SChuanqi Xu export module B; 130685b113c3SChuanqi Xu import :C; 130785b113c3SChuanqi Xu export template <typename T> inline void g() noexcept 130885b113c3SChuanqi Xu { 130985b113c3SChuanqi Xu return f<T>(); 131085b113c3SChuanqi Xu } 131185b113c3SChuanqi Xu 131285b113c3SChuanqi Xu // c.cppm 131385b113c3SChuanqi Xu module B:C; 131485b113c3SChuanqi Xu template<typename> inline void f() noexcept {} 131585b113c3SChuanqi Xu 131685b113c3SChuanqi XuThe internal partition unit ``c.cppm`` is not necessarily reachable by 131785b113c3SChuanqi Xu``a.cpp`` because ``c.cppm`` is not a module interface unit and ``a.cpp`` 131885b113c3SChuanqi Xudoesn't import ``c.cppm``. This leaves it up to the compiler to decide if 131985b113c3SChuanqi Xu``c.cppm`` is reachable by ``a.cpp`` or not. Clang's behavior is that 132085b113c3SChuanqi Xuindirectly imported internal partition units are not reachable. 132185b113c3SChuanqi Xu 132285b113c3SChuanqi XuThe suggested approach for using an internal partition unit in Clang is 132385b113c3SChuanqi Xuto only import them in the implementation unit. 132485b113c3SChuanqi Xu 13259263318fSAaron BallmanKnown Issues 13269263318fSAaron Ballman------------ 1327b1d5af81SChuanqi Xu 13289263318fSAaron BallmanThe following describes issues in the current implementation of modules. Please 13299263318fSAaron Ballmansee 13309263318fSAaron Ballman`the issues list for modules <https://github.com/llvm/llvm-project/labels/clang%3Amodules>`_ 13319263318fSAaron Ballmanfor a list of issues or to file a new issue if you don't find an existing one. 13329263318fSAaron BallmanWhen creating a new issue for standard C++ modules, please start the title with 13339263318fSAaron Ballman``[C++20] [Modules]`` (or ``[C++23] [Modules]``, etc) and add the label 13349263318fSAaron Ballman``clang:modules`` if possible. 1335b1d5af81SChuanqi Xu 13369263318fSAaron BallmanA high-level overview of support for standards features, including modules, can 13379263318fSAaron Ballmanbe found on the `C++ Feature Status <https://clang.llvm.org/cxx_status.html>`_ 13389263318fSAaron Ballmanpage. 1339b1d5af81SChuanqi Xu 13409263318fSAaron BallmanIncluding headers after import is not well-supported 13419263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1342684955a2SChuanqi Xu 13439263318fSAaron BallmanThe following example is accepted: 1344684955a2SChuanqi Xu 1345684955a2SChuanqi Xu.. code-block:: c++ 1346684955a2SChuanqi Xu 1347684955a2SChuanqi Xu #include <iostream> 1348684955a2SChuanqi Xu import foo; // assume module 'foo' contain the declarations from `<iostream>` 1349684955a2SChuanqi Xu 1350684955a2SChuanqi Xu int main(int argc, char *argv[]) 1351684955a2SChuanqi Xu { 1352684955a2SChuanqi Xu std::cout << "Test\n"; 1353684955a2SChuanqi Xu return 0; 1354684955a2SChuanqi Xu } 1355684955a2SChuanqi Xu 13569263318fSAaron Ballmanbut if the order of ``#include <iostream>`` and ``import foo;`` is reversed, 13579263318fSAaron Ballmanthen the code is currently rejected: 1358684955a2SChuanqi Xu 1359684955a2SChuanqi Xu.. code-block:: c++ 1360684955a2SChuanqi Xu 1361684955a2SChuanqi Xu import foo; // assume module 'foo' contain the declarations from `<iostream>` 1362684955a2SChuanqi Xu #include <iostream> 1363684955a2SChuanqi Xu 1364684955a2SChuanqi Xu int main(int argc, char *argv[]) 1365684955a2SChuanqi Xu { 1366684955a2SChuanqi Xu std::cout << "Test\n"; 1367684955a2SChuanqi Xu return 0; 1368684955a2SChuanqi Xu } 1369684955a2SChuanqi Xu 1370684955a2SChuanqi XuBoth of the above examples should be accepted. 1371684955a2SChuanqi Xu 13729263318fSAaron BallmanThis is a limitation of the implementation. In the first example, the compiler 13739263318fSAaron Ballmanwill see and parse ``<iostream>`` first then it will see the ``import``. In 13749263318fSAaron Ballmanthis case, ODR checking and declaration merging will happen in the 13759263318fSAaron Ballmandeserializer. In the second example, the compiler will see the ``import`` first 13769263318fSAaron Ballmanand the ``#include`` second which results in ODR checking and declarations 13779263318fSAaron Ballmanmerging happening in the semantic analyzer. This is due to a divergence in the 13789263318fSAaron Ballmanimplementation path. This is tracked by 13799263318fSAaron Ballman`#61465 <https://github.com/llvm/llvm-project/issues/61465>`_. 1380684955a2SChuanqi Xu 13819263318fSAaron BallmanIgnored ``preferred_name`` Attribute 13829263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1383684955a2SChuanqi Xu 13849263318fSAaron BallmanWhen Clang writes BMIs, it will ignore the ``preferred_name`` attribute on 13859263318fSAaron Ballmandeclarations which use it. Thus, the preferred name will not be displayed in 13869263318fSAaron Ballmanthe debugger as expected. This is tracked by 13879263318fSAaron Ballman`#56490 <https://github.com/llvm/llvm-project/issues/56490>`_. 1388b1d5af81SChuanqi Xu 1389b1d5af81SChuanqi XuDon't emit macros about module declaration 1390b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1391b1d5af81SChuanqi Xu 13929263318fSAaron BallmanThis is covered by `P1857R3 <https://wg21.link/P1857R3>`_. It is mentioned here 13939263318fSAaron Ballmanbecause we want users to be aware that we don't yet implement it. 1394b1d5af81SChuanqi Xu 13959263318fSAaron BallmanA direct approach to write code that can be compiled by both modules and 13969263318fSAaron Ballmannon-module builds may look like: 1397b1d5af81SChuanqi Xu 1398b1d5af81SChuanqi Xu.. code-block:: c++ 1399b1d5af81SChuanqi Xu 1400b1d5af81SChuanqi Xu MODULE 1401b1d5af81SChuanqi Xu IMPORT header_name 1402b1d5af81SChuanqi Xu EXPORT_MODULE MODULE_NAME; 1403b1d5af81SChuanqi Xu IMPORT header_name 1404b1d5af81SChuanqi Xu EXPORT ... 1405b1d5af81SChuanqi Xu 14069263318fSAaron BallmanThe intent of this is that this file can be compiled like a module unit or a 14079263318fSAaron Ballmannon-module unit depending on the definition of some macros. However, this usage 14089263318fSAaron Ballmanis forbidden by P1857R3 which is not yet implemented in Clang. This means that 14099263318fSAaron Ballmanis possible to write invalid modules which will no longer be accepted once 14109263318fSAaron BallmanP1857R3 is implemented. This is tracked by 1411ded6dd24Sh-vetinari`#54047 <https://github.com/llvm/llvm-project/issues/54047>`_. 1412b1d5af81SChuanqi Xu 14139263318fSAaron BallmanUntil then, it is recommended not to mix macros with module declarations. 14149263318fSAaron Ballman 1415b1d5af81SChuanqi Xu 1416b1d5af81SChuanqi XuIn consistent filename suffix requirement for importable module units 1417b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1418b1d5af81SChuanqi Xu 14199263318fSAaron BallmanCurrently, Clang requires the file name of an ``importable module unit`` to 14209263318fSAaron Ballmanhave ``.cppm`` (or ``.ccm``, ``.cxxm``, ``.c++m``) as the file extension. 14219263318fSAaron BallmanHowever, the behavior is inconsistent with other compilers. This is tracked by 14229263318fSAaron Ballman`#57416 <https://github.com/llvm/llvm-project/issues/57416>`_. 1423b1d5af81SChuanqi Xu 14249263318fSAaron BallmanIncorrect ODR violation diagnostics 14259263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14263b48613fSChuanqi Xu 14279263318fSAaron BallmanODR violations are a common issue when using modules. Clang sometimes produces 14289263318fSAaron Ballmanfalse-positive diagnostics or fails to produce true-positive diagnostics of the 14299263318fSAaron BallmanOne Definition Rule. One often-reported example is: 1430a31a6007SChuanqi Xu 1431a31a6007SChuanqi Xu.. code-block:: c++ 1432a31a6007SChuanqi Xu 1433a31a6007SChuanqi Xu // part.cc 1434a31a6007SChuanqi Xu module; 1435a31a6007SChuanqi Xu typedef long T; 1436a31a6007SChuanqi Xu namespace ns { 1437a31a6007SChuanqi Xu inline void fun() { 1438a31a6007SChuanqi Xu (void)(T)0; 1439a31a6007SChuanqi Xu } 1440a31a6007SChuanqi Xu } 1441a31a6007SChuanqi Xu export module repro:part; 1442a31a6007SChuanqi Xu 1443a31a6007SChuanqi Xu // repro.cc 1444a31a6007SChuanqi Xu module; 1445a31a6007SChuanqi Xu typedef long T; 1446a31a6007SChuanqi Xu namespace ns { 1447a31a6007SChuanqi Xu using ::T; 1448a31a6007SChuanqi Xu } 1449a31a6007SChuanqi Xu namespace ns { 1450a31a6007SChuanqi Xu inline void fun() { 1451a31a6007SChuanqi Xu (void)(T)0; 1452a31a6007SChuanqi Xu } 1453a31a6007SChuanqi Xu } 1454a31a6007SChuanqi Xu export module repro; 1455a31a6007SChuanqi Xu export import :part; 1456a31a6007SChuanqi Xu 14579263318fSAaron BallmanCurrently the compiler incorrectly diagnoses the inconsistent definition of 14589263318fSAaron Ballman``fun()`` in two module units. Because both definitions of ``fun()`` have the 14599263318fSAaron Ballmansame spelling and ``T`` refers to the same type entity, there is no ODR 14609263318fSAaron Ballmanviolation. This is tracked by 14619263318fSAaron Ballman`#78850 <https://github.com/llvm/llvm-project/issues/78850>`_. 1462a31a6007SChuanqi Xu 1463a31a6007SChuanqi XuUsing TU-local entity in other units 1464a31a6007SChuanqi Xu~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1465a31a6007SChuanqi Xu 14669263318fSAaron BallmanModule units are translation units, so the entities which should be local to 14679263318fSAaron Ballmanthe module unit itself should never be used by other units. 1468a31a6007SChuanqi Xu 14699263318fSAaron BallmanThe C++ standard defines the concept of ``TU-local`` and ``exposure`` in 1470a31a6007SChuanqi Xu`basic.link/p14 <https://eel.is/c++draft/basic.link#14>`_, 1471a31a6007SChuanqi Xu`basic.link/p15 <https://eel.is/c++draft/basic.link#15>`_, 1472a31a6007SChuanqi Xu`basic.link/p16 <https://eel.is/c++draft/basic.link#16>`_, 14739263318fSAaron Ballman`basic.link/p17 <https://eel.is/c++draft/basic.link#17>`_, and 1474a31a6007SChuanqi Xu`basic.link/p18 <https://eel.is/c++draft/basic.link#18>`_. 1475a31a6007SChuanqi Xu 14769263318fSAaron BallmanHowever, Clang doesn't formally support these two concepts. This results in 14779263318fSAaron Ballmanunclear or confusing diagnostic messages. Further, Clang may import 14789263318fSAaron Ballman``TU-local`` entities to other units without any diagnostics. This is tracked 14799263318fSAaron Ballmanby `#78173 <https://github.com/llvm/llvm-project/issues/78173>`_. 1480a31a6007SChuanqi Xu 14819263318fSAaron Ballman.. _header-units: 1482be72dca5SChuanqi Xu 1483b1d5af81SChuanqi XuHeader Units 1484b1d5af81SChuanqi Xu============ 1485b1d5af81SChuanqi Xu 14869263318fSAaron BallmanHow to build projects using header units 14879263318fSAaron Ballman---------------------------------------- 1488b1d5af81SChuanqi Xu 148920d9aa1aSChuanqi Xu.. warning:: 149020d9aa1aSChuanqi Xu 14919263318fSAaron Ballman The support for header units, including related command line options, is 14929263318fSAaron Ballman experimental. There are still many unanswered question about how tools 14939263318fSAaron Ballman should interact with header units. The details described here may change in 14949263318fSAaron Ballman the future. 149520d9aa1aSChuanqi Xu 1496b1d5af81SChuanqi XuQuick Start 1497b1d5af81SChuanqi Xu~~~~~~~~~~~ 1498b1d5af81SChuanqi Xu 14999263318fSAaron BallmanThe following example: 1500b1d5af81SChuanqi Xu 1501b1d5af81SChuanqi Xu.. code-block:: c++ 1502b1d5af81SChuanqi Xu 1503b1d5af81SChuanqi Xu import <iostream>; 1504b1d5af81SChuanqi Xu int main() { 1505b1d5af81SChuanqi Xu std::cout << "Hello World.\n"; 1506b1d5af81SChuanqi Xu } 1507b1d5af81SChuanqi Xu 15089263318fSAaron Ballmancould be compiled with: 1509b1d5af81SChuanqi Xu 1510b1d5af81SChuanqi Xu.. code-block:: console 1511b1d5af81SChuanqi Xu 1512b1d5af81SChuanqi Xu $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm 1513b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-file=iostream.pcm main.cpp 1514b1d5af81SChuanqi Xu 1515b1d5af81SChuanqi XuHow to produce BMIs 1516b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~ 1517b1d5af81SChuanqi Xu 15189263318fSAaron BallmanSimilar to named modules, ``--precompile`` can be used to produce a BMI. 15199263318fSAaron BallmanHowever, that requires specifying that the input file is a header by using 15209263318fSAaron Ballman``-xc++-system-header`` or ``-xc++-user-header``. 1521b1d5af81SChuanqi Xu 15229263318fSAaron BallmanThe ``-fmodule-header={user,system}`` option can also be used to produce a BMI 15239263318fSAaron Ballmanfor header units which have a file extension like `.h` or `.hh`. The argument to 15249263318fSAaron Ballman``-fmodule-header`` specifies either the user search path or the system search 15259263318fSAaron Ballmanpath. The default value for ``-fmodule-header`` is ``user``. For example: 1526b1d5af81SChuanqi Xu 1527b1d5af81SChuanqi Xu.. code-block:: c++ 1528b1d5af81SChuanqi Xu 1529b1d5af81SChuanqi Xu // foo.h 1530b1d5af81SChuanqi Xu #include <iostream> 1531b1d5af81SChuanqi Xu void Hello() { 1532b1d5af81SChuanqi Xu std::cout << "Hello World.\n"; 1533b1d5af81SChuanqi Xu } 1534b1d5af81SChuanqi Xu 1535b1d5af81SChuanqi Xu // use.cpp 1536b1d5af81SChuanqi Xu import "foo.h"; 1537b1d5af81SChuanqi Xu int main() { 1538b1d5af81SChuanqi Xu Hello(); 1539b1d5af81SChuanqi Xu } 1540b1d5af81SChuanqi Xu 15419263318fSAaron Ballmancould be compiled with: 1542b1d5af81SChuanqi Xu 1543b1d5af81SChuanqi Xu.. code-block:: console 1544b1d5af81SChuanqi Xu 1545b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-header foo.h -o foo.pcm 1546b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-file=foo.pcm use.cpp 1547b1d5af81SChuanqi Xu 15489263318fSAaron BallmanFor headers which do not have a file extension, ``-xc++-header`` (or 15499263318fSAaron Ballman``-xc++-system-header``, ``-xc++-user-header``) must be used to specify the 15509263318fSAaron Ballmanfile as a header. For example: 1551b1d5af81SChuanqi Xu 1552b1d5af81SChuanqi Xu.. code-block:: c++ 1553b1d5af81SChuanqi Xu 1554b1d5af81SChuanqi Xu // use.cpp 1555b1d5af81SChuanqi Xu import "foo.h"; 1556b1d5af81SChuanqi Xu int main() { 1557b1d5af81SChuanqi Xu Hello(); 1558b1d5af81SChuanqi Xu } 1559b1d5af81SChuanqi Xu 1560b1d5af81SChuanqi Xu.. code-block:: console 1561b1d5af81SChuanqi Xu 1562b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-header=system -xc++-header iostream -o iostream.pcm 1563b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-file=iostream.pcm use.cpp 1564b1d5af81SChuanqi Xu 15659263318fSAaron BallmanHow to specify dependent BMIs 15669263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1567b1d5af81SChuanqi Xu 15689263318fSAaron Ballman``-fmodule-file`` can be used to specify a dependent BMI (or multiple times for 15699263318fSAaron Ballmanmore than one dependent BMI). 1570b1d5af81SChuanqi Xu 15719263318fSAaron BallmanWith the existing implementation, ``-fprebuilt-module-path`` cannot be used for 15729263318fSAaron Ballmanheader units (because they are nominally anonymous). For header units, use 15739263318fSAaron Ballman``-fmodule-file`` to include the relevant PCM file for each header unit. 1574b1d5af81SChuanqi Xu 15759263318fSAaron BallmanThis is expect to be solved in a future version of Clang either by the compiler 15769263318fSAaron Ballmanfinding and specifying ``-fmodule-file`` automatically, or by the use of a 15779263318fSAaron Ballmanmodule-mapper that understands how to map the header name to their PCMs. 1578b1d5af81SChuanqi Xu 15799263318fSAaron BallmanCompiling a header unit to an object file 15809263318fSAaron Ballman~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1581b1d5af81SChuanqi Xu 15829263318fSAaron BallmanA header unit cannot be compiled to an object file due to the semantics of 15839263318fSAaron Ballmanheader units. For example: 1584b1d5af81SChuanqi Xu 1585b1d5af81SChuanqi Xu.. code-block:: console 1586b1d5af81SChuanqi Xu 1587b1d5af81SChuanqi Xu $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm 1588b1d5af81SChuanqi Xu # This is not allowed! 1589b1d5af81SChuanqi Xu $ clang++ iostream.pcm -c -o iostream.o 1590b1d5af81SChuanqi Xu 1591b1d5af81SChuanqi XuInclude translation 1592b1d5af81SChuanqi Xu~~~~~~~~~~~~~~~~~~~ 1593b1d5af81SChuanqi Xu 15949263318fSAaron BallmanThe C++ standard allows vendors to convert ``#include header-name`` to 15959263318fSAaron Ballman``import header-name;`` when possible. Currently, Clang does this translation 15969263318fSAaron Ballmanfor the ``#include`` in the global module fragment. For example, the following 15979263318fSAaron Ballmanexample: 1598b1d5af81SChuanqi Xu 1599b1d5af81SChuanqi Xu.. code-block:: c++ 1600b1d5af81SChuanqi Xu 1601b1d5af81SChuanqi Xu module; 1602b1d5af81SChuanqi Xu import <iostream>; 1603b1d5af81SChuanqi Xu export module M; 1604b1d5af81SChuanqi Xu export void Hello() { 1605b1d5af81SChuanqi Xu std::cout << "Hello.\n"; 1606b1d5af81SChuanqi Xu } 1607b1d5af81SChuanqi Xu 16089263318fSAaron Ballmanis the same as this example: 1609b1d5af81SChuanqi Xu 1610b1d5af81SChuanqi Xu.. code-block:: c++ 1611b1d5af81SChuanqi Xu 1612b1d5af81SChuanqi Xu module; 1613b1d5af81SChuanqi Xu #include <iostream> 1614b1d5af81SChuanqi Xu export module M; 1615b1d5af81SChuanqi Xu export void Hello() { 1616b1d5af81SChuanqi Xu std::cout << "Hello.\n"; 1617b1d5af81SChuanqi Xu } 1618b1d5af81SChuanqi Xu 1619b1d5af81SChuanqi Xu.. code-block:: console 1620b1d5af81SChuanqi Xu 1621b1d5af81SChuanqi Xu $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm 1622b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fmodule-file=iostream.pcm --precompile M.cppm -o M.cpp 1623b1d5af81SChuanqi Xu 16249263318fSAaron BallmanIn the latter example, Clang can find the BMI for ``<iostream>`` and so it 16259263318fSAaron Ballmantries to replace the ``#include <iostream>`` with ``import <iostream>;`` 16269263318fSAaron Ballmanautomatically. 1627b1d5af81SChuanqi Xu 1628b1d5af81SChuanqi Xu 16299263318fSAaron BallmanDifferences between Clang modules and header units 16309263318fSAaron Ballman-------------------------------------------------- 1631b1d5af81SChuanqi Xu 16329263318fSAaron BallmanHeader units have similar semantics to Clang modules. The semantics of both are 16339263318fSAaron Ballmanlike headers. Therefore, header units can be mimicked by Clang modules as in 16349263318fSAaron Ballmanthe following example: 1635b1d5af81SChuanqi Xu 1636b1d5af81SChuanqi Xu.. code-block:: c++ 1637b1d5af81SChuanqi Xu 1638b1d5af81SChuanqi Xu module "iostream" { 1639b1d5af81SChuanqi Xu export * 1640b1d5af81SChuanqi Xu header "/path/to/libstdcxx/iostream" 1641b1d5af81SChuanqi Xu } 1642b1d5af81SChuanqi Xu 1643b1d5af81SChuanqi Xu.. code-block:: console 1644b1d5af81SChuanqi Xu 1645b1d5af81SChuanqi Xu $ clang++ -std=c++20 -fimplicit-modules -fmodule-map-file=.modulemap main.cpp 1646b1d5af81SChuanqi Xu 16479263318fSAaron BallmanThis example is simplified when using libc++: 1648b1d5af81SChuanqi Xu 1649b1d5af81SChuanqi Xu.. code-block:: console 1650b1d5af81SChuanqi Xu 1651b1d5af81SChuanqi Xu $ clang++ -std=c++20 main.cpp -fimplicit-modules -fimplicit-module-maps 1652b1d5af81SChuanqi Xu 16539263318fSAaron Ballmanbecause libc++ already supplies a 16549263318fSAaron Ballman`module map <https://github.com/llvm/llvm-project/blob/main/libcxx/include/module.modulemap.in>`_. 1655b1d5af81SChuanqi Xu 16569263318fSAaron BallmanThis raises the question: why are header units not implemented through Clang 16579263318fSAaron Ballmanmodules? 1658b1d5af81SChuanqi Xu 16599263318fSAaron BallmanThis is primarily because Clang modules have more hierarchical semantics when 16609263318fSAaron Ballmanwrapping multiple headers together as one module, which is not supported by 16619263318fSAaron BallmanStandard C++ Header units. We want to avoid the impression that these 16629263318fSAaron Ballmanadditional semantics get interpreted as Standard C++ behavior. 1663b1d5af81SChuanqi Xu 16649263318fSAaron BallmanAnother reason is that there are proposals to introduce module mappers to the 16659263318fSAaron BallmanC++ standard (for example, https://wg21.link/p1184r2). Reusing Clang's 16669263318fSAaron Ballman``modulemap`` may be more difficult if we need to introduce another module 16679263318fSAaron Ballmanmapper. 1668b1d5af81SChuanqi Xu 16699263318fSAaron BallmanDiscovering Dependencies 16709263318fSAaron Ballman======================== 1671b1d5af81SChuanqi Xu 16729263318fSAaron BallmanWithout use of modules, all the translation units in a project can be compiled 16739263318fSAaron Ballmanin parallel. However, the presence of module units requires compiling the 16749263318fSAaron Ballmantranslation units in a topological order. 16759c4f0d83SChuanqi Xu 16769263318fSAaron BallmanThe ``clang-scan-deps`` tool can extract dependency information and produce a 16779263318fSAaron BallmanJSON file conforming to the specification described in 16789263318fSAaron Ballman`P1689 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html>`_. 16799263318fSAaron BallmanOnly named modules are supported currently. 16809c4f0d83SChuanqi Xu 16819263318fSAaron BallmanA compilation database is needed when using ``clang-scan-deps``. See 16829c4f0d83SChuanqi Xu`JSON Compilation Database Format Specification <JSONCompilationDatabase.html>`_ 16839263318fSAaron Ballmanfor more information about compilation databases. Note that the ``output`` 16849263318fSAaron BallmanJSON attribute is necessary for ``clang-scan-deps`` to scan using the P1689 16859263318fSAaron Ballmanformat. For example: 16869c4f0d83SChuanqi Xu 16879c4f0d83SChuanqi Xu.. code-block:: c++ 16889c4f0d83SChuanqi Xu 16899c4f0d83SChuanqi Xu //--- M.cppm 16909c4f0d83SChuanqi Xu export module M; 16919c4f0d83SChuanqi Xu export import :interface_part; 16929c4f0d83SChuanqi Xu import :impl_part; 16939c4f0d83SChuanqi Xu export int Hello(); 16949c4f0d83SChuanqi Xu 16959c4f0d83SChuanqi Xu //--- interface_part.cppm 16969c4f0d83SChuanqi Xu export module M:interface_part; 16979c4f0d83SChuanqi Xu export void World(); 16989c4f0d83SChuanqi Xu 16999c4f0d83SChuanqi Xu //--- Impl.cpp 17009c4f0d83SChuanqi Xu module; 17019c4f0d83SChuanqi Xu #include <iostream> 17029c4f0d83SChuanqi Xu module M; 17039c4f0d83SChuanqi Xu void Hello() { 17049c4f0d83SChuanqi Xu std::cout << "Hello "; 17059c4f0d83SChuanqi Xu } 17069c4f0d83SChuanqi Xu 17079c4f0d83SChuanqi Xu //--- impl_part.cppm 17089c4f0d83SChuanqi Xu module; 17099c4f0d83SChuanqi Xu #include <string> 17109c4f0d83SChuanqi Xu #include <iostream> 17119c4f0d83SChuanqi Xu module M:impl_part; 17129c4f0d83SChuanqi Xu import :interface_part; 17139c4f0d83SChuanqi Xu 17149c4f0d83SChuanqi Xu std::string W = "World."; 17159c4f0d83SChuanqi Xu void World() { 17169c4f0d83SChuanqi Xu std::cout << W << std::endl; 17179c4f0d83SChuanqi Xu } 17189c4f0d83SChuanqi Xu 17199c4f0d83SChuanqi Xu //--- User.cpp 17209c4f0d83SChuanqi Xu import M; 17219c4f0d83SChuanqi Xu import third_party_module; 17229c4f0d83SChuanqi Xu int main() { 17239c4f0d83SChuanqi Xu Hello(); 17249c4f0d83SChuanqi Xu World(); 17259c4f0d83SChuanqi Xu return 0; 17269c4f0d83SChuanqi Xu } 17279c4f0d83SChuanqi Xu 17289c4f0d83SChuanqi XuAnd here is the compilation database: 17299c4f0d83SChuanqi Xu 17309c4f0d83SChuanqi Xu.. code-block:: text 17319c4f0d83SChuanqi Xu 17329c4f0d83SChuanqi Xu [ 17339c4f0d83SChuanqi Xu { 17349c4f0d83SChuanqi Xu "directory": ".", 17359c4f0d83SChuanqi Xu "command": "<path-to-compiler-executable>/clang++ -std=c++20 M.cppm -c -o M.o", 17369c4f0d83SChuanqi Xu "file": "M.cppm", 17379c4f0d83SChuanqi Xu "output": "M.o" 17389c4f0d83SChuanqi Xu }, 17399c4f0d83SChuanqi Xu { 17409c4f0d83SChuanqi Xu "directory": ".", 17419c4f0d83SChuanqi Xu "command": "<path-to-compiler-executable>/clang++ -std=c++20 Impl.cpp -c -o Impl.o", 17429c4f0d83SChuanqi Xu "file": "Impl.cpp", 17439c4f0d83SChuanqi Xu "output": "Impl.o" 17449c4f0d83SChuanqi Xu }, 17459c4f0d83SChuanqi Xu { 17469c4f0d83SChuanqi Xu "directory": ".", 17479c4f0d83SChuanqi Xu "command": "<path-to-compiler-executable>/clang++ -std=c++20 impl_part.cppm -c -o impl_part.o", 17489c4f0d83SChuanqi Xu "file": "impl_part.cppm", 17499c4f0d83SChuanqi Xu "output": "impl_part.o" 17509c4f0d83SChuanqi Xu }, 17519c4f0d83SChuanqi Xu { 17529c4f0d83SChuanqi Xu "directory": ".", 17539c4f0d83SChuanqi Xu "command": "<path-to-compiler-executable>/clang++ -std=c++20 interface_part.cppm -c -o interface_part.o", 17549c4f0d83SChuanqi Xu "file": "interface_part.cppm", 17559c4f0d83SChuanqi Xu "output": "interface_part.o" 17569c4f0d83SChuanqi Xu }, 17579c4f0d83SChuanqi Xu { 17589c4f0d83SChuanqi Xu "directory": ".", 17599c4f0d83SChuanqi Xu "command": "<path-to-compiler-executable>/clang++ -std=c++20 User.cpp -c -o User.o", 17609c4f0d83SChuanqi Xu "file": "User.cpp", 17619c4f0d83SChuanqi Xu "output": "User.o" 17629c4f0d83SChuanqi Xu } 17639c4f0d83SChuanqi Xu ] 17649c4f0d83SChuanqi Xu 17659263318fSAaron BallmanTo get the dependency information in P1689 format, use: 17669c4f0d83SChuanqi Xu 17679c4f0d83SChuanqi Xu.. code-block:: console 17689c4f0d83SChuanqi Xu 17699c4f0d83SChuanqi Xu $ clang-scan-deps -format=p1689 -compilation-database P1689.json 17709c4f0d83SChuanqi Xu 17719263318fSAaron Ballmanto get: 17729c4f0d83SChuanqi Xu 17739c4f0d83SChuanqi Xu.. code-block:: text 17749c4f0d83SChuanqi Xu 17759c4f0d83SChuanqi Xu { 17769c4f0d83SChuanqi Xu "revision": 0, 17779c4f0d83SChuanqi Xu "rules": [ 17789c4f0d83SChuanqi Xu { 17799c4f0d83SChuanqi Xu "primary-output": "Impl.o", 17809c4f0d83SChuanqi Xu "requires": [ 17819c4f0d83SChuanqi Xu { 17829c4f0d83SChuanqi Xu "logical-name": "M", 17839c4f0d83SChuanqi Xu "source-path": "M.cppm" 17849c4f0d83SChuanqi Xu } 17859c4f0d83SChuanqi Xu ] 17869c4f0d83SChuanqi Xu }, 17879c4f0d83SChuanqi Xu { 17889c4f0d83SChuanqi Xu "primary-output": "M.o", 17899c4f0d83SChuanqi Xu "provides": [ 17909c4f0d83SChuanqi Xu { 17919c4f0d83SChuanqi Xu "is-interface": true, 17929c4f0d83SChuanqi Xu "logical-name": "M", 17939c4f0d83SChuanqi Xu "source-path": "M.cppm" 17949c4f0d83SChuanqi Xu } 17959c4f0d83SChuanqi Xu ], 17969c4f0d83SChuanqi Xu "requires": [ 17979c4f0d83SChuanqi Xu { 17989c4f0d83SChuanqi Xu "logical-name": "M:interface_part", 17999c4f0d83SChuanqi Xu "source-path": "interface_part.cppm" 18009c4f0d83SChuanqi Xu }, 18019c4f0d83SChuanqi Xu { 18029c4f0d83SChuanqi Xu "logical-name": "M:impl_part", 18039c4f0d83SChuanqi Xu "source-path": "impl_part.cppm" 18049c4f0d83SChuanqi Xu } 18059c4f0d83SChuanqi Xu ] 18069c4f0d83SChuanqi Xu }, 18079c4f0d83SChuanqi Xu { 18089c4f0d83SChuanqi Xu "primary-output": "User.o", 18099c4f0d83SChuanqi Xu "requires": [ 18109c4f0d83SChuanqi Xu { 18119c4f0d83SChuanqi Xu "logical-name": "M", 18129c4f0d83SChuanqi Xu "source-path": "M.cppm" 18139c4f0d83SChuanqi Xu }, 18149c4f0d83SChuanqi Xu { 18159c4f0d83SChuanqi Xu "logical-name": "third_party_module" 18169c4f0d83SChuanqi Xu } 18179c4f0d83SChuanqi Xu ] 18189c4f0d83SChuanqi Xu }, 18199c4f0d83SChuanqi Xu { 18209c4f0d83SChuanqi Xu "primary-output": "impl_part.o", 18219c4f0d83SChuanqi Xu "provides": [ 18229c4f0d83SChuanqi Xu { 18239c4f0d83SChuanqi Xu "is-interface": false, 18249c4f0d83SChuanqi Xu "logical-name": "M:impl_part", 18259c4f0d83SChuanqi Xu "source-path": "impl_part.cppm" 18269c4f0d83SChuanqi Xu } 18279c4f0d83SChuanqi Xu ], 18289c4f0d83SChuanqi Xu "requires": [ 18299c4f0d83SChuanqi Xu { 18309c4f0d83SChuanqi Xu "logical-name": "M:interface_part", 18319c4f0d83SChuanqi Xu "source-path": "interface_part.cppm" 18329c4f0d83SChuanqi Xu } 18339c4f0d83SChuanqi Xu ] 18349c4f0d83SChuanqi Xu }, 18359c4f0d83SChuanqi Xu { 18369c4f0d83SChuanqi Xu "primary-output": "interface_part.o", 18379c4f0d83SChuanqi Xu "provides": [ 18389c4f0d83SChuanqi Xu { 18399c4f0d83SChuanqi Xu "is-interface": true, 18409c4f0d83SChuanqi Xu "logical-name": "M:interface_part", 18419c4f0d83SChuanqi Xu "source-path": "interface_part.cppm" 18429c4f0d83SChuanqi Xu } 18439c4f0d83SChuanqi Xu ] 18449c4f0d83SChuanqi Xu } 18459c4f0d83SChuanqi Xu ], 18469c4f0d83SChuanqi Xu "version": 1 18479c4f0d83SChuanqi Xu } 18489c4f0d83SChuanqi Xu 18499c4f0d83SChuanqi XuSee the P1689 paper for the meaning of the fields. 18509c4f0d83SChuanqi Xu 18519263318fSAaron BallmanGetting dependency information per file with finer-grained control (such as 18529263318fSAaron Ballmanscanning generated source files) is possible. For example: 18539c4f0d83SChuanqi Xu 18549c4f0d83SChuanqi Xu.. code-block:: console 18559c4f0d83SChuanqi Xu 18569c4f0d83SChuanqi Xu $ clang-scan-deps -format=p1689 -- <path-to-compiler-executable>/clang++ -std=c++20 impl_part.cppm -c -o impl_part.o 18579c4f0d83SChuanqi Xu 18589263318fSAaron Ballmanwill produce: 18599c4f0d83SChuanqi Xu 18609c4f0d83SChuanqi Xu.. code-block:: text 18619c4f0d83SChuanqi Xu 18629c4f0d83SChuanqi Xu { 18639c4f0d83SChuanqi Xu "revision": 0, 18649c4f0d83SChuanqi Xu "rules": [ 18659c4f0d83SChuanqi Xu { 18669c4f0d83SChuanqi Xu "primary-output": "impl_part.o", 18679c4f0d83SChuanqi Xu "provides": [ 18689c4f0d83SChuanqi Xu { 18699c4f0d83SChuanqi Xu "is-interface": false, 18709c4f0d83SChuanqi Xu "logical-name": "M:impl_part", 18719c4f0d83SChuanqi Xu "source-path": "impl_part.cppm" 18729c4f0d83SChuanqi Xu } 18739c4f0d83SChuanqi Xu ], 18749c4f0d83SChuanqi Xu "requires": [ 18759c4f0d83SChuanqi Xu { 18769c4f0d83SChuanqi Xu "logical-name": "M:interface_part" 18779c4f0d83SChuanqi Xu } 18789c4f0d83SChuanqi Xu ] 18799c4f0d83SChuanqi Xu } 18809c4f0d83SChuanqi Xu ], 18819c4f0d83SChuanqi Xu "version": 1 18829c4f0d83SChuanqi Xu } 18839c4f0d83SChuanqi Xu 18849263318fSAaron BallmanIndividual command line options can be specified after ``--``. 18859263318fSAaron Ballman``clang-scan-deps`` will extract the necessary information from the specified 18869263318fSAaron Ballmanoptions. Note that the path to the compiler executable needs to be specified 18879263318fSAaron Ballmanexplicitly instead of using ``clang++`` directly. 18889c4f0d83SChuanqi Xu 18899263318fSAaron BallmanUsers may want the scanner to get the transitional dependency information for 18909263318fSAaron Ballmanheaders. Otherwise, the project has to be scanned twice, once for headers and 18919263318fSAaron Ballmanonce for modules. To address this, ``clang-scan-deps`` will recognize the 18929263318fSAaron Ballmanspecified preprocessor options in the given command line and generate the 18939263318fSAaron Ballmancorresponding dependency information. For example: 18949c4f0d83SChuanqi Xu 18959c4f0d83SChuanqi Xu.. code-block:: console 18969c4f0d83SChuanqi Xu 18979c4f0d83SChuanqi Xu $ clang-scan-deps -format=p1689 -- ../bin/clang++ -std=c++20 impl_part.cppm -c -o impl_part.o -MD -MT impl_part.ddi -MF impl_part.dep 18989c4f0d83SChuanqi Xu $ cat impl_part.dep 18999c4f0d83SChuanqi Xu 19009263318fSAaron Ballmanwill produce: 19019c4f0d83SChuanqi Xu 19029c4f0d83SChuanqi Xu.. code-block:: text 19039c4f0d83SChuanqi Xu 19049c4f0d83SChuanqi Xu impl_part.ddi: \ 19059c4f0d83SChuanqi Xu /usr/include/bits/wchar.h /usr/include/bits/types/wint_t.h \ 19069c4f0d83SChuanqi Xu /usr/include/bits/types/mbstate_t.h \ 19079c4f0d83SChuanqi Xu /usr/include/bits/types/__mbstate_t.h /usr/include/bits/types/__FILE.h \ 19089c4f0d83SChuanqi Xu /usr/include/bits/types/FILE.h /usr/include/bits/types/locale_t.h \ 19099c4f0d83SChuanqi Xu /usr/include/bits/types/__locale_t.h \ 19109c4f0d83SChuanqi Xu ... 19119c4f0d83SChuanqi Xu 19129263318fSAaron BallmanWhen ``clang-scan-deps`` detects the ``-MF`` option, it will try to write the 19132db08128SKazu Hiratadependency information for headers to the file specified by ``-MF``. 19149c4f0d83SChuanqi Xu 1915f6b94e00SChuanqi XuPossible Issues: Failed to find system headers 1916f6b94e00SChuanqi Xu---------------------------------------------- 1917f6b94e00SChuanqi Xu 19189263318fSAaron BallmanIf encountering an error like ``fatal error: 'stddef.h' file not found``, 19199263318fSAaron Ballmanthe specified ``<path-to-compiler-executable>/clang++`` probably refers to a 19209263318fSAaron Ballmansymlink instead a real binary. There are four potential solutions to the 19219263318fSAaron Ballmanproblem: 1922f6b94e00SChuanqi Xu 19239263318fSAaron Ballman1. Point the specified compiler executable to the real binary instead of the 19249263318fSAaron Ballman symlink. 19259263318fSAaron Ballman2. Invoke ``<path-to-compiler-executable>/clang++ -print-resource-dir`` to get 19269263318fSAaron Ballman the corresponding resource directory for your compiler and add that 19279263318fSAaron Ballman directory to the include search paths manually in the build scripts. 19289263318fSAaron Ballman3. For build systems that use a compilation database as the input for 19299263318fSAaron Ballman ``clang-scan-deps``, the build system can add the 19309263318fSAaron Ballman ``--resource-dir-recipe invoke-compiler`` option when executing 19319263318fSAaron Ballman ``clang-scan-deps`` to calculate the resource directory dynamically. 1932f6b94e00SChuanqi Xu The calculation happens only once for a unique ``<path-to-compiler-executable>/clang++``. 19339263318fSAaron Ballman4. For build systems that invoke ``clang-scan-deps`` per file, repeatedly 19349263318fSAaron Ballman calculating the resource directory may be inefficient. In such cases, the 19359263318fSAaron Ballman build system can cache the resource directory and specify 19369263318fSAaron Ballman ``-resource-dir <resource-dir>`` explicitly, as in: 1937f6b94e00SChuanqi Xu 1938f6b94e00SChuanqi Xu .. code-block:: console 1939f6b94e00SChuanqi Xu 1940f6b94e00SChuanqi Xu $ clang-scan-deps -format=p1689 -- <path-to-compiler-executable>/clang++ -std=c++20 -resource-dir <resource-dir> mod.cppm -c -o mod.o 1941f6b94e00SChuanqi Xu 1942f6b94e00SChuanqi Xu 1943bae1adaeSChuanqi XuImport modules with clang-repl 1944bae1adaeSChuanqi Xu============================== 1945bae1adaeSChuanqi Xu 19469263318fSAaron Ballman``clang-repl`` supports importing C++20 named modules. For example: 1947bae1adaeSChuanqi Xu 1948bae1adaeSChuanqi Xu.. code-block:: c++ 1949bae1adaeSChuanqi Xu 1950bae1adaeSChuanqi Xu // M.cppm 1951bae1adaeSChuanqi Xu export module M; 1952bae1adaeSChuanqi Xu export const char* Hello() { 1953bae1adaeSChuanqi Xu return "Hello Interpreter for Modules!"; 1954bae1adaeSChuanqi Xu } 1955bae1adaeSChuanqi Xu 19569263318fSAaron BallmanThe named module still needs to be compiled ahead of time. 1957bae1adaeSChuanqi Xu 1958bae1adaeSChuanqi Xu.. code-block:: console 1959bae1adaeSChuanqi Xu 1960bae1adaeSChuanqi Xu $ clang++ -std=c++20 M.cppm --precompile -o M.pcm 1961bae1adaeSChuanqi Xu $ clang++ M.pcm -c -o M.o 1962bae1adaeSChuanqi Xu $ clang++ -shared M.o -o libM.so 1963bae1adaeSChuanqi Xu 19649263318fSAaron BallmanNote that the module unit needs to be compiled as a dynamic library so that 19659263318fSAaron Ballman``clang-repl`` can load the object files of the module units. Then it is 19669263318fSAaron Ballmanpossible to import module ``M`` in clang-repl. 1967bae1adaeSChuanqi Xu 1968bae1adaeSChuanqi Xu.. code-block:: console 1969bae1adaeSChuanqi Xu 1970bae1adaeSChuanqi Xu $ clang-repl -Xcc=-std=c++20 -Xcc=-fprebuilt-module-path=. 1971bae1adaeSChuanqi Xu # We need to load the dynamic library first before importing the modules. 1972bae1adaeSChuanqi Xu clang-repl> %lib libM.so 1973bae1adaeSChuanqi Xu clang-repl> import M; 1974bae1adaeSChuanqi Xu clang-repl> extern "C" int printf(const char *, ...); 1975bae1adaeSChuanqi Xu clang-repl> printf("%s\n", Hello()); 1976bae1adaeSChuanqi Xu Hello Interpreter for Modules! 1977bae1adaeSChuanqi Xu clang-repl> %quit 1978bae1adaeSChuanqi Xu 1979b1d5af81SChuanqi XuPossible Questions 1980b1d5af81SChuanqi Xu================== 1981b1d5af81SChuanqi Xu 1982b1d5af81SChuanqi XuHow modules speed up compilation 1983b1d5af81SChuanqi Xu-------------------------------- 1984b1d5af81SChuanqi Xu 19859263318fSAaron BallmanA classic theory for the reason why modules speed up the compilation is: if 19869263318fSAaron Ballmanthere are ``n`` headers and ``m`` source files and each header is included by 19879263318fSAaron Ballmaneach source file, then the complexity of the compilation is ``O(n*m)``. 19889263318fSAaron BallmanHowever, if there are ``n`` module interfaces and ``m`` source files, the 19899263318fSAaron Ballmancomplexity of the compilation is ``O(n+m)``. Therefore, using modules would be 19909263318fSAaron Ballmana significant improvement at scale. More simply, use of modules causes many of 19919263318fSAaron Ballmanthe redundant compilations to no longer be necessary. 1992b1d5af81SChuanqi Xu 19939263318fSAaron BallmanWhile this is accurate at a high level, this depends greatly on the 19949263318fSAaron Ballmanoptimization level, as illustrated below. 1995b1d5af81SChuanqi Xu 19969263318fSAaron BallmanFirst is ``-O0``. The compilation process is described in the following graph. 1997b1d5af81SChuanqi Xu 1998b1d5af81SChuanqi Xu.. code-block:: none 1999b1d5af81SChuanqi Xu 2000b1d5af81SChuanqi Xu ├-------------frontend----------┼-------------middle end----------------┼----backend----┤ 2001b1d5af81SChuanqi Xu │ │ │ │ 2002b1d5af81SChuanqi Xu └---parsing----sema----codegen--┴----- transformations ---- codegen ----┴---- codegen --┘ 2003b1d5af81SChuanqi Xu 20049263318fSAaron Ballman ├---------------------------------------------------------------------------------------┐ 2005b1d5af81SChuanqi Xu | │ 2006b1d5af81SChuanqi Xu | source file │ 2007b1d5af81SChuanqi Xu | │ 2008b1d5af81SChuanqi Xu └---------------------------------------------------------------------------------------┘ 2009b1d5af81SChuanqi Xu 20109263318fSAaron Ballman ├--------┐ 2011b1d5af81SChuanqi Xu │ │ 2012b1d5af81SChuanqi Xu │imported│ 2013b1d5af81SChuanqi Xu │ │ 2014b1d5af81SChuanqi Xu │ code │ 2015b1d5af81SChuanqi Xu │ │ 2016b1d5af81SChuanqi Xu └--------┘ 2017b1d5af81SChuanqi Xu 20189263318fSAaron BallmanIn this case, the source file (which could be a non-module unit or a module 20199263318fSAaron Ballmanunit) would get processed by the entire pipeline. However, the imported code 20209263318fSAaron Ballmanwould only get involved in semantic analysis, which, for the most part, is name 20219263318fSAaron Ballmanlookup, overload resolution, and template instantiation. All of these processes 20229263318fSAaron Ballmanare fast relative to the whole compilation process. More importantly, the 20239263318fSAaron Ballmanimported code only needs to be processed once during frontend code generation, 20249263318fSAaron Ballmanas well as the whole middle end and backend. So we could get a big win for the 20259263318fSAaron Ballmancompilation time in ``-O0``. 2026b1d5af81SChuanqi Xu 20279263318fSAaron BallmanBut with optimizations, things are different (the ``code generation`` part for 20289263318fSAaron Ballmaneach end is omitted due to limited space): 2029b1d5af81SChuanqi Xu 2030b1d5af81SChuanqi Xu.. code-block:: none 2031b1d5af81SChuanqi Xu 2032b1d5af81SChuanqi Xu ├-------- frontend ---------┼--------------- middle end --------------------┼------ backend ----┤ 2033b1d5af81SChuanqi Xu │ │ │ │ 2034b1d5af81SChuanqi Xu └--- parsing ---- sema -----┴--- optimizations --- IPO ---- optimizations---┴--- optimizations -┘ 2035b1d5af81SChuanqi Xu 20369263318fSAaron Ballman ├-----------------------------------------------------------------------------------------------┐ 2037b1d5af81SChuanqi Xu │ │ 2038b1d5af81SChuanqi Xu │ source file │ 2039b1d5af81SChuanqi Xu │ │ 2040b1d5af81SChuanqi Xu └-----------------------------------------------------------------------------------------------┘ 20419263318fSAaron Ballman ├---------------------------------------┐ 2042b1d5af81SChuanqi Xu │ │ 2043b1d5af81SChuanqi Xu │ │ 2044b1d5af81SChuanqi Xu │ imported code │ 2045b1d5af81SChuanqi Xu │ │ 2046b1d5af81SChuanqi Xu │ │ 2047b1d5af81SChuanqi Xu └---------------------------------------┘ 2048b1d5af81SChuanqi Xu 20499263318fSAaron BallmanIt would be very unfortunate if we end up with worse performance when using 20509263318fSAaron Ballmanmodules. The main concern is that when a source file is compiled, the compiler 20519263318fSAaron Ballmanneeds to see the body of imported module units so that it can perform IPO 20529263318fSAaron Ballman(InterProcedural Optimization, primarily inlining in practice) to optimize 20539263318fSAaron Ballmanfunctions in the current source file with the help of the information provided 20549263318fSAaron Ballmanby the imported module units. In other words, the imported code would be 20559263318fSAaron Ballmanprocessed again and again in importee units by optimizations (including IPO 20569263318fSAaron Ballmanitself). The optimizations before IPO and IPO itself are the most time-consuming 20579263318fSAaron Ballmanpart in whole compilation process. So from this perspective, it might not be 20589263318fSAaron Ballmanpossible to get the compile time improvements described, but there could be 20599263318fSAaron Ballmantime savings for optimizations after IPO and the whole backend. 2060b1d5af81SChuanqi Xu 20619263318fSAaron BallmanOverall, at ``-O0`` the implementations of functions defined in a module will 20629263318fSAaron Ballmannot impact module users, but at higher optimization levels the definitions of 20639263318fSAaron Ballmansuch functions are provided to user compilations for the purposes of 20649263318fSAaron Ballmanoptimization (but definitions of these functions are still not included in the 20659263318fSAaron Ballmanuse's object file). This means the build speedup at higher optimization levels 20669263318fSAaron Ballmanmay be lower than expected given ``-O0`` experience, but does provide more 20679263318fSAaron Ballmanoptimization opportunities. 2068b1d5af81SChuanqi Xu 2069e12b627aSChuanqi XuInteroperability with Clang Modules 2070e12b627aSChuanqi Xu----------------------------------- 2071e12b627aSChuanqi Xu 20729263318fSAaron BallmanWe **wish** to support Clang modules and standard C++ modules at the same time, 20739263318fSAaron Ballmanbut the mixing them together is not well used/tested yet. Please file new 20749263318fSAaron BallmanGitHub issues as you find interoperability problems. 2075