天天看點

CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)

摘自:https://zhuanlan.zhihu.com/p/149191302?utm_source=wechat_session

CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)

CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)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庫

二、大型檔案

CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)CMakeList.txt在大型檔案應用(SLAM常用庫添加依賴項)

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

繼續閱讀