help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problems with eval


From: Noel Yap
Subject: Re: Problems with eval
Date: Wed, 29 Sep 2004 12:40:16 -0400
User-agent: Mozilla Thunderbird 0.5 (Windows/20040212)

Greg Kilfoyle wrote:
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.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]