最近在看高翔博士的《SLAM十四讲》,这本书真是太棒啦,以前对于cmake的使用和C++库的理解一直不是很清楚,看完第二讲基本上就搞清楚啦。为了更好地记住知识,做一下输出。
本文使用人员,对于cmake和c++有初步了解,知道cmake、makefile和C++源码之间的关系
1. cmake的使用
1.1 典型cmake工程的文件目录结构
.
├── build
├── CMakeLists.txt
└── main.cpp
[注]在编译之前,build
文件夹为空,编译的内容一般放在build
文件夹下
典型的CMakeLists.txt文件用于告诉cmake要对这个目录下的文件做什么事情。
# 声明要求的cmake最低版本
cmake_minimum_required( VERSION 2.8 )
# 声明一个cmake工程
project( HelloSLAM )
# 添加一个可执行程序
# 语法:add_executable( 程序名 源代码文件 )
add_executable( mian mian.cpp )
[注]main.cpp
内容如下:
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
cout << "hello world" << endl;
return 0;
}
1.2 编译方法
$ cd build //
$ cmake .. // 调用cmake对该工程进行cmake编译,编译到build文件夹下
// cmake会输出一些编译信息,在build文件夹下生成一些中间文件,其中最重要的是MakeFile,即自动化编译脚本
$ make //用make命令对工程进行编译,将会在build文件夹下生成一个可执行文件main
$ ./main //执行可执行程序
借助cmake可以很好地解决各种依赖关系
2. C++库的使用
在一个c++工程中,并不是所有代码都会编译程可执行文件。只有带有main函数的文件才会生成可执行程序。而另一些代码,将被打包成一个东西,供其他程序调用。
在linux中,库文件分成静态库和共享库两种。静态库以.a
结尾,共享库以.so
结尾。所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本。
[注]这里只谈到共享库
2.1 使用cmake生成共享库
一个共享库的工程文件内容如下:
.
├── build
├── CMakeLists.txt
├── testLib.h //头文件
└── testLib.cpp
testLib.cpp
文件内容如下:
#include <iostream>
using namespace std;
void testLib()
{
cout << "this is a library file" << endl;
return 0;
}
CMakeList.txt
文件内容如下:
# 声明要求的cmake最低版本
cmake_minimum_required( VERSION 2.8 )
# 声明一个cmake工程
project( TestLib )
add_library( testLib SHARED testLib.cpp )
编译过程如1.1
,得到库文件testLib.so
2.2 头文件
库文件是一个压缩包,里面有编译好的二进制函数。为了方便别人使用这个库,需要提供一个头文件,说明库里都有些什么。testLib.h
头文件如下:
#ifndef LIBTESTLIB_H_
#define LIBTESTLIB_H_
// 上面的宏定义是为了防止重复引用这个头文件而引起额重定义错误
// 提示库文件的函数
void testLib(); // 记得分号
2.3 库文件调用
根据头文件和编译得到的库文件,我们可以通过可执行程序来调用这个函数。项目工程如下:
.
├── build
├── CMakeLists.txt
└── useLib.cpp
useLib.cpp
如下
#include “testLib.h” // 引用头文件,使用testLib()函数
int main(int argc, char **argv)
{
testLib();
return 0;
}
CMakeLists.txt
中添加一个可执行程序的生成命令,链接到刚才使用的库上。内容如下如下:
# 声明要求的cmake最低版本
cmake_minimum_required( VERSION 2.8 )
# 声明一个cmake工程
project( UseLib )
target_link_libraries( useLib testLib )
# 添加一个可执行程序
add_executable( useLib useLib.cpp )
# 链接库文件到对应的可执行文件上
target_link_libraries( useLib testLib )
[注]链接对应的库文件到对应的可执行文件时,一定要指定对应的路径,如果库文件不在对应的build
目录下,需要指定目录:target_link_libraries( useLib [PATH]/testLib )