9

関連:Makefileの前提条件としてのターゲット固有の変数

ターゲット固有の変数を使用してオブジェクトファイルと最終的な実行可能ファイルの出力ディレクトリを指定するMakefileを作成しようとしています。アイデアは、2つの別々のバイナリバージョン、「リリース」バージョンと「デバッグ」バージョンを維持し、追加のデバッグ情報を提供することです。

私の問題は、「make」は、何も変更していなくても、毎回クリーンビルドを実行することです。'make'が'debug'または'release'ターゲットの前提条件の変数宣言の前に、ターゲット'corewars'の前提条件を評価しているためだと確信しています。

Makefileを以下に示します。

CXX=g++
LD=g++
LDFLAGS=
CXXFLAGS=-Iinclude -Wall -Wextra
OBJECTS=main.o Machine.o Core.o ProcessQueue.o Instruction.o
OUTPUT_DIR:=Test/

.PHONY: default
.PHONY: all
.PHONY: release
default: release
all: release
release: OUTPUT_DIR:=Release/
release: corewars

.PHONY: debug
debug: CXXFLAGS+=-DDEBUG -g
debug: OUTPUT_DIR:=Debug/
debug: corewars

corewars: $(OUTPUT_DIR) $(addprefix $(OUTPUT_DIR),$(OBJECTS))
    $(LD) -o $(addprefix $(OUTPUT_DIR),corewars) $(addprefix $(OUTPUT_DIR),$(OBJECTS))

Release:
    mkdir -p $@
Debug:
    mkdir -p $@

%.o: %.cpp include/%.h
    $(CXX) -c $(CXXFLAGS) $< -o $(OUTPUT_DIR)$@


.PHONY: clean
clean:
    $(RM) -r Release
    $(RM) -r Debug
4

2 に答える 2

15

まず第一に、非偽のレシピは、ではなく、ターゲットを作成する必要があり$@$(OUTPUT_DIR)$@ます。また、ディレクトリの依存関係を注文のみの前提条件に変換することも検討してください。

$(OUTPUT_DIR)前提条件のリスト内の適切な値を取得するには、セカンダリ拡張OUTPUT_DIR:=Test/を使用する必要があります。そうしないと、プライマリ拡張中に、ターゲット固有の定義の代わりにグローバル定義が使用されるためです。

残念ながら、二次展開とvpathマジックに頼らずに、ターゲット固有の変数を使用してそれを機能させるための正しい方法を考えることはできません。個人的には、最初に環境をセットアップして(の値OUTPUT_DIRなどを調べて)、適切な値でMakeを再実行したいと思います。

ifndef OUTPUT_DIR

.PHONY: default all release debug

default all: release

release: export OUTPUT_DIR := Release/
debug:   export OUTPUT_DIR := Debug/
debug:   export EXTRA_CXXFLAGS := -DDEBUG -g

release debug:
    @$(MAKE)

else

# ...
CXXFLAGS := -Iinclude -Wall -Wextra $(EXTRA_CXXFLAGS)

PROGRAM := $(OUTPUT_DIR)corewars
OBJECTS := $(addprefix $(OUTPUT_DIR), \
    main.o Machine.o Core.o ProcessQueue.o Instruction.o)

# Default target.
$(PROGRAM): $(OBJECTS) | $(OUTPUT_DIR)
    $(LD) -o $@ $<

$(OUTPUT_DIR)%.o: %.cpp | $(OUTPUT_DIR)
    $(CXX) -c $(CXXFLAGS) $< -o $@

$(OUTPUT_DIR):
    mkdir -p $@

endif # OUTPUT_DIR

2つの部分を別々のmakefileに分割して、ルート(スターター)と実際の作業を実行して、全体をより管理しやすくすることができます。

于 2012-05-30T22:28:19.053 に答える
1

ターゲット固有の変数は、ターゲットのレシピとその再帰的な前提条件のコンテキスト内でのみ使用できます。つまり、ターゲット固有の変数をターゲットまたは前提条件として使用することはできません

回避策の1つは、そこにあるmakefileです。

于 2020-06-12T18:35:23.700 に答える