基本的CMakeLists.txt并不难,主要有生成库、生成执行文件、链接二者以及找库find_package、找头文件include_directories、生成执行文件add_executable、链接库和执行文件target_link_libraries两种方法组成。
但是遇到大型库的编写,目标是生成一个新的大型库myslam,生成执行文件、链接二者。需要提前声明生成执行文件在bin,库在lib中,并把OPenCV、Sophus这些库整合到一个大型的第三方库THIRD_PARTY_LIBS中,供后面的target_link_libraries(myslam ${THIRD_PARTY_LIBS})用。myslam中包括两部分:frame.cpp、mappoint.cpp、map.cpp等+第三方库THIRD_PARTY_LIBS
1)从头开始:(生成库、生成执行文件、链接二者)
CMakeLists.txt
add_library( hello_shared SHARED libHelloSLAM.cpp ) # 生成库
add_executable( useHello useHello.cpp ) #执行文件
target_link_libraries( useHello hello_shared ) # 链接库到执行文件上
1、先生成库文件libhello_shred.so,需要libHelloSLAM.cpp和add_library(hello_shared SHARED libHelloSLAM.cpp)
2、之后要建立头文件libhellSLAM.h告诉如何调用库里的函数,需要把库连接到可执行文件名中 target_link_libraried(useHello hello_shared)
3、主函数useHello.cpp使用头文件
2)利用现成的库:
只需要建立头文件,说明怎么使用即可。
3)大型的库只需修改CMakeList.txt即可(找库、添加头文件、生成执行文件、链接库和执行文件)
头文件也已经建立好了,只需找到库然后加入头文件即可使用
CMakeLists.txt
find_package( OpenCV REQUIRED ) #寻找OpenCV库
include_directories( ${OpenCV_INCLUDE_DIRS}) #添加头文件
add_executable( imageBasics imageBasics.cpp) #添加可执行文件
target_link_libraries( imageBasics ${OpenCV_LIBS} ) #链接OpenCV库
写一个VO库myslam库,这个库需要自己写在include里的.cpp 五大类以及一些第三方库(Eigen、OpenCV、Sophus、G2O)。
之后需要测试程序生成执行文件run_vo,最后链接myslam库的run_vo,跑效果。
add_library( myslam SHARED
frame.cpp mappoint.cpp map.cpp camera.cpp config.cpp
g2o_types.cpp visual_odometry.cpp )
add_executable( run_vo run_vo.cpp )
target_link_libraries( run_vo myslam )
根目录的CMakeList.txt生成新的第三方库THIRD_PARTY_LIBS,需要include所有第三方库头文件,并set路径参数。
很多第三方库文件则被整合成了一个大的THIRD_PARTY_LIBS路径变量,以备后面src中生成myslam用target_link_libraries.
src中的CMakeList.txt中生成myslam库,需要五大类.cpp并链接到上层定义的THIRD_PARTY_LIBS库文件路径。
test中的CMakeList.txt中就是简单的生成可执行文件run_vo,并将源文件链接到我们写的myslam库文件上。
接下来,对这三个CMakeList.txt分别进行介绍:
先来看根目录下的这个CMakeList.txt:
#定义需求版本和工程名称#
cmake_minimum_required(VERSION 2.8)
project (myslam)
#cmake相关的一些设定#
set( CMAKE_CXX_COMPILER "g++" )
set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -march=native -O3" )
#添加cmake_modules到CMAKE_MODULE_PATH路径列表中和
list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
#设定可执行文件与库文件的输出路径bin、lib
set( EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin )
set( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib )
############### 找第三方库和添加头文件 ######################
# Eigen
include_directories( "/usr/include/eigen3" )
# OpenCV
find_package( OpenCV 3.1 REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
# Sophus
find_package( Sophus REQUIRED )
include_directories( ${Sophus_INCLUDE_DIRS} )
# G2O
find_package( G2O REQUIRED )
include_directories( ${G2O_INCLUDE_DIRS} )
#根据库文件路径参数生成第三方库THIRD_PARTY_LIBS
set( THIRD_PARTY_LIBS
${OpenCV_LIBS}
${Sophus_LIBRARIES}
g2o_core g2o_stuff g2o_types_sba
)
############### 自己写的头文件 ######################
include_directories( ${PROJECT_SOURCE_DIR}/include )
#增加子目录#
add_subdirectory( src )
add_subdirectory( test )
然后src中的CMakeList.txt:
#由此一堆生成自己写的一个库文件,名为myslam,这个库是链接在第三方库基础上的。
add_library( myslam SHARED
frame.cpp
mappoint.cpp
map.cpp
camera.cpp
config.cpp
g2o_types.cpp
visual_odometry.cpp
)
# myslam库需要链接上方定义好的第三方库,${THIRD_PARTY_LIBS}路径参数。
target_link_libraries( myslam
${THIRD_PARTY_LIBS}
)
然后test中的CMakeList.txt:
#最终到这里,添加可执行文件
add_executable( run_vo run_vo.cpp )
#可执行文件链接在自己写的库文件myslam上#
target_link_libraries( run_vo myslam )
注解:
1、当前目录名称为 {PROJECT_SOURCE_DIR},路径表达为 ${PROJECT_SOURCE_DIR}
2、list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules )
这句的意思也就很明了了,就是将工程根目录下的cmake_modules文件夹路径,添加到CMAKE_MODULE_PATH路径列表中。
3、add_subdirectory
命令。我们的项目各个子项目都在一个总的项目根目录下,该命令可以将指定的文件夹加到build任务列表中。
cmake_minimum_required(VERSION 2.8.3)
project(lidar_localization)
SET(CMAKE_BUILD_TYPE "Release")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
add_compile_options(-std=c++11)
add_definitions(-std=c++11)
# 加载catkin宏和指定对其他ROS功能包的依赖关系
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
pcl_ros
geometry_msgs
tf
eigen_conversions
)
# 把所有库列为一个集合,后面被target_link_libraries用,避免库名字太长
set(ALL_TARGET_LIBRARIES "")
# cmake包放在一个文件夹下
include(cmake/glog.cmake)
include(cmake/PCL.cmake)
include(cmake/eigen.cmake)
include(cmake/geographic.cmake)
include_directories(include ${catkin_INCLUDE_DIRS})# 指定头文件路径
include(cmake/global_defination.cmake)
# 空的?
catkin_package()
# 所有cpp合并到一个集合(多个node文件编到一个可执行文件中会出错,踢出去)
file(GLOB_RECURSE ALL_SRCS "*.cpp")
file(GLOB_RECURSE NODE_SRCS "src/*_node.cpp")
file(GLOB_RECURSE THIRD_PARTY_SRCS "third_party/*.cpp")
list(REMOVE_ITEM ALL_SRCS ${NODE_SRCS})
list(REMOVE_ITEM ALL_SRCS ${THIRD_PARTY_SRCS})
# 生成可执行文件,链接库
add_executable(test_frame_node src/test_frame_node.cpp ${ALL_SRCS})
target_link_libraries(test_frame_node ${catkin_LIBRARIES} ${ALL_TARGET_LIBRARIES})
find_package
是 cmake 中常见的宏,用于加载 catkin 宏和指定对其他 ROS 功能包的依赖关系。构建此功能包A需要依赖于
roscpp
rospy
std_msgs
pcl_ros
geometry_msgs
tf
eigen_conversions
catkin_package
宏是 catkin 的宏之一,声明要传递给依赖项目的内容,生成 cmake 配置文件。对依赖于功能包A的其他功能包B来需要依赖其他其他。。。
set(ALL_TARGET_LIBRARIES "")
把所有库列为一个集合,后面被target_link_libraries用,避免库名字太长
与之对应的是:
file(GLOB_RECURSE ALL_SRCS "*.cpp")
所有cpp合并到一个集合。
有个类似的表达方式为:将所有.cpp源文件赋值给参数 DIR_SRCS
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
在最后生成可执行文件、链接库的时候,只需要用到ALL_SRCS和ALL_TARGET_LIBRARIES即可。
# 生成可执行文件,链接库
add_executable(test_frame_node src/test_frame_node.cpp ${ALL_SRCS})
target_link_libraries(test_frame_node ${catkin_LIBRARIES} ${ALL_TARGET_LIBRARIES})
# cmake包放在一个文件夹下
include(cmake/glog.cmake)
include(cmake/PCL.cmake)
include(cmake/eigen.cmake)
include(cmake/geographic.cmake)
include_directories(include ${catkin_INCLUDE_DIRS})# 指定头文件路径
include(cmake/global_defination.cmake)v