Global Makefile with scoped variables

Suedocode

I am attempting to convert my entire project to a single Makefile at the behest if this paper that I see littering all of my search results whenever I have a recursive makefile question. However, I have run into quite a fundamental problem that I'm not sure how to address. I would like to define a couple common but not identical variables for every Makefile module. To do this, I have created a Makefile.var file first:

# ============================================================================
# Common aliases for local dirs
# ============================================================================
# Every make module must define WORKING_DIR :=
BIN = $(WORKING_DIR)/bin
OBJ = $(WORKING_DIR)/obj
SRC = $(WORKING_DIR)/src
DEP = $(WORKING_DIR)/obj
INC = $(WORKING_DIR)/include
INCLUDES = -I$(INC)

ALL_SRCS   = $(wildcard $(SRC)/*.C)
ALL_INCS   = $(wildcard $(INC)/*.h)
ALL_OBJS   = $(subst $(SRC),$(OBJ),$(ALL_SRCS:%.C=%.o))
ALL_DEPS   = $(subst $(SRC),$(DEP),$(ALL_SRCS:%.C=%.d))

This is in a Makefile.var file that is included first in the master file. After this, subsequent makefile modules are included. Here is my master Makefile:

include MakeModules/Makefile.var
include MakeModules/Makefile.tools

clean: $(CLEAN_LIST)

all: $(MAKE_LIST)

Finally, here is what a module would look like. For ease, I'll just copy and paste the same module twice, and tweak the name for the second instantion. This is Makefile.tools:

# ============================================================================
# queuing (QUE)
# ============================================================================
WORKING_DIR := $(TOP)/tools/queuing
QUE_TARGET  := libqueue.so

-include $(DEP)/*.d

$(QUE_TARGET): $(ALL_OBJS)
    $(CPP) $(CFLAGS) -shared -o $@ $(ALL_OBJS)

que-clean:
    -rm -f $(OBJ)/*.o $(DEP)/*.d

CLEAN_LIST += que-clean
MAKE_LIST += $(QUE_TARGET)

# ============================================================================
# queuing2 (QUE2)
# ============================================================================
WORKING_DIR := $(TOP)/tools/queuing2
QUE2_TARGET := libqueue2.so

-include $(DEP)/*.d

$(QUE2_TARGET): $(ALL_OBJS)
    $(CPP) $(CFLAGS) -shared -o $@ $(ALL_OBJS)

que2-clean:
    -rm -f $(OBJ)/*.o $(DEP)/*.d

CLEAN_LIST += que2-clean
MAKE_LIST += $(QUE2_TARGET)

As you can see, Makefile.tools uses the derived variables from Makefile.var based on the value of WORKING_DIR. Well, this doesn't actually work because of the 2-phase reading that make does. The WORKING_DIR variable will only take on the last known assignment, and ALL_OBJS will be the same value for all rules regardless of where they are located. This means only the last defined module actually has the correct rules.

Is there a way to give access to the common BIN, OBJ, SRC, ... variables to each module without just c/ping over and over again with new prefixes? That is, can I scope a variable definition to a Makefile section and then change it later while retaining the old rules? I have an itching feeling that this isn't possible, but it would be really nice if I'm missing some nice trick that will wrap this up nicely. Otherwise, this global Makefile thing isn't really feasible (there are TONS of common variables used that derive values from the WORKING_DIR, which was scoped by recursive make previously).

Etan Reisner

When a variable is evaluated its value at that time is used. Most make variables are recursively expanded and are thus deferred in their evaluation until used in a "final" location.

Where that final location is (and when it occurs in the processing) differs depending on the purpose of the variable.

Variables (like CFLAGS) used in rule bodies are not evaluated until the rule body runs and as such are going to see the last value assigned during the parsing phase.

Variables used in make context itself are simpler to handle. All you need to do is create simply expanded (and thus immediately evaluated) variables that reference the common variables and use those in your specific makefiles. (Additionally, you may have just realized, this is a solution to the rule body variable problem as well... at least for rules you are writing yourself and not generic pattern rules.)

Solving this for generic pattern rules is also possible and requires target-specific simply expanded variables to shadow the global variables.

I've only got a minute so I can't explain in detail but here's an example makefile that shows some of the issues and one of the fixes I mentioned (the pattern rules/target-specific variables one). See if this makes sense. Ask any questions about things that don't make sense and I'll try to explain/answer when I get time.

all: $(addsuffix -tgt,main second third)

W_D := main
ALLOBJS = $(addprefix main-,one two three)
OBJ = main-obj
DEP = main-dep
M_TGT := main-tgt
$(M_TGT): OBJ := $(OBJ)
$(M_TGT): DEP := $(DEP)
$(M_TGT): $(ALLOBJS)

W_D := second
ALLOBJS = $(addprefix second-,one two three)
OBJ = second-obj
DEP = second-dep
S_TGT := second-tgt
$(S_TGT): $(ALLOBJS)

W_D := third
ALLOBJS = $(addprefix third-,one two three)
OBJ = third-obj
DEP = third-dep
T_TGT := third-tgt
$(R_TGT): $(ALLOBJS)

%:
        @echo Making '$@' $(if $^,from '$^')
        @echo 'OBJ=$(OBJ)'
        @echo 'DEP=$(DEP)'

Repeated include:

$ more inc.mk Makefile | cat
::::::::::::::
inc.mk
::::::::::::::
FOO:=$(PREFIX)_bar
$(PREFIX)_OBJS=wildcard $(PREFIX)/*
::::::::::::::
Makefile
::::::::::::::
PREFIX=one
include inc.mk
$(info FOO:$(FOO))
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS))
rule_one: PREFIX:=$(PREFIX)

PREFIX=two
include inc.mk
$(info FOO:$(FOO))
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS))
rule_two: PREFIX:=$(PREFIX)

PREFIX=three
include inc.mk
$(info FOO:$(FOO))
$(info $$(PREFIX)_OBJS:$($(PREFIX)_OBJS))
rule_three: PREFIX:=$(PREFIX)

all: rule_one rule_two rule_three

%:
        @echo '# Making $@'
        @echo FOO:$(FOO)
        @echo PREFIX_OBJS:$($(PREFIX)_OBJS)

$ make
FOO:one_bar
$(PREFIX)_OBJS:wildcard one/*
FOO:two_bar
$(PREFIX)_OBJS:wildcard two/*
FOO:three_bar
$(PREFIX)_OBJS:wildcard three/*
# Making rule_one
FOO:three_bar
PREFIX_OBJS:wildcard one/*
# Making rule_two
FOO:three_bar
PREFIX_OBJS:wildcard two/*
# Making rule_three
FOO:three_bar
PREFIX_OBJS:wildcard three/*
# Making all
FOO:three_bar
PREFIX_OBJS:wildcard three/*

You could even get more clever and define a canned recipe in the included file which takes a target name and creates the per-target variable assignments to avoid needing to do that part manually if you wanted to.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Global Makefile with scoped variables

From Dev

Are "global" makefile variables distinct from target-specific variables?

From Dev

Javascript: why do callback functions with global execution context have access to scoped variables?

From Dev

Javascript: why do callback functions with global execution context have access to scoped variables?

From Dev

Perl variables scoped within a sub

From Dev

C++ Global and Scoped integers initial values

From Dev

Is Facebook app-scoped id global unique?

From Dev

EntityManagerFactory: global or scoped instance when used in a Servlet?

From Dev

Using bash variables in Makefile

From Dev

Understanding Makefile Syntax and Variables

From Dev

Setting environment variables in a makefile

From Dev

Makefile adding spaces to variables

From Dev

Dollars in Makefile environment variables

From Dev

Conditional variables in a makefile

From Dev

Passing Variables in Makefile

From Dev

Conditional variables in a makefile

From Dev

Makefile adding spaces to variables

From Dev

How are Makefile variables calculated?

From Dev

How to introduce variables in Makefile

From Dev

Generic Makefile disregarding variables

From Dev

Intersperse items in Makefile variables

From Dev

Extern for Global and static global variables

From Dev

Go Initialization operator, package scoped variables - confused:

From Dev

GHC type functions and scoped type variables

From Dev

Static global variables vs global variables C

From Dev

Escaping makefile variables (for internal makefile use)

From Dev

Global variables and local variables in PowerShell

From Dev

Generate function and global variables

From Dev

Are my variables global?

Related Related

HotTag

Archive