摘自:https://zhuanlan.zhihu.com/p/149191302?utm_source=wechat_session
CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)

曉偉Liu
CSDN無人駕駛部落格ID try_again_later
基本的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庫
二、大型檔案
1、我們的目标是:
寫一個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 )
2、步驟:
根目錄的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任務清單中。
三、解析多傳感器融合的CMakeLists.txt
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})
1、find_package和catkin_package
find_package
是 cmake 中常見的宏,用于加載 catkin 宏和指定對其他 ROS 功能包的依賴關系。建構此功能包A需要依賴于
roscpp
rospy
std_msgs
pcl_ros
geometry_msgs
tf
eigen_conversions
catkin_package
宏是 catkin 的宏之一,聲明要傳遞給依賴項目的内容,生成 cmake 配置檔案。對依賴于功能包A的其他功能包B來需要依賴其他其他。。。
2、set,file
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})
3、.cmake包
# 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
四、SLAM中常用庫的CMakeList.txt寫法(如何添加各種依賴庫)
1.添加Eigen頭檔案
Eigen通過apt-get安裝之後,我們要怎麼使用這個依賴庫呢?Eigen有一點很奇怪,Eigen庫隻有頭檔案,是以我們在CMakeLists.txt中是不需要寫target_link_libraries,因為我們是通過apt安裝的,是以很容易的知道Eigen庫的位置就是在/usr/include/eigen3
#添加頭檔案
include_directories("/usr/include/eigen3")
因為我們已經知道Eigen具體的位置,就不用使用find_package來尋找了,雖然有些粗暴,但是簡單有效。
2.添加Pangolin依賴
Pangolin的安裝也很簡單,功能主要就是做三維的可視化顯示,主要依賴庫是OpenGL,通過apt也很好安裝。
find_package(Pangolin)
include_directories(${Pangolin_INCLUDE_DIRS})
add_executable(project_name filename.cpp)
target_link_libraries(project_name ${Pangolin_LIBRARIES})
3.添加Sophus依賴
Sophus實際上是Eigen庫的擴充子產品,Eigen中雖然有幾何子產品,但是沒有提供李代數的支援,是以Sophus算是一個比較好的李代數庫,安裝參考之前博文。
find_package(Sophus REQUIRED)
include_directories(${Sophus_INCLUDE_DIRS})
add_executable(project_name project_name.cpp)
target_link_libraries(project_name ${Sophus_LIBRARIES})
4.添加OpenCV依賴
OpenCV經常會出現版本不相容的問題,LZ同時安裝了OpenCV2和OpenCV3兩個版本,是以在CMakeLists.txt要指定OpenCV的版本。
#指定OpenCV的版本是3.1
find_package(OpenCV 3.1 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(project_name filename.cpp)
target_link_libraries(project_name ${OpenCV_LIBS})
添加OpenCV要注意一個問題,大小寫!很重要!大小寫!
5.添加PCL依賴
這個點雲庫在SLAM應用中還是蠻重要的,通常情況下好像也都有安裝,安裝很簡單,這裡還是講一下CMakeLists.txt中怎麼寫:
find_package(PCL REQUIRED COMPONENT common io)
include_directories(${PCL_INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS})
target_link_libraries(project_name ${PCL_LIBRARIES})
6.添加Ceres依賴
Ceres是Google出品的一個優化庫,安裝編譯都在LZ之前寫過一個SLAM安裝大全裡都有。因為Ceres不是常用的庫,是以需要添加一個cmake_modules。
#這行代碼就是添加查找Ceres的一個檔案
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
target_link_libraries(project_name ${CERES_LIBRARIES})
7添加G2O的依賴
其實這個也是千篇一律,換湯不換藥。這裡也是要注意幾個問題,第一個,要在cmake_module中假如findG2O的檔案。第二個,注意大小寫問題,還有數字0和字母0,這個還是要注意的。
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
find_package(G2O REQUIRED)
include_directories(${G20_INCLUDE_DIRS})
target_link_libraries(project_name g2o_core g2o_stuff)
編輯于 2020-06-18