自从我了解了-j后,我就轻松地使用了-j8.前几天我正在编译一个地图集安装,但是make失败了.最终我将其追踪到了无序的事情 - 一旦我回到单线程制作,它就能正常工作.这让我很紧张.在编写自己的make文件时,我需要注意哪些条件,以避免使用make -j做出意外的事情?
我认为make -j将尊重您在Makefile中指定的依赖项; 即如果你指定objA依赖于objB和objC,那么在objB和objC完成之前make不会开始处理objA.
很可能你的Makefile没有足够严格地指定必要的操作顺序,而且运气恰好在单线程情况下适合你.
简而言之 - 确保您的依赖关系正确且完整.
如果您使用的是单线程make,那么您可能会盲目地忽略目标之间的隐式依赖关系.使用parallel make时,不能依赖隐式依赖.它们都应该明确.这可能是最常见的陷阱.特别是如果使用.phony目标作为依赖项.
这个链接是关于并行make的一些问题的一个很好的入门读物.
这是我开始使用并行构建时遇到的问题示例.我有一个名为"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
这基本上只是正确指定依赖关系的问题.诀窍在于并行构建比单线程构建更严格.我的示例演示了给定目标的依赖关系列表并不一定表示执行顺序.
如果你有一个递归制作,事情很容易破坏.如果你没有做一个递归make,那么只要你的依赖是正确和完整的,你就不应该遇到任何问题(除了make中的bug).有关递归make问题的详细描述,请参阅Recursive Make Considered Harmful.