Reputation: 44275
I have the following Makefile which I want to use to build a project serial.c
in Linux which lies in the current directory, but which uses C++ libraries from inside src
and include
, which should be build into a directory obj
, keeping all the files clear and separated.
#define some paths
DHOME = ${HOME}/Serial
SRC = ${DHOME}/src
INCLUDE = ${DHOME}/include
BIN = ${DHOME}/bin
OBJ = ${DHOME}/obj
# compiler
CFLAGS = -I$(INCLUDE)
CXX = g++ -g ${INCLUDE}
MAKE = ${CXX} -O -Wall -fPIC -c
$(OBJ)/%.o: $(SRC)/%.cc
$(MAKE) $(CFLAGS) $< -o ${OBJ}/$@
serial: $(OBJ)/%.o
${CXX} -o $@ [email protected] $< $(CFLAGS)
.PHONY: clean
clean:
@rm -f serial $(OBJ)/*.o
The error message when trying make serial
or just make
is
make: *** No rule to make target `/home/alex/Serial/obj/%.o', needed by `serial'. Stop.
But when looking at the Makefile it seem I have specified this rule (the rule above the serial
rule). I probably missed something basical. Maybe there is a better way to handle such a project and to have the different pieces clearly separated in directories?
Thanks, Alex
Upvotes: 0
Views: 83
Reputation: 126175
The problem is your rule:
serial: $(OBJ)/%.o
Since there is no %
in the TARGET of this rule, this is not a pattern rule. So it looks for a file named /home/alex/Serial/obj/%.o
(literally) which doesn't exist and can't be made.
You need to have serial
depend on a list of actual object file names. Then the pattern rule $(OBJ)/%.o: $(SRC)/%.cc
can match each of those and will be used to compile it.
edit
If you want to generate that list automatically, you can use a glob rule on your sourcefiles, and then a pattern replacement to generate the object files:
SOURCES = $(wildcard $(SRC)/*.cc)
OBJECTS = $(SOURCES:$(SRC)/%.cc=$(OBJ)/%.o)
Upvotes: 2
Reputation: 2019
Pattern matching rules act on targets.
You do not supply a list of targets to be built so the pattern matching does not work as you assume it does.
Pattern matching is not constructed to work as a wildcard on the command line. You can not ask make to look for targets, you have to supply them.
So, if serial
depends on some specific .o
files, you need to supply these. The easiest way to do that is to rewrite your rule:
serial: $(OBJ)/foo.o $(OBJ)/bar.o $(OBJ)/fie.o
#Insert build command here, as needed
This will trigger the pattern matching as each object file is set as a target before serial
can be linked.
Upvotes: 0