我正在编写一个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)
-
当我对LIB / src中的一个头文件进行更改时,make怎么没有运行规则"%.a %.h:"?
-
如何将ONE和TWO概括为单个规则?我想这样做(但目标不能在依赖项中使用,至少这种方式):
ONE TWO: $@/lib/libLIB.a $(subst LIB/src/,$@/include/,$(LIB_HEADERS))
@echo ---------- Compiling $@ ----------
@cd $@ && gmake.exe
UPDATE:
我找到了解决方案,退一步,绘制有向无环图,并考虑单个文件,而不是某种类型的所有文件 .
以下是(非常优雅)解决方案,为了完整性:
.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 回答
对于问题1:可能需要移动LIB_HEADERS定义并将规则更改为
%.a%.h:$(LIB_HEADERS)?
我很遗憾不得不告诉你这个,但你的构建系统是一个怪物 . 您试图通过奢侈地使用递归Make来进行复杂的依赖性处理;递归Make有它的用途,但它的一个缺点是它失败了Make的本机处理依赖性的能力 . 还有其他一些问题表明这个系统的作者并没有真正理解Make是如何工作的,或者是一个好的makefile应该是什么样子 .
当您在
LIB/src/
中更改头文件时Make不运行此%.a %.h:
规则的原因是此规则没有依赖关系,并且此makefile中的任何内容都不依赖于不了解Make规则如何工作的头文件 .这些规则:
可以合并为一个规则:
But don't do this. 相反,消除
ONE/include/
和TWO/include/
,因为它们只带来头痛 . 然后这里的规则可以ONE/
和TWO/
中的makefile可以引用LIB/src/
.