makefile 库依赖 - 解决循环依赖
makefile library dependencies - resolve circular dependency
我正在尝试在我的 makefile 中构建一个功能,它允许我指定特定库 依赖于
的库列表
这将允许在重建库的依赖项时自动重建该库的依赖项,并将依赖项添加到 link 行。
我在 SO 上问了一个相关问题,根据给定的答案,我想出了以下测试
uniq = $(if ,$(firstword ) $(call uniq,$(filter-out $(firstword ),)))
expand-deps = $(foreach _,, $(call expand-deps,$($__deps)))
make-dep-list = $(call uniq,$(call expand-deps,))
define make-lib
$(warning _deps: )
# capture the list of libraries this library depends on
_deps =
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning dep-list: [$(call make-dep-list,)])
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))
makefile 将陷入无限循环。
如何让用户指定循环依赖,跳出无限循环?
所以,你的问题是你正在递归地扩展 lib_deps
(比方说)。在这样做的同时,您又开始扩展 lib_deps
。无限循环(呃,堆栈崩溃)。为了阻止自己,你需要保留一份你已经扩展过的东西的清单。脱离函数式风格并将答案保留在全局 expansion
(啊!)中,类似于:
expand-deps = \
$(foreach _,, \
$(if $(filter $_,${expansion}),, \
$(eval expansion += $_)$(call expand-deps,${$__deps})))
make-dep-list = $(eval expansion :=)$(call expand-deps,)${expansion}
define make-lib
$(warning _deps: )
# capture the list of libraries this library depends on
_deps :=
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning dep-list: [$(call make-dep-list,)])
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
,将其替换为传递的参数。)
我正在尝试在我的 makefile 中构建一个功能,它允许我指定特定库 依赖于
的库列表这将允许在重建库的依赖项时自动重建该库的依赖项,并将依赖项添加到 link 行。
我在 SO
uniq = $(if ,$(firstword ) $(call uniq,$(filter-out $(firstword ),)))
expand-deps = $(foreach _,, $(call expand-deps,$($__deps)))
make-dep-list = $(call uniq,$(call expand-deps,))
define make-lib
$(warning _deps: )
# capture the list of libraries this library depends on
_deps =
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning dep-list: [$(call make-dep-list,)])
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))
makefile 将陷入无限循环。
如何让用户指定循环依赖,跳出无限循环?
所以,你的问题是你正在递归地扩展 lib_deps
(比方说)。在这样做的同时,您又开始扩展 lib_deps
。无限循环(呃,堆栈崩溃)。为了阻止自己,你需要保留一份你已经扩展过的东西的清单。脱离函数式风格并将答案保留在全局 expansion
(啊!)中,类似于:
expand-deps = \
$(foreach _,, \
$(if $(filter $_,${expansion}),, \
$(eval expansion += $_)$(call expand-deps,${$__deps})))
make-dep-list = $(eval expansion :=)$(call expand-deps,)${expansion}
define make-lib
$(warning _deps: )
# capture the list of libraries this library depends on
_deps :=
endef
define make-bin
# show the fully expanded list of libraries this binary depends on
$(warning dep-list: [$(call make-dep-list,)])
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
,将其替换为传递的参数。)