【问题标题】:Makefile builds source files from different directories into the same object directoryMakefile 将不同目录的源文件构建到同一个对象目录中
【发布时间】:2018-01-08 06:26:22
【问题描述】:

我有一个像这样的目录布局的 c 项目

src1
    -a.c
    -b.c
src2
    -c.c
    -d.c
objects

我正在尝试将 a/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

有人知道为什么要这么做吗?

【问题讨论】:

  • $(addprefix $(src1), $(src2_files) --> $(addprefix $(src2), $(src2_files)
  • @Gaurav 这还不够
  • 这是我在阅读Makefile 时遇到的。我必须执行 Makefile 才能发现任何其他问题。! :-|
  • 还有一个错字:src1 = src2/(第二行)。
  • @Gaurav 当然是正确的,但是这个 Makefile 除了拼写错误之外还有一个概念错误,它永远不会像这样工作;)

标签: c makefile gnu-make


【解决方案1】:

看完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)

我在 cygwin 上的 bash 中测试过:

$ 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 目录的细节——只是手动创建的)。

【讨论】:

  • 是的,这就是我在上一段中简要描述的内容。不推荐这条路线,至少如果源目录的数量以后会增加,但它有效:)(因此回答了直接的问题)
  • 我的目的是展示您的建议。可能是,我应该更清楚地说明我的答案作为你的补充。
  • 我明白,只是想确认这就是我的意思! (并怀疑它是“正确的做法”,但这当然取决于情况);)
【解决方案2】:

这不是模式规则的工作方式。尝试使用您的规则构建目标文件时,make 尝试将先决条件中的 % 替换为与目标中的 % 匹配的任何内容 - 但您的先决条件不包含 %,所以它是只是从字面上理解。在您的配方中,您只需从先决条件列表 ($&lt;) 中获取第一个,这始终是相同的。

最简单的做法是复制对象目录下的目录结构,这是大多数 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 中的源。

【讨论】:

    猜你喜欢
    • 2011-05-05
    • 2013-11-02
    • 1970-01-01
    • 2016-03-04
    • 2021-05-10
    • 1970-01-01
    • 2010-11-11
    • 2010-12-26
    • 1970-01-01
    相关资源
    最近更新 更多