GNU Make 下创建目录的问题
很多时候,我们的 Makefile 在工作的时候,往往需要把中间文件放在独立目录中。这个独立目录一开始又没有创建出来。所以,Makefile 就有责任创建它们。
正确的创建目录,对于 Make 来说可是一个头痛的事情。
直观的写法是让目标依赖目录。比如:
foo.c : out/foo.o out/foo.o : out out : mkdir $@
这样做的问题在于,out 作为一个特殊文件(目录文件),时间戳是不受控的。
如果你删除或添加新文件到 out 目录下,都会更改 out 的时间戳,这会进一步的影响其依赖的目标。
我以前的解决方法是,放一个 probe 文件在目标目录下。这个文件的时间戳就是正常的,它在目录第一次被建立时建立,以后不再更改。
out/foo.o :foo.c out/.probe out/.probe : mkdir -p $(dir $@) && touch $@
这个方法我用了半年,总是有点不爽(因为那个多余的文件)。尤其是在 Windows 下时,dir 不会隐藏 . 开头的文件,让我不能眼不见心不烦。跟 svn 在目录目录下创建一个 .svn 目录一样的让人恼火。
今天仔细研究了一下,发现 GNU Make 3.80 以后的版本可以比较完美的解决这个问题。
方法是,把目录作为 order-only 的依赖。写法是在填依赖关系时加一个 |
out/foo.o : foo.c | out 或是写成两行 out/foo.o : foo.c out/foo.o : | out
out 前修饰了 | ,这样,只有在 out 不存在时,才会提前(在构建 out/foo.o 前)去构建。当 out 已经存在,out/foo.o 则不依赖 out 的时间戳。
如果一个项目需要大量创建中间目录,手写每个目录的构建规则肯定不合适。那么如何批量创建目录呢?
我的方法是,每次依赖一个中间目录时,就把目录名加到一个变量中。如:
MKDIRS += out
然后在 Makefile 的末尾:
$(sort $(MKDIRS)) : mkdir -p $@
不过,这样做还有一个缺陷。如果需要创建的目录有父子关系,一个更深层次的目录被创建出来后;随后创建的目录就会因为存在而创建失败。
固然,我们可以在 mkdir 前加上 - 忽略出错信息。但这不符合我的审美观。
我的解决方法是,过滤出有父子关系的目录,让浅的目录依赖深的目录,只在深层目录上真正 mkdir 。
代码如下:
MKDIRS := $(sort $(MKDIRS)) define SAFE_MKDIR CHILD := $(firstword $(filter $(1)/%,$(MKDIRS))) ifeq ($$(strip $$(CHILD)),) $(1) : $(MKDIR) $$(call pathname,$$@) else $(1) : | $$(CHILD) endif endef $(foreach dir,$(MKDIRS),$(eval $(call SAFE_MKDIR,$(dir))))
如果你想直接使用,请注意以上的空格和 Tab 的区别。
Comments
是不是09年还没有scons这种神器。
Posted by: www | (24) June 18, 2014 05:44 PM
是不是09年还没有scons这种神器。
Posted by: www | (23) June 18, 2014 05:43 PM
@不去嫖:
我不知道触动了你哪根敏感、脆弱的神经,对于一个三十好几的人,我没觉得这个问题有多弱智!“风风”,我靠,是不是你每天帮他打飞机啊?
Posted by: 阿北 | (22) July 24, 2009 08:20 PM
云老大很久没写东西了...
Posted by: Jason | (21) July 24, 2009 02:49 PM
@阿北:
你的问题好弱智哦。。风风道德高尚,就算打飞机也不去找鸡。。你知道了吧。。反过来说,暗示你经常去嫖。。。我呸。。。。垃圾弱智问题。。。。滚开
Posted by: 不去嫖 | (20) July 23, 2009 05:43 PM
云风三十好几还没女朋友吧,想问下性生活是如何解决的?给广大单身的程序员朋友们传授点经验,也是给中国的软件业造福啊!
Posted by: 阿北 | (19) July 23, 2009 09:40 AM
唉,就这能耐了。
Posted by: __ | (18) July 19, 2009 08:29 AM
最近好像魔兽世界玩家集群攻击梦幻西游服务器的活动影响很坏,不知道是不是在忙这个呢?
Posted by: 白沙 | (17) July 18, 2009 06:39 PM
呵呵
Posted by: 骨头软件工作室 | (16) July 16, 2009 02:14 AM
这么多拍马屁的....
这个跟闲来无事去踢踢球有什么不同吗?
在我看闲来无事去磨磨jj跟磨磨刀没什么差别啊。。。。
言语粗俗,见谅。
Posted by: MJ | (15) July 14, 2009 02:04 PM
专业
Posted by: 百度玩吧 | (14) July 14, 2009 10:57 AM
他磨的不是刀,是寂寞
Posted by: TypeKey identity | (13) July 12, 2009 09:17 AM
楼主有米,还在不停地磨刀,是真的喜欢磨刀,享受磨刀。像我这种没米的人,磨刀是为了准备造反,境界差太远了。
Posted by: jacky | (12) July 11, 2009 10:56 PM
不错
Posted by: 爱玩游戏 | (11) July 11, 2009 10:50 PM
博主,真厉害,按照你的步骤,我试验了一下,可以啊
Posted by: 皇冠投注网 | (10) July 11, 2009 01:34 AM
呵呵,这个留言牛
Posted by: 游戏资讯网 | (9) July 9, 2009 11:18 PM
哎呦,又见风风磨刀玩弄
Posted by: 坎钱的刀 | (8) July 9, 2009 03:46 PM
好东西,学习了
Posted by: 桂林旅游 | (7) July 8, 2009 10:10 PM
从你的文章中能学到不少东西,希望博主能多多更新..
Posted by: object | (6) July 8, 2009 07:52 PM
磨刀不误砍柴工,不要太在意手中的工具,也不要太不在意手中的工具。
Posted by: Tairan | (5) July 8, 2009 03:20 PM
楼主喜欢磨刀,主要是他肚子不饿,想我这种肚子还很饿,或急于解放自己的,就不会有这种心态了. 很羡慕云风的这种境界.
Posted by: linghuye | (4) July 8, 2009 10:52 AM
楼主是喜欢玩弄的人,高啊....
Posted by: 空 | (3) July 8, 2009 10:36 AM
先占位,后阅读。。
Posted by: 文 | (2) July 8, 2009 09:30 AM
楼主是一个喜欢磨刀的人!
Posted by: 路人甲 | (1) July 8, 2009 07:57 AM