Skip to content

Conversation

@mikomikotaishi
Copy link

This PR adds support for C++ modules, which currently must be manually compiled (no CMakeLists.txt exists).

@tzcnt
Copy link
Owner

tzcnt commented Feb 5, 2026

Per the discussions recently, in order to avoid diamond dependency issues when packaging for vcpkg/conan, I may be moving away from any precompilation, and making the entire library header-only.

Apologies for the noob questions - I haven't investigated modules at all, having spent all my time on coroutines and concepts instead. I've done some reading and it appears that modules offer a way to do the precompilation that's currently gated behind the TMC_IMPL macro, but in a more elegant fashion? If I just define a normal function as inline (necessary to prevent ODR violation in a header-only library), will modules prevent that from being recompiled in every translation unit, and instead provide a single compilation which can be reused?

What is the impact of P1498R1 and P1779R3 on this library? Is there a recommendation that I should make member functions inline or not-inline?


There is a typo on line 47: tmc::cpuexecutorl instead of ;, and AI identified 6 missing symbols:
aw_spawn_fork - type alias from spawn.hpp
aw_spawn_impl - class template from spawn.hpp
aw_spawn_func_fork - type alias from spawn_func.hpp
aw_spawn_many_each - type alias from spawn_many.hpp
aw_spawn_many_fork - type alias from spawn_many.hpp
spawn_clang - function from spawn.hpp
spawn_func_many - function from spawn_many.hpp

Is there a more reliable method to export all of the symbols necessary so that I don't have to remember to update this file while I'm adding a header?

In order to ensure that nothing else has been missed, mind forking the examples repo and adding a module build option there? To test there, git clone --recurse-submodules https://github.com/tzcnt/tmc-examples and then define the CMake option TMC_AS_SUBMODULE which will let you work with your fork from the ./submodules/TooManyCooks directory.

@mikomikotaishi
Copy link
Author

Fixed the missing symbols and decided to alphabetise the using statements. I'll respond to the rest of these later

@mikomikotaishi
Copy link
Author

Okay, so as you are probably aware, one notable advantage of modules is that modular translation units are compiled once and importing that module will just get its compiled interface, unlike #include which re-compiles the header each time it is used.

I believe that modules do not make all functions non-recompiled, but importers only have to compile against the already built module interface to get its definitions. Also, in modules, member functions are not implicitly inline, so you can define functions in the module interface without worrying about ODR semantics.

@mikomikotaishi
Copy link
Author

@tzcnt Hi, is there anything else you want me to answer?

@tzcnt
Copy link
Owner

tzcnt commented Feb 9, 2026

I won't merge without compiling the full examples suite and tests using the module API. That's why I requested you open a PR into the examples repo.

Otherwise I'll do it myself after I work through removing the IMPL macro requirement and review the package manager PRs

@mikomikotaishi
Copy link
Author

compiling the full examples suite and tests using the module API.

Do you want me to duplicate all of the tests or do you want me to make it conditional on whether #include or import is used?

@mikomikotaishi
Copy link
Author

@tzcnt I do have a CMake working in my PR, and I have made several changes (such as using external linkage when building modules, and moving anonymous namespaces to detail namespaces). I'm just not really sure how to change your tmc-examples repo so that it can build with modules.

@tzcnt
Copy link
Owner

tzcnt commented Feb 10, 2026

Good enough would be a preprocessor macro used only in the tests (TMC_IMPORT_MODULE) that is used to swap between defines and includes in every file that needs them.

#ifdef TMC_IMPORT_MODULE
  import tmc::foo;
#else
  #include "tmc/foo.hpp"
#endif

It's OK to do this for the main tests target only. If there's really no other way to ensure that all symbols are exported (every symbol must be named manually as you've done) then we must also verify that all necessary symbols can be imported. The tests should be exhaustive in this regard. And I can make a CI workflow that defines this macro and validates that I haven't forgotten to export anything in the future.

Thanks for your time and effort on this.

@mikomikotaishi
Copy link
Author

The problem with this is that these are all in headers, where we have the following problems:

  • Module imports should come after all #includes (it seems to be a bug on GCC causing esoteric errors if an import precedes an #include).
  • Since the tests are all in headers, presumably they are meant to be #included, but putting import statements is probably a bad idea in headers (they are more reasonable for source files).
    If you know any other idea on how to approach this, I'm all ears, but these are some of the obstacles that come to mind to me at the moment.

@tzcnt
Copy link
Owner

tzcnt commented Feb 10, 2026

The tests are in .cpp files. There are some .ipp files that get included at the end of multiple .cpp files ,with different macro bases so I can test the same behavior on different executors. There are only a few .hpp files with some common behaviors.

What's wrong with importing a module from a header? Is module like a viral thing so the consuming code also has to be 100% module-ified?

@mikomikotaishi
Copy link
Author

mikomikotaishi commented Feb 10, 2026

The problem with importing a module into a header is that the module gets imported into every file that includes that header, which is risky and unstable.

Also, you are right, the code is in .cpp files. However, the problem is that a lot of those files #include "test_common.hpp", which in turn does #include "tmc/all_headers.hpp", which then adds all the headers to the file anyway, and then no longer can independently test the module.

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.

2 participants