How can I configure my makefile for debug and release builds?

后端 未结 7 572
借酒劲吻你
借酒劲吻你 2020-12-12 08:41

I have the following makefile for my project, and I\'d like to configure it for release and debug builds. In my code, I have lots of #ifdef DEBUG macros in plac

相关标签:
7条回答
  • 2020-12-12 09:26

    Note that you can also make your Makefile simpler, at the same time:

    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
    

    Now you don't have to repeat filenames all over the place. Any .l files will get passed through flex and gcc, any .y files will get passed through bison and g++, and any .cpp files through just g++.

    Just list the .o files you expect to end up with, and Make will do the work of figuring out which rules can satisfy the needs...

    for the record:

    • $@ The name of the target file (the one before the colon)

    • $< The name of the first (or only) prerequisite file (the first one after the colon)

    • $^ The names of all the prerequisite files (space separated)

    • $* The stem (the bit which matches the % wildcard in the rule definition.

    0 讨论(0)
  • 2020-12-12 09:31

    You can use Target-specific Variable Values. Example:

    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
    

    Remember to use $(CXX) or $(CC) in all your compile commands.

    Then, 'make debug' will have extra flags like -DDEBUG and -g where as 'make' will not.

    On a side note, you can make your Makefile a lot more concise like other posts had suggested.

    0 讨论(0)
  • 2020-12-12 09:33

    This question has appeared often when searching for a similar problem, so I feel a fully implemented solution is warranted. Especially since I (and I would assume others) have struggled piecing all the various answers together.

    Below is a sample Makefile which supports multiple build types in separate directories. The example illustrated shows debug and release builds.

    Supports ...

    • separate project directories for specific builds
    • easy selection of a default target build
    • silent prep target to create directories needed for building the project
    • build-specific compiler configuration flags
    • GNU Make's natural method of determining if project requires a rebuild
    • pattern rules rather than the obsolete suffix rules

    #
    # 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)
    
    0 讨论(0)
  • 2020-12-12 09:34

    Completing the answers from earlier... You need to reference the variables you define info in your commands...

    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
    
    0 讨论(0)
  • 2020-12-12 09:37

    You could also add something simple to your Makefile such as

    ifeq ($(DEBUG),1)
       OPTS = -g
    endif
    

    Then compile it for debugging

    make DEBUG=1

    0 讨论(0)
  • 2020-12-12 09:38

    If by configure release/build, you mean you only need one config per makefile, then it is simply a matter and decoupling CC and CFLAGS:

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

    Depending on whether you can use gnu makefile, you can use conditional to make this a bit fancier, and control it from the command line:

    DEBUG ?= 1
    ifeq ($(DEBUG), 1)
        CFLAGS =-DDEBUG
    else
        CFLAGS=-DNDEBUG
    endif
    
    .o: .c
        $(CC) -c $< -o $@ $(CFLAGS)
    

    and then use:

    make DEBUG=0
    make DEBUG=1
    

    If you need to control both configurations at the same time, I think it is better to have build directories, and one build directory / config.

    0 讨论(0)
提交回复
热议问题