我正在尝试在我的Makefile中构建一个功能,该功能允许我指定特定库取决于的库列表
如果重建了库的依赖关系,并且库的依赖关系已添加到链接行,这将允许该库的依赖关系自动重建。
我在SO here上问了一个相关的问题,并通过给出的答案,我想到了以下测试
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
expand-deps = $1 $(foreach _,$1, $(call expand-deps,$($__deps)))
make-dep-list = $(call uniq,$(call expand-deps,$1))
define make-lib
$(warning $1_deps: $2)
# capture the list of libraries this library depends on
$1_deps = $2
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning $1 dep-list: [$(call make-dep-list,$2)])
endef
#$(eval $(call make-lib, thread, log utils)) circular-dependency log->thread; thread->log
$(eval $(call make-lib, thread, utils))
$(eval $(call make-lib, log, thread))
$(eval $(call make-lib, order, log))
$(eval $(call make-lib, price, log))
$(eval $(call make-bin, test, order price))
运行上面的makefile会产生以下结果:
$ make
makefile:15: thread_deps: utils
makefile:16: log_deps: thread
makefile:17: order_deps: log
makefile:18: price_deps: log
makefile:19: test dep-list: [order price log thread utils ]
make: *** No targets. Stop.
库可能具有循环依赖关系。
例如:日志记录库是多线程的,因此需要线程库。线程库可以发出日志语句,因此需要日志库。
如果我取消注释具有循环依赖关系的行
$(eval $(call make-lib, thread, log utils))
$(eval $(call make-lib, log, thread))
生成文件将陷入无限循环。
如何允许用户指定循环依赖关系并突破无限循环?
最佳答案
因此,您的问题是您要递归扩展lib_deps
(例如)。在执行此操作时,您将再次开始扩展lib_deps
。无限循环(错误,堆栈崩溃)。要停止自己,您需要保留一份已经扩展的列表。脱离了功能风格,并将答案保留在全局expansion
(ugh!)中,如下所示:
expand-deps = \
$(foreach _,$1, \
$(if $(filter $_,${expansion}),, \
$(eval expansion += $_)$(call expand-deps,${$__deps})))
make-dep-list = $(eval expansion :=)$(call expand-deps,$1)${expansion}
define make-lib
$(warning $1_deps: $2)
# capture the list of libraries this library depends on
$1_deps := $2
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning $1 dep-list: [$(call make-dep-list,$2)])
endef
$(eval $(call make-lib,thread,log utils))#circular-dependency log->thread; thread->log
#$(eval $(call make-lib,thread,utils))
$(eval $(call make-lib,log,thread))
$(eval $(call make-lib,order,log))
$(eval $(call make-lib,price,log))
$(eval $(call make-bin,test,order price))
(作为练习,您可能希望以功能样式重写此代码,即,删除全局
$expansion
,将其替换为可以传递的参数。)