CERN-ROOT的CMake“未定义参考”错误

Posted

技术标签:

【中文标题】CERN-ROOT的CMake“未定义参考”错误【英文标题】:CMake 'undefined reference' error with CERN-ROOT 【发布时间】:2019-09-29 22:12:23 【问题描述】:

我正在为 CERN ROOT 编写一个小补充,现在无法摆脱我使用的每个 ROOT 函数(以及我的类)的“未定义引用”错误。找不到解决这个问题的方法,所以在这里寻求帮助)

我的操作系统是 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 $ENVROOTSYS)
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

【问题讨论】:

那么ROOT_LIBRARIES 的背后是什么? /path/to/root/compile/lib/libCore.so /path/to/root/npm/root/compile/lib/libImt.so /path/to/root/root/compile/lib/libRIO.so 等等。他们有很多。我的主目录中的根目录路径 【参考方案1】:

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

file(GLOB_RECURSE SOURCES2 . $ENVROOTSYS/lib/*.so)
add_library(General SHARED $SOURCES $SOURCES2 GeoManagerExtractor.cxx)

这消除了所有“对 'gGeoManager' 的未定义引用”等,但“对 TGeoManagerExporter 的 vtable 的未定义引用”(TGeoManagerExporter 是我自己的类)仍然存在。但是,我发现此错误是由反射功能引起的,因此作为临时解决方案,我只是不激活它。如果我解决了这个问题,我会在这里发表评论。

【讨论】:

以上是关于CERN-ROOT的CMake“未定义参考”错误的主要内容,如果未能解决你的问题,请参考以下文章

未定义参考错误“x”。运行命令时

来自 GCC 的未定义参考错误使用带有 std::vector 和特征矩阵的模板?

未定义参考编译MITK/Qt

Thrift 生成的代码未定义参考

是否有解决未定义参考/未解决符号问题的一般准则?

使用 G++,未定义参考 std::Makefile