刚开始学习 Linux C/C++、嵌入式 Linux 或 CMake 工程时,很容易被一堆名字绕晕:gcc、g++、Makefile、make、CMake、Ninja、MSVC、Visual Studio、Xcode。
这些名字看起来都和“编译”有关,但它们并不在同一个层级。有的是编译器,有的是构建工具,有的是工程生成工具,还有的是 IDE。只有先把层级理清,后面看 Makefile、CMakeLists.txt、动态库、静态库时才不会一直卡壳。
1. 先分清 gcc 和 g++
gcc 常用于编译 C 程序,g++ 常用于编译 C++ 程序。更准确地说,GCC 是 GNU Compiler Collection,也就是 GNU 编译器集合。
gcc main.c -o appg++ main.cpp -o app提示:C 程序通常用 gcc,C++ 程序通常用g++。因为g++会自动按照 C++ 规则编译,并链接 C++ 标准库。
2. 一个 C 文件会经历四个阶段
一个 C 文件从源代码到可执行文件,通常会经历预处理、编译、汇编、链接四个阶段。
.c 源文件 ↓ 预处理.i 预处理文件 ↓ 编译.s 汇编文件 ↓ 汇编.o 目标文件 ↓ 链接可执行文件gcc -E main.c -o main.igcc -S main.i -o main.sgcc -c main.s -o main.ogcc main.o -o app平时写的 gcc main.c -o app,其实是 GCC 自动完成了这四个阶段。
3. .c、.h、.o 的关系
.c 或 .cpp 是源文件,通常是真正参与编译的文件。.h 是头文件,通常通过 #include 被包含进源文件中,在预处理阶段展开。
#include "add.h".o 是目标文件,是源文件经过编译和汇编后得到的中间文件。多个 .o 文件可以进一步链接成最终可执行程序。
4. 为什么多文件工程要分步编译
多文件工程如果每次都全量编译,会浪费很多时间。更合理的方式是先把每个源文件编译成目标文件,再链接最终程序。
gcc -c main.c -o main.ogcc -c add.c -o add.ogcc -c sub.c -o sub.ogcc main.o add.o sub.o -o app这样如果只修改了 add.c,理论上只需要重新生成 add.o,然后重新链接最终程序即可。
5. Makefile 不是编译器
Makefile 的作用是描述构建规则:要生成什么目标,这个目标依赖哪些文件,应该用什么命令生成。真正负责编译代码的仍然是 gcc、g++、clang 或 MSVC。
app: main.o add.o gcc main.o add.o -o appmain.o: main.c add.h gcc -c main.c -o main.oadd.o: add.c add.h gcc -c add.c -o add.oclean: rm -f app *.o注意:Makefile 命令前面必须是 Tab,而不是普通空格。
6. Makefile 自动变量怎么记
$@:当前规则的目标文件。 $<:当前规则的第一个依赖文件。 $^:当前规则的所有依赖文件。
app: main.o add.o gcc $^ -o $@%.o: %.c gcc -c $< -o $@7. 静态库和动态库的区别
静态库:Linux 后缀通常是 .a,编译链接时打包进可执行文件。动态库:Linux 后缀通常是 .so,程序运行时加载。Windows 下的 .lib可能是真正的静态库,也可能是 DLL 的导入库。
8. CMake 到底做什么
CMake 是构建系统生成工具。它通常不直接编译代码,而是根据 CMakeLists.txt 生成不同平台需要的构建文件。
CMakeLists.txt ↓ cmakeMakefile / build.ninja / Visual Studio 工程 / Xcode 工程 ↓ make / ninja / MSBuild / xcodebuildgcc / g++ / MSVC / clang ↓可执行文件或库文件cmake_minimum_required(VERSION 3.10)project(MyCppProject)set(CMAKE_CXX_STANDARD 17)add_executable(app src/main.cpp src/add.cpp)target_include_directories(app PRIVATE include)9. MSVC、Ninja、Visual Studio 和 Xcode 不在同一层
MSVC:Windows 下常用的 C/C++ 编译工具链。 Visual Studio:微软的集成开发环境。 Ninja:构建工具,类似 make,读取 build.ninja。Xcode:苹果 macOS/iOS 开发环境。 clang:macOS 和部分 Linux 项目常用编译器。