我使用CMake 3.5.2。在尝试构建我的C ++代码时,出现以下错误:
[100%] Linking CXX executable SomeExecutable
CMakeFiles/SomeExecutable.dir/Common/src/FunctionOne.cpp.o: In function `FunctionOne::FunctionOne(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, double, unsigned int, bool)':
FunctionOne.cpp:(.text+0x490): undefined reference to `Helper::initLevel(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'
程序在myLib.so中找不到Helper :: initLevel()。我该如何解决?
CMakeLists.txt :(简称简称)
cmake_minimum_required(VERSION 3.0)
project(ProjectName)
add_definitions(-std=c++11)
add_definitions(-Wall)
add_definitions(-O2)
link_directories(/usr/local/lib)
add_executable(SomeExecutable SomeExecutable.cpp ${FunctionOne} ${FunctionTwo})
target_link_libraries(SomeExecutable -pthread -lboost_thread ${Boost_LIBRARIES} myLib armadillo)
文件结构(为简洁起见缩短):
├── bin
├── CMakeCache.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── Common
│ ├── include
│ │ ├── dataContainer.h
│ │ ├── FunctionOne.h
│ │ ├── FunctionTwo.h
│ └── src
│ ├── FunctionOne.cpp
│ └── FunctionTwo.cpp
├── SomeExecutable.cpp
├── myLib
│ ├── example.cpp
│ ├── include
│ │ ├── Config.h
│ │ ├── Helper.h
│ ├── libmyLib.so
更新
MYLIB /包含/ config.h中:
Namespace Helper {
[...]
Level* initLevel(const std::string& jsonLvlPath, bool twiceSpatPts = false);
[..]
}
更新2:
kepj@laptop:~/ProjectName$ make VERBOSE=1
/usr/bin/cmake -E cmake_link_script CMakeFiles/SomeExecutable.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/SomeExecutable.dir/SomeExecutable.cpp.o CMakeFiles/SomeExecutable.dir/Common/src/FunctionOne.cpp.o CMakeFiles/SomeExecutable.dir/Common/src/FunctionTwo.cpp.o SomeExecutable -L/usr/local/lib -rdynamic -pthread -lboost_thread -lboost_system -lboost_filesystem -lmyLib -lsymbolicc++ -lmatio -larmadillo -Wl,-rpath,/usr/local/lib
CMakeFiles/SomeExecutable.dir/Common/src/FunctionTwo.cpp.o: In function `FunctionTwo::FunctionTwo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double, double, unsigned int, bool)':
FunctionTwo.cpp:(.text+0x490): undefined reference to `Helper::initLevel(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)'
collect2: error: ld returned 1 exit status
CMakeFiles/SomeExecutable.dir/build.make:174: recipe for target 'SomeExecutable' failed
make[2]: *** [SomeExecutable] Error 1
make[2]: Leaving directory '/home/kepj/ProjectName'
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/SomeExecutable.dir/all' failed
make[1]: *** [CMakeFiles/SomeExecutable.dir/all] Error 2
make[1]: Leaving directory '/home/kepj/ProjectName'
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
答案 0 :(得分:1)
因此,在技术上仍然没有足够的信息可以肯定地回答这个问题,但我将分享如何调试这个问题,只知道问题的内容,解释一路上的每一步。
myLib.so
这个很有说服力,对于这个问题的根源我将是最好的猜测。
相关的编译器标志:-L/usr/local/lib -lmyLib
当您尝试使用编译命令的-l
参数找到指定的库时,链接器会执行一系列步骤:
1.它会看到传递给-l
的参数是否是绝对路径(从库的整个路径开始,即从* nix计算机上的/
或Windows上的驱动器号开始)或仅仅是名称。如果它是绝对路径,那么它知道它在哪里。在这种情况下,它只是一个名称,所以继续执行第2步。
2.下一个要查看的位置是-L
个参数中指定的路径。在这种情况下,唯一的-L
参数是/usr/local/lib
所以它看起来就在那里。这可能是也可能不是这个具体案例的地方。查看文件系统以查看文件/usr/local/lib/libmyLib.so
是否存在,如果存在,请确保该文件是最重要的版本。
3.现在它在configured linker paths中搜索。对于每个路径,请使用与步骤2中相同的步骤。
这是我的猜测,因为您的链接器参数中没有引用您的myLib
文件夹,但您声称它位于该文件夹中,因此我认为它使用的是过时的myLib.so
。
.so
或.a
文件实际上具有未定义的符号在Linux上,你可以list the symbols defined in a .so
file。确保解析为undefined的符号在那里。
如果他们不在那里,可能的原因如下:
.cpp
)来创建您的库。namespace Helper
MyClass::
。(感谢n.m在评论中指出这一点)
由于C ++标准库有多个实现(和版本),因此可能存在 ABI Mismatch 。
这意味着myLib
使用编译的标准库与您尝试编译可执行文件的标准库不兼容。例如,当您在linux上使用libstdc ++编译myLib
时,请转到mac并尝试编译您的可执行文件,其中标准库是libc ++,您将获取错误。为什么?任何事物的签名,例如std::string
都不一样。它们完全是不同的类,并且在链接时会导致签名不匹配。