back

by jjmarr·4mo ago·view on hn ↗
You don't on new projects. CMake + ninja has support for modules on gcc, clang, and MSVC.

This should be your default stack on any small-to-medium sized C++ project.

Bazel, the default pick for very large codebases, also has support for C++20 modules.

3 comments
I have yet to see modules in the wild. What I have seen extensively are header-only projects.
It's the fault of built systems. CMake still doesn't support `import std` officially and undocumented things are done in the ecosystem [1]

But once it works and you setup the new stuff, having started a new CPP26 Project with modules now, it's kinda awesome. I'm certainly never going back. The big compilers are also retroactively adding `import std` to CPP20, so support is widening.

[1] https://gitlab.kitware.com/cmake/cmake/-/work_items/27706

I wanted to ship import std in 4.3 but there are some major disagreements over where the std.o symbols are supposed to come from.

Clang says "we don't need them", GCC says "we'll ship them in libstdc++", and MSVC says "you are supposed to provide them".

I didn't know about that when I was working on finishing import std for CMake and accidentally broke a lot of code in the move to a native implementation of the module manifest format, so everything got reverted and put back into experimental.

That's really interesting info, thanks!
weird to blame build systems for a problem caused by the language
You are of course right. It's just that Modules inherently put a lot of responsibility on the build system. Among those, but not limited to: a "module registry" wasn't standardized and is in the hands of the build system.

Systems like ninja needs to know modules, which took time and then a stack further up systems like CMake needed to know modules, which took time. That's my answer to the parent "why are there so few modules projects". Because it took time for the ecosystem to catch up.

You're not supposed to distribute the precompiled module file. You are supposed to distribute the source code of the module.

Header-only projects are the best to convert to modules because you can put the implementation of a module in a "private module fragment" in that same file and make it invisible to users.

That prevents the compile-time bloat many header-only dependencies add. It also avoids distributing a `.cpp` file that has to be compiled and linked separately, which is why so many projects are header-only.

What I mean is, I have yet to see projects in the wild _use modules at all_.
Plenty of examples on Github, Microsoft has talks on how Office has migrated to modules, and the Vulkan updated tutorials from Khronos, have an optional learning path with modules.
Modules need a lot of tooling. The tool vendors have been working hard on this for years. They have only just now said this is ready for early adopters. Most people are waiting for the early adopters to write the books on what best practices are - this needs a few more years of experience.
if something so simple needs years of experience it's poorly designed
Modules are not simple. They sound simple only to people who have never digged into them.
I've worked extensively on module/import semantics for multiple products in my life. It is complex. However this complexity is on the implementer and not the user.

If "best practices" need to be refined over years, it is poorly designed. This is not untrodden ground, other languages and ecosystems do sane things.

This was considered during standardization. The feeling among tool developers at the time was it was "close enough" to Fortran modules to be mostly solvable.

This was wrong, mostly because C++ compiler flag semantics are far more complicated than in Fortran, you live and you learn. The bones of most implementations is identical to Fortran though, we got a ~3 year head start on the work because of that.

Ninja already had the dyndep patch ready to go from Fortran, CMake knew basically how to use scanners in build steps. However, it took longer than expected to get scanner support into the compilers, which then delayed everything downstream. Understanding when BMIs need to be rebuilt is still tricky. Packaging formats needed to be updated to understand module maps, etc, etc.

Each step took a little longer than was initially hoped, and delays snowballed a bit. We'll get there.

Thanks. It's been a long time since I started a C++ project, and I've never set up any build chain in Visual Studio or Xcode other than the default.
How about using Zig to build C++ projects?
I haven't used it.

That being said, while it looks better than CMake, for anything professional I need remote execution support to deviate from the industry standard. Zig doesn't have that.

This is because large C++ projects reach a point where they cannot be compiled locally if they use the full language. e.g. Multi-hour Chromium builds.

Surely Zig can also be invoked using any CI/CD flow running on a remote machine too.
I'm referring to this:

https://github.com/bazelbuild/remote-apis

Once you get a very large C++ project with several thousand compilation jobs over hundreds of devs, you need to distribute the build across multiple computers and have a shared cache for object files.

Zig doesn't seem to support that.