关于CMakeLists的基础知识

在使用ROS2框架开发机器人应用时,对各个功能包Cmakelist.txt文件的更改尤为重要。本系列旨在总头开始介绍Cmakelist.txt各条语句的意义和内涵。

Cmake已经是高度集成的构建工具,其作用是在不同开发环境下生成makefile文件,以此来执行make指令,将一系列c++源码编译为可以运行的文件。所以,我们将先介绍c++的编译过程

一、C++的编译过程

由c++源文件(即以.hpp和.cpp结尾的源文件)到可执行文件(在linux系统中默认以.out结尾)分为以下4个过程。

1、预处理:将#define定义的内容添加到代码中,处理#ifndef #endif等标记,完成删除注释等操作

2、编译:把C++代码编译为汇编语言代码

3、汇编:把汇编语言代码编译为二进制机器码

4、链接:将编译完成的二进制代码与诸如标准库等系统组件结合,使之能够运行

 当我们执行如下指令时,编译器已经自动将这四个步骤执行完毕。

g++ mysource.cpp -o myexe.out

mysource.cpp为源文件,myexe.out为编译出的可执行文件。

二、动态链接库和静态链接库

链接这一步会把我们编写的二进制代码与其他组件结合,其他组件包括标准库,也包括他人完成的库文件。譬如,如果在如下的代码中使用matio库

#include <string>
#include "matio.h"

int main(void)
{
    std::string path="/home/test.mat";
    std::string name="value"; 
    //待读取文件的地址和变量名称

    mat_t* p_mat_info;
    p_mat_info=Mat_Open(path.c_str(),MAT_ACC_RDONLY);
    matvar_t* p_mat_var;
    p_mat_var=Mat_VarRead(p_mat_info,name.c_str());
    double* data=(double*)p_mat_var->data;
}

mat_t和matvar_t均为matio库定义的类型,我们自己编写的代码中并不不包含其具体定义和实现。但我们的编写的代码保留了这一份标记,在经历预处理、编译和汇编步骤后,经得到的二进制代码与系统中保存的matio库二进制代码结合,使最终的可执行文件可以利用matio库包含的功能。这便是编译,而其中库的二进制代码,一般被称为库文件

依据链接的形式不同,库文件可以被分为静态链接库动态链接库

1、静态链接库:将所需的二进制代码片段拷贝到源代码编译得到的二进制文件中。

2、动态链接库:将所需的二进制代码的地址拷贝到源代码编译得到的二进制文件中。

两者的关系类似于普通函数和内联函数,按地址传递参数与按值传递参数。可以看出计算机中的概念时密切联系的!

在linux系统中,动态链接库以.so结尾,静态链接库以.a结尾。

在windows系统中,动态链接库以.dll结尾,静态链接库以.lib结尾。

进入linux系统的/lib目录,可以发现非常多的库文件,这些库文件都是系统中各个软件运行所需的必要保障。

lib目录下的.so文件和.a文件

三、make和Makefile的使用

对于简单的项目,比如单个c++文件,使用gcc/g++指令就可以实现由项目源文件到可执行文件的转变。但对于有多个cpp文件,多个hpp文件,使用了多个外部链接库的大项目,使用gcc/g++指令进行编译操作会复杂!

这里有笔者对于使用matio库的介绍:

Ubuntu平台上C语言利用matio库读取mat文件-CSDN博客

gcc test.c /usr/lib/libmatio.a -o name

可以看到,链接操作需要提供外部链接库的地址。如果一个项目使用了数十个,数百个链接库,每次编译就要输入非常长的指令。所以,make工具和makefile文件诞生了。makefile文件记录如何复杂项目的编译方式,make命令将其实现

使用如下命令在ubuntu系统中安装make工具

sudo apt install ubuntu-make

如下博文介绍了make工具的使用方式,本文不再详细介绍:

windows环境安装make命令-CSDN博客

四、cmake和CMakeLists的使用

make工具和makefile文件有一定局限性:其语法相对复杂,平台通用性较差。所以,cmake工具应运而生!

cmake允许开发者编写一种与平台无关(跨平台)的CMakeLists.txt 文件来制定整个工程的编译流程,cmake 工具会解析CMakeLists.txt 文件的语法规则,再根据当前的编译平台,生成本地化的Makefile 和工程文件。

可以使用如下指令在ubuntu上安装cmake:

sudo apt-get install cmake

下面给出最简单的cmake使用示例:

1、创建一个目录,在其中创建一个c++文件,编写一段非常简单的c++代码

#include <iostream>

int main(void)
{
    std::cout<<"Cmake is fun!";
    return 0;
}

2、在相同目录下创建CMakeLists.txt文件并进行编辑

注意,文件需要别严格命名为CMakeLists.txt

project(MYproject)
add_executable(myexecutable mycode.cpp)

project语句规定了项目名称,MYproject即为项目名,可以随意替换。

add_executable语句生成了一个可执行文件,名称为myexecutable,并且是由源文件mycode.cpp生成的。这句话其实等价于在命令行直接输入

g++ mycode.cpp -o myexecutable

也可以使用如下方式在CMakeLists.txt文件中创建变量,实现语句的简化

project(MYproject)
set(SOURCE_CODE mycode.cpp)
add_executable(myexecutable ${SOURCE_CODE})

3、运行cmake工具进行项目构建

在项目所在目录输入以下指令,可以运行cmake工具。cmake工具会自动寻找CMakeLists.txt文件并生成Makefile文件!

cmake .

 如图所示,cmake工具生成了一系列文件,包括最重要的Makefile和其他中间文件。

4、运行make工具生成可执行文件

在项目目录下输入以下指令,便可make工具自动寻找Makefile文件编译项目,得到所需要的可执行文件。

make


5、将编译结果与源文件分离

在某个文件夹里运行cmake指令,默认将生成的文件存在当前文件夹里。但如果cmake指令后面加上参数,可以将处理其他文件夹的源文件。

按照这个思路,我们在项目文件夹里创建src文件夹,build文件夹以及脚本,便可以实现分离!

其中,src文件里包含着源文件和CMakeList.txt,build文件夹为空,buildprocess.txt是我写的脚本,如下所示。

cd build
cmake ../src
make

即可在build文件里得到可执行文件!

五、ros2中的CMakeLists

ros2中,工作空间下包含4个文件夹:

其中,src文件夹储存源文件, build文件夹储存编译后的文件,install文件夹储存中间文件和资源文件。

src文件夹下有若干功能包,对于c++编写的功能包,目录下就包含了CMakeLists,如下所示:

当我们在工作空间下运行如下命令的时候

colcon build

ros2自带的构建工具会自动执行cmake指令和make指令,将源文件转化为可执行文件,并储存在build文件夹对应的位置中!

  • 35
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值