我有以下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
现在,如果我尝试调用“make -j4 release”,那么干净的目标通常会在构建文件的过程中执行,从而导致编译失败。我的问题是如何在开始发布版本之前确保干净的目标已经完成。
答案 0 :(得分:28)
我的偏好是
release:
$(MAKE) clean
$(MAKE) test1
这会迫使两个目标连续发生而不会打扰它们的内部平行度(如果有的话)。
答案 1 :(得分:10)
您可以将执行分为非并行(对于release
)和并行(对于其余目标)阶段。
ifneq ($(filter release,$(MAKECMDGOALS)),)
.NOTPARALLEL:
endif
release: clean
$(MAKE) test1
如果在命令行中提到release
目标, .NOTPARALLEL
target将禁止并行执行。 release
目标本身将在清理后重新运行Make并行构建test1
。
如果在命令行上有多个目标,那么更聪明的解决方案也会重新调用每个单个目标的Make,以便release
目标的存在不会强制其余目标执行非也是平行的。
ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
$(sort all $(MAKECMDGOALS)):
@$(MAKE) -f $(firstword $(MAKEFILE_LIST)) $@
else
# ...
endif
上面的巧妙解决方案不适用于不支持作业服务器的GNU make版本。例如,在版本4.0之前发布的GNU make的MinGW /本机版本不支持作业服务器。 (GNU make的Cygwin / MSYS版本。)下面的代码使用make 3.81中引入的.FEATURES
variable来检测是否支持作业服务器。在需要时不使用此解决方法的症状是您的“并行”构建将被序列化。
# 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
答案 2 :(得分:1)
在发布案例中,您需要确保在任何编译之前完成clean
。因此,您(只)将其作为依赖项添加到编译规则(而不是虚假目标)。有几种方法可以做到这一点,比如特定于目标的变量,或者:
$(OBJDIR)/%.o: %.cpp $(if $(filter release,${MAKECMDGOALS}),clean)
...
答案 3 :(得分:0)
我不确定支持此功能的版本,但您可以使用order-only
功能:
my_target: dep1 dep2 | must_run_1st must_run_2nd
正常处理|
字符左侧的所有依赖项。 |
右侧的依赖关系运行'仅限订单'
此功能描述于:
在您的情况下,以下规则定义就足够了:
release: | clean test1
test1: | clean
答案 4 :(得分:-1)
对于没有make的递归调用的解决方案,你可以试试这个。
ifneq ($(filter release,$(MAKECMDGOALS)),)
test1: clean
endif