GCC Memo

GCC Memo

g++ 备忘录涵盖了从基础编译到静态库、动态库创建与使用的常见操作,适合日常开发查阅。

一、基础编译命令

1. 单文件编译(生成可执行文件)

1
g++ main.cpp -o main  # 编译 main.cpp,输出可执行文件 main(默认输出 a.out)

2. 多文件编译

1
2
3
4
5
6
7
8
9
10
11
# 方式1:直接指定所有源文件

g++ main.cpp func.cpp -o app

# 方式2:先生成目标文件(.o),再链接(适合多文件大型项目)

g++ -c main.cpp # 生成 main.o(-c:只编译不链接)

g++ -c func.cpp # 生成 func.o

g++ main.o func.o -o app # 链接所有 .o 文件,生成可执行文件 app

3. 指定 C++ 标准

1
g++ main.cpp -o main -std=c++11  # 使用 C++11 标准(支持 c++14/c++17/c++20 等)

4. 包含头文件路径(-I)

当头文件不在当前目录时,指定头文件搜索路径:

1
g++ main.cpp -o main -I./include  # 搜索 ./include 目录下的头文件

5. 链接系统库(-l)

链接系统自带的库(如数学库、线程库):

1
2
3
g++ main.cpp -o main -lm    # 链接数学库(math.h,部分系统需显式指定)

g++ main.cpp -o main -lpthread # 链接线程库(pthread.h)

6. 生成调试信息(-g)

用于 GDB 调试:

1
g++ main.cpp -o main -g  # 生成带调试信息的可执行文件

7. 优化编译(-O)

1
2
3
4
5
6
7
8
9
g++ main.cpp -o main -O0  # 无优化(默认,适合调试)

g++ main.cpp -o main -O1 # 基础优化(平衡速度和编译时间)

g++ main.cpp -o main -O2 # 充分优化(推荐发布版本使用)

g++ main.cpp -o main -O3 # 极致优化(可能增加编译时间和可执行文件大小)

g++ main.cpp -o main -Os # 优化代码大小(适合嵌入式场景)

8. 显示警告信息(-Wall/-Wextra)

1
2
3
g++ main.cpp -o main -Wall  # 显示所有常见警告(推荐)

g++ main.cpp -o main -Wextra # 显示额外警告(更严格)

二、静态库(.a)的创建与使用

静态库是目标文件(.o)的集合,编译时会被完整复制到可执行文件中,运行时无需依赖库文件。

ar.a的单词是archive,意思是归档

1. 步骤 1:生成目标文件(.o)

1
2
3
g++ -c func1.cpp -o func1.o

g++ -c func2.cpp -o func2.o

2. 步骤 2:打包为静态库(ar 命令)

1
2
3
4
5
6
7
ar rcs libmylib.a func1.o func2.o

# ar:打包命令;rcs:r=替换旧文件,c=创建新库,s=生成索引(必须加 s,否则链接失败)

# 库文件名格式:libxxx.a(xxx 为库名,链接时用 -lxxx)

ar -t libmylib.a # 可以查看这个库包含的.o文件

3. 步骤 3:使用静态库编译可执行文件

1
2
3
4
5
6
7
8
9
# 方式1:直接指定库文件路径和库名

g++ main.cpp -o app ./libmylib.a

# 方式2:用 -L 指定库路径,-l 指定库名(推荐,更简洁)

g++ main.cpp -o app -L./ -lmylib

# -L./:搜索当前目录下的库文件;-lmylib:链接 libmylib.a(自动补全 lib 和 .a)

三、动态库(.so)的创建与使用

动态库在编译时仅记录引用,运行时才加载,可被多个程序共享,无需打包到可执行文件中。

1. 步骤 1:生成位置无关代码(-fPIC)

位置无关代码(Position-Independent Code)确保库可被加载到内存任意地址:

1
2
3
g++ -c -fPIC func1.cpp -o func1.o

g++ -c -fPIC func2.cpp -o func2.o

2. 步骤 2:生成动态库(-shared)

1
2
3
g++ -shared -o libmylib.so func1.o func2.o

# -shared:指定生成动态库;库文件名格式:libxxx.so(xxx 为库名)

3. 步骤 3:使用动态库编译可执行文件

1
2
3
g++ main.cpp -o app -L./ -lmylib

# 和静态库用法一致:-L 指定库路径,-l 指定库名(自动补全 lib 和 .so)

4. 步骤 4:运行动态库程序(解决 “找不到库” 问题)

动态库默认搜索路径:/lib/usr/lib/usr/local/lib,若库在当前目录,需手动指定路径:

1
2
3
4
5
6
7
8
# 方式1:临时指定 LD_LIBRARY_PATH(当前终端有效)
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
./app # 此时可正常运行

# 方式2:永久添加库路径(推荐)
echo "$PWD" | sudo tee /etc/ld.so.conf.d/mylib.conf # 将当前目录写入配置文件
sudo ldconfig # 更新动态库缓存
./app # 永久有效

四、常用选项速查

选项 功能说明
-o <file> 指定输出文件(可执行文件 / 库文件)
-c 只编译不链接,生成 .o 目标文件
-std=<std> 指定 C++ 标准(如 c++11/c++17)
-I <dir> 添加头文件搜索路径
-L <dir> 添加库文件搜索路径
-l <lib> 链接库(静态库 libxxx.a 或动态库 libxxx.so
-g 生成调试信息(供 GDB 调试)
-O<level> 优化编译(0/1/2/3/s,0 为无优化)
-Wall 显示所有常见警告
-fPIC 生成位置无关代码(动态库必需)
-shared 生成动态库

五、示例:完整流程(动态库)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 编写源文件
echo '#include "func.h"' > main.cpp
echo 'int add(int a, int b) { return a + b; }' > func.cpp
echo 'int add(int a, int b);' > func.h

# 2. 生成动态库
g++ -c -fPIC func.cpp -o func.o
g++ -shared -o libmylib.so func.o

# 3. 编译可执行文件
g++ main.cpp -o app -L./ -lmylib

# 4. 运行
export LD_LIBRARY_PATH=./
./app # 输出:(若 main.cpp 调用 add(1,2),则输出 3)

总结

  • 静态库:编译时打包,运行无依赖,文件较大,适合小项目或无需共享的场景。

  • 动态库:运行时加载,文件小,可共享,适合大型项目或多程序共用的场景。

  • 核心选项:-c(编译)、-shared(动态库)、-fPIC(动态库)、-L/-l(链接库)。