Compilation error using the cxxmodule option with ROOT_GENERATE_DICTIONARY

Dear ROOT-Team,

I started to investigate cxxmodules and ran into a compilation error for a simple example built with CMake.
I add parts of the CMakeLists.txt below, but you can find the whole reproducer at [1] and attached as an archive to this post.

# CMakeLists.txt
...
add_executable(myapp main.cc)
target_link_libraries(myapp ROOT::RIO)
ROOT_GENERATE_DICTIONARY(myapp_dict 
                         functor.h 
                         MODULE myapp 
                         LINKDEF LinkDef.h
                         OPTIONS --cxxmodule)
...

Build the example with:

git clone https://github.com/LukasBreitwieser/ROOT-cxxmodule-reproducer.git
# or by extracting ROOT-cxxmodule-reproducer.zip
cd ROOT-cxxmodule-reproducer
mkdir build && cd build
cmake .. && make

Here the complete build output including the error on ubuntu 22.04 with ROOT 6.28/04:

-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/lukas/ROOT-cxxmodule-reproducer/build
[ 25%] Generating myapp_dict.cxx, libmyapp_rdict.pcm, libmyapp.rootmap
/home/lukas/ROOT-cxxmodule-reproducer/build/module.modulemap:3:31: error: cannot emit module myapp: size must be explicitly specified for missing header file "functor.h"
  module "functor.h" { header "functor.h" export * }
                              ^
/home/lukas/ROOT-cxxmodule-reproducer/build/module.modulemap:3:31: error: cannot emit module myapp: size must be explicitly specified for missing header file "functor.h"
[ 25%] Generating myapp_dict.cxx, libmyapp_rdict.pcm, libmyapp.rootmap
/home/lukas/ROOT-cxxmodule-reproducer/build/module.modulemap:3:31: error: cannot emit module myapp: size must be explicitly specified for missing header file "functor.h"
  module "functor.h" { header "functor.h" export * }
                              ^
/home/lukas/ROOT-cxxmodule-reproducer/build/module.modulemap:3:31: error: cannot emit module myapp: size must be explicitly specified for missing header file "functor.h"
[ 50%] Building CXX object CMakeFiles/myapp_dict.dir/myapp_dict.cxx.o
[ 50%] Built target myapp_dict
[ 75%] Building CXX object CMakeFiles/myapp.dir/main.cc.o
[100%] Linking CXX executable myapp
[100%] Built target myapp

Here the rootcling call that errors out (copied from make VEBOSE=1):

/home/lukas/programs/root/bin/rootcling -v2 -f myapp_dict.cxx \
  -s /home/lukas/ROOT-cxxmodule-reproducer/build/libmyapp.so \
  -rml libmyapp.so -rmf /home/lukas/ROOT-cxxmodule-reproducer/build/libmyapp.rootmap \
  --cxxmodule \
  -compilerI/usr/include/c++/11 \
  -compilerI/usr/include/x86_64-linux-gnu/c++/11 \
  -compilerI/usr/include/c++/11/backward \
  -compilerI/usr/lib/gcc/x86_64-linux-gnu/11/include \
  -compilerI/usr/local/include \
  -compilerI/usr/include/x86_64-linux-gnu \
  -compilerI/usr/include \
  -compilerI/usr/lib/gcc/x86_64-linux-gnu/11/include \
  -compilerI/usr/local/include \
  -compilerI/usr/include/x86_64-linux-gnu \
  -compilerI/usr/include \
  -I/home/lukas/programs/root/include \
  -I/home/lukas/ROOT-cxxmodule-reproducer \
  -I/home/lukas/programs/root/include \
  functor.h \
  /home/lukas/ROOT-cxxmodule-reproducer/LinkDef.h

functor.h is stored in /home/lukas/ROOT-cxxmodule-reproducer, which is given as an include directory, so cling should find the header.
I also tried setting the ROOT_INCLUDE_PATH environment variable, but to no avail.
Can you confirm that this is a bug of rootcling, or did I miss something?

I found a workaround by setting the path of functor.h in module.modulemap relative to the build directory. (Uncomment the last four lines in CMakeLists.txt to try it out.)
However, I am unsure of the implications. Does this mess things up in the generated pcm that will only show up for more complex examples, e.g. with multiple modules?

Many thanks in advance for your help!

Lukas

[1] LukasBreitwieser/ROOT-cxxmodule-reproducer · GitHub

ROOT Version: 6.28/04 (Binaries from the root website)
Platform: Ubuntu 22.04
Compiler: g++ 11.3.0
ROOT-cxxmodule-reproducer.zip (2.0 KB)

Hello @lbreitwi,

welcome back to the forum. Maybe @bellenot could take a look?

Cheers,
Marta

OK, it works without MODULE myapp or without OPTIONS --cxxmodule in CMakeLists.txt. And since it’s a C++ module related issue, I’ll let @vvassilev or @Axel check what the error (or the correct syntax) is.

Thanks @bellenot for taking a look, but to enable cxxmodules I need both of these options.
@vvassilev , or @Axel what are your thoughts?

Apologies for the delay, I am slowly digging myself out :slight_smile:

We can only build dictionaries/modules for libraries. Your header file should become part of some library. Here is an example which seems to build a module file:

cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(myapp)

find_package(ROOT REQUIRED COMPONENTS Core)
include(${ROOT_USE_FILE})

ROOT_STANDARD_LIBRARY_PACKAGE(myapplib
  HEADERS functor.h
  SOURCES main.cc
  LIBRARIES Core
  )
add_executable(myapp main.cc)
target_link_libraries(myapp ROOT::RIO)

Here we probably hit a deficiency in our cmake files where we still build a libmyapplib.rootmap and libmyapplib_rdict.pcm. You can delete these.

Thank you for your time @vvassilev !
I took a look at your suggestion and think that it does not generate a cxxmodule.

Here my analysis:

  1. Although a module.modulemap file is generated, the myapplib.pcm file is missing.
  2. Also the dictionary file G__myapplib.cxx on line 141 reads:
        TriggerDictionaryInitialization_libmyapplib_Impl, {}, classesHeaders, /*hasCxxModule*/false);
  1. The dictionary variables headers, includePaths, fwdDeclCode, payloadCode, and classesHeaders are not empty.
  2. The only difference in the rootcling invocation between my reproducer and your suggestion is that in your suggestion the --cxxmodule flag is not passed.

If I add DICTIONARY_OPTIONS --cxxmodule to the invocation of the cmake macro ROOT_STANDARD_LIBRARY_PACKAGE, I receive the same error that I reported initially.

Although the usage of cxxmodules does not make a big difference in this simple reproducer, I am trying to reduce the startup time of the interpreter and hopefully also the memory consumption for the BioDynaMo code base [1, 2].

Thanks,
Lukas

[1] https://doi.org/10.1093/bioinformatics/btab649
[2] High-Performance and Scalable Agent-Based Simulation with BioDynaMo | Proceedings of the 28th ACM SIGPLAN Annual Symposium on Principles and Practice of Parallel Programming

@lbreitwi hm, yes, you are right.

I have a fix submitted here: [cxxmodules] Make the ROOT modulemap only a dependency when building ROOT by vgvassilev · Pull Request #13213 · root-project/root · GitHub

Now you can take the same example and configure it with cmake -Druntime_cxxmodules=On .. and you should be good to go.

I’d be happy to organize a hacking session if that helps you.

Hi @vvassilev ,
I just tested your PR (v6-29-01-1911-ga76fd114d7) with my reproducer, but unfortunately it does not solve the issue.
Without patching the module.modulemap, it shows the missing header file error and does not generate a pcm.
Do you have time for a pair programming session end of next week?

Worked for me… Let’s take this offline. Can you drop me an email?

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