CERN-ROOT 的 CMake 'undefined reference' 错误

CMake 'undefined reference' error with CERN-ROOT

我正在为 CERN ROOT 编写一个小的补充,现在无法消除我使用的 ROOT 中每个函数的 'undefined reference' 错误(以及我的 类)。找不到解决此问题的方法,因此请在此处寻求帮助。

我的 OS 是 Linux Mint 19。我使用 g++ 作为我的 c++ 编译器,但是,我尝试了 clang++ 并且没有区别。 我从他们的 github 下载了 ROOT 的源代码并在我的电脑上构建了它。 root --version 的输出是这样的:

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

这是我项目的结构:

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

来自顶层 CMakeLists.txt 的重要行是:

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

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

来自 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})

来自 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")

这是 CMake 生成的前几行(使用 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)

这里有几行来自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:忘了说,为了创建我的 CMakeLists.txt 文件,我使用了这两个来源: https://root.cern.ch/how/integrate-root-my-project-cmake https://cliutils.gitlab.io/modern-cmake/chapters/packages/ROOT.html

我已经成功地编译了我的项目。
事实证明,包含 TGeoManager 实现的 .so 文件未包含在 ROOT 开发人员提供的脚本中 ROOT_LIBRARIES(感谢 Kamil Cuk 让我注意到这个变量)。很难找到,因为这个 class 在 Cling 中正常工作(C++ 解释器包含在 ROOT 中)并且这个 class 几乎是我在项目中使用的唯一一个来自 ROOT 的,所以我假设,整个 ROOT 库没有正确链接。发现这个问题后,我修复了我的 CMake 文件(来自 General/CmakeLists.txt):

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

这消除了所有 "undefined reference to 'gGeoManager'" 等,但 "undefined reference to `vtable for TGeoManagerExporter'"(TGeoManagerExporter 是我自己的 class)保留了下来。但是,我发现这个错误是由反射特性引起的,所以作为临时解决方案,我只是不激活它。如果我解决了这个问题,我会post在这里发表评论。