简体   繁体   English

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

[英]Generic makefile target for object files in multiple subdirectories

I have a project with the following directory structure: 我有一个具有以下目录结构的项目:

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

My current makefile contains this: 我当前的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

My file lists work as expected and produce: 我的文件列表按预期工作并生成:

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

However when I run make I get the following error: 但是,当我运行make时,我收到以下错误:

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

My assumption is that: 我的假设是:

%.o: %.cpp

Doesn't work with a input like 不适合像这样的输入

mod1/build/file.o

Is there a way to make a generic target that takes a module directory and creates targets for that module's object files that require that module's source files in their respective sub-directories? 有没有办法制作一个通用目标,它接受一个模块目录,并为该模块的目标文件创建目标,这些目标文件需要该模块的源文件在各自的子目录中?

I know using recursive make can solve this issue but I want to avoid having to use that solution if possible. 我知道使用递归make可以解决这个问题,但我希望尽可能避免使用该解决方案。

There is no way to express such sophisticated target in GNU Make. 在GNU Make中无法表达如此复杂的目标。 Although there is a way to generate the set of targets (and corresponding rules). 虽然有一种方法可以生成目标集(和相应的规则)。 Except an obvious way to use some tool to generate Makefile, we can use eval feature of GNU Make to create rules programmatically. 除了使用某种工具生成Makefile的明显方法之外,我们可以使用GNU Make的eval功能以编程方式创建规则。 Example code is following. 示例代码如下。

# 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM