获取未定义的参考错误,但nm显示符号存在

时间:2017-06-12 13:54:32

标签: c++ makefile cmake kml ld

我正在使用libkml构建一个大型应用程序。我从这里使用libkml的cmake端口:https://github.com/rashadkm/libkml

即使符号似乎被引用和定义,我也会得到一个奇怪的未定义的符号错误引用。

这是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

make输出:

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

现在,如果我这样做:     daniyal @ daniyal-Inspiron-5521:/ $ nm --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&)

现在我不明白是什么问题。我已经检查了有关这方面的stackoverflow的现有问题,我在现有问题中找到了四个解决方案:

  1. 在某些情况下,demangled符号名称与导致错误的符号不匹配。这显然不是我的情况。
  2. 在输入.o文件的名称后,在命令末尾使用-llibrary。因此,当链接器遇到库时,它在该库中存在未定义的符号。这显然不是我的解决方案,因为我在命令末尾有库。
  3. 在某些情况下,符号存在于共享库中,但没有外部链接或未定义。这可以通过使用nm与--extern-only和--defined-only来确认。因此,这对我来说也不是一个解决方案。
  4. 编辑: 附加信息:

    这是我正在使用的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 ""
    

1 个答案:

答案 0 :(得分:2)

看起来您有ABI不匹配问题。 ABI是“应用程序二进制接口”,基本上是关于参数如何将其放入堆栈(或放入寄存器)以及其他各种类似的规范。

尝试确保使用-std=c++11编译代码(如果使用任何GNU扩展,则为-std=gnu++11)标记。看起来这就是libkml的编译方式。 C ++ 11具有一系列新功能,需要与C ++ 11之前的ABI兼容性中断。 C ++ 14和C ++ 1z的变化不大,但它们也可能打破ABI兼容性,我不确定。在这种情况下,demangled符号是清楚的,libkml至少需要C ++ 11。