Hi,
Apologies in advance for the length, but some background is needed...
I have a make file environment which builds objects, shared libraries and executable programs, using a non-recursive top-level make, following suggestions from Peter Miller's paper and Emile van Bergen's examples.
When a make file for a program is included, a variable is created which lists the libraries that the program is dependent on. When a make file for a library is included, a variable is created which lists any other libraries that this library is dependent on.
I had the same idea except that a library's makefile would actually include its dependencies' makefiles. In so doing, it would append to INCLUDES if need be and ensure that LIBRARIES is topologically sorted. Doing this also avoids circular dependencies among libraries (otherwise, without hacking, you'd wind up with circular makefile include's).
These variables are used to define dependency information for make, but also to allow a list of '-l<lib>' options to be constructed for the final link step (for the program).
The problem comes when the make file for the program is included before the make file for a dependent library. Because of this, the building of the '-l<lib>' list must be deferred until after all the make files are included. (Of course, the real make dependency is fine.)
Why not have the makefile for the program include the makefile for its dependency libraries?
One approach is to have two sets of make files in the directory hierarchy. The first set just builds up the library dependency information. I don't like this approach because of the extra 'walk' through the directory hierarchy.
I looked at using eval to do the work as part of the final link command. Here's a small make file which demonstrates this approach. Program Z is directly dependent on library A. Library A is directly dependent on library B:
prg_dep_Z = A lib_dep_A = B lib_dep_B =
recur = $(foreach lib_$(1),$(lib_dep_$(1)),$(call libdep,$(lib_$(1))))
define libdep all_dep += $(1) $(call recur,$(1)) endef
define prgdep $(foreach lib,$(prg_dep_$(1)),$(call libdep,$(lib))) endef
$(eval $(call prgdep,Z))
$(warning all_dep: $(all_dep))
all:
...running make on the above yields the correct result of 'A B':
gar-fc2:gregk ~ {1016} make Makefile:16: all_dep: A B make: Nothing to be done for `all'.
As a safety precaution, I wanted to ensure that a circular dependency did not cause make to loop forever (not sure if libraries are allowed to be dependent on each other and whether make handles it, but I'm assuming it is allowed and that make does handle it). I made lib_dep_B dependent on 'A' and tried changing the libdep define as follows:
define libdep ifneq ($(findstring $(1),$(all_dep)),$(1)) $(call recur,$(1)) endif all_dep += $(1) endef
...make just went into a endless loop.
I then looked into a different approach to the problem, creating a variable that I would later eval. Whenever a library make file is included, a variable is constructed as follows:
lib_dep_$(lib) := $(foreach lb,$(dep_libs),$$(lib_dep_$(lb))) lib_dep_$(lib) += $(lib)
...where $(dep_libs) is set to the libraries that this library is dependent on.
Whenever a program make file is included, a variable is constructed as follows:
prg_dep_$(prg) := $(foreach lb,$(libs),$$(lib_dep_$(lb)))
...where $(libs) is set to the libraries that this program is dependent on.
The intention was to then have something like this in the link call:
Z: $(objs) $(libs) $(CC) $($(eval $(prg_dep_Z)):%=-l%) ...
...this is simplified for the example. This didn't work. I placed some warning commands in the top level make file to see what was going on:
$(warning $(prg_dep_Z)) # this produced: $(lib_dep_A) $(lib_dep_B) $(warning $(lib_dep_A)) # this produced: $(lib_dep_B) A $(warning $(eval $(prg_dep_Z))) # this produced nothing
I'm using GNU make version 3.80 on RedHat Linux (both Fedora Core 2 and Enterprise Workstation 3).
Thanks in advance, Greg.
_______________________________________________ Help-make mailing list [EMAIL PROTECTED] http://lists.gnu.org/mailman/listinfo/help-make
