在编写通用 make 目标时,如何仅使用两个目录之一的文件?

How do I use a file from only one of two directories when writing a generic make target?

我正在尝试做类似于此的事情:

obj/32/%.o: src/all/%.c src/$(ARCH)/%.c
        @mkdir -p obj/32 || true
        $(CC) $(CFLAGS) -m32 -c $< -o $@
        objcopy --strip-unneeded $@

我希望这会检查 src/all/<file>.c 是否存在,如果不存在,请改用 src/$(ARCH)/<file>.c

然而,它不起作用。它尝试使用依赖项 src/all/%.csrc/$(ARCH)/%.c.

创建一个名为 obj/32/%.o 的目标

我该如何做这样的事情?

I would expect this to check if src/all/<file>.c exists, and if it doesn't, use src/$(ARCH)/<file>.c instead.

在这种情况下,一种选择是创建指向以下文件之一的符号链接:

src/<file>.c : # no dependencies
    test -f src/all/<file>.c && ln -fs src/all/<file>.c $@ || ln -fs src/$(ARCH)/<file>.c $@

然后改用那个符号链接:

obj/32/%.o : src/<file>.c | obj/32
    $(CC) $(CFLAGS) -m32 -c -o $@ $<
    objcopy --strip-unneeded $@

obj/32 :
    mkdir -p $@ || true

在上面它使用了对目录的 order-only 依赖,因此该目录是一个常规的 make 目标。


或者,使用 vpath:

vpath %.c src/all
vpath %.c src/$(ARCH)

obj/32/%.o: %.c
        @mkdir -p obj/32 || true
        $(CC) $(CFLAGS) -m32 -c $< -o $@
        objcopy --strip-unneeded $@

上面可能有错误,我无法测试,但你应该明白了。