I'm trying to compile a large C++ project with source files in several subdirectories of src.
My Makefile looks like this:
# ---------- Compiler and linker directives ----------
CXX = g++-11
CXXFLAGS = -std=c++17 -fopenmp -MD -g -Wall -pedantic
# LDFLAGS = -Wl,--gc-sections
# Output directory after linking
BIN_PATH = ../bin
BUILD_PATH = ../build
# ------- System Include --------------
# Change ~/include as necessary for your architecture
INC_FLAGS = -I../include -I/opt/homebrew/include
# -------- Establishing objects and sources ------
RATE_SRC = $(wildcard hartreefock/*.cpp) $(wildcard struct_hartreefock/*.cpp) $(wildcard numerical/*.cpp)
RATE_OBJ = $(addprefix $(BUILD_PATH)/,$(RATE_SRC:.cpp=.o)))
# ------------- Specific Include -----------
# RATE_HEADERS = $(wildcard hartreefock/*.hpp) $(wildcard struct_hartreefock/*.hpp) $(wildcard numerical/*.hpp)
RATE_DIR = hartreefock struct_hartreefock numerical
RATE_INC = $(addprefix -I,$(RATE_DIR))
# ---------- Libraries needed for linking ----------
# Change or remove ~/lib as necessary for your architecture
LIB_PATH = -L/opt/homebrew/lib
# Generic .cc -> .o rule
$(BUILD_PATH)/%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(INC_FLAGS) $(RATE_INC) $< -c -o $#
# ---------- Linking rules ----------
# Generic .o -> exec rule: uses all prerequisites (meant to be .o files)
ratecalc: $(RATE_OBJ)
$(CXX) $(CXXFLAGS) $(INC_PATH) $(A_RATE_INC) $(LDFLAGS) $^ \
$(LIB_PATH) -o $(BIN_PATH)/$#
# TODO
# simulate:
echo:
echo "$(RATE_OBJ)"
echo "$(BUILD_PATH)"
# Cleanup:
.PHONY: clean build_directories
clean:
-rm -r $(BUILD_PATH)/**
Bizarrely, this seems to do the right thing until I get to one specific file:
make clean
make ratecalc
g++-11 -std=c++17 -fopenmp -MD -g -Wall -pedantic -I../include -I/opt/homebrew/include -Ihartreefock -Istruct_hartreefock -Inumerical struct_hartreefock/RateData.cpp -c -o ../build/struct_hartreefock/RateData.o
g++-11 -std=c++17 -fopenmp -MD -g -Wall -pedantic -I../include -I/opt/homebrew/include -Ihartreefock -Istruct_hartreefock -Inumerical numerical/Constant.cpp -c -o ../build/numerical/Constant.o
make: *** No rule to make target `../build/numerical/wignerSymbols.o)', needed by `ratecalc'. Stop.
This is especially strange because Constant.cpp and wignerSymbols.cpp are in the same directory. Manually running with this target compiles the object file as needed,
make ../build/numerical/wignerSymbols.o
g++-11 -std=c++17 -fopenmp -MD -g -Wall -pedantic -I../include -I/opt/homebrew/include -Ihartreefock -Istruct_hartreefock -Inumerical numerical/wignerSymbols.cpp -c -o ../build/numerical/wignerSymbols.o
but this is not recognised as satisfying the dependency for the ratecalc rule.
It might be significant that wignerSymbols.cpp is the very last entry in RATE_OBJ, but to be honest I can't understand what's happening here.
For completeness: I'm using GNU make 3.81 on an M1 macbook air.
Typo:
RATE_OBJ = $(addprefix $(BUILD_PATH)/,$(RATE_SRC:.cpp=.o)))
There is an extra close paren here, which you can see in your error message:
make: *** No rule to make target `../build/numerical/wignerSymbols.o)', ...
Related
I have created the following makefile with reference to this site to try out automatic dependency generation. My makefile works fine when I run it with GNU Make 3.81(the one that comes with macOS). However, if I run it with the newer version of GNU Make(4.3, installed via Homebrew), all the objects and dependency files get recreated every single time when I run make, even though there is no change in the source files.
CXX := clang++
CXXFLAGS := -Wall -Werror -std=c++11
ICUROOT := ${HOME}/opt/icu4c
XERCESCROOT := ${HOME}/opt/xercesc
CPPFLAGS := -I$(ICUROOT)/include -I$(XERCESCROOT)/include
LDFLAGS := -lxerces-c -licuuc
LDLIBS := -L$(ICUROOT)/lib -L$(XERCESCROOT)/lib
OBJDIR := obj
DEPDIR := $(OBJDIR)/.deps
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.d
SRCS = $(wildcard *.cpp)
.PHONY: all
all: DOMPrint
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d | $(DEPDIR)
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(DEPDIR): ; #mkdir -p $#
DEPFILES := $(SRCS:%.cpp=$(DEPDIR)/%.d)
$(DEPFILES): ;
DOMPrint: $(addprefix $(OBJDIR)/,DOMPrint.o DOMPrintFilter.o DOMPrintErrorHandler.o DOMTreeErrorReporter.o)
$(CXX) $(CXXFLAGS) $(LDLIBS) $(LDFLAGS) -o $# $^
-include $(wildcard $(DEPFILES))
Debugging information printed from make --debug(partial), it shows that the dependency file is newer than the target, and the object file is rebuilt:
GNU Make 4.3
Built for arm-apple-darwin21.1.0
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating makefiles....
Updating goal targets....
File 'all' does not exist.
Prerequisite 'obj/.deps/DOMPrintErrorHandler.d' is newer than target 'obj/DOMPrintErrorHandler.o'.
Must remake target 'obj/DOMPrintErrorHandler.o'.
clang++ -MT obj/DOMPrintErrorHandler.o -MMD -MP -MF obj/.deps/DOMPrintErrorHandler.d -Wall -Werror -std=c++11 -I/Users/chunwaichan/opt/icu4c/include -I/Users/chunwaichan/opt/xercesc/include -c -o obj/DOMPrintErrorHandler.o DOMPrintErrorHandler.cpp
Successfully remade target file 'obj/DOMPrintErrorHandler.o'.
...
However, looking at the last modified time in make -p output below(partial), the dependency file isn't newer than the object file, but the automatic variable ? does show that it is newer.
obj/DOMPrintErrorHandler.o: DOMPrintErrorHandler.cpp obj/.deps/DOMPrintErrorHandler.d ...
# Implicit rule search has been done.
# Implicit/static pattern stem: 'DOMPrintErrorHandler'
# Last modified 2022-01-08 10:50:25.517904773
# File has been updated.
# Successfully updated.
# automatic
# ? := obj/.deps/DOMPrintErrorHandler.d
obj/.deps/DOMPrintErrorHandler.d:
# Implicit rule search has not been done.
# Last modified 2022-01-08 09:45:13.890973263
# File has been updated.
# Successfully updated.
# recipe to execute (from 'Makefile', line 32):
I have tested this makefile with GNU Make 3.81 till 4.3, starting from version 4.0, this issue happens. I would like to know what change/enhancement in the newer version of GNU Make has caused this issue and how can I fix my makefile to make it compatible.
I can't reproduce the behavior you see with the standard version of GNU make on my GNU/Linux system. Here is a complete repro case that I used:
$ cat main.h
#define RET 0
$ cat main.cpp
#include "main.h"
int main() { return RET; }
$ cat Makefile
CXX := g++
CXXFLAGS := -Wall -Werror -std=c++11
CPPFLAGS := -I.
OBJDIR := obj
DEPDIR := $(OBJDIR)/.deps
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.d
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:%.cpp=$(OBJDIR)/%.o)
DEPS = $(SRCS:%.cpp=$(DEPDIR)/%.d)
all: main
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d | $(DEPDIR) ; $(COMPILE.cc) $(OUTPUT_OPTION) $<
$(DEPDIR): ; #mkdir -p $#
$(DEPS): ;
main: $(OBJS) ; $(CXX) $(CXXFLAGS) $(LDLIBS) $(LDFLAGS) -o $# $^
clean: ; rm -rf obj main
-include $(wildcard $(DEPS))
$ make
g++ -MT obj/main.o -MMD -MP -MF obj/.deps/foo.d -Wall -Werror -std=c++11 -I. -c -o obj/main.o main.cpp
g++ -Wall -Werror -std=c++11 -o main obj/main.o
$ make
make: Nothing to be done for 'all'.
Also something odd: the output of my make -p does not show any automatic variables, as are shown in your example:
obj/main.o: main.cpp obj/.deps/main.d main.cpp main.h | obj/.deps
# Implicit rule search has been done.
# Implicit/static pattern stem: 'main'
# Last modified 2022-01-08 14:18:05.5745307
# File has been updated.
# Successfully updated.
# recipe to execute (from 'Makefile', line 19):
$(COMPILE.cc) $(OUTPUT_OPTION) $<
Maybe the version of GNU make you are using has some local changes?
If you download the vanilla GNU make source from https://ftp.gnu.org/gnu/make/ and compile that does it work properly?
I really don't know the function of the following part:
ifneq ($(MAKECMDGOALS),clean)
-include $(DFILES)
endif
Here is the possible explanation I get from the GNU make manual:
to avoid including ‘.d’ files during clean rules, so make won’t create
them only to immediately remove them again:
But I don't fully understand "won’t create them only to immediately remove them again".
Here is the Makefile from derivative.tar.bz2 from http://www.dirac.org/linux/gdb/03-Initialization,_Listing,_And_Running.php#wherearewegoingtogo:
TARGET = driver
# CC = colorgcc
CC = gcc
CFILES = $(wildcard *.c)
OFILES = $(patsubst %.c, %.o, $(CFILES))
DFILES = $(patsubst %.c, .deps/%.d, $(CFILES))
WARN = -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return \
-Wpointer-arith -Wcast-qual -Wcast-align -Wmissing-declarations -pedantic \
-Wnested-externs -Wredundant-decls -Wwrite-strings -Winline -Werror
CFLAGS = -std=c99 $(WARN) -g3
LDLIBS = -lm
all: $(TARGET)
ctags *.c *.h
$(TARGET): $(OFILES)
$(CC) -o $(TARGET) $(OFILES) $(LDLIBS)
.deps/%.d: %.c
#mkdir -p .deps
#$(CC) -MM $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; $(RM) -rf $#.$$$$
ifneq ($(MAKECMDGOALS),clean)
-include $(DFILES)
endif
.PHONY: clean nuke
clean:
$(RM) -rf $(TARGET) *.o core .deps tags
Let's suppose you've just untarred the archive, and for whatever reason you want to run make clean before anything else. Presumably, it is already clean. Now, without the ifneq, make would:
Execute the include $(DFILES) line. Before doing the include proper, it would...
Run the recipe for .deps/%.d: %.c because the $(DFILES) variable contains files with names that match .deps/%.d. This means running $(CC) (which is gcc by default), which is a rather expensive operation. Once the recipe is run as many times as there are .d files to generate, then...
Run the recipe for clean.
All the work done in 2 is pointless since at step 3 it will be deleted. The reason 2 exists is that when you include a file, make first checks whether it has a recipe to generate the file to be included an runs the recipe if the file does not exist or is out of date.
The ifneq bit allows the Makefile to avoid doing the work in step 2 if the goal is clean.
I'm working with a project using flex/bison and trying to compile it using make. The lex.yy.c, tab.c, tab.h from flex/bison are generated correctly and placed in the obj directory. However, there is an error when trying to compile the obj/lex.yy.c file and it cannot resolve an include to a file in the src/frontend directory. Any ideas where I am going wrong? Makefile and output included below.
Makefile:
VPATH = src obj src/frontend src/interpreter
SRCS = lex.yy.c C.tab.c symbol_table.c nodes.c print_ast.c interpreter.c main.c
OBJS := $(SRCS:%.c=obj/%.o)
INCLUDES = -Isrc -Iobj -Isrc/frontend -Isrc/interpreter
CPPFLAGS = -Wall
LDFLAGS = -Wall
CC = gcc
LEX = flex
YACC = bison -d -t -v
all: bin/mycc
bin/mycc: $(OBJS)
$(CC) -g $(LDFLAGS) $(INCLUDES) -o $# $^
obj/lex.yy.c: C.flex obj/C.tab.h
$(LEX) -o $# $<
obj/C.tab.c: C.y
$(YACC) -o $# $<
obj/C.tab.h: obj/C.tab.c
#touch $#
obj/%.o: src/%.c
$(CC) -g $(CPPFLAGS) $(INCLUDES) -c $^
clean:
rm $(OBJS) obj/lex.yy.c obj/C.tab.c obj/C.tab.h
depend:
$(CC) -M $(SRCS) > .deps
cat Makefile .deps > makefile
Output:
bison -d -t -v -o obj/C.tab.c src/frontend/C.y
src/frontend/C.y: conflicts: 4 shift/reduce, 14 reduce/reduce
src/frontend/C.y:248.11-53: warning: rule useless in parser due to conflicts: external_declaration: function_definition
flex -o obj/lex.yy.c src/frontend/C.flex
gcc -Wall -c -o obj/lex.yy.o obj/lex.yy.c
src/frontend/C.flex:13:19: fatal error: token.h: No such file or directory
#include "token.h"
^
compilation terminated.
make: *** [obj/lex.yy.o] Error 1
The problem is that you define your -I flags for compiling in the variable $(INCLUDES) instead of in the normal $(CPPFLAGS). As a result, when the default rule for compiling C files runs, it does not use any of those -I flags and so the compiler can't find the include files. You can see the command line for the compiler in your output.
To fix it, get rid of the INCLUDES = line and add all of them to CPPFLAGS:
CPPFLAGS = -Wall -Isrc -Iobj -Isrc/frontend -Isrc/interpreter
I have this folder/files structure:
./libs/
helpers.c
helpers.h
./a_app.c
./b_app.c
./c_app.c
Each app depends on helpers lib and GStreamer, so I need to compile helpers.o (inside libs/ folder) and then link each app.
Currently I have this Makefile:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LDFLAGS =
LDFLAGS += `pkg-config --libs gstreamer-app-0.10`
all: examples
examples: helpers.o a_app
$(info *** examples ***)
helpers.o:
$(info *** helpers.o ***)
$(CC) $(LFLAGS) libs/helpers.c -o libs/helpers.o $(LDFLAGS)
a_app: a_app.o
$(CC) $(CFLAGS) libs/helpers.o a_app.o -o a_app $(LDFLAGS)
a_app.o: a_app.c
$(info *** a_app.o ***)
$(CC) $(LFLAGS) a_app.c $(LDFLAGS)
While I could add b_appand c_app I'm looking for another (more elegant) way of doing it. Can't I just say that I have a, b and c _app and let Makefile compile them all and link them against GStreamer and helpers?
Also, is there any way to make Makefile compile files without needing to tell it -o name_of_file (and perhaps make it compile them in the folder that they are, because of the helpers library).
Okay, so - as we discussed in the comments, make can figure out how to make the .o files, so those rules are unnecessary. To make a generalized rule for all your *_app files (assuming they all have the same dependency on helpers.h, you can do this:
%_app: %_app.o libs/helpers.o
Make uses the % as a wildcard, and in the rule/dependency line the wildcard will expand to the same thing in the dependencies as it did in the rule. In the actual execution, you can use $* to get the same string. So a single rule for all your *_app executables winds up looking a bit like this:
%_app: %_app.o libs/helpers.o
$(CC) $(CFLAGS) libs/helpers.o $*_app.o -o $*_app $(LDFLAGS)
I was testing this on my machine (hence comments instead of answers, and wound up writing this Makefile:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LDFLAGS =
LDFLAGS += `pkg-config --libs gstreamer-app-0.10`
new: clean all
clean:
rm -rf *.o */*.o *_app
all: examples
examples: a_app b_app
%_app: %_app.o libs/helpers.o
$(CC) $(CFLAGS) libs/helpers.o $*_app.o -o $*_app $(LDFLAGS)
Does that all make sense?
EDIT: It occurs to me that GNU Make can run some commands on the command line and store the string for its own purposes.
$(shell ls *_app.c | sed 's/.c//') will expand into all the apps you have in the current directory. so you can say:
examples: $(shell ls *_app.c | sed 's/\.c//')
Or, as I think is a little better:
...
ALLAPPS = $(shell ls *_app.c | sed 's/\.c//')
...
all: $(ALLAPPS)
That way make can be used to make everything, and make ?_app can be used to compile one app at a time.
Super ultra mega double EDIT:
Using a bald % operator as a target will bust up Make's ability to auto generate .o files. Here's the solution we worked out in chat:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += $(shell pkg-config --cflags gstreamer-app-0.10)
LFLAGS += $(shell pkg-config --cflags gstreamer-app-0.10)
LDFLAGS =
LDFLAGS += $(shell pkg-config --libs gstreamer-app-0.10)
TARGETS = $(shell ls *.c | sed 's/\.c//')
new: clean all
clean:
rm -rf *.o */*.o *_app
all: examples
examples: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): libs/helpers.o $$#.o
$(CC) $(CFLAGS) libs/helpers.o $#.o -o $# $(LDFLAGS)
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