【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
linux系统里面的编译和windows下面的编译不同,它没有什么特别好用的IDE。一般都需要自己写编译脚本。这项工作在以前可能很麻烦,但是现在一般都被cmake取代了。cmake本身不能直接编译代码,它也是通过脚本生成复杂的makefile,借助于makefile来编译生成可执行文件的。所以说,cmake的本质,其实就是降低我们个人写makefile的难度。我们所要做的,就是写好cmake脚本,剩下来的事情,和之前的make工具并无差别。
1、单一可执行程序
假设我们需要编写一个可执行文件,它的文件名叫helloSLAM.cpp,代码是这样的,
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
std::cout << "Hello, SLAM" << std::endl;
return 0;
}
这个时候需要做的,就是在同级目录下创建一个CMakeLists.txt文件,
cmake_minimum_required(VERSION 2.8)
project(helloSLAM)
add_executable(helloSLAM helloSLAM.cpp)
有了这个cmake脚本,下面可以先创建一个debug目录,cd到debug目录下,输入cmake ..就可以看到这样的打印,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj1/debug$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/feixiaoxing/Desktop/slam/prj1/debug
这个时候,其实cmake已经帮助我们生成好了makefile,直接输入make就可以编译了,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj1/debug$ make
Scanning dependencies of target helloSLAM
[100%] Building CXX object CMakeFiles/helloSLAM.dir/helloSLAM.cpp.o
Linking CXX executable helloSLAM
[100%] Built target helloSLAM
2、生成静态库
生成静态库,其实就是说把软件按照各个模块先分别编译成.a文件。等所有的.a文件都ok之后,下面就可以链接成最终的执行文件。这里,我们对helloSLAM.cpp修改一下,方便生成.a文件,
#include <iostream>
using namespace std;
void printHello()
{
std::cout << "Hello, SLAM" << std::endl;
}
代码和之前相比,其实就是删除了main函数,取而代之的是printHello函数。与此对应的CMakeLists.txt也要发生修改,
cmake_minimum_required(VERSION 2.8)
project(helloSLAM)
add_library(hello helloSLAM.cpp)
同样经过观察,我们发现,CMakeLists.txt中的add_executable已经被add_library代替,那么目标也从生成可执行文件,变成了生成静态库文件。同样mkdir debug & cmake .. & make之后,就会发现这样的打印,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj2/debug$ make
Scanning dependencies of target hello
[100%] Building CXX object CMakeFiles/hello.dir/helloSLAM.cpp.o
Linking CXX static library libhello.a
[100%] Built target hello
3、生成动态库
生成动态库的流程和生成静态库非常相似,所要修改的地方就是CMakeLists.txt这一个文件,
cmake_minimum_required(VERSION 2.8)
project(helloSLAM)
add_library(hello_shared SHARED helloSLAM.cpp)
虽然CMakeLists中的目标还是add_library,但是中间多了一个SHARED关键字。就是这个关键字,我们会发现最终生成的是.so文件,而不是.a文件。和.a文件相比,.so文件不占地方,程序有bug,只要修复一个.so文件即可。这里可以看下mkdir debug & cmake .. & make之后的结果是什么样的,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj3/debug$ make
Scanning dependencies of target hello_shared
[100%] Building CXX object CMakeFiles/hello_shared.dir/helloSLAM.cpp.o
Linking CXX shared library libhello_shared.so
[100%] Built target hello_shared
4、编译带动态库的可执行文件
既然生成了静态库,或者动态库,就要看下怎么把相关的文件链接到最终的可执行文件中去。这里主要有四步。第一步把3中生成的so文件copy到当前目录下;第二步,接着修改helloSLAM.cpp文件,
#include <iostream>
using namespace std;
#include "helloSLAM.h"
int main(int argc, char* argv[])
{
printHello();
return 0;
}
注意,这里多了一个helloSLAM.h文件,所以第三步需要继续添加一个头文件,
#ifndef _HELLO_SLAM_H
#define _HELLO_SLAM_H
void printHello();
#endif
最后一步,就是修改CMakeLists.txt文件,
cmake_minimum_required(VERSION 2.8)
project(helloSLAM)
link_directories("/home/feixiaoxing/Desktop/slam/prj4")
add_executable(helloSLAM helloSLAM.cpp)
target_link_libraries(helloSLAM hello_shared)
和最初的可执行文件相比较,这里多了两个内容。第一,添加了link_directories,也就是告诉编译工具,链接库在哪里可以找到;第二,增加了一个target_link_libraries,它表明最终的可执行文件一定要带上hello_shared这个共享库文件。经过上面的操作之后,就可以看看最终的结果是啥样的了,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4$ mkdir debug
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4$ cd debug/
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4/debug$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/feixiaoxing/Desktop/slam/prj4/debug
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4/debug$ make
Scanning dependencies of target helloSLAM
[100%] Building CXX object CMakeFiles/helloSLAM.dir/helloSLAM.cpp.o
Linking CXX executable helloSLAM
[100%] Built target helloSLAM
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4/debug$ ./helloSLAM
Hello, SLAM
看上去和最初的单文件编译没区别。但是大家要注意下,这里的helloSLAM.cpp没有printHello的实现过程,所以最终helloSLAM可以运行起来,肯定有动态库的功劳。通过输入ldd命令也可以证明这一点,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/slam/prj4/debug$ ldd ./helloSLAM
linux-vdso.so.1 (0x00007ffeedad7000)
libhello_shared.so => /home/feixiaoxing/Desktop/slam/prj4/libhello_shared.so (0x00007fdb9a036000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdb99e38000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdb99c46000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdb99af7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdb9a042000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdb99adc000)