【问题标题】:add dependencies to a library, and add them to a binary which depends on that library将依赖项添加到库中,并将它们添加到依赖于该库的二进制文件中
【发布时间】:2015-06-12 07:37:37
【问题描述】:

我有什么:

我有一个非递归的 makefile,它搜索 module.mk 文件并包含它们

modules := $(shell find . -name module.mk)
include $(modules)

如果我想创建一个静态库module.mk 看起来像这样:

$(eval $(call make-lib, test_lib))

这将找到当前目录中所有.cpp文件的列表,并调用do-make-lib,其中:

  • $1 是库名
  • $2 为源文件列表

do-make-lib定义如下(部分细节省略):

define do-make-lib
    $(addprefix $(addprefix $(LIB_DIR)lib,$1),.a): $(call src_to_obj, $2)
    @$(AR) $(ARFLAGS) $$@ $$?
endef

现在当我构建一个二进制文件时,module.mk 看起来像这样:

$(eval $(call make-bin, test_bin, test_lib))

同样,make-bin 会在当前目录中找到所有.cpp 文件的列表,并调用do-make-bin,使用:

  • $1 是二进制名称
  • $2 是源文件列表
  • $3 是要链接的静态库列表

do-make-bin定义如下:

define do-make-bin
    $(addprefix $(BIN_DIR),$1): $(call src_to_obj,$2) \
        $(addsuffix .a,$(addprefix $(LIB_DIR)lib,$3))))
    @$(CXX) $(call src_to_obj,$2) \
        -L/usr/lib -L$(LIB_DIR) \
        -Wl$(,)-Bstatic $(addprefix -l,$3) \
        -o $$@
endef

我的问题:

库依赖于其他库。当我链接二进制文件时,我需要以正确的顺序给出它所依赖的库的列表。

$(eval $(call make-bin, my_bin, lib5 lib4 lib3 lib2 lib1))

我想要什么:

我想向make-lib 传递一个附加参数,它是依赖项

的列表
$(eval $(call make-lib, test_lib, lib3 lib2 lib1))

do-make-lib 中,我可以创建一个变量,其中包含正在构建的库的名称,它捕获依赖项

伪代码(不确定语法 - 如何从另一个变量构建变量?)

$1_DEPS = $3

然后在构建我的二进制文件时,我可以将库的依赖项包含为二进制文件的依赖项,并将它们添加到链接行

伪代码(不确定语法)

define do-make-bin

    # build a list of dependencies, eg: lib2_DEPS lib2_DEPS lib1_DEPS
    $1_DEPS = $(addsuffix _DEPS,$3)

    $(addprefix $(BIN_DIR),$1): $(call src_to_obj,$2) \
        $(addsuffix .a,$(addprefix $(LIB_DIR)lib,$3)) \
        $(addsuffix .a,$(addprefix $(LIB_DIR)lib,$($1_DEPS))))) # include the libs dependencies as dependencies of the binary
    @$(CXX) $(call src_to_obj,$2) \
        -L/usr/lib -L$(LIB_DIR) \
        -Wl$(,)-Bstatic $(addprefix -l,$3) $(addprefix -l,$($1_DEPS))) \ # link against dependencies' dependencies
        -o $$@
endef

问题:

  • 这可行吗?
  • 谁能帮我语法?

【问题讨论】:

    标签: c++ makefile gnu-make


    【解决方案1】:

    所以,你有这些定义(比如说)

    test_lib_DEPS := lib5 lib4 lib3 lib2 lib1
    lib5_DEPS := lib6 lib3
    lib6_DEPS := lib1
    lib2_DEPS := lib1
    

    手动扩展test_lib_DEPS,我们发现我们首先需要lib5,然后是$lib5_DEPS的递归扩展,然后是lib4$lib4_DEPS等。深度优先扩展。

    expand = $(foreach _,$1,$_ $(call expand,${$__DEPS}))
    
    $(error [$(call expand,${test_lib_DEPS})])
    

    这给了

    $ make
    1:9: *** [lib5 lib6 lib1  lib3  lib4  lib3  lib2 lib1  lib1 ].  Stop.
    

    相当不错。您可能希望梳理出这些重复项。 $(sort) 符合要求,但在链接时,您可能希望保留订单。根据类似的参数,我们可以编写函数式的uniq 函数:返回参数的第一个元素,然后递归调用uniq,但第一个元素丢失了,因为我们已经有了它。

    test_lib_DEPS := lib5 lib4 lib3 lib2 lib1
    lib5_DEPS := lib6 lib3
    lib6_DEPS := lib1
    lib2_DEPS := lib1
    
    uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
    depth-first = $(foreach _,$1,$_ $(call depth-first,${$__DEPS}))
    expand = $(call uniq,$(call depth-first,$1))
    
    $(error [$(call expand,${test_lib_DEPS})])
    

    给予

    $ make
    1:10: *** [lib5 lib6 lib1 lib3 lib4 lib2 ].  Stop.
    

    【讨论】:

    • 感谢您的回答!我有一个问题,我列出了一个循环依赖项。我问了related question here。请问您有什么意见吗?
    猜你喜欢
    • 2016-08-23
    • 2019-06-24
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多