Makefile依赖修改检测

时间:2013-09-17 13:50:08

标签: makefile gnu-make

我正在编写一个makefile来处理构建单元ONE和TWO的依赖关系 - >建设单位LIB。

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

当对LIB中的头文件进行更改时,此makefile用于检测它并在编译之前重新编译+安装(将.a + .h文件复制到ONE和TWO)新版本的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 $@

(假设LIB的makefile处理复制到ONE和TWO)

  1. 当我对LIB / src中的一个头文件进行更改时,make怎么没有运行规则“%.a%.h:”?
  2. 如何将ONE和TWO概括为单个规则?我想这样做(但目标不能在依赖项中使用,至少这种方式):

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

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

    为了完整性,这是(不是很优雅)的解决方案:

    .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 $@
    

    我非常欢迎有关如何进一步概括ONE和TWO的提示。

2 个答案:

答案 0 :(得分:0)

对于问题1:可能需要移动LIB_HEADERS定义并将规则更改为
    %.a%.h:$(LIB_HEADERS) ?

答案 1 :(得分:0)

我很遗憾不得不告诉你这个,但你的构建系统是一个怪物。您试图通过奢侈地使用递归Make来进行复杂的依赖性处理;递归Make有它的用途,但它的一个缺点是它失败了Make的本机处理依赖性的能力。还有其他一些问题表明这个系统的作者并没有真正理解Make是如何工作的,或者是一个好的makefile应该是什么样的。

当您更改%.a %.h:中的头文件时Make不运行此LIB/src/规则的原因是此规则没有依赖关系,此makefile中的任何内容都不依赖于不具有的头文件存在。如果这对你没有意义,那么你就不明白Make规则是如何运作的。

这些规则:

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

但是不要这样做。相反,消除ONE/include/TWO/include/,因为它们只带来头痛。那么这里的规则可以是

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

并且ONE/TWO/中的makefile可以引用LIB/src/