Makefile依赖项修改检测

Makefile依赖项修改检测,makefile,gnu-make,Makefile,Gnu Make,我正在编写一个makefile来处理buildunitone和TWO->buildunitlib的依赖关系 所谓构建单元,我指的是包含src、lib、include和bin目录的目录,以及用于在src中编译源代码的makefile。库放在lib中,库头文件放在include中。编译后的二进制文件放在bin中。构建单元接受make、make all、make lint和make clean 当对LIB中的头文件进行更改时,此makefile用于检测它,并在编译之前将copy.a+.h-files重

我正在编写一个makefile来处理buildunitone和TWO->buildunitlib的依赖关系

所谓构建单元,我指的是包含src、lib、include和bin目录的目录,以及用于在src中编译源代码的makefile。库放在lib中,库头文件放在include中。编译后的二进制文件放在bin中。构建单元接受make、make all、make lint和make clean

当对LIB中的头文件进行更改时,此makefile用于检测它,并在编译之前将copy.a+.h-files重新编译并安装到新版本的LIB中的一个和两个

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

%.a %.h:
    @echo ---------- Compiling LIB ----------
    @cd LIB && gmake.exe LIB

LIB_HEADERS := $(wildcard LIB/src/*.h)

ONE: ONE/lib/libLIB.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

TWO: TWO/lib/libLIB.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@
假设makefile for LIB处理复制为1和2的操作

为什么make不运行规则%.a%.h:当我更改LIB/src中的一个头文件时? 如何将一和二归纳为一条规则?我想这样做,但目标不能在依赖项中使用,至少这样:

ONE TWO: $@/lib/libLIB.a $(subst LIB/src/,$@/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe
更新:

我通过后退一步,绘制有向无环图,并考虑单个文件,而不是某一类型的所有文件,找到了解决方案

为了完整起见,以下是不太优雅的解决方案:

.PHONY: ONE TWO CLEAN LINT

ALL: ONE TWO

LIB_HEADERS := $(sort $(subst name.h,,$(wildcard LIB/src/*.h)))

# ------------------------------------------------------------
ONE/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir ONE\\include 2> NUL || :)
    @copy $(subst /,\,$<) ONE\\include\\ 1> NUL

TWO/include/%.h: LIB/src/%.h
    @echo Copying $< to $@
    @mkdir TWO\\include 2> NUL || :)
    @copy $(subst /,\,$<) TWO\\include\\ 1> NUL
# ------------------------------------------------------------
ONE/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir ONE\\lib 2> NUL || :)
    @copy $(subst /,\,$<) ONE\\lib\\ 1> NUL

TWO/lib/liblib.a: LIB/bin/liblib.a
    @echo Copying $< to $@
    @mkdir TWO\\lib 2> NUL || :)
# Windows-equivalent of touch (discarding any output to stdout):
    @copy $(subst /,\,$<) TWO\\lib\\ 1> NUL
# ------------------------------------------------------------
LIB/bin/liblib.a: $(LIB_HEADERS) $(wildcard LIB/src/*.cpp)
    @echo ---------- Looking for changes to liblib ----------
    @cd LIB && gmake.exe LIB
    @copy /b $(subst /,\,$@) +,, 1> NUL || :)
# ------------------------------------------------------------
ONE: ONE/lib/liblib.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling ONE ----------
    @cd ONE && gmake.exe

TWO: TWO/lib/liblib.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling TWO ----------
    @cd TWO && gmake.exe
# ------------------------------------------------------------
CLEAN LINT:
    @cd ONE && gmake.exe $@
    @cd TWO && gmake.exe $@
    @cd LIB && gmake.exe $@

我非常欢迎关于如何进一步概括1和2的提示。

对于问题1:可能需要将LIB_HEADERS定义上移,并将规则更改为 %.a%.h:$LIB_头

很抱歉不得不告诉您,您的构建系统是一个怪物。您正试图通过过度使用递归Make来进行复杂的依赖处理;递归Make有它的用途,但它的缺点之一是它破坏了Make处理依赖关系的固有能力。还有其他一些问题表明,这个系统的作者并不真正理解Make是如何工作的,或者一个好的makefile应该是什么样子

Make不运行此%.a%.h:在LIB/src/中更改头文件时的规则是,此规则没有依赖项,并且此makefile中的任何内容都不依赖于不存在的头文件。如果这对你来说毫无意义,那么你就不明白如何制定规则

这些规则:

ONE: ONE/lib/libLIB.a $(subst LIB/src/,ONE/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

TWO: TWO/lib/libLIB.a $(subst LIB/src/,TWO/include/,$(LIB_HEADERS))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe
可合并为一条规则:

ONE TWO: % : %/lib/libLIB.a $(addprefix %/include/,$(notdir $(LIB_HEADERS)))
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe
但不要这样做。相反,应该删除一个/include/和两个/include/,因为它们只会带来头痛。那么这里的规则就是

ONE TWO: % : %/lib/libLIB.a $(LIB_HEADERS)
    @echo ---------- Compiling $@ ----------
    @cd $@ && gmake.exe

1/和2/中的makefile可以引用LIB/src/

当然可以吗?我说服自己的方法是,认为include文件夹中的头文件类似于.o-files,src中的头文件类似于.cpp文件,而copy命令就是编译器。区别在哪里?顺便说一句,是的,我是新来的,我没有要求任何其他东西。虽然我非常感谢你的建议,但听到你不知道自己在做什么是非常令人沮丧的。@Chetic:请理解我是在帮助你,而不仅仅是在扔石头。如果您编写了这个makefile,那么您正在尝试在能够走路之前跑步,您可以做的最好的事情就是停下来尝试一些更温和的设计。我很乐意提供帮助,但我们必须从简单开始,到复杂。我建议从LIB/开始。您能进一步解释一下为什么不执行%.a%.h规则吗?1和2的依赖关系符合模式,因此从我的理解来看,它应该执行。即使我将$LIB_头添加为依赖项,这意味着我要在修改它们时检测的头文件被显式列为依赖项,但在我更改文件时,规则不会执行。我告诉过你,该规则不会执行,因为即使添加$LIB_头,也存在一个和二个头的先决条件。对不起,我想我帮不了你。