Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support C++20 modules #4005

Open
abergmeier opened this issue Nov 1, 2017 · 60 comments
Open

Support C++20 modules #4005

abergmeier opened this issue Nov 1, 2017 · 60 comments
Assignees
Labels
P2 We'll consider working on this in future. (Assignee optional) team-Rules-CPP Issues for C++ rules type: feature request

Comments

@abergmeier
Copy link
Contributor

Description of the problem / feature request / question:

Starting to look into C++ Modules. While it will earliest officially arrive in 2020, would be good to have support for that soonish.
Heard there is some Module support inside of Google. Can/Will that be opensourced?

@katre katre added category: rules > C++ P2 We'll consider working on this in future. (Assignee optional) type: feature request labels Nov 2, 2017
@hlopko
Copy link
Member

hlopko commented Nov 3, 2017

Hi Andreas,
everything regarding modules (only for clang) is open sourced already. The only missing piece is a CROSSTOOL that makes use of them and provides all necessary features. But I think it would be quite a challenge to write such CROSSTOOL without understanding the implementation. If I don't find a good movie on my flight to bazel conference I might take a look and hack something together. No promises though, since this would be a free time exercise, not something that is a priority for bazel right now.

@hlopko hlopko added P3 We're not considering working on this, but happy to review a PR. (No assignee) and removed P2 We'll consider working on this in future. (Assignee optional) labels Nov 3, 2017
@abergmeier
Copy link
Contributor Author

Interesting.
@mhlopko Can you perhaps elaborate a bit, what parts of CROSSTOOL would interact with modules? Personally I thought it would be more in the realm of cc-providers and additional actions for module validity checks.

@hlopko
Copy link
Member

hlopko commented Nov 3, 2017

Yeah you are right, the implementation does deal with providers and actions, but all that logic is already in bazel and ready to be used. What is missing is a bunch of features (and maybe action_configs, I'm not sure) in the CROSSTOOL to pass the right flags for the right actions. Names of the features are hardcoded in bazel, so they need to match.

@hlopko
Copy link
Member

hlopko commented Nov 3, 2017

So in other words, it's all there, just not very well documented.

@abergmeier
Copy link
Contributor Author

just not very well documented

Like all else about CC toolchains you mean ;)

Thanks. I am trying to get a custom hermetic Clang toolchain running anyways. Perhaps will then try this out a bit.

@hlopko
Copy link
Member

hlopko commented Nov 3, 2017

Exactly :) I hope I'll see you next week on the crosstool breakout session during bazel conference? :) Btw, just wrote this yesterday, I really hope I'm not one day late: https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial

Anyway, don't hesitate to ask if you get stuck on the way. I'm also grateful for any input/comments/suggestions.

@abergmeier
Copy link
Contributor Author

Since I do have problems with the include paths for libc (https://stackoverflow.com/questions/47078520/clang-toolchain-fails-for-system-libc-files), how does libc_top (inputsForLibc) work?

Especially since I cannot seem to be able to glob system files.

@hlopko hlopko added team-Rules-CPP Issues for C++ rules and removed category: rules > C++ labels Oct 11, 2018
@ArekSredzki
Copy link
Contributor

Now that C++20 Modules are nearing standardization, could we get some updates on the status of properly supporting them within Bazel?

I was fortunate to attend CppCon this year and was excited to see that many build systems were making progress on supporting modules. Unfortunately, myself and other Bazel users that I spoke to were concerned that there was no Bazel-specific information on the topic.

@hlopko
Copy link
Member

hlopko commented Oct 16, 2019

We don't plan to work on C++ modules in 2019. We are discussing working on them in 2020 mostly in the context of objc and swift rules. We'll update this issue once we have more precise plans.

@ArekSredzki
Copy link
Contributor

Thanks @hlopko, I'm sure that much of the C++ Bazel community will very much value support for them. Looking forward to hearing more.

@hlopko hlopko removed their assignment Dec 6, 2019
@ctrysbita
Copy link

Any update here? :D

@ArekSredzki
Copy link
Contributor

@hlopko Is there anyone that we could ping regarding the timeline for supporting C++20 modules?
There appears to be significant community interest in this feature, it'd be good to set expectations :)

@hlopko
Copy link
Member

hlopko commented Oct 9, 2020

@oquenchil and @c-mita are authorities there.

@ArekSredzki
Copy link
Contributor

@oquenchil @c-mita Bump on the above? :)

@oquenchil
Copy link
Contributor

It might be that this gathers steam at the beginning of next year but I can't promise anything. In any case, it would be clang modules, not C++20 modules.

Whoever is interested in clang modules, definitely thumbs up the original issue above and that might help with prioritization.

@technoir42
Copy link
Contributor

technoir42 commented Oct 23, 2020

it would be clang modules, not C++20 modules.

Should we create a separate issue for C++20 modules then? I'm only interested in those as I'm using MSVC on Windows.

@oquenchil
Copy link
Contributor

Yes, you can create a separate issue for tracking C++20 module support. Be aware though that as it looks right now it will be a long time before we work on it, probably not next year.

@thii
Copy link
Member

thii commented Oct 23, 2020

Can you rename this issue to "Support Clang modules"?

@oquenchil oquenchil changed the title Support C++ modules Support clang modules Oct 23, 2020
@rnburn
Copy link

rnburn commented Oct 23, 2020

In any case, it would be clang modules, not C++20 modules.

@oquenchil - By "Clang modules", do you mean Clang's non-standard module system that pre-dates C++20 modules?

Why target that instead of C++20 modules? Clang supports a lot of the standard module spec already (blog post) -- I expect enough that people could start using it.

@prez
Copy link

prez commented May 13, 2022

So from reading this issue am I correct in assuming that currently there is no way to use cpp20 Modules in bazel? If so is there any chance we will get support in the near future?

This is over-the-wall-style open source. You'll see support exactly when google switches to C++20 internally, it will get implemented in like a week or two then.

@dpeter99
Copy link

You'll see support exactly when googling switches to C++20 internally

I know this. what I'm asking is if there is some way to use modules, like community-driven rules. Or if not that at least some update on when if ever we can expect Google to switch.
I'm asking because I'm currently setting up a new project that I want to use a monorepo style set up for, but I also would like to use cpp20 modules.

@MahmoodMahmood
Copy link

Any ETA on support for this?

@Genomorf
Copy link

Any update here?

@oquenchil
Copy link
Contributor

oquenchil commented Aug 12, 2022

@oquenchil would you be able to post a gist for the missing cc_toolchain features that are needed to try out clang modules (not c++ 20 modules)? It looks like there are a few -- use_header_modules, header_module_compile, header_module_codegen -- that I wasn't able to find in the toolchain config but exist in the java code. And with those features added, is it as simple as CC=clang and adding build --features=use_header_modules to .bazelrc to try it out?

I'm not sure whether it will just work, but here are the missing features that are in the internal toolchain:
https://gist.github.com/oquenchil/e6e39237b4c7b95b7b96396764b9a97c

You would need the module map features that are already in tools/cpp/unix_cc_toolchain_config.bzl

@det
Copy link
Contributor

det commented Aug 12, 2022

Thanks for the missing features @oquenchil!

I will note the following line from the header_module_compile feature:

"-Xcrosstool-module-compilation",

The string crosstool-module-compilation is not present in the Bazel or LLVM codebases. Is this likely to matter?

@det
Copy link
Contributor

det commented Aug 12, 2022

Shouldn't all those "-Xclang=-<flag>" be "-Xclang", "-<flag>"? My clang doesn't (14.0.1) seem to recognize the former.

@det
Copy link
Contributor

det commented Aug 14, 2022

So I took the new module's configuration you posted for a spin, but I am still running into the same problem as I was previously. It's not clear what to do about module maps for libc/libc++. You can merge them into the module_map artifact for the toolchain, but it will never be compiled by bazel. You must compile module maps which contain any non textual headers so I am not sure how to make this work. Is it possible there is some internal Google secret sauce that is missing before anyone else can use this? Maybe related to -Xcrosstool-module-compilation?

@hlopko
Copy link
Member

hlopko commented Aug 16, 2022

Yeah, there are a couple of things happening in the snippet @oquenchil shared.

  1. This is an internal toolchain that uses a a couple of clang wrappers. Those handle things like -Xclang=-<flag> flags or implement behavior needed for Bazel, for example ensuring that action doing header parsing creates an output.
  2. This snippet relies on having module_maps feature (I think this one works but I haven't tried). You also very likely need working layering_check and parse_headers features.
  3. And IMHO the biggest problem is the high-level design of internal support for Clang modules, at least for now. It is not assumed that all targets in the repository will be compiled into modules. Instead, only a couple of hand-picked, high value targets are compiled into modules, and everything else is built in a traditional way. The flag -fmodules-embed-all-files tells Clang to bundle the whole transitive closure of dependencies of a target into a single module. This will grow quadratically if enabled for all targets, but works quite nice for high value targets that don't change often. I can't say if this model works well for non-Google users though, and it is certainly not something that I'd have expected from Bazel.
  4. As @det points out, you need to manually create/generate a module map for your toolchain libraries. I might be wrong, but I think internally we don't actuallly generate a Clang module only for the C++ standard library, we generate them for some libraries that users commonly explicitly depend on, such as Abseil.

I guess the point I'm trying to make is that there is still a lot of work to be done to make Clang modules work in Bazel in general, and the snippet helps a bit, but do not assume that what you need is within a hand's reach. For context, there's a toolchain that Carbon folks use to build Carbon, and it doesn't support Clang modules, even though it is created by the group of engineers who helped to implement the support for Clang modules in Bazel internally.

@aaronmondal
Copy link

We just added highly experimental support for standard C++ modules in rules_ll (not the Clang variant with module maps). Considering how experimental C++ modules are currently in Clang/LLVM, things work quite well so far 😅

Build files look like this:

ll_library(
    name = "mymodule",
    srcs = ["m.cpp"]  # Module implementation unit
    transitive_interfaces = {"m.cppm": "m"},  # Mapping module interface unit to module name
)

ll_binary(
  name = "main",
  srcs = ["main.cpp"],
  deps = [":mymodule"],
)

Docs with examples and on how things work under the hood:
https://ll.eomii.org/guides/modules.html

@rnburn
Copy link

rnburn commented Sep 5, 2022

@aaronmondal - with your rules is there any way for module libraries to depend on regular cc_library's? I see this in the docs:

Every dependency needs to be an ll_library.

@aaronmondal
Copy link

@rnburn We have some logic to reuse already-built cc_libraries from the llvm-project overlay, and at a glance I think putting a cc_library in the llvm_project_deps may work. There may be a need to specify custom include paths, but apart from that I don't think that this attribute is actually specific to LLVM targets.

Note that ll_* targets will use a different toolchain than the cc_toolchain. I think we can go from cc_* to ll_*, but it would probably be very hard to go back. If cc_* targets work, we'll rename the llvm_project_deps attribute 😇

@HappyCerberus
Copy link

There seems to be some progress on the Clang side: https://releases.llvm.org/15.0.0/tools/clang/docs/StandardCPlusPlusModules.html

Any corresponding changes on Bazel's side?

@aaronmondal
Copy link

aaronmondal commented Oct 2, 2022

@HappyCerberus This is the one we implemented in rules_ll. The current state is likely not stable enough for native rules. For instance, lambdas are not merged correctly in certain cases and we cannot use Clang's BMI caching system when building modules with Bazel.

Currently, BMIs contain absolute paths to their sources at the time of precompilation. This means that sandboxed precompilations are hard to implement and BMIs are currently not reproducible. We have not yet managed to get rid of these sandbox paths, so we work around this by disabling sandboxing for precompilations. This is not ideal and would not be viable in the native rules.

We didn't try with libstdc++, but libcxx still requires manual patching to work with global module fragments. This is another big limitation. Even if the native rules supported C++ modules, they would be essentially unusable since they use the host's C++ standard library.

So for C++ modules to be viable in native rules, distributions will need to distribute libcxx 16 or 17, assuming that the current issues are fixed by then. Otherwise there would be infinite bug reports because not even <iostream> works without patches.

@nadiasvertex
Copy link

C++23 is here... any progress on this? I can't find anything definitive from Google.

@aaronmondal
Copy link

rules_ll upstream supports the std module from libc++, and Clang 17 will ship the std module as an experimental preview. Most issues have been fixed, and I'd consider modules as pretty much fully usable.

A few issues remain which I could imagine to be fairly hard blockers for rules_cc:

  • Modules built with Clang aren't reproducible. Some absolute paths leak into BMIs. This means that you can't use them with remote execution. This is a tricky situation and a critical issue for Bazel because this can subtly poison your cache and might go unnoticed for a long time.
  • BMIs aren't movable. Modules have to be distributed as .cppm files and they have to be built locally. If you depend on a modularized external dependency, you can't import a prebuilt BMI of that dependency. You have to build the entire dependency from source yourself. Not an issue if you do that anyways, but many users would probably prefer including some headers and linking a prebuild archive over building the entire dependency from source.
  • There is no interop with modules and heterogeneous code. If you want to use modules and let's say CUDA in the same project, you need a very specific code layout to ensure that the CUDA code and module code never see each other during compilation and only get combined during linking.

We'll probably need distros to actually ship Clang 17 with the std module .cppm files to get a better feeling on what's good and bad for build-system UX with modules. The implementation in rules_ll certainly has some subtleties regarding inter-module visibility that I've reworked several times now and might have to rework several times more.

Then again C++23 is basically Rust already. Seems like that's also where all the Bazel engineering power is being redirected to. I wouldn't find it too surprising if the recommendation for the future is to just not write new C++ and use rules_rust with crubit for legacy-compatibility instead 😄

@nadiasvertex
Copy link

That’s a shame. I was hoping to use Bazel for a large project we are migrating. C++20 modules are more important to me than Bazels many advantages, and rules_ll is a non-starter because I need to support macOS and Windows.

Maybe next year things will be better.

@BorisChenCZY
Copy link

Do we have any update on this?

@BorisChenCZY
Copy link

I'm also quite interested in contributing this featuer. Is there any guidance on this for me to do so?

@nadiasvertex
Copy link

I would help with such an effort too.

@oquenchil
Copy link
Contributor

See #4005 (comment)

@nadiasvertex
Copy link

See #4005 (comment)

It sounds like that is basically saying nothing is done and some one wanting good support should start from scratch.

@jsharpe
Copy link

jsharpe commented Sep 5, 2023

Note also that post was referring to clang modules and not c++20 modules; this issue got hijacked from clang module support to c++ 20 at some point in the history of this issue.

@PikachuHyA
Copy link

Dear all, the support for C++20 Modules is here.
PR: #19940
design doc: bazelbuild/proposals#354
discussion: #19939
a demo built with C++20 Modules (about 10 kloc): https://github.com/PikachuHyA/async_simple
extra tests: https://github.com/PikachuHyA/bazel_cxx20_module_test
the new bazel is built by GitHub Action, see https://github.com/PikachuHyA/bazel/actions/runs/6638058320
you can download the prebuilt version and play with your code.
Feedback is very welcome.
please note, only Clang is supported now. and Clang 17 or higher is required.

@kelteseth
Copy link

This issue is track it on https://arewemodulesyet.org/tools/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P2 We'll consider working on this in future. (Assignee optional) team-Rules-CPP Issues for C++ rules type: feature request
Projects
None yet
Development

No branches or pull requests