清理我的 makefile 片段吗?
我正在使用 GNU Make 来运行科学数据分析,其中我们有一堆 Matlab 脚本,可以思考一些输入数据,然后生成几个文件。它以相当复杂的方式完成此操作,因此在尝试向 Make 描述其功能时,我不得不使用一些令人讨厌的 Makefile 技巧。这是一个例子:
seg_cams_nozero := cam1 cam2 cam3
seg_per_camera := $(shell echo {,dyn_}{hands,obj{1,2,3,4,5}}.mat)
# the complete list of things we want
segmentation_outputs := $(foreach cam,$(seg_cams_nozero),$(foreach product,$(seg_per_camera),derived/cont_$(cam)_$(product)))
# how to make some product, independent of what camera
define seg_per_product
derived/cont_cam%_$$(product): /path/to/input/file_%.mat
run_a_script $$*
endef
$(foreach product,$(seg_per_camera),$(eval $(seg_per_product)))
segmentation: $(segmentation_outputs)
所以,这基本上是可怕的,因为我还没有弄清楚如何在这种情况下有效地使用模式规则,并且因为我必须使用 shell 生成大量文件名。
你会怎么写这样的东西?您会预先生成文件名并将它们放入包含的 Makefile 中吗?想出一个使用模式规则的好方法吗?有没有办法不用 $(eval ...)
来做到这一点?
I'm using GNU Make to run scientific data analysis, where we have a bunch of Matlab scripts that ponder some input data and then spit out several files. It does this in a fairly complex way, so I've had to do some nasty Makefile tricks when trying to describe its function to Make. Here's an example:
seg_cams_nozero := cam1 cam2 cam3
seg_per_camera := $(shell echo {,dyn_}{hands,obj{1,2,3,4,5}}.mat)
# the complete list of things we want
segmentation_outputs := $(foreach cam,$(seg_cams_nozero),$(foreach product,$(seg_per_camera),derived/cont_$(cam)_$(product)))
# how to make some product, independent of what camera
define seg_per_product
derived/cont_cam%_$(product): /path/to/input/file_%.mat
run_a_script $*
endef
$(foreach product,$(seg_per_camera),$(eval $(seg_per_product)))
segmentation: $(segmentation_outputs)
So, this is basically horrible because I haven't figured out how to use pattern rules effectively in this situation, and because I have to generate a ton of filenames using the shell.
How would you write something like this? Would you pre-generate the filenames and put them in an included Makefile? Figure out a great way to use pattern rules? Is there any way to do it without $(eval ...)
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有几种方法可以做到这一点,但没有一种方法是完美的(直到有人将正则表达式处理放入 Make 中)。
首先,我注意到一个命令为给定的摄像机创建了所有目标,但它针对每个目标运行,这是一种浪费。因此,让我们从 cam1 的目标开始
,将第一个目标设为“主要目标”(并将其从列表中删除)。这将是其余部分的先决条件,并且是唯一实际需要运行该脚本的部分。 (使用更高级的方法可能有稍微更优雅的方法,但现在就这样了。)
现在将其扩展到其他两个相机。我们可以将“主要”规则重写为模式规则:
其余的我们可以为所有三个摄像头拼写出来,但这意味着大量冗余代码。我们可以
定义
一个模板并评估
它,但我希望尽可能避免这种情况。因此,我们将使用一个小技巧:(这有点多余,但并不太可怕。)
将它们放在一起,我们得到:
There are several ways to do this, none of them perfect (until someone puts regex handling into Make).
First, I notice that one command makes all of the targets for a given camera, but it's run for each target, which is a waste. So let's start with the targets for cam1
and make the first one the "primary one" (and remove it from the list). This will be a prerequisite for the rest, and will be the only one that actually requires that the script be run. (There may be slightly more elegant ways using more advanced methods, but this'll do for now.)
Now to extend this to the other two cameras. We can rewrite the "primary" rule as a pattern rule:
The rest we could just spell out for all three cameras, but that would mean a lot of redundant code. We could
define
a template andeval
it, but I like to avoid that if possible. So we'll just use a little trick:(That's a little redundant, but not too terrible.)
Put it all together and we get: