tags:

views:

47

answers:

4

I'm using Make and I have a makefile which sets a variable with a value that I need to override from a parent makefile. I've tried setting the variable in the parent makefile and using export to pass it to the submake but the variable is not using the passed down value, instead it is using the value explicitly set in the sub-Makefile.

I know that variables specified on the command line override any ordinary assignments in the makefile (unless override is used) but is there a way to achieve this for submakes without having to specify it on the command line for each invocation of the submake (because there are quite a few and I like to stay DRY)?

UPDATE

I should have mentioned that I can't modify the submake file because it's from an external repository that we track and I don't have the authority to modify it so I need to work at the parent makefile level to influence the submake.

EXAMPLE

Here's a representative target in the parent makefile that's calling the submake:

$.PHONY (external_lib)
$(external_lib): 
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_a
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_b
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_c
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_d
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_e
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_f
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_g
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_h
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_i
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) library
A: 

Section 5.7.2 of make.info (gnu make that is):

The special variable `MAKEFLAGS` is always exported. ...

Variables are _not_ normally passed down if they were created by
default by `make` (Implicit Rules)

if you want to export specific variables to sub-`make`, use the
`export` directive.

    export VARIABLE ...

So, my recommendation is to either use the MAKEFLAGS variable, or else explicitly export the variable you want to use.

John Weldon
Thanks John but as I mentioned in my question, I've tried using export but because the sub-makefile explicitly assigns that variable it's not using the exported value that's passed down.
TheJuice
A: 

You would need to check to see if the variable already has a value before assigning it in the sub-make.

From the GNU Make manual (http://www.gnu.org/software/make/manual/make.html) Section 6.5:

If you'd like a variable to be set to a value only if it's not already set, then you can use the shorthand operator ?=' instead of='. These two settings of the variable `FOO' are identical (see The origin Function):

 FOO ?= bar

and

 ifeq ($(origin FOO), undefined)
 FOO = bar
 endif
d.w.
+1  A: 

If you don't want your sub-makefile to override the value set by the parent, have the sub-makefile assign the value using the VARIABLE ?= value syntax. This will only perform the assignment if the variable has yet been defined. In your case, the variable will have been defined in the parent makefile so the assignment will not take place.

Update: If you can't modify the sub-makefile, then you don't have a lot of options. I would probably recommend setting the variable on the command line when you invoke the sub-make file. Wrap these definitions in a make variable for the sake of clarity. For example,

CUSTOM_DEFINITIONS := VAR1=value1 VAR2=value2 VAR3=value3
$(external_lib): 
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_a
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_b
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_c

It's not the prettiest solution, but it can be done from the parent makefile.

bta
Unfortunately I can't make (persistent) modifications to the submake file.
TheJuice
+1  A: 

(You appear to be using something other than GNUMake, which is the only Make I know, so take this with a grain of salt.)

First you can make your Makefile tidier by making the components separate targets:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) $@

(If you're worried about name collisions, there are simple ways to deal with that.)

Now if you want to override a variable called, say, VAR, you can do it all in one place:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) VAR=$(VAR) $@

This assumes that you want to override the same variable for all components, which is how I read the question. If you want to override a different variable for some targets, that's easy:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

VARNAME = VAR
$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) \
$(VARNAME)=$($(VARNAME)) $@

make_c: VARNAME=OtherVar
make_h: VARNAME=YetAnotherVar

If you want to override several variables for some targets, that's a little tricky...

Beta
Target-specific variable values is a GNU extension, I believe.
JesperE