web-dev-qa-db-ja.com

デバッグおよびリリースビルド用にメイクファイルを構成するにはどうすればよいですか?

私のプロジェクトには次のメイクファイルがあり、リリースおよびデバッグビルド用に構成したいと思います。私のコードでは、たくさんの#ifdef DEBUGマクロが用意されているので、このマクロを設定し、コンパイラに-g3 -gdwarf2フラグを追加するだけです。これどうやってするの?

$(CC) = g++ -g3 -gdwarf2
$(cc) = gcc -g3 -gdwarf2

all: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    g++ -g -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    gcc -g -c CommandParser.yy.c

CommandParser.tab.o: CommandParser.y
    bison -d CommandParser.y
    g++ -g -c CommandParser.tab.c

Command.o: Command.cpp
    g++ -g -c Command.cpp

clean:
    rm -f CommandParser.tab.* CommandParser.yy.* output *.o

明確にするために、リリース/デバッグビルドを言うときは、makeを入力してリリースビルドまたはmake debugを取得し、デバッグファイルを手動でコメントアウトせずに取得できるようにします。

162
samoz

ターゲット固有の変数値 を使用できます。例:

CXXFLAGS = -g3 -gdwarf2
CCFLAGS = -g3 -gdwarf2

all: executable

debug: CXXFLAGS += -DDEBUG -g
debug: CCFLAGS += -DDEBUG -g
debug: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    $(CC) -c CommandParser.yy.c

すべてのコンパイルコマンドで、必ず$(CXX)または$(CC)を使用してください。

次に、「make debug」には-DDEBUGや-gのような追加フラグがありますが、「make」にはありません。

補足として、他の投稿が示唆したように、Makefileをより簡潔にすることができます。

174
David Lin

リリース/ビルドを構成することにより、メイクファイルごとに1つの構成のみが必要な場合、それは単に問題であり、CCとCFLAGSを切り離すことです:

CFLAGS=-DDEBUG
#CFLAGS=-O2 -DNDEBUG
CC=g++ -g3 -gdwarf2 $(CFLAGS)

Gnu makefileを使用できるかどうかに応じて、条件を使用してこれを少し見栄えよくし、コマンドラインから制御できます。

DEBUG ?= 1
ifeq ($(DEBUG), 1)
    CFLAGS =-DDEBUG
else
    CFLAGS=-DNDEBUG
endif

.o: .c
    $(CC) -c $< -o $@ $(CFLAGS)

次に使用します:

make DEBUG=0
make DEBUG=1

両方の構成を同時に制御する必要がある場合は、ビルドディレクトリと1つのビルドディレクトリ/ configがある方が良いと思います。

39

この問題は、同様の問題を検索するときに頻繁に発生するため、完全に実装されたソリューションが必要であると感じています。特に、私(および他の人もそう思います)は、さまざまな答えをすべてつなぎ合わせるのに苦労しています。

以下は、別々のディレクトリで複数のビルドタイプをサポートするサンプルMakefileです。図の例は、デバッグおよびリリースビルドを示しています。

サポート...

  • 特定のビルド用の個別のプロジェクトディレクトリ
  • デフォルトのターゲットビルドの簡単な選択
  • プロジェクトのビルドに必要なディレクトリを作成するためのサイレント準備ターゲット
  • ビルド固有のコンパイラー構成フラグ
  • プロジェクトに再構築が必要かどうかを判断するGNU Makeの自然な方法
  • 廃止された接尾辞規則ではなくパターン規則

#
# Compiler flags
#
CC     = gcc
CFLAGS = -Wall -Werror -Wextra

#
# Project files
#
SRCS = file1.c file2.c file3.c file4.c
OBJS = $(SRCS:.c=.o)
EXE  = exefile

#
# Debug build settings
#
DBGDIR = debug
DBGEXE = $(DBGDIR)/$(EXE)
DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS))
DBGCFLAGS = -g -O0 -DDEBUG

#
# Release build settings
#
RELDIR = release
RELEXE = $(RELDIR)/$(EXE)
RELOBJS = $(addprefix $(RELDIR)/, $(OBJS))
RELCFLAGS = -O3 -DNDEBUG

.PHONY: all clean debug prep release remake

# Default build
all: prep release

#
# Debug rules
#
debug: $(DBGEXE)

$(DBGEXE): $(DBGOBJS)
    $(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^

$(DBGDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $@ $<

#
# Release rules
#
release: $(RELEXE)

$(RELEXE): $(RELOBJS)
    $(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^

$(RELDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) $(RELCFLAGS) -o $@ $<

#
# Other rules
#
prep:
    @mkdir -p $(DBGDIR) $(RELDIR)

remake: clean all

clean:
    rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)
36
ffhaddad

Makefileをより簡単にすることもできることに注意してください:

DEBUG ?= 1
ifeq (DEBUG, 1)
    CFLAGS =-g3 -gdwarf2 -DDEBUG
else
    CFLAGS=-DNDEBUG
endif

CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)

EXECUTABLE = output
OBJECTS = CommandParser.tab.o CommandParser.yy.o Command.o
LIBRARIES = -lfl

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CXX) -o $@ $^ $(LIBRARIES)

%.yy.o: %.l 
    flex -o $*.yy.c $<
    $(CC) -c $*.yy.c

%.tab.o: %.y
    bison -d $<
    $(CXX) -c $*.tab.c

%.o: %.cpp
    $(CXX) -c $<

clean:
    rm -f $(EXECUTABLE) $(OBJECTS) *.yy.c *.tab.c

これで、あちこちでファイル名を繰り返す必要がなくなりました。 .lファイルはflexとgccを、.yファイルはbisonとg ++を、.cppファイルはg ++を介して渡されます。

最終的に期待される.oファイルをリストするだけで、Makeはどのルールがニーズを満たすことができるかを判断します...

記録のために:

  • $@ターゲットファイルの名前(コロンの前のもの)

  • $<最初の(または唯一の)前提条件ファイルの名前(コロンの後の最初のファイル)

  • $^すべての前提条件ファイルの名前(スペース区切り)

  • $*ステム(ルール定義の%ワイルドカードに一致するビット。

23
Stobor

あなたは変数を持つことができます

DEBUG = 0

その後、条件文を使用できます

  ifeq ($(DEBUG),1)

  else

  endif
3
Tiberiu

以前の回答を完了する...コマンドで情報を定義する変数を参照する必要があります...

DEBUG ?= 1
ifeq (DEBUG, 1)
    CFLAGS =-g3 -gdwarf2 -DDEBUG
else
    CFLAGS=-DNDEBUG
endif

CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)

all: executable

executable: CommandParser.tab.o CommandParser.yy.o Command.o
    $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl

CommandParser.yy.o: CommandParser.l 
    flex -o CommandParser.yy.c CommandParser.l
    $(CC) -c CommandParser.yy.c

CommandParser.tab.o: CommandParser.y
    bison -d CommandParser.y
    $(CXX) -c CommandParser.tab.c

Command.o: Command.cpp
    $(CXX) -c Command.cpp

clean:
    rm -f CommandParser.tab.* CommandParser.yy.* output *.o
1
Stobor