带有CERN-ROOT的CMake'未定义参考'错误

时间:2019-09-29 22:12:23

标签: c++ cmake

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

我的操作系统是Linux Mint19。我将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

1 个答案:

答案 0 :(得分:0)

我设法编译了项目。
事实证明,ROOT开发人员提供的脚本未将包含TGeoManager实现的.so文件包含在ROOT_LIBRARIES中(感谢,卡米尔·库克(Kamil Cuk,使我注意到了此变量))。很难找到该类,因为该类在Cling(ROOT附带的c ++解释器)中可以正常工作,并且该类几乎是我在项目中使用的ROOT中的唯一类,因此我认为整个ROOT库未正确链接。找到此问题后,我修复了这样的CMake文件(这是来自General / CmakeLists.txt):

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

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