6

I'm trying to glue two build systems together. Both are recursive (rules in the makefile use make to call other makefiles to build components of the project).

I'll call them 'A' and 'B' where 'A' builds the application and 'B' builds libraries used by 'A'.

The top level makefile in A calls 'make TARGET=whatever' which means that all the recursively-invoked bits of the build inherit the value of TARGET as a read-only variable, including the build system from B, which is called as part of the recursive build.

I don't want this to happen in the build system for 'B' (which come from a different project) as the makefiles there use TARGET for their own purposes and the build fails since TARGET has the wrong value and is read-only.

I can only see two solutions to this, neither of which is palettable;

1) Rename TARGET to something else in the makefile in A that sets it and in the makefiles in A that use it, to avoid the clash with the lower levels of the build system.

2) Use the 'override' directive everywhere in the makefiles in B where the TARGET variable is set, to override its read-only status.

Anyone got any better ideas? - ideally, I want nothing to be inherited by the B's build system from A's, except those options I explicitly pass to the B build system from A.

Incidentally, I'm using GNU Make v3.80.

Ludwig Weinzierl
  • 15,980
  • 10
  • 45
  • 49
  • If you don't want to set TARGET in B's makefile, then why are you passing TARGET=whatever in A's makefile? – JesperE Jun 01 '09 at 14:32
  • A's top-level makefile passes TARGET=whatever to a second-level makefile in A (which needs it) and the second-level makefile in A then calls B's makefile, which inherits TARGET as a read-only variable from the environment of the second-level make. – John Skilleter Jun 01 '09 at 15:04

4 Answers4

3

You could set MAKEOVERRIDES to nothing in the second-level makefile in A.

callb:
      cd subdir && $(MAKE) MAKEOVERRIDES=

This passes down the normal commandline parameters like -k and -s but not commandline variable definitions.

Or you use the historical MFLAGS which is the same as MAKEFLAGS except MFLAGS doesn't contain the commandline variable definitions.

callb:
     cd subdir && $(MAKE) $(MFLAGS)

Details about this two options can be read here: The GNU Make Manual

0

It sounds like you have modified the A makefile to recursively invoke the B makefile, and thus your problem. Why not instead introduce a new toplevel makefile which recursively invokes the B makefile, and then recursively invokes the A makefile? For example, combined.mk:

all:
    $(MAKE) -f Makefile.B
    $(MAKE) -f Makefile.A

That way the B makefile inherits nothing from the A makefile.

Eric Melski
  • 16,432
  • 3
  • 38
  • 52
0

Perhaps you can use the "unexport" directive to prevent TARGET from being propagated to B's makefile?

JesperE
  • 63,317
  • 21
  • 138
  • 197
  • Unfortunately, the unexport directive only prevents variables exported using export from being exported - it has no effect on variables passed on the command line to the current make process or inherited from the command line of a parent make. It looks as if setting a value via the make command line makes it indestructably read-only to all child makes. – John Skilleter Jun 02 '09 at 09:33
0

At the point where build system A invokes build system B, do not use '${MAKE}' directly; invoke a shell script that invokes build system B (possibly after sanitizing the environment).

To achieve the behaviour where the commands are executed by 'make -n', prefix the command line in the makefile with '+' (similar to prefixing the line with '@' or '-').

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278