How to write Generic Rule based makefile - makefile

I have following folder structure
--Makefile
--source/
--boot.s
--kernel.c
--linker.ld
--build/
and I compile my sources using following Makefile
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(TARGET): kernel.elf
arm-none-eabi-objcopy $(BUILD)kernel.elf -O binary $(BUILD)kernel.img
kernel.elf: boot.o kernel.o
$(LD) $(LDFLAGS) -o $(BUILD)kernel.elf $(BUILD)boot.o $(BUILD)kernel.o
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
kernel.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)kernel.c -o $(BUILD)kernel.o
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img
How to write pattern based rules ? I tried many stack overflow answers but couldn't make it work.
First I listed my source using wild cards but couldn't write proper target as sources list had [source/boot.s source/kernel.c] and it would create object files in source folder it self.
I was facing difficulty while keeping sources and build directory different. Any help is appreciated.
----------Complete solution as per #MadScientist -----------
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(BUILD)$(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)%.o : $(SOURCE)%.c
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img

This is wrong:
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
You are telling make that your recipe will build a file named boot.o, but it doesn't: it creates a file named $(BUILD)boot.o, which is completely different. Same with your rules to build kernel.img and kernel.elf.
If you want to write a pattern rule the % can match only identical parts. Since SOURCE and BUILD are not identical, they won't match the % part. So you have to write this:
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
Since you're building $(BUILD)xxx.o you have to use that as a prerequisite as well, so you have to write:
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(BUILD)boot.o $(BUILD)kernel.o
$(LD) $(LDFLAGS) -o $# $^
ETA
If you want to get the source files via wildcard you can, but you have to substitute the directory as well not just the suffix, like this:
SOURCES := $(wildcard $(SOURCE)*.s)
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(SOURCES))
If you have both assembly and C source files (you didn't show any C source files in your example makefile) you can use this:
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))

Related

How to let avr-gcc output *.o to separate folder in Makefile with `%.o: %.c`?

As showed in first screenshot, my ideal AVR project structure is that:
*.o, *.elf and *.hex files are in build folder.
PomoScheler.c and pinDefines.h as main files are in root folder, while other *.c and *.h are in src folder.
But *.o are always generated at the same folder as *.c like showed in second screenshot, no matter how.
(I attached my endeavors and whole Makefile below the screenshots)
Firstly, I tried build/ before $#, in vain. The terminal still the same.
# My first Makefile endeavor
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o build/$#
# Terminal command generated by Makefile (Look at the end: *.o path still same as *.c)
avr-gcc -Os -g -std=gnu99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -DF_CPU=1000000UL -DBAUD=9600UL -I. -I~/Developer/bin/avr8-gnu-toolchain-darwin_x86_64/avr/include -mmcu=atmega328p -c -o src/RotaryEncoder.o src/RotaryEncoder.c
Secondly, I tried to add mv $# build to explicitly move it to build folder. But nothing happened. Even echo are not displayed in Terminal.
# My second Makefile endeavor
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $#
mv $# build
echo ---------Hello---------
Thirdly, I delete $(HEADERS) and replace $< with $^ just to have a try. The mv is executed. But it cannot find *.o file this time even though I have VPATH = src:build in Makefile.
# My third Makefile endeavor
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $^ -o $#
mv $# build
# Terminal error
Assembler messages:
Fatal error: can't create build/src/RotaryEncoder.o: No such file or directory
And my whole Makefile is here. Please help me out.
# My whole Makefile
MCU = atmega328p
F_CPU = 1000000UL
BAUD = 9600UL
LIBDIR = ~/Developer/bin/avr8-gnu-toolchain-darwin_x86_64/avr/include
PROGRAMMER_TYPE = usbtiny
PROGRAMMER_ARGS =
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
VPATH = ./src:./build
TARGET = $(lastword $(subst /, ,$(CURDIR)))
SOURCES=$(wildcard *.c src/*.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,build/$(TARGET).map
LDFLAGS += -Wl,--gc-sections
TARGET_ARCH = -mmcu=$(MCU)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o build/$#
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o build/$#
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex build/$< build/$#
all: $(TARGET).hex
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
This is clearly not right:
OBJECTS = $(SOURCES:.c=.o)
because the object files you want to create are not foo.o etc. which is what this will expand to; the object files are build/foo.o etc. So this has to be:
OBJECTS = $(patsubst %.c,build/%.o)
All of your attempts to trick make by telling it your recipe will build one target (foo.o) but actually building a totally different target (build/foo.o) are doomed to fail, regardless of whether you have the compiler do it directly, you use mv, or any other method.
If you just tell make what your recipe actually does, you will have a much simpler time of it:
build/%.o: %.c
mkdir -p $(#D)
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $^ -o $#
Probably you have similar issues with the other rules that you want to put into other directories.
You can't do this by trying to hide it from make. Make has to know where the files actually are.
BTW, VPATH cannot help here. VPATH is for finding source files, it cannot be used for finding generated files. So you could use VPATH to find your .c files but not your .o files.

How to compile avr c and c++ source code with make

I was trying to compile some code written in c and c++ for an atmega32u4.
I wrote a makefile from information gathered from the internet, but it fails for some reason.
If I run the commands separately from the command line, they all work. However running the make command gives the following error:
main.cpp:3:10: fatal error: avr/io.h: No such file or directory
The contents of the main.cpp file are not really relevant, it's just a blink code.
The makefile looks like this:
all: init clean $(patsubst %.cpp, %.hex, $(wildcard *.cpp))
avr-size -A $(BUILDPATH)/*.elf
%.c.o: %.c
#mkdir -p $(BUILDPATH)
avr-gcc -c -g -Os -w -mmcu=$(CHIP) $^ -o $(BUILDPATH)/$#
%.cpp.o: %.cpp
#mkdir -p $(BUILDPATH)
avr-g++ -c -g -Os -w -mmcu=$(CHIP) $^ -o $(BUILDPATH)/$#
%.elf: %.o
avr-gcc -g -Os -w -mmcu=$(CHIP) $(BUILDPATH)/$^ -o $(BUILDPATH)/$#
%.hex: %.elf
avr-objcopy -R .eeprom --change-section-lma .eeprom=0 -O ihex $(BUILDPATH)/$^ $(BUILDPATH)/$#
So what am I doing wrong? Do I have to set up some environment variables or is the structure of the makefile incorrect?

How to rename various file extensions to .o in makefile?

Hi I have this makefile:
CC = gcc
AS = nasm
CFLAGS = -ffreestanding -Wall -Wextra -std=c11 -m32 -nostdlib -nostdinc -fno-stack-protector
LDFLAGS = -m elf_i386 -T link.ld
ASFLAGS = -f elf32
SOURCES = $(wildcard src/*.c wildcard src/*.s)
OBJECTS = $(SOURCES:.[s|o]=.o)
INCLUDEPATH = -I inc src/include
OBJDIR = bin/obj
SRCDIR = src/
all: build
build:
ld $(LDFLAGS) $(OBJECTS) -o bin/kernel.bin
iso: build
cp bin/kernel.bin XeonOS/boot
grub-mkrescue -o XeonOS.iso XeonOS/
run: iso
quemu-system-i386 -m 512M -cdrom XeonOS.iso
clean:
rm -rf bin/*.o bin/kernel.bin
%.o: $(SRCDIR)%.c
$(CC) $(INCLUDEPATH) $(CFLAGS) $< -o $(OBJDIR)/$(OBJECTS)
%.o: $(SRCDIR)%.s
$(AS) $(ASFLAGS) $< -o $(OBJDIR)/$(OBJECTS)
And when i execute the command make run i get the following error:
ld -m elf_i386 -T link.ld src/kernel_c.c src/kernel_asm.s -o bin/kernel.bin
ld:src/kernel_c.c: file format not recognized; treating as linker script
Because the kernel_c.c and kernel_asm.s didn' change their extension to .o. How can i change the extension of both .s and .c to .o at the same time?
By the way, I will have another problem, the value of the OBJECTS variable contains the src/ directory but the object files are stored in the bin/obj folder, How can i change that?
When I had this problem last month I just did this:
SOURCES_C := $(wildcard src/*.c)
SOURCES_S := $(wildcard src/*.s)
OBJECTS := $(SOURCES_C:%.c=%.o) \
$(SOURCES_S:%.s=%.o)
I haven't looked at this too deeply but, as far as I know, that's your best bet.
Finally I used the #LightnessRacesinOrbit advice and also used patsubsr so the code is now working:
CC = gcc
AS = nasm
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror
LDFLAGS = -m elf_i386 -T link.ld
ASFLAGS = -f elf32
C_SOURCES = $(wildcard src/*.c)
C_OBJECTS = $(patsubst %.c,%.o, $(notdir $(C_SOURCES) ))
ASM_SOURCES = $(wildcard src/*.s)
ASM_OBJECTS = $(patsubst %.s,%.o, $(notdir $(ASM_SOURCES) ))
INCLUDEPATH = -I src/include
OBJDIR = bin/obj
SRCDIR = src/
.PHONY: build
all: build
build: $(C_OBJECTS) $(ASM_OBJECTS)
ld $(LDFLAGS) $(OBJDIR)/$(ASM_OBJECTS) $(OBJDIR)/$(C_OBJECTS) -o bin/kernel.bin
iso: build
cp bin/kernel.bin XeonOS/boot
grub-mkrescue -o XeonOS.iso XeonOS/
run: iso
bochs -f bochsconfig.cfg -q
clean:
rm -rf XeonOS/boot/kernel.bin
rm -rf bin/obj/*.o bin/kernel.bin
%.o: $(SRCDIR)%.c
$(CC) $(INCLUDEPATH) $(CFLAGS) $< -o $(OBJDIR)/$#
%.o: $(SRCDIR)%.s
$(AS) $(ASFLAGS) $< -o $(OBJDIR)/$#

How to remove Makefile Dependency on C file

I have the below Makefile and for some reason it's dependent on a file, ewapi.c. This file executes some SWIG commands and uses the ewapi.i file. I've clear out all the contents of ewapi.c and the Makefile successfully runs. If I remove the ewapi.c file the make file will not complete. The exception stack is below if that helps. Any ideas on how to change the Makefile so its not dependent on ewapi.c?
# BUILD_DIR and DIST_DIR are exported by build.xml
#
CMODE=
SWIG = swig
CC = $(PREFIX)gcc
LD = $(CC)
OBJ_DIR = $(BUILD_DIR)/obj
AUTOGEN_DIR = $(BUILD_DIR)/auto-generated
PACKAGE_DIR = $(AUTOGEN_DIR)/com/sample/jni
PACKAGE = com.sample.jni
INCLUDES = -I$(JAVA_INCLUDE) \
-I$(SAMPLE_SDK_DIR)/include \
-I$(JDK_HOME)/include
LIB_INCLUDES = -L$(SAMPLE_SDK_DIR)/lib
LIBS = /lib/libssl.so.4 \
/lib/libcrypto.so.4 \
-lSampleApi \
-lm
DIRS = $(PACKAGE_DIR) $(DIST_DIR) $(OBJ_DIR) $(AUTOGEN_DIR)
CFLAGS = $(CMODE) -Wall -fpic $(INCLUDES) -O0 -g3
SFLAGS = -java $(INCLUDES) -package $(PACKAGE) -outdir $(PACKAGE_DIR)
LDFLAGS = -shared $(LIB_INCLUDES) $(LIBS)
OBJECTS = $(OBJ_DIR)/ewapi_wrap.o $(OBJ_DIR)/ewapi.o
TARGET = $(DIST_DIR)/libSample.so
all: $(DIRS) $(TARGET)
%_wrap.c: %.i
$(SWIG) $(SFLAGS) $<
$(OBJ_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(TARGET): $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $#
$(DIRS):
mkdir -p $#
clean:
rm -rf $(TARGET) $(PACKAGE_DIR)/* $(TARGET) $(AUTOGEN_DIR) $(OBJ_DIR)
Exception Stack (when I remove ewapi.c):
[exec] rm ewapi_wrap.c
[exec] make-3.79.1-p7: *** No rule to make target `/test/build/obj/ewapi.o', needed by `/test/dist/libSample.so'. Stop.
The macros OBJECTS includes $(OBJ_DIR)/ewapi.o; the rule for $(TARGET) says it depends on $(OBJECTS); and the rule for all says it depends on $(TARGET). So, there needs to be a way to create ewapi.o from something - and in the absence of ewapi.c, there is no way to build ewapi.o, hence the complaint you get.
Possible fixes:
Replace ewapi.c.
Remove ewapi.o from the macro $(OBJECTS).
Remove $(OBJ_DIR)/ewapi.o from OBJECTS.

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