已使用AI重构结构,笔记会更有条理。

🚀 一、Makefile 是干什么的?

Makefile 是一个“构建脚本”,告诉 make 命令如何一步步编译代码、生成程序、运行测试、清理文件等。


🧱 二、基本结构

一个最小的 Makefile:

main: main.c
    gcc -o main main.c
  • 目标main

  • 依赖main.c

  • 命令gcc -o main main.c注意:必须以Tab开头!

执行:

make        # 自动查找默认目标(第一个),即编译 main

🧩 三、变量(变量就是字符串)

CC = gcc
CFLAGS = -Wall -O2
​
main: main.c
    $(CC) $(CFLAGS) -o main main.c

变量使用:$(变量名) 常见变量:

  • CC:编译器

  • CFLAGS:编译参数

  • LDFLAGS:链接参数


🔁 四、规则(规则 = 目标 + 依赖 + 命令)

目标: 依赖1 依赖2 ...
    命令1
    命令2

每次 make 会检查:

如果 目标文件不存在 或者 依赖文件比目标文件更新,就执行命令。


🎯 五、目标(Target)

常见目标类型:

类型

示例

可执行文件

main

中间文件

main.o

特殊操作

cleantest(不对应文件)

.PHONY:告诉 make 这个目标不是文件名

.PHONY: clean test

🔗 六、依赖(Dependencies)

告诉 make 哪些文件变了就需要重新构建:

main: main.o utils.o

意思是:

如果 main.o 或 utils.o 被修改,就需要重新编译 main。


🔧 七、通配符 & 模板规则

%:通配符规则(模式匹配)

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

表示:任何 .o 文件都由对应 .c 文件编译而来。

  • $<:第一个依赖(如 main.c

  • $@:目标名(如 main.o


🧹 八、clean 目标(清理构建文件)

.PHONY: clean
clean:
    rm -f *.o main

✅ 九、test 目标(运行测试)

.PHONY: test
test: test.o lib.o
    $(CC) -o test test.o lib.o
    ./test

🧪 十、一个完整小例子

CC = gcc
CFLAGS = -Wall -Wextra -O2
OBJS = main.o utils.o
TARGET = main
​
all: $(TARGET)
​
$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $@ $^
​
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
​
.PHONY: clean test
​
clean:
    rm -f *.o $(TARGET)
​
test: test.o utils.o
    $(CC) $(CFLAGS) -o test test.o utils.o
    ./test

🧠 Bonus:常用自动变量

自动变量

含义

$@

目标文件名(例如 main.o

$<

第一个依赖文件(例如 main.c

$^

所有依赖文件列表(去重)


📦 总结口诀

目标: 依赖
    命令(必须Tab开头)
​
变量用 $(XXX),通配符用 %,clean 记得加 .PHONY

CMake

当然可以!下面这份是为你量身定制的 ✨CMake 基础入门笔记✨,对应你提到的核心命令讲解,清晰、实用、能直接上手项目。


📘 CMake 基础入门笔记(含关键命令)

🎯 什么是 CMake?

CMake 是一个跨平台的构建系统生成工具,不是构建器(Make才是),它生成 Makefile、Ninja 等构建脚本。


📦 一、最基本结构

cmake_minimum_required(VERSION 3.10)
project(MyProject)
​
add_executable(main main.c)
  • cmake_minimum_required:指定最低 CMake 版本

  • project:定义项目名(可选加语言)

  • add_executable:添加一个可执行程序


🔨 二、add_executable(添加可执行程序)

add_executable(目标名 源文件1 源文件2 ...)

示例:

add_executable(my_app main.cpp utils.cpp)

🧱 三、add_library(添加库文件)

可以添加静态库或动态库(默认动态)。

# 静态库
add_library(mylib STATIC functions.c)
​
# 动态库
add_library(mylib SHARED functions.c)

用于把库链接到目标(可执行文件或其他库):

target_link_libraries(目标名 私有/公开/接口 库名1 库名2 ...)
  • 简单用法:

    target_link_libraries(my_app mylib)
  • 高级写法(指定链接范围):

    • PRIVATE:仅当前目标用

    • PUBLIC:当前和依赖它的目标都能用

    • INTERFACE:仅依赖者用(本目标不用)

    target_link_libraries(my_app PRIVATE mylib)

📁 五、target_include_directories(添加头文件路径)

告诉编译器去哪找 .h 文件:

target_include_directories(目标名 PRIVATE/INTERFACE/PUBLIC 路径1 路径2 ...)

示例:

target_include_directories(my_app PRIVATE ${CMAKE_SOURCE_DIR}/include)

🗃 六、文件组织建议

project/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   └── functions.cpp
├── include/
│   └── functions.h
└── build/

对应 CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
​
# 设置头文件路径
include_directories(include)
​
# 添加源代码
add_executable(my_app src/main.cpp src/functions.cpp)

或者更现代方式:

add_executable(my_app
  src/main.cpp
  src/functions.cpp
)
​
target_include_directories(my_app PRIVATE include)

🛠 七、构建流程(CLI)

mkdir build
cd build
cmake ..
make

🧹 八、常用小技巧

设置 C++ 标准

set(CMAKE_CXX_STANDARD 17)

设置编译选项

target_compile_options(my_app PRIVATE -Wall -Wextra)

设置输出路径

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

🧪 九、完整案例

cmake_minimum_required(VERSION 3.14)
project(MyApp CXX)
​
set(CMAKE_CXX_STANDARD 17)
​
add_library(mylib STATIC src/functions.cpp)
target_include_directories(mylib PUBLIC include)
​
add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE mylib)

🧠 总结一张表

命令

作用

add_executable

添加可执行程序

add_library

添加静态/动态库

target_link_libraries

链接库

target_include_directories

添加头文件路径

set(CMAKE_...)

设置编译标准、输出路径等

project()

定义项目和语言

cmake_minimum_required

设置最低 CMake 版本


📌 下一步推荐学啥?

  • FetchContent:下载并集成外部项目(如 gtest、fmt)

  • install():安装头文件、库

  • find_package():查找系统库或其他 CMake 项目

  • option():添加可选编译选项


🚀 CMake 高级功能详解笔记


📦 一、FetchContent(自动拉取依赖源码)

用途:从 Git 或 URL 自动下载并构建第三方库(如 gtest、fmt、nlohmann/json)

基本用法:

include(FetchContent)
​
FetchContent_Declare(
  json
  GIT_REPOSITORY https://github.com/nlohmann/json.git
  GIT_TAG v3.11.2
)
​
FetchContent_MakeAvailable(json)
​
target_link_libraries(my_app PRIVATE nlohmann_json::nlohmann_json)

FetchContent_MakeAvailable() 会自动 clone + add_subdirectory。


🧩 二、find_package(集成系统或已安装的库)

find_package(OpenCV REQUIRED)
target_link_libraries(my_app PRIVATE ${OpenCV_LIBS})
target_include_directories(my_app PRIVATE ${OpenCV_INCLUDE_DIRS})

📌 常用于已安装库 + .cmake 支持库(OpenCV、Boost、fmt、gtest 等)


🛠 三、install(安装程序/库/头文件)

install(TARGETS my_app DESTINATION bin)
install(TARGETS mylib DESTINATION lib)
install(DIRECTORY include/ DESTINATION include)

构建后使用:

cmake --install build/

可以配合 CPack 打包为 .tar.gz.deb.msi 等格式。


📦 四、打包(CPack)

在 CMakeLists.txt 末尾添加:

include(CPack)

设置包信息:

set(CPACK_PACKAGE_NAME "MyApp")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_GENERATOR "TGZ;DEB")  # 支持 .tgz, .deb, .rpm, .msi, ...

打包命令:

cpack  # 自动生成安装包

🌍 五、跨平台工具链支持

示例:交叉编译(如 ARM、嵌入式)

创建 toolchain-arm.cmake 文件:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
​
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)

然后构建时使用:

cmake -DCMAKE_TOOLCHAIN_FILE=toolchain-arm.cmake ..

📚 CMake 项目结构推荐(现代)

my_project/
├── CMakeLists.txt
├── include/
│   └── mylib/
│       └── mylib.h
├── src/
│   └── mylib.cpp
├── app/
│   └── main.cpp
├── test/
│   └── test.cpp
└── cmake/
    └── toolchain-arm.cmake

✨ 总结功能速查表

功能

命令

用途

拉取依赖

FetchContent_Declare

下载源码依赖

查找依赖

find_package

查找系统已安装库

安装构件

install()

安装可执行文件、头文件

打包

include(CPack)

自动生成安装包

跨平台

toolchain file

用于交叉编译和平台切换