多个子目录中目标文件的通用生成文件目标

Posted

技术标签:

【中文标题】多个子目录中目标文件的通用生成文件目标【英文标题】:Generic makefile target for object files in multiple subdirectories 【发布时间】:2015-04-01 18:02:49 【问题描述】:

我有一个目录结构如下的项目:

Root directory
    bin/ (for final executable)
    Mod1/
        build/ (for *.o / *.d files)
        inc/
        src/
    Mod2/
        build/
        inc/
        src/
    Mod.../ (future module directories)
        build/
        inc/
        src/
    makefile

我当前的 makefile 包含以下内容:

# Directory naming conventions
SRC_DIR_NAME = src
BUILD_DIR_NAME = build

# Parallel source/object/dependency file lists
SRCS = $(shell find -name *.cpp)
OBJS = $(subst $(SRC_DIR_NAME),$(BUILD_DIR_NAME),$(SRCS:%.cpp=%.o))

# Final executable
APP = bin/app

build: $(APP)

$(APP): $(OBJS)
    # link objects and compile app

%.o: %.cpp
    # compile sources into objects

我的文件列表按预期工作并产生:

SRCS=./mod1/src/file.cpp ./mod2/src/file.cpp
OBJS=./mod1/build/file.o ./mod2/build/file.o
DEPS=./mod1/build/file.d ./mod2/build/file.d

但是当我运行 make 时出现以下错误:

make: *** No rule to make target `mod1/build/file.o', needed by `/bin/app'.  Stop.

我的假设是:

%.o: %.cpp

不适用于类似的输入

mod1/build/file.o

有没有办法制作一个通用目标,该目标接受一个模块目录并为该模块的目标文件创建目标,这些目标文件需要该模块的源文件在其各自的子目录中?

我知道使用递归 make 可以解决这个问题,但我想尽可能避免使用该解决方案。

【问题讨论】:

这就是static pattern rules 的用途。好吧,它们至少对一件事有用。 @EtanReisner 我仍然没有取得任何进展。是否有将多个 % 通配符传递给目标? (例如 %/build/%.o: %/src/%.cpp) 【参考方案1】:

在 GNU Make 中无法表达如此复杂的目标。虽然有一种方法可以生成一组目标(和相应的规则)。除了使用某些工具生成 Makefile 的明显方法外,我们可以使用 GNU Make 的eval 功能以编程方式创建规则。示例代码如下。

# Directory naming conventions
SRC_DIR_NAME := src
BUILD_DIR_NAME := build

# source files list
SRCS := $(shell find -name '*.cpp')

# function to get obj file name from src file name
OBJ_FROM_SRC = $(subst /$(SRC_DIR_NAME)/,/$(BUILD_DIR_NAME)/,$(1:%.cpp=%.o))

# Final executable
APP := bin/app

.PHONY: build
.DEFAULT_GOAL := build

# rule template for obj
define obj_rule_by_src =
src := $(1)
obj := $$(call OBJ_FROM_SRC,$$(src))
OBJS := $$(OBJS) $$(obj)
$$(obj): $$(src)
    # compile source into object
    echo build $$@ from $$<
endef

# generate rules for OBJS
$(foreach src,$(SRCS),$(eval $(call obj_rule_by_src,$(src))))


$(APP): $(OBJS)
# link objects and compile app
    echo create $@ from $^

build: $(APP)

【讨论】:

以上是关于多个子目录中目标文件的通用生成文件目标的主要内容,如果未能解决你的问题,请参考以下文章

通用生成文件显示没有生成目标错误的规则

如何在“sbt dist”在目标/通用内部生成的脚本文件夹中包含一个附加文件?

C语言如何实现多个文件生成一个目标文件 例如,main.c config.h key.c key.h cmdline.c cmdlin.h 等这些文

VS中定义后期生成事件,希望生成的目标文件拷贝到指定目录当中

为多个目标编写一个包含一条规则的生成文件?

如何指定Makefile编译目标文件到指定目录