Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper method for wildcard targets in GNU Make

Tags:

I am trying to write a Makefile with my source and object files separated and I can't seem to figure out the proper way to accomplish this. I have two methods that work but I'm hoping someone can point the "correct" way to do this is.

My project is separated into a src and obj folder with the Makefile at the same level as these.

The first method uses the wildcard function to find the source files in src then uses text replacement to determine the corresponding object files.

SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)

prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))

%.o: %.cpp
     $(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)  

This seems to work, however, every time I run make prog it recompiles all the object files. The OBJ variable has to have the src/ in front of all the objects or else I get the "no rule to make target". On the plus side, I can easily use the patsubst in the prog target to specify the object files.

The second method is similar but uses vpaths and text replacement on the OBJ variable:

 vpath = %.cpp src
 vpath = %.o obj

 SRC = $(wildcard src/*.cpp)
 OBJ = $(subst src/,,$(SRC:.cpp=.o))
 POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))

 prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)

 %.o: %.cpp
     $(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)  

This eliminates the recompiling of object files, but requires me to add another variable POJB for the prog target (since I can't do any patsubst on just the object files without a basedir).

Both methods work and each has its advantages over the other but which one is the "correct" approach and if neither, what is the proper way to achieve this type of building?

like image 454
nhmood Avatar asked Dec 25 '12 06:12

nhmood


People also ask

How do you use wildcards in makefile?

If you want to do wildcard expansion in such places, you need to use the wildcard function, like this: $(wildcard pattern ...) This string, used anywhere in a makefile, is replaced by a space-separated list of names of existing files that match one of the given file name patterns.

What is a target and a rule in makefile?

A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.

What is $$ in makefile?

$$ means be interpreted as a $ by the shell. the $(UNZIP_PATH) gets expanded by make before being interpreted by the shell.

What does $@ mean in makefile?

The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.


1 Answers

Your first example is almost there:

SRC = $(wildcard src/*.cpp)
OBJ = $(patsubst src/%.cpp, obj/%.o, $(SRC))

prog: $(OBJ)
  $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o prog 

obj/%.o: src/%.cpp
  $(CC) $(CFLAGS) -c $< -o $@
like image 73
perreal Avatar answered Sep 30 '22 19:09

perreal