Parallel processing 如何强制某些目标组始终按顺序运行?
有没有办法让gmake永远不要在一个集合中同时运行两个目标 我不想使用.NOTPARALLEL,因为它强制整个Makefile按顺序运行,而不仅仅是必需的部分 我还可以添加依赖项,以便一个依赖于另一个,但是(除了丑陋之外)我需要构建所有依赖项,以便构建最后一个,这是不必要的Parallel processing 如何强制某些目标组始终按顺序运行?,parallel-processing,makefile,gnu-make,ghc,Parallel Processing,Makefile,Gnu Make,Ghc,有没有办法让gmake永远不要在一个集合中同时运行两个目标 我不想使用.NOTPARALLEL,因为它强制整个Makefile按顺序运行,而不仅仅是必需的部分 我还可以添加依赖项,以便一个依赖于另一个,但是(除了丑陋之外)我需要构建所有依赖项,以便构建最后一个,这是不必要的 我之所以需要它,是因为(只有一部分)我的Makefile调用了ghc--make,它自己处理它的依赖关系。而且不可能在两个不同的目标上并行运行它,因为如果两个目标共享一些依赖关系,它们可以重写彼此的.o文件。(但是按顺序调
我之所以需要它,是因为(只有一部分)我的Makefile调用了
ghc--make
,它自己处理它的依赖关系。而且不可能在两个不同的目标上并行运行它,因为如果两个目标共享一些依赖关系,它们可以重写彼此的.o
文件。(但是按顺序调用ghc是可以的。)
更新:以给出具体示例。假设我需要在Makefile中编译两个程序:
取决于prog1
和prog1.hs
李>mylib.hs
取决于prog2
和prog2.hs
mylib.hs
prog1.hs
和mylib.hs
编译到各自的对象和接口文件中,并链接prog1
。调用ghc--makeprog2.hs
时也会发生同样的情况。因此,如果这两个命令并行运行,其中一个将覆盖另一个命令的mylib.o
,导致它严重失败
但是,我需要
prog1
既不依赖于prog2
,也不依赖于prog2
,因为它们应该可以单独编译。(实际上,它们非常大,有很多模块,需要编译它们,这大大降低了开发速度。)Hmmm,可能需要更多的信息,所以这只是一个暗中操作
Make并不真正支持这一点,但您可以通过几种方式实现两个目标。首先,递归make的真正用途是:
targ1: ; recipe1...
targ2: ; recipe2...
both-targets:
${MAKE} targ1
${MAKE} targ2
因此,在这里,您只需使-j成为两个目标
,一切都很好。但是很脆弱,因为make-jtarg1targ2
仍然并行运行。您可以改为使用依赖项:
targ1: ; recipe1...
targ2: | targ1 ; recipe2...
现在make-jtarg1targ2
做你想做的事。劣势<代码>生成targ2将始终尝试先(按顺序)生成targ1
。这可能(也可能不是)会阻碍你的表演
编辑
另一个不令人满意的策略是明确查看$MAKECMDGOALS
,其中列出了您在命令行上指定的目标。这仍然是一个脆弱的解决方案,因为当有人使用Makefile中的依赖项来构建东西时,它就被破坏了(这不是不合理的操作)
假设makefile包含两个独立的目标targ1
和targ2
。基本上,它们保持独立,直到有人在命令行上指定必须同时构建它们。在这种特殊情况下,你打破了这种独立性。考虑这个片段:
$(and $(filter targ1,${MAKECMDGOALS)),$(filter targ2,${MAKECMDGOALS}),$(eval targ1: | targ2))
乌尔克!这是怎么回事
- Make评估
$(和)
- 它首先必须展开
$(过滤器arg1,${MAKECMDGOALS})
- 如果指定了
,它将继续展开targ1
$(过滤器targ2,${MAKECMDGOALS})
- 如果还指定了
,它将继续扩展targ2
,强制序列化$(eval)
和targ1
。targ2
- 请注意,
扩展为零(其所有工作都是作为副作用完成的),因此原始的$(eval)
始终扩展为零,不会导致语法错误$(and)
- 请注意,
prog2:|$(filter prog1,${MAKECMDGOALS})
我想到了。哦,好吧
YMMV等等
我不熟悉ghc,但正确的解决方案是让ghc的两次运行使用不同的构建文件夹,然后它们可以愉快地并行运行。由于我遇到了相同的问题,这里有另一个指向
make
不提供您描述的功能的方向的指针:
从:
在使用并行执行(-j开关;请参阅并行执行)和归档时,务必小心。如果在同一存档文件上同时运行多个ar命令,它们将互不了解,并可能损坏文件
make的未来版本可能会提供一种机制,通过序列化在同一存档文件上运行的所有配方来规避此问题。但目前,您必须要么编写makefile,以其他方式避免此问题,要么不使用-j
您正在尝试的和我正在尝试的(使用make在SQLite3数据库中插入数据)都遇到了完全相同的问题。我需要将编译与其他步骤(清理、构建目录和链接)分开,因为我希望使用更多的核心进程和-j标志来运行编译 我设法解决了这个问题,使用不同的makefile相互包含和调用。只有“编译”make文件与所有内核并行运行,其余过程是同步的 我将makefile分为3个单独的脚本:
- settings.mk:包含所有变量和标志定义
- makefile:具有除编译目标以外的所有目标(它具有.NOTPARALLEL指令)。它使用-j标志调用compile.mk
- compile.mk:仅包含编译操作(不含.NOTPARALLEL)
CC = g++
DB = gdb
RM = rm
MD = mkdir
CP = cp
MAKE = mingw32-make
BUILD = Debug
DEBUG = true
[... all other variables and flags needed, directories etc ...]
在makefile中,我有如下链接和编译目标:
include .makefiles/settings.mk
[... OTHER TARGETS (clean, directories etc)]
compilation:
@echo Compilation
@$(MAKE) -f .makefiles/compile.mk --silent -j 8 -Oline
#Link
$(TARGET): compilation
@echo -e Linking $(TARGET)
@$(CC) $(LNKFLAGS) -o $(TARGETDIR)/$(TARGET) $(OBJECTS) $(LIBDIRS) $(LIB)
#Non-File Targets
.PHONY: all prebuild release rebuild clean resources directories run debug
.NOTPARALLEL: all
# include dependency files (*.d) if available
-include $(DEPENDS)
这是我的compile.mk:
include .makefiles/settings.mk
#Defauilt
all: $(OBJECTS)
#Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
@echo -e Compiling: $<
@$(MD) -p $(dir $@)
@$(CC) $(COMFLAGS) $(INCDIRS) -c $< -o $@
#Non-File Targets
.PHONY: all
# include dependency files (*.d) if available
-include $(DEPENDS)
include.makefile/settings.mk
#脱脂
全部:$(对象)
#编撰
$(BUILDDIR)/%.$(OBJEXT):$(SRCDIR)/%.$(SRCE)