具有范围变量的全局Makefile [英] Global Makefile with scoped variables

查看:59
本文介绍了具有范围变量的全局Makefile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果这篇论文,我试图将我的整个项目转换为单个Makefile每当遇到递归makefile问题时,我都会发现所有搜索结果都乱七八糟.但是,我遇到了一个非常基本的问题,我不确定该如何解决.我想为每个Makefile模块定义几个常见但不完全相同的变量.为此,我首先创建了一个Makefile.var文件:

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

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

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)

最后,这是模块的外观.为简便起见,我将复制和粘贴相同的模块两次,然后为第二个实例调整名称.这是Makefile.tools:

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)

如您所见,Makefile.tools使用基于WORKING_DIR的值从Makefile.var派生的变量.嗯,这实际上不起作用,因为make可以进行两相读取. WORKING_DIR变量将仅接受最后一次已知的赋值,并且ALL_OBJS对于所有规则将是相同的值,无论它们位于何处.这意味着只有最后定义的模块实际上具有正确的规则.

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.

有没有一种方法可以使对每个模块的公共BIN, OBJ, SRC, ...变量的访问权不只是用新的前缀反复遍历c/ping?也就是说,我可以将变量定义的作用域限定在Makefile节中,然后在保留旧规则的情况下进行更改吗?我有点发痒的感觉,这是不可能的,但是如果我错过了一些很好的技巧可以很好地解决这个问题,那将是非常好的.否则,这种全局Makefile事情实际上是不可行的(使用了TONS的公用变量来从WORKING_DIR派生值,该变量以前由递归make限定).

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

推荐答案

对变量求值时,将使用当时的值 .大多数make变量会递归扩展,因此将其评估推迟到最终"位置使用.

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.

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

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.

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

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.

我只有一分钟的时间,所以我无法详细解释,但是这里有一个示例makefile,其中显示了一些问题以及我提到的一种修复方法(模式规则/特定于目标的变量一个).看看这是否有意义.询问关于没有意义的事情的任何问题,我会在有时间的时候尝试解释/回答.

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

重复包括:

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

这篇关于具有范围变量的全局Makefile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆