GCC
是在linux下使用的编译器,Clang
是在mac
上使用的编译器,两者的命令几乎一样.
对于苹果iOS
,使用的编译器是LLVM
,相比于xcode 5
版本前使用的GCC
编译速度提高了3倍。
LLVM
是编译器工具链技术的一个集合,其中的lld
项目,就是内置链接器。LLVM
架构前段为Clang
后端为LLVM
整体的编译器架构就是 LLVM
架构;Clang
大致可以对应到编译器的前端,主要处理一些和具体机器无关的针对语言的分析操作;编译器的优化器和后端部分就是之前提到的 LLVM
后端,即狭义的 LLVM
。
本文运行环境为mac
编译指令
gcc/clang -g -O2 -o test test.c -I... -L... -l...
-g
输出文件中的调试信息
-O
大写的O,对输出文件做指令优化,2表示对文件进行第二个级别的编译优化,更彻底,如果调试的话,则不需要-O
-o
输出文件
-I
指定头文件位置,使用第三方库或者自己创建,
-L
指定lib库位置
-l
意为link,指定使用哪个库,不一定所有都用
编译过程
vim main.c
创建一个main
函数文件,c程序
必须以main函数为入口点
# include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
预处理
gcc -E main.c -o main.i
-E
表示生成预处理文件
具体内容:
- 宏定义指令
#define xxxx
- 条件编译
#if #else #endif...
- 头文件包含指令
#include
将头文件和源代码拷贝到一起 - 特殊符号处理 例如对方法参数中的空格处理
常见问题:
不能在头文件中定义全局变量,因为在头文件中定义全局变量将会使所有包含该头文件的文件存在该段代码,也就是说这些文件将定义一个相同的全局变量,这样将不可避免的造成冲突
首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件。即绑定头文件和宏判定等操作,将头文件和源代码拷贝到一起,以便编译器进行编译
生成汇编代码
gcc -S main.i -o main.s
-S
让编译程序在生成汇编语言输出
具体内容:
编译环节是指对源代码进行语法分析,并优化产生对应的汇编代码的过程,通过词法分析
和语法分析
,将其翻译成等价的中间代码或汇编代码。局部优化、控制流分析和循环优化、数据流的分析和全局优化。
进行词法分析、语法分析和语义分析等,生成*.s的汇编文件
词法分析
编译器中负责将程序分解为一个一个符号的部分,一般称为“词法分析器
”(引用自《C Traps and Pitfalls》)。
词法分析器读入组成源程序的字符流,并且将他们组织成为有意义的词素(lexeme)
序列。对于每个词素,词法分析器产生词法单元token(符号)
作为输出(引用自《编译原理》)。
token
指的是程序的一个基本组成单元—词法单元。token
的作用相当于一个句子中的单词,从某种意义上来说,一个单词无论出现在哪个句子中,它代表的意思都是一样的,是一个表义的基本单元。与此类似,token
就是程序中的一个基本信息单元。词法分析器将源文件的字符流转换为token
的过程被称作词法分析(lexical anaysis)
。
对某一个源文件进行词法分析
,可以使用下面这个命令
clang -fmodules -E -Xclang -dump-tokens main.m
annot_module_include '# include <s' Loc=<main.m:1:1>
int 'int' [StartOfLine] Loc=<main.m:3:1>
identifier 'main' [LeadingSpace] Loc=<main.m:3:5>
l_paren '(' Loc=<main.m:3:9>
r_paren ')' Loc=<main.m:3:10>
l_brace '{' [StartOfLine] Loc=<main.m:4:1>
identifier 'printf' [StartOfLine] [LeadingSpace] Loc=<main.m:5:5>
l_paren '(' Loc=<main.m:5:11>
string_literal '"hello world\n"' Loc=<main.m:5:12>
r_paren ')' Loc=<main.m:5:27>
semi ';' Loc=<main.m:5:28>
return 'return' [StartOfLine] [LeadingSpace] Loc=<main.m:6:5>
numeric_constant '0' [LeadingSpace] Loc=<main.m:6:12>
semi ';' Loc=<main.m:6:13>
r_brace '}' [StartOfLine] Loc=<main.m:7:1>
eof '' Loc=