gcc编译过程
gcc命令其实依次执行了四步操作:
1、预处理(Preprocessing):将所有的.c 、.cpp文件处理为.i文件,
2、编译(Compilation):将所有的.i文件编译为.S文件
3、汇编(Assemble):将所有的.S文件汇编为.o文件
4、链接(Linking):将所有的.o文件链接为一个可执行文件
如果把汇编这一步隐藏掉,就有如下流程:
(1)预处理
C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。
预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理。
预处理不处理语法错误,只是会执行预处理指令(包含头文件,宏定义,预处理条件开关)。比如,源文件中少了个分号之类的,预处理不会报错,编译的时候才会报错。
(2)编译
编译就是把C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码。编译的时候编译器会检查语法错误。
(3)汇编
汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现为ELF目标文件(OBJ文件)。“反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。
(4)链接
链接就是将上步生成的OBJ文件和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件。
gcc常用命令
选项 | 功能 |
---|---|
--help | 查看所有命令选项 |
-v | 查看gcc编译器的版本,显示gcc执行时的详细过程 |
-o | 指定输出文件名为file,这个名称不能跟源文件名同名 |
-E | 只预处理,不会编译、汇编、链接t |
-S | 只编译,不会汇编、链接 |
-c | 编译和汇编,不会链接 |
-pass-exit-codes
:从一个阶段以最高错误代码退出。
--target-help
:显示特定于目标的命令行选项。
--help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]
:显示特定类型的命令行选项(使用 -v --help
显示子进程的命令行选项)。
-dumpspecs
:显示所有内置规范字符串。
-dumpversion
:显示编译器的版本。
-dumpmachine
:显示编译器的目标处理器。
-print-search-dirs
:显示编译器搜索路径中的目录。
-print-libgcc-file-name
:显示编译器配套库的名称。
-print-file-name=<lib>
:显示库 <lib>
的完整路径。
-print-prog-name=<prog>
:显示编译器组件 <prog>
的完整路径。
-print-multiarch
:显示目标的规范化 GNU 三元组,用作库路径中的一个组件。
-print-multi-directory
:显示 libgcc 版本的根目录。
-print-multi-lib
:显示命令行选项和多个库搜索目录之间的映射。
-print-multi-os-directory
:显示操作系统库的相对路径。
-print-sysroot
:显示目标库目录。
-print-sysroot-headers-suffix
:显示用于查找标题的 sysroot 后缀。
-Wa,<options>
:将逗号分隔的 <options>
传递给汇编器(assembler)。
-Wp,<options>
:将逗号分隔的 <options>
传递给预处理器(preprocessor)。
-Wl,<options>
:将逗号分隔的 <options>
传递给链接器(linker)。
-Xassembler <arg>
:将 <arg>
传递给汇编器(assembler)。
-Xpreprocessor <arg>
:将 <arg>
传递给预处理器(preprocessor)。
-Xlinker <arg>
:将 <arg>
传递给链接器(linker)。
-save-temps
:不用删除中间文件。
-save-temps=<arg>
:不用删除指定的中间文件。
-no-canonical-prefixes
:在构建其他 gcc 组件的相对前缀时,不要规范化路径。
-pipe
:使用管道而不是中间文件。
-time
:为每个子流程的执行计时。
-specs=<file>
:使用 <file>
的内容覆盖内置规范。
-std=<standard>
:假设输入源为 <standard>
。
--sysroot=<directory>
:使用 <directory>
作为头文件和库的根目录。
-B <directory>
:将 <directory>
添加到编译器的搜索路径。
-v
:显示编译器调用的程序。
-###
:与 -v
类似,但引用的选项和命令不执行。
-E
:仅执行预处理(不要编译、汇编或链接)。
-S
:只编译(不汇编或链接)。
-c
:编译和汇编,但不链接。
-o <file>
:指定输出文件。
-pie
:创建一个动态链接、位置无关的可执行文件。
-I
:指定头文件的包含路径。
-L
:指定链接库的包含路径。
-shared
:创建共享库/动态库。
-static
:使用静态链接。
--help
:显示帮助信息。
--version
:显示编译器版本信息。
参考