具有作用域变量的全局 Makefile

2024-03-18

我正在尝试根据需要将整个项目转换为单个 Makefile,如果this http://aegis.sourceforge.net/auug97.pdf每当我遇到递归 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。嗯,这实际上不起作用,因为 2 相读数make做。这WORKING_DIR变量只会接受最后一次已知的赋值,并且ALL_OBJS所有规则的值都相同,无论它们位于何处。这意味着只有最后定义的模块实际上具有正确的规则。

有没有办法提供公共访问权限BIN, OBJ, SRC, ...每个模块的变量,而无需使用新前缀一遍又一遍地进行 c/ping?也就是说,我可以将变量定义的范围限定为 Makefile 部分,然后在保留旧规则的同时更改它吗?我有一种渴望这是不可能的感觉,但如果我错过了一些可以很好地解决这个问题的好技巧,那就太好了。否则,这个全局 Makefile 的事情实际上是不可行的(使用了大量的公共变量来从WORKING_DIR,之前的范围由递归 make 确定)。


当一个变量被求值时当时用来。大多数 make 变量都是递归扩展的,因此它们的计算被推迟,直到在“最终”位置使用。

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

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

make context 本身使用的变量更容易处理。您需要做的就是创建引用公共变量的简单扩展(因此立即评估)变量并在特定的 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/*

您甚至可以变得更聪明,在包含的文件中定义一个固定的配方,它采用目标名称并创建每个目标的变量分配,以避免需要手动执行该部分(如果您愿意)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有作用域变量的全局 Makefile 的相关文章

随机推荐

  • 无法将 NULL 值插入 AspNetUsers 表“Discriminator”列

    代码首次迁移后 使用寄存器添加用户失败 并显示 无法将 NULL 值插入表 aspnet BSF2013 20130918101120 dbo AspNetUsers 列 Discriminator 列不允许为空 创建用户代码是项目模板生成
  • 如何在计时器到期时关闭 InfoBox.Popup?

    我在 Outlook 2013 中从其他帖子中拼凑出了这个测试过程 它应该显示一个弹出框 然后在 3 秒后关闭 它永远不会关闭 Sub MessageBoxTimer Dim AckTime As Integer InfoBox As Ob
  • JLabel 超链接可在正确的 URL 处打开浏览器

    我需要使用 Java Swing 创建一个可单击的标签 并且能够打开桌面上的默认浏览器并将其重定向到特定的 url 我的代码能够打开浏览器 但无法将其重定向到正确的网址 加载默认主页 我的测试代码 import java awt impor
  • Node.js 用户名和密码认证

    我目前正在使用构建一个网络应用程序Node js and Express js 我正在寻找一种方法 在我的主目录中使用用户名和密码进行简单的服务器端身份验证app js正在监听的文件post请求于http www domain com lo
  • 如何在 Android 选择器中定义粗体?

    在我的 Android 应用程序中 我有几个单选按钮 它们应该具有不同的颜色并在选择时变为粗体 我设法通过定义来获得不同的颜色radio pick color xml可绘制文件
  • iOS 强密码自动填充未显示在确认密码上

    iOS 会自动填充第一个密码字段 但不会填充第二个密码字段 如何像应用程序中那样自动填充密码和确认密码字段 更新 系统似乎将注册表单视为登录表单 因此它会自动填充第一个密码字段 另外 当我导航回登录屏幕时 系统提示我是否要将密码保存在钥匙串
  • 如何在IDEA中打开项目时停止自动刷新SBT模块?

    我们有多个 Play 2 应用程序和模块 但我在将 IntelliJ IDEA 13 集成到我的开发流程中时遇到了问题 我有一个基于应用程序的公共父级的空项目 并且我已使用导入现有 SBT 项目选项将每个应用程序作为模块导入 我的问题是 每
  • Plotly for R:当数据集包含大于 1000 的数字时,删除 y 轴上出现的 k

    您好 关于plotly的一个 简单 问题 我想删除当数据集包含大于10000的数字时似乎自动出现在y轴上的k 我尝试将数据上传到plotly在线并将 k 放入以及 例如使用数据的子集 date lt c 1 07 1987 2 07 198
  • 应用程序部署到网络驱动器

    我有一个 NET 4 WPF需要在公司网络内运行的应用程序 该应用程序不使用本地文件 它确实有一个app config文件 但它只包含一些connection strings 用于数据存储 但中央SQL server数据库 将应用程序文件放
  • 如何在 python Bottle 中提供带有希伯来语名称的静态文件?

    我收到客户端的请求 要求从服务器下载一些文件 文件名是希伯来语 bottle get download
  • Python/ Boto 3:如何从AWS S3检索/下载文件?

    在Python Boto 3中 发现从S3单独下载文件到本地可以执行以下操作 bucket self aws connection get bucket aws bucketname for s3 file in bucket list i
  • 使用 CakePHP 将视图嵌入到另一个视图中

    我有一个新闻控制器 每个新闻项目都有一个 查看 操作 在每个新闻项目的 查看 操作中 我想包含另一个视图 即评论控制器的 添加 操作 基本上 我需要在每个新闻项目的页面上添加一个表单来添加评论 我有两种观点 但我无法将它们联系起来 我尝试使
  • 期望在 while 循环内 - 永远循环

    我是新来的脚本 所以请原谅我的绊脚石 以下是我的预期脚本的主要内容 目的是滚动浏览多个输出屏幕 在每个屏幕之后都会提示用户 继续 y n 最后 当没有更多屏幕时 会显示 提示符 这应该导致执行脱离 while 循环 set more scr
  • 强制 Expression<> 计算局部变量

    我的 LinqPad 中有类似的东西 void Main var t1 DateTimeOffset Parse 10 1 2012 int n1 1 Expression
  • 我如何委托给 Scala 中的成员?

    在 Scala 中是否可以这样写 trait Road class BridgeCauseway extends Road implements method in Road class Bridge extends Road val ro
  • iPad 弹出窗口中的 NavigationView 在 SwiftUI 中无法正常工作

    我有以下代码 当点击按钮时显示弹出窗口 struct ContentView View State private var show false var body some View Button Open self show toggle
  • 无法使用 torch.Tensor 创建张量

    我试图创建一个张量 如下所示 import torch t torch tensor 2 3 我收到以下错误 类型错误回溯 最近调用 最后 在 gt 1 a torch tensor 2 3 类型错误 tensor 需要 1 个位置参数 但
  • 使用 objdump 反汇编平面二进制文件

    我可以使用 objdump 反汇编平面二进制文件吗 我熟悉使用以下方法反汇编结构化二进制可执行文件 例如 ELF 文件 objdump d file elf 但是 如果我有一个我知道应该加载的平面二进制文件 例如地址 0xabcd1000
  • MappingException Edm.String 与 SqlServer.varbinary 不兼容

    我很难解决一个愚蠢的地图问题 基本上发生的事情是我在 sql db 表中有一个字段 该字段是出于安全目的 加密和解密 的 varbinary 所有这些东西都很好 但似乎 edmx 将该表中的字段视为一个字符串 我认为它应该将其视为给定的数据
  • 具有作用域变量的全局 Makefile

    我正在尝试根据需要将整个项目转换为单个 Makefile 如果this http aegis sourceforge net auug97 pdf每当我遇到递归 makefile 问题时 我都会看到我的所有搜索结果都乱七八糟 然而 我遇到了