Building C++ Modules - Boris Kolpackov - CppCon 2017
Building C++ Modules - Boris Kolpackov - CppCon 2017
Boris Kolpackov
Code Synthesis
CODE
SYNTHESIS
-1-
Practical C++ Modules
-2-
Why Modules?
-3-
Speed!!!
-4-
What is a Module?
Three Perspectives
• module consumer
• module producer
• build system
-5-
What is a Module?
Language-level mechanism:
import hello.core;
Not preprocessor-level:
#import hello.core
-6-
Modules from Consumer Perspective
import hello.core;
-7-
Modules from Consumer Perspective
-8-
Modules and Namespaces
-9-
Modules and Namespaces
-9-
Module and Libraries
-10-
Modules from Producer Perspective
-11-
Modules from Producer Perspective
-12-
Modules Interface Unit
-13-
Modules Implementation Unit
module hello.core;
-14-
Interface File Extensions
-15-
Interface File Extensions
My recommendation:
.hpp/.cpp .mpp
.hxx/.cxx .mxx
Other? Switch!
-15-
Module Purview
-16-
Module Export
-17-
Export Specifier
-18-
Exported Group
export
{
enum class volume {quiet, normal, loud};
-19-
Exported Namespace
namespace hello
{
void impl (const char*, volume); // Not exported.
}
-20-
Module Ownership Model
-21-
Module Ownership Model
-22-
Modules and Preprocessor
-23-
Import Visibility
// hello.extra interface
//
export module hello.extra;
// hello.extra implementation
//
module hello.extra;
-24-
Import Visibility
// hello.extra interface
//
export module hello.extra;
// hello.extra implementation
//
module hello.extra;
-24-
Import Visibility
// hello.extra interface
//
export module hello.extra;
// hello.extra implementation
//
module hello.extra;
-24-
Import Visibility
// hello.extra interface
//
export module hello.extra;
// hello.extra consumer
//
import hello.extra;
-25-
Import Visibility
// hello.extra interface
//
export module hello.extra;
// hello.extra consumer
//
import hello.extra;
-25-
Re-Export
// hello.extra interface
//
export module hello.extra;
// hello.extra consumer
//
import hello.extra;
-26-
Re-Export and Submodules
export
{
import hello.core;
import hello.basic;
import hello.extra;
}
-27-
Modules from Build System Perspective
-28-
Hello Module
// hello.mxx
export module hello;
export void say_hello (const char* name);
// hello.cxx
#include <iostream>
module hello;
// driver.cxx
import hello;
// hello.cxx
#include <iostream>
module hello;
// driver.cxx
import hello;
// hello.cxx
#include <iostream>
module hello;
// driver.cxx
import hello;
// hello.cxx
#include <iostream>
module hello;
// driver.cxx
import hello;
cl /D_CRT_SECURE_NO_WARNINGS -IC:\tmp\build\libodb-sql
ite-2.5.0-b.6.1503567680.1432c5607115e465 -IC:\tmp\bui
ld\libodb-sqlite-2.5.0-b.6.1503567680.1432c5607115e465
-DLIBODB_SQLITE_BUILD2 -DLIBODB_SQLITE_SHARED_BUILD -I
C:\tmp\build\libodb-2.5.0-b.6.1503567043.6b15416ac28ad
a02-IC:\tmp\build\libodb-2.5.0-b.6.1503567043.6b15416a
c28ada02 -DLIBODB_BUILD2 -DLIBODB_SHARED -IC:\tmp\buil
d\libsqlite3-3.18.3-a.0.1503562393.3c9bf2b8ce40e258\li
bsqlite3 -DSQLITE_API=__declspec(dllimport) /W3 /WX /w
d4251/wd4275 /nologo /EHsc/MD /Fo: libodb-sqlite-2.5.0
-b.6.1503567680.1432c5607115e465\odb\sqlite\database.d
ll.obj /c /TP C:\tmp\build\libodb-sqlite-2.5.0-b.6.150
3567680.1432c5607115e465\odb\sqlite\database.cxx
-30-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with GCC
$ ls -1
hello.mxx
hello.cxx
driver.cxx
-31-
Compiling with Clang
$ clang++ -std=c++2a -fmodules-ts --precompile \
-x c++-module [...] -o hello.pcm hello.mxx
-32-
Compiling with Clang
$ clang++ -std=c++2a -fmodules-ts --precompile \
-x c++-module [...] -o hello.pcm hello.mxx
-32-
Compiling with VC
-33-
Modules from Build System Perspective
-34-
Compilation of Header Project
hello.cxx
driver.cxx
time
-35-
Compilation of Module Project
hello.cxx
hello.mxx driver.cxx
time
-36-
More Complex Module Project
$ ls -1
core.mxx
extra.mxx # imports hello.core
hello.mxx # re-exports hello.core and hello.extra
core.cxx
extra.cxx
-37-
Compilation of Complex Module Project
extra.mxx hello.mxx
time
-38-
Compilation of Generated Header Project
hello.cxx
driver.cxx
time
-39-
Compilation of Generated Header Project
hello.cxx
hello.hxx driver.cxx
time
-39-
Modules Support via Ad Hoc Pre-Build Step
-40-
Compilation via Ad Hoc Pre-Build Step
core.cxx
extra.cxx
time
-41-
What’s in a BMI?
-42-
What to Install/Distribute?
-43-
Standard Library Modules (P0581R0)
-44-
Module Design Guidelines
• Explicit exportation
• Module purview
• Module building
-45-
Module Granularity
-46-
Module Granularity
• xml.parser
• xml.serializer
-47-
Module Partitioning into Units
• Unnecessary recompilation
-48-
Module Partitioning into Units
-49-
Module-Only Libraries
import std.core;
import std.io;
-50-
Module-Only Libraries
• ODR violations
• Incompatible versions
-51-
First Real Module
• In what order?
-52-
First Real Module
// Old rules.
// New rules.
-53-
First Real Module
#include <string>
...
-54-
Where to Include?
-55-
First Real Module
#include <string>
#include <libhello/export.hxx>
#include <libhello/hello.ixx>
-56-
Where to Import?
-57-
Where to Import?
-58-
First Real Module
#include <cassert>
import std.core;
#include <libhello/export.hxx>
#include <libhello/hello.ixx>
-59-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Interface Template
<header includes>
<module imports>
export
{
<module interface>
}
<inline/template includes>
-60-
Module Implementation Template
<header includes>
<module implementation>
-61-
Module Implementation Template
<header includes>
<module implementation>
-61-
Module Implementation Template
<header includes>
<module implementation>
-61-
Module Implementation Template
<header includes>
<module implementation>
-61-
Module Naming
-62-
Module Naming
-63-
Module Naming Examples
• Library name: libbutl
• Library namespace: butl
• Library modules:
butl.base64 butl.path
butl.char_scanner butl.path_io
butl.const_ptr butl.path_map
butl.diagnostics butl.process
butl.fdstream butl.sha256
butl.filesystem butl.small_vector
butl.manifest_parser butl.string_parser
butl.manifest_serializer butl.string_table
butl.multi_index butl.target_triplet
butl.openssl butl.timestamp
butl.pager butl.vector_view
-64-
When to Re-Export?
-65-
When to Re-Export?
-65-
Modularizing Existing Code
-66-
Modularizing Existing Code
Bad Idea!
export
{
#include ”hello.hxx”
}
-67-
Guerrilla Modularization
export
{
#include ”hello.hxx”
}
-68-
Modularizing Existing Code
-69-
Modularized Standard Library
-70-
Modularized Standard Library
module hello.extra;
import std.io;
-71-
Modularizing Own Code
-72-
Modularizing Existing Code
module hello.extra;
-73-
Backwards Compatibility
• modules-only
• modules-or-headers
• modules-and-headers
-74-
Modules-Only
-75-
Modules-or-Headers
-76-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Interface
#ifndef __cpp_modules
#pragma once
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
#endif
#ifdef __cpp_modules
export module <name>;
#ifdef __cpp_lib_modules
<std imports>
#endif
#endif
-77-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Implementation
#ifndef __cpp_modules
#include <module interface file>
#endif
// C includes, if any.
#ifndef __cpp_lib_modules
<std includes>
<extra std includes>
#endif
#ifdef __cpp_modules
module <name>;
#ifdef __cpp_lib_modules
<extra std imports> // Only additional to interface.
#endif
#endif -78-
Modules-or-Headers Consumer
#ifdef __cpp_modules
import hello;
#else
#include <libhello/hello.mxx>
#endif
-79-
Modules-and-Headers
-80-
Questions?
build2.org
Build System Manual → C++ Modules Support
Acknowledgements
Andrew Pardoe (VC/Microsoft)
David Blaikie (Clang/Google)
Gabriel Dos Reis (VC/Microsoft)
Nathan Sidwell (GCC/Facebook)
Richard Smith (Clang/Google)
-81-