How can I fix the root map ?
It seems enum class is missing in root map so MyEnum is not defined.
Here are some abstractions:
# LinkDef.h
#pragma link C++ enum class MyEnum;
#pragma link C++ class MyClass<MyEnum::E0>+;
#pragma link C++ class MyClass <MyEnum::E1>+;
#pragma link C++ class MyClass <MyEnum::E2>+;
# Header.h
enum class MyEnum { E0, E1, E2 };
template <MyEnum T = MyEnum::E0>
class MyClass : public MyClassAbstract
{
// [...]
}
Thank you for your great help! It sounds like progress.
I can now see MyEnum in [..]/install/lib/libXXX.rootmap under the list of [ libXXX.dylib ] elements, but the following issue persists.
Forward declarations from [..]/install/lib/libXXX.rootmap:3:11: error: unknown type name 'MyEnum'
template <MyEnum> class MyClass;
May I ask some information about the meaning of { decls } ? It seems to be detached of the [ libXXX.dylib ] column.
The issue happens when I load the libXXX library and start using templated class MyClass. I use ROOT 6.32 and 6.34, issue tested on macOS and Linux on my side.
I believe this issue has also been reproduced by @vpadulan earlier this year.
Would you have any further idea how to fix that ?
Or some possible investigation I could do ? I basically don’t know where this error comes from and don’t know where to look at.
Support for enum class as template arguments in a I/O class (i.e your case) using rootmap files is not yet implemented (side note, support for unscoped enum as template arguments in an I/O class using rootmap files can not be supported as they can not be forward declared).
The file interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp would need to be enhance to print the necessary enum class declarations.
Alternatively you can try to switch to the newer ‘cxx module’ based dictionary (replacing both the rootmap file and headers), using something like:
Indeed, I use enum class, I believe it has some advantages as compared to enum.
I had a look at your file. It seems the method is partially implemented already:
I am already using ROOT_GENERATE_DICTIONARY with the MODULE option since couple of years so I believe I may use already this cxx module features under the hood.
$ ls
libMyLib.dylib libMyLib.rootmap libMyLib_rdict.pcm MyLib.Dict.cxx
I just removed libMyLib.rootmap and kept cxx & pcm files. I believe the cxx module based dictionary should be libMyLib_rdict.pcm ? Not sure why rootmap is prioritized, but the error message disappear if I just remove rootmap file. How to check everything is working ?
No. It would be MyLib.pcm. The .rootmap and _rdict.pcm files are working together.
So something is going wrong(ish?) in the cmake execution (and/or my memory of how it should work) of ROOT_GENERATE_DICTIONARY … since you have ROOT configured with runtime_cxxmodules. I need to try to reproduce this. Can you give me access to your code/project?
While preparing this example, I ended up moving my hand the outgoing files one by one: libMyLib.dylib, libMyLib_rdict.pcm, libMyLib.rootmap.
Here are some of my observations. I would be
mkdir lib && cd lib
mv ../libMyLib.dylib .
# root [0] .L libMyLib.dylib
# Error in <TCling::LoadPCM>: ROOT PCM ./pcanal/build/lib/libMyLib_rdict.pcm file does not exist
# Info in <TCling::LoadPCM>: In-memory ROOT PCM candidate ./root/20240914/lib/libASImageGui_rdict.pcm
# [...]
mv ../libMyLib_rdict.pcm libMyLib_rdict.pcm
# root [0] .L libMyLib.dylib
# <no error>, can use the library and execute my templated class
mv ../libMyLib.rootmap libMyLib.rootmap
#$ root -l
#Forward declarations from ./libMyLib.rootmap:2:11: error: unknown type name 'MyEnum'
#template <MyEnum> class MyClass;
# ^
#Warning in <TInterpreter::LoadLibraryMap>: Problems in (null) declaring '
#line 2 "Forward declarations from [...]
When using the older alternative, the file libMyLib_rdict.pcm is indeed necessary while the file libMyLib.rootmap is optional but enables the autoloading of libraries.
I managed to run cxxmodules and also generate a module.modulemap. It can be renamed at installation stage and then I just point to it using ‘CLING_MODULEMAP_FILES’ to load it with a custom name and location.
I don’t get anymore the enum class issue using this new method. I just noticed my new .pcm is about 130MB. I believe this is due to the embedded libraries implemented in the source.