静态库的c ++链接器错误
Posted
技术标签:
【中文标题】静态库的c ++链接器错误【英文标题】:c++ Linker error with static library 【发布时间】:2018-06-06 08:02:49 【问题描述】:我正在尝试包含使用静态方法创建的静态库,但在尝试调用该方法时在运行时出现以下错误:
[ INFO] [1528271039.635221775]:使用 4 个工作线程初始化 nodelet。 /opt/ros/kinetic/lib/nodelet/nodelet:符号查找错误:/catkin_ws/devel/lib//libmission_manager_nodelet.so:未定义符号:_ZN14my_commons10ConsoleLog6ROSLogEiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_
静态库有 2 个文件: ConsoleLog.h:
#ifndef CONSOLE_LOG_H
#define CONSOLE_LOG_H
#include "ros/ros.h"
namespace my_commons
class ConsoleLog
public:
static void ROSLog(int type, std::string message,std::string taskName);
static void STDLog(int logType, std::string msg,std::string taskName);
;
// namespace my_commons
#endif //CONSOLE_LOG_H
和 ConsoleLog.cpp:
#include "ConsoleLog.h"
namespace my_commons
void ConsoleLog::ROSLog(int type, std::string message, std::string task)
switch (type)
case (0):
ROS_DEBUG_STREAM("########## " << task << " DEBUG: " << message << " ##########");
break;
case (1):
ROS_INFO_STREAM("########## " << task << " " << message << " ##########");
break;
case (2):
ROS_WARN_STREAM("########## " << task << " WARNNING: " << message << " ##########");
break;
case (3):
ROS_ERROR_STREAM("########## " << task << " ERROR: " << message << " ##########");
break;
void ConsoleLog::STDLog(int logType, std::string msg, std::string task)
std::cout << msg << std::endl;
// namespace my_commons
CMakelist.txt:
cmake_minimum_required(VERSION 2.8.3)
project(my_commons)
set(CMAKE_CXX_FLAGS "-std=c++0x $CMAKE_CXX_FLAGS")
find_package(catkin REQUIRED COMPONENTS
roscpp
)
catkin_package(CATKIN_DEPENDS
INCLUDE_DIRS include)
include_directories(
$catkin_INCLUDE_DIRS
include/
)
###########
## Build ##
###########
add_library(my_commons
src/ConsoleLog.cpp
)
## Specify libraries to link a library or executable target against
set_target_properties(my_commons PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(my_commons
$catkin_LIBRARIES
$roscpp_LIBRARIES
)
#add_dependencies(name_of_package_nodelet)
install(DIRECTORY include/
DESTINATION $CATKIN_PACKAGE_INCLUDE_DESTINATION
FILES_MATCHING PATTERN "*.h"
PATTERN ".svn" EXCLUDE)
# Install library
install(TARGETS my_commons
ARCHIVE DESTINATION $CATKIN_PACKAGE_LIB_DESTINATION
LIBRARY DESTINATION $CATKIN_PACKAGE_LIB_DESTINATION
RUNTIME DESTINATION $CATKIN_PACKAGE_BIN_DESTINATION
)
编辑:
这里是客户端 CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.3)
project(my_mission_manager)
set(CMAKE_CXX_FLAGS "-std=c++0x $CMAKE_CXX_FLAGS")
find_package(catkin REQUIRED COMPONENTS
roscpp
nodelet
std_msgs
my_commons
message_runtime
std_srvs
)
catkin_package(
CATKIN_DEPENDS
message_runtime
std_msgs
my_commons
)
include_directories(
$catkin_INCLUDE_DIRS
include/
)
###########
## Build ##
###########
add_library(my_mission_manager_nodelet
src/my_mission_manager_nodelet.cpp
)
## Specify libraries to link a library or executable target against
target_link_libraries( my_mission_manager_nodelet
$catkin_LIBRARIES
$roscpp_LIBRARIES
)
#add_dependencies(my_mission_manager_nodelet)
# Install library
install(TARGETS my_mission_manager_nodelet
ARCHIVE DESTINATION $CATKIN_PACKAGE_LIB_DESTINATION
LIBRARY DESTINATION $CATKIN_PACKAGE_LIB_DESTINATION
RUNTIME DESTINATION $CATKIN_PACKAGE_BIN_DESTINATION
)
# Install header files
install(DIRECTORY src/
DESTINATION $CATKIN_PACKAGE_INCLUDE_DESTINATION
)
# Install launch files
install(DIRECTORY launch/
DESTINATION $CATKIN_PACKAGE_SHARE_DESTINATION/launch
)
# Install xml files
install(FILES nodelet_plugins.xml
DESTINATION $CATKIN_PACKAGE_SHARE_DESTINATION
)
我在这里错过了什么?
顺便说一句,我可以在 my_commons(枚举)中使用头文件中的数据,但在尝试添加 cpp 文件并在其中调用静态方法时会出现问题。
感谢您的帮助!
【问题讨论】:
编译成功。它在运行时崩溃。 添加了一个缺失的行...你可以再试一次吗?感谢您的帮助。 当然不行,因为你没有为你的库提供任何源文件——因此你的项目甚至没有被编译——因此你缺少一个符号。add_library(my_commons <here you should put sth like MyCommons.cpp>)
。 set_target_properties(my_commons PROPERTIES LINKER_LANGUAGE CXX)
是一种 hack,不是一个好习惯。你的安装命令也有点老套。你到底想达到什么目标?
你说你有静态库,但我看不到你在哪里链接。
@Ptaq666 我不喜欢在这里复制它。添加了缺少的行...
【参考方案1】:
请在下面找到正确 CMake 项目的工作示例:
目录结构:
ROOT
|
+--inc
| +--ConsoleLog.hpp
+--src
| +--ConsoleLog.cpp
| +--main.cpp
+CMakeLists.txt
您的源文件和头文件保持不变(我只是将 *.h 更改为 *.hpp --> 毕竟您是用 C++ 编写的,而不是 C)。
main.cpp:
#include "ConsoleLog.hpp"
int main()
my_commons::ConsoleLog log;
log.ROSLog(1, "xxx", "yyy");
return 0;
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.11)
project(my_commons)
set(CMAKE_CXX_FLAGS "-std=c++11 $CMAKE_CXX_FLAGS")
find_package(catkin REQUIRED COMPONENTS roscpp)
add_library(my_commons STATIC src/ConsoleLog.cpp)
target_include_directories(my_commons PUBLIC inc $roscpp_INCLUDE_DIRS)
target_link_libraries(my_commons $catkin_LIBRARIES $roscpp_LIBRARIES)
add_executable(MyExec src/main.cpp)
target_link_libraries(MyExec my_commons)
执行结果:
./MyExec
[ INFO] [1528280295.971205050]: ########## yyy xxx ##########
我使用更新的 CMake 版本才能使用target_include_directories
,因为我喜欢这个功能。我更改了您的编译器标志以包含 C++11 标准,因为显然您使用它。我还删除了 INSTALL CMake 规则,因为它们与问题无关。让我知道这个答案是否适合您。
=============== 编辑(回答OP评论)==============
嗯,将这个库嵌入到另一个项目结构中没有任何问题。您收到的错误意味着您的目录结构不正确(my_commons
dir 不存在)。您的项目树应如下所示:
ROOT
|
+--MyCommonsLib (this is the root of your my_commons library)
|
+--src
| +--main.cpp
+CMakeLists.txt
您项目的 CMakeLists.txt
可能如下所示:
cmake_minimum_required(VERSION 2.8.11)
project(SomeSimpleProjectUsingMyCommonsLib)
add_subdirectory(MyCommonsLib)
add_executable(MyExec src/main.cpp)
target_link_libraries(MyExec my_commons)
请记住从您的MyCommonLib/CMakeLists.txt
中删除add_executable
指令。 main.cpp
也应该是这样的:
#include "ConsoleLog.hpp"
int main()
my_commons::ConsoleLog::ROSLog(1, "xxx", "yyy");
return 0;
抱歉,在我没有注意到 ROSLog
被声明为静态之前。
【讨论】:
嗨@Ptaq666,感谢您的回复!有必要在静态库中有一个 main 吗?重点是创建一类我可以在不同项目中使用的静态方法...此外,由于我有更多具有相同编译器标志的项目,我现在不想将其更改为较新的版本.. . 不不,当然没必要。我只包含了主要的可执行文件来证明该解决方案是有效的。您可以通过调用add_subdirectory
将 my_commons
库嵌入到项目的 CMakeLists.txt
中。如果您想在系统上安装my_commons
并使用find_package
找到它 - 这更复杂,因为您需要创建my_commonsConfig.cmake
,这会使您的任务进一步复杂化。如何适当地做到这一点是另一个话题(虽然不是那么难)。
问题是我能够使用来自 my_common 库中头文件的数据。仅当使用静态方法添加 cpp 时才会出现问题...尝试 add_subdirectory 时得到:CMake Error at my_mission_manager/CMakeLists.txt:27 (add_subdirectory): add_subdirectory given source "my_commons" which is not an existing directory.
表示my_commons
目录不存在。我编辑了答案并解释了你应该如何将你的库嵌入到项目中。
感谢您提供的所有帮助... 看来层次结构是正确的,但它仍然无法正常工作。但是,当我尝试将代码从 cpp 文件移动到头文件时,一切正常。所以现在我很困惑:)以上是关于静态库的c ++链接器错误的主要内容,如果未能解决你的问题,请参考以下文章
qt creator qt5.1 vs2010 使用静态库时链接器错误
linux上静态库和动态库的编译和使用(附外部符号错误浅谈)