菜鸟科技网

gcc 命令 执行

最简单的编译和链接 (单个 C 文件)

假设你有一个名为 hello.c 的 C 语言源文件:

gcc 命令 执行-图1
(图片来源网络,侵删)

hello.c

#include <stdio.h>
int main() {
    printf("Hello, World!\n");
    return 0;
}

要将其编译成可执行文件,最简单的命令是:

gcc hello.c

执行过程详解:

当你输入这个命令后,gcc 会自动执行以下步骤:

gcc 命令 执行-图2
(图片来源网络,侵删)
  1. 预处理:处理 #include#define 等预处理指令,它会将 stdio.h 的内容展开到 hello.c 中,并生成一个临时文件(hello.i)。
  2. 编译:将预处理后的代码(.i 文件)转换成汇编代码,这步会进行语法分析、词法分析、语义分析等,最终生成一个汇编文件(hello.s)。
  3. 汇编:将汇编代码(.s 文件)转换成机器语言,生成目标文件(Object File,.o 文件)。hello.o,这个文件包含了机器码,但还不能直接运行,因为它可能还缺少其他部分。
  4. 链接:这是最后一步。gcc 会将你的 hello.o 文件与 C 标准库(printf 函数的实现就在里面)以及其他必要的文件链接起来,生成一个最终的可执行文件。

默认生成的文件名:

在 Linux 系统上,gcc 默认会生成一个名为 a.out 的可执行文件。

执行程序:

你可以使用 来运行当前目录下的可执行文件:

gcc 命令 执行-图3
(图片来源网络,侵删)
./a.out

输出:

Hello, World!

指定输出文件名

默认的 a.out 文件名很不直观,我们可以使用 -o 选项来指定输出的可执行文件名。

gcc hello.c -o hello

这个命令告诉 gcc 将编译和链接后的最终结果保存为 hello 文件。

你可以这样运行它:

./hello

输出和之前一样。


分步编译 (推荐用于大型项目)

理解分步编译对于调试大型项目非常重要。

第一步:只编译,不链接

使用 -c 选项,gcc 只会执行到“汇编”步骤,生成 .o 目标文件,而不会进行链接。

gcc -c hello.c -o hello.o

执行后,你会得到一个 hello.o 文件,你可以用 file 命令查看它的类型:

file hello.o

输出会类似这样,表明它是一个可重定位的目标文件:

hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

第二步:链接

当你有了所有目标文件后(比如还有 main.o, utils.o 等),你可以将它们链接成一个可执行文件。

gcc hello.o -o hello

这个命令会链接 hello.o 和所需的 C 库,生成最终的 hello 可执行文件。


常用编译选项

gcc 的强大之处在于其丰富的选项。

选项 全称 描述 示例
-o --output= 指定输出文件名 gcc -o myapp main.c utils.c
-c 只编译,不链接,生成 .o 文件。 gcc -c main.c -o main.o
-I --include-dir= 添加头文件搜索路径,当你把头文件放在非标准目录时使用。 gcc -I /path/to/my/headers main.c
-L --library-path= 添加库文件搜索路径 gcc -L /path/to/my/libs myapp.c -lmath
-l --library= 链接指定的库,注意库名不带 lib 前缀和 .so/.a 后缀。 gcc myapp.c -lm (链接 math 库)
-g 包含调试信息,使用 GDB 调试时必须的选项。 gcc -g main.c -o myapp
-O0, -O1, -O2, -O3 优化级别-O0 不优化(最快编译),-O3 最高优化(最慢编译,性能最好)。-O2 是最常用的平衡点。 gcc -O2 main.c -o myapp
-Wall --warnings=all 开启所有常见警告,强烈推荐始终使用! gcc -Wall main.c -o myapp
-Wextra 开启额外的警告,比 -Wall 更严格。 gcc -Wall -Wextra main.c -o myapp
-std= --standard= 指定 C 语言标准,如 c89, c99, c11, c17 (或 gnu89, gnu99 等)。 gcc -std=c11 main.c -o myapp
-D --define-macro= 在编译时定义宏,相当于在代码中写 #define gcc -DDEBUG=1 main.c -o myapp
-E 只进行预处理,输出到标准输出,通常用于调试预处理过程。 gcc -E hello.c
-S 只进行到编译阶段,生成汇编代码(.s 文件)。 gcc -S hello.c

综合实例

假设你的项目结构如下:

my_project/
├── src/
│   ├── main.c
│   └── utils.c
├── include/
│   └── utils.h
└── Makefile  (稍后介绍)
  • include/utils.h

    #ifndef UTILS_H
    #define UTILS_H
    int add(int a, int b);
    #endif
  • src/utils.c

    #include "utils.h"
    int add(int a, int b) {
        return a + b;
    }
  • src/main.c

    #include <stdio.h>
    #include "../include/utils.h"  // 注意路径
    int main() {
        int result = add(5, 3);
        printf("The result is: %d\n", result);
        return 0;
    }

编译命令:

我们需要:

  1. main.cutils.c 分别生成 .o 文件。
  2. 链接这两个 .o 文件。
# 1. 编译 main.c,指定头文件搜索路径为 include 目录
gcc -c src/main.c -I include -o main.o
# 2. 编译 utils.c
gcc -c src/utils.c -I include -o utils.o
# 3. 链接 main.o 和 utils.o,生成最终可执行文件 app
gcc main.o utils.o -o app
# 4. 运行
./app

输出:

The result is: 8

自动化编译:makeMakefile

手动输入上述命令很繁琐,尤其是在项目文件很多时。make 是一个自动化工具,通过读取 Makefile 文件来管理项目的编译。

下面是为上面项目编写的简单 Makefile

# 定义变量
CC = gcc
CFLAGS = -Wall -Wextra -I include -std=c11
TARGET = app
SRCS = src/main.c src/utils.c
OBJS = $(SRCS:.c=.o)
# 默认目标
all: $(TARGET)
# 链接规则
$(TARGET): $(OBJS)
    $(CC) $(OBJS) -o $(TARGET)
# 隐式规则:如何从 .c 文件生成 .o 文件
# make 内置了这个规则,我们这里只是展示
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
# 清理生成的文件
clean:
    rm -f $(OBJS) $(TARGET)

使用 make

你只需要在项目根目录下运行:

make

make 会自动读取 Makefile,并根据规则执行编译命令,它会输出类似这样的信息:

gcc -Wall -Wextra -I include -std=c11 -c src/main.c -o main.o
gcc -Wall -Wextra -I include -std=c11 -c src/utils.c -o utils.o
gcc main.o utils.o -o app

要清理所有编译产物,运行:

make clean

任务 命令
快速编译单个文件 gcc source.c
指定输出文件名 gcc source.c -o my_program
生成目标文件 (不链接) gcc -c source.c -o source.o
链接目标文件 gcc main.o utils.o -o my_program
开启警告和调试信息 gcc -g -Wall source.c -o my_program
添加头文件/库路径 gcc -I /path/to/headers -L /path/to/libs source.c -lmylib -o my_program
自动化编译 make (需要 Makefile)

掌握 gcc 命令是成为 C/C++ 开发者的必备技能,从 -o, -c, -Wall 开始,逐步学习其他选项,你会发现它非常强大和灵活。

分享:
扫描分享到社交APP
上一篇
下一篇