当前位置:  开发笔记 > 编程语言 > 正文

GNU make的-j选项

如何解决《GNUmake的-j选项》经验,为你挑选了4个好方法。

自从我了解了-j后,我就轻松地使用了-j8.前几天我正在编译一个地图集安装,但是make失败了.最终我将其追踪到了无序的事情 - 一旦我回到单线程制作,它就能正常工作.这让我很紧张.在编写自己的make文件时,我需要注意哪些条件,以避免使用make -j做出意外的事情?



1> Jeremy Fries..:

我认为make -j将尊重您在Makefile中指定的依赖项; 即如果你指定objA依赖于objB和objC,那么在objB和objC完成之前make不会开始处理objA.

很可能你的Makefile没有足够严格地指定必要的操作顺序,而且运气恰好在单线程情况下适合你.


那是对的.我的代码库大约有2000万行,大多数是C语言,带有一点点C++.它被分成数百个组件,其中大约一半使用make,其中一半使用jam.我总是使用-j选项进行并行编译; 否则,构建将花费数小时.Jam会生成自己的依赖项,因此使用它的组件总是会成功.但是,使用手工制作的makefile的组件有时会因为依赖性不足而窒息.

2> Andrew Edgec..:

简而言之 - 确保您的依赖关系正确且完整.

如果您使用的是单线程make,那么您可能会盲目地忽略目标之间的隐式依赖关系.使用parallel make时,不能依赖隐式依赖.它们都应该明确.这可能是最常见的陷阱.特别是如果使用.phony目标作为依赖项.

这个链接是关于并行make的一些问题的一个很好的入门读物.



3> nobar..:

这是我开始使用并行构建时遇到的问题示例.我有一个名为"fresh"的目标,我用它从头开始重建目标(一个"新鲜的"构建).在过去,我通过简单地指示"干净"然后"构建"作为依赖性来编码"新鲜"目标.

build: ## builds the default target
clean: ## removes generated files
fresh: clean build ## works for -j1 but fails for -j2

在我开始使用并行构建之前,这很好用,但是对于并行构建,它会同时尝试"清理"和"构建".所以我改变了"新鲜"的定义如下,以保证正确的操作顺序.

fresh:
    $(MAKE) clean
    $(MAKE) build

这基本上只是正确指定依赖关系的问题.诀窍在于并行构建比单线程构建更严格.我的示例演示了给定目标的依赖关系列表并不一定表示执行顺序.


递归制作,yuk!.说make_please的正确方法总是在build_之前干净,当然是`build:clean`.
@bobbogo:我不想在构建之前总是干净 - 在大多数情况下这是不必要的.我描述的"新鲜"目标基本上只是一个简单的脚本,运行"make clean",然后是"make build"(对于那些我想要这样做的罕见时间).在这种情况下,我没有看到以递归方式执行make有任何损害.
如何用条件保护它:`ifeq($(MAKECMDGOALS),新鲜); 建造:干净; endif`(用换行符替换分号)?

4> Adam Rosenfi..:

如果你有一个递归制作,事情很容易破坏.如果你没有做一个递归make,那么只要你的依赖是正确和完整的,你就不应该遇到任何问题(除了make中的bug).有关递归make问题的详细描述,请参阅Recursive Make Considered Harmful.

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有