C++编译的基本知识

1 C++编译的基本知识

对于源代码包,咱们只有编译才能在系统上运行。ios

在一个 C++ 工程中,并非全部代码都会编译成可执行文件。只有带有 main 函数的文件才会生成可执行程序。而另外一些代码,咱们只想把它们打包成一个东西,供其余程序调用。这个东西叫作库。 一个库每每是许多算法、程序的集合,咱们会在以后的练习中,接触到许多库。例如,OpenCV 库提供了许多计算机视觉相关的算法,而 Eigen 库提供了矩阵代数的计算。 Linux下的编译器有gcc、g++,随着源文件的增长,直接用gcc/g++命令的方式显得效率低下,人们开始用Makefile来进行编译。然而随着工程体量的增大,Makefile也不能知足需求,因而便出现了Cmake工具。CMake是对make工具的生成器,是更高层的工具,它简化了编译构建过程,可以管理大型项目,具备良好的扩展性。对于ROS这样大致量的平台来讲,就采用的是CMake,而且ROS对CMake进行了扩展,因而便有了Catkin编译系统。c++

2 使用g++

咱们用编译器 g++ (g++ 是一个 C++ 编译器)把.cpp文件编译成一个可执行文件 。算法

g++ helloSLAM.cpp

刚才这条编译命令把 helloSLAM.cpp 这个文本文件编译成了一个可执行程序。咱们检查当前目录,会发现多了一个 a.out 文件,并且它具备执行权限(终端里颜色不一样)。咱们输入./a.out 便可运行此程序编辑器

3 使用 cmake

3.1 cmake简介

单个C++文件能够用g++来编译成一个可执行文件。可是一个大工程使用 cmake 来管理源代码 。函数

理论上说,任意一个 C++ 程序均可以用 g++ 来编译。但当程序规模愈来愈大时,一个工程可能有许多个文件夹和里边的源文件,这时输入的编译命令将愈来愈长。一般一个小型 c++ 项目含有十几个类,各种间还存在着复杂的依赖关系。 可能原文件中其中一部分要编译成可执行文件,另外一部分编译成库文件。 若是仅靠 g++ 命令,咱们须要输入大量的编译指令,整个编译过程会变得异常繁琐。工具

3.2 cmake使用介绍,与生成可执行文件

在一个 cmake 工程中,咱们会用 cmake 命令生成一个 makefle 文件,而后,用 make命令 ,根据这个 makefle 文件的内容,编译整个工程。 cmake 过程处理了工程文件之间的关系,而 make 过程实际调用了 g++ 来编译程序 。ui

cmake的操做对象其实是CMakeLists.txt 文件,所以须要开发者先编写一个CMakeLists.txt 文件CMakeLists.txt 文件告诉 cmake 咱们要对这个目录下的文件作什么事情。CMakeLists.txt 文件内容须要遵照 cmake 的语法。spa

好比:code

# 声明要求的 cmake 最低版本
cmake_minimum_required( VERSION 2.8 )

# 声明一个 cmake 工程
project( HelloSLAM )
# 添加一个可执行程序
# 语法: add_executable( 自定义程序名 源代码文件 )
add_executable( helloSLAM helloSLAM.cpp )

演示了最基本的工程:指定一个工程名和一个可执行程序(这也是如何使用cmake生成可执行文件的示例)。对象

过程:

在当前目录下 ,首先用cmake对该工程进行分析,再用make指令对工程进行编译。

第一步

cmake .

注意加这个.说明要编译的源文件以及CMakeLists.txt 文件应当都在打当前目录下。

第二步:

make

cmake 会输出一些编译器等信息,而后在当前目录下生成一些中间文件,其中最重要的就是 MakeFile。MakeFile 是一个自动化编译的脚本,能够将它理解成一系统自动生成的编译指令。

效果:

cmake 过程处理了工程文件之间的关系,而 make 过程实际调用了 g++ 来编译程序。虽然这个过程当中多了调用cmake 和 make 的步骤,但咱们对项目的编译管理工做,从输入一串 g++ 命令,变成了维护若干个比较直观的 CMakeLists.txt 文件,这将明显下降维护整个工程的难度。好比,当我想新增一个可执行文件时,只需在 CMakeLists.txt 中添加一行“add_executable”命令便可,然后续的步骤都是不变的。 cmake 会帮咱们解决代码的依赖关系,无需咱们输入一大串 g++ 命令。

删除中间文件:

如今这个过程当中,惟一让咱们不满的是, cmake 生成的中间文件还留在咱们代码文件当中。当咱们想要发布代码时,并不但愿把这些中间文件一同发布出去。这时咱们还需把它们一个个删除,这十分的不便。一种更好的作法是让这些中间文件都放在一个中间目录中,在编译成功后,把这个中间目录删除便可。因此,更常见的编译 cmake 工程的作法就是这样 :

mkdir build
cd build
cmake ..
make

咱们新建了一个中间文件夹“build”,而后进入 build 文件夹,经过 cmake .. 命令,对上一层文件夹,也就是代码所在的文件夹进行编译。这样, cmake 产生的中间文件就会生成在 build 文件夹中,与源代码分开。当咱们发布源代码时,只要把 build 文件夹删掉便可。 下次编译的时候再像这样新建。

3.3 cmake生成库文件

只有带有 main 函数的文件才会生成可执行程序。而另外一些代码,咱们只想把它们打包成一个东西,供其余程序调用。这个东西叫作库。

一个库每每是许多算法、程序的集合(由不含main函数的源文件编译而成),咱们会在以后的练习中,接触到许多库。例如,OpenCV 库提供了许多计算机视觉相关的算法,而 Eigen 库提供了矩阵代数的计算。

3.3.1 使用cmake 生成库

好比对于一个libHelloSLAM.cpp 文件 。这个库提供了一个 printHello 函数,调用此函数将输出一个信息。可是它没有 main函数,这意味着这个库中没有可执行文件。

//这是一个库文件
#include <iostream>
using namespace std;
void printHello()
{
cout<<"Hello SLAM"<<endl;
}

这个库提供了一个 printHello 函数,调用此函数将输出一个信息。可是它没有 main函数,这意味着这个库中没有可执行文件。为了libHelloSLAM.cpp编译成库文件,咱们在 CMakeLists.txt 里加一句:

add_library( hello libHelloSLAM.cpp )

这条命令告诉 cmake,我想把这个文件编译成一个叫作“hello”的库。以后即可以使用 cmake 和make编译整个工程:

cd build
cmake ..
make

这时,在 build 文件夹中会生成一个 libhello.a 文件,这就是咱们获得的库(静态库),以.a 做为后缀名。


在 Linux 中,库文件分红静态库和共享库两种。静态库以.a 做为后缀名,共享库以.so结尾。全部库都是一些函数打包后的集合,差异在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。若是咱们想生成共享库而不是静态库,只需用:

add_library( hello_shared SHARED libHelloSLAM.cpp )

就能够编译成一个共享库。此时获得的文件是 libhello_shared.so 了。

3.3.2 使用库文件

库文件是一个压缩包,里头带有编译好的二进制函数。不过,仅有.a 或.so 库文件的话,咱们并不知道它里头的函数究竟是什么,调用的形式又是什么样的。为了让别人(或者本身)使用这个库,咱们须要提供一个头文件,说明这些库里都有些什么。所以,对于库的使用者, 只要拿到了头文件和库文件,就能够调用这个库了

编写一个库文件对应的头文件:

libHelloSLAM.h

#ifndef LIBHELLOSLAM_H_
#define LIBHELLOSLAM_H_
void printHello();// 对库文件中的函数进行声明,以让别人知道库文件里有什么
#endif

这样,根据这个文件和咱们刚才编译获得的库文件,就可使用这个函数了。下面我
们写一个可执行程序,调用这个简单的函数void printHello()

useHello.cpp

#include "libHelloSLAM.h"
int main( int argc, char** argv )
{
printHello();
return 0;
}

而后,在 CMakeLists.txt 中添加一个可执行程序的生成命令,连接到刚才咱们使用的库上:

add_executable( useHello useHello.cpp ) //编译刚编写的可执行文件
target_link_libraries( useHello hello_shared )//将共享库连接到某个头文件

经过这两句话, useHello 程序就能顺利使用 hello_shared 库中的代码了。

对于他人提供的库,咱们也可用一样的方式对它们进行调用,整合到本身的程序中。

3.4 小结

  1. 首先,程序代码由头文件和源文件组成;
  2. 带有 main 函数的源文件编译成可执行程序,其余的编译成库文件。
  3. 若是可执行程序想调用库文件中的函数,它须要参考该库提供的头文件,以明白调用
    的格式。同时,要把可执行程序连接到库文件上。 (可是根据描述是不须要编译头文件的)

使用g++或者cmake本质是使用文本开发环境,即便用文本编辑器编辑代码,再对编辑好的代码进行编译等生成文件。除此以外,还可使用集成开发环境。

相关文章
相关标签/搜索