I am trying to write a makefile to build a set of c++ programs in the same directory that have independent source code, but similar compilation rules and shared dependencies (common headers).
/path/to/project/
peformance.h
vector.h
pqvm.cpp
quantum/
quantum-tbb.h
quantum-sequential.h
...
tests/
grainsize.cpp
kronecker.cpp
sigma-z.cpp
...
Makefile
I want to compile the sources in the tests
folder, each source to a corresponding executable. Below is the makefile I am trying to use; there seems to be a problem in the line $(TARGETS): %.o
.
I want to refer to the current target's name (e.g. grainsize
) and have it depend on its corresponding object file (e.g. grainsize.o
), neither %.o
nor [email protected]
seem to work. I could change the line to $(TARGETS): $(OBJECTS)
but then every target would depend on all the objects, triggering a lot of unnecessary recompilation on each change.
So basically: how do I correctly refer to a target name in its dependency list? I am aware of this related question: Passing target name to a dependency in makefile, but I can't see how it would apply to this problem.
CXX = g++
SOURCES = $(wildcard *.cpp)
DEPS = ../performance.h $(wildcard ../quantum/*.h) ../vector.h
TARGETS = $(basename $(SOURCES))
OBJECTS = $(addsuffix .o, $(TARGETS))
INCPATH = -I../../local/include
LIBPATH = -L../../local/lib
LIBS = -lpfm -lpapi -ltbb
OFLAGS = -Wall -O2
DFLAGS = -g3
CFLAGS = -march=native $(OFLAGS) $(DFLAGS) $(INCPATH) $(LIBPATH) -fopenmp
UNAME = $(shell uname)
ifeq ($(UNAME), Linux)
LIBS += -lrt
endif
.PHONY: all
all: $(TARGETS)
#for each target: link its object file to the libraries and produce an executable binary
#this does not work as expected
$(TARGETS): %.o
$(CXX) $(CFLAGS) [email protected] $(LIBS) -o $@
#compile each target to its object file
#this works as expected
%.o: %.cpp $(DEPS)
$(CXX) -c $(CFLAGS) -o $@ $<
This is the error message on the command line:
$ make
make: *** No rule to make target `%.o', needed by `grainsize'. Stop.
The problem is that this:
$(TARGETS): %.o
...
is not a pattern rule; there is a %
in the prerequisite list, but not in the target. So Make interprets the %
literally, and there's no such file as %.o
.
Try this:
$(TARGETS): % : %.o
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
This is a static pattern rule. Also, I've changed [email protected]
(which would work but is a kludge) to $^
(which means "all of the prerequisites", and is more robust and easier on the eyes).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With