-
Notifications
You must be signed in to change notification settings - Fork 5
add module file for scope and modular example #34
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
You may try a set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")
cmake_minimum_required(VERSION 4.0.0)
project(cxx_modules_import_std CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_MODULE_STD 1)
set(CXX_SCAN_FOR_MODULES 1)
add_executable(main main.cxx)
target_compile_features(main PRIVATE cxx_std_23)
enable_testing()
add_test(NAME main COMMAND main) |
Thanks I'll experiment with that -- I've been following this which is close to what you're suggesting. I'm basically running into the same issues since my g++-15 is installed in a non-standard location - specifically the bits.cc location. https://igormcoelho.medium.com/its-time-to-use-cxx-modules-on-modern-c-41a574b77e83 And now I'm going to go off the rails and say, isn't this much ado about nothing with the cmake? Why don't write a couple cmake functions to compile the .gcm or .ppm, make those a target and call it a day? I mean, I used to work on projects with SWIG and CORBA where we generated header file dependencies with a bit of custom cmake foo and it worked fine. @nickelpro (and others), am I missing something big that says I really want to limit modules usage to some super experimental mode in cmake and only ninja builds? walk me off the ledge... |
or from the article this one...hmm
|
So basically it seems like there's interference here with other stuff we have
that's despite me moving the STD macro above the project |
https://github.com/Kitware/CMake/tree/master/Tests/RunCMake/CXXModules/examples/import-std is the basic current example for it, if I'm reading it correctly. set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
"d0edc3af-4c50-42ea-a356-e2862fe7a444") is the current GUID. I haven't tried modules with GCC15 and CMake yet. I don't know if CMake has learned the incantations for GCC yet, but it would be in a recent version if it has. |
Noted -- also noting that this is using 3.x version of cmake. I'm am using 4.
I can't make it work with clang either. cmake .. -DCMAKE_CXX_COMPILER=clang++-20 -DCMAKE_CXX_STANDARD=26 -G=Ninja
|
Ok so there's a bit going on here I'll try to address it all:
That's what add_library(modlib)
target_sources(modlib
PUBLIC
FILE_SET CXX_MODULES
FILES
intf_unit_a.cpp
intf_unit_b.cpp
) This code is not experimental, you don't need any weird CMake rain dance to make it work, it shipped in CMake 3.28 so it's not even particularly new. You also don't need stuff like
The UUID changes with every tweak to the CMake code relevant to The current UUIDs are documented in the CMake developer documentation which is nearly ungoogable. Again this is intentionally cumbersome, a big flashing sign that says NOT FOR PRODUCTION.
I don't think Makefiles will ever support anything about modules, same story with other legacy tooling like The experimental mode is only for Footnotes
|
Thanks -- it's a steep ledge :)
ok -- if only I could figure out how to use them lol. People, c++ is easy -- cmake on the other hand. It's clear that I have to wipe my brain of cmake knowledge every few years and reset it...
So my ~5th attempt at this windmill was this:
tldr it can't be interface either -- so sure then make a separate target, no you're too dumb Jeff! Sorry I haven't found the correct approach to this seemingly trivial problem after banging my head on the wall for a couple hours (I'm ignoring the guy replacing the broken glass door where a large object exited at high velocity /s ). The long and short is I tried to add a test case get the scope module generated ahead of the compile....
Walks back from ledge. That's good news -- if we can get the beman module to work then great (see above). The std module would be nice but it can wait...
Ok, well I guess that's just a modules problem. I don't have a problem with ninja, just that I feel like any barrier to adoption because of tooling isn't good. see also boost. boost.build is an amazing barrier for some -- it's dumb, but it is.
Gotcha --I expect the hoards will be banging at the gates soon... |
One of the hardest problem with cmake, more than even C++, is that answers that were OK 10 years ago are now not just not the best way, but are badly wrong, and may be actively harmful. You aren't alone. |
Gnu Make can do it, and I've written some Makefile that can do the necessary dynamic steps. But there's little point, and there's no real value in rewriting the current ninja cmake generator to emit the same structure only using make instead of ninja. The current typical recursive makefile type project, which is what the generator mostly does, is not going to be able to cope. It's just one of the ways where your current build system is not going to survive contact with modules, and your meta-build system will need new versions. Posix make, and most of its descendants, can't do the dynamic self updates that are necessary. This is of course, not really here nor there for getting |
Modules are distinct from all traditional kinds of libraries in a way that is infuriatingly complex to wrap your around even for experienced build system developers. Header libraries are "interface only" they are a set of flags you describe to the compiler. CMake describes these using Static and dynamic libraries involve a build step, so in your source folder they must be described with However, after such a library gets built, the only thing you normally need to export is the archive or shared object itself and its associated headers, and those can be described using just a set of flags passed to the compiler and the linker. A library that has been built and installed acts a lot like a header-only library, its some flags we need to pass through to the rest of the system. Modules are different. Module interface units are kinda like header files, they get described and listed like header files, but we need to run the compiler on them. Nothing in the history of build systems has ever acted like that before, in any programming language.1 We've never had the idea of an installed file, that is also a source file that gets fed to the compiler. Either everything is source code and constructed in one big static build (Rust, Go), or everything can be described by flags, no one ever tried to split the difference before. At least not anything the general purpose build systems support. All this to say modules are hard by construction, CMake isn't personally screwing with you. Anyway I've constructed a patch that illustrates how to do this with Exemplar. It makes a lot of other changes to Exemplar to, of stuff we learned doing the Footnotes
|
This is what I'm talking about when I said "won't support". Nothing that generates makefiles knows how to do it, and make itself has no built in facilities to handle modules in a clean, terse, first-class manner. Make is of course a general-purpose, Turing-complete, scripting language, as all good washing machine firmware should be. It nominally supports everything. |
yes, and part of my problem is that at the day job I have a couple good engineers that just handle this -- so I'm out of practice. And then I just can't go to a cmake talk at a conference because I'm aware of the dynamic you're citing. And yeah the internet answers are a complete mess -- as demonstrated by this thread. |
Forever we've had things like IDL files that get installed and generated into header files using an idl compiler. That step always has to run first -- I'm failing to see how that's really different. In a single tree build with cross-dependencies that was never fun, but we managed.
lol, thanks -- I'm sure that's what people say about c++ as well -- except then they blame people like me. Who of course are doing are best to stop c++ from screwing with them...
ahem...my first language was Fortran IV on punch cards which had 'very specific line spacing rules'. As a bad 'rule follower' it didn't go well for me. Ducks for incoming shoe ;) |
That's a build time operation, it happens with files in your source tree at build time. CMake views code generators as funky compilers. We've never had something come from an install tree, described as "this is a library from the outside world you're linking to", that we couldn't describe as a set of flags. CMake is more sophisticated than Running the compiler to consume a library, after it has already been built and installed, is new to us. A lot of engineering work went into that idea. If you sit down and try to work out how you would patch |
Sure, I think the difference is that kitware is doing the work here -- the systems I'm talking about we did the work with custom cmake functions. That work, no doubt had some gaps where certain sorts of dependencies weren't 100% represented -- and as a result there could be a broken build. But everyone knew what those gaps were and dealt with it -- we didn't expect perfection. |
We're sufficiently off-topic for the PR, but the discussion is fun. Yes, everything is doable in a sufficiently constrained environment. It's why when people say "X has arrived!" and it's a bunch of slideware, 20-line, raw compiler commands run by hand from the terminal there's usually months or years left of work to do before they can be adopted generally. None of this stuff is really a restriction of the compilers, nor is it some academic, information-theoretic problem where we're saying the set of known information is less than what is required. A human can write the necessary commands pretty easily. It's a problem with the set of assumptions that the build infrastructure has made for decades. It's a problem of our internal models of what building C++ software means. Ya it sucks pretty bad. In my defense I was [REDACTED] ft under the icecaps when WG21 voted modules in. I would have pointed this stuff out at the time otherwise. |
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The current CI failures seem to be this problem with cmake 3.28 |
Currently no ubuntu 24.04 based package manager ships it, we will need to write setup scripts to build gcc from source. Once we have the infra up getting arbitrary testing image should be painless. This is high priority for me, but I am more than happy if anyone want to work on it because I have interviews coming up. |
I've thought about getting a new version of https://wg21.link/p1427 "Concerns about module toolability" (from 2018) out so we could add all the ones we've found since then and add a longer signatory list. TL;DR -- the stuff was pointed out beforehand, we did it anyway. |
I didn't have to compile it, but I'm using 2504 -- maybe just update?
|
Seems like a waste of time now -- it looks to me like this is almost H20 under the bridge. Right now everything is working 100% for me with the named module (ubuntu 2504, clang20). It's 95% with gcc on same platform -- the 5% isn't tooling it's a compiler/library issue with g++15 and order of includes/imports -- imports need to be after. Line 6 in 4c77cca
yeah one more person wouldn't have mattered there... |
ugh -- this seems to still be an issue with cmake 4 sadly
I don't really want to turn of the non-modules version of the CI there... |
I should have commented earlier and saved you some frustration. You've got Which tells CMake to act exactly like CMake 3.25, which didn't know about modules, and will never scan under any conditions. Up that to |
We need clang-tools-20 too! |
Claus had my back -- all working now, except his note below that cmake requires the scanning tool even when not scanning... |
Q: how do you handle runtime dependencies? include(CMakeFindDependencyMacro)
find_dependency(Threads)
find_dependency(OpenSSL) see a working example https://github.com/ClausKlein/asio/blob/feature/update-cmake-asio-version/asio/cmake/install-config.cmake |
Dit you ever check that the exported cmake config package can be found and imported? |
There aren't any for scope? I'm not sure I understand the question |
hmm, no -- I guess that requires doing an install and then somehow running cmake against just the installed files? |
CMakeLists.txt
Outdated
@@ -12,7 +12,7 @@ project( | |||
# gersemi: off | |||
|
|||
# Modules opt in only on compilers that support g++-15 and clang-20 |
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.
# Modules opt in only on compilers that support g++-15 and clang-20 | |
# Modules opt in only on compilers that support g++-15 and clang-19 |
I think the code here is pretty self explanatory, this comment may not be needed.
Also if we can test module support instead of just doing a compiler version that would be great. This is how we test induce this in iterator interface iirc.
We can leave that to another PR though.
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.
I think the code here is pretty self explanatory, this comment may not be needed.
With the modules stuff I want it to be triple clear what is supported and what isn't. Of course it was already wrong...
Also if we can test module support instead of just doing a compiler version that would be great. This is how we test induce this in iterator interface iirc.
We can leave that to another PR though.
Yes, but I"m not sure it's possible. We'd have to find out what flags the compilers have switched on and it might not line up with 'practical reality' -- that is it might not be supported even though it is or vise versa. Also in the case of gcc-15, as commented in the test file, reorder the includes and the import and kaboom -- it won't compile. So it's kinda fragile. There's reports of similar on visual studio (still not supported here)...
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.
Yes, but I"m not sure it's possible.
Yeah that's fair, we probably want to implement this test as close as possible for exemplar's module support though.
that is it might not be supported even though it is or vise versa
What do you mean here. If we can test that module is supported than module is supported, if test module support fails than it's not supported, if we tested that it's supported but it is not, then our test is wrong....
I don't quite follow what you mean.
Also in the case of gcc-15, as commented in the test file, reorder the includes and the import and kaboom -- it won't compile. So it's kinda fragile.
I don't see the relevance here.
What I am proposing is basically:
test_if_module_is_supported(MODULE_SUPPORTED)
option(
BEMAN_SCOPE_USE_MODULE
"Controls if the project is built using modules. Default: ${MODULE_SUPPORTED}."
MODULE_SUPPORTED
)
if (BEMAN_SCOPE_USE_MODULE)
setup_modules()
endif()
We export a config.hpp file.
// ....
#cmakedefine01 BEMAN_SCOPE_USE_MODULE
// ....
Then in the implementation it will be:
#include "config.hpp"
#if BEMAN_SCOPE_USE_MODULE()
export module beman.scope;
import std;
#else
#include <...>
#endif
We can force runs with module support to use module by just passing -DBEMAN_SCOPE_USE_MODULE=ON
and we will catch the reordering issues.
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.
that is it might not be supported even though it is or vise versa
What do you mean here. If we can test that module is supported than module is supported, if test module support fails than it's not supported, if we tested that it's supported but it is not, then our test is wrong.... I don't quite follow what you mean.
I mean that c++ feature test macros (the way we would tell) might not tell the entire story because module implementations are till buggy.
Also in the case of gcc-15, as commented in the test file, reorder the includes and the import and kaboom -- it won't compile. So it's kinda fragile.
I don't see the relevance here.
See above -- just bc 'modules are supported' doesn't mean they will work for all libraries.
What I am proposing is basically:
test_if_module_is_supported(MODULE_SUPPORTED) ...edited... We export a config.hpp file. ```c++ // .... #cmakedefine01 BEMAN_SCOPE_USE_MODULE // ....
ABSOLUTELY NOT. Generation of headers is a bad solution -- especially for modules which don't inherently need headers. David's solution for the linking problem
is bad (even if the above about modules wasn't true) and scope won't be adopting the agreed solution
in the sync. I have a better option in the works.
Then in the implementation it will be: ```c++ #include "config.hpp" #if BEMAN_SCOPE_USE_MODULE() export module beman.scope; import std; #else #include <...> #endif
You've missed the big arc of things here -- import std (a c++23 feature) is completely NOT needed for scope or other libraries to support their named modules. Absolutely nothing in the PR here does import std
or requires higher than c++20.
We can force runs with module support to use module by just passing
-DBEMAN_SCOPE_USE_MODULE=ON
and we will catch the reordering issues.
We aren't forcing anything here and reordering can't be determined until compile failures. The solution in the PR is clean an elegant -- it enables the test on the compilers that work and disables it otherwise.
@@ -9,6 +9,19 @@ project( | |||
VERSION 0.0.1 | |||
) | |||
|
|||
# gersemi: off |
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.
If more than 60% of the CMake file is ignored, we might as well remove the cmake formatter.
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.
There are other cmake files. I have a bunch of clang-format exclusions as well -- that doesn't mean I want it all turned off.
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.
I'm pro removing the formatter, it's too wrong too often to really be useful
It is simply not available on 24.04, see link. |
Understood -- I think I mentioned in exemplar review that we need to update to 25.04 ubuntu -- aka plucky for this to be available. |
I guess I can see that for testing container. The devcontainer is backed on Microsoft's devcontainer images, which follows the two year release of Ubuntu iirc, so 25.04 is not available. Testing and devcontainer currently share the same docker build process with a variable to switch between two backing containers. We will need infrastructure to custom built compilers anyway, relying on package manager means we have to chase things like this. Once custom compiler building is setup we can do cool things like "this library paper relies on this language feature that's only implemented in this branch of gcc/clang, let's just add this to the testing container build definition so we can test our library against this language extension it's meant to go with". An example of this will be in place vector with trivial unions. |
Yes. The only reason to use a debian compiler is if you're compiling a package for a debian repository ( |
Is kitware's apt trust worthy? Should we build our own CMake? (jk |
Ok, I'm persuaded by this point and g++-15 is an easy one to start with. Go find the instructions, it's quite trivial from a process perspective to build gcc these days. It does take time though... |
CI fixes on clang are relative to this change being implemented: |
still somewhat preliminary as I'm experimenting with the cmake aspects...
@ClausKlein please have a look