将依赖项添加到库中,并将它们添加到依赖于该库的二进制文件中

add dependencies to a library, and add them to a binary which depends on that library

本文关键字:添加 依赖于 二进制文件 依赖      更新时间:2023-10-16

我有什么:

我有一个非递归的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

问题:

  • 这可行吗?
  • 有人可以帮我语法吗?

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

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.