私は次の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」を呼び出そうとすると、ファイルのビルド中にクリーンターゲットが実行されることが多く、コンパイルが失敗します。私の質問は、リリースビルドを開始する前にクリーンターゲットが完了したことを確認する方法です。
私の好みは
release:
$(MAKE) clean
$(MAKE) test1
これにより、2つのターゲットは、内部の並列処理(存在する場合)を妨げることなく、連続して作成されます。
実行を非並列(release
の場合)フェーズと並列(残りのターゲットの場合)フェーズに分割できます。
ifneq ($(filter release,$(MAKECMDGOALS)),)
.NOTPARALLEL:
endif
release: clean
$(MAKE) test1
.NOTPARALLEL
targetは、コマンドラインでrelease
targetが指定されている場合、並列実行を抑制します。 release
ターゲット自体は、クリーニングおよびビルド後にMakeを再実行しますtest1
並行して。
コマンドラインに複数のターゲットが指定されている場合、より巧妙なソリューションでは、単一のターゲットごとにMakeが再度呼び出されるため、release
ターゲットが存在しても、残りのターゲットが非並列で実行されることはありません。 。
ifneq ($(words $(MAKECMDGOALS)),1)
.NOTPARALLEL:
$(sort all $(MAKECMDGOALS)):
@$(MAKE) -f $(firstword $(MAKEFILE_LIST)) $@
else
# ...
endif
上記の巧妙なソリューションは、ジョブサーバーをサポートしないバージョンのGNU makeでは機能しません。たとえば、リリースされたMinGW /ネイティブビルドのGNU makeバージョン4.0より前では、ジョブサーバーはサポートされていません(Cygwin/MSYSビルドのGNU make do。))以下のコードは .FEATURES
variable ジョブサーバーがサポートされているかどうかを検出するためにmake3.81で導入されました。必要なときにこの回避策を使用しない場合の症状は、「並列」ビルドがシリアル化されることです。
# 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
リリースの場合、anyコンパイルする前にclean
が完了することを確認する必要があります。したがって、(偽のターゲットではなく)コンパイルルールへの依存関係として(ただ)それを追加します。ターゲット固有の変数など、これを行ういくつかの方法、または:
$(OBJDIR)/%.o: %.cpp $(if $(filter release,${MAKECMDGOALS}),clean)
...
この機能がサポートされているバージョンは正確にはわかりませんが、order-only
機能を使用できます。
my_target: dep1 dep2 | must_run_1st must_run_2nd
|
文字の左側にあるすべての依存関係は通常どおり処理されます。 |
の右側の依存関係は「順序のみ」で実行されます
この機能については、次の場所で説明しています。
https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
あなたの場合、次のルール定義で十分です。
release: | clean test1
test1: | clean