【问题标题】:Telling make that targets will be in a subfolder告诉 make 目标将在子文件夹中
【发布时间】:2019-07-12 11:36:08
【问题描述】:

我有一个具有这种玩具结构的项目:

src:
    obj1.cpp
    obj2.cpp
obj: 
    (empty folder)

我想使用make 编译成一个库。我想在我的 makefile 中写的是:

mylib.a: obj1.o obj2.o
    ar $@ $^

这可行,但是它使文件夹变得混乱,因为它导致了这种结构:

obj1.o
obj2.o
mylib.a
src:
    obj1.cpp
    obj2.cpp
obj: 
    (empty folder)

我希望调用的结果是这样的:

mylib.a
src:
    obj1.cpp
    obj2.cpp
obj: 
    obj1.o
    obj2.o

其中两个obj 源都被编译成obj 中的.o 对象。我尝试在我的 makefile 中这样做:

vpath %.o obj
mylib.a: obj1.o obj2.o

但这与上面的结果相同。所以,我很确定,obj1.o 的隐式规则不知道输出到哪里,对吧?好的,所以我添加了这条规则:

%.o: %.cpp
    g++ $^ -o obj/$@

为了确保我正在编译成obj,但是,现在 make 命令失败了,我明白为什么它失败了。它失败是因为 mylib 找到了 obj1.o,因为它找到了它的规则,它执行了规则,但是规则并没有导致 obj1.o 的存在,而是导致 obj/obj1.o 的存在,所以当mylib 是组合的,它的规则是 ar obj1.o obj2.o 并且它失败了。


所以,我的问题是:有没有一种简单而优雅的方法来避免这个问题?

我看到的一个解决方案是始终有一些文件,如果需要,则为空,在obj 中命名为 obj1.o,但这对我来说似乎很难看。另一个是添加 "obj/" 到 mylib.a 的每个对象,但这意味着重复代码,甚至更丑陋。那么,解决这个问题的最佳方法是什么?

【问题讨论】:

  • 在应该在该目录中的每个路径前指定 obj/ 是标准解决方案,如果使用模式规则,则不会特别冗长或混乱。

标签: makefile gnu-make


【解决方案1】:

vpathVPATH 不用于目标,它们用于源。使用它们来告诉 make 目标文件应该去哪里不是一个好主意。最简单的解决方案可能是pattern rule

obj/%.o: src/%.c
    <your compilation rule>

基于此你可以详细说明一下:

SRCDIR := src
OBJDIR := obj
SRCS   := $(wildcard $(SRCDIR)/*.c)
OBJS   := $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS))

mylib.a: $(OBJS)
    <your library building recipe>

$(OBJDIR)/%.o: $(SRCDIR)/%.c
    <your compilation recipe>

clean:
    rm -f $(OBJS) mylib.a

当然,在你的食谱中,不要犹豫使用automatic variables 和你自己声明的变量,例如OBJS。例子:

mylib.a: $(OBJS)
    $(AR) $@ $^

$(OBJDIR)/%.o: $(SRCDIR)/%.c
    $(CC) $(CFLAGS) -c $< -o $@

【讨论】:

  • 我的答案的扩展版能解决你的问题吗?
  • 答案的扩展版很有用,是的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2019-07-08
  • 1970-01-01
相关资源
最近更新 更多