繁体   English   中英

Makefile依赖项修改检测

[英]Makefile dependency modification detection

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

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

当对LIB中的头文件进行更改时,此makefile可以检测到该文件并在编译前重新编译+安装(将.a + .h文件复制到ONE和2)新版本的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处理复制到一个和两个)

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

     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:也许您需要向上移动LIB_HEADERS定义并将规则更改为
%.a%.h:$(LIB_HEADERS)吗?

很抱歉不得不告诉您这一点,但是您的构建系统是一个怪物。 您正试图通过大量使用递归Make来进行复杂的依赖关系处理; 递归Make有其用途,但其缺点之一是它使Make的固有能力无法处理依赖项。 还有其他问题表明该系统的作者并没有真正理解Make的工作原理或良好的makefile的外观。

当您在LIB/src/更改头文件时,Make不运行此%.a %.h:规则的原因是该规则没有依赖性,并且该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/

暂无
暂无

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

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