Makefile——Linux下C/C++编译方法

55 阅读1分钟

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)(OBJ) (CC) (CFLAGS)o(CFLAGS) -o @ ^%.o: %.c (CC) (CFLAGS)c(CFLAGS) -c < -o @.PHONY:cleanclean:rmf@.PHONY: cleanclean: rm -f (OBJ) app

二、多文件与目录管理

多目录项目结构

makefile

复制

SRCDIR = src
OBJDIR = obj
SRCS = (wildcard(wildcard (SRCDIR)/*.c (SRCDIR)//.c)OBJS=(SRCDIR)/*/*.c)OBJS = (patsubst (SRCDIR)/(SRCDIR)/%.c, (OBJDIR)/%.o, (SRCS))app:(SRCS))app: (OBJS)
(CC)(CC) (CFLAGS) -o @@ ^(OBJDIR)/(OBJDIR)/%.o: (SRCDIR)/%.c
mkdir -p (@D)(@D) (CC) (CFLAGS)c(CFLAGS) -c < -o @.PHONY:cleanclean:rmrf@.PHONY: cleanclean: rm -rf (OBJDIR) app

静态库与动态库

makefile

复制

LIBDIR = lib
STATIC_LIB = (LIBDIR)/libmodule.a(LIBDIR)/libmodule.a(STATIC_LIB): (OBJS)arrcs(OBJS) ar rcs @ app:^app: (STATIC_LIB)
(CC)(CC) (CFLAGS) -o @main.oL@ main.o -L(LIBDIR) -lmodule

三、依赖自动生成

makefile

复制

DEPDIR = .deps
DEPFLAGS = -MT @MMDMPMF@ -MMD -MP -MF (DEPDIR)/.d*.d(OBJDIR)/%.o: (SRCDIR)/(SRCDIR)/%.c (DEPDIR)/%.d | (DEPDIR)(DEPDIR) (CC) (CFLAGS)(CFLAGS) (DEPFLAGS) -c <o< -o @(DEPDIR)/(DEPDIR)/%.d: ;.PRECIOUS: (DEPDIR)/%.dinclude (wildcard(wildcard (DEPDIR)/*.d)

四、高级技巧与优化

并行编译

bash

复制

make -j$(nproc)

调试与发布模式

makefile

复制

DEBUG ?= 1ifeq ($(DEBUG), 1)
CFLAGS += -g -O0else
CFLAGS += -O2endif

集成单元测试

makefile

复制

TEST_SRCS = (wildcardtests/.c)TESTOBJS=(wildcard tests/*.c)TEST_OBJS = (patsubst tests/%.c, (OBJDIR)/tests/(OBJDIR)/tests/%.o, (TEST_SRCS))test: (TESTOBJS)(TEST_OBJS) (STATIC_LIB)
(CC)(CC) (CFLAGS) -o @@ ^ -lgtest -lgtest_main -lpthread
./@@(OBJDIR)/tests/%.o: tests/%.c
mkdir -p (@D)(@D) (CC) (CFLAGS)I(CFLAGS) -I(SRCDIR) -c <o< -o @

五、完整示例

makefile

复制

CC = gcc
CFLAGS = -Wall -Iinclude
LDFLAGS = -Llib -lmodule
SRCDIR = src
OBJDIR = obj
DEPDIR = .deps
LIBDIR = lib
BINDIR = bin

SRCS = (wildcard(wildcard (SRCDIR)/.c (SRCDIR)//.c)OBJS=(SRCDIR)/*/*.c)OBJS = (patsubst (SRCDIR)/(SRCDIR)/%.c, (OBJDIR)/%.o, (SRCS))DEPS=(SRCS))DEPS = (patsubst (SRCDIR)/(SRCDIR)/%.c, (DEPDIR)/%.d, (SRCS))TARGET=(SRCS))TARGET = (BINDIR)/app.PHONY: all clean testall: (TARGET)(TARGET)(TARGET): (OBJS)(OBJS) | (BINDIR)
(CC)(CC) (CFLAGS) -o @@ ^ (LDFLAGS)(LDFLAGS)(OBJDIR)/%.o: (SRCDIR)/(SRCDIR)/%.c (DEPDIR)/%.d | (OBJDIR)(OBJDIR) (DEPDIR)
(CC)(CC) (CFLAGS) -MMD -MP -MF (DEPDIR)/(DEPDIR)/
.d -c <o< -o @(DEPDIR)/(DEPDIR)/%.d: ;(BINDIR) (OBJDIR)(OBJDIR) (DEPDIR) (LIBDIR):mkdirp(LIBDIR): mkdir -p @-include (DEPS)clean:rmrf(DEPS)clean: rm -rf (OBJDIR) (DEPDIR)(DEPDIR) (BINDIR) $(LIBDIR)/*.atest: # 添加测试目标规则(参考第四部分)

测试命令