https://buildingblock.ai/cpp20-modules-bazel/ [PjwhRE9DVF] Reference GitHub How to Use C++20 Modules with Bazel and ClangP Modules are a feature added to C++20 that aims to provide better encapsulation and faster build times. While modules are not fully supported by compilers and probably not ready for use in production code, Clang's support is fairly usable. In this guide, I'll show you how to use modules with Clang and the Bazel build system by making use of the project github.com/rnburn/ rules_cc_module. Let's look at it works on a simple hello world program. Hello World ExampleP Suppose we have the following code // hello.ixx export module hello; import ; import ; export inline void say_hello(std::string_view const &name) { std::cout << "Hello " << name << "!\n"; } and // main.cc import hello; import ; int main() { say_hello("world"); return 0; } The code creates module hello with a function say_hello and calls it from main. To set this up in bazel, we can write the following BUILD file: load("//cc_module:defs.bzl", "cc_module", "cc_module_binary") cc_module( name = "hello", src = "hello.ixx", copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], deps = [ ":std", ], ) cc_module_binary( name = "a.out", srcs = [ "main.cc", ], deps = [ ":hello", ":std", ], copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], linkopts = [ "-stdlib=libc++", ], ) cc_module( name = "_Builtin_stddef_max_align_t", is_system = True, copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], ) cc_module( name = "std_config", is_system = True, copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], deps = [ ":_Builtin_stddef_max_align_t", ], ) cc_module( name = "std", is_system = True, copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], deps = [ ":std_config", ], ) cc_module sets up our module with the say_hello function. In order to make use of standard c++ library components in their module form, we also need to set up the system modules _Builtin_stddef_max_align_t, std_config, and std. But what if we want say_hello to be in a translation unit instead of an inline function? Then we can refactor the module to use an implementation unit. // hello.ixx export module hello; import ; export void say_hello(std::string_view const &name); and // hello.cc module hello; import ; import ; void say_hello(std::string_view const &name) { std::cout << "Hello " << name << "!\n"; } We update the BUILD file to # ... cc_module( name = "hello", src = "hello.ixx", impl_srcs = [ "hello.cc", ], copts = [ "-fmodules", "-fbuiltin-module-map", "-stdlib=libc++", "-std=c++20", ], deps = [ ":std", ], ) # ... The full source code for this and other examples are available in github/rnburn/rules_cc/examples. Setting up a ProjectP Tracking all of those dependencies and options can be tedious. Let's consider how we might set up a full project to avoid the boilerplate. First, we'll add a .bazelrc file at the project root to specify all the options we use # .bazelrc build --copt -std=c++20 build --copt -fmodules build --copt -fno-implicit-modules build --copt -fbuiltin-module-map build --copt -stdlib=libc++ build --linkopt -stdlib=libc++ Next, we'll make a file toolchain/BUILD that sets up the standard library modules. # toolchain/BUILD load("@com_github_rnburn_bazel_cpp20_modules//cc_module:defs.bzl", "cc_module") package(default_visibility = ["//visibility:public"]) cc_module( name = "_Builtin_stddef_max_align_t", is_system = True, ) cc_module( name = "std_config", is_system = True, deps = [ ":_Builtin_stddef_max_align_t", ], ) cc_module( name = "std", is_system = True, deps = [ ":std_config", ":_Builtin_stddef_max_align_t", ], ) Then we'll make a file bazel/build_system.bzl which adds macros to automatically inject the standard library dependencies. # bazel/build_system.bzl load("@com_github_rnburn_bazel_cpp20_modules//cc_module:defs.bzl", "cc_module", "cc_module_binary") def zoo_cc_module(name, deps = [], *args, **kwargs): cc_module( name = name, deps = deps + ["//toolchain:std"], *args, **kwargs) Now, we can write BUILD files like this # zoo/mammals/BUILD load("//bazel:build_system.bzl", "zoo_cc_module") package(default_visibility = ["//visibility:public"]) zoo_cc_module( name = "zoo.mammals.tiger", src = "tiger.ixx", impl_srcs = [ "tiger.cc", ], ) A full project example is available at github.com/rnburn/ cpp20-module-example. Stay up to date [ ]