编译代码是程序员每天都要做的事情,每次都是一个简单的 make 指令搞定,但是背后编译的流程到底是怎么样的,还是需要了解一下。下面以 clang 为例子,看看编译过程中都干了啥。
Clang 基本流程
-
预处理:将 .cpp 文件处理为 .i 文件。
- 宏替换
- 头文件展开
- 去除注释
-
编译:编译器将 .i 文件编译为 .s 文件
- 生成汇编文件
-
汇编:汇编器将 .s 文件处理生成 .o 目标文件
- 生成二进制文件
-
链接:链接器将目标文件链接后生成可执行文件
- 生成可执行文件
- 生成可执行文件
代码测试
测试代码:
#include <iostream>
int main(int argc, const char * argv[])
{
// insert code here...
std::cout << "Hello, World!\n";
return 0;
}
-
预处理,执行
clang++ -E main.cpp -o main.i
,该过程会进行头文件展开,宏替换,删除注释。生成文件如下,可以看到,一个很简单的 cpp 文件展开后也有很多行。
-
编译,执行
clang++ -S main.i -o main.s
,会生成汇编文件。
-
汇编,执行
clang++ -c main.s -o main.o
,会生成目标文件。由于是二进制,所以打开是乱码。
-
链接,执行
clang++ main.o -o hello
,会生成可执行文件,运行结果如图。
Clang 常见选项(未校对供参考)
选项 | 描述 | 示例 |
---|---|---|
-o <file> | 指定输出文件的名称。 | clang -o my_program my_program.c |
-c | 将源文件编译为目标文件 (.o),不进行链接。 | clang -c my_program.c |
-E | 仅进行预处理,输出预处理后的源代码。 | clang -E my_program.c |
-S | 将源代码编译为汇编文件 (.s),不进行后续汇编和链接。 | clang -S my_program.c |
-x <language> | 指定源文件的语言类型,例如 `c`、`cpp`、`objcpp`、`objective-c` 等。 | clang -x c++ my_program.cpp |
-v | 显示编译过程中的详细信息,包括调用的命令和路径。 | clang -v my_program.c |
--help | 显示所有可用的命令行选项和参数。 | clang --help |
-O0 | 禁用所有优化。 | clang -O0 -o my_program my_program.c |
-O1 | 启用基本优化,平衡编译速度和优化效果。 | clang -O1 -o my_program my_program.c |
-O2 | 启用更高级的优化,常用于生产环境中的代码。 | clang -O2 -o my_program my_program.c |
-O3 | 启用最大化优化,适用于性能要求极高的代码。 | clang -O3 -o my_program my_program.c |
-Os | 优化代码大小。 | clang -Os -o my_program my_program.c |
-Ofast | 启用最大优化,并禁用某些非性能相关的标准检查。 | clang -Ofast -o my_program my_program.c |
-funroll-loops | 启用循环展开优化,帮助提高某些类型循环的执行效率。 | clang -O3 -funroll-loops -o my_program my_program.c |
-g | 生成调试信息,供调试器使用。 | clang -g -o my_program my_program.c |
-gline-tables-only | 只生成行号表,减少调试信息的大小。 | clang -gline-tables-only -o my_program my_program.c |
-Wall | 启用所有常见的警告。 | clang -Wall -o my_program my_program.c |
-Werror | 将所有警告视为错误,编译时如果有警告则会停止编译。 | clang -Wall -Werror -o my_program my_program.c |
-Wno-<warning-name> | 禁用特定的警告。 | clang -Wall -Wno-unused-variable -o my_program my_program.c |
-Wextra | 启用额外的警告信息,帮助捕获更多潜在问题。 | clang -Wextra -o my_program my_program.c |
-pedantic | 启用更严格的标准遵循检查,警告标准之外的代码。 | clang -pedantic -o my_program my_program.c |
-std=c++11 | 指定 C++ 标准版本为 C++11。 | clang++ -std=c++17 -o my_program my_program.cpp |
-std=c99 | 指定 C 标准版本为 C99。 | clang -std=c99 -o my_program my_program.c |
-ansi | 使用 C89 标准来编译 C 代码,等同于 `-std=c89`。 | clang -ansi -o my_program my_program.c |
-L<dir> | 指定搜索库的目录。 | clang -L/usr/local/lib -o my_program my_program.c -lmylib |
-l<library> | 链接指定的库文件。 | clang -L/usr/local/lib -lmylib -o my_program my_program.c |
-static | 使用静态链接而非动态链接。 | clang -static -o my_program my_program.c |
-shared | 编译成共享库 (动态库)。 | clang -shared -o libmylib.so mylib.c |
关注公众号:C++学习与探索,有惊喜哦~