带有范围变量的全局Makefile

时间:2014-07-11 22:14:38

标签: makefile

我正试图将我的整个项目转换为单个Makefile,如果this论文,我看到每当我有一个递归的makefile问题时,我会乱丢我的所有搜索结果。但是,我遇到了一个基本问题,我不确定如何解决。我想为每个Makefile模块定义一些常见但不相同的变量。为此,我首先创建了一个Makefile.var文件:

# ============================================================================
# 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))

这是在主文件中首先包含的Makefile.var文件中。在此之后,包括后续的makefile模块。这是我的主人Makefile

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

clean: $(CLEAN_LIST)

all: $(MAKE_LIST)

最后,这是模块的样子。为了方便起见,我只需复制并粘贴相同的模块两次,然后调整第二个实例的名称。这是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)

如您所见,Makefile.tools根据Makefile.var的值使用WORKING_DIR中的派生变量。嗯,由于make所做的两阶段读数,这实际上并不起作用。 WORKING_DIR变量将仅采用最后一次已知的分配,ALL_OBJS将是所有规则的相同值,无论它们位于何处。这意味着只有最后定义的模块实际上具有正确的规则。

有没有办法让每个模块都可以访问常见的BIN, OBJ, SRC, ...变量而不需要使用新的前缀反复进行c / ping操作?也就是说,我可以将变量定义范围扩展到Makefile部分,然后在保留旧规则的同时更改它吗?我有一种瘙痒的感觉,这是不可能的,但如果我错过了一些很好的技巧,那将会非常好。否则,这个全局Makefile的东西实际上并不可行(有一些常见变量用于从WORKING_DIR派生值,这些值由先前的递归make限定。)

1 个答案:

答案 0 :(得分:1)

当评估变量时,使用其当时的值 。大多数make变量都是递归扩展的,因此在评估中推迟使用,直到用于“最终”位置。

最终位置(以及处理中发生的位置)根据变量的用途而有所不同。

规则体中使用的变量(如CFLAGS)在规则体运行之前不会被评估,因此会在解析阶段看到分配的最后一个值。

make上下文中使用的变量本身更易于处理。您需要做的就是创建简单扩展(因此立即评估)的变量,这些变量引用公共变量并使用特定makefile中的变量。 (另外,您可能刚刚意识到,这也是规则体变量问题的解决方案......至少对于您自己编写的规则而不是通用模式规则。)

也可以将此解决方案用于通用模式规则,并且需要特定于目标的扩展变量来遮蔽全局变量。

我只有一分钟,所以我无法详细解释,但这里是一个示例makefile,它显示了一些问题和我提到的修复之一(模式规则/特定于目标的变量之一)。看看这是否有意义。对任何没有意义的事情提出任何问题,我会在我有时间时解释/回答。

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)'

重复包括:

$ 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/*

您甚至可以更聪明地在包含文件中定义一个预制配方,该配方采用目标名称并创建每目标变量分配,以避免在需要时手动执行该部分。