【HarmonyOS 移植】gcc编译过程详解之005
gcc编译过程详解
配套源码在GIT仓库里各个板子的source\02_录制视频时编写的源码\01_gcc_options
里。
1. 程序编译4步骤
我们经常使用“编译”泛指上面的4个步骤之一,甚至有时候会囊括这四个步骤。
2. gcc的使用方法
gcc [选项] 文件名
2.1 gcc使用示例
gcc hello.c // 输出一个名为a.out的可执行程序,然后可以执行./a.out
gcc -o hello hello.c // 输出名为hello的可执行程序,然后可以执行./hello
gcc -o hello hello.c -static // 静态链接
gcc -c -o hello.o hello.c // 先编译(不链接)
gcc -o hello hello.o // 再链接
2.2 gcc常用选项
2.2.1 手工控制编译过程
选项 | 功能 |
---|---|
-v | 查看gcc编译器的版本,显示gcc执行时的详细过程 |
-o <file> | 指定输出文件名为file,这个名称不能跟源文件名同名 |
-E | 只预处理,不会编译、汇编、链接t |
-S | 只编译,不会汇编、链接 |
-c | 编译和汇编,不会链接 |
一个c/c++文件要经过预处理、编译、汇编和链接才能变成可执行文件。
(1)预处理
C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理。
(2)编译
编译就是把C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码。
(3)汇编
汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现为ELF目标文件(OBJ文件)。“反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。
(4)链接
链接就是将上步生成的OBJ文件和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件。
hello.c(预处理)->hello.i(编译)->hello.s(汇编)->hello.o(链接)->hello
详细的每一步命令如下:
gcc -E -o hello.i hello.c
gcc -S -o hello.s hello.i
gcc -c -o hello.o hello.s
gcc -o hello hello.o
上面一连串命令比较麻烦,gcc会对.c文件默认进行预处理操作,使用-c再来指明了编译、汇编,从而得到.o文件,
再将.o文件进行链接,得到可执行应用程序。简化如下:
gcc -c -o hello.o hello.c
gcc -o hello hello.o
2.2.2 使用后缀名决定编译过程
参考《嵌入式Linux应用开发完全手册》
:
- 总结
- 输入文件的后缀名和选项共同决定gcc到底执行那些操作
- 在编译过程中,最后的步骤都是链接
- 除非使用了-E、-S、-c选项
- 或者编译出错阻止了完整的编译过程
2.2.3 指定头文件目录
头文件在哪里?
- 系统目录
-
系统目录在哪?工具链里的某个include目录
-
怎么确定?
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)
-
可以不使用系统include目录吗?可以,编译时指定参数
-nostdinc
-
- 可以自己指定头文件目录
-I <头文件目录>
2.2.4 指定库文件
库文件在哪里?
- 系统目录
-
系统目录在哪?工具链里的某个lib目录
-
怎么确定?
echo 'main(){}'| gcc -E -v - // 它会列出头文件目录、库目录(LIBRARY_PATH)
-
可以不使用系统lib目录吗?可以,编译时指定参数
-nostdlib
-
- 可以自己指定库文件目录
-L <库文件目录>
- 指定库文件
-l <abc> // 链接 libabc.so 或 lib.a
3. 开发板程序编译示例
最后链接时,使用arm-linux-ld而不是使用arm-linux-gcc
- 前者可以完全自己指定所连接的文件
- 后者会链接一些默认的启动文件
4. 参考书籍
《嵌入式Linux应用开发完全手册》中的《3.1 交叉编译工具选项说明》
- 点赞
- 收藏
- 关注作者
评论(0)