« 关于“群”的那些破事 | 返回首页 | 老人言 »

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 的时间戳。

参考:GNU Make 手册:4.3 依赖的类型


如果一个项目需要大量创建中间目录,手写每个目录的构建规则肯定不合适。那么如何批量创建目录呢?

我的方法是,每次依赖一个中间目录时,就把目录名加到一个变量中。如:

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这种神器。
是不是09年还没有scons这种神器。
@不去嫖: 我不知道触动了你哪根敏感、脆弱的神经,对于一个三十好几的人,我没觉得这个问题有多弱智!“风风”,我靠,是不是你每天帮他打飞机啊?
云老大很久没写东西了...
@阿北: 你的问题好弱智哦。。风风道德高尚,就算打飞机也不去找鸡。。你知道了吧。。反过来说,暗示你经常去嫖。。。我呸。。。。垃圾弱智问题。。。。滚开
云风三十好几还没女朋友吧,想问下性生活是如何解决的?给广大单身的程序员朋友们传授点经验,也是给中国的软件业造福啊!
唉,就这能耐了。
最近好像魔兽世界玩家集群攻击梦幻西游服务器的活动影响很坏,不知道是不是在忙这个呢?
这么多拍马屁的.... 这个跟闲来无事去踢踢球有什么不同吗? 在我看闲来无事去磨磨jj跟磨磨刀没什么差别啊。。。。 言语粗俗,见谅。
专业
他磨的不是刀,是寂寞
楼主有米,还在不停地磨刀,是真的喜欢磨刀,享受磨刀。像我这种没米的人,磨刀是为了准备造反,境界差太远了。
不错
博主,真厉害,按照你的步骤,我试验了一下,可以啊
呵呵,这个留言牛
哎呦,又见风风磨刀玩弄
好东西,学习了
从你的文章中能学到不少东西,希望博主能多多更新..
磨刀不误砍柴工,不要太在意手中的工具,也不要太不在意手中的工具。
楼主喜欢磨刀,主要是他肚子不饿,想我这种肚子还很饿,或急于解放自己的,就不会有这种心态了. 很羡慕云风的这种境界.
楼主是喜欢玩弄的人,高啊....
先占位,后阅读。。
楼主是一个喜欢磨刀的人!

Post a comment

非这个主题相关的留言请到:留言本