Makefile 工程项目通用版
目录:
工程项目的Makefile分为3类:
- 顶层目录的Makefile
- 顶层目录的Makefile.build
- 各级子目录的Makefile
顶层目录的Makefile
顶层:Makefile ; 顶层:Makefile.build ;子目录:Makefile
编译过程: 从顶层开始递归进入子目录,当进入到一个目录的最底层时,开始使用GCC编译,再将该层的所有.o文件打包成build-in.o,返回它的上一层目录再递归进入子目录,当编译完所有的子目录后,就开始编译顶层的.c文件,最后将顶层的.o文件和顶层每个子目录的build-in.o链接成我们的目标文件
——[通用Makefile编写]
#-------------指定编译工具链---
CROSS_COMPILE = mipsel-openwrt-linux-uclibc-
#export PATH=$PATH:/Volumes/OpenWrt/openwrt_widora/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin
#export STAGING_DIR=/Volumes/OpenWrt/openwrt_widora/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin:$STAGING_DIR
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP
#编译器参数
CFLAGS := -Wall -O2 -g
#指定编译器头文件(根据实际项目手动修改)
CFLAGS += -I./font -I./LCD -I./sys -I./touch -I./pwm -I./spi -I./key -I./picture
#指定编译器链接库(根据实际项目手动修改)
LDFLAGS := -lpthread -lm -lrt -ldl
export CFLAGS LDFLAGS
#获得当前程序的顶层目录
TOPDIR := $(shell pwd)
export TOPDIR
#编译后的程序名(根据实际项目手动修改)
TARGET := show_file
#-------------------------顶层要生成的.o文件以及顶层文件夹(根据实际项目手动修改)------------------
obj-y += main.o
obj-y += LCD/
obj-y += font/
obj-y += sys/
obj-y += touch/
obj-y += pwm/
obj-y += spi/
obj-y += key/
obj-y += picture/
#obj-y += GUI/
#--------------顶层的第一个规则(默认规则)------------------
all :
#进入当前目录,使用顶层的makefile.build进行编译
make -C ./ -f $(TOPDIR)/Makefile.build
#将编译好的built-in.o文件链接生成我们的目标文件
$(CPP) $(LDFLAGS) -o $(TARGET) built-in.o
#---------------顶层的清除规则----------------------------
clean:
rm -f $(shell find . -name "*.o")
rm -f $(TARGET)
distclean:
rm -f $(shell find . -name "*.o")
rm -f $(shell find . -name "*.d")
rm -f $(TARGET)
顶层目录的Makefile.build(无需改动)
#定义一个PHONY变量
PHONY := __build
#开头说明__build伪目标,使其成为Makefile.build的第一个目标
__build:
#定义当前目录的目标变量,初始值为空
obj-y :=
#定义当前目录的子目录变量,初始值为空
subdir-y :=
#将当前目录的Makefile包含进来,初始化obj-y
include Makefile
# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y)) : c/ d/
# __subdir-y : c d
# subdir-y : c d
#筛选出当前目录的目标变量中的子目录,并且去掉/
__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
#将开始定义的subdir-y赋值为__subdir-y
subdir-y += $(__subdir-y)
# c/built-in.o d/built-in.o
#对于subdir-y里面的每一个值(目录),增加一个相应的目录/built-in.o的变量值
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
# a.o b.o
#得到obj-y中的.o文件
cur_objs := $(filter-out %/, $(obj-y))
#对于所有的.o文件,定义它的依赖文件名
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))
#根据依赖文件名,判断依赖文件是否存在,存在就包含就来
ifneq ($(dep_files),)
include $(dep_files)
endif
PHONY += $(subdir-y)
#将$(subdir-y)也加入到变量PHONY中
__build : $(subdir-y) built-in.o
$(subdir-y):
make -C $@ -f $(TOPDIR)/Makefile.build
built-in.o : $(cur_objs) $(subdir_objs)
$(LD) -r -o $@ $^
dep_file = .$@.d
%.o : %.cpp
$(CPP) $(CFLAGS) -Wp,-MD,$(dep_file) -c $< -o $@
.PHONY : $(PHONY)
各级子目录的Makefile
它最简单,形式如下:
obj-y += file.o
obj-y += subdir/
“obj-y += file.o”表示把当前目录下的file.c编进程序里,
“obj-y += subdir/”表示要进入subdir这个子目录下去寻找文件来编进程序里,是哪些文件由subdir目录下的Makefile决定。
注意: “subdir/”中的斜杠”/”不可省略
CROSS_COMPILE = mipsel-openwrt-linux-uclibc-
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP
CFLAGS := -Wall -O2 -g
CFLAGS += -I./ -I../sys
LDFLAGS := -lm -lrt -ldl
export CFLAGS LDFLAGS
TOPDIR := $(shell pwd)
export TOPDIR
obj-y += spi.o
all :
make -C ./ -f $(TOPDIR)/Makefile.build
$(CPP) $(LDFLAGS) -o built-in.o
clean:
rm -f $(shell find -name "*.o")
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")