Makefile——Linux下C/C++编译方法
一、基础语法与示例
基本规则
makefile
复制
定义目标、依赖和命令app: main.o module1.o module2.o
gcc -o app main.o module1.o module2.omain.o: main.c
gcc -c main.cmodule1.o: module1.c module1.h
gcc -c module1.cmodule2.o: module2.c module2.h
gcc -c module2.c.PHONY: cleanclean:
rm -f *.o app
变量与自动化变量
makefile
复制
CC = gcc
CFLAGS = -Wall -g
OBJ = main.o module1.o module2.oapp: (OBJ)(CC) (CFLAGS)−o@ ^%.o: %.c (CC) (CFLAGS)−c< -o @.PHONY:cleanclean:rm−f(OBJ) app
二、多文件与目录管理
多目录项目结构
makefile
复制
SRCDIR = src
OBJDIR = obj
SRCS = (wildcard(SRCDIR)/*.c (SRCDIR)/∗/∗.c)OBJS=(patsubst (SRCDIR)/(OBJDIR)/%.o, (SRCS))app:(OBJS)
(CC)(CFLAGS) -o @^(OBJDIR)/(SRCDIR)/%.c
mkdir -p (@D)(CC) (CFLAGS)−c< -o @.PHONY:cleanclean:rm−rf(OBJDIR) app
静态库与动态库
makefile
复制
LIBDIR = lib
STATIC_LIB = (LIBDIR)/libmodule.a(STATIC_LIB): (OBJS)arrcs@ app:(STATIC_LIB)
(CC)(CFLAGS) -o @main.o−L(LIBDIR) -lmodule
三、依赖自动生成
makefile
复制
DEPDIR = .deps
DEPFLAGS = -MT @−MMD−MP−MF(DEPDIR)/∗.d(OBJDIR)/%.o: (SRCDIR)/(DEPDIR)/%.d | (DEPDIR)(CC) (CFLAGS)(DEPFLAGS) -c <−o@(DEPDIR)/(DEPDIR)/%.dinclude (wildcard(DEPDIR)/*.d)
四、高级技巧与优化
并行编译
bash
复制
make -j$(nproc)
调试与发布模式
makefile
复制
DEBUG ?= 1ifeq ($(DEBUG), 1)
CFLAGS += -g -O0else
CFLAGS += -O2endif
集成单元测试
makefile
复制
TEST_SRCS = (wildcardtests/∗.c)TESTOBJS=(patsubst tests/%.c, (OBJDIR)/tests/(TEST_SRCS))test: (TESTOBJS)(STATIC_LIB)
(CC)(CFLAGS) -o @^ -lgtest -lgtest_main -lpthread
./@(OBJDIR)/tests/%.o: tests/%.c
mkdir -p (@D)(CC) (CFLAGS)−I(SRCDIR) -c <−o@
五、完整示例
makefile
复制
CC = gcc
CFLAGS = -Wall -Iinclude
LDFLAGS = -Llib -lmodule
SRCDIR = src
OBJDIR = obj
DEPDIR = .deps
LIBDIR = lib
BINDIR = bin
SRCS = (wildcard(SRCDIR)/.c (SRCDIR)/∗/∗.c)OBJS=(patsubst (SRCDIR)/(OBJDIR)/%.o, (SRCS))DEPS=(patsubst (SRCDIR)/(DEPDIR)/%.d, (SRCS))TARGET=(BINDIR)/app.PHONY: all clean testall: (TARGET)(TARGET): (OBJS)∣(BINDIR)
(CC)(CFLAGS) -o @^ (LDFLAGS)(OBJDIR)/%.o: (SRCDIR)/(DEPDIR)/%.d | (OBJDIR)(DEPDIR)
(CC)(CFLAGS) -MMD -MP -MF (DEPDIR)/.d -c <−o@(DEPDIR)/(BINDIR) (OBJDIR)(DEPDIR) (LIBDIR):mkdir−p@-include (DEPS)clean:rm−rf(OBJDIR) (DEPDIR)(BINDIR) $(LIBDIR)/*.atest: # 添加测试目标规则(参考第四部分)
测试命令