原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/

在多个Makefile嵌套调用时,有时我们需要传递一些参数给下一层Makefile。比如我们在顶层Makefile里面定义的打开调试信息变量 DEBUG_SYMBOLS,我们希望在进入子目录执行子Makefile时该变量仍然有效,这是需要将该变量传递给子Makefile,那怎么传递呢? 这里有两种方法:
1.     在上层Makefile中使用”export”关键字对需要传递的变量进行声明。比如:

    DEBUG_SYMBOLS = TRUE
export DEBUG_SYMBOLS

当不希望将一个变量传递给子 make 时,可以使用指示符 “unexport”来声明这个变量。
export一般用法是在定义变量的同时对它进行声明。如下:

export DEBUG_SYMBOLS = TRUE

2.     在命令行上指定变量。比如:

$(MAKE) -C xxx DEBUG_SYMBOLS = TRUE

这样在进入子目录xxx执行make时该变量也有效。
像编程语言一样,Makefile也有自己的条件语句。条件语句可以根据一个变量值来控制make的执行逻辑。比较常用的条件语句是ifeq –else-endif、ifneq-else-endif、ifdef-else-endif。
ifeq关键字用来判断参数是否相等。
比如判断是否生成调试信息可以这么用:

    ifeq ($(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就可以了。如下:

include $(SRC_BASE)/Makefile.rule

include类似于C语言的头文件包含,你把它理解为为本替换就什么都明白了。
这样以后规则有修改的话我们直接修改该Makefile就可以了,就不用进入每一个模块去修改,这样也便于维护。
这样我们今天顶层Makefile稍作修改:

# 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 distclean:
>---@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

目前我们顶层目录下的目录树为:

   SRC_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.rule

而处于顶层目录下的Makefile.rule专门处理各模块编译链接时需要的规则。内容如下:

   # 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

我们将Makefile.rule放在顶层有可能会一不小心在命令行上面执行了该Makefile,如下:

  # 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为:

    # 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:

        # make -f Makefile.rule
You cannot directily execute this Makefile! This Makefile should called by toplevel Makefile.
#

makefile--参数传递、条件判断、include (五)的更多相关文章

  1. [转] Makefile 基础 (6) —— Makefile 使用条件判断

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

  2. Linux makefile教程之条件判断六[转]

    使用条件判断 —————— 使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支.条件表达式可以是比较变量的值,或是比较变量和常量的值. 一.示例 下面的例子,判断$(CC)变量是否“g ...

  3. Makefile学习(二)条件判断和内嵌函数

    第七章:Makefile的条件执行 条件语句可是是两个不同的变量.或者变量和常量值的比较: 7.1例子: 对变量“CC”进行判断,其值如果是“gcc ”那么在程序连接时使用库“libgnu.so”或者 ...

  4. makefile笔记6 - makefile条件判断

    使用条件判断,可以让 make 根据运行时的不同情况选择不同的执行分支.条件表达式可以是比较变量的值,或是变量和常量的值. 一.示例 下面的例子,判断\(\$\)(CC)变量是否"gcc&q ...

  5. Ruby自学笔记(五)— 条件判断

    条件判断,在编程语言中都存在,而Ruby中的条件判断和Java中类似,当然还是存在些许差别 Ruby中条件判断的条件: 1) 可以使用 ==,<,>等比较运算来作为条件,比较运算可以返回t ...

  6. python笔记五(条件判断/循环/break和continue)

    一 条件判断 if <条件判断1>: <执行1> elif <条件判断2>: <执行2> elif <条件判断3>: <执行3> ...

  7. shell基础篇(五)条件判断

    写脚本时:有时要判断字符串是否相等,数字测试.这对后面学习的shell语句,循环,条件语句做好基础. 条件判断格式  1. test condition : test命令  2. [ conditio ...

  8. Python 入门(五)条件判断和循环

    if语句 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,可以用if语句实现: age = 20 if age > ...

  9. 五、Angular定义字段、绑定字段、获取数据、对象获取数据、*ngFor循环获取数据,自定义方法、*ngIf条件判断、双向数据绑定

    1.定义属性 2.绑定属性.绑定html中 3.循环获取数据 编写的时候没有注意,第二个循环 i 需要改成 {{i}} ,这样才会显示 出效果 4.自定义方法 变量名截图省略 5.*ngIf条件判断 ...

  10. python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器

    python3.5 manage.py runserver python Django教程 之模板渲染.循环.条件判断.常用的标签.过滤器 一.Django模板渲染模板 1. 创建一个 zqxt_tm ...

随机推荐

  1. SpringCloud重试机制配置

    SpringCloud重试retry是一个很赞的功能,能够有效的处理单点故障的问题.主要功能是当请求一个服务的某个实例时,譬如你的User服务启动了2个,它们都在eureka里注册了,那么正常情况下当 ...

  2. servlet的编码原理

    编码问题: 在介绍编码问题前,先介绍一下java平台(JVM)上的编码转化情况.首先要说明的一点,在JVM中,即java平台上,运行的程序一定都是Unicode编码方式的.对于代码中的字符串常量,根据 ...

  3. CPAN镜像使用帮助

    https://lug.ustc.edu.cn/wiki/mirrors/help/cpan ************************************************** 使用 ...

  4. Web应用程序开发的标准架构

  5. Python中的画图初体验

    学到<父与子编程之旅>的16章了,跟书上的例子进行学习,学会了画圆,我又找到了画线的方法,于是就可以在screen上画日本国旗了: 手动画的不好看,也可以不手动画,直接画线: 当然也可以直 ...

  6. 设置将Maven的jar包发布到lib

    2,设置将Maven的jar包发布到lib下. Add -> Java Build Path Entries -> Maven Dependencies -> Finish 设置完成 ...

  7. 人工智能时代,应立即学习python

    人工智能时代,应立即学习python 应用:web开发,自动化运维开发,自动化测试,数据分析,机器学习 1.python 快速易学习2.python 基于web开发(zhihu:tornad web框 ...

  8. php7+apache2.4 安装(window)

    一.下载 需要下载 php7.apache2.4.vc2015(VC库) PHP7下载地址:http://windows.php.net/download/ Apache 下载地址:https://h ...

  9. 核心交换机各项配置 Vlan划分、互访、ACL管控、链路聚合等

    #!Software Version V200R001C00SPC300sysname IT_ServerRoom  #交换机名称##vlan batch 10 20 30 40 50 60 70 8 ...

  10. CMake 用法导览

    Preface : 本文是CMake官方文档CMake Tutorial (http://www.cmake.org/cmake/help/cmake_tutorial.html) 的翻译.通过一个样 ...