'CMake 'undefined reference' error with CERN-ROOT

I'm writing a small addition to CERN ROOT and now can't get rid of 'undefined reference' errors on every function from ROOT that I use (and my classes too). Can't find a way to fix this, so looking for help here.

My OS is Linux Mint 19. I use g++ as my c++ compiler, however, I tried clang++ and there was no difference. I downloaded sources of ROOT from their github and built it now on my computer. Output of root --version is this:

ROOT Version: 6.19/01
Built for linuxx8664gcc on Sep 29 2019, 14:25:35
From heads/master@v6-19-01-1167-gbec9f2d1f7

This is the structure of my project:

ParentFolder
--CMakeLists.txt
--General
----include/...
----source/...
----CMakeLists.txt
----LinkDef.h
--Test
----include/...
----source/...
----CMakeLists.txt

Important lines from top level CMakeLists.txt are:

find_package(ROOT REQUIRED)
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
include(${ROOT_USE_FILE})

add_subdirectory("./General")
add_subdirectory("./Test")

From Test/CmakeLists.txt:

add_executable(Test source/test_main.cpp)

target_include_directories(Test PUBLIC "./include")

target_link_libraries(Test PUBLIC General GTest::GTest GTest::Main ${ROOT_LIBRARIES})

From General/CmakeLists.txt:

file(GLOB_RECURSE SOURCES . source/*.cpp)

ROOT_GENERATE_DICTIONARY(GeoManagerExtractor LINKDEF LinkDef.h)

add_library(General SHARED ${SOURCES} GeoManagerExtractor.cxx)

target_link_libraries(General ${ROOT_LIBRARIES})

target_include_directories(General PUBLIC "./include")

Here are first few lines produced by CMake (while using clang++)

CMakeFiles/Test.dir/source/test_main.cpp.o: In function `main':
test_main.cpp:(.text+0x37): undefined reference to `TGeoManager::Import(char const*, char const*, char const*)'
test_main.cpp:(.text+0x3f): undefined reference to `gGeoManager'
test_main.cpp:(.text+0x8c): undefined reference to `gGeoManager'
CMakeFiles/Test.dir/source/test_main.cpp.o: In function `TGeoManagerExporter::~TGeoManagerExporter()':
test_main.cpp:(.text._ZN19TGeoManagerExporterD2Ev[_ZN19TGeoManagerExporterD2Ev]+0xa): undefined reference to `vtable for TGeoManagerExporter'
../General/libGeneral.so: undefined reference to `ROOT::GenerateInitInstance(TGeoManagerExporter const*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Here are a few lines from test_main.cpp:

TGeoManager::Import("../root_tests/geofile_full.root");
    if (gGeoManager == nullptr) {
        std::cerr << "Can't find TGeoManager in file" << std::endl;
        return 0;
    }

UPD: Forgot to mention, that in order to create my CMakeLists.txt files I used these two sources: https://root.cern.ch/how/integrate-root-my-project-cmake https://cliutils.gitlab.io/modern-cmake/chapters/packages/ROOT.html



Solution 1:[1]

I have managed to compile my project.
As it turned out, .so file that contains TGeoManager implementation was not included in ROOT_LIBRARIES(thanks, Kamil Cuk for bringing my attention to this variable) by the script provided by ROOT developers. It was hard to find as this class was working properly in Cling(c++ interpreter included with ROOT) and this class is almost the only one from ROOT that I use in the project, so I assumed, that the whole ROOT library was not linking properly. After I found this issue, I fixed my CMake files like this (this is from General/CmakeLists.txt):

file(GLOB_RECURSE SOURCES2 . $ENV{ROOTSYS}/lib/*.so)
add_library(General SHARED ${SOURCES} ${SOURCES2} GeoManagerExtractor.cxx)

This eliminates all of the "undefined reference to 'gGeoManager'" and alike, but "undefined reference to `vtable for TGeoManagerExporter'" (TGeoManagerExporter is my own class) stays. However, I figured out that this error is caused by a reflection feature, so as a temporary solution I just don't activate it. I'll post a comment here if I solve this problem.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Unrealf1