Dependencies Makefile先决条件中的复杂模式替换

Dependencies Makefile先决条件中的复杂模式替换,dependencies,makefile,build-automation,Dependencies,Makefile,Build Automation,我有以下目录结构: ./ |- obj/ |--- debug/ |--- release/ |- bin/ |--- debug/ |--- release/ |- src/ |--- main.c |--- libb/ |----- foo.c |- include/ |--- libb/ |----- foo.h 此外,我在myMakefile中手动指定各个对象的依赖项,格式如下(示例): 现在我希望能够键入make bin/debug/main,这将生成必要的

我有以下目录结构:

./
 |- obj/
 |--- debug/
 |--- release/
 |- bin/
 |--- debug/
 |--- release/
 |- src/
 |--- main.c
 |--- libb/
 |----- foo.c
 |- include/
 |--- libb/
 |----- foo.h
此外,我在my
Makefile
中手动指定各个对象的依赖项,格式如下(示例):

现在我希望能够键入
make bin/debug/main
,这将生成必要的依赖项和目标文件:

  • obj/debug/libb/foo.o
  • obj/debug/main.o
  • bin/debug/main
我如何做到这一点?我目前的方法非常复杂且不完整:

  • 下面创建对象文件。但是,如果还不存在任何必要的子文件夹(
    libb
    ),它将无法创建这些子文件夹。它也不会跟踪任何更改的头文件。这部电影也许可以改编

    CFLAGS+=-I include
    
    obj/*/%.o: src/%.cpp
        $(CC) $(CFLAGS) $< -c -o $@
    
    不幸的是,这并没有自动构建依赖关系:它只是抱怨“obj/debug/libb/foo.o:没有这样的文件或目录”——但如果我使用
    mkdir obj/debug/libb手动构建这个文件,它的工作就够奇怪了;使obj/debug/libb/foo.o

    它也非常复杂,并且使用了免费的代码复制(如果不让它变得更复杂,我就无法摆脱它)


最简单的解决方案是什么?原则上,我不反对使用除
make
之外的其他东西,如果它广泛可用(autoconf…),但我更喜欢保持努力(以及需要的新学习)至少,从目前为止我所看到的情况来看,所有其他构建系统似乎都比响应

@是的,这使它变得稍微容易一些……但是重复仍然存在,而且不建立依赖关系的问题也存在

我已经找到了一种详细但有效(不复杂)的方法,使它能够处理submake调用(在单个Makefile中)

我们有只包含一条规则和依赖项定义的“外部制造”

A_DEPS=dep1 dep2
C_DEPS=dep2

##########################
# "outer" Make
bin/%/A bin/%/B bin/%/C:
    $(MAKE) BUILD="$*" TARGET=$(@F) DEPS="$($(@F)_DEPS)" GENRULE
实际上,我们在子调用时将“推断”信息转换为显式变量。Makefile的其余部分包含“通用目标规则”的定义,
GENRULE

##########################
# "inner" Make

%/*.o:
    mkdir -p "$(@D)" && touch "$@"

GENRULE: obj/$(BUILD)/$(TARGET).o $(DEPS:%=obj/$(BUILD)/%.o) 
    echo gcc -o "bin/$(BUILD)/$(TARGET)" $^
    mkdir -p "bin/$(BUILD)" && touch "bin/$(BUILD)/$(TARGET)"
.PHONY: GENRULE
同样,测试运行:

$ for target in bin/{debug,release}/{A,B,C}; do make -Bs "$target"; done

gcc -o bin/debug/A obj/debug/A.o obj/debug/dep1.o obj/debug/dep2.o
gcc -o bin/debug/B obj/debug/B.o
gcc -o bin/debug/C obj/debug/C.o obj/debug/dep2.o
gcc -o bin/release/A obj/release/A.o obj/release/dep1.o obj/release/dep2.o
gcc -o bin/release/B obj/release/B.o
gcc -o bin/release/C obj/release/C.o obj/release/dep2.o
所有对象都已创建:

$ find bin obj

bin
bin/debug
bin/debug/A
bin/debug/B
bin/debug/C
bin/release
bin/release/A
bin/release/B
bin/release/C
obj
obj/debug
obj/debug/A.o
obj/debug/B.o
obj/debug/C.o
obj/debug/dep1.o
obj/debug/dep2.o
obj/release
obj/release/A.o
obj/release/B.o
obj/release/C.o
obj/release/dep1.o
obj/release/dep2.o

对于简单变量(非依赖项),这里有一个使用$@和$(@F)自动变量的简单示例:

$ for target in bin/{debug,release}/{A,B,C}; do make -Bs "$target"; done

gcc -o bin/debug/A obj/debug/A.o obj/debug/dep1.o obj/debug/dep2.o
gcc -o bin/debug/B obj/debug/B.o
gcc -o bin/debug/C obj/debug/C.o obj/debug/dep2.o
gcc -o bin/release/A obj/release/A.o obj/release/dep1.o obj/release/dep2.o
gcc -o bin/release/B obj/release/B.o
gcc -o bin/release/C obj/release/C.o obj/release/dep2.o
$ find bin obj

bin
bin/debug
bin/debug/A
bin/debug/B
bin/debug/C
bin/release
bin/release/A
bin/release/B
bin/release/C
obj
obj/debug
obj/debug/A.o
obj/debug/B.o
obj/debug/C.o
obj/debug/dep1.o
obj/debug/dep2.o
obj/release
obj/release/A.o
obj/release/B.o
obj/release/C.o
obj/release/dep1.o
obj/release/dep2.o
EXTRA="--standardopts"
A_FLAGS="--a-opts"
B_FLAGS="--b-opts"

.SECONDEXPANSION:
    
debug/% release/%: EXTRA+=$($(@F)_FLAGS)

%/A %/B %/C:
    echo building $@ with $(EXTRA)