本文主要涉及到以下几个话题:
-
嵌入式开发编译过程中用到哪些工具
-
windows下MinGW是个什么ghost
-
在windows上交叉编译liunx软件cmake环境配置
-
你的bat文件是个什么角色
-
一个hello_world两种编法
1. 嵌入式开发编译过程中用到的工具
我们知道从.c/.cpp工程到生成适应于个硬件平台的可执行文件要经历:预编译--编译--汇编--链接
-
预编译:把.c/.cpp 转成.i/.ii。在转换过程中,会把c/cpp中的头文件展开,删掉注释,展开宏定义并删掉#define,保留#pragma等编译器指令等等。笔者理解在这个过程中,即使源文件写错了也不会报错的。
-
编译:把.i/.ii文件转换成.s文件,这个过程中会做词法分析,语法分析,语义分析等。这个时候源代码写错了就会报错了。
-
汇编:汇编就是把.s文件生成.o(windows下.obj)文件等,就是说白了就是把汇编语言转成机器码的过程。
-
链接:把以上生成的各种.o/,或者依赖库,一起“打包”组成一个最终可以执行的文件(或者一个中间文件.a,然后各个.a在继续链接生成可执行文件)。
从上面的过程来看,编译的过程就是把高级语言一步步转换成机器语言,最好整合在一起形成一个完整的可执行文件的过程。
注意:其实步骤3跟步骤4生成的文件格式基本是一样的,步骤4其实就是来“”填补步骤3的缺口项的。
举个例子:
我有两个源文件hello.c和sky_henshuai.c,hello,c里面调用了sky_henshuai.c里面的一个函数 void print_sky_zuishuai(); 其实在第三步他们能够正常的生成,hello.o和sky_henshuai.o两个目标文件。但是hello.o里面他不知道函数void print_sky_zuishuai();的地址在哪里。所以你运行hello.o那肯定会出错。所以这个时候就需要把他俩做链接,填补引用了彼此的空白地址。.o和.a的关系,读者自己去思考下吧。
注意注意注意我们平时点的bat文件其实通过工具调用,运行了以上四个步骤的。其实每个步骤都有自己的工具(这些工具可能通过芯片厂商自己的编译工具集成好了,比如gcc就集成好了预编译器,编译器,汇编器等,通过不同的指令可以调用不用的工具)。这个时候就要从根源处说下GUN(为了减少中英文切换以下会叫做滚项目)这个开源项目了。简单说就是滚项目其实是针对linux操作系统开发的一套工具,这套工具也包括了编译工具gcc(g++与gcc的区别建议百度下看看)。
针对以上四个步骤我们可以用GCC命令在Linux下做编译:
gcc -E hello.c -o hello.i 调用预编译器cpp
gcc -S hello.i -o hello.s 调用编译器ccl
gcc -c hello.s -o hello.o 调用汇编器as
ld -static hello.o “dependency lib”调用链接器ld(这个笔者目前还不知道是否支持通过gcc传参调入)
注意:如果下文没有特殊说明,本文说的编译器是指集成好了所有其他编译工具的编译工具,比如上文说的gcc。
2.windows下MinGW是个什么ghost
通过以上我们知道滚项目是基于linux等操作系统的,它不能支持windows下运行,MinGW就是起了这么个作用,让滚项目中有些编译相关工具(这其中还包括很多目标文件查看工具)在windows下也能运行。通过百度百科的定义可以看出来MinGW带的编译器只能编译出在windows下运行的程序。
如果你们电脑上安装了MinGW包的话,会在bin下面看到很多与编译相关的exe,比如:g++.exe,c++.exe, x86_64-w64-mingw32-g++.exe等.
这些exe非常有用。笔者经常用下面的addr2line.exe来通过elf和地址来定位源代码位置。
通过以上分析可以看出,硬件结构,操作系统等能够决定那种编译器编出来的程序运行在上面,结合我们实际工作,所以我们想想目前这么多芯片厂家他们是否是都有自己的编译器与自己的芯片适配呢?当然可能这些编译器都是基于最初的greenhill等适配出来的。