Jak mogę skonfigurować plik makefile dla wersji debugowania i Wydania?

Mam następujący plik makefile dla mojego projektu i chciałbym go skonfigurować do wydania i debugowania kompilacji. W kodzie mam mnóstwo makr #ifdef DEBUG, więc jest to po prostu kwestia ustawienia tego makra i dodania Flag -g3 -gdwarf2 do kompilatorów. Jak mogę to zrobić?

$(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

Dla jasności, kiedy mówię release / debug builds, chcę być w stanie po prostu wpisać make i uzyskać release build lub make debug i uzyskać debug build, bez ręcznego komentowania rzeczy w pliku makefile.

Author: nbro, 2009-07-03

6 answers

Możesz użyć wartości zmiennych specyficznych dla Celu . Przykład:

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

Pamiętaj, aby używać $(CXX) lub $(CC) we wszystkich komend kompilacji.

Wtedy 'make debug' będzie miał dodatkowe flagi, takie jak-DDEBUG i-g, gdzie jako 'make' nie będzie.

Na marginesie, możesz uczynić swój plik Makefile o wiele bardziej zwięzłym, jak sugerowały inne posty.

 160
Author: David Lin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-15 05:26:40

Jeśli przez configure release / build masz na myśli tylko jedną konfigurację na makefile, to jest to po prostu sprawa i oddzielenie CC i CFLAGS:

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

W zależności od tego, czy możesz użyć gnu makefile, możesz użyć warunkowego, aby uczynić to nieco bardziej fantazyjnym i sterować nim z linii poleceń:

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

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

A następnie użyj:

make DEBUG=0
make DEBUG=1

Jeśli chcesz kontrolować obie konfiguracje jednocześnie, myślę, że lepiej mieć katalogi build i jeden katalog build / config.

 37
Author: David Cournapeau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 15:06:03

To pytanie pojawiało się często podczas poszukiwania podobnego problemu, więc uważam, że w pełni wdrożone rozwiązanie jest uzasadnione. Zwłaszcza, że ja (i zakładam, że inni) walczyłem składając wszystkie różne odpowiedzi razem.

Poniżej znajduje się przykładowy plik Makefile, który obsługuje wiele typów kompilacji w oddzielnych katalogach. Ilustrowany przykład pokazuje Debug i release builds.

Podpory ...

  • oddzielne katalogi projektów dla konkretnych budów
  • easy wybór domyślnej budowy celu
  • silent Prep cel do tworzenia katalogów potrzebnych do budowy projektu
  • flagi konfiguracji kompilatora specyficzne dla kompilatora
  • naturalna metoda GNU Make określająca, czy projekt wymaga przebudowy
  • reguły wzorca zamiast przestarzałych reguł sufiksu

#
# 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)
 33
Author: ffhaddad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-29 22:14:36

Zauważ, że możesz również uprościć swój Makefile, w tym samym czasie:

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

Teraz nie musisz powtarzać nazw plików w każdym miejscu. Każdy .pliki l będą przekazywane przez flex i gcc, dowolne .pliki y będą przekazywane przez bison i g++ i dowolne .pliki cpp poprzez g++.

Po prostu wymień .o pliki, które spodziewasz się skończyć z, I Make zrobi pracę zastanawiając się, które zasady mogą zaspokoić potrzeby...

Dla przypomnienia:

  • $@ Na nazwa pliku docelowego (tego przed dwukropkiem)

  • $< Nazwa pierwszego (lub jedynego) pliku warunkowego (pierwszego po dwukropku)

  • $^ nazwy wszystkich plików warunkowych (rozdzielone spacjami)

  • $* Rdzeń (bit, który pasuje do symbolu % w definicji reguły.

 23
Author: Stobor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-05 23:49:21

Możesz mieć zmienną

DEBUG = 0

Wtedy możesz użyć instrukcji warunkowej

  ifeq ($(DEBUG),1)

  else

  endif
 2
Author: Tiberiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-03 15:54:42

Uzupełnianie odpowiedzi z wcześniejszych... Musisz odwoływać się do zmiennych, które definiujesz w poleceniach...

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
Author: Stobor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-03 16:05:01