Alex
Alex

Reputation: 44275

Makefile misses a rule which looks to be available

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

Answers (2)

Chris Dodd
Chris Dodd

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

HonkyTonk
HonkyTonk

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

Related Questions