分享

cmake快速入门-1

 SLAM之路 2022-04-24

01

cmake是什么

开源的跨平台自动化构建系统,用来管理程序构建,不依赖于特定编译器

安装:ubuntu下,sudo apt install cmake

02

cmake基本布局

~/Project

----------src.cpp

----------CMakeLists.txt

----------build文件夹

03

cmake编译方法

1、 进入build文件夹,cd ~/build

2、 cmake ..(必须两个点表示编译父文件夹);

3、 (sudo) make

会在build文件夹中生成可执行文件;

04

cmake编写命令

CMakeLists.txt最简单结构:

cmake_minimum_required(VERSION 2.8)

声明要求的cmake最低版本;

project(ProjectName)

设置当前项目名,存于变量PROJECT_NAME;

add_definitions(-std = c++11

c++11编译; 也可采用set(CMAKE_CXX_FLAGS “-std=c++11”)

set(CMAKE_BUILD_TYPE Release)

设置编译方式,Release或Debug(gdb调试需设置debug);

#Debug:调试模式,输出调试信息,不做优化,可进行gdb调试;

#Release:发布模式,没有调试信息,全优化;

#RelWithDebInfo:类似Release,但包括调试信息

#MinSizeRel:一种特殊的Release,会特别优化库的大小;

find_package(package  version                    

EXACT/QUIET/REQUIRED)

1、搜索外部库,根据任意一种搜索模式查找到其中定义OpenCV_INCLUDE_DIRS和OpenCV_LIBS 等变量;

2、使用 include_directories和target_link_libraries来访问这两个变量

搜索模式

俩种Module模式和Config模式; 

config

1、搜索XXX_DIR指定路径下的XXXConfig.cmake文件找到XXX库;

2、由XXXConfig.cmake模块赋值XXX_INCLUDE_DIRS和XXX_LIBRARIES

module

1、搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件

2、并执行该文件从而找到XXX库;其中给出XXX_INCLUDE_DIRS和XXX_LIBRARIES

模式选择

1、默认采取Module模式

2、XXX_DIR路径下没有XXXConfig.cmake文件,则会找/usr/local/lib/cmake/XXX/中的XXXConfig.cmake文件;

3、Config模式是一个备选策略,通常库安装时会拷贝一份XXXConfig.cmake;

4、若XXX安装时没有安装到系统目录,则无法找到XXXConfig.cmake,手动设置:

5、set(XXX_DIR

 /home/cxl/projects/OpenCV3.1/build) 添加搜索路径;

version

1、指定查找库的版本号;

2、EXACT要求必须精确匹配,

3、QUIET禁掉没有找到时警告信息;

4、REQUIRED如果没有找到会终止cmake;

注意

find_package找到库时,以下变量会初始化:

#<NAME>_FOUND:显示库是否找到;

#<NAME_INCLUDE_DIRS>  

  <NAME_DIRS>:显示头文件路径;

#<NAME>_LIBRARIES>或

  <NAME>_LIBS:库文件

#<NAME>_DEFINITIONS

include_directories(“dir”)

1、指定头文件搜索路径,编译器查找;

例如需要#include"cv.h",但是这个cv.h的路径是#/usr/local/include/opencv,这时候用include_directories,提供搜索头文件根目录,#即你可以在cmakelists中写上include_directories(/usr/local/include)来让库文件,搜索以/usr/local/include为基础, main函数前写上#include “opencv/cv.h"即可;

2、添加find_package中得到的XXX_INCLUDE_DIRS或XXX_DIRS

add_executable(exec_Name source.cpp)

1、将源代码src.cpp生成可执行文件exec_Name;

2、只有main函数所在cpp可以使用该命令;

add_library(libray library.cpp) 

1、将指定的源文件生成库文件;

2、一个库通常是许多算法、程序的集合,多个cpp生成一个库文件library;

3、ibrary.cpp—>库libray的过程;

这条语句将library.cpp编译成一个叫libray的库,即build文件夹中生成liblibray.a;

4、STATIC:静态库,SHARED:共享库

库分为静态.a和共享库.so,两者差别在于静态库每次被调用都会生成一个副本,共享库则只有一个副本:add_library(libray_shared SHARED libray.cpp)

target_link_libraries(programName library )

1、将可执行文件连接到库上,要用在add_executable之后;

2、自己独立写的头文件,#include导入时候使用双引号;

set(variable value)

1、用变量代替值

2、set(SRC_LST main.cpp other.cpp)

add_subdirector(source_dir)

向当前工程添加存放源文件的子目录,目录可以是绝对路径或相对路径;

if/elseif/endif

1、判断语句,使用和c语言一致

message(mode "message txt")

1、打印输出信息,mode包括FATAL_ERROR/WARNING/STATUS/DEBUG等;

2、FATAL_ERROR:产生 CMake Error,会停止编译系统的构建过程;

3、STATUS:最常用的命令,常用于查看变量值,类似于编程语言中的 DEBUG 级别信息。

"message text"为显示在终端的内容,message(STATUS “Set debugmode”)

list

    list(LENGTH <list><output variable>)
list(GET
<list> <elementindex> [<element index> ...]<output variable>)
list(APPEND
<list><element> [<element> ...])
list(FIND
<list> <value><output variable>)
list(INSERT
<list><element_index> <element> [<element> ...])
list(REMOVE_ITEM
<list> <value>[<value> ...])
list(REMOVE_AT
<list><index> [<index> ...])
list(REMOVE_DUPLICATES
<list>)
list(REVERSE
<list>)
list(SORT
<list>)
LENGTH            返回list的长度
GET              返回list中index的element到value中
APPEND            添加新element到list中
FIND             返回list中element的index,没有找到返回-1
INSERT           将新element插入到list中index的位置
REMOVE_ITEM      从list中删除某个element
REMOVE_AT       从list中删除指定index的element
REMOVE_DUPLICATES       从list中删除重复的element
REVERSE         将list的内容反转
SORT           将list按字母顺序排序

预定义好的指令

1、PROJECT_NAME:项目名称,即project(XXX)一致;

2、PROJECT_SOURCE_DIR:project指令CmakeLists.txt所在文件夹;

3、EXECUTABLE_OUTPUT_PATH:可执行文件输出路径;

4、LIBRARY_BINARY_DIR:默认是build文件夹所在的决定路径

5、CMAKE_SOURCE_DIR:源文件所在的绝对路径

其他指令

更多指令介绍,

参考https:///cmake/help/latest/genindex.html

CMakeLists.txt示例(ORB_SLAM2)

cmake_minimum_required(VERSION 2.8)#要求的cmake最低版本2.8
project(ORB_SLAM2)#工程名字ORB_SLAM2,即变量PROJECT_NAME = "ORB_SLAM2"
IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE Release)ENDIF()#if语句搭配endif使用#set(variable value)
MESSAGE("Build type: " ${CMAKE_BUILD_TYPE})#message(mode "message txt")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 ")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 ")#set(variable value)

# Check C++11 or C++0x support#检查 CXX 编译器是否支持给定的标志#可参考链接:https://blog.csdn.net/zhizhengguan/article/details/115324806#必须先include(CheckCXXCompilerFlag)include(CheckCXXCompilerFlag)CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") add_definitions(-DCOMPILEDWITHC11) message(STATUS "Using flag -std=c++11.")elseif(COMPILER_SUPPORTS_CXX0X) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") add_definitions(-DCOMPILEDWITHC0X) message(STATUS "Using flag -std=c++0x.")else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")endif()
LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)#find_package中module模式在 CMAKE_MODULE_PATH路径中查找FindXXX.CMAKE,#这里追加改 CMAKE_MODULE_PATH所包含的路径,以便搜索特定FindXXX.cmake
find_package(OpenCV 3.0 QUIET)if(NOT OpenCV_FOUND) find_package(OpenCV 2.4.3 QUIET) if(NOT OpenCV_FOUND) message(FATAL_ERROR "OpenCV > 2.4.3 not found.") endif()endif()#先查找Opencv3.0,如果没找到查找opencv2.4.3#if语句和endif()#预定义变量XXX_FOUND,find_package调用后判断该包是否找到;
find_package(Eigen3 3.1.0 REQUIRED)find_package(Pangolin REQUIRED)#搜索EIGEN和PANGOLIN包
include_directories(${PROJECT_SOURCE_DIR}${PROJECT_SOURCE_DIR}/include${EIGEN3_INCLUDE_DIR}${Pangolin_INCLUDE_DIRS})#添加工程源文件目录、EIGEN头文件目录,PANGOLIN头文件目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)#CMAKE_LIBRARY_OUTPUT_DIRECTORYg变量是工程源目录下的lib文件夹
add_library(${PROJECT_NAME} SHAREDsrc/System.ccsrc/Tracking.ccsrc/LocalMapping.ccsrc/LoopClosing.ccsrc/ORBextractor.ccsrc/ORBmatcher.ccsrc/FrameDrawer.ccsrc/Converter.ccsrc/MapPoint.ccsrc/KeyFrame.ccsrc/Map.ccsrc/MapDrawer.ccsrc/Optimizer.ccsrc/PnPsolver.ccsrc/Frame.ccsrc/KeyFrameDatabase.ccsrc/Sim3Solver.ccsrc/Initializer.ccsrc/Viewer.cc)#将以上函数共同生成库PROJECT_NAME
target_link_libraries(${PROJECT_NAME}${OpenCV_LIBS}${EIGEN3_LIBS}${Pangolin_LIBRARIES}${PROJECT_SOURCE_DIR}/Thirdparty/DBoW2/lib/libDBoW2.so${PROJECT_SOURCE_DIR}/Thirdparty/g2o/lib/libg2o.so)#将库PROJECT_NAME所依赖的库链接起来
# 生成可执行文件set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/RGB-D)#设置rgbd对应的可执行文件存放目录
#基于tum数据集的可执行文件,链接库PROJECT_NAMEadd_executable(rgbd_tumExamples/RGB-D/rgbd_tum.cc)target_link_libraries(rgbd_tum ${PROJECT_NAME})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Stereo)#设置双目对应的可执行文件存放目录
#基于kitti数据集的可执行文件,链接k库add_executable(stereo_kittiExamples/Stereo/stereo_kitti.cc)target_link_libraries(stereo_kitti ${PROJECT_NAME})
#基于euroc数据集的可执行文件,链接k库add_executable(stereo_eurocExamples/Stereo/stereo_euroc.cc)target_link_libraries(stereo_euroc ${PROJECT_NAME})

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Monocular)#设置单目对应的可执行文件存放目录
#基于tum数据集的可执行文件,链接库add_executable(mono_tumExamples/Monocular/mono_tum.cc)target_link_libraries(mono_tum ${PROJECT_NAME})
#基于kitti数据集的可执行文件,链接库add_executable(mono_kittiExamples/Monocular/mono_kitti.cc)target_link_libraries(mono_kitti ${PROJECT_NAME})
#基于euroc数据集的可执行文件,链接库add_executable(mono_eurocExamples/Monocular/mono_euroc.cc)target_link_libraries(mono_euroc ${PROJECT_NAME})

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多