问题
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:
$1being the library name$2being 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:
$1being the binary name$2being the list of source files$3being 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:
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.
来源:https://stackoverflow.com/questions/30797762/add-dependencies-to-a-library-and-add-them-to-a-binary-which-depends-on-that-li