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

334 views Asked by At

What I have:

I have a non-recursive makefile which searches for module.mk files, and includes them

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

If I want to create a static library, the module.mk looks like this:

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

Which will find a list of all .cpp files in the current directory, and call do-make-lib, with:

  • $1 being the library name
  • $2 being the list of source files

do-make-lib is defined as follows (some details omitted for brevity):

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

Now when I build a binary, module.mk looks like this:

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

Similarly, make-bin will find a list of all .cpp files in the current directory, and call do-make-bin, with:

  • $1 being the binary name
  • $2 being the list of source files
  • $3 being the list of static libraries to link against

do-make-bin is defined as follows:

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

My problem:

Libraries depend on other libraries. When I link the binary, I need to give is a list of all the libraries it depends on, in the correct order.

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

What I want:

I would like to pass an additional parameter to make-lib which is a list of dependencies

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

In do-make-lib I could then make a variable which includes the name of the library being built, which captures the dependencies

pseudo code (not sure of syntax - how do I build a variable from another variable?)

$1_DEPS = $3

Then when building my binary I can include the libs' dependencies as dependencies of the binary, and also add them to the link line

pseudo code (not sure of syntax)

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

Questions:

  • Is this feasible?
  • Can someone help me with the syntax?
1

There are 1 answers

1
bobbogo On BEST ANSWER

So, you have these definitions (say)

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

Expanding test_lib_DEPS by hand, we find we first want lib5, followed by the recursive expansion of $lib5_DEPS, then lib4 and $lib4_DEPS etc. A depth-first expansion.

expand = $(foreach _,$1,$_ $(call expand,${$__DEPS}))

$(error [$(call expand,${test_lib_DEPS})])

This gives

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

Pretty good. You may wish to tease out those duplicates. $(sort) fits the bill, but when linking you probably want to preserve ordering. Following similar arguments we can write a uniq function in functional style: return the first element of the arguments, followed by a recursive call of uniq, but with the first element missing since we already have it.

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})])

Giving

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