-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[libcxx][clang-modules] Fix headers being marked as textual #130723
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
base: main
Are you sure you want to change the base?
Conversation
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
|
@llvm/pr-subscribers-libcxx Author: Matt (matts1) ChangesWhen building libcxx as a module, it fails to build because it's missing various definitions. Consider the following code for module A: With the module map file: Macro visibility rules state that "[macros] are visible if they are from the current submodule or translation unit, or if they were exported from a submodule that has been imported."
Module B exports: __config_site contents, __config_site header guard
Because it can see module B's exports, it stops at the header guard for __config_site and does not include __config_site. This is not an issue, however, because it has visibility onto everything exported from __config_site thanks to module B. Module A exports: __config contents, __config header guard, __config's includes' content and header guard (except __config_site)
Because of that, we see the header guard for __config and do not import it at all. This is mostly OK, as we can see the __config that module A exported. However, if we ever try and access __config_site, it will fail, as A did not export __config_site. Full diff: https://github.com/llvm/llvm-project/pull/130723.diff 1 Files Affected:
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index b9964dac84acd..b719f6d69273d 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1,13 +1,14 @@
// This module contains headers related to the configuration of the library. These headers
// are free of any dependency on the rest of libc++.
module std_config [system] {
- textual header "__config"
- textual header "__configuration/abi.h"
- textual header "__configuration/availability.h"
- textual header "__configuration/compiler.h"
- textual header "__configuration/language.h"
- textual header "__configuration/platform.h"
- textual header "version"
+ header "__config"
+ header "__configuration/abi.h"
+ header "__configuration/availability.h"
+ header "__configuration/compiler.h"
+ header "__configuration/language.h"
+ header "__configuration/platform.h"
+ header "version"
+ export *
}
module std_core [system] {
|
19092b4 to
7be9524
Compare
|
I'm not too familiar with this part. I've adjusted the description, the previous one was looking odd with the naming and no context. |
|
@atetubou Could you please review this, it seems like no-one is taking a look. |
7be9524 to
21b6a64
Compare
|
I'm still not sure what is the problem using
Include directly what?
|
I actually don't have commit access for llvm repository. So we anyway need to wait for review from someone who has commit access here. |
Not only that, but patches for libc++ should be reviewed by the libcxx-reviewers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch. I'm trying to understand the issue you're running into (I read the PR description a few times), and I'm struggling to understand how you run into this issue (especially why we don't run into it in our current modules build). Could you provide a reproducer for this issue? How do you come across it? You mention
When building libcxx as a module
but it's not clear to me what that means. Additionally, the modules CI job is now failing with issues like:
/.../libcxx/test/libcxx/libcpp_version.gen.py/experimental/iterator.compile.pass.cpp:8:3: error: <experimental/iterator> does not seem to define _LIBCPP_VERSION
# | 8 | # error <experimental/iterator> does not seem to define _LIBCPP_VERSION
# | | ^
# | 1 error generated.
There are also some XPASSes in tests like std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp. After investigating and reproducing locally (by applying your patch), what's happening with these XPASSes is that the testing configuration incorrectly defines the win32-broken-utf8-wchar-ctype Lit feature, because _LIBCPP_HAS_LOCALIZATION is not detected in the compiler macros here.
All in all, it seems like the net effect of making this change is that we don't export the __config_site macros out of libc++ anymore. Perhaps there's a simple fix, but I tried a couple of things locally with no success.
I don't have a problem with this patch as a matter of principle, but I'd like to understand what it fixes, add a test for that, and make sure that it doesn't break other stuff.
CC @ian-twilightcoder for general modules expertise
|
None of these should be |
21b6a64 to
a050cf2
Compare
When building libcxx as a module, it fails to build because it's missing various definitions.
Consider the following code for module A:
```
#include <module B that includes config_site>
#include <config>
#include <module C that includes config>
```
With the module map file:
```
module std {
module A { header "a.h" }
module B { header "b.h" }
module C { header "c.h" }
}
```
Macro visibility rules state that "[macros] are visible if they are from the current submodule or translation unit, or if they were exported from a submodule that has been imported."
* Module A has visibility of all macros exported by modules B and C (because they were exported from an imported submodule)
* Module B and C have visibility over all macros exported by module A (because they are from the current submodule)
1) When we #include the first line, module B successfully includes config_site.
Module B exports: config_site contents, config_site header guard
2) Module A now `includes <config>` directly
Because it can see module B's exports, it stops at the header guard for config_site and does not include config_site. This is not an issue, however, because it has visibility onto everything exported from config_site thanks to module B.
Module A exports: config contents, config header guard, config's includes' content and header guard (*except config_site*)
3) Module C now includes config. Based on the above visibility rules, it can see everything exported from module A.
Because of that, we see the header guard for config and do not import it at all. This is mostly OK, as we can see the config that module A exported. However, if we ever try and access config_site, it will fail, as A did not export config_site.
a050cf2 to
28e79c6
Compare
I'm on the chrome build team, and we're trying resolve #127012. We want to build libc++ into .pcm files, but this is currently not possible. We have a (build file) that you can see the general idea in. The reason this is not occuring in the modules CI builder is because the modules CI builder doesn't do this (I don't know what it does, but I know it's currently unsupported).
That's correct. I believe I've now fixed it though.
This is impossible to write a test for currently, since even with this fix, it still won't work (it needs several different patches, all of which need to be submitted before it starts working). I'm hoping you'll be satisfied with "it doesn't break anything existing, and @ian-twilightcoder it shouldn't be textual, so the current definition is incorrect". FWIW, with this patch (and a few others, eg #132125), I've successfully built the whole of Chrome. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of these should be
textualbecause they have declarations, which becomes a problem because their declarations build into all of their (transitive) includers' modules.
@ian-twilightcoder Correction, they don't contain declarations -- macros only. That may not change the fact that these shouldn't be textual, but I still wanted to clarify.
I'm on the chrome build team, and we're trying resolve #127012. We want to build libc++ into .pcm files, but this is currently not possible. We have a (build file) that you can see the general idea in.
Thanks, that's very helpful context.
There's a few places where you folks mentioned "explicit" modules -- what do you mean by that? Do you mean just Clang's -fmodules flag, or something else? I usually hear -fmodules referred to as "just Clang Modules", and I wonder if "explicit" modules is something else I should pay attention to?
I'm hoping you'll be satisfied with "it doesn't break anything existing, and @ian-twilightcoder it shouldn't be textual, so the current definition is incorrect".
Having green CI tells me that this is at least not a regression as far as we can tell, so yes, that's helpful. And having someone else with modules expertise chime in and confirm that we want to eliminate textual headers as much as possible is also helpful. I still do think that if this doesn't fail in our CI, then there must be a way to compile libc++'s own code without this patch. For example, you could probably switch to using public includes only from libc++'s own source files and I believe that would fix this issue. That being said, I am also happy (probably happier, even) with actually fixing our modulemap, so this LGTM assuming CI passes.
Macros count as declarations, at least in the pcm/ast sense.
Presumably that means |
|
I still feel like this is very likely to break something if we don't modularize |
|
It's definitely not possible to do in this modulemap file (since you need a relative path). You might be able to do it by having That being said, I believe it's perfectly safe since:
Because of the above reasons, if you can ever see a header guard that blocks you from importing And yes, @ian-twilightcoder is correct - when we say explicit modules, we're referring to Also FYI, I'm gonna be on holiday for the next 3 weeks, so will be unable to respond. |
It's definitely not safe. As a non-modular include, you'll get weird absorption behavior. It might work if it was |
It's used to ship differently-configured libc++'s on different targets. We have: The compiler then adds Note that I am not concerned with the modulemap not working from the build directory. There might be a few challenges to deploying that (I think when @arichardson last tried he found some places in LLVM that relied on the structure of our build directory), but in principle we should never use anything from our build directory, only from the installed result. |
Doesn't the build directory get used for running tests, at least locally? Is there a particular reason we don't just re-generate |
Not anymore. We now perform an installation at a fake location and the test suite is configured to use that instead. This ensures that what we test is faithful with what we ship (eg. the install name of the library, its path, etc).
I'm not certain I understand. But the idea is that on some platforms, we ship a single libc++ with multiple |
Ah, spiffy.
Oh I see so it will be installed with multiple |
When building libcxx as a module, it fails to build because it's missing various definitions.
Consider the following code for module A:
With the module map file:
Macro visibility rules state that "[macros] are visible if they are from the current submodule or translation unit, or if they were exported from a submodule that has been imported."
Module B exports: config_site contents, config_site header guard
Because it can see module B's exports, it stops at the header guard for config_site and does not include config_site. This is not an issue, however, because it has visibility onto everything exported from config_site thanks to module B.
Module A exports: config contents, config header guard, config's includes' content and header guard (except config_site)
Because of that, we see the header guard for config and do not import it at all. This is mostly OK, as we can see the config that module A exported. However, if we ever try and access config_site, it will fail, as A did not export config_site.