CXXFLAGS not being appended in makefile - makefile

I have a makefile that I want to be able to produce both a release build and a debug build. When I just run:
make
I want the CXXFLAGS to be:
-std=c++11 -Isrc/includes -c -Os
and when I run
make debug
I want the CXXFLAGS to be
-std=c++11 -Isrc/includes -c -g
I am trying to do this through he use of phony targets and appending the extra flags to the CXXFLAGS variable, however these extra flags are never being appended. why is it that make debug still produces:
g++ -std=c++11 -Isrc/includes -c src/file.cpp -o build/obj/file.o
and not the expected
g++ -std=c++11 -Isrc/includes -c -g src/file.cpp -o build/obj/file.o
when it is run?
contents of makefile:
vpath %.cpp src/macro
vpath %.cpp src/data_types
vpath %.hpp src/includes
vpath %.cpp src
CXX := g++
CXXFLAGS := -std=c++11 -Isrc/includes -c
LXX = g++
LXXFLAGS :=
BUILDDIR := build
OBJDIR := $(BUILDDIR)/obj
SRCS := $(notdir $(shell find -name '*.cpp'))
OBJS := $(patsubst %.cpp, $(OBJDIR)/%.o, $(SRCS))
all: release aval
aval: builddir $(OBJS) $(SRCS)
$(LXX) $(LXXFLAGS) $(OBJS) -o $(BUILDDIR)/aval
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $^ -o $#
.PHONY: release
release: CXXFLAGS += -Os
release: LXXFLAGS += -s -Os
.PHONY: debug
debug: clean db aval
.PHONY: db
db: CXXFLAGS += -g
.PHONY: builddir
builddir:
#mkdir -p $(OBJDIR)
.PHONY: clean
clean:
#rm -f -r build/obj/*.o
#rm -f build/avalanche

the issue with what you are doing is that you are editing the CXXFLAGS in the dependency list of a rule which won't work because of the way the make file is parsed.
Another way - and really easy, and saves you recursively calling make - which I don't see as particularly evil - but some do. Its certainly less complicated this way I find.
CXXFLAGS = defaults
ifneq (,$(findstring release,$(MAKECMDGOALS)))
CXXFLAGS += release
else ifneq (,$(findstring debug,$(MAKECMDGOALS)))
CXXFLAGS += debug
endif
all:
#echo CXXFLAGS = $(CXXFLAGS)
# Rules for release / debug. The `; #:` part means the body of the rule is empty (do nothing). It just "calls" the dependency rule `all`.
release: all ; #:
debug: all ; #:
So here we are looking at the command goals and "parsing them" to look for your options and add to the flags.
We also need rules for debug and release to call the build rule (which I am calling all for the moment).
Here is the output:
admin#osboxes:~/sandbox/flags$ make
CXXFLAGS = defaults
admin#osboxes:~/sandbox/flags$ make release
CXXFLAGS = defaults release
admin#osboxes:~/sandbox/flags$ make debug
CXXFLAGS = defaults debug

The approach you have chosen does not work, because
db: CXXFLAGS += -g
means that the variable CXXFLAGS is updated to include -g for the goal db, but no other goal. I.e. this change is not global like you intended it to be.
The following would be one way of implementing what you intended:
.PHONY: all release
# NOTE: must be first goal in Makefile to be default goal
all release:
$(MAKE) -f $(lastword $(MAKEFILE_LIST)) BUILD_CXXFLAGS="-Os" BUILD_LXXFLAGS="-s -Os" build
.PHONY: debug
debug:
$(MAKE) -f $(lastword $(MAKEFILE_LIST)) BUILD_CXXFLAGS="-g" BUILD_LXXFLAGS="-g" build
.PHONY: build
build: clean aval
CXX := g++
CXXFLAGS := $(BUILD_CXXFLAGS) -std=c++11 -Isrc/includes -c
LXX = g++
LXXFLAGS := $(BUILD_LXXFLAGS)
# ... and the rest of your original Makefile ...
With build implemented as a dummy echo, I get the following output from the above:
$ make -s
CXX '-Os -std=c++11 -Isrc/includes -c' LXX '-s -Os'
$ make -s all
CXX '-Os -std=c++11 -Isrc/includes -c' LXX '-s -Os'
$ make -s release
CXX '-Os -std=c++11 -Isrc/includes -c' LXX '-s -Os'
$ make -s debug
CXX '-g -std=c++11 -Isrc/includes -c' LXX '-g'
BTW: you also need to add -g to LXXFLAGS, otherwise you won't get a debug binary.

Related

Makefile with multiple programs with debug and release modes?

I've written simple calculator in C++, and decided to separate lexer+parser and actual "frontends" which can be GUI or command-line. Project structure looks like that:
src/
parser.hpp
parser.cpp
scanner.hpp
scanner.cpp
exceptions.hpp
term-calc.cpp
gui-calc.cpp
Makefile
Obviously parser and scanner should be compiled into object files separately, and term-calc and gui-calc separately. Furthermore I want to have debug builds and release builds,
so I imagine final project structure like that:
src/
...
obj/
debug/
parser.o
scanner.o
...
release/
parser.o
scanner.o
...
out/
debug/
term-calc
gui-calc
release/
term-calc
gui-calc
Makefile
I'm pretty new to Makefiles but this is what I came up with so far (I've ommited automatic dependency generation for now):
CXX := g++
CXXFLAGS := -std=c++17 -pedantic -Wall -Wextra -fno-rtti
SRCDIR := $(CURDIR)/src # sources
OBJDIR := $(CURDIR)/obj # objects
INCDIR := $(CURDIR)/inc # generated dependencies
OUTDIR := $(CURDIR)/out # executables
# target programs
TERM_CALC := term-calc
GUI_CALC := gui-calc
all: debug
# debug flags
debug: CXXFLAGS += -O0 -g -fsanitize=address
# debug objects and executables go into /debug subdirectory
debug: OBJDIR += /debug
debug: OUTDIR += /debug
# release flags
release: CXXFLAGS += -Os -ffunction-sections -fdata-sections -flto -fno-ident
release: LDFLAGS += -Wl,-gc-sections -s -flto
# release objects and executables go into /release subdirectory
release: OBJDIR += /release
release: OUTDIR += /release
# common objects
OBJECTS := $(OBJDIR)/scanner.o $(OBJDIR)/parser.o
# target-specific objects
$(TERM_CALC): OBJECTS += $(OBJDIR)/term-calc.o
$(GUI_CALC): OBJECTS += $(OBJDIR)/gui-calc.o
# TARGET_NAME is name of program to build
# ensure it is valid, if defined
ifdef TARGET_NAME
ifneq ($(TARGET_NAME),$(TERM_CALC))
ifneq ($(TARGET_NAME),$(GUI_CALC))
$(error Invalid target name '$(TARGET_NANE)')
endif
endif
endif
ifdef TARGET_NAME
# how to build target program
$(TARGET_NAME): $(OUTDIR)/$(TARGET_NAME)
$(OUTDIR)/$(TARGET_NAME): $(OBJECTS)
#mkdir -p $(OUTDIR)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $^ -o $#
endif
# how to build objects
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(OBJDIR)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $#
# if TARGET_NAME is not specified, just compile objects
TARGET_NAME ?= $(OBJECTS)
debug : $(TARGET_NAME)
release : $(TARGET_NAME)
# clean everything
clean:
$(RM) -r $(OBJDIR) $(OUTDIR) $(INCDIR)
.PHONY = all debug release clean
Unfortunately it absolutely does not work, while writing this makefile, I was getting many errors but even after fixing all of them as I thought, I still get:
Makefile:52: *** mixed implicit and normal rules: deprecated syntax
make: *** No rule to make target '/%.cpp', needed by '/root/cpp/calc/obj'. Stop.

Makefile that rebuilds all if compiled with dif flags

So I am having a little bit of a tough time trying to figure out how to make my Makefile so that when I do make and it compiles a release version then later on do a make debug it compiles a debug version with the new -DDEBUG and -g set on gcc if the files have not been updated.
For example:
main.cpp is edited
run make
compiles main.cpp
run make debug
main.cpp is not recompiled because there were no changes even though the flags for compilation differ
Note I don't want to have to do a clean each time either because I dont want to have to recompile files if I do 2 makes in a row so setting clean as a dependency is not going to be a valid answer here
You may like to compile object files into a different directory depending on the build mode, e.g.:
# default mode, override with `make BUILD=release`
BUILD := debug
obj_dir := ${BUILD}
CFLAGS.debug := -g -O0
CFLAGS.release := -g -O3 -march=native -DNDEBUG
all : ${obj_dir}/test
# Example executable
${obj_dir}/test : ${obj_dir}/test.o
test.c :
echo "int main() { return 0; }" > $#
# Generic rules
${obj_dir} :
mkdir $#
${obj_dir}/%.o : %.c Makefile | ${obj_dir} # Also recompile when Makefile changes.
${CC} -c -o $# ${CPPFLAGS} ${CFLAGS} ${CFLAGS.${BUILD}} -MD -MP $<
${obj_dir}/% : Makefile | ${obj_dir} # Also re-link when Makefile changes.
${CC} -o $# ${LDFLAGS} $(filter-out Makefile,$^) ${LDLIBS}
clean :
rm -rf ${obj_dir}
-include $(wildcard ${obj_dir}/*.d)
${obj_dir}/*.d : ;
.PHONY: all clean
(Bonus feature: automatic dependency generation).
Usage:
[max#localhost:~/tmp] $ make
mkdir debug
echo "int main() { return 0; }" > test.c
cc -c -o debug/test.o -g -O0 -MD -MP test.c
cc -o debug/test debug/test.o
[max#localhost:~/tmp] $ make
make: Nothing to be done for 'all'.
[max#localhost:~/tmp] $ make BUILD=release
mkdir release
cc -c -o release/test.o -g -O3 -march=native -DNDEBUG -MD -MP test.c
cc -o release/test release/test.o
[max#localhost:~/tmp] $ make BUILD=release
make: Nothing to be done for 'all'.
First of all, you should not run make debug - that would mean, you want to build a different target (debug). But you don't, you want to build the same target, just with different options. That's what you do, you run a different option, a variable value
>make DEBUG=Y
When you run
>make
you also pass that variable really, just with the empty string as value.
Now, in order for this to work as you want in the Makefile, you would want to make it as if DEBUG was a prerequisite file, with recipes like this:
foobar.o: foobar.c DEBUG
gcc $(if $(DEBUG), -DDEBUG -g) -c $< -o $#
Of course, normally this won't work, because DEBUG is a variable, not a file. So you need a hack, that I call "dependable variables". It is basically a way to declare a variable to behave like a file. I describe this technique in one of my other answers:
How do I add a debug option to Makefile
I once did something like this, it looked like that (boiled down to the minimum):
EXE := a.out
SRC := $(wildcard *.c)
ifneq ($(MAKECMDGOALS),debug)
OBJ := $(SRC:.c=.o)
else
OBJ := $(SRC:.c=-d.o)
endif
.PHONY: all debug
all: $(EXE)
debug: CFLAGS += -g -DDEBUG
debug: $(EXE)
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
%.o %-d.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
The trick is to use two separate list of object files, and select one depending of the target.

Eclipse CDT MinGW - Make skips rules, no such file or directory error

I am trying to create debug and release configurations for a project, and I just can't figure out what is wrong.
For some reason, when I do 'make debug', make skips the dependencies for 'all', giving me a bunch of errors from g++ (no such file or directory). Even weirder is that if I do 'make all', everything works just fine.
Here is the makefile:
SHELL=/bin/sh
CXX=g++
LIBS=-LE:\Software\StrategyEngine\Release -llibdebug
CFLAGS=-Wall -O3 -IE:\Software\StrategyEngine\include
BDIR=Build\Release
debug: CFLAGS+=-g -DDEBUG
debug: LIBS=-LE:\Software\StrategyEngine\Debug -llibdebug
debug: BDIR=Build\Debug
OBJS= $(BDIR)\blocksort.o \
#... more object files
$(BDIR)\CompressionStream.o
debug: all
all: $(OBJS)
$(CXX) $(LIBS) -shared -o $(BDIR)\libbz2.dll $(OBJS)
$(CXX) $(LIBS) $(CFLAGS) -o $(BDIR)\bzip2-shared bzip2.cpp $(BDIR)\libbz2.dll
$(BDIR)\blocksort.o: blocksort.cpp
$(CXX) $(CFLAGS) -c blocksort.cpp -o $(BDIR)\blocksort.o
#.... more rules for each object file defined in OBJS
clean:
rm -f Build\debug\* Build\release\*
Why is this happening? I can't find any error in the makefile.
I am using the mingw compiler suite (make version 3.81), running on windows 7.
The object file location BDIR in your makefile doesn't change depending on the build mode.
I suggest refactoring the script as follows:
SHELL=/bin/sh
CXX=g++
BUILD := debug # default mode
CFLAGS.release := -Wall -O3 -IE:/Software/StrategyEngine/include -D_NDEBUG
CFLAGS.debug := -Wall -g -IE:/Software/StrategyEngine/include -DDEBUG
LIBS.release := -LE:/Software/StrategyEngine/Release -llibdebug
LIBS.debug := -LE:/Software/StrategyEngine/Debug -llibdebug
BDIR.release := Build/Release
BDIR.debug := Build/Debug
CFLAGS := ${CFLAGS.${BUILD}}
LIBS := ${LIBS.${BUILD}}
BDIR := ${BDIR.${BUILD}}
OBJS= $(BDIR)/blocksort.o /
#... more object files
$(BDIR)/CompressionStream.o
all: $(OBJS)
$(CXX) $(LIBS) -shared -o $(BDIR)/libbz2.dll $(OBJS)
$(CXX) $(LIBS) $(CFLAGS) -o $(BDIR)/bzip2-shared bzip2.cpp $(BDIR)/libbz2.dll
$(BDIR)/blocksort.o: blocksort.cpp
$(CXX) $(CFLAGS) -c blocksort.cpp -o $(BDIR)/blocksort.o
#.... more rules for each object file defined in OBJS
clean:
rm -f Build/debug/* Build/release/*
.PHONY: all clean
And use it like:
make BUILD=debug
make BUILD=release

Making a better Makefile

so I learned what a Makefile was some time ago, created a template Makefile and all I do is copy and alter the same file for every program I'm doing. I changed it a few times, but it's still a very crude Makefile. How should I improve it? This is an example of my current version:
CC = g++
CFLAGS = -std=gnu++0x -m64 -O3 -Wall
IFLAGS = -I/usr/include/igraph
LFLAGS = -ligraph -lgsl -lgslcblas -lm
DFLAGS = -g -pg
# make all
all: run test
# make a fresh compilation from scratch
fresh: clean test
#makes the final executable binary
run: main.o foo1.o foo2.o
$(CC) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes the test executable with debugging and profiling tags
test: test.o foo1.o foo2.o
$(CC) $(DFLAGS) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes teste.o
teste.o: teste.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#makes main.o
main.o: main.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo1
foo1.o: foo1.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo2
foo2.o: foo2.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
clean: clean-test clean-o clean-annoying
clean-test:
rm test-rfv
clean-o:
rm *.o -rfv
clean-annoying:
rm *~ -rfv
Just by visually comparing with other makefiles I saw around in the web, this seems to be not a very bright Makefile. I don't know how they work, but I can see there's significantly less boilerplate and more generic code in them.
Can this can be made better, safer, and easier to particularize for each project?
You don't want to name specific files in a makefile if you can get away with it, and 99% of the time you can. This page shows how to develop a very general makefile. The following is my own makefile, based on that page's info:
SHELL := bash
PROG := pathed.exe
OUTDIRS := bin/debug bin/rel obj/debug obj/rel
PROG_REL := bin/rel/$(PROG)
PROG_DEBUG := bin/debug/$(PROG)
SRCFILES := $(wildcard src/*.cpp)
OBJFILES_REL := $(patsubst src/%.cpp,obj/rel/%.o,$(SRCFILES))
OBJFILES_DEBUG := $(patsubst src/%.cpp,obj/debug/%.o,$(SRCFILES))
DEPFILES := $(patsubst src/%.cpp,obj/%.d,$(SRCFILES))
CFLAGS := -Iinc -Wall -Wextra -MMD -MP
DBFLAGS := -g
RELFLAGS :=
CC := g++
.PHONY: default all testmake debug release clean dirs
default: debug
all: dirs clean debug release
dirs:
#mkdir -p $(OUTDIRS)
debug: $(PROG_DEBUG)
release: $(PROG_REL)
testmake:
#echo OBJFILES_REL = $(OBJFILES_REL)
#echo OBJFILES_DEBUG = $(OBJFILES_DEBUG)
#echo SRCFILES = $(SRCFILES)
#echo DEPFILES = $(DEPFILES)
clean:
rm -f $(OBJFILES_REL) $(OBJFILES_DEBUG) $(DEPFILES) $(PROG)
$(PROG_REL): $(OBJFILES_REL)
$(CC) $(OBJFILES_REL) -o $(PROG_REL)
strip $(PROG_REL)
#echo "---- created release binary ----"
$(PROG_DEBUG): $(OBJFILES_DEBUG)
$(CC) $(OBJFILES_DEBUG) -o $(PROG_DEBUG)
#echo "---- created debug binary ----"
-include $(DEPFILES)
obj/rel/%.o: src/%.cpp
$(CC) $(RELFLAGS) $(CFLAGS) -MF $(patsubst obj/rel/%.o, obj/%.d,$#) -c $< -o $#
obj/debug/%.o: src/%.cpp
$(CC) $(DBFLAGS) $(CFLAGS) -MF $(patsubst obj/debug/%.o, obj/%.d,$#) -c $< -o $#
Do NOT use CC for the C++ compiler. The standard convention is that CC is the C compiler, CXX is the C++ compiler. CFLAGS are flags for the C compiler, CXXFLAGS are flags for the C++ compiler, and CPPFLAGS are flags for the pre-processor (eg, -I or -D flags). Use LDFLAGS for -L flags to the linker, and LDLIBS (or LOADLIBES) for -l flags.
Using the standard conventions is good not just because it makes things easier for others to understand, but also because it allows you to take advantage of implicit rules. If make needs to make a .o file from a .c file and you have not provided a rule, it will use a standard rule and honor the settings of CC, CFLAGS, and CPPFLAGS. If CC is a C++ compiler, things will probably not work.

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

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 place, so it's simply a matter of setting this macro and adding the -g3 -gdwarf2 flags to the compilers. How can I do this?
$(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
Just to clarify, when I say release/debug builds, I want to be able to just type make and get a release build or make debug and get a debug build, without manually commenting out things in the makefile.
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.
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)
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.
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.
you can have a variable
DEBUG = 0
then you can use a conditional statement
ifeq ($(DEBUG),1)
else
endif
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
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

Resources