Make file two macros - makefile

I want to use macros in a single Makefile to compile two programs. When I run make, it produces this output:
Makefile:27: warning: overriding commands for target `compose'
Makefile:24: warning: ignoring old commands for target `compose'
g++ -g `Magick++-config --cppflags` -c alphamask.cpp
g++ -g `Magick++-config --ldflags` -o alphamask alphamask.o -L /usr/lib64/ -lglut -lGL -lGLU -lMagick++ -lm
It only compiles the second program. Is there any way to have the macros compile both programs? Here's my current Makefile:
CC = g++
C = cpp
CFLAGS = -g `Magick++-config --cppflags`
LFLAGS = -g `Magick++-config --ldflags`
ifeq ("$(shell uname)", "Darwin")
LDFLAGS = -framework Foundation -framework GLUT -framework OpenGL -lMagick++ -lm
else
ifeq ("$(shell uname)", "Linux")
LDFLAGS = -L /usr/lib64/ -lglut -lGL -lGLU -lMagick++ -lm
endif
endif
ALPHA = alphamask
COMP = compose
${ALPHA}: ${ALPHA}.o
${CC} ${LFLAGS} -o ${ALPHA} ${ALPHA}.o ${LDFLAGS}
${ALPHA}.o: ${ALPHA}.${C}
${CC} ${CFLAGS} -c ${ALPHA}.${C}
${COMP}: ${COMP}.o
${CC} ${LFLAGS} -o ${COMP} ${COMP}.o ${LDFLAGS}
${COMP}.o: ${COMP}.${C}
${CC} ${CFLAGS} -c ${COMP}.${C}
run:
./alphamask dhouse.png
./compose alphamask.png
clean:
rm -f core.* *.o *~ ${ALPHA} ${COMP}

First problem:
COMP = compose
${COMP}.o: ...
Adding a suffix to a variable isn't quite that simple in Make. And in this case you have some whitespace problems, which is why you're getting the warning messages, and why you couldn't build compose even if you tried.
Since you're a beginner, let's take a simple approach, crude but effective. We'll rewrite those rules, and add one at the top so that you can build both files with make:
all: alphamask compose
alphamask: alphamask.o
${CC} ${LFLAGS} -o alphamask alphamask.o ${LDFLAGS}
alphamask.o: alphamask.cpp
${CC} ${CFLAGS} -c alphamask.cpp
compose: compose.o
${CC} ${LFLAGS} -o compose compose.o ${LDFLAGS}
compose.o: compose.cpp
${CC} ${CFLAGS} -c compose.cpp
After you've got this working perfectly, a lot of improvements are possible.
EDIT:
Now that it's working perfectly, we can improve it. First let's put in automatic variables, to reduce the redundancy: $# is the name of the target, $^ is the prerequisites, and $< is the first prerequisite.
all: alphamask compose
alphamask: alphamask.o
${CC} ${LFLAGS} -o $# $^ ${LDFLAGS}
alphamask.o: alphamask.cpp
${CC} ${CFLAGS} -c $<
compose: compose.o
${CC} ${LFLAGS} -o $# $^ ${LDFLAGS}
compose.o: compose.cpp
${CC} ${CFLAGS} -c $<
Now we see redundancy in the commands, so we can combine the rules:
all: alphamask compose
alphamask: alphamask.o
compose: compose.o
alphamask compose:
${CC} ${LFLAGS} -o $# $^ ${LDFLAGS}
alphamask.o: alphamask.cpp
compose.o: compose.cpp
alphamask.o compose.o:
${CC} ${CFLAGS} -c $<
Now we can replace the object (.o) rules with a pattern rule:
all: alphamask compose
alphamask: alphamask.o
compose: compose.o
alphamask compose:
${CC} ${LFLAGS} -o $# $^ ${LDFLAGS}
%.o: %.cpp
${CC} ${CFLAGS} -c $<
And a static pattern rule for the executables. (We could use a pattern rule for these too, but that would be a little too general.)
EXECUTABLES = alphamask compose
.PHONY: all
all: $(EXECUTABLES)
$(EXECUTABLES): % : %.o
${CC} ${LFLAGS} -o $# $^ ${LDFLAGS}
%.o: %.cpp
${CC} ${CFLAGS} -c $<
When you make these improvements, get each improvement working perfectly before you advance to the next.

I'm pretty sure you need a rule to make them all (using dependencies for both projects):
all: ${ALPHA} ${COMP}
And then of course:
make all

Related

Makefile change suffix rule based on target

Currently, I have two sets of flags in my Makefile. I comment one out if I want my program to be optimized or if I want more debugging information (see below).
FC = gfortran
# I switch between having one of the following two lines commented
# FFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
FFLAGS = -O3
MOD='Modules/'
SRC = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90
OBJ = ${SRC:.f90=.o}
%.o: %.f90
$(FC) -c -J${MOD} $< $(FFLAGS) -o $#
program: $(OBJ)
$(FC) -J${MOD} $(FFLAGS) -o $# $(OBJ)
remake: remove program
clean:
rm -f **/*.o **/*.mod
remove: clean
rm -f program
Is there a way to have two different suffix rules and have a specific one used based on which target I call. I desire something like I have show below. I suspect this is an XY problem, but I don't know how else to approach this.
FC = gfortran
# Notice changes here
DEBUGFFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
FFLAGS = -O3
MOD='Modules/'
SRC = Modules/pyplot_module.f90
SRC += Modules/logs.f90
SRC += program.f90
OBJ = ${SRC:.f90=.o}
%.o: %.f90
$(FC) -c -J${MOD} $< $(FFLAGS) -o $#
%.o: %.f90 # I want this suffix rule to be used only when program-debug target is made
$(FC) -c -J${MOD} $< $(DEBUGFFLAGS) -o $#
program-optimized: $(OBJ)
$(FC) -J${MOD} $(FFLAGS) -o $# $(OBJ)
program-debug: $(OBJ)
# But I also want the SRC files to be compiled with these flags aswell
$(FC) -J${MOD} $(DEBUGFFLAGS) -o $# $(OBJ)
remake: remove program
clean:
rm -f **/*.o **/*.mod
remove: clean
rm -f program
You can use target-specific variables to do this, like this:
DEBUGFFLAGS = -Og -Wall -Wextra -fcheck=all -fbacktrace -fbounds-check
FFLAGS = -O3
EXTRAFLAGS =
%.o: %.f90
$(FC) -c -J${MOD} $< $(FFLAGS) $(EXTRAFLAGS) -o $#
program-optimized program-debug: $(OBJ)
$(FC) -J${MOD} $(FFLAGS) $(EXTRAFLAGS) -o $# $(OBJ)
program-debug: EXTRAFLAGS = $(DEBUGFLAGS) # this is the magic
However, this is a bad idea.
The problem is make won't rebuild your object files when you change the flags, it only rebuilds when the files are edited. So, whenever you run make you could have some mix of object files compiled with optimized options and debug options, and you'll never know which are which unless you completely clean all object files in between builds.
Much better is to create a separate subdirectory to hold the object files built for debug versus optimized, then they don't conflict with each other.

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.

Makefile causes `gfortran: error: No such file or directory`

I am trying to compile this code with gfortran.
Makefile:
# makefile for BIRRP
FC = gfortran
FCFLAGS = -g -fbounds-check
FLFLAGS = -g -fbacktrace
SRC = birrp.f coherence.f dataft.f diagnostic.f fft.f filter.f math.f rarfilt.f response.f rtpss.f utils.f weight.f zlinpack.f
# "make" builds all
PROGRAM = birrp
all: $(PROGRAM)
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) $# $<
%.o: %.f
$(FC) $(FLFLAGS) -o $# $^
clean:
rm -f *.o
It doesn't work
gfortran -g -fbounds-check birrp birrp.f
gfortran: error: birrp: No such file or directory
Makefile:13: recipe for target 'birrp' failed
make: *** [birrp] Error 1
I am using the gfortran compiler. I have copied the Makefile from my other program.
After adding -o:
FC = gfortran
FCFLAGS = -g -c -fbounds-check
FLFLAGS = -g -fbacktrace
SRC = birrp.f coherence.f dataft.f diagnostic.f fft.f filter.f math.f rarfilt.f response.f rtpss.f utils.f weight.f zlinpack.f
# "make" builds all
PROGRAM = birrp
all: $(PROGRAM)
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $<
%.o: %.f
$(FC) $(FLFLAGS) -o $# $^
clean:
rm -f *.o
Now it just compiles
gfortran -g -c -fbounds-check -o birrp birrp.f
Why?
gfortran interprets birrp as a source-file, but you want it as the outfile.
man gfortran
says the outfile is specified by the -o parameter, so your target becomes this:
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $<
But this doesn't solve all your problems. According to the GNU Make manual $< specifies the first dependency and not all of them. You always want to have the whole list of dependencies, which would be $^.
So your target becomes this:
$(PROGRAM): $(SRC)
$(FC) $(FCFLAGS) -o $# $^

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 putting objs in separate directory

Why does
$(OBJDIR)\%.o:$(SRDDIR)\%.s
$(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
$(OBJDIR)\%.o:$(SRDDIR)\%.c
$(GCC) -c -g -I$(SRCDIR) $(CFLAGS) $< -o $#
gives warning (says ignoring the first rule)
where as
%.o:%.s
$(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
%.o:%.c
$(GCC) -c -g -I$(SRCDIR) $(CFLAGS) $< -o $#
works fine but I will have all my sources and objs in the same directory.
I would like to put the objs (generated from assembly files and c files) in a separate directory( and I am running make on windows).
Try using forward slashes ("/") instead of backward ones ("\").
The -o flag of GCC determines where the output file are made.
So this may work if you change:
%.o:%.s $(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o $#
TO
%.o:%.s $(GCC) -c -g -I$(SRCDIR) $(ASFLAGS) $< -o myoutputdir/$#

Resources