help-make
[Top][All Lists]
Advanced

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

Re: recursive/multiplatform make


From: Markus Mauhart
Subject: Re: recursive/multiplatform make
Date: Wed, 9 Jul 2003 11:28:29 +0200

"Bruce Jones" <address@hidden> wrote ...
>
> I am trying to create some Makefiles for multi-architecture builds as
> described here http://make.paulandlesley.org/multi-arch.html.  I am
> using the advanced VPATH method and that works fine.
>
> My problem is that some of the directories have both source code and
> sub-directories to build.  Normally I would do something like this.
>
> all: subdirs src
>
> subdirs:
> for i in $(SUBDIRS); do \
> $(MAKE) -C $$dir; \
> done

?? "i" and "dir" ??

>
> src:
> whatever
>
> But using the VPATH method, the make switches to the obj directory first
> and then fails because it can't find the subdirs.  What would be the best
> way to handle this situation ?

The best solution for most problems is using the __FILE__ variable ;-)
It needs at least GNUmake 3.80.

replace every line ...

   SUBDIRS += anything

... with ...

   SUBDIRS += ($addprefix $(dir $(__FILE__)),anything)

... and pay attention that SUBDIRS is NOT a recursive variable
(SUBDIRS = ....), instead initialize it with SUBDIRS := .... ,
then the following will do what you wanted:

subdirs: $(SUBDIRS)

define dir_specific
$$(dir):
    $$(MAKE) -C $$@
endef

$(foreach dir,$(SUBDIRS),$(eval $(dir_specific)))

Pay attention NOT to use __FILE__ (or any recursive variable that
referres to __FILE__) inside rule-commands, cause at the time when
make parses the commands, __FILE__ points to the top-level makefile,
or to nothing.


What I mean generally with __FILE__ is:

  Inside that makefile that KNOWS the relative path's of some
  other files or directory, add this makefile-local knowledge
  to all rules and variables that prior or later need to access
  the files or directories from within another directory.

In my case the result is that I dont use any implicit rules or VPATH,
instead I generate all explicit rules via 'eval' like ...

mains  := $(wildcard $(__FILE_DIR__)*.cpp)

tmp  := $(call app_from_main,$(mains))
apps  += $(tmp)
targets  += $(tmp)

define main_specific
app  := $$(call app_from_main,$$(main))
$$(app).input := $$(main) #$(call obj_from_src,misc.cpp)
endef

$(foreach main,$(mains),$(eval $(main_specific)))
...
apps := $(sort $(apps)) #remove duplicates
$(foreach app,$(apps),$(eval $(app_specific)))

(but for complicated 'eval' you will need make380
+ the eval-virtual-memory-patch)


Back to your original problem and using __FILE__ for it.
__FILE__ is not builtin, therefore you have to compute it yourself:

__FILE__ := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))

The 1st problem is that this variable only points to the current
makefile (relative to CURDIR)  IF  you didnt include another makefile
before doing this computation.

The 2nd problem comes as soon as you include another makefile after
this computation, and the other makefile recomputes __FILE__.

My current solution is ...


1) put this complicated definitions inside your toplevel makefile or
inside any makefile you like:
#***************************************
# __FILE__
#
var_from_string = $1

define __FILE__prefix
tmp := $$(word $$(words $$(MAKEFILE_LIST)),$$(MAKEFILE_LIST))
$$(call var_from_string,$$(tmp))__FILE__parent := $$(__FILE__)
__FILE__ := $$(tmp)
endef

define __FILE__suffix
__FILE__ := $($(call var_from_string,$(__FILE__))__FILE__parent)
endef

#__FILE_DIR__ = $(dir $(__FILE__))
# !!! unlike CURDIR, __FILE_DIR__ has a trailing slash !!!
#
# __FILE__
#***************************************

2) then, inside any makefile that needs to use __FILE__, put one line
BEFORE including any other file:

    $(eval $(__FILE__prefix))

... and anytime after having used __FILE__ (e.g. at the end of the makefile),
you have to restore the old state of __FILE__ ...

    $(eval $(__FILE__suffix))


One funny sideeffect is that my makefiles now know their parents
(better: all their parants that use __FILE__):

    parent := $($(__FILE__)__FILE__parent)
    grandma:= $($(parent)__FILE__parent)


Regards,
Markus.







reply via email to

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