前言
最近刚开始学习slam,在用高翔的《视觉slam十四讲》,该书第二讲的第8个习题要求将helloSLAM小程序库安装进计算机,并用find_packege调用。我没有任何计算机视觉基础,也没有用过Linux系统,因此写下这个博客当成我的学习记录。本文采用c++语言
Cmake
Cmake是一个用于管理源代码的工具,能高效地编译源代码。主要使用流程如下:
1、新建一个CMakeLists.txt文件并编辑
2、依次使用cmake命令和make命令
编译helloSLAM库
编写源文件
先在当前用户目录
1 2 3 4 5 6 | cd ~ mkdir slam cd slam mkdir ch1 cd ch1 mkdir src |
helloSLAM库的头文件
1 2 3 4 | #ifndef HELLOSLAM_H_ #define HELLOSLAM_H_ int helloSLAMFunc(); #endif |
helloSLAM库的库文件
1 2 3 4 5 6 7 8 | #include<iostream> #include "helloSLAM.h" using namespace std; int main() { cout<<"Damn, I love Slam!" return 0; } |
编写CMakeLists.txt文件
在主工程目录ch1下,新建CMakeLists.txt文件,并写入以下内容
1 2 3 4 5 6 7 8 | # 声明所需的cmake的最低版本为2.8 cmake_minimum_required(VERSION,2.8) # CMAKE工程名helloSLAM project(helloSLAM) # 添加子工程目录 add_subdirectories(src lib) |
接着在src目录下新建CMakeLists.txt文件,并写入一下内容
1 2 3 4 | # 源文件名赋给LIB_SRC 变量 set(LIB_SRC helloSLAM.cpp) # 将库设为共享库 add_librariy(helloSLAM SHARED ${LIB_SRC}) |
到此CMakeLists.txt编写完成,可以看出,除了主工程目录外,每一个需要管理的字母里也需要编写CMakeLists.txt文件,并利用add_subdirectories函数添加到主工程列表中。
add_ subdirectories()`函数的调用格式为
1 | ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL]) |
source_dir 可以指定需要管理的子目录,而binary_dir指定生成编译中间文件和结果的子目录。这两个目录均为相对路径,分别相对于
使用cmake-make命令编译库
一般采用外部编译,将编译中间文件与源码分离。在主目录下新建build文件夹,cd到此文件夹
1 2 3 | cd ~/slam/ch1 mkdir build cd build |
依次运行如下指令
1 2 | cmake .. make |
便可在build/lib文件夹中看到
一般而言,动态库还需要一个版本号,可在src/CMakeLists.txt中添加
1 | SET_TARGET_PROPERTIES(helloSLAM PROPERTIES VERSION 1.2 SOVERSION 1) |
参数VERSION 指的是动态库版本,而SOVERSION 指的是API版本,此处待检验
重新运行cmake-make即可,使用tree命令检查build文件夹,可看到
安装helloSLAM库
需要使用
1 2 3 4 5 | INSTALL(FILES files... DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [RENAME <name>] [OPTIONAL]) |
可在一条语句中同时安装多个文件
而库文件使用工程目标格式安装
1 2 3 4 5 6 7 8 9 | INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] ] [...]) |
其中,RUNTIME 代指可执行文件,LIBRARY 特指共享库,ARCHIVE 特指静态库
本例中安装如下,在lib/CMakeLists.txt添加如下语句,将头文件安装在
头文件
1 2 3 | set(LIB_HEAD helloSLAM.h) INSTALL(FILES ${LIB_HEAD} DESTINATION include/hello/SLAM) |
库文件
1 2 | INSTALL(TARGETS helloSLAM DESTINATION lib) |
为了指定
1 2 | cd ~/slam/ch1/build cmake -DCMAKE_INSTALL_PREFIX=/usr .. |
接着运行cmake-make即可完成编译和安装。
调用helloSLAM库
新建一个文件夹ch0,同时在ch0下新建src、build文件夹(意义同上)
编写cpp文件
在src文件夹中新建useHello.cpp,分别如下
1 2 3 4 5 6 7 8 | //useHello.cpp #include<iostream> #include<helloSLAM.h> int main() { helloSLAMFunc();//调用库函数 return 0; } |
改写CMakeLists.txt文件
主工程下新建CMakeLists.txt文件并编辑
1 2 3 4 5 6 7 8 | # 声明所需的cmake的最低版本为2.8 cmake_minimum_required(VERSION,2.8) # CMAKE工程名USEHELLO project(USEHELLO) # 添加子工程目录 add_subdirectories(src bin) |
在src目录下新建并编辑CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #添加可执行程序 set(EXE_SRC useHello.c) add_executable(useHello ${EXE_SRC}) #目录前缀 set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr") #添加库的头文件目录 include_directories(include/helloSLAM) #添加库文件目录 link_directories(lib) #将可执行文件与库连接起来 target_link_libraries(useHello helloSLAM) |
其中
cd 到build目录下,执行cmake-make即可
利用find_package()查找并调用helloSLAM库
自编库
我们安装好库之后,调用是每次都需要去检查库的位置,这是非常麻烦的,于是我们便可以编写FindhelloSLAM.cmake文件(称为module),来记录库的位置,下次直接读取该文件即可实现对库的路径和名称查找。FindhelloSLAM.cmake的一般放在二级目录cmake文件夹下,本例中为~/slam/ch1/cmake
FindhelloSLAM.cmake文件内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 辅助输出信息 message("now using FindhelloSLAM.cmake find demo9 lib") # 将helloSLAM.h文件路径赋值给HELLOSLAM_INCLUDE_DIR,FIND_PATH可以指定若干个查找路径,查到的第一个赋给HELLOSLAM_INCLUDE_DIR FIND_PATH(HELLOSLAM_INCLUDE_DIR helloSLAM.h /usr/include/demo9/ /usr/local/demo9/include/) # 将libhelloSLAM.so文件路径赋值给HELLOSLAM_LIBRARY,FIND_LIBRARY可以指定若干个查找路径,查到的第一个赋给HELLOSLAM_LIBRARY FIND_LIBRARY(HELLOSLAM_LIBRARY libhelloSLAM.so /usr/local/demo9/lib/) if(HELLOSLAM_INCLUDE_DIR AND HELLOSLAM_LIBRARY ) # 设置变量结果 set(HELLOSLAM_FOUND TRUE) endif(HELLOSLAM_INCLUDE_DIR AND HELLOSLAM_LIBRARY ) |
该文件指定了三个变量的值,以供CMakeLists.txt文件使用,分别是HELLOSLAM_INCLUDE_DIR 、HELLOSLAM_LIBRARY 、HELLOSLAM_FOUND
对应的src/CMakeLists.txt中内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #添加可执行程序 set(EXE_SRC useHello.c) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) find_packages(helloSLAM) if(HELLOSLAM_FOUND) add_executable(useHello ${EXE_SRC}) #添加库的头文件目录 include_directories(HELLOSLAM_INCLUDE_DIR ) #添加库文件目录 link_directories(HELLOSLAM_LIBRARY) #将可执行文件与库连接起来 target_link_libraries(useHello helloSLAM) else() message("Library : helloSLAM Not Found") endif(HELLOSLAM_FOUND) |
非自编库
对比非自编库,一般库的作者会提供Find
此外cmake软件还提供了许多多常用库的module来帮助查找该库使用命令
1 | cmake --help-module-list |
可以查看提供了哪些module
本文参考Cmake实践与踩坑记录