在使用普通 old 的相对较大make
的项目中,即使在没有任何变化的情况下构建项目也需要几十秒。尤其是对于 的许多执行make -C
,它们具有新的进程开销。
这个问题的明显解决方案是基于inotify
操作系统的类似特性的构建工具。它会查看某个文件何时更改,并根据该列表单独编译该文件。
有这样的机器吗?开源项目的奖励积分。
你的意思是像Tup:
从主页:
“Tup 是一个基于文件的构建系统——它输入文件更改列表和有向无环图 (DAG),然后处理 DAG 以执行更新相关文件所需的适当命令。DAG 存储在 SQLite 数据库中。默认情况下,文件更改列表是通过扫描文件系统生成的。或者,可以通过运行包含的文件监视器守护进程预先提供该列表。
我只是想知道它是否stat()
需要花费这么长时间的文件。在这里检查这个是我写的一个小的systemtap脚本来测量stat()
文件花费的时间:
# call-counts.stp
global calls, times
probe kernel.function(@1) {
times[probefunc()] = gettimeofday_ns()
}
probe kernel.function(@1).return {
now = gettimeofday_ns()
delta = now - times[probefunc()]
calls[probefunc()] <<< delta
}
然后像这样使用它:
$ stap -c "make -rC ~/src/prj -j8 -k" ~/tmp/count-calls.stp sys_newstat
make: Entering directory `/home/user/src/prj'
make: Nothing to be done for `all'.
make: Leaving directory `/home/user/src/prj'
calls["sys_newstat"] @count=8318 @min=684 @max=910667 @sum=26952500 @avg=3240
我运行它的项目有 4593 个源文件,make 需要大约 27 毫秒(以上为 26952500 纳秒)来统计所有文件以及相应的 .d 文件。我正在使用非递归make。
如果您使用的是 OSX,则可以使用fswatch
https://github.com/alandipert/fswatch
以下是如何使用 fswatch 对文件进行更改,然后在检测到任何文件时运行 make
fswatch -o anyFile | xargs -n1 -I{} make
您可以像这样从 makefile 中运行 fswatch:
watch: $(FILE)
fswatch -o $^ | xargs -n1 -I{} make
(当然,$(FILE) 是在 makefile 中定义的。) make 现在可以像这样监视文件中的更改:
> make watch
您可以像这样观看另一个文件:
> make watch anotherFile
安装inotify-tools并写几行在某些目录更新时bash
调用。make
附带说明一下,递归 make 的扩展性很差并且容易出错。首选非递归 make。
您描述的更改依赖性已经是 Make 的一部分,但 Make 足够灵活,可以以低效的方式使用。如果缓慢确实是由递归(make -C
命令)引起的——它可能是——那么你应该减少递归。(您可以尝试放入自己的条件逻辑来决定是否执行make -C
,但这将是一个非常不雅的解决方案。)
粗略地说,如果你的 makefile 看起来像这样
# main makefile
foo:
make -C bar baz
还有这个
# makefile in bar/
baz: quartz
do something
您可以将它们更改为:
# main makefile
foo: bar/quartz
cd bar && do something
有很多细节要做好,但现在如果bar/quartz
没有更改,foo
规则将不会运行。