Linux 编译工具全家桶:GCC/G++、Makefile、CMake 从入门到实战
·
一、编译工具链整体认知
1.1 三者定位与关系
- GCC/G++:编译器,负责把
.c/.cpp源码编译成目标文件.o或可执行程序。 - Makefile:构建脚本,通过规则描述依赖关系,调用 GCC/G++ 实现自动化编译、增量构建。
- CMake:构建生成器,跨平台生成 Makefile / IDE 工程文件,屏蔽平台差异,简化大型项目管理。
典型工作流:
plaintext
CMakeLists.txt →(cmake)→ Makefile →(make)→ 调用 GCC/G++ → 可执行文件/库
1.2 为什么要学全这三件套
- 小项目:直接 GCC/G++
- 中型项目:手写 Makefile
- 大型 / 跨平台项目:CMake 生成 Makefile掌握全套工具,才能应对从单机练习到企业级工程的全场景开发。
二、GCC/G++ 基础与常用编译指令
2.1 基本概念
- GCC:GNU Compiler Collection,支持 C、C++、Fortran 等。
- G++:面向 C++ 的编译指令,默认链接
libstdc++,处理.cpp/.cc。
日常习惯:C 用
gcc,C++ 用g++。
2.2 编译四阶段(重要)
C/C++ 程序编译分为四步,理解它才能看懂报错与 Makefile 规则:
| 阶段 | 选项 | 功能 | 典型输入输出 |
|---|---|---|---|
| 预处理 | -E |
展开头文件、宏、去注释 | .c → .i |
| 编译 | -S |
语法检查,生成汇编 | .i → .s |
| 汇编 | -c |
生成二进制目标文件 | .s → .o |
| 链接 | 无 | 合并目标文件与库,生成可执行文件 | .o/.a/.so → bin |
示例分步编译:
bash
运行
g++ -E main.cpp -o main.i
g++ -S main.i -o main.s
g++ -c main.s -o main.o
g++ main.o -o app
2.3 高频编译选项(必须背)
| 选项 | 作用 |
|---|---|
-o file |
指定输出文件名 |
-c |
只编译不链接,生成 .o |
-g |
带调试信息(GDB 必备) |
-Wall |
打开绝大多数警告 |
-Werror |
警告当错误,强制规范 |
-I dir |
增加头文件搜索路径 |
-L dir |
增加库文件搜索路径 |
-lxxx |
链接 libxxx.so 或 libxxx.a |
-std=c++11/c++17 |
指定 C++ 标准 |
-O2 |
生产环境常用优化等级 |
-fPIC -shared |
编译动态库 .so |
2.4 常用编译示例
2.4.1 单文件
bash
运行
g++ main.cpp -o app -Wall -g -std=c++17
2.4.2 多文件
bash
运行
g++ func.cpp main.cpp -o app -I./include
2.4.3 编译动态库与链接
bash
运行
# 编译动态库 libdemo.so
g++ -fPIC -shared demo.cpp -o libdemo.so
# 链接库
g++ main.cpp -o app -L. -ldemo
三、Makefile 自动化构建入门与实战
3.1 Makefile 核心规则
makefile
目标: 依赖
[Tab] 命令
- 目标:要生成的文件(可执行文件、.o、库)
- 依赖:生成目标需要的文件
- 命令:如何生成目标,必须以 Tab 开头
执行:
bash
运行
make # 构建第一个目标
make clean
3.2 常用变量与自动化变量
makefile
CC = g++
CFLAGS = -Wall -g -std=c++17
INCLUDE = -I./include
TARGET = app
SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, %.o, $(SRC))
| 变量 | 含义 |
|---|---|
$@ |
目标文件名 |
$< |
第一个依赖 |
$^ |
所有依赖 |
$? |
比目标更新的依赖 |
3.3 通用 Makefile 模板(推荐直接使用)
makefile
CC := g++
CFLAGS := -Wall -g -O2 -std=c++17
INCLUDE := -I./include
TARGET := app
SRC := $(wildcard src/*.cpp *.cpp)
OBJ := $(patsubst %.cpp, %.o, $(SRC))
$(TARGET): $(OBJ)
$(CC) $^ -o $@
%.o: %.cpp
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE)
.PHONY: clean
clean:
rm -f $(OBJ) $(TARGET)
3.4 Makefile 亮点
- 自动增量编译:只编译修改过的文件
- 适合中小规模 C/C++ 项目
- Linux 环境默认支持,无需额外安装
四、CMake 跨平台构建系统(现代工程主流)
4.1 CMake 解决了什么问题
- 跨平台:一套
CMakeLists.txt生成 Makefile / VS / XCode 工程 - 自动查找依赖库、自动管理头文件 / 库路径
- 语法比 Makefile 更清晰、更易维护
- 大型项目(ROS、OpenCV、PCL、Qt 等)主流构建工具
4.2 CMake 基础语法
4.2.1 最小 CMakeLists.txt
cmake
cmake_minimum_required(VERSION 3.10)
project(demo)
set(CMAKE_CXX_STANDARD 17)
add_executable(app main.cpp)
构建流程(out-of-source 最佳实践):
bash
运行
mkdir build && cd build
cmake ..
make -j8
./app
4.2.2 常用指令
| 指令 | 作用 |
|---|---|
cmake_minimum_required |
指定最低 CMake 版本 |
project |
设定项目名 |
set(CMAKE_CXX_STANDARD 17) |
设置 C++ 版本 |
include_directories |
头文件路径 |
aux_source_directory |
批量搜集源文件 |
add_executable |
生成可执行文件 |
add_library |
生成静态 / 动态库 |
target_link_libraries |
链接库 |
find_package |
自动查找系统库(如 OpenCV、Boost) |
4.3 多目录工程 CMake 模板
工程结构:
plaintext
project/
├── CMakeLists.txt
├── include/
│ ├── func.h
│ └── utils.h
├── src/
│ ├── func.cpp
│ └── utils.cpp
└── main.cpp
顶层 CMakeLists.txt:
cmake
cmake_minimum_required(VERSION 3.10)
project(myapp)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE Debug) # 或 Release
# 头文件路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 搜集源文件
file(GLOB SRC_FILES
${PROJECT_SOURCE_DIR}/src/*.cpp
${PROJECT_SOURCE_DIR}/main.cpp
)
add_executable(app ${SRC_FILES})
构建:
bash
运行
cd build
cmake ..
make -j
4.4 链接第三方库(以 OpenCV 为例)
cmake
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(app main.cpp)
target_link_libraries(app ${OpenCV_LIBS})
五、GCC / Makefile / CMake 如何选型?
| 项目规模 | 推荐方案 | 优点 |
|---|---|---|
| 单文件练习 | GCC/G++ | 简单直接 |
| 小型项目、固定平台 | Makefile | 轻量、无需额外工具 |
| 中大型 / 跨平台 / 第三方库多 | CMake | 工程化强、跨平台、生态好 |
企业主流:CMake + Makefile + GCC/G++。
六、常见问题与避坑指南
6.1 Makefile 常见错误
missing separator:命令必须以 Tab 开头,不能用空格。- undefined reference:
- 缺少
.o - 未链接库(
-lxxx) - 库路径未用
-L指定
- 缺少
- 头文件找不到:使用
-I指定头文件目录。
6.2 CMake 常见问题
- 始终使用外部构建(
mkdir build; cd build; cmake ..) - 找不到库:设置
CMAKE_PREFIX_PATHbash
运行
cmake .. -DCMAKE_PREFIX_PATH=/path/to/opencv - 切换 Release/Debug:
bash
运行
cmake .. -DCMAKE_BUILD_TYPE=Release
6.3 运行时动态库找不到
bash
运行
export LD_LIBRARY_PATH=./
# 或写入 ~/.bashrc
七、总结
- GCC/G++ 是编译执行者,掌握
-c/-g/-Wall/-I/-L/-l等核心选项。 - Makefile 是自动化构建脚本,核心是规则、变量、模式规则、增量编译。
- CMake 是现代跨平台构建工具,通过
CMakeLists.txt生成 Makefile,适合工程化项目。
更多推荐





所有评论(0)