参考1:王利涛linux三剑客Makefile
参考2:宅学部落
Makefile杂记
1-1 开始
hello:helloworld.o
gcc -o hello helloworld.o
helloworld.o:helloworld.c
gcc -o helloworld.o -c helloworld.c
clean:
rm hello helloworld.o
2-1 条件变量复制及默认参数
DEBUG ?= false//默认false ?= 是当DEBUG没有值的时候会赋值
ifeq ($(DEBUG),"true")
CC = gcc -g// 生成调试信息,可以用gdb等工具做调试
else
CC = gcc
endif
all:hello
hello:lcd.o player.o
$(CC) -o hello lcd.o player.o
player.o:player.c
$(CC) -o player.o -c player.c
lcd.o:lcd.c
$(CC) -o lcd.o -c lcd.c
clean:
rm lcd.o hello player.o
2-2
.PHONY:_all clean //伪目标,all,clean 对应伪target,不生成具体的文件
.PONHY:all clean
ifeq ($(DEBUG),"true")
CC = gcc -g
else
CC = gcc
endif
all:test1
all:test2
test1 :
@echo "Just for test1:$@"
test2:
@echo "Just for test2"
hello:lcd.o player.o
@echo "start build hello"
$(CC) -o hello lcd.o player.o
@echo "build hello sucess"
#%.o:%.c
# $(CC) -o $@ -c $^
clean:
rm -f lcd.o hello player.o
2-3-1
.PHONY:clean
CC = gcc
BIN = hello
OBJS = player.o lcd.o
$(BIN): $(OBJS)
$(CC) -o $(BIN) $(OBJS)
player.o:player.c
$(CC) -o player.o -c player.c
lcd.o:lcd.c
$(CC) -o lcd.o -c lcd.c
clean:
rm -f player.o lcd.o hello
2-3-2
$(info $(MESSAGE)) // info 是makefile 内置函数,用于向控制台打印信息
.PHONY:all
HELLO = Good
TIME = morning!
STRING = $(HELLO) $(TIME)
$(info $(STRING))
TIME = afternoon!
$(info $(STRING))
all:
@echo "done"
2-3-3 变量的重定义,作用范围
//类似于C语言中的全局变量,局部变量
.PHONY:clean
OBJS = player.o lcd.o
BIN = mp3
N = 1
$(BIN): N = 2
$(BIN):$(OBJS)
@echo "BIN: N = $(N)"
gcc -o $(BIN) $(OBJS)
player.o:N= 3
player.o:player.c
@echo "player.o: N = $(N)"
gcc -o player.o -c player.c
lcd.o:lcd.c
@echo "lcd.o: N = $(N)"
gcc -o lcd.o -c lcd.c
clean:
@echo "clean: N = $(N)"
rm -f $(BIN) $(OBJS)
输出
2-3-4
变量的作用范围
.PHONY:clean
N = 1
OBJS = player.o lcd.o
BIN = mp3
$(BIN):$(OBJS)
@echo "BIN:N=$(N)"
gcc -o $(BIN) $(OBJS)
$(BIN): N = 2
%.o: N = 3 // 对每个target %.o都有一个变量N = 3
player.o:player.c
@echo "player.o:N=$(N)"
gcc -o player.o -c player.c
lcd.o:lcd.c
@echo "lcd.o:N=$(N)"
gcc -o lcd.o -c lcd.c
clean:
@echo "clean: N = $(N)"
rm $(BIN) $(OBJS)
2-3-5
// 根据依赖的顺序,去构建依赖
$@ 当前target
$^ 当前依赖
.PHONY:clean
OBJS = player.o lcd.o
BIN = mp3
$(BIN):$(OBJS)
@echo "BIN------------$@:$^"
gcc -o $@ $^
player.o:player.c
@echo "------------$@:$^"
gcc -o $@ -c $^
lcd.o:lcd.c
@echo "---------$@:$^"
gcc -o $@ -c $^
clean:
rm -f $(BIN) $(OBJS)
2-3-6
.PHONY:all
CFLAGS = -g
all:
@echo "CFLAGS = $(CFLAGS)"
@echo "SHELL = $(SHELL)"
@echo "MAKE = $(MAKE)"
# @echo "HOSTNAME = $(HOSTNAME)" 这里要用下面的方式
@echo "HOSTNAME = $(shell hostname)"
输出
2-3-7
export 导出变量后,变量的值
#./ makefile路径
.PHONY:all
export N = 3
#N = 3
all:
@echo "build...."
# cd test && make N=$(N)
cd test && make
make -C lcd
#./lcd/makefile
.PHONY:all
all:
@echo "build lcd"
@echo "N = $(N)"
2-4
.PHONY:all
DEBUG = true
ifeq ($(DEBUG),true)
VERSION = debug
CC = gcc -g
else
VERSION = release
CC = gcc
endif
hello:hello.c
@echo "build $(VERSION) mode"
$(CC) -o $@ $^
clean:
rm hello
输出
2-5-1 列表处理的内建函数
makefile内建函数使用
$(strip $(SRCS)) //去除SRCS中文件名间多余的空格
(
s
u
b
s
t
.
c
,
.
o
,
(subst .c,.o,
(subst.c,.o,(strip $(SRCS))) // 把(第三个)变量文件名,格式替换 .c 后缀(第一个)-> .o后缀(第二个)
subst 用于生成对象文件的列表
(
p
a
t
s
u
b
s
t
(patsubst %.c,%.d,
(patsubst(SRCS))// 将.c后缀替换为.d后缀,用于生成依赖文件列表
$(SRCS:.c=.d)// 类似于 patsubst , 也是生成依赖文件列表
(
f
i
n
d
s
t
r
i
n
g
u
s
b
,
(findstring usb,
(findstringusb,(SRCS))//findstring 去找字符串,如果找到返回字符串;否则返回空
$(filter %.c %.h, $(SRCS))// 从 SRCS列表中,帅选出后缀为.c , .h 的文件
.PHONY:all
SRCS = player.c lcd.c usb.c media.c hello.h main.txt
OBJS = $(subst .c,.o,$(strip $(SRCS)))
DEPS = $(patsubst %.c,%.d,$(SRCS))
DEPS2 = $(SRCS:.c=.d)
FIND = $(findstring usb,$(SRCS))
FILTER = $(filter %.c %.h, $(SRCS))
all:
@echo "OBJS = $(OBJS)"
@echo "DEPS = $(DEPS)"
@echo "DEPS2 = $(DEPS2)"
@echo "FIND = $(FIND)"
@echo "FILTER = $(FILTER)"
输出
OBJS = $(subst .c,.o,$(SRCS)) 这样修改时
2-5-2 文件名操作的内建函数
.PHONY:all
LIB = /home/hello/libhello.a
#获得路径
LIB1 = $(dir $(LIB))
#滤除路径
LIB2 = $(notdir $(LIB))
#获得后缀
LIB3 = $(suffix $(LIB))
#滤除后缀
LIB4 = $(basename $(LIB))
#添加后缀,在LIB4的基础上
LIB5 = $(addsuffix .c,$(LIB4))
#添加前缀,在LIB2的基础上
LIB6 = $(addprefix /usr/lib/,$(LIB2))
#找出当前路径的.c后缀文件
SRCS = $(wildcard *.c)
all:
@echo "LIB1 = $(LIB1)"
@echo "LIB2 = $(LIB2)"
@echo "LIB3 = $(LIB3)"
@echo "LIB4 = $(LIB4)"
@echo "LIB5 = $(LIB5)"
@echo "LIB6 = $(LIB6)"
@echo "SRCS = $(SRCS)"
输出
.PHONY:all
LIB = /home/hello/libhello.a
LIB1 = $(dir $(LIB))
LIB2 = $(notdir $(LIB))
LIB3 = $(suffix $(LIB))
LIB4 = $(basename $(LIB))
LIB5 = $(addsuffix .c,$(LIB2))
LIB6 = $(addprefix /usr/lib/,$(LIB5))
SRCS = $(wildcard *.c *.h)
all:
@echo "LIB1 = $(LIB1)"
@echo "LIB2 = $(LIB2)"
@echo "LIB3 = $(LIB3)"
@echo "LIB4 = $(LIB4)"
@echo "LIB5 = $(LIB5)"
@echo "LIB6 = $(LIB6)"
@echo "SRCS = $(SRCS)"
2-5-3 foreach & shell
foreach 使用
A = 1 3 4 5 6 7 8 9
# 第一个元素: i 变量 对应A立刻表中的某个元素
# 第二个元素: A 列表,需要遍历的列表
# 第三个操作: 遍历到某个元素,都会将元素值赋值给i,并操作当前的操作
B = $(foreach i,$(A),$(addprefix 0.,$(i)))
C = $(foreach i,$(A),$(addsuffix .0,$(i)))
all:
@echo "A = $(A)"
@echo "B = $(B)"
@echo "C = $(C)"
shell cmd的使用
.PHONY:all clean
$(shell mkdir -p s1)
$(shell mkdir -p s2)
all:
@echo "hello world"
clean:
rm -r s1 s2
make 后, 构建了两个目录 s1, s2
2-6 构建 static & dll 库
2-6-1 static 库
.PHONY:clean
libmath.a:libmath.o
ar rcs $@ $^
libmath.o:libmath.c libmath.h
A:main.o
gcc -o $@ main.o -I. -L. -lmath
main.o:main.c
gcc -o $@ -c $^
clean:
rm libmath.a libmath.o
rm A main.o
2-6-2 dll库
.PHONY:clean AA
libdll.so:dll.o
gcc -o $@ -shared $^
dll.o:dll.c
gcc -o $@ -fPIC -c $^
SOURCE2 = main.c
DE_SOURCE2 = $(subst .c,.o,$(strip $(SOURCE2)))
CFLAGS = -I.
DLLLIBS = -L. -ldll
$(info $(DE_SOURCE2))
TA = A
AA: $(TA)
$(TA): $(DE_SOURCE2)
gcc -o $@ $^ $(CFLAGS) $(DLLLIBS)
%.o:%.c
gcc -o $@ -fPIC -c $^
clean:
rm libdll.so dll.o
rm $(TA) $(SOURCE2)
2-8
2-8-1
.PHONY:clean
hello:hello.o
gcc -o hello hello.o
#hello.o:hello.c
# gcc -o $@ -c $^
clean:
rm hello hello.o
2-8-2 测试环境变量的值
.PHONY:all
all:
@echo "CC = $(CC)"
@echo "AS = $(AS)"
@echo "CXX = $(CXX)"
@echo "AR = $(AR)"
@echo "CFLAGS = $(CFLAGS)"
@echo "CXXFLAGS = $(CXXFLAGS)"
@echo "ASFLAGS = $(ASFLAGS)"
@echo "ARFLAGS = $(ARFLAAGS)"
@echo "LDFLAGS = $(LDFLAGS)"
输出
2-8-3
.PHONY: clean
test1 test2:// 这里target是test1 (那意思是字符后第一个空格就分出了target)
@echo "test:$@"
hello:player.o lcd.o media.o
gcc -o $@ $^
%.o:%.c
gcc -o $@ -c $^
clean:
rm *.o hello
3.1
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
BIN = mp3
all: $(BIN)
$(BIN):$(OBJS)
@echo "SRCS =$(SRCS)"
@echo "OBJS =$(OBJS)"
gcc -o $@ $^
%.o:%.c
gcc -o $@ -c $^
clean:
rm -f $(BIN) $(OBJS)
输出
3.2
// gcc -MM 是生成依赖文件,不进行编译什么的,这个xxx.d的依赖能够保证依赖的完整性,在include后
// 这里的运发,文件列表,都是文件名的列表,不一定真实存在
// 所以*.d 是不存在的,再gcc -MM 生成的时候,是一个空的文件,使用> 或者>> 效果是等效的
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN = mp3
all: $(BIN) $(DEPS)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(OBJS)
gcc -o $@ $^
%.o:%.c
gcc -o $@ -c $(filter %.c,$^)
%.d:%.c
gcc -MM $^ > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
输出
3.3 多级makefile与include
//使用include 文件,
//make -C path 执行指定路径的makefile
源目录结构
./makefile
.PHONY:all clean
all:
make -C lcd
make -C usb
make -C media
make -C app
clean:
rm -fr app/player.o app/player.d app/mp3
rm -fr usb/usb.o usb/usb.d
rm -fr lcd/lcd.o lcd/lcd.d
rm -fr media/media.o media/media.d
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
$(info $(SRCS))
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
all: $(DEPS) $(OBJS) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(OBJS)
gcc -o $@ $^ ../lcd/lcd.o ../usb/usb.o ../media/media.o
%.o:%.c
gcc -o $@ -c $(filter %.c,$^)
%.d:%.c
gcc -MM $^ > $@
AA: AB AC
AB: 1.c 2.c 3.c
AB: 4.c
echo "$@ $^"
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
./app/makefile
BIN = mp3
include ../common.mk
./usb/makefile
BIN =
include ../common.mk
./media/makefile
BIN =
include ../common.mk
./lcd/makefile
BIN =
include ../common.mk
3.4 对OBJS和BIN 引入LINK_OBJ_DIR & addprefix
与3.3 对比,3.4改动了./common.mk和 ./makefile文件
源文件
./makefile
.PHONY:all clean
all:
make -C lcd
make -C usb
make -C media
make -C app
clean:
rm -f mp3
rm -fr app/link_obj/*.o app/player.d
rm -fr usb/usb.o usb/usb.d
rm -fr lcd/lcd.o lcd/lcd.d
rm -fr media/media.o media/media.d
rm -rf app/link_obj
与3.3对比
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix /home/mp3/,$(BIN))
LINK_OBJ_DIR =/home/mp3/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
OBJS := $(addprefix $(LINK_OBJ_DIR)/,$(OBJS))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ +=$(OBJS)
all: $(DEPS) $(OBJS) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ)
@echo "LINK_OBJ=$(LINK_OBJ)"
gcc -o $@ $^
$(LINK_OBJ_DIR)/%.o:%.c
gcc -o $@ -c $(filter %.c,$^)
%.d:%.c
gcc -MM $^ | sed 's,\(.*\).o[ :]*,$(LINK_OBJ_DIR)/\1.o:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
对BIN,OBJS等引入了prefix,将生成的BIN,OBJS放入了LINK_OBJ_DIR
3.5 引入shell pwd 项目路径
在3.4的基础上,将绝对路径改为pwd 的项目路径
编译前
编译后
相关改动./app/makefile, ./makefile, common.mk
./app/makefile
BIN = mp3
include $(BUILD_ROOT)/common.mk
./makefile
.PHONY:all clean
export BUILD_ROOT = $(shell pwd) // 获得当前项目的根目录
all:
make -C lcd
make -C usb
make -C media
make -C app
clean:
rm -rf app/link_obj app/dep mp3
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
DEP_DIR = $(BUILD_ROOT)/app/dep
$(shell mkdir -p $(DEP_DIR))
OBJS := $(addprefix $(LINK_OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ +=$(OBJS)
all: $(DEPS) $(OBJS) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ)
@echo "LINK_OBJ=$(LINK_OBJ)"
gcc -o $@ $^
$(LINK_OBJ_DIR)/%.o:%.c
gcc -o $@ -c $(filter %.c,$^)
$(DEP_DIR)/%.d:%.c
gcc -MM $(filter %.c,$^) | sed 's,\(.*\).o[ :]*,$(LINK_OBJ_DIR)/\1.o $@:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
3.6 引入HEAD_PATH 头文件目录
与3.5的变化
1. buil_root 目录中添加一个方头文件的目录
2. 在makefile 文件中引入了相关处理的参数
编译前后对比
编译前
编译后
相关源文件 ./makefile, ./common.mk,
./makefile
.PHONY:all clean
export BUILD_ROOT = $(shell pwd)
export HEAD_PATH = $(BUILD_ROOT)/inc
all:
make -C lcd
make -C usb
make -C media
make -C app
clean:
rm -rf app/link_obj app/dep mp3
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
DEP_DIR = $(BUILD_ROOT)/app/dep
$(shell mkdir -p $(DEP_DIR))
OBJS := $(addprefix $(LINK_OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ +=$(OBJS)
all: $(DEPS) $(OBJS) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ)
@echo "LINK_OBJ=$(LINK_OBJ)"
gcc -o $@ $^
$(LINK_OBJ_DIR)/%.o:%.c
gcc -I$(HEAD_PATH) -o $@ -c $(filter %.c,$^)
$(DEP_DIR)/%.d:%.c
gcc -I$(HEAD_PATH) -MM $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,$(LINK_OBJ_DIR)/\1.o $@:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
3.7 引入static lib 构建
与3.6的变化在./common.mk中引入了lib相关的编译,在需要生成lib的模块中,子 makefile 添加LIB变量
源文件
./makefile 输出构建的内容
.PHONY:all clean
export BUILD_ROOT = $(shell pwd)
export HEAD_PATH = $(BUILD_ROOT)/inc
all:
make -C lcd
make -C usb
make -C media
make -C app
clean:
rm -rf app/link_obj app/dep app/lib_obj mp3
rm -rf lib/*.a
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
DEP_DIR = $(BUILD_ROOT)/app/dep
$(shell mkdir -p $(DEP_DIR))
LIB_OBJ_DIR = $(BUILD_ROOT)/app/lib_obj
$(shell mkdir -p $(LIB_OBJ_DIR))
LIB_DIR = $(BUILD_ROOT)/lib
$(shell mkdir -p $(LIB_OBJ_DIR))
OBJ_DIR = $(LINK_OBJ_DIR)
ifneq ("$(LIB)","")
OBJ_DIR = $(LIB_OBJ_DIR)
endif
OBJS := $(addprefix $(OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))
LIB := $(addprefix $(LIB_DIR)/,$(LIB))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ +=$(OBJS)
LIB_DEP = $(wildcard $(LIB_DIR)/*.a)
LINK_LIB_NAME = $(patsubst lib%,-l%,$(basename $(notdir $(LIB_DEP))))
all: $(DEPS) $(OBJS) $(LIB) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ) $(LIB_DEP)
@echo "LINK_LIB_NAME=$(LINK_LIB_NAME)"
gcc -o $@ $^ -L$(LIB_DIR) $(LINK_LIB_NAME)
$(LIB):$(OBJS)
ar rcs $@ $^
$(OBJ_DIR)/%.o:%.c
gcc -I$(HEAD_PATH) -o $@ -c $(filter %.c,$^)
$(DEP_DIR)/%.d:%.c
gcc -I$(HEAD_PATH) -MM $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,$(OBJ_DIR)/\1.o $@:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
需要构建static 文件的子模块的makefile,引入LIB
BIN =
LIB = libmedia.a
include ../common.mk
3.8 引入动态库dll lib
关注./makefile, ./common.mk, 需要构建dll lib模块的子makefile
源文件
./makefile
添加了math模块,对应生成dll lib
.PHONY:all clean
export BUILD_ROOT = $(shell pwd)
export HEAD_PATH = $(BUILD_ROOT)/inc
all:
make -C lcd
make -C usb
make -C media
make -C math
make -C app
clean:
rm -rf app/link_obj app/dep app/lib_obj mp3
rm -rf lib/*.a lib/*.so
./common.mk
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
DEP_DIR = $(BUILD_ROOT)/app/dep
$(shell mkdir -p $(DEP_DIR))
LIB_OBJ_DIR = $(BUILD_ROOT)/app/lib_obj
$(shell mkdir -p $(LIB_OBJ_DIR))
LIB_DIR = $(BUILD_ROOT)/lib
OBJ_DIR = $(LINK_OBJ_DIR)
ifneq ("$(LIB)","")
OBJ_DIR = $(LIB_OBJ_DIR)
endif
ifneq ("$(DLL)","")
OBJ_DIR = $(LIB_OBJ_DIR)
PIC = -fPIC
endif
OBJS := $(addprefix $(OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))
LIB := $(addprefix $(LIB_DIR)/,$(LIB))
DLL := $(addprefix $(LIB_DIR)/,$(DLL))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ += $(OBJS)
LIB_DEP = $(wildcard $(LIB_DIR)/*.a) $(wildcard $(LIB_DIR)/*.so)
LINK_LIB_NAME = $(patsubst lib%,-l%,$(basename $(notdir $(LIB_DEP))))
all: $(DEPS) $(OBJS) $(LIB) $(DLL) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ)
gcc -o $@ $^ -L$(LIB_DIR) $(LINK_LIB_NAME)
$(LIB):$(OBJS)
ar rcs $@ $^
$(DLL):$(OBJS)
gcc -shared -o $@ $^
$(OBJ_DIR)/%.o:%.c
gcc -I$(HEAD_PATH) -o $@ -c $(PIC) $(filter %.c,$^)
$(DEP_DIR)/%.d:%.c
gcc -I$(HEAD_PATH) -MM $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,$(OBJ_DIR)/\1.o $@:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
生成dll lib模块的子makefile文件
BIN =
LIB =
DLL = libmath.so
include $(BUILD_ROOT)/common.mk
3.9 引入ext lib到当前项目
在./common.mk中引入了对外部库的支持
源文件
.PHONY:all clean
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
$(shell mkdir -p $(LINK_OBJ_DIR))
DEP_DIR = $(BUILD_ROOT)/app/dep
$(shell mkdir -p $(DEP_DIR))
LIB_OBJ_DIR = $(BUILD_ROOT)/app/lib_obj
$(shell mkdir -p $(LIB_OBJ_DIR))
LIB_DIR = $(BUILD_ROOT)/lib
OBJ_DIR = $(LINK_OBJ_DIR)
ifneq ("$(LIB)","")
OBJ_DIR = $(LIB_OBJ_DIR)
endif
ifneq ("$(DLL)","")
OBJ_DIR = $(LIB_OBJ_DIR)
PIC = -fPIC
endif
OBJS := $(addprefix $(OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))
LIB := $(addprefix $(LIB_DIR)/,$(LIB))
DLL := $(addprefix $(LIB_DIR)/,$(DLL))
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
LINK_OBJ += $(OBJS)
LIB_DEP = $(wildcard $(LIB_DIR)/*.a) $(wildcard $(LIB_DIR)/*.so)
LIB_DEP += $(wildcard $(LIB_DIR)/ext_lib/*.a) $(wildcard $(LIB_DIR)/ext_lib/*.so)
LINK_LIB_NAME = $(patsubst lib%,-l%,$(basename $(notdir $(LIB_DEP))))
all: $(DEPS) $(OBJS) $(LIB) $(DLL) $(BIN)
ifneq ("$(wildcard $(DEPS))","")
include $(DEPS)
endif
$(BIN):$(LINK_OBJ)
gcc -o $@ $^ -L$(LIB_DIR) -L$(LIB_DIR)/ext_lib $(LINK_LIB_NAME)
$(LIB):$(OBJS)
ar rcs $@ $^
$(DLL):$(OBJS)
gcc -shared -o $@ $^
$(OBJ_DIR)/%.o:%.c
gcc -I$(HEAD_PATH) -o $@ -c $(PIC) $(filter %.c,$^)
$(DEP_DIR)/%.d:%.c
gcc -I$(HEAD_PATH) -MM $(filter %.c,$^) | sed 's,\(.*\)\.o[ :]*,$(OBJ_DIR)/\1.o $@:,g' > $@
clean:
rm -f $(BIN) $(OBJS) $(DEPS)
3.10 引入install & uninstall
相关文件./makefile
.PHONY:all clean
export BUILD_ROOT = $(shell pwd)
export HEAD_PATH = $(BUILD_ROOT)/inc
all:
make -C lcd
make -C usb
make -C media
make -C math
make -C app
clean:
rm -rf app/link_obj app/dep app/lib_obj mp3
rm -rf lib/*.a
rm -rf lib/*.so
install:
cp mp3 /usr/bin
cp lib/libmath.so /usr/lib
cp lib/ext_lib/librmvb.so /usr/lib
uninstall:
rm /usr/bin/mp3
rm /usr/lib/libmath.so
rm /usr/lib/librmvb.so
3.11 引入配置文件
./makefile ./config.mk 两个相关文件
源文件
./config.mk
#---------------------------------
# ZHAIXUE_MAKEFILE
# Description: a project makefile demo
# Author : ddblog@qq.com
# Date : 2016.12.23
#---------------------------------
# build root directory
export BUILD_ROOT = $(shell pwd)
# Head files PATH
export HEAD_PATH = $(BUILD_ROOT)/inc
#build directory
#when you add a module,you need add you directory
# here
BUILD_DIR = $(BUILD_ROOT)/lcd/ \
$(BUILD_ROOT)/usb/ \
$(BUILD_ROOT)/media/ \
$(BUILD_ROOT)/math/ \
$(BUILD_ROOT)/app/
DEBUG = true
ARCH = arm
./makefile
.PHONY:all clean install uninstall
include config.mk
all:
@for dir in $(BUILD_DIR); \
do \
make -C $$dir; \
done
clean:
rm -rf app/link_obj app/dep app/lib_obj mp3
rm -rf lib/*.a
rm -rf lib/*.so
install:
cp mp3 /usr/bin
cp lib/libmath.so /usr/lib
cp lib/ext_lib/librmvb.so /usr/lib
uninstall:
rm -f /usr/bin/mp3
rm /usr/lib/libmath.so
rm /usr/lib/librmvb.so