@@ -610,6 +610,345 @@ the following style significantly:
610610
611611The key part of the tip is to reduce the duplications from the text includes.
612612
613+ Ideas for converting to modules
614+ -------------------------------
615+
616+ For new libraries, we encourage them to use modules completely from day one if possible.
617+ This will be pretty helpful to make the whole ecosystems to get ready.
618+
619+ For many existing libraries, it may be a breaking change to refactor themselves
620+ into modules completely. So that many existing libraries need to provide headers and module
621+ interfaces for a while to not break existing users.
622+ Here we provide some ideas to ease the transition process for existing libraries.
623+ **Note that the this section is only about helping ideas instead of requirement from clang **.
624+
625+ Let's start with the case that there is no dependency or no dependent libraries providing
626+ modules for your library.
627+
628+ ABI non-breaking styles
629+ ~~~~~~~~~~~~~~~~~~~~~~~
630+
631+ export-using style
632+ ^^^^^^^^^^^^^^^^^^
633+
634+ .. code-block :: c++
635+
636+ module;
637+ #include "header_1.h"
638+ #include "header_2.h"
639+ ...
640+ #include "header_n.h"
641+ export module your_library;
642+ export namespace your_namespace {
643+ using decl_1;
644+ using decl_2;
645+ ...
646+ using decl_n;
647+ }
648+
649+ As the example shows, you need to include all the headers containing declarations needs
650+ to be exported and `using ` such declarations in an `export ` block. Then, basically,
651+ we're done.
652+
653+ export extern-C++ style
654+ ^^^^^^^^^^^^^^^^^^^^^^^
655+
656+ .. code-block :: c++
657+
658+ module;
659+ #include "third_party/A/headers.h"
660+ #include "third_party/B/headers.h"
661+ ...
662+ #include "third_party/Z/headers.h"
663+ export module your_library;
664+ #define IN_MODULE_INTERFACE
665+ extern "C++" {
666+ #include "header_1.h"
667+ #include "header_2.h"
668+ ...
669+ #include "header_n.h"
670+ }
671+
672+ Then in your headers (from ``header_1.h `` to ``header_n.h ``), you need to define the macro:
673+
674+ .. code-block :: c++
675+
676+ #ifdef IN_MODULE_INTERFACE
677+ #define EXPORT export
678+ #else
679+ #define EXPORT
680+ #endif
681+
682+ And you should put ``EXPORT `` to the beginning of the declarations you want to export.
683+
684+ Also it is suggested to refactor your headers to include thirdparty headers conditionally:
685+
686+ .. code-block :: c++
687+
688+ #ifndef IN_MODULE_INTERFACE
689+ #include "third_party/A/headers.h"
690+ #endif
691+
692+ #include "header_x.h"
693+
694+ ...
695+
696+ This may be helpful to get better diagnostic messages if you forgot to update your module
697+ interface unit file during maintaining.
698+
699+ The reasoning for the practice is that the declarations in the language linkage are considered
700+ to be attached to the global module. So the ABI of your library in the modular version
701+ wouldn't change.
702+
703+ While this style looks not as convenient as the export-using style, it is easier to convert
704+ to other styles.
705+
706+ ABI breaking style
707+ ~~~~~~~~~~~~~~~~~~
708+
709+ The term ``ABI breaking `` sounds terrifying generally. But you may want it here if you want
710+ to force your users to introduce your library in a consistent way. E.g., they either include
711+ your headers all the way or import your modules all the way.
712+ The style prevents the users to include your headers and import your modules at the same time
713+ in the same repo.
714+
715+ The pattern for ABI breaking style is similar with export extern-C++ style.
716+
717+ .. code-block :: c++
718+
719+ module;
720+ #include "third_party/A/headers.h"
721+ #include "third_party/B/headers.h"
722+ ...
723+ #include "third_party/Z/headers.h"
724+ export module your_library;
725+ #define IN_MODULE_INTERFACE
726+ #include "header_1.h"
727+ #include "header_2.h"
728+ ...
729+ #include "header_n.h"
730+
731+ #if the number of .cpp files in your project are small
732+ module :private;
733+ #include "source_1.cpp"
734+ #include "source_2.cpp"
735+ ...
736+ #include "source_n.cpp"
737+ #else // the number of .cpp files in your project are a lot
738+ // Using all the declarations from thirdparty libraries which are
739+ // used in the .cpp files.
740+ namespace third_party_namespace {
741+ using third_party_decl_used_in_cpp_1;
742+ using third_party_decl_used_in_cpp_2;
743+ ...
744+ using third_party_decl_used_in_cpp_n;
745+ }
746+ #endif
747+
748+ (And add `EXPORT ` and conditional include to the headers as suggested in the export
749+ extern-C++ style section)
750+
751+ Remember that the ABI get changed and we need to compile our source files into the
752+ new ABI format. This is the job of the additional part of the interface unit:
753+
754+ .. code-block :: c++
755+
756+ #if the number of .cpp files in your project are small
757+ module :private;
758+ #include "source_1.cpp"
759+ #include "source_2.cpp"
760+ ...
761+ #include "source_n.cpp"
762+ #else // the number of .cpp files in your project are a lot
763+ // Using all the declarations from thirdparty libraries which are
764+ // used in the .cpp files.
765+ namespace third_party_namespace {
766+ using third_party_decl_used_in_cpp_1;
767+ using third_party_decl_used_in_cpp_2;
768+ ...
769+ using third_party_decl_used_in_cpp_n;
770+ }
771+ #endif
772+
773+ In case the number of your source files are small, we may put everything in the private
774+ module fragment directly. (it is suggested to add conditional include to the source
775+ files too). But it will make the compilation of the module interface unit to be slow
776+ when the number of the source files are not small enough.
777+
778+ **Note that the private module fragment can only be in the primary module interface unit
779+ and the primary module interface unit containing private module fragment should be the only
780+ module unit of the corresponding module. **
781+
782+ In that case, you need to convert your source files (.cpp files) to module implementation units:
783+
784+ .. code-block :: c++
785+
786+ #ifndef IN_MODULE_INTERFACE
787+ // List all the includes here.
788+ #include "third_party/A/headers.h"
789+ ...
790+ #include "header.h"
791+ #endif
792+
793+ module your_library;
794+
795+ // Following off should be unchanged.
796+ ...
797+
798+ The module implementation unit will import the primary module implicitly.
799+ We don't include any headers in the module implementation units
800+ here since we want to avoid duplicated declarations between translation units.
801+ This is the reason why we add non-exported using declarations from the third
802+ party libraries in the primary module interface unit.
803+
804+ And if you provide your library as ``libyour_library.so ``, you probably need to
805+ provide a modular one ``libyour_library_modules.so `` since you changed the ABI.
806+
807+ What if there are headers only inclued by the source files
808+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
809+
810+ The above practice may be problematic if there are headers only included by the source
811+ files. If you're using private module fragment, you may solve the issue by including them
812+ in the private module fragment. While it is OK to solve it by including the implementation
813+ headers in the module purview if you're using implementation module units, it may be
814+ suboptimal since the primary module interface units now containing entities not belongs
815+ to the interface.
816+
817+ If you're a perfectionist, maybe you can improve it by introducing internal module partition unit.
818+
819+ The internal module partition unit is an importable module unit which is internal
820+ to the module itself. The concept just meets the headers only included by the source files.
821+
822+ We don't show code snippet since it may be too verbose or not good or not general.
823+ But it may not be too hard if you can understand the points of the section.
824+
825+ Providing a header to skip parsing redundant headers
826+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
827+
828+ It is a problem for clang to handle redeclarations between translation units.
829+ Also there is a long standing issue in clang (`problematic include after import <https://github.com/llvm/llvm-project/issues/61465 >`_).
830+ But even if the issue get fixed in clang someday, the users may still get slower compilation speed
831+ and larger BMI size. So it is suggested to not include headers after importing the corresponding
832+ library.
833+
834+ However, it is not easy for users if your library are included by other dependencies.
835+
836+ So the users may have to write codes like:
837+
838+ .. code-block :: c++
839+
840+ #include "third_party/A.h" // #include "your_library/a_header.h"
841+ import your_library;
842+
843+ or
844+
845+ .. code-block :: c++
846+
847+ import your_library;
848+ #include "third_party/A.h" // #include "your_library/a_header.h"
849+
850+ For such cases, we suggest the libraries providing modules and the headers at the same time
851+ to provide a header to skip parsing all the headers in your libraries. So the users can
852+ import your library as the following style to skip redundant handling:
853+
854+ .. code-block :: c++
855+
856+ import your_library;
857+ #include "your_library_imported.h"
858+ #include "third_party/A.h" // #include "your_library/a_header.h" but got skipped
859+
860+ The implementation of ``your_library_imported.h `` can be a set of controlling macros or
861+ an overall controlling macro if you're using `#pragma once `. So you can convert your
862+ headers to:
863+
864+ .. code-block :: c++
865+
866+ #pragma once
867+ #ifndef YOUR_LIBRARY_IMPORTED
868+ ...
869+ #endif
870+
871+ Importing modules
872+ ~~~~~~~~~~~~~~~~~
873+
874+ When there are dependent libraries providing modules, we suggest you to import that in
875+ your module.
876+
877+ Most of the existing libraries would fall into this catagory once the std module gets available.
878+
879+ All dependent libraries providing modules
880+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
881+
882+ Life gets easier if all the dependent libraries providing modules.
883+
884+ You need to convert your headers to include thirdparty headers conditionally.
885+
886+ Then for export-using style:
887+
888+ .. code-block :: c++
889+
890+ module;
891+ import modules_from_third_party;
892+ #define IN_MODULE_INTERFACE
893+ #include "header_1.h"
894+ #include "header_2.h"
895+ ...
896+ #include "header_n.h"
897+ export module your_library;
898+ export namespace your_namespace {
899+ using decl_1;
900+ using decl_2;
901+ ...
902+ using decl_n;
903+ }
904+
905+ For export extern-C++ style:
906+
907+ .. code-block :: c++
908+
909+ export module your_library;
910+ import modules_from_third_party;
911+ #define IN_MODULE_INTERFACE
912+ extern "C++" {
913+ #include "header_1.h"
914+ #include "header_2.h"
915+ ...
916+ #include "header_n.h"
917+ }
918+
919+ For ABI breaking style,
920+
921+ .. code-block :: c++
922+
923+ export module your_library;
924+ import modules_from_third_party;
925+ #define IN_MODULE_INTERFACE
926+ #include "header_1.h"
927+ #include "header_2.h"
928+ ...
929+ #include "header_n.h"
930+
931+ #if the number of .cpp files in your project are small
932+ module :private;
933+ #include "source_1.cpp"
934+ #include "source_2.cpp"
935+ ...
936+ #include "source_n.cpp"
937+ #endif
938+
939+ We don't need the non-exported using declarations if we're using implementation module
940+ units now. We can import thirdparty modules directly in the implementation module
941+ units.
942+
943+ Partial dependent libraries providing modules
944+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
945+
946+ In this case, we have to mix the use of ``include `` and ``import `` in the module of our
947+ library. The key point here is still to remove duplicated declarations in translation
948+ units as much as possible. If the imported modules provide headers to skip parsing their
949+ headers, we should include that after the including. If the imported modules don't provide
950+ the headers, we can make it ourselves if we still want to optimize it.
951+
613952Known Problems
614953--------------
615954
0 commit comments