GNU Make中动态目标生成与多维迭代构建策略

GNU Make中动态目标生成与多维迭代构建策略

本文探讨了在gnu make中实现跨平台多架构动态构建的策略。针对`:=`无法在目标定义时动态评估自动变量的问题,我们引入了`foreach`、`eval`和`define`的组合用法,通过定义模板并动态生成目标及其配方,有效解决了需要迭代不同操作系统和架构组合进行构建的场景,从而避免了手动枚举所有构建选项的繁琐。

挑战:GNU Make中动态变量赋值与自动变量的限制

在GNU Make中,当需要针对不同的维度(例如操作系统和处理器架构)生成多个构建产物时,开发者常常希望能够使用简洁的循环或模式规则来自动化这一过程。然而,直接在模式规则中使用:=(简单扩展赋值)配合自动变量(如$@)往往无法达到预期效果。

例如,考虑以下场景:我们希望为Go项目构建针对darwinwindowslinux三种操作系统和amd64、386两种架构的发布版本。一个直观但存在问题的尝试可能如下:

GOOSES = darwin windows linuxGOARCHS = amd64 386.PHONY: release-all $(GOOSES) $(GOARCHS)release: $(GOOSES)$(GOOSES): GOOS := app $@ # 尝试将GOOS设置为当前目标名$(GOOSES): $(GOARCHS)    # 每个OS依赖所有ARCH$(GOARCHS): GOARCH := $@ # 尝试将GOARCH设置为当前目标名$(GOARCHS): build        # 每个ARCH依赖buildbuild:    GOOS=$(GOOS) GOARCH=$(GOARCH) go install ...

当执行make release时,我们可能会观察到GOOS和GOARCH变量在build配方中为空,例如输出GOOS= GOARCH= go install …。这是因为:=是“简单扩展赋值”,它在Make解析文件时只扩展一次右侧的值。在$(GOOSES): GOOS := app $@这样的规则中,当Make解析到GOOS := app $@时,$@(代表当前目标名)尚未在配方执行的上下文中可用,因此它被扩展为空字符串。结果是GOOS被赋值为app(或者如果app不存在,则为空),而非预期的darwin、windows等。这种机制使得我们无法在变量定义阶段动态地捕获当前目标的信息。

解决方案:利用foreach、eval和define实现动态目标生成

为了克服上述限制,GNU Make提供了一套强大的机制,即结合使用foreach、eval和define指令来动态生成目标和配方。这种方法允许我们在Make解析时“编写”新的Make代码,从而实现高度灵活的自动化构建。

核心概念解析

define 和 endef:多行变量定义define用于定义一个多行变量,通常作为模板使用。它允许我们将一段Make代码(包括目标、依赖和配方)封装起来,并在后续通过call函数调用。

define MY_TEMPLATE# 这里可以包含多行Make代码# 例如:target_$(1):    echo "Processing $(1)"endef

在模板中,$(1)、$(2)等表示位置参数,它们在通过call函数调用时会被实际参数替换。

call 函数:调用多行变量模板call函数用于调用一个define定义的多行变量,并将提供的参数替换到模板中的$(1)、$(2)等位置。

$(call MY_TEMPLATE,arg1)

这会生成:

target_arg1:    echo "Processing arg1"

foreach 函数:迭代列表foreach函数用于遍历一个列表,并对列表中的每个元素执行一段Make代码。

$(foreach var,list,text)

它会将list中的每个元素依次赋值给var,然后对text进行扩展。

eval 函数:动态解析Make代码eval函数是实现动态目标生成的关键。它会将一个字符串作为Make代码进行解析和评估,就好像这段字符串是直接写在Makefile中一样。

$(eval $(call MY_TEMPLATE,arg1))

eval会接收$(call MY_TEMPLATE,arg1)的输出字符串,然后将其作为Make代码进行解析,从而动态地创建target_arg1这个目标及其配方。

实施动态构建策略

结合上述概念,我们可以构建一个针对多操作系统和多架构的动态构建方案:

# 定义操作系统和架构列表GOOSES = darwin windows linuxGOARCHS = amd64 386# 默认的'build'目标,它将依赖所有动态生成的特定平台构建目标build:# 定义一个多行变量模板,用于生成每个GOOS/GOARCH组合的构建目标和配方define template# 定义一个名为 build_$(1)_$(2) 的目标,其中 $(1) 是GOOS,$(2) 是GOARCHbuild_$(1)_$(2):    # 在执行配方时,将GOOS和GOARCH作为环境变量传递给go install命令    GOOS=$(1) GOARCH=$(2) go install ... # 替换为你的实际构建命令endef# 使用foreach循环嵌套,遍历所有GOARCH和GOOS组合# 对于每个组合,通过call函数调用模板,并使用eval函数动态生成目标$(foreach GOARCH,$(GOARCHS),  $(foreach GOOS,$(GOOSES),    $(eval $(call template,$(GOOS),$(GOARCH)))))# 可选:定义一个 .PHONY 目标,确保即使文件不存在也能执行.PHONY: $(foreach GOARCH,$(GOARCHS),$(foreach GOOS,$(GOOSES),build_$(GOOS)_$(GOARCH)))# 定义一个all目标,使其依赖于所有生成的构建目标all: $(foreach GOARCH,$(GOARCHS),$(foreach GOOS,$(GOOSES),build_$(GOOS)_$(GOARCH)))# 清理目标(示例)clean:    rm -f myapp_* # 替换为你的实际清理命令

工作原理详解:

GOOSES和GOARCHS:定义了所有需要迭代的操作系统和架构列表。define template … endef:定义了一个名为template的多行变量。这个模板是核心,它包含了为单个GOOS和GOARCH组合构建所需的Make代码。build_$(1)_$(2)::这里定义了一个具体的构建目标,例如build_darwin_amd64。$(1)和$(2)是占位符,分别代表传入的GOOS和GOARCH值。GOOS=$(1) GOARCH=$(2) go install …:这是实际的构建命令。在配方执行时,$(1)和$(2)已经被替换为具体的操作系统和架构值,并作为环境变量传递给go install命令。$(foreach GOARCH,$(GOARCHS),…):这是一个嵌套的foreach循环。外层循环遍历GOARCHS列表中的每个架构(amd64, 386)。内层循环遍历GOOSES列表中的每个操作系统(darwin, windows, linux)。$(eval $(call template,$(GOOS),$(GOARCH))):$(call template,$(GOOS),$(GOARCH)):对于每个GOOS/GOARCH组合,call函数会调用template,并将当前的GOOS和GOARCH值分别作为$(1)和$(2)传入。例如,当GOOS为darwin,GOARCH为amd64时,call会生成以下字符串:

build_darwin_amd64:    GOOS=darwin GOARCH=amd64 go install ...

$(eval …):eval函数接收上述生成的字符串,并将其作为Make代码进行解析。这样,Make就会动态地创建build_darwin_amd64这个目标及其对应的配方。这个过程对所有GOOS/GOARCH组合重复,从而生成build_darwin_amd64、build_darwin_386、build_windows_amd64等所有目标。all: …:定义了一个all目标,它依赖于所有通过foreach和eval动态生成的build_$(GOOS)_$(GOARCH)目标。当你运行make all(或默认的make),Make就会尝试构建所有这些目标。

使用示例

将上述Makefile保存为Makefile,然后执行:

make all

你将看到Make依次为darwin/amd64、darwin/386、windows/amd64、windows/386、linux/amd64、linux/386等所有组合执行go install命令。

注意事项与总结

调试复杂性:使用eval和define的组合虽然强大,但可能使Makefile的调试变得复杂,因为部分代码是动态生成的。可以使用$(info …)或$(warning …)来输出eval前生成的字符串,以帮助理解。.PHONY:为动态生成的目标添加.PHONY声明是良好的实践,以确保即使不存在同名文件,这些目标也能被正确执行。可扩展性:这种模式非常适合处理多维度的构建需求。如果需要增加新的操作系统或架构,只需修改GOOSES或GOARCHS列表即可,无需修改核心逻辑。变量作用域:在define模板内部,$(1)和$(2)等是参数,而GOOS和GOARCH在配方中是环境变量。理解它们的作用域和传递方式至关重要。

通过掌握foreach、eval和define的联合使用,开发者可以在GNU Make中实现高度灵活和自动化的构建流程,尤其适用于需要处理多维度组合的复杂项目。这种模式将大大减少重复代码,提高Makefile的可维护性和可扩展性。

以上就是GNU Make中动态目标生成与多维迭代构建策略的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1416735.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Go语言并发执行外部命令:构建高效协程池的最佳实践
上一篇 2025年12月16日 10:47:12
Go语言中带有互斥锁的结构体如何安全地实现JSON序列化
下一篇 2025年12月16日 10:47:21

相关推荐

  • 电脑主机开机提示无启动设备故障排查及修复教程

    电脑主机开机提示无启动设备故障排查及修复教程电脑主机开机提示无启动设备故障排查及修复教程电脑主机开机提示无启动设备故障排查及修复教程电脑主机开机提示无启动设备故障排查及修复教程

    电脑开机提示“无启动设备”通常是因为系统无法识别启动盘。1. 首先应拔除所有外部设备,避免被误识别为启动项;2. 检查硬盘的数据线和电源线是否松动,必要时更换sata线;3. 进入bios/uefi设置,查看硬盘是否被识别、调整启动顺序、确认sata模式是否正确;4. 若软件层面异常,可用pe工具修…

    2026年9月6日 用户投稿
    000
  • linux开机步骤

      1.加载BIOS   当你打开计算机电源,计算机首先会加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、pnp等等。在此之后,计算机信息就有谱了,知道要去找哪个硬件设备。 2.读取…

    2026年9月6日
    000
  • win10电脑无线网卡连接找不到无线信号的解决方法!

    最近,一位朋友向我反映,他的电脑在使用无线网络时无法搜索到网络信号,但移动设备却可以正常搜到信号,这让他感到十分困扰。针对这种情况,您可以尝试以下几种解决方案: 教程/方法 检查服务状态:右键点击“计算机管理”中的服务选项,确认“WLAN AutoConfig”服务是否被意外关闭,确保该服务处于运行…

    2026年9月6日
    000
  • 59元!华为无线鼠标优享版今日开售:支持星闪、蓝牙双连接 续航12个月

    59元!华为无线鼠标优享版今日开售:支持星闪、蓝牙双连接 续航12个月59元!华为无线鼠标优享版今日开售:支持星闪、蓝牙双连接 续航12个月59元!华为无线鼠标优享版今日开售:支持星闪、蓝牙双连接 续航12个月59元!华为无线鼠标优享版今日开售:支持星闪、蓝牙双连接 续航12个月

    10月14日消息,华为终端宣布,华为无线鼠标优享版今日正式在华为商城开售,定价59元,支持星闪连接技术,更快更准更稳。 ‘’ 从售价来看,改款是目前华为最便宜的无线鼠标,但规格上依然支持华为独家的星闪连接技术,可实现靠近即连、自动发现设备。 据了解,鼠标靠近电脑或平板,即可自动发现并配对,省去多步骤…

    2026年9月6日 用户投稿
    000
  • 有应用假冒WSATools上架微软商城 连描述都没修改

    有应用假冒WSATools上架微软商城 连描述都没修改有应用假冒WSATools上架微软商城 连描述都没修改有应用假冒WSATools上架微软商城 连描述都没修改有应用假冒WSATools上架微软商城 连描述都没修改

    WSATools 是大约两个月前在 Microsoft Store 上线的一款软件,它的主要功能是简化在 Windows 11 系统中安装 Android 应用的过程,通过采用 Android Debug Bridge(adb)命令行工具的方式来优化这一流程。 不过,由于一些原因,该软件目前已经被下…

    2026年9月6日 用户投稿
    000
  • 什么是消息队列?在Linux中使用消息队列

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处。有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道 一、什么是消息队列消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。  每个数据块都被认为含有一个类型,接收进程可以独立地…

    2026年9月6日
    000
  • 高德地图APP怎么切换城市_高德地图APP城市切换操作步骤

    高德地图切换城市有三种方法:一、通过“我的”进入设置,选择通用设置中的“城市切换”功能,搜索或选择目标城市;二、在首页顶部搜索框输入城市名,点击搜索结果直接跳转;三、长按地图空白处弹出地点卡片,若属其他城市可点击详情中的切换选项完成定位。 如果您在使用高德地图时需要查询或导航至非当前所在城市,系统可…

    2026年9月6日
    000
  • win10系统怎样禁用驱动强制签名

    安装完windows 10系统之后,有时会用到一些未签名的驱动程序,但在运行时却弹出了需要数字签名的提示,这使得相关程序无法正常使用,让人感到十分困扰。那么,该如何关闭驱动签名的强制检查呢?接下来就为大家介绍一种在windows 10中禁用驱动签名强制检查的方法。以下是具体的操作步骤: 首先,按下键…

    2026年9月6日
    000
  • 剪映pc版怎么导入视频_剪映PC版导入视频素材方法

    剪映PC版无法导入视频时,可通过首页“开始创作”按钮、拖拽文件至时间轴、使用媒体库“导入”功能等方式解决;若因格式不兼容(如非MP4、MOV等),需用工具如HandBrake转换为H.264编码的MP4后再导入。 如果您在使用剪映PC版时无法顺利导入视频素材,可能是由于文件格式不支持或操作步骤有误。…

    2026年9月6日
    100
  • 史上最黑的黑科技–把chromium 的blink、v8、skia用vc6的crt编译并运行!

    史上最黑的黑科技–把chromium 的blink、v8、skia用vc6的crt编译并运行!史上最黑的黑科技–把chromium 的blink、v8、skia用vc6的crt编译并运行!史上最黑的黑科技–把chromium 的blink、v8、skia用vc6的crt编译并运行!史上最黑的黑科技–把chromium 的blink、v8、skia用vc6的crt编译并运行!

    这个想法由来已久,其原因有三个显著的优势: 1、可以忽略VS2015的MD版本所需的那些api-xxxx-xxx的dll文件。这些文件数量庞大,令人头疼。 2、可以不必处理manifest的问题。这东西非常烦人,设置稍有不慎就会导致各种无法加载的问题。特别是本机没问题,但客户机上可能就会出现问题。 …

    2026年9月6日 用户投稿
    000
  • 小强阅读app怎么关闭阅读通知_小强阅读app推送通知如何关闭详细方法

    可通过小强阅读App内设置和手机系统设置关闭通知。2. 在App中进入“我的”→“设置”→“消息通知”,关闭所有推送类型。3. 在手机设置中找到“通知管理”,禁止小强阅读的通知权限。4. 建议同时关闭自启动、角标显示和锁屏通知,确保无干扰。 小强阅读App的推送通知可以通过应用内设置和手机系统设置两…

    2026年9月6日
    100
  • windows8怎么设置屏幕保护程序_windows8启用屏保的方法

    首先通过个性化设置选择屏保类型并设定等待时间,其次勾选“恢复时显示登录屏幕”以增强安全性,最后点击应用保存配置,完成Windows 8系统屏保启用。 如果您希望在Windows 8系统中启用屏幕保护程序以防止他人窥视或增加设备安全性,可以通过系统内置的个性化设置来完成配置。以下是具体的操作方法。 本…

    2026年9月6日
    000
  • Laravel:高效加载关联关系并获取ID数组

    本文旨在介绍在 Laravel 中高效加载关联关系,并将关联模型的 ID 以数组形式获取的几种实用方法。针对 `belongsToMany` 关系,我们将探讨如何避免多次 `transform` 操作,通过 `pluck` 方法、循环处理以及使用 Eloquent Resources 和 Colle…

    2026年9月6日
    000
  • 今天重构了我的生产工具

    为了适应新的工作需求,一番最近对电脑系统进行了重新配置,从之前的ubuntu 18.04和virtualbox中的windows 7组合,改成了windows 10搭配内置的ubuntu 18.04。 主要原因是之前的系统使用了将近两年时间。在这段时间里,一番从一个纯粹的开发者转变为兼具管理职能的开…

    2026年9月6日
    100
  • 一条项目中常用的linux命令引发的经典算法题

      小时候家里定了《读者》的月刊,里面记录一个故事:说有有个偏僻的乡村一日突然来了一个美女,她携着万贯家财子女在当地安家落户,成了当地的乡绅。她让她的子女世世代代的保守这个秘密,直到这个秘密不会再对家族带来灾难。她就是陈圆圆。当年吴三桂领清兵入关,冲冠一怒为红颜,改写了中国的历史,自己却能全身而退的…

    2026年9月6日
    100
  • Word表格第一行怎么锁定不动_Word表格标题行跨页重复显示设置

    首先启用表格“重复标题行”功能,选中第一行后通过“表格属性”勾选对应选项;其次检查前后段落格式,避免分页设置干扰;最后调整行高并禁止跨页断行以优化显示效果。 如果您在编辑Word文档时,希望表格的第一行(如标题行)在跨页时始终显示在每一页的顶部,以便于阅读和对照,则需要启用表格的“重复标题行”功能。…

    2026年9月6日
    200
  • 分享Linux中文件创建与删除

    文件命名规则: 1.严格区分大小写; 2.长度不能超过255个字符; 3.不能使用/当文件名 mkdir:创建空目录   -p:parent,父目录,逐级创建   -v:verbose,打印详细信息 命令行展开:mkdir -pv  /mnt/test/{x/m,y} 波浪线展开:~USERNAME…

    用户投稿 2026年9月6日
    100
  • Win7系统如何开启混响模式?

    回想起过去,当windows 10还没有面世的时候,windows 7可是用户们的首选操作系统呢。不过,在使用过程中,大家难免会遇到各种各样的问题,例如今天要聊到的windows 7如何开启混响的问题。那么在windows 7中该如何打开混响模式呢?我们接着往下看。 什么是声音立体混响呢?简单来说,…

    2026年9月6日
    200
  • 谷歌回应Win10 Edge访问Chrome商店安全警告

    谷歌回应Win10 Edge访问Chrome商店安全警告谷歌回应Win10 Edge访问Chrome商店安全警告谷歌回应Win10 Edge访问Chrome商店安全警告谷歌回应Win10 Edge访问Chrome商店安全警告

    自从微软的新版edge浏览器从edgehtml架构转向chromium之后,这款浏览器已经实现了跨平台支持,同时拥有了chrome浏览器的所有优点。新版edge基于相同的引擎运行,并且能够兼容google网上应用商店中的扩展程序,这意味着用户可以直接在edge浏览器里搜索、下载以及安装chrome扩…

    2026年9月6日 用户投稿
    200
  • Chrome访问京东移动端滑块验证失败是什么原因?

    Chrome浏览器访问京东移动端滑块验证失败的解决方法 问题描述: 使用Chrome浏览器访问京东移动端时,无法通过滑块验证,多次尝试均告失败。 问题原因: 京东移动端滑块验证机制依赖于设备指纹识别。使用Chrome等桌面浏览器访问移动端页面时,浏览器设备指纹(例如屏幕分辨率、操作系统版本等信息)与…

    2026年9月6日
    300

发表回复

登录后才能评论
关注微信