构建系统:Makefile 与 CMake
一、Makefile 基础
1. 最小 Makefile
hello: hello.c
gcc -o hello hello.c
注意:命令前必须是 TAB,不能用空格。
2. 多文件 Makefile
CC = gcc
CFLAGS = -O2 -Wall -g
LDFLAGS =
SRCS = main.c foo.c bar.c
OBJS = $(SRCS:.c=.o)
TARGET = app
.PHONY: all clean install
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) $(TARGET)
install: $(TARGET)
install -m 0755 $(TARGET) /usr/local/bin
3. 自动变量
$@ 目标
$< 第一个依赖
$^ 所有依赖
$* 通配符匹配的部分
$(@D) 目标目录
$(@F) 目标文件名
4. 隐含规则
Makefile 内置:
- %.o: %.c → $(CC) $(CFLAGS) -c -o $@ $<
- %.c: %.y → bison
- %.c: %.l → flex
5. 常用函数
$(wildcard *.c) # 文件名列表
$(patsubst %.c, %.o, $(SRCS))
$(subst old, new, text)
$(addprefix src/, foo.c)
$(shell uname -r)
$(error stop)
$(warning caution)
6. 条件判断
ifeq ($(DEBUG),1)
CFLAGS += -O0 -g3
else
CFLAGS += -O2
endif
ifdef ARCH
CC = $(ARCH)-linux-gnu-gcc
endif
7. 子目录
SUBDIRS = lib app
all:
@for d in $(SUBDIRS); do $(MAKE) -C $$d || exit 1; done
二、CMake
1. 最小 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(app C)
add_executable(app main.c)
target_link_libraries(app m)
2. 常用命令
# 变量
set(SOURCES main.c foo.c bar.c)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
# 可执行
add_executable(app ${SOURCES})
# 静态库
add_library(mylib STATIC src1.c src2.c)
target_link_libraries(app mylib)
# 动态库
add_library(mylib SHARED src1.c)
set_target_properties(mylib PROPERTIES VERSION 1.0 SOVERSION 1)
# 子目录
add_subdirectory(lib)
add_subdirectory(app)
# 安装
install(TARGETS app RUNTIME DESTINATION bin)
install(FILES config.h DESTINATION include)
# 找依赖
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0)
target_include_directories(app PRIVATE ${GLIB_INCLUDE_DIRS})
target_link_libraries(app PRIVATE ${GLIB_LIBRARIES})
# 找头文件和库
find_path(MY_INCLUDE_DIR foo.h)
find_library(MY_LIB foo)
3. 选项
option(BUILD_TESTS "Build tests" ON)
option(USE_OPENSSL "Use OpenSSL" OFF)
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
4. 命令行
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_TESTS=ON
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failure
cmake --install build --prefix /tmp/install
三、其他构建系统(了解)
| 系统 | 场景 |
|---|---|
| autotools (autoconf + automake + libtool) | 老牌 C 项目(Linux 内核外许多) |
| meson + ninja | GNOME、新项目(如 systemd、QEMU) |
| Bazel / Pants / Buck2 | Google 系、大规模 |
| xmake | 中文社区,跨平台 |
| scons | Python 风格 |
四、内核 / U-Boot 的 Makefile 风格
- 使用
Kbuild系统(基于 make) obj-y/obj-m/obj-n- 详见
Documentation/kbuild/内核文档