Skip to content

Commit

Permalink
Update module implementation status and fix errors
Browse files Browse the repository at this point in the history
Fixes: #487
  • Loading branch information
bernhardmgruber committed Sep 12, 2023
1 parent c9dafc0 commit 6df808e
Showing 1 changed file with 112 additions and 90 deletions.
202 changes: 112 additions & 90 deletions talk/expert/modules.tex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
\begin{itemize}
\item Better isolation. No cross-talk between multiple pieces of included code, and also not between included code and your code.
\item Better control over public interface of your library. Avoid leaking library dependencies into user code.
\item Faster compilation
\item Faster compilation (\href{https://youtu.be/DJTEUFRslbI?si=ZRvH1wx0sVJVriLh&t=3259}{import fmt; \textgreater1500x faster})
\end{itemize}
\end{itemize}
\end{block}
Expand Down Expand Up @@ -121,12 +121,12 @@
import math;
import <iostream>;
int main() {
Ratio r = golden(); // error (Ratio not visible)
auto r = golden(); // ok: (Ratio is reachable)
std::cout << r.num; // ok: members of reachable
// class types become visible
Ratio r = golden(); // error: Ratio not visible
auto r = golden(); // OK: Ratio is reachable
std::cout << r.num; // OK: members of reachable
// types are visible
using R = decltype(r);
R r2{1.f, 3.f}; // ok
R r2{1.f, 3.f}; // OK
}
\end{cppcode*}
\end{exampleblock}
Expand All @@ -135,20 +135,24 @@
\begin{frame}[fragile]
\frametitlecpp[20]{Module structure}
\begin{exampleblock}{}
\small
\begin{cppcode*}{gobble=2}
module;
#include <cassert> // global module fragment
// ... // only preprocessor
// statements allowed

export module math; // exported module name

import <string>; // module preamble
// ... // only imports allowed

export struct S { ... }; // module purview
export S f() { ... } // starts at first
std::string h() { ... } // non-import
module; // global module fragment (opt.)
#include <cassert> // only preprocessor
// ... // statements allowed

export module math; // module preamble starts with
// exported module name.
import <string>; // only imports allowed
// ... //

export struct S { ... }; // module purview started
export S f(); // at first non-import
std::string h() { ... }

module :private // private module fragment (opt.)
S f() { ... } // changes here trigger
// no recompilation of BMI
\end{cppcode*}
\end{exampleblock}
\end{frame}
Expand Down Expand Up @@ -206,10 +210,64 @@
\end{exampleblock}
\end{frame}

\begin{frame}[fragile,shrink=5]
\frametitlecpp[20]{Submodules and re-exporting}
\begin{block}{}
Modules can (re-)export other modules using \cppinline{export import}:
\end{block}
\vspace{-5mm}
\begin{columns}[t]
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module one}
\begin{cppcode*}{gobble=6}
export module one;

export struct S { ... };
\end{cppcode*}
\end{exampleblock}
\end{column}
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module two}
\begin{cppcode*}{gobble=6}
export module two;
import <string>;

export std::string b()
{ ... }
\end{cppcode*}
\end{exampleblock}
\end{column}
\end{columns}
\begin{columns}[t]
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module three}
\begin{cppcode*}{gobble=6}
export module three;
import one;
export import two;

export S f() { ... }
\end{cppcode*}
\end{exampleblock}
\end{column}
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module four}
\begin{cppcode*}{gobble=6}
export module four;
import three;
// b and f visible
// S and std::string only
// reachable
\end{cppcode*}
\end{exampleblock}
\end{column}
\end{columns}
\end{frame}

\begin{frame}[fragile,shrink=5]
\frametitlecpp[20]{Module partitions}
\begin{block}{}
We can split a module's interface into multiple files:
We can split a module's \emph{interface} into multiple files:
\end{block}
\vspace{-5mm}
\begin{columns}[t]
Expand Down Expand Up @@ -248,7 +306,7 @@
\begin{frame}[fragile,shrink=5]
\frametitlecpp[20]{Module implementation units}
\begin{block}{}
We can split a module's implementation into multiple files:
We can split a module's \emph{implementation} into multiple files:
\end{block}
\begin{exampleblock}{Interface}
\begin{cppcode*}{gobble=2}
Expand Down Expand Up @@ -285,65 +343,14 @@
\end{columns}
\end{frame}

\begin{frame}[fragile,shrink=5]
\frametitlecpp[20]{Submodules and re-exporting}
\begin{block}{}
Modules can (re-)export other modules:
\end{block}
\vspace{-5mm}
\begin{columns}[t]
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module base}
\begin{cppcode*}{gobble=6}
export module base;

export struct S { ... };
\end{cppcode*}
\end{exampleblock}
\end{column}
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module bar}
\begin{cppcode*}{gobble=6}
export module bar;
import <string>;

export std::string b()
{ ... }
\end{cppcode*}
\end{exampleblock}
\end{column}
\end{columns}
\begin{columns}[t]
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module foo}
\begin{cppcode*}{gobble=6}
export module foo;
import export module base;
import bar;

export S f() { ... }
\end{cppcode*}
\end{exampleblock}
\end{column}
\begin{column}{.45\textwidth}
\begin{exampleblock}{Module math}
\begin{cppcode*}{gobble=6}
export module math;
export import foo;
\end{cppcode*}
\end{exampleblock}
\end{column}
\end{columns}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[23]{Standard library modules}
% see: Minimal module support for the standard library http://wg21.link/P2412
\begin{block}{Standard library modules}
\begin{itemize}
\item Use \cppinline|import std;| for the entire C++ standard library. Basically everything in namespace \cppinline|std|.
\begin{itemize}
\item E.g.\ \cppinline{memcpy(a, b, n);}, \cppinline{sqrt(val);}, \cppinline{uint32_t i;} will not compile. You need to prefix \cppinline{std::}.
\item E.g.\ \cppinline{memcpy(a, b, n)}, \cppinline{sqrt(val)}, \cppinline{uint32_t i} will not compile. You need to prefix \cppinline{std::}.
\end{itemize}
\item Use \cppinline|import std.compat;| for the entire C and C++ standard library
\item No macros are exported. For these, you still need to include the corresponding headers.
Expand Down Expand Up @@ -525,7 +532,7 @@
very thick
]
\draw [-Latex](7,10) -- (7,0) node [midway,right] {t};
\draw[thick] node at(3, 10) [fill=white,rounded rectangle] {build dependencies};
\draw[thick] node at(3, 10) [fill=white,rounded rectangle] {scan dependencies};
\path[thick]
node (vec) at(5,9) [rectangle,draw] {\textless{}vector\textgreater{}}
node (vecbmi) at(4,7.5) [rectangle,draw] {vector.bmi}
Expand Down Expand Up @@ -572,16 +579,22 @@
\item Translation units no longer independent
\begin{itemize}
\item Extra tool needs to infer dependency graph before building
\item This graph needs to be communicated to the build system
\item We will likely need a \href{https://wg21.link/P1689}{standard dependency file format}
\begin{itemize}
\item Called a ``dependency scanner''
\item Needs to be communicated to the build system
\item Using a new \href{https://wg21.link/P1689}{standard dependency file format}
\end{itemize}
\item Parallel and distributed builds need synchronization
\end{itemize}
\item Compilation of module translation units produces binary module interface (BMI) and object file
\item Compilation of module translation units produces a binary module interface (BMI) \emph{and} an object file
\begin{itemize}
\item BMIs need to be maintained/shared between multiple compiler instances
\item Need to manage BMIs between multiple compiler invocations
\end{itemize}
\item Tools beside the compiler need to build/read binary module interface (static analysis, auto completion, etc.)
\item The C++ standard specifies very little on how this works
\item Tools beside the compiler need to build/read BMIs
\begin{itemize}
\item E.g. static analysis, language servers for auto completion, etc.
\end{itemize}
\item The \cpp standard specifies very little on how this works
\begin{itemize}
\item We may experience large implementation divergence
\end{itemize}
Expand All @@ -593,12 +606,16 @@
\frametitlecpp[20]{Build system}
\begin{block}{Status}
\begin{itemize}
\item build2 supports everything g++ does
\item MSBuild figures out dependencies and build order automatically (Windows/Visual Studio only)
\item Dependency scanner since clang 16: \texttt{clang-scan-deps}
\item Experimental module support in cmake since 3.26, uses \texttt{clang-scan-deps}, many fixes in later versions % see: https://discourse.cmake.org/t/c-20-modules-update/7330/24 and https://youtu.be/c563KgO-uf4?si=HUpnSivtDxvBoTr3&t=3592
\item MSBuild (Windows) fully handles dependency scanning
\item \cppinline{g++ a.cpp b.cpp ...} ``just works'', must be one line though
\item GCC uses a \href{https://wg21.link/P1184}{module mapper} to resolve imports, which specifies a protocol and uses a central server for module maintenance
\item \href{https://wg21.link/p1602}{Experimental extensions to GNU make} exist to grow dependency graph on the fly while modules are discovered
\item No support in cmake (3.23) yet
\item Header units unsupported in all build systems (May 2023) % See talk: https://youtu.be/_LGR0U5Opdg?si=yQoCYD2yGFhi_vs6&t=3768
\item C++23: \cppinline{import std;} supported in MSVC, partially in clang
\begin{itemize}
\item GCC/clang/MSVC also plan support in C++20 % see: https://github.com/microsoft/STL/issues/3945
\end{itemize}
\end{itemize}
\end{block}
\end{frame}
Expand All @@ -607,7 +624,9 @@
\frametitlecpp[20]{Building modules (g++)}
\begin{block}{Case study: g++}
\begin{itemize}
\item By default, g++ caches compiled module interfaces (CMI, i.e.\ BMI) in subdirectory \texttt{./gcm.cache}
\item BMI is called CMI (compiled module interfaces)
\item By default, g++ caches CMIs in subdirectory \texttt{./gcm.cache}
\item Uses a \href{https://wg21.link/P1184}{module mapper} to resolve imports, which specifies a protocol and uses a central server for module maintenance
\item Each module needs to be built before it can be imported
\begin{itemize}
\item {\footnotesize \cppinline{g++ -std=c++20 -fmodules-ts -c ratio.cpp -o ratio.o}}
Expand All @@ -630,27 +649,30 @@
\begin{itemize}
\item Start writing importable headers (no macro dependencies)
\begin{itemize}
\item This allows dual use: \cppinline{#include} before \cpp20 and \cppinline{import} with \cpp20
\item Dual use: \cppinline{#include} before \cpp20 and \cppinline{import} with \cpp20
\end{itemize}
\item Watch progress on module support in your build system
\end{itemize}
\end{exampleblock}
\begin{exampleblock}{Guidance for tomorrow}
\begin{itemize}
\item Start importing headers when \cpp20 is available
\item Start writing modules when all users of your code have \cpp20
\item Start using \cppinline{import std;} when \cpp23 is available
\item Start writing modules when your users have \cpp20
\item Maybe import standard headers when \cpp20 is available
\item Start using \cppinline{import std;} when available
\item Future of header units unclear (implementation difficulties)
\end{itemize}
\end{exampleblock}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[20]{Modules}
\begin{block}{Resources}
\small
\begin{itemize}
\item \href{https://www.youtube.com/watch?v=szHV6RdQdg8}{Practical C++ Modules - Boris Kolpackov - CppCon 2019}
\item \href{https://www.youtube.com/watch?v=nP8QcvPpGeM}{A (Short) Tour of C++ Modules - Daniela Engert - CppCon 2021} (very technical)
\item Understanding C++ Modules: \href{https://vector-of-bool.github.io/2019/03/10/modules-1.html}{Part1}, \href{https://vector-of-bool.github.io/2019/03/31/modules-2.html}{Part2} and \href{https://vector-of-bool.github.io/2019/10/07/modules-3.html}{Part3}.
\item \href{https://www.youtube.com/watch?v=DJTEUFRslbI}{So, You Want to Use C++ Modules … Cross-Platform? - Daniela Engert - C++ on Sea 2023}
\item \href{https://www.youtube.com/watch?v=c563KgO-uf4&t=686s}{import CMake: 2023 State of C++20 modules in CMake - Bill Hoffman - CppNow 2023}
\end{itemize}
\end{block}
\end{frame}
Expand Down

0 comments on commit 6df808e

Please sign in to comment.