cmake教程(二) 库的使用

include_directories

参数应该是find_package调用生成的* _INCLUDE_DIRS变量以及需要包含的任何其他目录。如果您使用catkin和Boost,则include_directories调用应如下所示:

1
2
# 先调用find_package(Boost catkin),才能使用下面两个宏
include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

include是目录名,不是命令,一般放头文件。使用message函数发现catkin_INCLUDE_DIRS/opt/ros/kinetic/include/usr/include

不能直接include当前文件夹的头文件,这倒是奇怪。需要加一行include_directories(.)。另一种解决方法就是在add_executable里添加用到的头文件

添加库路径

1
LINK_DIRECTORIES(/usr/lib/) 

并不是必须的,如果能直接链接就不需要。

ADD_LIBRARY

生成库文件是ADD_LIBRARY,它的功能是用来指定库来构建。默认情况下,catkin构建共享库。

构建库如下PointManage:

1
2
3
4
5
6
7
add_library(PointManage src/point_manage.cpp)
target_link_libraries(PointManage
${catkin_LIBRARIES} -pthread -llog4cpp -lcgicc -lmysqlclient jsoncpp Qt5::Core Qt5::Xml
)

add_executable(point_node src/point_manage_node.cpp src/point_manage.cpp)
target_link_libraries(point_node ${catkin_LIBRARIES} -llog4cpp -lmysqlclient -pthread Qt5::Core Qt5::Xml)

库PointManage用到了Qt库,此时也需要加上target_link_libraries命令,编译才能成功。

add_library(lib a.cpp),如果a.cpp中使用了类Test,对应头文件test.h和源文件test.cpp。这种情况下,光include "test.h"不够,应当改成add_library(lib a.cpp test.cpp)

链接库

target_link_libraries必须放在add_executable(或者add_library)的后面。一般要先写好后者,然后再链接库:

1
2
3
4
5
add_executable(test "main.c")

target_link_libraries(test
${catkin_LIBRARIES}
) //必须跟上面的test同名,后者是很多共享库,大部分是Boost,显然ROS底层用的是Boost

但是注意,如果是生成动态库文件,最好不要再让它链接其他库文件,有时会失败。对于静态库,禁止链接其他库。

查看是否链接动态库成功,可以使用Linux的ldd命令

链接库时报警 缺函数.png
从报错内容可以看出是缺了distance函数,也就是要链接的so文件里没有distance函数

ALL_TARGET_LIBRARIES 变量

为了避免target_link_libraries后面跟很长一串库的名字,而且库增减的时候它也得跟着增减,我们在CMakeLists一开始定义一个变量: set(ALL_TARGET_LIBRARIES "")

然后在每个库对应的XX.cmake文件中,把库的名字合并到这个变量中去,list(APPEND ALL_TARGET_LIBRARIES ${XX_LIBRARIES}),这样在target_link_libraries就只使用ALL_TARGET_LIBRARIES这一个变量就好了。

install命令

安装网上下载的库时常常最后一步是make install,这是使用CMake的install函数完成的,该函数的参数:

1
2
3
4
TARGETS   目标安装
ARCHIVE DESTINATION 静态库和DLL(Windows).lib存根
LIBRARY DESTINATION 非DLL共享库和模块
RUNTIME DESTINATION 可执行目标和DLL(Windows)样式共享库

ROS的launch文件可以安装到${CATKIN_PACKAGE_SHARE_DESTINATION}:

1
2
3
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
PATTERN ".svn" EXCLUDE)

参考:
ROS CMakeLists Posted by G.J.先生
catkin_make的时候发生了什么