specifying the compiler in a gnu makefile - makefile

I have a gnu makefile template that has served me well, but when I try to specify a compiler other than the first g++ in my path, it fails.
Here's the template.
CXX = g++
CXXFLAGS = $(INC) $(LIB) -Wall
INC = -I./ -I/usr/local/include
LIB = -L/usr/local/lib
SRCS = \
blah1.cpp
blah2.cpp
OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d)
PROG = myprog
$(PROG): $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $(OBJS)
%.d: %.cpp
#set -e; rm -f $#; \
$(CXX) -MM $(CXXFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
debug: CXXFLAGS += -O0 -DDEBUG -ggdb
debug: $(PROG)
-include $(DEPS)
.PHONY: clean
clean:
rm -f $(DEPS) $(OBJS) $(PROG)
When I change the compiler from g++ to something like /usr/local/bin/g++46, it still compiles with g++ (/usr/bin/g++ to be exact). Why?
P.S. Any criticisms with the template are welcome. I'm not very comfortable with gnu make; I just crammed and searched the web for a day to come up with this.

You haven't specified your own rule for how to build object files, so Make uses the default implicit rule, which is:
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c
Note $(CXX), not $(CC), which specifies the default C compiler.

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.

Why does my Makefile with pattern rules not create debugging symbols for main?

I am using this auto-generated Makefile with pattern rules, that I oviously do not understand yet. I want to create debuggins symbols and then debug main, but it doesn't work. There is a -g flag. Adding $(LDFLAGS) statement above after $(ODIR) does not print one as expcted.
IDIR =./include
CC=g++
CFLAGS = -I$(IDIR)
LDFLAGS = -g
ODIR=./
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
main: $(OBJ)
$(CC) $(LDFLAGS) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o
This is the terminal output
g++ -c -o Source.o Source.cpp
g++ -g -o Source Source.o -I./include
Your sources are C++ (.cpp) but your Makefile contains explicit instructions for building C files. Make is therefore falling back to its built in implicit rules.
Also note that by convention those rules use $(CXX) to refer to the C++ compiler, with $(CXXFLAGS) replacing $(CFLAGS), and the -I flag belongs in $(CPPFLAGS):
IDIR =./include
CPPFLAGS = -I$(IDIR)
CXXFLAGS = -g
ODIR=.
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cpp
$(CXX) -c -o $# $(CPPFLAGS) $(CXXFLAGS) $<
main: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJ)
If you were to do away with the ODIR handling and use the conventional variable names you could do without the explicit .o: .cpp rule altogether.

How to change gcc compile message in makefile

I am new to programming.
I need to help me with hiding a message in makefile.
Let me show you:
When compiling this set of files(grid.cc attribute.cc targa.cc) http://prntscr.com/67ack4
I see this message: gcc5 -Wall -O2 -pipe -mtune=i686 -c attribute.cc
And I want to defend me something like: Compilation targa.cc
And I want to defend me something like: Compilation attribute.cc
etc
etc ...
I hope you understand what I mean.
Here is my makefile :
BIN = ../libgame.a
CXX = gcc5
CFLAGS = -Wall -O2 -pipe -mtune=i686
OBJFILES = grid.o attribute.o targa.o
########################################################################################################
default:
$(CXX) $(CFLAGS) -c grid.cc
$(CXX) $(CFLAGS) -c attribute.cc
$(CXX) $(CFLAGS) -c targa.cc
ar cru $(BIN) $(OBJFILES)
ranlib $(BIN)
rm -f *.o
You can use an automake-style silent rules trick to control what is output for your commands.
To do this directly you would do this:
BIN = ../libgame.a
CXX = gcc5
CFLAGS = -Wall -O2 -pipe -mtune=i686
OBJFILES = grid.o attribute.o targa.o
########################################################################################################
default:
#echo 'Compiling grid.cc';$(CXX) $(CFLAGS) -c grid.cc
#echo 'Compiling attribute.cc';$(CXX) $(CFLAGS) -c attribute.cc
#echo 'Compiling targa.cc';$(CXX) $(CFLAGS) -c targa.cc
ar cru $(BIN) $(OBJFILES)
ranlib $(BIN)
rm -f *.o
Alternatively you could use my silent_rules.mk and use:
$(eval $(call vrule,Compile,Compiling $$(value 1))
$(call Compile,grid.cc);$(CXX) $(CFLAGS) -c grid.cc
$(call Compile,attribute.cc);$(CXX) $(CFLAGS) -c attribute.cc
$(call Compile,targa.cc);$(CXX) $(CFLAGS) -c targa.cc
to get Compiling grid.cc, Compiling attribute.cc and Compiling targa.cc messages instead. (If you were using proper targets for your object files you could use the default $(GEN) silent rule to get GEN xxx.o output automatically.

Makefile not prompting compiler to use optimization flag

I have a simple makefile that I am using in bash to compile a C++ program and its associated .h files, not every .h file has a .cpp file associated with it. I wrote a makefile where each dependency was called out explicitly and the CFLAG macro was used for each specific dependency and it did compile with the -O3 flag and ran nearly 3 times faster. However, when I use this simpler, but somewhat more sophisticated makefile, it does not compile with the -O3 flag even though it is clearly included with the CFLAG macro. Can someone point out to me what I am missing, I would greatly appreciate it.
OBJS = main.o Output_Files.o Calendar.o Random_Number_Generator.o \
Algorithm.o Statistics.o
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CC=c++
CFLAGS=-c -Wall -O3
all: economics
%o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $# $<
economics: $(OBJS)
$(CC) $(OBJS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CC) $(CFLAGS) main.cpp
The rule:
%o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $# $<
should be written with an extra dot:
%.o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $<
Also, you don't want $# in the command line, or (if you must have it) you need to prefix it with -o.
The makefile is not using the faulty rule but instead uses the default rule for building C++ object files, and that most probably doesn't use $(CFLAGS) but uses $(CXXFLAGS) instead.
CC is the macro for the C compiler, not the C++ compiler. Normally, that is CXX. Also, the rule to build economics actually creates a.out and not economics.
I'd prefer it if you wrote:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
…
economics: $(OBJS)
$(CC) -o $# $(OBJS)
Putting it all together gives this new.makefile:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CC = c++
CFLAGS = -c -Wall -O3
all: economics
%.o: %.cpp $(DEPS)
$(CC) $(CFLAGS) $<
economics: $(OBJS)
$(CC) -o $# $(OBJS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CC) $(CFLAGS) main.cpp
Running make -n with the old makefile
$ make -n -f old.makefile
c++ -c -Wall -O3 main.cpp
c++ -c -o Output_Files.o Output_Files.cpp
c++ -c -o Calendar.o Calendar.cpp
c++ -c -o Random_Number_Generator.o Random_Number_Generator.cpp
c++ -c -o Algorithm.o Algorithm.cpp
c++ -c -o Statistics.o Statistics.cpp
c++ -o economics main.o Output_Files.o Calendar.o Random_Number_Generator.o Algorithm.o Statistics.o
$
Running make -n with the new makefile
$ make -n -f new.makefile
c++ -c -Wall -O3 main.cpp
c++ -c -Wall -O3 Output_Files.cpp
c++ -c -Wall -O3 Calendar.cpp
c++ -c -Wall -O3 Random_Number_Generator.cpp
c++ -c -Wall -O3 Algorithm.cpp
c++ -c -Wall -O3 Statistics.cpp
c++ -o economics main.o Output_Files.o Calendar.o Random_Number_Generator.o Algorithm.o Statistics.o
$
This is still an abnormal way of writing the make rules on a number of grounds, one being the $(CC) vs $(CXX) change. Normally, the -c option is not included in $(CFLAGS) or $(CXXFLAGS). Normally, you include $(CFLAGS) or $(CXXFLAGS) in the link line too (because some of the flags might affect linking). Often, you need libraries and related flags in the linker line too.
This leads to a more orthodox naming convention:
SRCS = main.cpp Output_Files.cpp Calendar.cpp Random_Number_Generator.cpp \
Algorithm.cpp Statistics.cpp
OBJS = ${SRCS:.cpp=.o}
DEPS = Output_Files.h Calendar.h Random_Number_Generator.h Algorithm.h \
Statistics.h
CXX = c++
CXXFLAGS = -Wall -O3
LDFLAGS =
LDLIBS =
all: economics
%.o: %.cpp $(DEPS)
$(CXX) -c $(CXXFLAGS) $<
economics: $(OBJS)
$(CXX) -o $# $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
main.o: main.cpp Data_Parser.h PDF_and_CDF.h
$(CXX) -c $(CXXFLAGS) main.cpp

Makefile issue. Second set of eyes please

PROJ = .
SRC_ROOT = .
FLAGS = -g -Wall -Wextra
INC = -I$(PROJ) \
-I$(SRC_ROOT)/Exception \
-I$(SRC_ROOT)/MapFile
DEPS = $(SRC_ROOT)/Exception/Exception.h \
$(SRC_ROOT)/Exception/Exception.cpp \
$(SRC_ROOT)/MapFile/MapFile.h \
$(SRC_ROOT)/MapFile/MapFile.cpp
OBJS = $(SRC_ROOT)/MapFile/MapFIle.o \
$(SRC_ROOT)/Exception/Exception.o
all: main $(OBJS)
%.o : %.cpp %.h
g++ -c $(FLAGS) $(INC) $< -o $#
main: $(DEPS) $(OBJS) main.cpp
g++ -o main $(FLAGS) $(INC) main.cpp $(OBJS)
$(SRC_ROOT)/MapFile/MapFIle.o : $(SRC_ROOT)/MapFile/MapFIle.cpp $(SRC_ROOT)/MapFile/MapFIle.h
g++ -c $(FLAGS) $(INC) $< -o $#
clean:
rm -f *~
rm -f $(OBJS)
rm -f main
rm -f -R *.dSYM
When I comment out the explicit rule for MapFile.o I get a "no rule to build error for it" yet the implicit rule clearly works for Exception.o. Any idea what could be the issue? Hope it is not something simple that I am missing having been staring at it for a few. Thanks in advance.
Using GNU Make 3.81
The filenames are case-sensitive; in some places you have MapFile.cpp and MapFile.h, but elsewhere you have MapFIle.o (with a capital I) and MapFIle.cpp and so on.

Resources