<中常⽤库⽂件的查和链接⼤家好,我已经把CSDN上的博客迁移到了知乎上,欢迎⼤家在知乎关注我的专栏()。希望⼤家可以多多交流,互相学习。
⽬录
CMake链接库的基本套路
在使⽤CMake组织⼯程时,如果我们需要依赖某个库⽂件,需要完成以下步骤:
1. 查库⽂件(find_package命令)
2. 判断是否到库⽂件(XXX_FOUND标记),并包含头⽂件(include_directories命令)
3. 链接库⽂件到⽬标(target_link_libraries命令)
因此,库⽂件、头⽂件的名字(⼤⼩写)我们就要清楚的写明,不要混淆。我常⽤的库如OpenCV, catkin, Boost, Eigen, glog, gtest等,其⽤法如下。常见的名字有:name_INCLUDE_DIRS, name_INCLUDE_DIR,
NAME_INCLUDE_DIRS, NAME_INCLUDE_DIR; name_LIBS, NAME_LIBS, name_LIBRARIES, NAME_LIBRARIES等。OpenCV
#查OpenCV是否安装
find_package(OpenCV REQUIRED core highgui imgproc imgcodecs)
if (OPENCV_FOUND)
message(STATUS "到OpenCV:\"${OpenCV_INCLUDE_DIRS}\",ENABLE_OPENCV宏已打开")
message(STATUS "到OpenCV:\"${OpenCV_LIBS}\"")
include_directories(${OpenCV_INCLUDE_DIRS})
add_definitions(-DENABLE_OPENCV)
list(APPEND LINK_LIB_LIST ${OpenCV_LIBS})
endif (OPENCV_FOUND)
Boost
#查Boost是否安装
find_package(Boost REQUIRED COMPONENTS
regex
graph
chrono
thread
system
filesystem
serialization)
if (Boost_FOUND)
message(STATUS "到Boost:\"${Boost_INCLUDE_DIRS}\",ENABLE_BOOST宏已打开")
message(STATUS "到Boost:\"${Boost_LIBRARIES}\"")
include_directories(${Boost_INCLUDE_DIRS})
add_definitions(-DENABLE_BOOST)
list(APPEND LINK_LIB_LIST ${Boost_LIBRARIES})
endif (Boost_FOUND)
ROS catkin
#查catkin是否安装
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
tf
)
if (catkin_FOUND)
message(STATUS "到catkin:\"${catkin_INCLUDE_DIRS}\",ENABLE_CATKIN宏已打开")
message(STATUS "到catkin:\"${catkin_LIBRARIES}\"")
include_directories(${catkin_INCLUDE_DIRS})
add_definitions(-DENABLE_CATKIN)
list(APPEND LINK_LIB_LIST ${catkin_LIBRARIES})
endif (catkin_FOUND)
Eigen
Eigen⽐较特殊, Eigen采⽤源码的⽅式提供给⽤户使⽤,在使⽤时只需要包含Eigen的头⽂件即可进⾏使⽤。之所以采⽤这种⽅式,是因为Eigen采⽤模板⽅式实现,由于模板函数不⽀持分离编译,所以只能提供源码⽽不是动态库的⽅式供⽤户使⽤。Eigen的默认安装路径是/usr/local/include/eigen3/Eigen,安装后需要将Eigen⽂件夹移动到/usr/local/include/下,可以执⾏如下语句,请。
sudo cp -r /usr/local/include/eigen3/Eigen /usr/local/include
#查Eigen3是否安装
find_package(Eigen3 REQUIRED)
if (EIGEN3_FOUND)
message(STATUS "到Eigen3:\"${EIGEN3_INCLUDE_DIR}\",ENABLE_EIGEN3宏已打开")
include_directories(${EIGEN3_INCLUDE_DIR})
add_definitions(-DENABLE_EIGEN3)
#    Eigen采⽤源码的⽅式提供给⽤户使⽤,在使⽤时只需要包含Eigen的头⽂件即可进⾏使⽤。
#    之所以采⽤这种⽅式,是因为Eigen采⽤模板⽅式实现,由于模板函数不⽀持分离编译,所以只能提供源码⽽不是动态库的⽅式供⽤户使⽤。
#    list(APPEND LINK_LIB_LIST ${EIGEN3_LIBRARIES})
endif (EIGEN3_FOUND)
glog
先安装好glog。安装后,⽆需在中 find_package() 和 include_directories(),直接 target_link_libraries()。记得在使⽤glog的⽂件中包含头⽂件。
#include <glog/logging.h>
target_link_libraries(${PROJECT_NAME} glog)
gtest
先安装好gtest。安装后,⽆需在中 find_package() 和 include_directories(),直接 target_link_libraries()。
FILE(GLOB_RECURSE TEST_SRC "${CMAKE_SOURCE_DIR}/test/*.cpp" "${CMAKE_SOURCE_DIR}/test/*.h")
system的头文件
add_executable(${PROJECT_NAME}_test ${TEST_SRC})
target_link_libraries(${PROJECT_NAME}_test gtest ${LINK_LIB_LIST} glog)
⼀般测试⽂件夹test会放在⼯程内和 src、include ⽂件夹同级别的位置,在test⽂件夹内存放不同的测试⽂件test cases,并包含头⽂件。具体的请参考gtest的tutorials。
#include "gtest/gtest.h"
另外,要记得通过main() 运⾏所有的test cases。如下:
#include "gtest/gtest.h"
int main(int argc,char **argv){
testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
CMake 输出信息
执⾏Reload CMake Project后的输出信息如下(不同的机器不同的安装路径输出会不⼀样):
-
- 到OpenCV:"/opt/ros/kinetic/include/opencv-3.3.1;/opt/ros/kinetic/include/opencv-3.3.1/opencv",ENABLE_OPENCV宏已打开
-- 到OpenCV:"opencv_core;opencv_highgui;opencv_imgproc;opencv_imgcodecs"
-- Boost version: 1.58.0
-- Found the following Boost libraries:
--  regex
--  graph
--  chrono
--  thread
--  system
--  filesystem
--  serialization
--  date_time
--  atomic
-- 到Boost:"/usr/include",ENABLE_BOOST宏已打开
-- 到Boost:"/usr/lib/x86_64-linux-gnu/libboost_regex.so;/usr/lib/x86_64-linux-gnu/libboost_graph.so;/usr/lib/x86_64-linux-gnu/libboost_chrono.so;/usr/lib/x86_64 -- .......省略........
-- 到catkin:"/home/gjs/catkin_ws/devel/include;/home/gjs/catkin_ws/src/geometry/tf/include;/opt/ros/kinetic/include;/opt/ros/kinetic/share/xmlrpcpp/cmake/../../../in -- 到catkin:"/opt/ros/kinetic/lib/libtf.so;/opt/ros/kinetic/lib/libtf2_ros.so;/opt/ros/kinetic/lib/libactionlib.so;/opt/ros/kinetic/lib/libmessage_filters.so;/opt/ros/kinetic/lib/lib -- 到Eigen3:"/usr/include/eigen3",ENABLE_EIGEN3宏已打开
对于⾃定义的库,库⽂件和头⽂件的名称可能有所区别。