如何强制 gnu make 不并行构建配方?
我如何告诉 gnu make 不要并行构建某些配方。假设我有以下 makefile :
sources = a.xxx b.xxx c.xxx
target = program
all : $(target)
$(target) : $(patsubst %.xxx,%.o,$(sources))
$(CXX) -o $@ $<
%.o : %.cpp
$(CXX) -c -o $@ $<
%.cpp : %.xxx
my-pre-processor -o $@ $<
但是,my-pre-processor
命令创建具有固定名称的临时文件(我无法更改它)。如果我只使用不带 -j
参数的 make,则效果很好。但是,如果使用 -j 选项,构建有时会失败,因为两次并发调用 my-pre-processor 会覆盖其临时文件。
我想知道是否有一种方法可以告诉 make 它不能构建并行执行 %.cpp : %.xxx
配方的尝试。
How can I tell gnu make not to build some recipe in parallel. Let's say I have the following makefile :
sources = a.xxx b.xxx c.xxx
target = program
all : $(target)
$(target) : $(patsubst %.xxx,%.o,$(sources))
$(CXX) -o $@ lt;
%.o : %.cpp
$(CXX) -c -o $@ lt;
%.cpp : %.xxx
my-pre-processor -o $@ lt;
However, the my-pre-processor
command create temporary files with fixed name (I cannot change this). This is working fine if I just use make without the -j
parameter. However, if the -j
option is used, the build sometimes fails because two concurrent invocation of my-pre-processor
overwrite their temporary files.
I'd like to know if there is a way to tell make that it must not build the try to parallelize the execution of the %.cpp : %.xxx
recipes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
解决方案 1
GNU Make 包含特殊的内置伪目标
.NOTPARALLEL
示例:
解决方案 2
您还可以使用
-j
,--命令行上的 jobs[=]
标志,其中n
是允许并行运行的食谱数量。用法:
make -j
或make --jobs=
示例:
make -j 1
或make --jobs=1
注意: 省略
将允许任意要执行的配方数量,仅受系统可用资源的限制解决方案 3
最后,您可以将解决方案 2 中的命令行标志分配给 Makefile
示例中的
MAKEFLAGS
变量:MAKEFLAGS := -j 1
或者
MAKEFLAGS := --jobs=1
Solution 1
GNU Make contains the special built-in pseudo-target
.NOTPARALLEL
Example:
Solution 2
You can also use the
-j <n>
,--jobs[=<n>]
flag on the command line wheren
is the number of recipies allowed to run in parallel.Usage:
make -j <n>
ormake --jobs=<n>
Example:
make -j 1
ormake --jobs=1
note: omitting
<n>
will allow an arbitrary number of recipes to be executed, only limited by your system's available resourcesSolution 3
Finally, you can assign the command line flag in solution 2 to the
MAKEFLAGS
variable from within your MakefileExample:
MAKEFLAGS := -j 1
or
MAKEFLAGS := --jobs=1
一个相关的解决方案是指定您想要构建的确切顺序(而不是说“不要并行构建”)。
要指定确切的顺序,您可以使用仅订单先决条件。这是 GNU make 的手册页:
这是他们提供的示例:
由于竞争条件,我不得不在
make dist
规则上使用仅顺序先决条件。dist
配方依赖于distclean
和diff
规则,并且diff
规则执行svn diff -r XXX
显示确切的更改。有时,make 会删除它刚刚创建的 diff,因为 clean 规则将在 diff 规则之后运行。A related solution is to specify the exact order you want things built (rather than saying, "don't build in parallel").
To specify the exact order, you can use order-only prerequisites. Here's GNU make's man page on it:
And here's the example they offer:
I had to use order only prerequisites on a
make dist
rule due to a race condition. Thedist
recipe depended on adistclean
anddiff
rules, and thediff
rule performed ansvn diff -r XXX
to show the exact changes. On occasion, make would delete the diff it just created because the clean rule would run after the diff rule.这是一个可怕的拼凑,但它会完成工作:
或者如果实际上有很多这样的东西,你可以喝一些烈性饮料并执行此操作:(
这在 GNUMake 中有效,我不知道其他版本。)
This is a horrible kludge, but it will do the job:
Or if there are actually a lot of these, you can have a few stiff drinks and do this:
(This works in GNUMake, I don't know about other versions.)
如果临时文件是在当前工作目录中创建的,您也许可以使用子目录(不太漂亮,但很少见):
此外,由于您使用的是语法,但不是 GNU make 专用的功能,请注意以下内容等效的 Makefile 应该更可移植
另请注意,GNU make 的固有
.cpp.o:
规则允许用户在命令行上指定标志,(类似于)您的用户在需要提供时可能会喜欢的标志,比如说,通过
-L... 自定义包含目录
If the temporary files are created in the current working directory, you may be able to use subdirectories (not pretty, but rare):
Also, since you are using syntax but not features that are exclusively available to GNU make, please note that the following equivalent Makefile should be more portable
Also note that GNU make's intrinsic
.cpp.o:
rule allows for users to specify flags on the command line, (similar to)which your users may like when they need to provide, say, custom include directories via
-L...
你最好研究一下
automake
自带的ylwrap
工具的操作:它解决了旧版本lex
的大部分相同问题和yacc
:http://git .savannah.gnu.org/cgit/automake.git/tree/lib/ylwrap
You would do well to study the operation of the
ylwrap
tool that comes withautomake
: It solves most of the same problems for old versions oflex
andyacc
:http://git.savannah.gnu.org/cgit/automake.git/tree/lib/ylwrap
在 Linux 上,您可以使用
flock file -c "command"
: https://man7.org/linux/man-pages/man1/flock.1.html。我已经使用flock
解决了GPU资源同步问题。如果我调用:
make 1.mp3 2.mp3 3.mp3 -j3
- 它将同步python
,但不会同步ffmpeg
。On linux you can use
flock file -c "command"
: https://man7.org/linux/man-pages/man1/flock.1.html. I have solved a problem with GPU resource synchronization using theflock
.If I call:
make 1.mp3 2.mp3 3.mp3 -j3
- it will syncpython
, but notffmpeg
.我遇到了同样的问题(我的 sw 签名服务不接受多个并发请求)。我的解决方案是在接收器中添加一个互斥锁:
这允许 makefile 的所有其他部分并行运行,但此时只会运行一个“我的预处理器”。
I run into the same problem (my sw signing service did not accept multiple concurrent requests). My solution was to add a mutex in the recepie:
This allows all other parts of the makefile to run in parallel, but there will only be one "my-pre-processor" running at the time.
@airenas 使用集群的建议可以概括为一个实用程序 Makefile,您可以在此测试 makefile 中包含和使用:
NOTPARALLEL_test.mk 的内容
,这取决于包含的实用程序:
NOTPARALLEL 的内容。 mk
然后您可以调用 NOTPARALLEL_test 文件的多种不同用法,如下所示:
这是一些文档:
@airenas's suggestion to use flock can be generalized as a utility Makefile you can include and use as in this test makefile:
Contents of NOTPARALLEL_test.mk
which depends upon the included utility:
contents of NOTPARALLEL.mk
You can then invoke multiple different usages of NOTPARALLEL_test file like this:
Here's some documentation: