@@ -652,6 +652,149 @@ in the future. The expected roadmap for Reduced BMIs as of Clang 19.x is:
652
652
comes, the term BMI will refer to the Reduced BMI and the Full BMI will only
653
653
be meaningful to build systems which elect to support two-phase compilation.
654
654
655
+ Experimental Non-Cascading Changes
656
+ ----------------------------------
657
+
658
+ This section is primarily for build system vendors. For end compiler users,
659
+ if you don't want to read it all, this is helpful to reduce recompilations.
660
+ We encourage build system vendors and end users try this out and bring feedback.
661
+
662
+ Before Clang 19, a change in BMI of any (transitive) dependency would cause the
663
+ outputs of the BMI to change. Starting with Clang 19, changes to non-direct
664
+ dependencies should not directly affect the output BMI, unless they affect the
665
+ results of the compilations. We expect that there are many more opportunities
666
+ for this optimization than we currently have realized and would appreaciate
667
+ feedback about missed optimization opportunities. For example,
668
+
669
+ .. code-block :: c++
670
+
671
+ // m-partA.cppm
672
+ export module m:partA;
673
+
674
+ // m-partB.cppm
675
+ export module m:partB;
676
+ export int getB() { return 44; }
677
+
678
+ // m.cppm
679
+ export module m;
680
+ export import :partA;
681
+ export import :partB;
682
+
683
+ // useBOnly.cppm
684
+ export module useBOnly;
685
+ import m;
686
+ export int B() {
687
+ return getB();
688
+ }
689
+
690
+ // Use.cc
691
+ import useBOnly;
692
+ int get() {
693
+ return B();
694
+ }
695
+
696
+ To compile the project (for brevity, some commands are omitted.):
697
+
698
+ .. code-block :: console
699
+
700
+ $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm
701
+ $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm
702
+ $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=.
703
+ $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=.
704
+ $ md5sum useBOnly.pcm
705
+ 07656bf4a6908626795729295f9608da useBOnly.pcm
706
+
707
+ If the interface of ``m-partA.cppm `` is changed to:
708
+
709
+ .. code-block :: c++
710
+
711
+ // m-partA.v1.cppm
712
+ export module m:partA;
713
+ export int getA() { return 43; }
714
+
715
+ and the BMI for ``useBOnly `` is recompiled as in:
716
+
717
+ .. code-block :: console
718
+
719
+ $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm
720
+ $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm
721
+ $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=.
722
+ $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=.
723
+ $ md5sum useBOnly.pcm
724
+ 07656bf4a6908626795729295f9608da useBOnly.pcm
725
+
726
+ then the contents of ``useBOnly.pcm `` remain unchanged.
727
+ Consequently, if the build system only bases recompilation decisions on directly imported modules,
728
+ it becomes possible to skip the recompilation of ``Use.cc ``.
729
+ It should be fine because the altered interfaces do not affect ``Use.cc `` in any way;
730
+ the changes do not cascade.
731
+
732
+ When ``Clang `` generates a BMI, it records the hash values of all potentially contributory BMIs
733
+ for the BMI being produced. This ensures that build systems are not required to consider
734
+ transitively imported modules when deciding whether to recompile.
735
+
736
+ What is considered to be a potential contributory BMIs is currently unspecified.
737
+ However, it is a severe bug for a BMI to remain unchanged following an observable change
738
+ that affects its consumers.
739
+
740
+ Build systems may utilize this optimization by doing an update-if-changed operation to the BMI
741
+ that is consumed from the BMI that is output by the compiler.
742
+
743
+ We encourage build systems to add an experimental mode that
744
+ reuses the cached BMI when **direct ** dependencies did not change,
745
+ even if **transitive ** dependencies did change.
746
+
747
+ Given there are potential compiler bugs, we recommend that build systems
748
+ support this feature as a configurable option so that users
749
+ can go back to the transitive change mode safely at any time.
750
+
751
+ Interactions with Reduced BMI
752
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
753
+
754
+ With reduced BMI, non-cascading changes can be more powerful. For example,
755
+
756
+ .. code-block :: c++
757
+
758
+ // A.cppm
759
+ export module A;
760
+ export int a() { return 44; }
761
+
762
+ // B.cppm
763
+ export module B;
764
+ import A;
765
+ export int b() { return a(); }
766
+
767
+ .. code-block :: console
768
+
769
+ $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fexperimental-modules-reduced-bmi -o A.o
770
+ $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fexperimental-modules-reduced-bmi -o B.o -fmodule-file=A=A.pcm
771
+ $ md5sum B.pcm
772
+ 6c2bd452ca32ab418bf35cd141b060b9 B.pcm
773
+
774
+ And let's change the implementation for ``A.cppm `` into:
775
+
776
+ .. code-block :: c++
777
+
778
+ export module A;
779
+ int a_impl() { return 99; }
780
+ export int a() { return a_impl(); }
781
+
782
+ and recompile the example:
783
+
784
+ .. code-block :: console
785
+
786
+ $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fexperimental-modules-reduced-bmi -o A.o
787
+ $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fexperimental-modules-reduced-bmi -o B.o -fmodule-file=A=A.pcm
788
+ $ md5sum B.pcm
789
+ 6c2bd452ca32ab418bf35cd141b060b9 B.pcm
790
+
791
+ We should find the contents of ``B.pcm `` remains the same. In this case, the build system is
792
+ allowed to skip recompilations of TUs which solely and directly depend on module ``B ``.
793
+
794
+ This only happens with a reduced BMI. With reduced BMIs, we won't record the function body
795
+ of ``int b() `` in the BMI for ``B `` so that the module ``A `` doesn't contribute to the BMI of ``B ``
796
+ and we have less dependencies.
797
+
655
798
Performance Tips
656
799
----------------
657
800
0 commit comments