并行makefile需要依赖顺序

kyk*_*yku 24 makefile gnu-make

我有以下makefile:

CXXFLAGS = -std=c++0x -Wall
SRCS     = test1.cpp test2.cpp
OBJDIR   = object
OBJS     = $(SRCS:%.cpp=$(OBJDIR)/%.o)

all: test1 
release: clean test1

test1: $(OBJS)
    $(CXX) -o $@ $(OBJS)

$(OBJDIR)/%.o: %.cpp
    $(CXX) $(CXXFLAGS) -MD -c -o $@ $<

-include $(SRCS:.cpp=.d)

clean:
    rm -rf $(OBJDIR)/*

.PHONY: all clean release 
Run Code Online (Sandbox Code Playgroud)

现在,如果我尝试调用"make -j4 release",那么干净的目标通常会在构建文件的过程中执行,从而导致编译失败.我的问题是如何在开始发布版本之前确保干净的目标已完成.

Nei*_*eil 31

我的偏好是

release:
    $(MAKE) clean
    $(MAKE) test1
Run Code Online (Sandbox Code Playgroud)

这迫使两个目标连续制造而不会干扰它们的内部平行度(如果有的话).


Eld*_*mov 11

您可以将执行拆分为非并行(for release)和并行(对于其余目标)阶段.

ifneq ($(filter release,$(MAKECMDGOALS)),)
.NOTPARALLEL:
endif

release: clean
    $(MAKE) test1
Run Code Online (Sandbox Code Playgroud)

.NOTPARALLEL如果release在命令行中提到target,则target将禁止并行执行.在release本身将重新目标使清洗后,并建立test1并行.

UPD.

如果在命令行上给出多个目标,则更聪明的解决方案也会重新调用每个单个目标的Make,以便release目标的存在不会强制其余目标执行非并行.

ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
$(sort all $(MAKECMDGOALS)):
    @$(MAKE) -f $(firstword $(MAKEFILE_LIST)) $@
else
# ...
endif
Run Code Online (Sandbox Code Playgroud)

James Johnston更新

上面的聪明解决方案不适用于不支持作业服务器的GNU make版本.例如,在版本4.0之前发布的GNU make的MinGW /本机版本不支持作业服务器.(GNU make的Cygwin/MSYS版本.)下面的代码使用make 3.81中引入的.FEATURES变量来检测是否支持作业服务器.在需要时不使用此变通办法的症状是您的"并行"构建将被序列化.

# Check if job server supported:
ifeq ($(filter jobserver, $(.FEATURES)),)
# Job server not supported: sub-makes will only start one job unless
# you specify a higher number here.  Here we use a MS Windows environment
# variable specifying number of processors.
JOBSARG := -j $(NUMBER_OF_PROCESSORS)
else
# Job server is supported; let GNU Make work as normal.
JOBSARG :=
endif

# .FEATURES only works in GNU Make 3.81+.
# If GNU make is older, assume job server support.
ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))),3.81)
# If you are using GNU Make < 3.81 that does not support job servers, you
# might want to specify -jN parameter here instead.
JOBSARG :=
endif

ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
# The "all" target is required in the list,
# in case user invokes make with no targets.
$(sort all $(MAKECMDGOALS)):
    @$(MAKE) $(JOBSARG) -f $(firstword $(MAKEFILE_LIST)) $@
else

# Put remainder of your makefile here.

endif
Run Code Online (Sandbox Code Playgroud)