GNU Make的平面对象文件目录结构输出

Jus*_*cle 9 makefile gnu-make

我有一个使用GNU Make的C++小项目.我希望能够打开以下源文件:

src/
  a.cpp
  b/
    b.cpp
  c/
    c.cpp
Run Code Online (Sandbox Code Playgroud)

进入以下输出结构(此时我不关心重复):

build/
  a.o
  b.o
  c.o
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有以下内容,不幸的是,将.o和.d放在每个.cpp旁边:

OBJS            :=      $(foreach file,$(SRCS),$(file).o)
DEPS            :=      $(patsubst %.o,%.d,$(OBJS))
sinclude $(DEPS)

$(OBJS) : %.o : %.cpp
        @echo Compiling $<
        $(CC) $(CC_FLAGS) $(INCS) -MMD -o $@ $<  
Run Code Online (Sandbox Code Playgroud)

我知道$(notdir ...)函数,但此时我用它来过滤对象的努力失败了.任何人都可以对此有所了解吗?这似乎是合理的事情.

Dan*_*ing 9

至少有两种方法可以做到这一点.首先(以及我建议的)是您可以将构建目录添加到目标名称(即使使用模式规则).例如:

$(OBJS) : build/%.o : %.cpp
Run Code Online (Sandbox Code Playgroud)

其次,您可以使用VPATH变量告诉make在不同的目录中搜索先决条件.这可能是更常用(过)使用的方法.它至少有一个严重的缺点,那就是如果你使用它,后来遇到"重复"的问题,就没有办法解决问题.使用前一种方法,您始终可以镜像构建目录下的源目录结构,以避免重复冲突.

编辑:我以前的回答有点细节,所以我会对它进行扩展,以表明这实际上和宣传的一样.这是一个完整的工作示例Makefile,它使用上述第一种技术来解决问题.只需将其粘贴到Makefile中并运行make - 它将完成剩下的工作并显示这确实有效.

编辑:我无法弄清楚如何让我的答案文本中的标签字符(它用空格替换它们).复制并粘贴此示例后,您需要将命令脚本中的前导空格转换为选项卡.

BUILD_DIR := build

SRCS := \
    a.c \
    b.c \
    c.c \
    a/a.c \
    b/b.c \
    c/c.c

OBJS := ${SRCS:%.c=${BUILD_DIR}/%.o}

foo: ${OBJS}
    @echo Linking $@ using $?
    @touch $@

${BUILD_DIR}/%.o: %.c
    @mkdir -p $(dir $@)
    @echo Compiling $< ...
    @touch $@

${SRCS}:
    @echo Creating $@
    @mkdir -p $(dir $@)
    @touch $@

.PHONY: clean
clean:
    rm -f foo
    rm -f ${OBJS}
Run Code Online (Sandbox Code Playgroud)

特别要注意的是,源文件有重复的名称(ac和a/ac,bc和b/bc等),这不会导致任何问题.另请注意,没有使用VPATH,由于其固有的限制,我建议避免使用它.