Syl*_*sne 12 parallel-processing makefile gnu-make
我怎么能告诉gnu不要并行构建一些配方.假设我有以下makefile:
sources = a.xxx b.xxx c.xxx
target = program
all : $(target)
$(target) : $(patsubst %.xxx,%.o,$(sources))
$(CXX) -o $@ $<
%.o : %.cpp
$(CXX) -c -o $@ $<
%.cpp : %.xxx
my-pre-processor -o $@ $<
Run Code Online (Sandbox Code Playgroud)
但是,该my-pre-processor命令创建具有固定名称的临时文件(我无法更改此名称).如果我只使用没有-j参数的make,这工作正常.但是,如果使用该-j选项,则构建有时会失败,因为两次并发调用会my-pre-processor覆盖其临时文件.
我想知道是否有办法告诉make它必须不构建并行化%.cpp : %.xxx配方执行的尝试.
Sha*_*Lee 17
GNU Make包含特殊的内置伪目标 .NOTPARALLEL
例:
.PHONY: all clean
.NOTPARALLEL:
anotherTarget: dependency1
Run Code Online (Sandbox Code Playgroud)
您还可以在命令行上使用-j <n>,--jobs[=<n>]标志,其中n是允许并行运行的收件人数.
用法:
make -j <n>或make --jobs=<n>
示例:
make -j 1或make --jobs=1
注意:省略<n>将允许执行任意数量的配方,仅受系统可用资源的限制
最后,您可以将解决方案2中的命令行标志分配给MAKEFLAGSMakefile中的变量
示例:
MAKEFLAGS := -j 1
或
MAKEFLAGS := --jobs=1
jww*_*jww 11
一个相关的解决方案是指定您想要构建的确切顺序(而不是说"不要并行构建").
要指定确切的顺序,可以使用仅订单的先决条件.这是GNU make的手册页:
但是,有时您可能希望对要调用的规则强制执行特定排序,而不强制在执行其中一个规则时更新目标.在这种情况下,您希望定义仅订单的先决条件.可以通过在先决条件列表中放置管道符号(|)来指定仅订单的先决条件:管道符号左侧的任何先决条件都是正常的; 右边的任何先决条件都是仅限订单:
Run Code Online (Sandbox Code Playgroud)targets : normal-prerequisites | order-only-prerequisites
以下是他们提供的示例:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
Run Code Online (Sandbox Code Playgroud)
make dist由于竞争条件,我不得不在规则上使用仅限订单的先决条件.该dist配方依赖于一个distclean和diff规则,而diff规则执行svn diff -r XXX,以显示确切的变化.有时,make会删除它刚刚创建的diff,因为clean规则将在diff规则之后运行.
如果在当前工作目录中创建临时文件,您可以使用子目录(不是很漂亮,但很少见):
sources = a.xxx b.xxx c.xxx
target = program
all : $(target)
$(target) : $(patsubst %.xxx,%.o,$(sources))
$(CXX) -o $@ $<
%.o : %.cpp
$(CXX) -c -o $@ $<
%.cpp : %.xxx
mkdir $@.d
s=`realpath $<` && cd $@.d && my-pre-processor -o ../$@ "$${s}" || { $(RM) -r $@.d && false; }
$(RM) -r $@.d
Run Code Online (Sandbox Code Playgroud)
此外,由于您使用的是语法但不是GNU make专有的功能,请注意以下等效的Makefile应该更具可移植性
sources = a.xxx b.xxx c.xxx
target = program
all : $(target)
$(target) : $(sources:.xxx=.o)
$(CXX) -o $@ $<
.cpp.o:
$(CXX) -c -o $@ $<
.xxx.cpp:
mkdir $@.d
s=`realpath $<` && cd $@.d && my-pre-processor -o ../$@ "$${s}" || { $(RM) -r $@.d && false; }
$(RM) -r $@.d
.PHONY: all
.SUFFIXES: .xxx .cpp .o
Run Code Online (Sandbox Code Playgroud)
另请注意,GNU make的内在.cpp.o:规则允许用户在命令行上指定标志,(类似于)
.cpp.o:
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
Run Code Online (Sandbox Code Playgroud)
用户在需要提供自定义包含目录时可能会喜欢的内容 -L...
这是一个可怕的kludge,但它将完成这项工作:
b.cpp: a.cpp
c.cpp: b.cpp
Run Code Online (Sandbox Code Playgroud)
或者,如果实际上有很多这些,你可以喝几杯烈酒并做到这一点:
c-sources = $(sources:.xxx=.cpp)
ALLBUTFIRST = $(filter-out $(firstword $(c-sources)), $(c-sources))
ALLBUTLAST = $(filter-out $(lastword $(c-sources)), $(c-sources))
PAIRS = $(join $(ALLBUTLAST),$(addprefix :,$(ALLBUTFIRST)))
$(foreach pair,$(PAIRS),$(eval $(pair)))
Run Code Online (Sandbox Code Playgroud)
(这适用于GNUMake,我不知道其他版本.)
| 归档时间: |
|
| 查看次数: |
9303 次 |
| 最近记录: |