Examples for using modules with Cling?

Hey folks. I’ve been digging through the forum and source, trying to find out how I can do the following with Cling:

  1. Compile some source to a C++20 module (.pcm) file
  2. Load a compiled module into Cling

I’m hoping to be able to load modules I’ve previously compiled with (the same version of) Cling, so the subsequent runs can be much faster.

So far, I’ve found that the Cling interpreter has a loadModule function, but it’s unable to find any module I try to load.

The source I’ve tried

Currently using the Clang built alongside Cling to compile the module, but I would like to be able to do this programmatically, via Cling.

❯ cat foo.cpp
export module foo;

export int bar()
{ return 42; }

❯ cling-build/bin/clang -std=c++20 -c -o foo.pcm -Xclang -emit-module-interface foo.cpp

❯ ls
foo.cpp foo.pcm

What I’m seeing

When I try this:

interpreter->loadModule("foo")

It returns false and says “Module foo not found.” I’ve tried specifying both of these flags to Cling as args:

  1. -I.
  2. -fprebuilt-module-path=.

Still, it cannot find the PCM. I’ve also tried reaching into some of the clang internals, through Cling, to help it find the PCM, but that has not worked:

auto const &hs = jit_prc.interpreter->getCI()->getPreprocessor().getHeaderSearchInfo();
hs.getHeaderSearchOpts().PrebuiltModulePaths.emplace_back("/home/jeaye/projects/jank/tmp/ir");

Dear @jeaye ,

I believe @Axel or @pcanal will know better about your use case.

Cheers,
Vincenzo

The use of modules is transparent, other than the requirement that they need to be co-located with the compiled dictionary shared library.

Thanks, Michael. What do you mean by the compiled dictionary shared library? I’m embedding Cling in my application, not using ROOT, in case that matters.

In my tests, I had the PCM file in the current working directory, hence my trying -I. and -fprebuilt-module-path=..

Hey, following up on this, hoping for some clearer explanation or documentation. I have not yet been able to make this work.

Also, will you please answer my first question (out of the two listed), which is how I might generate compiled PCMs using Cling? Do I need to call out to clang instead?

Can @Axel or @pcanal jump in here? I’m still trying to find a way to get Cling to find these PCM files.

I’m waiting for @vvassilev - I’m hoping he will share his view on how things could work in the near future!

Hi @jeaye,

We are in uncharted waters here. If you build the module with clang, then we will need to teach cling’s driver to load that file the C++20 way. That means that we will likely need to copy some code from the FrontendActions in clang.

This functionality is meant to enable Clang “explicit” modules which ROOT uses. This means that we build a Clang-module and we need to explicitly activate it.

If you want to get started I’d suggest running cling with -fmodules. This option will set up cling to support clang modules which are the basis for the C++20 modules. Cling is implemented in such a way that if you pass a -I to an include path it knows, it would automatically build and load the module for you. Small example is tinyxml. If you do cling -fmodules -I/path/to/tinyxml it would implicitly build the module and load it. Similarly for several other packages: root/interpreter/cling/lib/Interpreter/CIFactory.cpp at 7bc2524108dda41998eaa87abca5edfa877f838f · root-project/root · GitHub

That does not answer directly to your request but I believe starting from there we would be able to figure out how to plug the new system in.

Thanks, Vassil. What I’m understanding from your message is that I cannot simply build a module (with Clang or Cling) and have Cling later load it. Cling has some hard-coded support for modules, but I’ll need to extend that if I want to load my own. Since my use case is a programming language compiler which is compiling each namespace into a module, my approach here would need to be dynamic. It sounds like this has not been attempted before with Cling.

One follow up question, though, is that when I run cling with -fmodules, it dies in a fiery explosion. From what you said, I just need to run it from the cmdline with -fmodules, which is what I did. Am I missing something?

Log here (too long to include in this post): cling-error · GitHub

Also, since it’s related, @vvassilev, do you recommend a different way of loading pre-compiled C++? For example, would it be easier to just load compiled object files? I was trying to use modules because they seemed like the cleanest solution, but object files would work just as well. If necessary, I’d entertain even loading LLVM IR files. Any of that would be a speed improvement.

I’m mainly just interested in not having to compile the same code multiple times unless it changes, especially across runs; this will drastically improve startup times for my compiler and runtime.

Nominally it should work. I suspect the problem is that you used a very new version of gcc. Can you go back to something older and check. I’d start with gcc9 or gcc10, gcc11 and gcc12 should also work.

C++ spends around 50% of the time in the frontend. If you compile certain libraries ahead of time that would give you some benefits. In general it depends on the particular workflows.

Modules is the way to go here in my opinion.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.