使用shell的结果查找Makefile中的目标

时间:2014-03-21 05:47:02

标签: shell makefile

说,有一个具有未定义内部结构的源目录,我们想要获取所有文件并声明它们应该被编译为目标的文件。

类似的东西:

SOURCES := $(shell find src -name \*.c)
OBJS := $(addprefix /tmp,$(addsuffix .o,$(basename $(notdir $(SOURCES)))))
$(OBJS): $(SOURCES)
    cc $(CFLAGS) -o $@ $^

但是,它从第二行开始不起作用(它只是空的)。所以,我最终取代了它:

OBJS := $(shell find src -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\/g' | sed 's/\.c/\./o/g'" \;)

我不太喜欢这种方法,但无论如何它似乎都不起作用。好的,现在预计会有效。但是,目标不会像预期的那样发挥作用,就像我明确宣布它们一样:

TARGETS := /tmp/foo.o /tmp/bar.o
$(TARGETS): $(SOURCES)
    ...

相反,我只是收到错误No rule to make target /tmp/foo.o

所以,猜猜,我有两个问题:

  1. 为什么第一个代码段会使$(OBJS)为空?
  2. 有没有办法实际实现动态目标?

1 个答案:

答案 0 :(得分:2)

在我的机器上测试第一个片段。

uname -a
Linux - 3.2.0-4-686-pae #1 SMP Debian 3.2.54-2 i686 GNU/Linux

make -v
GNU Make 3.81

cat makefile
SOURCES := $(shell find ./ -name \*.c)
OBJS := $(addprefix /tmp,$(addsuffix .o,$(basename $(notdir $(SOURCES)))))
$(info $(OBJS))

mkdir test; touch test/1.c; touch test/2.c; make -f makefile

输出:
/tmp1.o /tmp2.o

测试显示,{em>第一个片段没有问题,但在/tmp之后缺少斜杠。 你如何测试OBJS的空虚?
你确定SOURCES没有空吗? make$(info $(SOURCES)) makefile的输出结果是什么? *.c目录中是否有src个文件?

在我的机器上测试第二个片段。

sed --version
GNU sed 4.2.1

cat makefile
SOURCES := $(shell find ./ -name \*.c)
OBJS := $(shell find ./ -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\/g' | sed 's/\.c/\./o/g'" \;)
$(info $(OBJS))

make -f makefile

输出:
sed: -e expression #1, symbol 10: unknown modifier for s'
sed: -e expression #1, символ 12: incomplete command s'
sed: -e expression #1, символ 12: incomplete command s'
sed: -e expression #1, символ 10: unknown modifier for s'

第二个代码段OBJS的版本不为空 (注意在第一个'\'命令中删除了sed,在第二个命令中删除了'/'。)
OBJS := $(shell find ./ -name \*.c -exec sh -c "basename {} | sed 's/^/\/tmp\//g' | sed 's/\.c/\.o/g'" \;)

有没有办法实际实现动态目标?

是的。如果您可以将.o文件存储在源目录中,这很容易 下一个片段可以解决问题:

sources := $(shell find ./ -name \*.c)
objects := $(sources:.c=.o)

$(objects): %.o: %.c
    $(cc) -c $<

但也许这不是你想要的 使用VPATH和其他几个字符串可以做得更好。

target   := ./a.out
obj_dir  := ./tmp/
sources  := $(shell find ./ -name \*.c)
objects  := $(addprefix $(obj_dir), $(notdir $(sources:.c=.o)))
dirs     := $(dir $(sources))
VPATH    := $(dirs)

$(target): $(objects)
    $(cc) -o $@ $^

$(objects): $(obj_dir)%.o: %.c
    $(cc) -o $@ -c $<