makefile--参数传递、条件判断、include(五)
在多个Makefile嵌套调⽤时,有时我们需要传递⼀些参数给下⼀层Makefile。⽐如我们在顶层Makefile⾥⾯定义的打开调试信息变量DEBUG_SYMBOLS,我们希望在进⼊⼦⽬录执⾏⼦Makefile时该变量仍然有效,这是需要将该变量传递给⼦Makefile,那怎么传递呢?这⾥有两种⽅法:
1.    在上层Makefile中使⽤”export”关键字对需要传递的变量进⾏声明。⽐如:
1 2DEBUG_SYMBOLS = TRUE export DEBUG_SYMBOLS
当不希望将⼀个变量传递给⼦ make 时,可以使⽤指⽰符 “unexport”来声明这个变量。
export⼀般⽤法是在定义变量的同时对它进⾏声明。如下:
1export DEBUG_SYMBOLS = TRUE
2.    在命令⾏上指定变量。⽐如:
1$(MAKE) -C xxx DEBUG_SYMBOLS = TRUE
这样在进⼊⼦⽬录xxx执⾏make时该变量也有效。
像编程语⾔⼀样,Makefile也有⾃⼰的条件语句。条件语句可以根据⼀个变量值来控制make的执⾏逻辑。⽐较常⽤的条件语句是ifeq –else-endif、ifneq-else-endif、ifdef-else-endif。
ifeq关键字⽤来判断参数是否相等。
⽐如判断是否⽣成调试信息可以这么⽤:
1 2 3 4 5 6ifeq ($(DEBUG_SYMBOLS), TRUE) >---CFLAGS += -g -Wall -Werror -O0 else
>---CFLAGS += -Wall -Werror -O2 endif
Ifneq和ifeq作⽤相反,此关键字是⽤来判断参数是否不相等。
ifdef关键字⽤来判断⼀个变量是否已经定义。
后两个关键字⽤法和ifeq类似。
现在我们继续改进我们上⼀节的Makefile,上⼀节的Makefile完成Makefile的嵌套调⽤,每⼀个模块都有⾃⼰的Makefile。其实每个模块的Makefile都⼤同⼩异,只需要改改最后编译成⽣成的⽬标名称或者编译链接选项,规则都差不多,那么我们是否可以考虑将规则部分提取出来,每个模块只需修改各⾃
变量即可。这样是可⾏的,我们将规则单独提取出来,写⼀个Makefile.rule,将他放在顶层Makefile同⽬录下,其他模块内部的Makefile只需要include该Makefile就可以了。如下:
1include $(SRC_BASE)/Makefile.rule
include类似于C语⾔的头⽂件包含,你把它理解为为本替换就什么都明⽩了。
这样以后规则有修改的话我们直接修改该Makefile就可以了,就不⽤进⼊每⼀个模块去修改,这样也便于维护。
这样我们今天顶层Makefile稍作修改:
1
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20# Top Makefile for C program                                                                                                                                                              # Copyright (C) 2014 shallnew \at 163 \dot com
export DEBUG_SYMBOLS = TRUE
DIR = src
MODULES = $(shell ls $(DIR))
# MODULES = ipc main tools
all : $(MODULES)
$(MODULES):
>---$(MAKE) -C $(DIR)/$@
main:tools ipc
clean :
>---@for subdir in$(MODULES); \
>---do$(MAKE) -C $(DIR)/$$subdir $@; \
>---done
20
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45distclean:
>---@for subdir in$(MODULES); \
>---do$(MAKE) -C $(DIR)/$$subdir $@; \
>---done
tags:
>---ctags -R
help:
>---@echo "===============A common Makefilefor c programs=============="
>---@echo "Copyright (C) 2014 liuy0711 \at 163\dot com"
>---@echo "The following targets aresupport:"
>---@echo
>---@echo " all              - (==make) compile and link"
>---@echo " clean            - clean target"
>---@echo " distclean        - clean target and otherinformation"
>---@echo " tags            - create ctags for vimeditor"
>---@echo " help            - print help information"
>---@echo
>---@echo "To make a target, do 'make[target]'"
>---@echo "========================= Version2.2 =======================" .PHONY : all clean distclean tags help
⽬前我们顶层⽬录下的⽬录树为:
1 2 3 4 5 6 7 8 9 10 11SRC_BASE = ../..
CFLAGS +=
CPPFLAGS += -I. -I./inc -I$(SRC_BASE)/include  # SRC_OBJ = $(patsubst %.c, %.o, $(wildcard *.c))  SRC_FILES = $(wildcard src/*.c)
SRC_OBJ = $(SRC_FILES:.c=.o)
SRC_LIB = libtools.a
include $(SRC_BASE)/Makefile.rulemakefile phony
⽽处于顶层⽬录下的Makefile.rule专门处理各模块编译链接时需要的规则。内容如下:1
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27# Copyright (C) 2014 shallnew \at 163 \dot com                                                                                                                                            ifeq ($(DEBUG_SYMBOLS), TRUE)
>---CFLAGS += -g -Wall -Werror -O0
else
>---CFLAGS += -Wall -Werror -O2
endif
all : $(SRC_BIN) $(SRC_LIB)
ifneq ($(SRC_BIN),)
$(SRC_BIN) : $(SRC_OBJ)
>---$(CC) -o $@ $^ $(LDFLAGS)
endif
ifneq ($(SRC_LIB),)
$(SRC_LIB) : $(SRC_OBJ)
>---$(AR) rcs $@ $^
>---cp $@ $(SRC_BASE)/libs
endif
# clean target
clean:
>---$(RM) $(SRC_OBJ) $(SRC_LIB) $(SRC_BIN)$(SRC_BIN).exe
distclean:
>---$(RM) $(SRC_OBJ) $(SRC_LIB) $(SRC_BIN)$(SRC_BIN).exe $(SRC_BASE)/libs/* $(SRC_BASE)/tags *~
.PHONY : all clean disclean
27
28
29
.PHONY : all clean disclean
我们将Makefile.rule放在顶层有可能会⼀不⼩⼼在命令⾏上⾯执⾏了该Makefile,如下:
1 2 3# make -f Makefile.rule
make: Nothing tobe done for`all'.  #
在make⾥⾯有这样⼀个变量:MAKELEVEL,它在多级调⽤的 make 执⾏过程中。变量代表了调⽤的深度。在 make ⼀级级的执⾏过程中变量MAKELEVEL的值不断的发⽣变化,通过它的值我们可以了解当前make 递归调⽤的深度。顶层的MAKELEVEL的值为“0” 、下⼀级时为“1” 、再下⼀级为“2”.......,所以我们希望⼀个⼦⽬录的Makefile必须被上层 make 调⽤才可以执⾏,⽽不允许直接执⾏,我们可以判断变量MAKELEVEL来控制。所以我们这⼀节最终的Makefile.rule为:
1
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36# Copyright (C)2014 shallnew \at 163 \dot com
ifeq ($(DEBUG_SYMBOLS),TRUE)
>---CFLAGS +=-g -Wall -Werror -O0
else
>---CFLAGS +=-Wall -Werror -O2
endif
ifeq($(MAKELEVEL), 0)                                                                                                                                                                    all : msg
else
all : $(SRC_BIN)$(SRC_LIB)
endif
ifneq ($(SRC_BIN),)
$(SRC_BIN) :$(SRC_OBJ)
>---$(CC) -o $@$^ $(LDFLAGS)
endif
ifneq($(SRC_LIB),)
$(SRC_LIB) :$(SRC_OBJ)
>---$(AR) rcs$@ $^
>---cp $@$(SRC_BASE)/libs
endif
msg:
>---@echo"You cannot directily execute this Makefile! This Makefile should calledby toplevel Makefile."
# clean target
clean:
>---$(RM)$(SRC_OBJ) $(SRC_LIB) $(SRC_BIN) $(SRC_BIN).exe
distclean:
>---$(RM)$(SRC_OBJ) $(SRC_LIB) $(SRC_BIN) $(SRC_BIN).exe $(SRC_BASE)/libs/*$(SRC_BASE)/tags *~
.PHONY : all cleandisclean
此时再直接执⾏该Makefile:
1 2 3# make -f Makefile.rule
You cannot directily execute this Makefile! This Makefile should called by toplevel Makefile. #

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。