视觉SLAM十四讲【ch2】
2.4.2 Hllo SLAM
调用g++编译器对main.cpp进行编译,g++默认把源文件编译成a.out这个名字的程序。也可以指定文件名。
//编译可执行目标文件
g++ main.cpp -o mySLAM
mySLAM.out
和tmySLAM
有没有区别?编译和执行的时候是一样的吗?试验如下:
因为,一般来说,linux可执行文件没有扩展名。Linux与Windows不同,不是根据扩展名来区分文件类型的。事实上,Linux下的文件不需要扩展名。一切皆文件,包含设备文件、目录文件、普通文件等。要知道是否是可执行文件,一般是通过 ls -l 命令看文件属性中是否包含可执行权限 (x)。
比如下面,mySLAM.out
,mySLAM
均是可执行文件。
整个编译和链接的过程都使用了默认选项,省略了中间步骤。当工程很大时,文件之间的依赖关系,类之间的依赖关系很复杂,gcc或g++命令很多,编译过程繁琐,所以使用cmake
对工程进行编译。
2.4.3 cmake
在一个cmake工程中,会用cmake命令生成一个makefile文件,然后用make命令根据这个makefile文件的内容编译整个工程。这次不适用g++,用cmake。新建一个CMakeLists.txt文件,内容如下:
CMakeLists.txt文件用于告诉cmake要对这个目录下的文件做什么事情。CMakeLists.txt文件的内容要遵守cmake语法。这里演示最基本的工程:指定一个工程名和一个可执行程序。现在在当前目录下调用cmake对该工程进行cmake编译:
//调用cmake对工程进行编译
cmake .
这个cmake过程提示使用了哪种编译器,产生了一些中间文件,最重要的是产生了MakeFile,用MakeFile来编译工程,输入make指令:
make
执行helloSLAM2:
中间文件的处理方法是把这些文件放在一个文件夹build中,cd进入build文件夹中,然后对上层文件进行编译,指令:
cmake ..
接下来进入build文件夹目录,执行make命令,编译工程:
2.4.4 使用库
只有带main函数的文件才会生成可执行程序。而另一些代码,我们只想打包成一个东西,供其他程序调用。这个就是库(Libeary)。例如OpenCV库等。演示如何编写一个库。创建libHelloSLAM.cpp文件。ps:一开始写错扩展名了,用mv命令可以修改文件名,mv命令还可以移动文件。
这个库提供了一个printHello函数,但是没有main函数,库中没有可执行文件。在CMakeLists.txt里加上如下内容:
//告诉cmake,想把这个文件编译成一个叫做“hello”的库
add_library(hello libHelloSLAM.cpp)
这条命令告诉cmake,想把这个文件编译成一个叫做“hello”的库。然后用cmake和make命令编译过程:
//注:该命令用于删除文件夹下所有文件而不删除文件夹
rm -rf *
build文件夹下产生的linhello.a文件就是我们得到的库。Linux中库分为两种,静态库和共享库两种,静态库以 .a 为后缀名,共享库后缀名为 .so ,所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库只有一个副本,更省空间。生成共享库的方法如下:
//
add_library(hello_shared SHARED libHelloSLAM.cpp)
库文件是一个压缩包,里面是编译好的二进制函数,仅有库文件的话我们并不知道里面的函数是什么,怎么调用。为了使用库函数,需要提供头文件,只要拿到了头文件和库文件,就可以调用这个库。libhello头文件:
下面,根据这个头文件和刚才得到的库文件,就可以使用printHello函数了。编写一个useHello.cpp文件来使用一下它。使用方法如下:
在CMakeLists.txt中添加一个可执行程序生成命令(add_executable),链接(target_link_libraries)到刚才使用的库上:
通过这两行语句,useHello程序就能够顺利使用hello库中的代码了。