3

想象一下这个结构:

root/
|
+-- include/
+-- src/
+-- build/
+-- lib/
+-- tests/
    |
    +-- common
    +-- test1
    +-- test2
    +-- test3

tests/中,该文件夹common/包含几个源文件,它们生成数据或从记录的文件中读取数据等,这些文件在所有测试之间共享。因此,每个测试只有一个文件;main.c(目前)。每个Makefile测试的看起来像这样:

.SUFFIXES:
.SUFFIXES: .c .o

TARGET := test
# OS dependent stuff omitted for brevity
CFLAGS += -I../../include -I../common
LDFLAGS += -L../../lib -lname

VPATH = ../common

.phony: all clean
all: $(TARGET)
clean:
    -$(RM) *.o $(TARGET)
# Other targets removed for brevity

OBJECTS := main.o io.o read_str.o
$(TARGET): $(OBJECTS) ../../lib/libname.a
    $(LD) -o $@ $(OBJECTS) $(LDFLAGS)
%.o: %.c
    $(CC) -c $(CFLAGS) -o $@ $<
main.o: main.c io.h $(wildcard ../../include/*.h)

起初我common/在每个测试中都复制了文件,一切都很好,但现在我把它们放进去common/使用了VPATH,我遇到了一个问题。

让我解释几行:

main.o: main.c io.h $(wildcard ../../include/*.h)
               ^^^^
           VPATH correctly finds this file in common/

$(TARGET): $(OBJECTS) ../../lib/libname.a
                      ^^^^^^^^^^^^^^^^^^^
                  If the library is rebuilt, the tests need to re-link

    $(LD) -o $@ $(OBJECTS) $(LDFLAGS)
                ^^^^^^^^^^
            I can't use $^ because that also includes ../../lib/libname.a

正如您可能已经猜到的那样,由于common/*.o文件不在此文件夹中,因此$(LD)无法找到它们。另一方面,make, givenVPATH = ../common找到它们没有问题。如果我可以删除../../lib/libname.a,然后使用$^,我可以提供目标文件的正确路径。

然而,删除对 lib 文件的依赖意味着当我make处于顶层时,如果仅更新 lib 本身,测试将不会得到更新。

所以,我的问题是,如果make其他依赖项是使用VPATH?

我考虑过删除依赖项,并在Makefilethat buildslibname.a中,在创建库后添加一个命令,告诉Makefile测试的 s 删除它们TARGET的 s:

lib/Makefile:

.SUFFIXES:

TARGET = libname.a
VPATH = ../build

.PHONY: all clean
all: $(TARGET)
clean:
        -$(RM) $(TARGET)

$(TARGET): list.o of.o my.o library.o files.o
        $(AR) $(TARGET) $^
        @$(MAKE) --no-print-directory -C ../tests remove_targets

这将迫使$(LD)他们再次制造。然而,这种解决方案往往会使Makefile关系变得一团糟。Makefile构建 lib 与是否有测试无关,我更喜欢将它们解耦。


我进行了很多构建和测试,这就是为什么我尝试完成依赖项,以便make采取尽可能少的操作来正确构建所有内容。说,每次都清理和重建的解决方案不是一种选择。

我也知道这种语法,如果我想将 lib 文件目录提供给gcc,而不是使用-Lpath/to/lib -lname. 但是我不确定这是否是一个好主意(我的意思是,我总是看到与 链接-L,我不确定直接提供库文件是否有缺点)

顺便说一句,如果我做错了什么,或者我让自己太难了,请告诉我应该如何正确地做到这一点。

4

1 回答 1

4

所以,我的问题是,如果其他依赖项是使用 VPATH 找到的,我怎么能告诉 make 存在对另一个文件(lib 文件)的依赖项,但它没有在它下面的命令中使用?

问题是“我怎样才能使 LIB 成为先决条件但不在所有先决条件列表中?”

这可能不是最好的答案,但应该可以,只需将其从列表中过滤出来:

$(TARGET): $(OBJECTS) ../../lib/libname.a
    $(LD) -o $@ $(filter-out ../../lib/libname.a,$^) $(LDFLAGS)
于 2012-06-18T09:34:18.523 回答