Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding submake assigned variables in a parent makefile

Tags:

makefile

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
like image 922
TheJuice Avatar asked Jun 23 '10 16:06

TheJuice


3 Answers

(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...

like image 177
Beta Avatar answered Sep 23 '22 19:09

Beta


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.

like image 41
bta Avatar answered Sep 22 '22 19:09

bta


Apart from using Export which is not always recommended, you can pass variables to sub-make files like this --

**HOSTCC = gcc**
CC= MIPS-GCC
FLAGS = -O2 -Wall -DSELECT_PROBLEM
M="CC=$(CC) $(FLAGS)"

all:

cd ../rng ; $(MAKE) $(M) **HOSTCC=$(HOSTCC)** ;

so if your sub-make file has 2 files each requires different compile toolchain you can do what is shown above.

like image 38
Sagar Zaveri Avatar answered Sep 24 '22 19:09

Sagar Zaveri