MetNP
MetNP

Reputation: 551

makefile automatic variable for corresponding c file

i hava a makefile something like this:

 outdir = release
 allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(notdir $(allsrc:.c=.o))
...
test: $(allobjs)

$(allobjs): $(allsrc)
        gcc -c -o $@ $<

make test performs:

gcc -c -o release/a.o aaa/a.c
gcc -c -o release/b.o aaa/a.c
gcc -c -o release/c.o aaa/a.c

(automatic variable $< always takes first prerequisite) but i want "corresponding one":

gcc -c -o release/a.o aaa/a.c
gcc -c -o release/b.o bbb/b.c
gcc -c -o release/c.o ccc/c.c

what should i change to accomplish desirable result?

i know that this will work for sure:

$(outdir)/a.o: aaa/a.c
        gcc -c -o $@ $<

$(outdir)/b.o: bbb/b.c
        gcc -c -o $@ $<

$(outdir)/c.o: ccc/c.c
        gcc -c -o $@ $<

and wondering how to accomplish the same in one receipe. (because in my real makefile i have ~20 different source files not just 3 like i made here for example)

Upvotes: 1

Views: 160

Answers (2)

Etan Reisner
Etan Reisner

Reputation: 80921

You don't write your recipe like that. That's not how make works.

That recipe says that every item in $(allobjs) has every item in $(allsrc) as its prerequisite but that's not what you mean.

You mean that every .o file has the matching .c file as its prerequisite which is exactly what the built in %.o: %.c rule already does. You don't even need a makefile to do that.

Edit: Actually, you don't mean that. I had missed that the source files were in different directories. That changes and complicates things.

Chris Dodd wrote up two good solutions for this.

Upvotes: 2

Chris Dodd
Chris Dodd

Reputation: 126140

The usual way to do what you are asking would be something like:

outdir = release
allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(notdir $(allsrc:.c=.o)))
VPATH = $(sort $(dir $(allsrc)))
...
test: $(allobjs)

$(outdir)/%.o: %.c
        gcc -c -o $@ $<

Of course, this will run into problems if you have a b.c in both aaa and bbb, but since you're trying to put all the object files in the same directory, you have that regardless. It might make more sense to get rid of the $(notdir and keep the same directory structure under $(outdir), in which case you don't need the VPATH

outdir = release
allsrc = aaa/a.c bbb/b.c ccc/c.c
allobjs = $(addprefix $(outdir), $(allsrc:.c=.o))
...
test: $(allobjs)

$(outdir)/%.o: %.c
        mkdir -p `dirname $@`
        gcc -c -o $@ $<

Upvotes: 1

Related Questions