1. GCC/G++
gcc和g++是GNU Compiler Collection中的编译器,分别用于编译C和C++程序。它们的编译过程主要包括四个步骤:预处理(Pre-Processing)、编译(Compiling)、汇编(Assembling)、链接(Linking)。
1.1 编译过程
- 预处理(Pre-Processing):
- gcc -E hello.c -o hello.i
复制代码 对hello.c文件进行预处理,生成预处理文件hello.i。
作用:扩展宏、包含头文件、处理条件编译、删除注释等。
- 编译(Compiling):
- gcc -S hello.i -o hello.s
复制代码 对预处理文件进行编译,生成汇编文件hello.s。
作用:将高级语言代码转换为汇编语言,便于进一步转换为机器代码。
- 汇编(Assembling):
- gcc -c hello.s -o hello.o
复制代码 对汇编文件进行汇编,生成目标文件hello.o。
作用:将汇编代码转换为机器代码,包含程序的二进制指令,但还未链接库函数或其他目标文件。
- 链接(Linking):对目标文件进行链接,生成可执行文件hello。
作用:生成最终的可执行程序,可以在目标操作体系上运行。
可以一步完成所有过程:大概只生成目标文件:- gcc -c hello.c -o hello.o
复制代码 1.2 GCC基本使用
- 编译单个C文件并生成可执行文件:
- gcc -o outputfile sourcefile.c
复制代码 -o outputfile:指定输出的可执行文件名。
sourcefile.c:要编译的源文件。
- 编译多个C文件并生成可执行文件:
- gcc -o myprogram file1.c file2.c file3.c
复制代码 - 编译并生成目标文件(.o文件):-c:仅编译,生成目标文件(object file)。
- 指定头文件目录:
- gcc -Iinclude -o myprogram src/file1.c src/file2.c
复制代码 -Iinclude:指定包含头文件的目录include。
详细解释:
-I 选项用于指定头文件的搜索目录。这在包含自定义头文件大概头文件不在标准目录时非常有用。
头文件(.h或.hpp文件)通常包含函数声明、宏定义、数据范例、预处理指令等。当编写一个程序时,头文件可以被多个源文件包含,以便共享这些声明和定义。
编译器默认会在一些标准目录中搜索头文件,比如 /usr/include 和 /usr/local/include。假如头文件不在这些默认目录中,编译器就无法找到它们,会报错。
使用 -I 选项可以告诉编译器在指定目录中搜索头文件。假设你的头文件在一个自定义目录中,比如 include 目录,可以使用以下下令:- gcc -Iinclude -o myprogram src/main.c
复制代码 这样编译器就会在 include 目录中找到头文件。以下是一个示例:- // include/myheader.h
- #ifndef MYHEADER_H
- #define MYHEADER_H
- void myFunction();
- #endif
- // src/main.c
- #include "myheader.h"
- #include <stdio.h>
- void myFunction() {
- printf("Hello from myFunction!\n");
- }
- int main() {
- myFunction();
- return 0;
- }
复制代码 编译下令:- gcc -Iinclude -o myprogram src/main.c
复制代码 - 链接目标文件生成可执行文件:
- gcc -o myprogram file1.o file2.o
复制代码 1.3 GCC常用选项
- 编译优化:
-O1、-O2、-O3:差别级别的优化。
-Os:优化生成的代码大小。
- 调试信息:
-g:生成调试信息,用于调试程序。
- 警告信息:
-Wall:启用所有常见的警告。
-Werror:将所有警告视为错误。
1.4 G++使用
g++用于编译C++程序,使用方法与gcc类似:
- 编译单个C++文件并生成可执行文件:
- g++ -o outputfile sourcefile.cpp
复制代码 - 编译多个C++文件并生成可执行文件:
- g++ -o myprogram file1.cpp file2.cpp
复制代码 - 编译并生成目标文件(.o文件):-c:仅编译,生成目标文件(object file)。
- 指定头文件目录:
- g++ -Iinclude -o myprogram src/file1.cpp src/file2.cpp
复制代码 -Iinclude:指定包含头文件的目录include。
- 链接目标文件生成可执行文件:
- g++ -o myprogram file1.o file2.o
复制代码 2.Makefile
Makefile 是用于主动化编译和构建软件项目的工具。在大型项目中,手动编译每个文件非常繁琐,使用 Makefile 可以简化这一过程。Makefile 由一系列规则(rules)组成,每个规则包含目标(target)、依赖(dependencies)和下令(commands)。
2.1 基本结构
一个基本的 Makefile 的规则结构如下:- target: dependencies
- command
复制代码
- target:要生成的文件或目标,可以是可执行文件、目标文件或其他规则。
- dependencies:生成目标所依赖的文件或其他目标。
- command:生成目标所需执行的下令。
2.2 示例
假设有以下项目结构:- project/
- ├── include/
- │ └── myheader.h
- ├── src/
- │ ├── main.c
- │ ├── file1.c
- │ ├── file2.c
- ├── Makefile
复制代码 Makefile 内容如下:- # 指定编译器
- CC = gcc
- # 编译选项
- CFLAGS = -Wall -g -Iinclude
- # 源文件目录
- SRC_DIR = src
- # 所有的源文件
- SRCS = $(wildcard $(SRC_DIR)/*.c)
- # 生成的目标文件
- OBJS = $(SRCS:.c=.o)
- # 生成的可执行文件名
- TARGET = myprogram
- # 默认规则,生成最终的可执行文件
- all: $(TARGET)
- # 生成最终的可执行文件 $(TARGET),依赖所有目标文件 $(OBJS)
- $(TARGET): $(OBJS)
- $(CC) -o $@ $^
- # 生成目标文件的规则
- $(SRC_DIR)/%.o: $(SRC_DIR)/%.c
- $(CC) $(CFLAGS) -c $< -o $@
- # 清理规则
- clean:
- rm -f $(OBJS) $(TARGET)
- # 打印文件列表
- print:
- @echo "Source files: $(SRCS)"
- @echo "Object files: $(OBJS)"
- # 伪目标
- .PHONY: all clean print
复制代码 2.3 变量
- CC:指定编译器,通常为 gcc 或 g++。
- CFLAGS:编译选项,如包含目录(-I)、警告(-Wall)、调试信息(-g)等。
- SRCS:源文件列表,由 wildcard 函数生成。
- OBJS:目标文件列表,由源文件列表通过模式替换生成。
- TARGET:最终生成的可执行文件名。
2.4 规则说明
<ul>all 规则:默认规则,生成目标文件 $(TARGET)。
$(TARGET) 规则:- $(TARGET): $(OBJS)
- $(CC) -o $@ $^
复制代码 生成最终的可执行文件 $(TARGET),依赖所有目标文件 $(OBJS)。
模式规则:- $(SRC_DIR)/%.o: $(SRC_DIR)/%.c
- $(CC) $(CFLAGS) -c $< -o $@
复制代码 通用规则,将 .c 文件编译为 .o 文件。$ |