一、编译工具链整体认知

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/.sobin

示例分步编译:

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.solibxxx.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_PATH

    bash

    运行

    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,适合工程化项目。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐