ROS2中的CmakeLists——从编译开始才能理解

ROS中的CMakeLists——从编译开始才能理解

写在前面

最近在网上找各种帖子学习CMakeLists,但是都感觉学得不得劲,所以写下此篇文章,但是也是刚学习,难免会有不正确的地方,仅以此作为笔记记录。

编译过程

无论我们使用的是Windows系统还是Ubuntu系统,我们平时所需要写的代码都在对应的IDE中点击运行即可生成结果,导致现在很多人对C++的编译过程只是停留在背诵的内容上(我就深受其害),因此对CMakeLists的理解必定不到位,所以我觉得先从编译过程开始了解更有助于后面理解。
先贴一张网上到处都有的流程图:
在这里插入图片描述这张图其实就很清楚地说明了问题:首先我们编写的代码是.c或者.cpp文件格式的,这是我们的源代码,进行编译的第一步就是进行预处理,当然这张图没有注明,这也是编译过程中的一部分。

预处理

所谓预处理就是处理一些#内容,比如include命令,define命令,去除一些注释,以及一些特殊符号。这也就是为什么大家在C语言课程中会听到老师说#后面的字符一般不是关键字,而称之为预处理指令,同时也是其不加#报错的原因。预处理完之后的“源代码”仍然是.cpp和.c文件,但是其内容全部变成了没有宏定义,没有特殊符号,没有注释,变成了一个“程序可读性几乎为零”的代码。

编译

然后就是进行编译了,编译就是将经过预处理的代码文件进行分析,这一步就会检查有没有语法问题了,这也是为什么一般大佬在检查程序语法的时候会选择编译而不是运行。检查无误后,就会将其代码翻译成对应的汇编代码,当然这里面还有关于代码优化的问题,这里跳过。汇编代码相对来说比较低级(可不是不好的意思),它接近于机器语言,但是人类可读。我用GPT写了一个输出“hello world”的程序:

section .data
    hello db 'Hello, World!', 0x0A  ; 定义一个字符串,并以换行符结尾

section .text
    global _start

_start:
    ; 写操作,系统调用号为 1 (sys_write)
    mov eax, 4        ; 系统调用号 4: sys_write
    mov ebx, 1        ; 文件描述符 1: 标准输出 (stdout)
    mov ecx, hello    ; 将要输出的字符串地址
    mov edx, 14       ; 字符串长度 (13 个字符 + 1 个换行符)
    int 0x80          ; 调用内核

    ; 退出程序,系统调用号为 1 (sys_exit)
    mov eax, 1        ; 系统调用号 1: sys_exit
    xor ebx, ebx      ; 退出状态 0
    int 0x80          ; 调用内核

不客气地说我能看懂int,以及……没有以及。

汇编

刚才说到编译后的代码就是汇编代码,汇编代码进入汇编器后,就成了目标代码,目标代码那就是传说中的机器指令编码了,是二进制格式文件,属于极其ZB的存在了,我也用GPT写了一个和上面对应的:

hello.o:     file format elf32-i386

Disassembly of section .text:

00000000 <_start>:
   0:	b8 04 00 00 00       	mov    $0x4,%eax
   5:	bb 01 00 00 00       	mov    $0x1,%ebx
   a:	b9 00 00 00 00       	mov    $0x0,%ecx
   f:	ba 0e 00 00 00       	mov    $0xe,%edx
  14:	cd 80                	int    $0x80
  16:	b8 01 00 00 00       	mov    $0x1,%eax
  1b:	31 db                	xor    %ebx,%ebx
  1d:	cd 80                	int    $0x80

这就是属于机器可读的代码了,可以称之为机器语言。

链接

那么问题来了,都机器可读了,为啥.o文件不是可执行程序?我们在写C++程序的时候肯定会不可避免的调用其他库,另外一般一个稍微大一点的程序也不会只有一个.cpp文件,等各种情况,通过上面的汇编我们将一个个代码翻译成了机器语言,但是,各个源文件之间还相互独立,符号引用和外部依赖还没解决。或者换个表达方式——报错:“未解析的符号和外部依赖”,(听懂掌声,我就不信学C++的不知道这个)。因此这就需要最后一步建立这些文件间的关系——链接。
链接也分为两种,静态链接和动态链接,首先声明,二者没有高级低级之分,只有在不同情况下的实用性。两种方式都是处理程序代码和库代码之间的关系。

静态链接

静态链接就是直接把库文件内容全盘粘贴上去,举个例子,我想实现一个C++的加法程序,相加函数太难不会写,直接找到网上有的函数直接一手C+V,这不是抄袭,这是静态链接!这样有啥好处呢?他不依赖库文件,库文件不管怎么动都和我没关系,就像这个代码是我自己写的一样。缺点就是不好维护,假如我写了100个加法程序,我突然意识到那个函数有个地方写错了,我就得改100次,另外,每个程序都有他自己的静态链接,全是拷贝的文件,因此他占用的内存也更大。

动态链接

所谓动态链接就是不同程序共享相同的代码段,我印象嘎嘎深。以前课题组有一个C#程序,需要我进行一定的维护,有一次我电脑重装系统了,因为是我自己装的,所以就没装Office,Office有一个动态库叫Mgd.dll(也可能是叫其他名字),好巧不巧,这个程序用到了Office,然后我运行一直报错找不到这个dll,最后我还是翻代码才弄清楚了。上面Office和C#程序都用到了这个dll(当然Ubuntu里面的动态链接库不叫dll,叫.so),可以这样理解,电脑里面只有一个这样子的文件,然后两个程序在文件中包含了这个库的注册信息,当调用的时候拿着信息满盘的找他,找到了即调用成功。因此,哪怕我写100个程序,我也只需要一个库,每个程序只需要留一段他的注册信息即可,这样便节省了大量空间,同时维护也只需要修改库即可,无需变动各个程序。当然损耗的就是性能,毕竟要拿着门牌号去找。

经过链接器之后,得到的程序就是我们最后需要的可执行程序了,也就是windows下的.exe,ubuntu下的话未必会有后缀或固定后缀。

以上就是一个C++源码程序编译的整个过程,不过解释型的语言例如python的运行流程一般情况下就会有很大不同。

总结

这次写了很多,但感觉质量可能不高,里面可能会有很多表达不够严谨甚至表达不正确的地方。

ROS2CMakeLists.txt是用来构建和编译ROS2软件包的配置文件。它包含了一系列指令和参数,用于指导构建系统进行编译和链接操作。根据引用\[1\]的示例,可以看到CMakeLists.txt文件首先指定了所需的CMake的最低版本,然后定义了项目名称为nav2_costmap_2d。引用\[2\]的代码展示了在CMakeLists.txt使用find_package命令来查找所需的依赖包,例如roscpp、rospy、std_msgs和message_generation。这些依赖包是在构建过程需要的库和工具。最后,引用\[3\]提到了CMakeLists.txt的重要性,它决定了ROS2软件包的编译是否成功。因此,了解和正确编写CMakeLists.txt对于ROS2编程非常重要。 #### 引用[.reference_title] - *1* [详细分析一个ROS2 CMakeLists.txt文件](https://blog.csdn.net/shoufei403/article/details/125831552)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [ROS cmakelist](https://blog.csdn.net/zacharyzqc/article/details/103130779)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值