Makefile builds source files from different directories into the same object directory

筅森魡賤 提交于 2020-01-04 05:32:27

问题


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?


回答1:


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 in src2.

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).




回答2:


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.



来源:https://stackoverflow.com/questions/48145240/makefile-builds-source-files-from-different-directories-into-the-same-object-dir

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!