如何编写 makefile 来自动检测并使用 GNU Make 并行化构建?
不确定这是否可以单独在一个 Makefile 中实现,但我希望以一种方式编写 Makefile,以便尝试在文件中构建任何目标会自动检测当前系统上的处理器数量并并行构建目标对于处理器的数量。
类似于下面的“伪代码”示例,但更清晰?
all:
@make -j$(NUM_PROCESSORS) all
或者:
all: .inparallel
... build all here ...
.inparallel:
@make -j$(NUM_PROCESSORS) $(ORIGINAL_TARGET)
在这两种情况下,您只需输入:
% make all
希望这是有道理的。
更新:仍然希望有一个用于上述内容的示例 Makefile。对查找进程数并不是很感兴趣,而是对如何编写 makefile 来并行构建而不使用 -j 命令行选项感兴趣。
Not sure if this is possible in one Makefile alone, but I was hoping to write a Makefile in a way such that trying to build any target in the file auto-magically detects the number of processors on the current system and builds the target in parallel for the number of processors.
Something like the below "pseudo-code" examples, but much cleaner?
all:
@make -j$(NUM_PROCESSORS) all
Or:
all: .inparallel
... build all here ...
.inparallel:
@make -j$(NUM_PROCESSORS) $(ORIGINAL_TARGET)
In both cases, all you would have to type is:
% make all
Hopefully that makes sense.
UPDATE: Still hoping for an example Makefile for the above. Not really interested in finding the number of processes, but interested in how to write a makefile to build in parallel without the -j command line option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
检测部分将取决于操作系统。下面是一个可以在 Linux 和 Mac OS X 上运行的片段:
为了让它工作,你可能需要重新调用 make。那么你的问题就是防止无限递归。您可以通过两个 makefile 来管理它(第一个仅重置
-j
值),但可能可以巧妙地处理它。The detection part is going to be OS dependent. Here's a fragment that will work on Linux and Mac OS X:
To get it working you are probably going to have to re-invoke make. Then your problem is preventing infinite recursion. You could manage that by having two makefiles (the first only resetting the
-j
value), but it is probably possible to finesse it.我刚刚将其添加到我的 Makefile 的顶部。它允许 make 创建任意数量的作业,但会尝试将平均负载保持在 CPU 核心数量以下。
请注意,这是 Linux 特定的。
I just added this to the top of my Makefile. It lets make create any number of jobs, but tries to keep the load average below the number of cpu cores.
Note this is Linux specific.
这是我的做法:
Here's what I went with:
在稍微浏览了一下 LDD3 第 2 章并阅读 dmckee 的答案后,我想出了使用两个 makefile 的不太好的答案(我更喜欢只使用一个)。
您对此解决方案有何看法?
我看到的好处是人们仍然可以输入
make
来构建。因此,没有一些“驱动程序”脚本可以执行NPROCS
和make -j$(NPROCS)
工作,人们必须知道这些脚本而不是键入 make。缺点是您必须显式使用 make -f Makefile.goals 才能进行串行构建。我不知道如何解决这个问题...
更新:将 $J 添加到上面的代码段。看来工作进展顺利。尽管它有两个而不是一个 makefile,但它仍然非常无缝且有用。
After poking around the LDD3 chapter 2 a bit and reading dmckee's answer, I came up with this not so great answer of using two makefiles (I would prefer just one).
What do you think about this solution?
Benefits I see is that people still type
make
to build. So there isn't some "driver" script that does theNPROCS
andmake -j$(NPROCS)
work which people will have to know instead of typing make.Downside is that you'll have to explicitly use
make -f Makefile.goals
in order to do a serial build. And I'm not sure how to solve this problem...UPDATED: added $J to above code segment. Seems work work quite well. Even though its two makefiles instead of one, its still quite seamless and useful.
我将跳过
$(NPROCS)
检测内容,但以下是如何在单个Makefile
中执行此操作(这可能是 GNU Make 特定的,但看起来像您正在运行的变体):请参阅定义最后手段默认规则 和 覆盖另一个 Makefile 的部分 GNU Make 手册。
I'll skip over the
$(NPROCS)
detection stuff, but here's how you could do this in a singleMakefile
(this is probably GNU Make specific, but that looks like the variant you're running):See Defining Last-Resort Default Rules and Overriding Part of Another Makefile in the GNU Make Manual.
如果我正确地阅读了问题,目标是尽可能并行化构建过程。
make
手册页说明了以下内容这基本上不是您想要的解决方案吗?如果你的 Makefile 有足够的并行目标,你将使用所有的 CPU,如果目标不是并行的,那么
-j
选项将无济于事。If I read the question correctly, the goal is to parallelize the build process as much as possible. The
make
man page states the followingIsn't this basically the solution that you want? If your Makefile has enough parallel targets you will use all your CPUs and if the targets are not parallel, that
-j
option won't help anywas.如果您希望它是自动的,那么您可以覆盖典型的 make 命令,使其成为主目录中
.bashrc
中自身的别名。示例:
或者您可以这样做:
如果您不想覆盖它,但想要一种快速且简单(且令人难忘)的方式来并行运行 make 。
If you want it to be automatic, then you can override your typical make command to be an alias to itself in your
.bashrc
in your home directory.Example:
Or you could do something like:
in the case that you don't want to override it, but want a quick and easy (and memorable) way to run make in parallel.