出现未定义的参考错误,但 nm 显示符号存在
Getting undefined reference error but nm shows symbol present
我正在使用 libkml 构建一个大型应用程序。我从这里使用 libkml 的 cmake 端口:https://github.com/rashadkm/libkml
我收到一个奇怪的符号未定义引用错误,即使该符号似乎已被引用和定义。
这是制作命令:
/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.所以 | grep SerializePretty
清楚地显示:
000000000013c9aa T kmldom::SerializePretty[abi:cxx11](boost::intrusive_ptr<kmldom::Element> const&)
现在我不明白是什么问题。我查看了Whosebug上关于这个的现有问题,我在现有问题中找到了四个解决方案:
- 在某些情况下,demangled 符号名称与导致错误的符号不匹配。这显然不是我的情况。
- 在输入 .o 文件的名称后,在命令末尾使用 -llibrary。因此,当链接器遇到库时,它在该库中存在一个未定义的符号。这显然不是我的解决方案,因为我在命令末尾有库。
- 在某些情况下,符号存在于共享库中但没有外部链接或未定义。这可以通过将 nm 与 --extern-only 和 --defined-only 一起使用来确认。因此这对我来说也不是解决方案。
编辑:
附加信息:
这是我正在使用的 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 是 "Application Binary Interface",基本上是关于参数如何进入堆栈(或放入寄存器)以及各种其他类似内容的规范。
尝试确保您的代码是使用 -std=c++11
(或 -std=gnu++11
,如果您使用任何 GNU 扩展)标志编译的。看起来这就是 libkml 的编译方式。 C++11 有许多新功能,需要与 C++11 之前的 ABI 兼容性中断。 C++14 和 C++1z 变化不大,但它们也可能破坏 ABI 兼容性,我不确定。不过在这种情况下,demangled 符号很清楚,libkml 至少需要 C++11。
我正在使用 libkml 构建一个大型应用程序。我从这里使用 libkml 的 cmake 端口:https://github.com/rashadkm/libkml
我收到一个奇怪的符号未定义引用错误,即使该符号似乎已被引用和定义。
这是制作命令:
/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.所以 | grep SerializePretty
清楚地显示:
000000000013c9aa T kmldom::SerializePretty[abi:cxx11](boost::intrusive_ptr<kmldom::Element> const&)
现在我不明白是什么问题。我查看了Whosebug上关于这个的现有问题,我在现有问题中找到了四个解决方案:
- 在某些情况下,demangled 符号名称与导致错误的符号不匹配。这显然不是我的情况。
- 在输入 .o 文件的名称后,在命令末尾使用 -llibrary。因此,当链接器遇到库时,它在该库中存在一个未定义的符号。这显然不是我的解决方案,因为我在命令末尾有库。
- 在某些情况下,符号存在于共享库中但没有外部链接或未定义。这可以通过将 nm 与 --extern-only 和 --defined-only 一起使用来确认。因此这对我来说也不是解决方案。
编辑: 附加信息:
这是我正在使用的 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 是 "Application Binary Interface",基本上是关于参数如何进入堆栈(或放入寄存器)以及各种其他类似内容的规范。
尝试确保您的代码是使用 -std=c++11
(或 -std=gnu++11
,如果您使用任何 GNU 扩展)标志编译的。看起来这就是 libkml 的编译方式。 C++11 有许多新功能,需要与 C++11 之前的 ABI 兼容性中断。 C++14 和 C++1z 变化不大,但它们也可能破坏 ABI 兼容性,我不确定。不过在这种情况下,demangled 符号很清楚,libkml 至少需要 C++11。