我正试图将我的整个项目转换为单个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限定。)
答案 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/*
您甚至可以更聪明地在包含文件中定义一个预制配方,该配方采用目标名称并创建每目标变量分配,以避免在需要时手动执行该部分。