Reputation: 43
I have a c project with directory layout like this
src1
-a.c
-b.c
src2
-c.c
-d.c
objects
I'm trying to compile a/b/c/d into objects files and saved them into objects directory and here is part of my Makefile.
src1 = src1/
src1 = src2/
obj = objects/
src1_files = a.c b.c
src2_files = c.c d.c
source_files = $(addprefix $(src1), $(src1_files)) $(addprefix $(src1), $(src2_files))
objects := $(addprefix $(obj), $(src1_files:.c=.o)) $(addprefix $(obj), $(src2_files:.c=.o))
$(obj)%.o: $(source_files)
$(CC) $(CFLAGS) -c $< -o $@
all: $(objects)
However when I try to run make, I got the following.
gcc -Wall -c src1/a.c -o objects/a.o
gcc -Wall -c src1/a.c -o objects/b.o
gcc -Wall -c src1/a.c -o objects/c.o
gcc -Wall -c src1/a.c -o objects/d.o
Anyone knows why is it doing that?
Upvotes: 3
Views: 309
Reputation: 20141
After having read the answer of Felix Palmen, especially the last sentence
If you really want the objects directly in your objects directory, you need two pattern rules, one matching the sources in
src1
and one matching the sources insrc2
.
I modified the Makefile
accordingly (out of curiosity):
src1 = src1/
src2 = src2/
obj = objects/
src1_files = a.c b.c
src2_files = c.c d.c
source_files = $(addprefix $(src1), $(src1_files)) $(addprefix $(src2), $(src2_files))
objects := $(addprefix $(obj), $(src1_files:.c=.o)) $(addprefix $(obj), $(src2_files:.c=.o))
$(obj)%.o: src1/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(obj)%.o: src2/%.c
$(CC) $(CFLAGS) -c $< -o $@
all: $(objects)
I tested in bash
on cygwin:
$ mkdir src1 src2 objects
$ touch src1/a.c src1/b.c src2/c.c src2/d.c
$ make
cc -c src1/a.c -o objects/a.o
cc -c src1/b.c -o objects/b.o
cc -c src2/c.c -o objects/c.o
cc -c src2/d.c -o objects/d.o
$
...and it worked.
(I left out the detail about building the objects
directory – just created it manually).
Upvotes: 3
Reputation:
This is not how pattern rules work. When trying to build an object file with your rule, make
tries to replace a %
in the prerequisite with whatever matches the %
in your target -- but your prerequisite doesn't contain a %
, so it's just taken literally. In your recipe, you just take the first one from the prerequisites list ($<
), which is always the same.
The easiest thing to do is to just replicate the directory structure below your object directory, this is what most Makefiles will actually do. Something like this:
objects := $(addprefix $(obj), $(source_files:.c=.o))
$(obj)%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
You will need to make sure the directories exist, e.g. like this (untested):
objdirs := $(obj)$(src1) $(obj)$(src2)
$(objdirs):
mkdir -p $@
$(obj)%.o: %.c | $(objdirs)
$(CC) $(CFLAGS) -c $< -o $@
If you really want the objects directly in your objects
directory, you need two pattern rules, one matching the sources in src1
and one matching the sources in src2
.
Upvotes: 2