views:

533

answers:

2

Hello,

In a makefile, I build all my .o files in a build directory:

program: class1.o class2.o class3.o
    g++ $(BUILDDIR)class1.o $(BUILDDIR)class2.o $(BUILDDIR)class3.o -o $@

It would be cool to generate $(BUILDDIR)class1.o $(BUILDDIR)class2.o $(BUILDDIR)class3.o from the dependencies list...

I know that $^ would give me the list of all dependencies, separated by spaces, but I can't deal with the sub-directory.

Is it possible ?

And if I have program: class1.o class2.o class3.o configure, can I exclude configure from the list ?

Thank you :)

Edit: Michael's solutions works well, but doing that, make does not find the dependencies and has to build everything everytime... Isn't there a simpler way, when making implicit rules like program: class1.o class2.o class3.o, to tell it to put the binaries in a build directory ?

+3  A: 

Off the top of my head

g++ $(addprefix $(BUILDDIR), $^) -o $@

should do it.

The Make manual has a list of these functions in section 8.3.

Michael Kohne
Thank you! I will have a more attentive look at the manual :)
Klaus
Yea...don't feel too bad about having missed it. Like most GNU documentation, I find that the Make manual is well-organized for people who already know everything, and just need to look up the exact spelling or whatever. If you're unsure of what something is called, it's really not possible to find it in the GNU manual without reading the whole thing.
Michael Kohne
+2  A: 

You've hit on two (or maybe three) of the big shortcomings of Make. It's good at using files there to make files here, but not the other way around, and it gets confused if a rule makes something other than the exact target (and it's automatic variables should work in prerequisites, but they don't). Fortunately we can get around these problems.

Make can't find the prerequisites when you use Michael Kohne's solution because it's looking for class1.o, not $(BUILDDIR)class1.o. (And if you simply tell it to look in $(BUILDDIR) using VPATH, you may run into other problems.)

The simplest, crudest solution (which I recommend if you're not too experienced) is brute force:

NAMES = class1 class2  
OBJECTS = $(patsubst %,$(BUILDDIR)%.o,$(NAMES))

program: $(OBJECTS) configure
    g++ $(OBJECTS) -o $@

$(OBJECTS):$(BUILDDIR)%.o:%.cc
    g++ -c $^ -o $@

There are more elegant solutions using more advanced techniques, but this should do for now.

Beta