makefile库依赖项 - 解决循环依赖项

时间:2015-06-15 05:26:42

标签: c++ makefile gnu-make

我正在尝试在我的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))

makefile会陷入无限循环。

如何允许用户指定循环依赖关系,并打破无限循环?

1 个答案:

答案 0 :(得分:1)

所以,你的问题是你递归地扩展lib_deps(比方说)。在此过程中,您再次开始展开lib_deps。无限循环(呃,堆栈崩溃)。要阻止自己,您需要保留已经扩展的事项列表。脱离功能风格并在全球范围内保持答案expansion(呃!),如:

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将其替换为传递的参数。)