公用规则用升级版[3]Makefile 适用于中大型工程
一.目录一览:
[user:公用规则用升级版[3]Makefile] tree
.
├── app_dev
│ ├── app_dev.i386.elf
│ ├── build
│ │ ├── arm
│ │ │ ├── libapp_dev.arm.a
│ │ │ ├── main.arm.d
│ │ │ ├── main.arm.o
│ │ │ ├── printEnd.arm.d
│ │ │ ├── printEnd.arm.o
│ │ │ ├── printStart.arm.d
│ │ │ └── printStart.arm.o
│ │ └── i386
│ │ ├── libapp_dev.i386.a
│ │ ├── main.i386.d
│ │ ├── main.i386.o
│ │ ├── printEnd.i386.d
│ │ ├── printEnd.i386.o
│ │ ├── printStart.i386.d
│ │ └── printStart.i386.o
│ ├── main.cpp
│ ├── Makefile
│ ├── printEnd.cpp
│ ├── printEnd.h
│ ├── printStart.cpp
│ └── printStart.h
├── lib_hdmanage
│ ├── build
│ │ ├── arm
│ │ │ ├── echoInt.arm.d
│ │ │ ├── echoInt.arm.o
│ │ │ ├── echoString.arm.d
│ │ │ ├── echoString.arm.o
│ │ │ └── libhdmanage.arm.a
│ │ └── i386
│ │ ├── echoInt.i386.d
│ │ ├── echoInt.i386.o
│ │ ├── echoString.i386.d
│ │ ├── echoString.i386.o
│ │ └── libhdmanage.i386.a
│ ├── echoInt.cpp
│ ├── echoInt.h
│ ├── echoString.cpp
│ ├── echoString.h
│ └── Makefile
├── lib_pub
│ ├── add.cpp
│ ├── add.h
│ ├── build
│ │ ├── arm
│ │ │ ├── add.arm.d
│ │ │ ├── add.arm.o
│ │ │ ├── del.arm.d
│ │ │ ├── del.arm.o
│ │ │ └── libpub.arm.a
│ │ └── i386
│ │ ├── add.i386.d
│ │ ├── add.i386.o
│ │ ├── del.i386.d
│ │ ├── del.i386.o
│ │ └── libpub.i386.a
│ ├── del.cpp
│ ├── del.h
│ └── Makefile
├── Makefile
└── makefiles
├── common.mk
└── rules.mk
13 directories, 54 files
二.Makefile文件详情:
1.顶层Makefile:
[user:公用规则用升级版[3]Makefile] cat Makefile
TOP_DIR = $(realpath .)
-include $(TOP_DIR)/makefiles/common.mk
lib_list += lib_pub
lib_list += lib_hdmanage
lib_list += app_dev
link_libs += $(addsuffix /$(BUILD_NAME)/$(ARCH),$(addprefix -L$(TOP_DIR)/,$(lib_list)))
link_libs += $(addsuffix .$(ARCH), $(addprefix -l, $(subst lib_,,$(lib_list))))
.PHONY: all clean
all:
$(call make_in_list, $(lib_list), all)
$(CPP) app_dev/main.cpp $(link_libs) -o app_dev/$(TARGET)
clean:
$(call make_in_list, $(lib_list), clean)
[user:公用规则用升级版[3]Makefile]
2.app_dev目录的Makefile:
[user:公用规则用升级版[3]Makefile] cat app_dev/Makefile
TOP_DIR = $(realpath ..)
-include $(TOP_DIR)/makefiles/common.mk
.PHONY: all clean
all: ar_lib
clean: clear
# @[ $(debug) -eq 1 ] && echo "$(CUR_DIR):clean"
# include原理:分两步:1)先把外面的makefile从上到下加载插入到文件中(相当于预编译);
# 2) 如果插入的是变量,就当成目标从下到上运行(运行).
-include $(TOP_DIR)/makefiles/rules.mk
3.lib_hdmanage目录的Makefile:
[user:公用规则用升级版[3]Makefile] cat lib_hdmanage/Makefile
TOP_DIR = $(realpath ..)
-include $(TOP_DIR)/makefiles/common.mk
.PHONY: all clean
all: ar_lib
clean: clear
# @[ $(debug) -eq 1 ] && echo "$(CUR_DIR):clean"
# include原理:分两步:1)先把外面的makefile从上到下加载插入到文件中(相当于预编译);
# 2) 如果插入的是变量,就当成目标从下到上运行(运行).
-include $(TOP_DIR)/makefiles/rules.mk
4.lib_pub目录的Makefile:
[user:公用规则用升级版[3]Makefile] cat lib_pub/Makefile
TOP_DIR = $(realpath ..)
-include $(TOP_DIR)/makefiles/common.mk
.PHONY: all clean
all: ar_lib
clean: clear
# @[ $(debug) -eq 1 ] && echo "$(CUR_DIR):clean"
# include原理:分两步:1)先把外面的makefile从上到下加载插入到文件中(相当于预编译);
# 2) 如果插入的是变量,就当成目标从下到上运行(运行).
-include $(TOP_DIR)/makefiles/rules.mk
5.makefiles目录的Makefile (精华都在这里,重点看)
1) 公用变量Makefile
[user:公用规则用升级版[3]Makefile] cat makefiles/common.mk
###################### 编译设置 ###############################
debug = 1
ifeq ($(ARCH),arm)
ARCH = arm
CROSS = arm-linux-
else
ARCH = i386
CROSS =
endif
TARGET=app_dev.$(ARCH).elf
CC = $(CROSS)gcc
CPP = $(CROSS)g++
AR = $(CROSS)ar
####################### 文件结构 ##############################
CUR_DIR=$(realpath .)
BUILD_NAME=build
BUILD_PATH=$(CUR_DIR)/$(BUILD_NAME)/$(ARCH)
SRCS=$(wildcard *.cpp)
OBJS=$(addprefix $(BUILD_PATH)/,$(filter-out main.o, $(SRCS:.cpp=.$(ARCH).o)))
DEPS=$(addprefix $(BUILD_PATH)/,$(SRCS:.cpp=.$(ARCH).d))
LNAME=$(subst lib_,,$(shell basename $(CUR_DIR)))
LPATH=$(BUILD_PATH)/lib$(LNAME).$(ARCH).a
##################### shell 函数 #############################
make_in_list = for dir in $(1);do make $(2) -C $$dir || exit 1;done
2) 公用规则Makefile
[user:公用规则用升级版[3]Makefile] cat makefiles/rules.mk
init: $(BUILD_PATH)
$(BUILD_PATH):
# @[ $(debug) -eq 1 ] && echo "@mkdir -p $@"
@mkdir -p $@
clear:
# @[ $(debug) -eq 1 ] && echo "$(CUR_DIR):clear"
@rm *.a *.d* *.o *.elf -rf
@rm $(BUILD_PATH) -rf
ar_lib:$(OBJS)
$(AR) crs $(LPATH) $^
#这依赖关系如果改成"$(OBJS):%.$(ARCH).o:%.cpp",.o和.cpp的路径就一致了,所以不能改
$(BUILD_PATH)/%.$(ARCH).o : %.cpp
@[ $(debug) -eq 1 ] && echo "$<"
@[ $(debug) -eq 1 ] && echo "$@"
$(CPP) -c $< -o $@
#这依赖关系如果改成"$(DEPS):%.$(ARCH).d:%.cpp",.d和.cpp的路径就一致了,所以不能改
$(BUILD_PATH)/%.$(ARCH).d : %.cpp
# @[ $(debug) -eq 1 ] && echo "$@";
@rm $@ -rf; \
$(CPP) -MM $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm $@.$$$$ -rf
auto_deps = 0
ifeq (,$(MAKECMDGOALS))
auto_deps = 1
else ifeq (all, $(findstring all, $(MAKECMDGOALS)))
auto_deps = 1
endif
ifeq (1, $(auto_deps))
-include $(DEPS)
endif
# include <file or value> file 或 目标越的Makefile的下面就越先执行,所以init要比$(DEPS)先运行
-include init
[user:公用规则用升级版[3]Makefile]
其它函数的实现,自已可以写个简单例子。具体可参考Makefile学习第一步(简单Makefile)的例子