Makefile规则的问题

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Makefile规则的问题

#1

帖子 tosail2010 » 2011-06-29 16:10

当前目录中的makefile,有一段如下:
###########################

代码: 全选

.PHONY:sample
sample:
	make -C $(SAMPLE_DIR)
sample_clean:
	make -C $(SAMPLE_DIR) clean
############################
在子目录sample中,子makefile,有一段内容如下:

代码: 全选

target:=$(firstword $(MAKECMDGOALS))

.PHONY:$(target)

ifeq ($(target), all)
	target=./
endif

ifeq ($(target), clean)
	target=
endif
$(target):
	echo $(target)
	echo $(MAKECMDGOALS)
	make -C $(MAKECMDGOALS)
all:
	make -C xxxxx
	make -C xxxxx
clean:
	make -C xxxxx clean
	make -C xxxxx clean
############################

##################################
///////////////////////////////////////////////////////
当我在当前目录下,运行make sample时,执行的是如下的规则

代码: 全选

all:
make -C xxxxx
make -C xxxxx
当我在当前目录下,运行make sample_clean时,执行的是如下的规则

代码: 全选

clean:
make -C xxxxx clean
make -C xxxxx clean
我有几个疑惑点,
1)在执行make sample时,target值是sample吗?
2)感觉下面的规则没有用

代码: 全选

.PHONY:$(target)

ifeq ($(target), all)
	target=./
endif

ifeq ($(target), clean)
	target=
endif
$(target):
	echo $(target)
	echo $(MAKECMDGOALS)
	make -C $(MAKECMDGOALS)
还是我理解的有问题。
上次由 tosail2010 在 2011-06-30 10:17,总共编辑 2 次。
A year's plan starts with spring.
MaskRay
帖子: 61
注册时间: 2010-04-29 22:00
系统: Gentoo Linux ~amd64
联系:

Re: Makefile规则的问题

#2

帖子 MaskRay » 2011-06-29 16:25

你加上 code 吧,tab 都被吃掉了
头像
lexdene
帖子: 434
注册时间: 2010-02-21 16:19
来自: 大连
联系:

Re: Makefile规则的问题

#3

帖子 lexdene » 2011-06-29 16:37

好长哦。
mark一下。
有空回来看。
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Re: Makefile规则的问题

#4

帖子 tosail2010 » 2011-06-29 16:42

MaskRay 写了:你加上 code 吧,tab 都被吃掉了
OKay
A year's plan starts with spring.
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Re: Makefile规则的问题

#5

帖子 tosail2010 » 2011-06-30 10:43

翻了翻makefile的资料,对于自己的提问找到了部分答案。
1)在当前目录下输入make sample,执行的是makefile中命令 make -C $(SAMPLE_DIR)
,此时会进入sample 目录,执行目录下的子makefile。
target值为空。运行目标名为all 下的所有命令。

2)这个规则还是有用的,但有一点我不明白
如果将代码作如下改动:
情况1)

代码: 全选

.PHONY:sample
sample:
   make -C $(SAMPLE_DIR) all
sample_clean:
   make -C $(SAMPLE_DIR) clean
情况2)

代码: 全选

.PHONY:sample
sample:
   make -C $(SAMPLE_DIR) clean
sample_clean:
   make -C $(SAMPLE_DIR) clean
对应情况1)

代码: 全选

ifeq ($(target), all)
   target=./
endif
上述代码会执行,
对应情况2)
ifeq ($(target), clean)
target=
endif
上述代码会执行。

情况1)和情况2)target被赋不同的值,出于什么目的?(抠细点)
大家发表看法呀。
A year's plan starts with spring.
头像
lexdene
帖子: 434
注册时间: 2010-02-21 16:19
来自: 大连
联系:

Re: Makefile规则的问题

#6

帖子 lexdene » 2011-06-30 11:59

怀疑和rm有关。
线索太少,看不出什么东西来。
MaskRay
帖子: 61
注册时间: 2010-04-29 22:00
系统: Gentoo Linux ~amd64
联系:

Re: Makefile规则的问题

#7

帖子 MaskRay » 2011-06-30 16:52

可能是递归处理 sample 下的 makefile 时,发现 $(target) 为空,就不匹配 $(target): 了

我做了个测试,空的 target 似乎是无法匹配的
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Re: Makefile规则的问题

#8

帖子 tosail2010 » 2011-06-30 21:57

MaskRay 写了:可能是递归处理 sample 下的 makefile 时,发现 $(target) 为空,就不匹配 $(target): 了

我做了个测试,空的 target 似乎是无法匹配的
不匹配会怎么样运行呢?你说的匹配是指哪两者?你的意思是当在目录sample的上一级目录运行命令make sample时吗?
我翻过makefile的资料,对于依赖关系的格式描述<目标名: 依赖文件列表>,目标名通常是最后可执行的文件名或者.o文件名,但是在这里 $(target) ,all, clean应该属于伪目标。我看的资料中并没有给出这方面的详细说明。
当$(target)为空时,运行make sample,便会执行子makefile中的all目标下所有规则。关于$(target)为符号时,有什么说法吗?
A year's plan starts with spring.
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Re: Makefile规则的问题

#9

帖子 tosail2010 » 2011-06-30 21:59

lexdene 写了:怀疑和rm有关。
线索太少,看不出什么东西来。
呵呵,你要细细的看。 :em09
A year's plan starts with spring.
头像
fanhe
帖子: 2357
注册时间: 2007-03-24 23:45

Re: Makefile规则的问题

#10

帖子 fanhe » 2011-07-01 0:15

tosail2010 写了:
MaskRay 写了:可能是递归处理 sample 下的 makefile 时,发现 $(target) 为空,就不匹配 $(target): 了

我做了个测试,空的 target 似乎是无法匹配的
不匹配会怎么样运行呢?你说的匹配是指哪两者?你的意思是当在目录sample的上一级目录运行命令make sample时吗?
我翻过makefile的资料,对于依赖关系的格式描述<目标名: 依赖文件列表>,目标名通常是最后可执行的文件名或者.o文件名,但是在这里 $(target) ,all, clean应该属于伪目标。我看的资料中并没有给出这方面的详细说明。
当$(target)为空时,运行make sample,便会执行子makefile中的all目标下所有规则。关于$(target)为符号时,有什么说法吗?
不是这样理解的

首先, 我不清楚的是, 如果是空目标的话, 不知道是跳过还是什么, 没时间测试, 那就假设是跳过吧

有一点我先跟你说清楚, 目标和依赖默认情况下都对应硬盘上的文件
所以 ./ 就对应当前目录, 但是由第一行可知, 这是伪目标, 伪目标是无条件执行的
真目标只有比较了时间戳后再决定是否需要运行的

目标可以为任何符号(? 应该有限制的), 默认都对应硬盘上的文件, 如果硬盘没有这个文件, 代表必定运行这个目标的规则
为什么要有伪目标的?

假设, 你有个目标叫 love, 你要确保 make love 的时候一定要执行, 如果这个不是伪目标的时候, 在以下情况就会不执行:
硬盘中有一个叫 love 的文件, 它的最后修改时间比它的所有依赖要迟.

当定义了 love 为伪目标之后, 就会不管硬盘上有没有love这个文件, 都会直接 make love
应该清楚了吧
MaskRay
帖子: 61
注册时间: 2010-04-29 22:00
系统: Gentoo Linux ~amd64
联系:

Re: Makefile规则的问题

#11

帖子 MaskRay » 2011-07-01 14:58

你说的什么“情况1”“对应情况”之类的,我没看懂

对于1楼,make sample 会执行 make -C $(SAMPLE_DIR),转而在 sample/ 下递归执行 make
此时 $MAKECMDGOALS 为空,所以 target 为空
$(target):
是一条目标为空的规则

关于目标为空的规则,我的理解是 GNU make 直接忽略了,无法匹配任何指定的目标,它也不能作为默认目标,所以 all 成为默认目标




对于 make -C $(SAMPLE_DIR) all,转而在 sample/ 下递归执行 make,此时 MAKECMDGOALS 为 all,所以 target 为 all,根据你的替换,target 成了 ./ ,./: 是默认目标,但因为 MAKECMDGOALS 是 all,所以执行 all:



对于 make -C $(SAMPLE_DIR) clean,转而在 sample/ 下递归执行 make,此时 MAKECMDGOALS 为 clean,所以 target 为空,根据你的替换,target 成了,又出现了目标为空的规则,它无法匹配任何指定的目标,因为 MAKECMDGOALS 是 clean,所以执行 clean:
上次由 MaskRay 在 2011-07-01 15:09,总共编辑 1 次。
MaskRay
帖子: 61
注册时间: 2010-04-29 22:00
系统: Gentoo Linux ~amd64
联系:

Re: Makefile规则的问题

#12

帖子 MaskRay » 2011-07-01 14:59

你要注意,target 的变化是不影响 MAKECMDGOALS 的
头像
tosail2010
帖子: 83
注册时间: 2011-03-27 19:01
联系:

Re: Makefile规则的问题

#13

帖子 tosail2010 » 2011-07-02 11:10

楼上2位分析的很精彩,多谢。
A year's plan starts with spring.
回复