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?
So, you have these definitions (say)
Expanding
test_lib_DEPS
by hand, we find we first wantlib5
, followed by the recursive expansion of$lib5_DEPS
, thenlib4
and$lib4_DEPS
etc. A depth-first expansion.This gives
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 auniq
function in functional style: return the first element of the arguments, followed by a recursive call ofuniq
, but with the first element missing since we already have it.Giving