在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
对于源代码包,我们只有编译才能在系统上运行。 在一个 C++ 工程中,并不是所有代码都会编译成可执行文件。只有带有 main 函数的文件才会生成可执行程序。而另一些代码,我们只想把它们打包成一个东西,供其他程序调用。这个东西叫做库。 一个库往往是许多算法、程序的集合,我们会在之后的练习中,接触到许多库。例如,OpenCV 库提供了许多计算机视觉相关的算法,而 Eigen 库提供了矩阵代数的计算。 Linux下的编译器有gcc、g++,随着源文件的增加,直接用gcc/g++命令的方式显得效率低下,人们开始用Makefile来进行编译。然而随着工程体量的增大,Makefile也不能满足需求,于是便出现了Cmake工具。CMake是对make工具的生成器,是更高层的工具,它简化了编译构建过程,能够管理大型项目,具有良好的扩展性。对于ROS这样大体量的平台来说,就采用的是CMake,并且ROS对CMake进行了扩展,于是便有了Catkin编译系统。 2 使用g++我们用编译器 g++ (g++ 是一个 C++ 编译器)把
刚才这条编译命令把 helloSLAM.cpp 这个文本文件编译成了一个可执行程序。我们检查当前目录,会发现多了一个 a.out 文件,而且它具有执行权限(终端里颜色不同)。我们输入./a.out 即可运行此程序 3 使用 cmake3.1 cmake简介单个C++文件可以用g++来编译成一个可执行文件。但是一个大工程使用 cmake 来管理源代码 。 理论上说,任意一个 C++ 程序都可以用 g++ 来编译。但当程序规模越来越大时,一个工程可能有许多个文件夹和里边的源文件,这时输入的编译命令将越来越长。通常一个小型 c++ 项目含有十几个类,各类间还存在着复杂的依赖关系。 可能原文件中其中一部分要编译成可执行文件,另一部分编译成库文件。 如果仅靠 g++ 命令,我们需要输入大量的编译指令,整个编译过程会变得异常繁琐。 3.2 cmake使用介绍,与生成可执行文件在一个 cmake 工程中,我们会用 cmake 命令生成一个 makefle 文件,然后,用 make命令 ,根据这个 makefle 文件的内容,编译整个工程。 cmake 过程处理了工程文件之间的关系,而 make 过程实际调用了 g++ 来编译程序 。 cmake的操作对象实际上是CMakeLists.txt 文件,因此需要开发者先编写一个CMakeLists.txt 文件CMakeLists.txt 文件告诉 cmake 我们要对这个目录下的文件做什么事情。CMakeLists.txt 文件内容需要遵守 cmake 的语法。 比如:
演示了最基本的工程:指定一个工程名和一个可执行程序(这也是如何使用cmake生成可执行文件的示例)。 过程: 在当前目录下 ,首先用cmake对该工程进行分析,再用make指令对工程进行编译。 第一步
注意加这个 第二步:
cmake 会输出一些编译器等信息,然后在当前目录下生成一些中间文件,其中最重要的就是 MakeFile。MakeFile 是一个自动化编译的脚本,可以将它理解成一系统自动生成的编译指令。 效果: cmake 过程处理了工程文件之间的关系,而 make 过程实际调用了 g++ 来编译程序。虽然这个过程中多了调用cmake 和 make 的步骤,但我们对项目的编译管理工作,从输入一串 g++ 命令,变成了维护若干个比较直观的 CMakeLists.txt 文件,这将明显降低维护整个工程的难度。比如,当我想新增一个可执行文件时,只需在 CMakeLists.txt 中添加一行“add_executable”命令即可,而后续的步骤都是不变的。 cmake 会帮我们解决代码的依赖关系,无需我们输入一大串 g++ 命令。 删除中间文件: 现在这个过程中,唯一让我们不满的是, cmake 生成的中间文件还留在我们代码文件当中。当我们想要发布代码时,并不希望把这些中间文件一同发布出去。这时我们还需把它们一个个删除,这十分的不便。一种更好的做法是让这些中间文件都放在一个中间目录中,在编译成功后,把这个中间目录删除即可。所以,更常见的编译 cmake 工程的做法就是这样 :
我们新建了一个中间文件夹“build”,然后进入 build 文件夹,通过 cmake .. 命令,对上一层文件夹,也就是代码所在的文件夹进行编译。这样, cmake 产生的中间文件就会生成在 build 文件夹中,与源代码分开。当我们发布源代码时,只要把 build 文件夹删掉即可。 下次编译的时候再像这样新建。 3.3 cmake生成库文件只有带有 main 函数的文件才会生成可执行程序。而另一些代码,我们只想把它们打包成一个东西,供其他程序调用。这个东西叫做库。 一个库往往是许多算法、程序的集合(由不含main函数的源文件编译而成),我们会在之后的练习中,接触到许多库。例如,OpenCV 库提供了许多计算机视觉相关的算法,而 Eigen 库提供了矩阵代数的计算。 3.3.1 使用cmake 生成库比如对于一个libHelloSLAM.cpp 文件 。这个库提供了一个 printHello 函数,调用此函数将输出一个信息。但是它没有 main函数,这意味着这个库中没有可执行文件。
这个库提供了一个 printHello 函数,调用此函数将输出一个信息。但是它没有 main函数,这意味着这个库中没有可执行文件。为了
这条命令告诉 cmake,我想把这个文件编译成一个叫做“hello”的库。之后便可以使用 cmake 和make编译整个工程:
这时,在 build 文件夹中会生成一个 libhello.a 文件,这就是我们得到的库(静态库),以.a 作为后缀名。 在 Linux 中,库文件分成静态库和共享库两种。静态库以.a 作为后缀名,共享库以.so结尾。所有库都是一些函数打包后的集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。如果我们想生成共享库而不是静态库,只需用:
就可以编译成一个共享库。此时得到的文件是 libhello_shared.so 了。 3.3.2 使用库文件库文件是一个压缩包,里头带有编译好的二进制函数。不过,仅有.a 或.so 库文件的话,我们并不知道它里头的函数到底是什么,调用的形式又是什么样的。为了让别人(或者自己)使用这个库,我们需要提供一个头文件,说明这些库里都有些什么。因此,对于库的使用者, 只要拿到了头文件和库文件,就可以调用这个库了。 编写一个库文件对应的头文件:
这样,根据这个文件和我们刚才编译得到的库文件,就可以使用这个函数了。下面我
然后,在 CMakeLists.txt 中添加一个可执行程序的生成命令,链接到刚才我们使用的库上:
通过这两句话, useHello 程序就能顺利使用 hello_shared 库中的代码了。 对于他人提供的库,我们也可用同样的方式对它们进行调用,整合到自己的程序中。 3.4 小结
使用g++或者cmake本质是使用文本开发环境,即使用文本编辑器编辑代码,再对编辑好的代码进行编译等生成文件。除此之外,还可以使用集成开发环境。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论