Building mbun With Bazel
Author’s note: This article was created with substantial AI assistance.
mbun (an experimental project that rewrites the Bun runtime in C++26 and C++ modules) was originally built using the custom mcpp toolchain.
This migration introduces a Bazel 9 build on top of baseline 5a901d7 to test Bazel’s support for C++20 modules. Previously, when testing modules, the module version of async_simple was the only available open-source project suitable for testing. mbun itself is a native modules project (with 98 modules), making it an ideal test case for Bazel and Clang’s module support. The mcpp build system has not been removed; both systems coexist during the migration. The BUILD.bazel files retain comments mapping them to the mcpp manifests (for example, src/BUILD.bazel maps each item to [targets.mbun] / [dependencies] in mcpp.toml).
The complete code is available at https://github.com/PikachuHyA/mbun/tree/bazel_build_mbun_opensource_20260805.
An Empirical Study of Module Maps: Faster C++ Builds Without Changing Source Code
Large C++ projects often spend a surprising amount of time repeatedly parsing the same third-party headers. Header-only and template-heavy libraries make this even worse: every translation unit pays the cost again.
C++20 Modules provide a way out, but fully migrating a large codebase from #include to import is rarely realistic. This article describes a more incremental approach: use Clang module maps to translate selected #include directives into module imports during the build, while keeping application source code unchanged.
Bazel cc_shared_library Explained
cc_shared_library is a Bazel rule for building C++ shared libraries (.so/.dll). Unlike the simple cc_binary(linkshared=1), it provides fine-grained dependency management, intelligently deciding which libraries should be statically linked into the shared library and which should be obtained through dynamic dependencies.
This blog provides an in-depth analysis of the cc_shared_library implementation to help you understand its internal workings.
C++ Code Coverage with Bazel
Recently, it was reported that C++20 module interface files generate no code coverage data. Upon investigating, I discovered that this is due to an instrumentation file that only accounts for explicitly instrumented files. If a file is not listed, its coverage data is skipped. For more details, refer to CoverageOutputGenerator–Main.java#L151-L155.
To address this, I’ve created a patch to include module interfaces in the instrumentation file. Below is the fix:
Bazel collect2: fatal error: cannot find 'ld' with build
The issue at hand stems from the linker ld.lld, which is specified by the -fuse-ld=lld option, not being present in the PATH during the binary linking process. The error message “cannot find ’ld’” can be misleading; it does not refer to /usr/bin/ld, but rather indicates a failure to locate ld.lld. The resolution involves adding the directory containing ld.lld to your PATH, either by overriding the PATH variable directly or by using --host_action_env=PATH=xxx.