Skip to content

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

Open
wants to merge 27 commits into
base: main
Choose a base branch
from

Conversation

JeffGarland
Copy link
Member

@JeffGarland JeffGarland commented May 30, 2025

still somewhat preliminary as I'm experimenting with the cmake aspects...

@ClausKlein please have a look

@JeffGarland JeffGarland requested review from robert-andrzejuk, wusatosi and a team as code owners May 30, 2025 12:03
@JeffGarland JeffGarland linked an issue May 30, 2025 that may be closed by this pull request
@JeffGarland JeffGarland requested a review from steve-downey May 30, 2025 12:03
@ClausKlein
Copy link

ClausKlein commented May 30, 2025

You may try a CMakeLists.txt like this:

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)

@JeffGarland
Copy link
Member Author

You may try a CMakeLists.txt like this:
...

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...

@JeffGarland
Copy link
Member Author

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")

or from the article this one...hmm

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "a9e1cf81-9932-4810-974b-6eccaf14e457")

@JeffGarland
Copy link
Member Author

So basically it seems like there's interference here with other stuff we have

-- The CXX compiler identification is Clang 20.1.2
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++-20 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAVE_FLAG__ffile_prefix_map__home_jeff_dev_scope_modules_build__deps_catch2_src__
-- Performing Test HAVE_FLAG__ffile_prefix_map__home_jeff_dev_scope_modules_build__deps_catch2_src__ - Success
Tests to be built: scope_success;scope_exit;scope_fail;unique_resource
Examples to be built: scope_example;unique_resource;unique_resource-file
-- Configuring done (3.8s)
CMake Error in CMakeLists.txt:
  The "CXX_MODULE_STD" property on the target
  "beman.scope_verify_interface_header_sets" requires that the
  "__CMAKE::CXX26" target exist, but it was not provided by the toolchain.
  Reason:

    Experimental `import std` support not enabled when detecting toolchain; it must be set before `CXX` is enabled (usually a `project()` call)

that's despite me moving the STD macro above the project

@steve-downey
Copy link
Member

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.
https://github.com/Kitware/CMake/blob/master/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt#L1-L2

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.

@JeffGarland
Copy link
Member Author

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. https://github.com/Kitware/CMake/blob/master/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt#L1-L2

Noted -- also noting that this is using 3.x version of cmake. I'm am using 4.

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.

I can't make it work with clang either.

cmake .. -DCMAKE_CXX_COMPILER=clang++-20 -DCMAKE_CXX_STANDARD=26 -G=Ninja

CMake Error in examples/CMakeLists.txt:
  The "CXX_MODULE_STD" property on the target "unique_resource-file" requires
  that the "__CMAKE::CXX26" target exist, but it was not provided by the
  toolchain.  Reason:

    Experimental `import std` support not enabled when detecting toolchain; it must be set before `CXX` is enabled (usually a `project()` call)

@wusatosi wusatosi requested a review from nickelpro May 30, 2025 15:50
@nickelpro
Copy link
Member

nickelpro commented May 30, 2025

Ok so there's a bit going on here I'll try to address it all:

Why don't write a couple cmake functions to compile the .gcm or .ppm, make those a target and call it a day?

That's what target_sources(FILE_SET CXX_MODULES) does. It compiles your gcm and ppm files for you, attaching them to whatever target you want. As a practical example:

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 CXX_SCAN_FOR_MODULES. CMake knows that modules are a thing in C++20, so if the user chose to build with C++20 or later CMake knows it's obligated to scan for modules.1

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD ...)

The UUID changes with every tweak to the CMake code relevant to import std. This is intentionally very difficult/impossible for downstream projects to track. CMake has an extremely nasty history with experimental/debug interfaces breaking out of containment, incorporated by projects, and being strong-armed into supporting those features for decades.

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.

limit modules usage to some super experimental mode in cmake and only ninja builds

I don't think Makefiles will ever support anything about modules, same story with other legacy tooling like pkg-config. The scanning step is fundamentally hostile to primitive tooling. It's not impossible,2 it's just a lot of work and the people who pay for these things are uninterested in make as a build program (it's fine as a general purpose task runner). ninja is the new standard.

The experimental mode is only for import std, and that's because GCC didn't support it in a stable release. With GCC 15, CMake will probably move the support out of experimental within a release or two. I think it's missed the train for 4.1 (but this has prompted me to at least ask), but 4.2 or 4.3 are likely targets. As mentioned above, named modules "just work".

Footnotes

  1. In fact you might want to turn off module scanning if you know you don't use import in a given set of files. CMake is obligated to scan by the language standard, your code might call import, CMake doesn't know. This is slower than omitting scanning entirely, which a human can know is the right thing to do.

  2. I know (Kitware) Ben has all the necessary changes rattling around in his head and talked about it as a nice-to-have

@JeffGarland
Copy link
Member Author

JeffGarland commented May 30, 2025

Ok so there's a bit going on here I'll try to address it all:

Thanks -- it's a steep ledge :)

Why don't write a couple cmake functions to compile the .gcm or .ppm, make those a target and call it a day?

That's what target_sources(FILE_SET CXX_MODULES) does. It compiles your gcm and ppm files for you, attaching them to whatever target you want.

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...

As a practical example:

add_library(modlib)

target_sources(modlib
    PUBLIC
        FILE_SET CXX_MODULES
        FILES
            intf_unit_a.cpp
            intf_unit_b.cpp
 )

So my ~5th attempt at this windmill was this:

target_sources(
    beman.scope
    INTERFACE
        FILE_SET HEADERS
        BASE_DIRS include
        FILES include/beman/scope/scope.hpp
    PUBLIC
           FILE_SET CXX_MODULES
          FILES include/beman/scope/beman.scope.cppm
)
CMake Error at CMakeLists.txt:58 (target_sources):
  target_sources File set TYPE "CXX_MODULES" may not have "PUBLIC" or
  "PRIVATE" visibility on INTERFACE libraries.

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....

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.

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...

limit modules usage to some super experimental mode in cmake and only ninja builds

I don't think Makefiles will ever support anything about modules, same story with other legacy tooling like pkg-config.
...
ninja is the new standard.

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.

The experimental mode is only for import std, and that's because GCC didn't support it in a stable release. With GCC 15,

Gotcha --I expect the hoards will be banging at the gates soon...

@steve-downey
Copy link
Member

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...

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.

@steve-downey
Copy link
Member

I don't think Makefiles will ever support anything about modules, same story with other legacy tooling like pkg-config. The scanning step is fundamentally hostile to primitive tooling.

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 import std; to work for scope.

@nickelpro
Copy link
Member

nickelpro commented May 31, 2025

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 add_library(INTERFACE) and throughout the rest of its commands with the INTERFACE keyword. There are subtleties here but that's the gist.

Static and dynamic libraries involve a build step, so in your source folder they must be described with add_library(STATIC/SHARED/MODULE) whatever, just not INTERFACE. This tells CMake that it needs to build something, the details of which are as complex as you can possibly want to make them. See everything ever written about CMake for more information.

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 beman.scope update. I'll link it here in a sec.

Footnotes

  1. If you say Fortran I'll throw a shoe at you

@nickelpro
Copy link
Member

The current typical recursive makefile type project, which is what the generator mostly does, is not going to be able to cope

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.

@JeffGarland
Copy link
Member Author

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.

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.

@JeffGarland
Copy link
Member Author

JeffGarland commented May 31, 2025

We've never had the idea of an installed file, that is also a source file that gets fed to the compiler.

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.

All this to say modules are hard by construction, CMake isn't personally screwing with you.

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...

If you say Fortran I'll throw a shoe at you

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 ;)

@nickelpro
Copy link
Member

nickelpro commented May 31, 2025

Forever we've had things like IDL files that get installed and generated into header files using an idl compiler

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 pkg-config in many ways, but it made several of the same assumptions as pkg-config with regards to what a "library" is. That is, a library is a set of flags you pass to compilers and linkers. You might have to run a bunch of compilers, code generators, sanitizers, and linkers to get that library, but once you've got it it's just a set of flags.

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 pkg-config to work with C++20 modules, you will arrive naturally at the same problem CMake had to solve. It is not a terribly fun exercise.

@JeffGarland
Copy link
Member Author

Running the compiler to consume a library is new to us, a lot of engineering work went into that idea.

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.

@nickelpro
Copy link
Member

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.

JeffGarland and others added 2 commits May 30, 2025 20:56
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
JeffGarland and others added 2 commits May 31, 2025 11:01
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>
@JeffGarland
Copy link
Member Author

The current CI failures seem to be this problem with cmake 3.28

https://discourse.cmake.org/t/cmake-3-28-cmake-cxx-compiler-clang-scan-deps-notfound-not-found/9244/3

@wusatosi
Copy link
Member

wusatosi commented May 31, 2025

@wusatosi is it possible to get g++-15 into the CI containers?

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.
See: bemanproject/infra#18

@steve-downey
Copy link
Member

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.

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.
Google and Microsoft's (differing) plans to make it "just work" did not materialize.

@JeffGarland
Copy link
Member Author

@wusatosi is it possible to get g++-15 into the CI containers?

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. See: bemanproject/infra#18

I didn't have to compile it, but I'm using 2504 -- maybe just update?

apt policy g++-15
g++-15:
  Installed: 15-20250404-0ubuntu1
  Candidate: 15-20250404-0ubuntu1
  Version table:
 *** 15-20250404-0ubuntu1 500
        500 http://ports.ubuntu.com/ubuntu-ports plucky/universe arm64 Packages
        100 /var/lib/dpkg/status
     15-20250304-0ubuntu2 500
        500 https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu plucky/main arm64 Packages

@JeffGarland
Copy link
Member Author

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.

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.

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.

// for g++-15 the order is important -- import after includes

TL;DR -- the stuff was pointed out beforehand, we did it anyway. Google and Microsoft's (differing) plans to make it "just work" did not materialize.

yeah one more person wouldn't have mattered there...

@JeffGarland
Copy link
Member Author

JeffGarland commented May 31, 2025

The current CI failures seem to be this problem with cmake 3.28

https://discourse.cmake.org/t/cmake-3-28-cmake-cxx-compiler-clang-scan-deps-notfound-not-found/9244/3

ugh -- this seems to still be an issue with cmake 4 sadly

Run cmake -B build -S . -DCMAKE_CXX_STANDARD=20 -DCMAKE_TOOLCHAIN_FILE="cmake/llvm-toolchain.cmake"
-- The CXX compiler identification is Clang 19.1.7
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Compiler is: Clang version:  19.1.7
cmake is: 4.0.2 modules scan :  

I don't really want to turn of the non-modules version of the CI there...

@nickelpro
Copy link
Member

I should have commented earlier and saved you some frustration.

You've got cmake_minimum_required(VERSION 3.25)

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 VERSION 3.28 and you should find things work much better.

@ClausKlein
Copy link

ClausKlein commented Jun 1, 2025

We need clang-tools-20 too!
See llvm/llvm-project#117333
And note this https://gitlab.kitware.com/cmake/cmake/-/issues/25916

@JeffGarland
Copy link
Member Author

I should have commented earlier and saved you some frustration.

You've got cmake_minimum_required(VERSION 3.25)

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 VERSION 3.28 and you should find things work much better.

Claus had my back -- all working now, except his note below that cmake requires the scanning tool even when not scanning...

@ClausKlein
Copy link

ClausKlein commented Jun 1, 2025

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
and an impossible one https://github.com/bemanproject/execution/blob/98059d76a344a04787276f7e577f7cbef5cbf848/src/beman/execution/CMakeLists.txt#L194

@ClausKlein
Copy link

Dit you ever check that the exported cmake config package can be found and imported?

see bemanproject/execution#155

@JeffGarland
Copy link
Member Author

Q: how do you handle runtime dependencies?

There aren't any for scope? I'm not sure I understand the question

@JeffGarland
Copy link
Member Author

Dit you ever check that the exported cmake config package can be found and imported?

see bemanproject/execution#155

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# 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.

Copy link
Member Author

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)...

Copy link
Member

@wusatosi wusatosi Jun 2, 2025

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.

Copy link
Member Author

@JeffGarland JeffGarland Jun 2, 2025

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
Copy link
Member

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.

Copy link
Member Author

@JeffGarland JeffGarland Jun 2, 2025

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.

Copy link
Member

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

@wusatosi
Copy link
Member

wusatosi commented Jun 2, 2025

apt policy g++-15
g++-15:
  Installed: 15-20250404-0ubuntu1
  Candidate: 15-20250404-0ubuntu1
  Version table:
 *** 15-20250404-0ubuntu1 500
        500 http://ports.ubuntu.com/ubuntu-ports plucky/universe arm64 Packages
        100 /var/lib/dpkg/status
     15-20250304-0ubuntu2 500
        500 https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu plucky/main arm64 Packages

It is simply not available on 24.04, see link.

@JeffGarland
Copy link
Member Author

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.

@wusatosi
Copy link
Member

wusatosi commented Jun 2, 2025

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.

@nickelpro
Copy link
Member

Yes. The only reason to use a debian compiler is if you're compiling a package for a debian repository (s/debian/[distro of your choice]/g), otherwise "whatever debian happens to have lying around" isn't a good plan. This holds true for any development dependency or resource.

@wusatosi
Copy link
Member

wusatosi commented Jun 2, 2025

Yes. The only reason to use a debian compiler is if you're compiling a package for a debian repository (s/debian/[distro of your choice]/g), otherwise "whatever debian happens to have lying around" isn't a good plan. This holds true for any development dependency or resource.

Is kitware's apt trust worthy? Should we build our own CMake? (jk

@JeffGarland
Copy link
Member Author

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.

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...

@JeffGarland
Copy link
Member Author

CI fixes on clang are relative to this change being implemented:

bemanproject/infra#20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

make a module for beman.scope
5 participants