我有一个像这样的目录布局的c项目
src1
-a.c
-b.c
src2
-c.c
-d.c
objects
我正在尝试将/ b / c / d编译成对象文件并将它们保存到对象目录中,这是我的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)
然而,当我尝试运行make时,我得到了以下内容。
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
任何人都知道为什么会这样做?
答案 0 :(得分:2)
这不是模式规则的工作方式。在尝试使用您的规则构建目标文件时,make
会尝试将先决条件中的%
替换为目标中%
的匹配项 - 但您的先决条件并非如此包含%
,所以它只是字面意思。在您的食谱中,您只需从先决条件列表($<
)中取出第一个,它始终是相同的。
最简单的方法是只复制对象目录下的目录结构,这就是大多数Makefile实际上会做的事情。像这样:
objects := $(addprefix $(obj), $(source_files:.c=.o))
$(obj)%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
您需要确保目录存在,例如像这样(未经测试):
objdirs := $(obj)$(src1) $(obj)$(src2)
$(objdirs):
mkdir -p $@
$(obj)%.o: %.c | $(objdirs)
$(CC) $(CFLAGS) -c $< -o $@
如果您确实希望对象直接位于objects
目录中,则需要两个模式规则,一个匹配src1
中的来源,另一个匹配src2
中的来源。
答案 1 :(得分:2)
阅读answer of Felix Palmen后,特别是最后一句
如果您确实希望对象直接在对象目录中,则需要两个模式规则,一个匹配
src1
中的来源,另一个匹配src2
中的来源。
我相应地修改了Makefile
(出于好奇心):
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)
我在bash
上对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
$
......它有效。
(我遗漏了有关构建objects
目录的详细信息 - 只是手动创建它。)