【版权声明:转载请保留出处:http://blog.csdn.net/shallnet/article/details/37657597?utm_source=tuicool&utm_medium=referral】

在多个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 comexport DEBUG_SYMBOLS = TRUEDIR = src
MODULES = $(shell ls $(DIR))
# MODULES = ipc main toolsall : $(MODULES)$(MODULES):
>---$(MAKE) -C $(DIR)/$@main:tools ipcclean :
>---@for subdir in $(MODULES); \
>---do $(MAKE) -C $(DIR)/$$subdir $@; \
>---donedistclean:
>---@for subdir in $(MODULES); \
>---do $(MAKE) -C $(DIR)/$$subdir $@; \
>---donetags:
>---ctags -Rhelp:
>---@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

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

.
├── include
│   ├── common.h
│   ├── ipc
│   │   └── ipc.h
│   └── tools
│      ├── base64.h
│      ├── md5.h
│      └── tools.h
├── libs
├── Makefile
├── Makefile.rule
└── src├── ipc│  ├──inc│  ├──Makefile│  └──src│    └── ipc.c├── main│  ├──inc│  ├──Makefile│  └──src│      ├── main.c│     └── main.c~└── tools├── inc├── Makefile└── src├── base64.c├── md5.c└── tools.c14 directories, 16 files

每个子模块下的Makefile删除规则后修改为如下:

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.ainclude $(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
endifall : $(SRC_BIN) $(SRC_LIB)ifneq ($(SRC_BIN),)
$(SRC_BIN) : $(SRC_OBJ)
>---$(CC) -o $@ $^ $(LDFLAGS)
endififneq ($(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).exedistclean:
>---$(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'.
#

由于我们没有定义变量$(SRC_BIN)和$(SRC_LIB),伪目标all没有任何依赖,所以编译是无法成功的。这里我们我们应该禁止直接执行该Makefile。

在make里面有这样一个变量:MAKELEVEL,它在多级调用的 make 执行过程中。变量代表了调用的深度。在 make 一级级的执行过程中变量MAKELEVEL的值不断的发生变化,通过它的值我们可以了解当前make 递归调用的深度。顶层的MAKELEVEL的值为“0” 、下一级时为“1” 、再下一级为“2”.......,所以我们希望一个子目录的Makefile必须被上层 make 调用才可以执行,而不允许直接执行,我们可以判断变量MAKELEVEL来控制。所以我们这一节最终的Makefile.rule为:

# Copyright (C)2014 shallnew \at 163 \dot comifeq ($(DEBUG_SYMBOLS),TRUE)
>---CFLAGS +=-g -Wall -Werror -O0
else
>---CFLAGS +=-Wall -Werror -O2
endififeq($(MAKELEVEL), 0)
all : msg
else
all : $(SRC_BIN)$(SRC_LIB)
endififneq ($(SRC_BIN),)
$(SRC_BIN) :$(SRC_OBJ)
>---$(CC) -o $@$^ $(LDFLAGS)
endififneq($(SRC_LIB),)
$(SRC_LIB) :$(SRC_OBJ)
>---$(AR) rcs$@ $^
>---cp $@$(SRC_BASE)/libs
endifmsg:
>---@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).exedistclean:
>---$(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中的条件判断(ifeq、ifneq、ifdef、ifndef)

    以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除. 一.条件判断的关键字 日常使用 Makefile 编译文件时,可能会遇到需要分条件执行的情况.比如在一个工程文件中可编译的源文件很多 ...

  2. 从头開始写项目Makefile(三):变量的使用

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu. Mail:shallnew at 163 dot com] 细致研究我们的之前Makefile发现.我们还有改进的地方.就 ...

  3. makefile条件判断语句和函数

    1.makefile中支持条件判断语句 可以根据条件的值来决定make的执行 可以比较两个不同变量或者变量和常量值 ifxxx(arg1,arg2)elseendif 注意事项:条件判断语句只能用于控 ...

  4. 【Makefile由浅入深完全学习记录8】条件判断语句

    加qq:1126137994 微信:liu1126137994 一起学习更多技术~ 今天来学习Makefile中条件判断语句! Makefile也算是一门语言,它有自己的语法,那么它应该也会像C/C+ ...

  5. 【Linux学习009】脚本编程之变量、条件测试和条件判断

    一.Bash环境变量 bash中变量有四种种类型:环境变量.本地变量(局部变量).位置变量.特殊变量. 1.环境变量 环境变量作用范围最广,所有子bash进程都能够访问环境变量中的值,定义环境变量的方 ...

  6. 判断参数大于0_能做条件判断的文本函数

    我们知道文本函数的一般作用就是查找.替换.提取文本等等,可是能做条件判断的文本函数你见过吗?不仅如此,它还可以让日期变数字.数字变大写.金额变万元等等.说到这里,屏幕前的小伙伴有猜到它是谁吗? 在Ex ...

  7. wx:if 多条件判断

    wx:if 多条件判断 <view wx:if="{{condition}}">单个条件</view> <view wx:if="{{con ...

  8. 雷观(十六):帮人写项目,不如教会别人写项目的方法

    2019独角兽企业重金招聘Python工程师标准>>> 前段时间,有个潜在客户,想付钱,让我帮他写个简单的项目,最后还是被我委婉地拒绝了. 情况是这样的,这名网友还在读大学,刚来到一 ...

  9. 2022成都市专利培育中心项目资助申报主体条件条件及资助标准

    2022成都市专利培育中心项目资助申报主体条件条件及资助标准的相关信息已经整理好了,希望能给您企业申报高企奖补带来帮助,正在尽力收集所有四川的高新技术企业政策及其他惠企政策,在申报中有任何疑问都可以来 ...

  10. 【创新基金项目可行性报告】如何写项目可行性报告/项目申报文档

    最近在知乎上回答了一个问题,关于国家/省创新基金项目可行性项目报告的撰写,以及创新基金的申请. 情况介绍: 1. 国家级创新项目      国家级的申请比较严,审批项目都是两院院士及国家级专家,一群五 ...

最新文章

  1. R语言使用integrate函数进行函数积分计算实战
  2. 学Linux的你还在为正则表达式而挠头?
  3. Persona 动画编辑器参考
  4. [NOIP模拟测试3] 建造游乐园 题解(欧拉图性质)
  5. 西游之路——python全栈——上传文件
  6. 移动互联网时代: 妈,我回不去了
  7. 汇编 编程实现从键盘输入三位以内的十进制负数_macOS上的汇编入门(二)——数学基础...
  8. IT项目管理需要注意的细节
  9. 安卓SQLiteOpenHelper使用说明
  10. 概率论 一维随机变量
  11. mcp证书有什么用_建造师的行情怎么样呢?建造师证书有什么用?
  12. 华为跨域bgp_通知:2019华为认证体系全新升级!
  13. dotnetNuke module development steps, dnn 模块开发步骤
  14. nuget包循环引用问题
  15. static library libs/libvpx/libvpx.a is not portable!
  16. matlab程序转成可执行文件,matlab程序如何生成可执行文件
  17. 江南大学c语言课程绩点评分,江南大学无锡医学院课程考核档案管理办法
  18. android闪光灯测心率,MIUI 12新功能来了,通过闪光灯测心率,支持全部机型
  19. JavaFX入门(五):使用CSS样式美化你的UI控件
  20. 方法调用机制内存分析★

热门文章

  1. 第二十四节(Java文件流,缓冲流)
  2. java生成随机验证图片的实现
  3. KVM通过qemu实现USB重定向
  4. C# 将数据导出到Excel汇总(转)
  5. android开发歌词滑动效果_一些Flutter开发中的“坑”
  6. 【微服务直播】60分钟掌握微服务治理之道
  7. 【15】万魂杀服务器开发之原始NIO、Mina、Netty使用
  8. 运维基础--虚拟机的使用(一)
  9. 前端内容占位技术分享
  10. 分享:BlackHole开发日记-Java守护进程、Signal处理