makefile 使用举例

甲. 让make 每次都执行特定的命令

例子:

all:
	date

说明:

  1. all 是第一个目标,所以成为默认的目标.DEFAULT_GOAL
  2. 由于all文件不存在,所以必须重新制作目标all,制作的方法是,执行date命令

乙. 让make 每次都更新文件

例子: 热热身.
假如文件名是test.txt,
每次执行make都更新test.txt
最简单写法当然是:

all:
	date > test.txt

但是, 为了增强功能,这里决定要使用宏, 例如把文件名用一个宏变量来表示.
同时引入依赖, 这样更便于控制, 用以判断是否需要更新.

file = test.txt
all: $(file)

$(file) :
	date > $@

分析: 上述写法,

  1. all依赖于$(file), 生成all的配方是空, 所以对"all"无需做任何事
  2. 生成$(file)的配方是执行date 命令.
  3. 如果$(file)已经存在, 则不必在执行配方命令.
  4. 如果想让$(file)每次都更新,可以让它依赖于一个伪目标,如下示例
file = test.txt
all: $(file)

$(file) : FORCE
	date > $@
.PHONY FORCE

说明:

  1. 由于FORCE是不存在的,所以必须重新制作FORCE,但FORCE 是伪目标,所以总是可以制作成功.
  2. FORCE 更新了,所以要更新$(file), 其处方是date 命令, 所以$(file)被更新.

丙. 让make 每次都判断,更新版本文件version.h

例子: 来源于linux Makefile, 有自己的更改,我们考察一些其中的一些概念.
当makefile 中三个变量改变的时候,就会更新version.h, version.h 就是这三个变量的变体.
如果3个变量没有改变,则不必更新version.h,保留旧的时间戳.

VERSION = 2
PATCHLEVEL = 3
SUBLEVEL = 1

# filechk 用来检查产生的文件内容是否需要更新
# 使用:
#	$(call filechk,sample)
# 实现:
# 定义的规则会输出到新文件
# 存在的文件会与新文件比较
# - 如果 旧文件不存在,使用新文件
# - 如果 旧文件和新文件内容不同,使用新闻界
# - 如果 旧文件和新文件内容相同,使用旧文件,这样时间戳就不会改变.
define filechk
	@set -e;				\
	echo '  CHK     $@';		\
	mkdir -p $(dir $@);			\
	$(create_$(1)) > $@.new;		\
	if [ -r $@ ] && cmp -s $@ $@.new; then	\
	rm -f $@.new;			\
	else					\
	echo '  UPD     $@';	\
	mv -f $@.new $@;		\
	fi
endef

# 该函数向屏幕输出 "版本信息", Makefile 竟能直接调用 shell 函数?!
define create_version.h
(echo \#define LINUX_VERSION_CODE $(shell expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \
 echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef


.PHONY: FORCE
version.h: FORCE
	$(call filechk,version.h)

说明,

  1. 定义了2个函数,filechk, filechk_version.h
  2. filechk_version.h 只是简单的向控制台输出两行 define 字符串. 可被重定向生成version.h
  3. filechk 函数, 比较两个文件是否相同并决定是否替换文件.
    set -e 表示执行出错时立即退出
    调用了filechk_version.h 并把输出重定向到文件
    调用了cmp 程序,比较两个文件的内容,相同则保留旧的,不同则替换旧的.

当你把主版本号, 或次版本号,build 号一改, 生成的文件与原文件不同,就替换原来的文件了.
Makefile 中命令语句就是tab 开头的 shell 命令.

Makefile 中定义的命令包又与纯bash_script 有区别, 例如$() 在bash中是执行命令而不是变量引用, ${}是变量引用, 无shell 命令, dir 与这里的
dir 含义不同, 在这里写的命令包难以跟踪,难以调试, 最好别用!!!

另一种写法,供参考

VERSION = 2
PATCHLEVEL = 3
SUBLEVEL = 1
VERSTR=$(shell printf "0x%x" $$((($(VERSION)<<16)+($(PATCHLEVEL)<<8)+$(SUBLEVEL))))

define filechk
	@set -e;				\
	echo '  CHK     $@';		\
	$(filechk_$(1)) > $@.tmp;		\
	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
	rm -f $@.tmp;			\
	else					\
	echo '  UPD     $@';	\
	mv -f $@.tmp $@;		\
	fi
endef

define filechk_version.h
(echo '#define KERNEL_VERSION(a,b,c) (a << 16) + (b << 8) + (c))'; \
echo '#define KERNEL_VERSION' $(VERSTR); \
)
endef

.PHONY: FORCE
version.h: FORCE
	$(call filechk,version.h)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值