自从我知道了-j我愉快地使用-j8。 有一天,我正在编制一本地图册安装和化妆失败。 最后,我跟踪下来的东西被做出来的顺序 - 一旦我回到了单线程使其正常工作。 这让我很紧张。 我需要什么样的条件看写我自己制作的文件时,避免做一些意想不到的用make -j呢?
Answer 1:
我觉得做-j会尊重您在Makefile中指定的依赖; 也就是说,如果你指定objA取决于objB和objC,然后进行将不会启动对objA工作,直到objB和objC齐全。
最有可能你的Makefile不指定操作的必要为了严格不够的,这只是运气它发生了,你在单线程的情况下工作。
Answer 2:
总之 - 确保您的依赖是正确和完整的。
如果您使用的是单线程的化妆那么你可以忽略盲目目标之间隐含的依赖关系。 当使用并行让你无法依靠隐式依赖性。 他们应该都作出了明确。 这大概是最常见的陷阱。 特别是如果使用.PHONY目标,因为依赖关系。
这个链接是一些与并行make的问题的很好的入门。
Answer 3:
下面是我碰到了,当我开始使用并行构建了问题的一个例子。 我有一个名为“新鲜”的目标,我用它来从头重建目标(“新鲜”版本)。 在过去,我简单地表示“干净”,然后“建设”作为依赖编码“新鲜”的目标。
build: ## builds the default target
clean: ## removes generated files
fresh: clean build ## works for -j1 but fails for -j2
这工作得很好,直到我开始使用并行编译,但并行编译,它试图做到既“干净”和“建”并举。 所以我改变了“新鲜”的定义,以保证正确的操作顺序如下。
fresh:
$(MAKE) clean
$(MAKE) build
这是从根本上只是一个正确指定依赖文件的问题。 诀窍是比是单线程生成平行版本是更严格的这个问题。 我的例子证明,依赖关系给定的目标名单并不一定表示执行的顺序。
Answer 4:
如果你有一个递归时许,东西可以打破很容易地。 如果你不这样做递归化妆,然后只要你的依赖是正确和完整的,你不应该遇到任何问题(除了在化妆的错误)。 见是有害的递归制作为递归化妆的问题进行更全面的描述。
Answer 5:
它是有一个自动化测试来测试所有的make文件的-j选项是个好主意。 即使是最好的开发者使用make的-j选项的问题。 最常见的问题是最简单的。
myrule: subrule1 subrule2
echo done
subrule1:
echo hello
subrule2:
echo world
在正常的化妆,你会看到你好 - >世界 - >完成。 用make -j 4,你将可能看到世界 - >你好 - >完成
在那里我看到这种情况发生最多的是与创建输出目录。 例如:
build: $(DIRS) $(OBJECTS)
echo done
$(DIRS):
-@mkdir -p $@
$(OBJECTS):
$(CC) ...
Answer 6:
只是想我会增加subsetbrew的答案,因为它并不显示效果清晰。 但是增加了一些睡眠命令一样。 那么它在Linux上工作。
然后运行make显示了不同之处:
- 使
- 使-j4
all: toprule1
toprule1: botrule2 subrule1 subrule2
@echo toprule 1 start
@sleep 0.01
@echo toprule 1 done
subrule1: botrule1
@echo subrule 1 start
@sleep 0.08
@echo subrule 1 done
subrule2: botrule1
@echo subrule 2 start
@sleep 0.05
@echo subrule 2 done
botrule1:
@echo botrule 1 start
@sleep 0.20
@echo "botrule 1 done (good prerequiste in sub)"
botrule2:
@echo "botrule 2 start"
@sleep 0.30
@echo "botrule 2 done (bad prerequiste in top)"