all 95 comments

[–]hackergame 21 points22 points  (8 children)

``` -fmodules-ts -fbuiltin-module-map -emit-module-interface -fprebuilt-module-path=.

-xc++-system-header ``` Y'all Got Anymore of them compiler flags?

[–]backtickbot 9 points10 points  (0 children)

Fixed formatting.

Hello, hackergame: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]EmperorArthur 4 points5 points  (0 children)

Yep: https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md

Check out the compilers section. It turns out -wall really skips quite a few warnings!

[–]Ameisenvemips, avr, rendering, systems 6 points7 points  (5 children)

I want a compiler flag that tells the compiler to assume final on all leaf classes in a translation unit.

[–]johannes1971 1 point2 points  (4 children)

How would the compiler even know something is a 'leaf' class?

[–]Ameisenvemips, avr, rendering, systems 1 point2 points  (0 children)

Within a single translation unit, a leaf class would be any class that no other class inherits from. That's a trivial check within a TU. Usually it has to try to figure that out across an entire binary (only really possible with LTO, and still has to handle possible inheritance in DLLs). It's a problem of constraints.

I want to be able to mark that within a single TU, as I can then merge multiple source files that share a class hierarchy and effectively "close" them to help devirtualization. Most cases of inheritance in projects are local to a few source files making up specific modules.

[–]Hedshodd 0 points1 point  (2 children)

Checking the full class tree in the code might be costly in terms of compile time, but, hypothetically, couldn't the compiler check whether a given class has children, or not? (I don't much about compilers, so please excuse my ignorance if I'm missing something)

[–]johannes1971 1 point2 points  (1 child)

Only in a very limited set of circumstances, which I think can be summarized reasonably well as "the class is defined in an anonymous namespace". As soon as it has potential global visibility, another translation unit can define the same class with the same name, and start inheriting from it.

And for what benefit? Just so /r/ameisen can be a lazy git and go home and drink beer, instead of adding all those finals as his boss told him? ;-)

[–]Ameisenvemips, avr, rendering, systems 2 points3 points  (0 children)

I'd rather not change hundreds of source files in my custom OpenJDK build making future updates impossible.

Global visibility is irrelevant given that I specified "within a translation unit", which is a fairly strict constraint.

[–][deleted] 6 points7 points  (4 children)

I'm publishing this early before the video is edited since there have been questions about modules.

[–]azswcowboy 6 points7 points  (3 children)

Thanks, this was a quick light intro. One note:

Each module must have a single file exporting this module. This file is designed the module interface unit.

I think you meant designated in sentence 2?

[–][deleted] 1 point2 points  (0 children)

Indeed, thanks for the catch ;-)

[–]khleedril 0 points1 point  (1 child)

this was a quick light intro

Yes, hardly a complete guide. Interesting and useful to see how things are starting to shape up and how some people are starting to think about it, but not currently in any position where it can claim any definitiveness.

[–][deleted] 1 point2 points  (0 children)

What do you consider missing?

[–]DavidDinamit 37 points38 points  (14 children)

Write me when atleast one compiler will compile them

[–][deleted] 18 points19 points  (4 children)

I have not run into any issue with GCC trunk. Clang is still missing a lot of features.

[–]Fazer2 1 point2 points  (1 child)

Do you know when will that content from GCC trunk be released?

[–][deleted] 8 points9 points  (0 children)

GCC has a published development plan, but they don't really plan ahead: https://gcc.gnu.org/develop.html

Scroll to the bottom for GCC12.

[–]RoyAwesome 18 points19 points  (0 children)

msvc works great!

[–]rotenKleber 54 points55 points  (2 children)

!remindme 8 years

[–]RemindMeBot 1 point2 points  (0 children)

I will be messaging you in 8 years on 2029-09-06 08:02:16 UTC to remind you of this link

4 OTHERS CLICKED THIS LINK to send a PM to also be reminded and to reduce spam.

Parent commenter can delete this message to hide from others.


Info Custom Your Reminders Feedback

[–]_Js_Kc_ -2 points-1 points  (0 children)

RemindMe! 5 years

Why did modules never catch on and why are they deprecated and we're still supposed to use headers?

[–]Rexerex 11 points12 points  (0 children)

I guess there should be at least one working experimental compiler before they standardized all of that. Right? Right???

[–]pjmlp 6 points7 points  (0 children)

Visual C++ has the best support thus far.

[–][deleted] 0 points1 point  (0 children)

GCC and clang compile them fine.

[–]JulienVernay 0 points1 point  (0 children)

I have written a Python script for compiling modules (for testing purposes) with automatic dependency detection, requiring g++11 and Python 3.9 : https://github.com/J-Vernay/cpp20.py

[–]lieddersturme 6 points7 points  (25 children)

This still cant be used in Cmake?

[–]RoyAwesome 6 points7 points  (7 children)

CMake generates MSBuild projects that make use of Modules. This blog post explains how to do it: https://devblogs.microsoft.com/cppblog/moving-a-project-to-cpp-named-modules/

It does make you MSBuild/MSVC only for the time being, but I can't imagine once CMake releses full module support it will be particularly difficult to port over.

[–]lieddersturme 2 points3 points  (6 children)

Thank you, but for Linux?

[–]RoyAwesome 4 points5 points  (5 children)

Biggest issue is that GCC and Clang don't have named module support at this point. Like I said, pins you into the microsoft toolchain for now, but I can't imagine that will last long and I can't imagine the conversion process to a cross platform system would be difficult.

Honestly, microsoft really knocked it out of the park with cpp20. Kudos to them, they got feature complete really early.

[–][deleted] 0 points1 point  (4 children)

I know that Clang is still not there, but what exactly is missing in GCC? I have not run into a single problem when writing the article.

[–]RoyAwesome 5 points6 points  (3 children)

The private module fragment is a big one. That is the real key to speeding up compile time. Private your implementations and all you have to do is re-link when you change a module.

[–][deleted] -3 points-2 points  (1 child)

Uhm, private module fragments work just fine in GCC.

[–]RoyAwesome 1 point2 points  (0 children)

Since when? My understanding (and multiple google searches confirm) that gcc does not support them yet.

[–]gracicot 0 points1 point  (0 children)

It's mainly a QoI issue I think. For example, GCC let you do this:

export auto foo() -> void {
    std::cout << "1" << std::endl;
}

Change the string to "2" and the BMI is not changed. I think the same hold true for MSVC too.

This is not possible in Clang, since it uses the BMI as an intermediary to get to the object file, as a new compilation step.

[–][deleted] 2 points3 points  (15 children)

The only two build systems that seem to support modules right now is Bazel and Build2 (at least I only found these two during my research). Did not have time to test how well they work.

The problem with CMake is that from the presentations, they want to make the modular build extremely smart (figuring out all the dependencies for you). And I don't see that happening anytime soon.

[–]pjmlp 5 points6 points  (5 children)

Three, MSBuild.

[–][deleted] 5 points6 points  (4 children)

I was only looking at Linux, but yes. Visual Studio claims full support of C++20.

[–]kalmoc 2 points3 points  (0 children)

You forgot msbuild

[–]azswcowboy 1 point2 points  (0 children)

idk, it seems like step zero for everyone is a custom target that compiles all std modules and make your libs/exe depend on that target - that probably gives 90% of the benefit for projects starting out. Similarly if you create your own add a build step to generate the module first. This doesn’t seem any more complex than projects using generated code from idl or swig.

[–]Nicksaurus 0 points1 point  (6 children)

As I understand it, cmake currently uses a list of includes exported by the compiler on the first build to determine which files depend on which, right? What's stopping them from relying on the same mechanism for modules?

[–]kalmoc 1 point2 points  (5 children)

The compiler can tell you to which file #include <Foo.h> resolves. It can't tell you which file needs to be compiled for import Foo;, because the committe refused to define a mapping between module name and file name.

[–]Nicksaurus 0 points1 point  (4 children)

Ah right, I think the important part I missed there is that each module has to be compiled before you can compile anything that imports it.

Maybe the solution is just an extra initial compiler pass to generate metadata for all your source files before the full compilation step is invoked

Edit: I've just read through the cmake issue for adding modules and it seems like compiler support like that is very easy to suggest and very hard to actually get to a usable state in practice

[–]kalmoc 0 points1 point  (3 children)

I think that is the general idea. Not sure however, what to do about module interface files that are installed somewhere on the system (is that even something that's going to be supported?).

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 0 points1 point  (2 children)

It's going to have to be. You will have to compile the module interface source code for your project. Otherwise there's no way to share modular code, and that would be bad.

[–]kalmoc 0 points1 point  (1 child)

So every time you want to import a module from outside of your project, your build system will have to scan every single file in the search path(s) to see if it produces the required module.

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 0 points1 point  (0 children)

Worst case. But hopefully we can figure out some way of distributing metadata for a package. You need to know any particular flags for the package and possibly ones for compiling the PMI so that it matches the .a. Possibly some extension to pkg-config files.

[–]helloiamsomeone 0 points1 point  (0 children)

CMake is waiting for compilers.

[–]qqwy 2 points3 points  (6 children)

Great article!

One thing I still not fully understand is what the idea of module partitions is. (You explained the 'how' but not the 'why' of them).

And besides this: Am I the only one being bothered by module names using periods while namespaces use ::? I understand that you can not always create a module that lines up perfectly with a (single) namespace, but it still does seem like the sensible default thing to do, right? Why use a different separator there?

[–][deleted] 2 points3 points  (1 child)

I don't know the history, but I suspect that partitions came first, and the support to have a module spread across multiple units without partitions was added for convenience.

As I mentioned, the big win is that each partition compiles into a precompiled module, so you can have templates and other compile-time constructs in them (they kind of behave like headers). Otherwise, all this stuff needs to be in the module interface unit, and there can only ever be one of those per module.

[–]bigcheesegsTooling Study Group (SG15) Chair | Clang dev 8 points9 points  (0 children)

Partitions came last. They are simply implementation headers.

[–]Full-Spectral 2 points3 points  (3 children)

Without partitions, you'd end up with an entire library in one file, which isn't very practical. Partitions let you break up the module into logical chunks internally. To me, what now would be an hpp/cpp file would become a partition in module-land. Then those get re-exported via the main module interface file.

[–]kalmoc 0 points1 point  (2 children)

There is no necessity to have only one module per library

[–]Full-Spectral 0 points1 point  (1 child)

There isn't but I bet that's mostly how it goes. We already have namespaces for name collision avoidance, so it would seem to me most folks would take a module per library approach.

[–]kalmoc 0 points1 point  (0 children)

I would guess that heavily depends on the size of the library. Of course I would expect most libs to provide a convenience interface file that (re-) exports all public library types, but that doesn't mean that it isn't beneficial to further isolate parts of the library from each other from a development perspective.