获取未定义的参考错误,但nm显示符号存在
我正在使用libkml构建一个大型应用程序。我从这里使用libkml的cmake端口:https://github.com/rashadkm/libkml获取未定义的参考错误,但nm显示符号存在
我得到一个奇怪的未定义的符号错误引用,即使认为该符号似乎被引用和定义。
这是make命令:
/usr/bin/c++ -fPIC -Werror=return-type -Werror=return-type -Wall
-Werror=parentheses -Werror=uninitialized -Werror=missing-braces
-fPIC -O0 -Wall -fPIC -fvisibility=hidden -fno-strict-aliasing
-Wno-long-long -m64 -g -D_DEBUG --coverage -Wl,-Bsymbolic -Wl,--
no-undefined -shared -o GPS2KML.plb CMakeFiles/GPS2KML.dir
/gps.cpp.o CMakeFiles/GPS2KML.dir/kml.cpp.o CMakeFiles/GPS2KML.dir
/stdafx.cpp.o /trunk/src/filter/GPS2KML/external/libkml/lib/cmake
/libkml/../../libkmlconvenience.so.1.3.1 /trunk/src/filter/GPS2KML
/external/libkml/lib/cmake/libkml/../../libkmlengine.so.1.3.1
/trunk/src/filter/GPS2KML/external/libkml/lib/cmake/libkml/../..
/libkmldom.so.1.3.1 /trunk/src/filter/GPS2KML/external/libkml
/lib/cmake/libkml/../../libkmlbase.so.1.3.1 -lminizip -luriparser
-lexpat
的化妆输出:
CMakeFiles/GPS2KML.dir/kml.cpp.o: In function `cKML::~cKML()':
/trunk/src/filter/GPS2KML/src/kml.cpp:55: undefined reference to `*kmldom::SerializePretty(boost::intrusive_ptr<kmldom::Element> const&)*'
collect2: error: ld returned 1 exit status
现在,如果我这样做: 丹尼亚尔@丹尼亚尔-的Inspiron-5521:/ $纳米--demangle - -extern-only --defined-only ../trunk/src/filter/GPS2KML/external/libkml/lib/libkmldom.so | grep的SerializePretty
它清楚地表明:
000000000013c9aa T kmldom::SerializePretty[abi:cxx11](boost::intrusive_ptr<kmldom::Element> const&)
现在我不明白是什么问题。我有检查计算器对此中存在的问题,我发现了存在的问题四种解决方案:
- 在某些情况下,demangled符号名称不与已导致错误的符号匹配。这显然不是我的情况。
- 在放入.o文件的名称后,在命令末尾使用-llibrary。因此,当链接器遇到库时,库中存在未定义的符号。对于我来说,这显然不是解决方案,因为我在图书馆结束时提供了图书馆。
- 在某些情况下,符号存在于共享库中,但没有外部链接或未定义。这可以通过使用带有--extern-only和--defined-only的nm来确认。因此这对我来说也不是解决方案。
编辑: 附加信息:
这是我使用的cmake的文件:
find_package(LibKML REQUIRED)
include_directories(${LIBKML_INCLUDE_DIRS})
add_filter(${PROJECT}
gps.h
gps.cpp
kml.h
kml.cpp
#can2gps.h
#can2gps.cpp
stdafx.h
stdafx.cpp)
target_link_libraries (${PROJECT} ${LIBKML_LIBRARIES})
的add_filter大致翻译这个宏:
add_library(${NAME} MODULE ${ARGN} ${${NAME}_MOC} ${${NAME}_UI} ${${NAME}_QRC})
target_link_libraries(${NAME} ${BUILD_LIBS} ${QT_LIBRARIES} ${ADTF_OPENGL_LIBRARY} ${ADTF_ADDITIONAL_UTILS_LIBS})
set_target_properties(${NAME}
PROPERTIES
SUFFIX ".plb"
)
if(UNIX)
set_target_properties(${NAME}
PROPERTIES
PREFIX ""
)
它看起来像你ABI不匹配问题。 ABI是“应用程序二进制接口”,基本上就是参数如何进入堆栈(或放入寄存器)以及其他各种事情的规范。
请确保您的代码与-std=c++11
(或-std=gnu++11
,如果您使用任何GNU扩展)标志编译。它看起来就是如何编译libkml的。 C++ 11具有一系列需要与C++ 11之前的ABI兼容性中断的新功能。 C++ 14和C++ 1z并没有那么剧烈的变化,但它们也可能会破坏ABI兼容性,我不确定。在这种情况下,demangled符号很清晰,libkml至少需要C++ 11。
对不起,这么晚将它标记为已接受的答案。我的项目的cmake结构是强制执行C++ 98 ..我必须找出add_definitions(-D_GLIBCXX_USE_CXX11_ABI = 1)选项 非常感谢你的帮助 –
@DaniyalYasin - 我只是很高兴你的问题解决了。 – Omnifarious
链接的顺序很重要...您必须先与依赖者链接,然后依赖链接。如果您有循环引用,则可能需要多次链接到库 – UKMonkey
另一种可能性是,名称demangling不知何故模糊了某些内容。试试'nm --extern-only --defined-only | egrep'kmldom。* Serialize。* boost。* intrusive_ptr。* kmldom。* Element''然后看看你能否看到精确的损坏符号。也许这个符号是针对不同的ABI版本的。 – Omnifarious
@Omnifarious在运行你的命令时,没有产生输出。 –