尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Universal Ctags 的 Meson 构建脚本标签解析:用法、Kind 体系与 optlib 实现解析

Universal Ctags 的 Meson 构建脚本标签解析:用法、Kind 体系与 optlib 实现解析 开发工具CLI【免费下载链接】ctagsA maintained ctags implementation项目地址https://gitcode.com/gh_mirrors/ct/ctags点击查看免费下载本文围绕 Universal Ctags 官方手册 ctags-lang-meson(7) 展开系统讲解如何对 Meson 构建脚本meson.build、meson_options.txt进行源码标记tagging包括语言启用方式、kind 与 role 体系、cfgdata/cfgvar配置变量的提取机制并结合仓库中 optlib/meson.ctags 与 optlib/mesonOptions.ctags 的实际实现与 Units 测试用例进行验证。读完本文你将掌握使用 ctags 为 Meson 项目生成可检索标签的完整命令、各标签类型的语义以及其底层多表正则multitable regex解析器的设计思路。概述为 Meson 构建脚本生成标签Universal Ctags 提供了一种可扩展的标签生成机制除了内置的 C、C、Python 等语言解析器外还支持通过 optlib 脚本自定义解析器。Mesonmesonbuild.com 的构建系统的构建脚本meson.build与选项文件meson_options.txt便是通过此类 optlib 解析器得到支持的。根据 ctags-lang-meson(7)该手册收集了关于使用 Universal Ctags 标记taggingMeson 构建脚本的零散笔记Random notes about tagging Meson build scripts with Universal Ctags版本为 6.2.0属于 Universal Ctags 手册组第 7 节man page section 7即杂项文档。与常规 man page 一样它开篇给出三种典型调用方式ctags ... --languagesMeson ... # 在现有语言集上追加启用 Meson ctags ... --language-forceMeson ... # 强制按 Meson 解析忽略扩展名/文件内容猜测 ctags ... --map-Meson(meson.build) # 将 meson.build 显式映射到 Meson 语言这三条命令分别对应三种场景--languagesMeson当文件扩展名或文件名已经能被自动识别时meson.build默认就被映射到 Meson只需确保 Meson 语言处于启用状态--language-forceMeson对于扩展名不标准、或需要绕过语言猜测逻辑的输入文件强制指定解析语言--map-Meson(meson.build)显式建立文件名到语言的映射表示追加而非覆盖。在实际使用中通常直接执行即可识别标准的meson.build文件因为 optlib/meson.ctags 中已经声明了--map-Meson(meson.build)这一默认映射。快速上手最小可运行示例克隆并构建 Universal Ctags 后参见 docs/building.rst对任意包含meson.build的项目执行$ ctags -o - --languagesMeson meson.build仓库的单元测试 Units/parser-meson.r/simple-meson.d/expected.tags 展示了真实输出形态。例如对于类似下面的构建脚本project(c foolib, cpp) glib_dep dependency(glib-2.0) inc include_directories(include) subdir(include) pkg_mod import(pkgconfig) foolib shared_library(foo, source1.cpp) test(foolib test, testexe)生成的标签tags如下c foolib input.meson /^project(c foolib, cpp,$/; project glib_dep input.meson /^glib_dep dependency(glib-2.0)$/; variable inc input.meson /^inc include_directories(include)$/; variable include input.meson /^subdir(include)$/; subdir pkg_mod input.meson /^pkg_mod import(pkgconfig)$/; variable foo input-1.meson /^foolib shared_library(foo,$/; build foo0 input-1.meson /^foolib0 library(foo0,$/; build testexe input-2.meson /^testexe executable(testexe, footest.cpp,$/; build foolib test input-2.meson /^test(foolib test, testexe)$/; test targetname input-3.meson /^mytarget custom_target(targetname,$/; custom inspector input-4.meson /^run_target(inspector,$/; run bench-connect input-5.meson /^bench_connect executable(bench-connect, ...)$/; build Connection input-5.meson /^ benchmark(Connection, bench_connect, ...)$/; benchmark docs input-6.meson /^alias_target(docs,$/; run标签文件采用经典的tags五字段格式标签名、源文件、Exuberant 模式、行号、kind 字母kind 字母来自下文的 kind 定义。若需要 JSON 输出可追加--output-formatjson格式规范见 ctags-json-output(5)。语言启用与文件映射Meson 语言与默认映射optlib/meson.ctags 的头部声明了--langdefMeson{version1.1} --map-Meson(meson.build)--langdefMeson定义了一个名为Meson的 optlib 语言{version1.1}表示该解析器定义的版本号用于 optlib 版本追踪--map-Meson(meson.build)将文件名meson.build映射到 Meson 语言表示在原有映射基础上追加。因此当 ctags 遇到名为meson.build的文件时会自动选用 Meson 解析器无需额外参数。手册中的--languagesMeson主要用于语言已禁用或需要显式确认时的场景。值得注意的是仓库还提供了另一个独立的语言MesonOptions用于解析meson_options.txt选项文件见下文选项文件的解析一节。语言强制与映射调整--language-forceMeson无视输入文件的扩展名、内容与已有映射强制按 Meson 解析。适合处理被重命名、无扩展名或内容被误判的文件。--map-Meson(meson.build)如果你想将其他文件名如meson.build.example也映射到 Meson可写成--map-Meson.example或--map-Meson(文件名)保持既有映射不被覆盖。通用选项的完整说明见 ctags(1) 与 ctags-client-tools(7)。标签类型体系Kinds 一览Meson 解析器通过--kinddef定义了 10 种标签类型kind见 optlib/meson.ctags字母名称单数名称复数含义Pprojectprojectsproject()声明的项目名Vvariablevariables顶层变量赋值name valueSsubdirsubdirssubdir(...)引入的子目录Bbuildbuild targets库/可执行文件等构建目标ccustomcustom targetscustom_target()自定义目标ttestteststest()声明的测试bbenchmarkbenchmark targetsbenchmark()基准测试rrunrun targetsrun_target()/alias_target()运行目标mmodulemodulesimport(...)导入的模块Dcfgdataconfiguration data objectsconfiguration_data()对象版本 1 起Ccfgvarconfiguration variablesconf.set(...)配置变量版本 1 起其中cfgdataD与cfgvarC是手册明确标注的新增内容手册在 Change since 0.0 一节写道New kindscfgdataandcfgvar这与 docs/news/6-2-0.rst 中 Meson: New kindscfgdataandcfgvar 的版本记录一致。这两个 kind 用于提取configuration_data()对象及其内部通过set/set_quoted/set10设置的配置键是 Meson 构建参数化的重要标签来源。角色Role模块的 imported除 kind 外解析器还定义了一个角色imported隶属于modulemkind见 optlib/meson.ctags--_roledef-Meson.{module}imported,imported其作用是把import(pkgconfig)这类调用打上imported角色标记。在标签输出中角色会以role:字段呈现。角色机制的通用说明可参考 ctags(1) 中--list-roles相关内容。使用--list-kinds-full查看可用 Kind要查看 Meson 解析器当前支持的全部 kind可用$ ctags --list-kinds-fullMeson输出将包含上述每个 kind 的字母、名称、复数形式及描述description。这一点也可以通过--machinable等通用选项机器化读取。--list-kinds-full是排查为什么某个标签没生成的首选工具——例如若你的 ctags 版本低于 6.2.0cfgdata/cfgvar不会出现在列表中。深入源码解析器如何工作Meson 解析器是 optlib 的多表正则multitable regex解析器即把词法分析拆分成多个可相互跳转的状态表table。optlib/meson.ctags 声明了以下状态表--_tabledef-Mesonmain --_tabledef-Mesonmline_string --_tabledef-Mesonstring --_tabledef-Mesoncomment --_tabledef-MesonskipPair --_tabledef-Mesoncommon --_tabledef-MesonskipToArgEnd --_tabledef-MesonconfigBody --_tabledef-MesonconfigElt --_tabledef-MesonconfigValue各表职责如下main入口表识别顶层变量赋值、project()、subdir()、test()common共享的词法规则空白、注释、字符串、括号配对被多个表--_mtable-extend复用comment/string/mline_string分别处理#注释、单引号字符串与三引号多行字符串skipPair跳过()[]{}配对内容如函数参数内部避免误匹配skipToArgEnd进入某个函数调用后跳过其整个参数列表到右括号configBody/configElt/configValue处理configuration_data()对象的内部结构用于提取cfgvar。顶层标签的识别规则main表中定义了核心匹配optlib/meson.ctags--_mtable-regex-Mesonmain/([a-zA-Z_][a-zA-Z_0-9]*)[ \t\n]*([^]|$)/\1/V/{_advanceTo2start} --_mtable-regex-Mesonmain/project[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/P/{tenterskipToArgEnd} --_mtable-regex-Mesonmain/subdir[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/S/{tenterskipToArgEnd} --_mtable-regex-Mesonmain/test[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/t/{tenterskipToArgEnd}要点解读变量赋值name value通过([a-zA-Z_][a-zA-Z_0-9]*)[ \t\n]*([^]|$)匹配用[^]排除比较运算生成variableV标签{_advanceTo2start}使匹配从赋值号的第二个字符继续扫描project(...)、subdir(...)、test(...)分别捕获第一个字符串参数生成对应 kind随后{tenterskipToArgEnd}进入参数跳过表避免继续扫描括号内内容造成重复匹配。构建目标与模块构建目标在common表中识别optlib/meson.ctags--_mtable-regex-Mesoncommon/(jar|executable|shared_module|(both_|shared_|static_)?library)[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\3/B/{tenterskipToArgEnd} --_mtable-regex-Mesoncommon/custom_target[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/c/{tenterskipToArgEnd} --_mtable-regex-Mesoncommon/(alias|run)_target[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\2/r/{tenterskipToArgEnd} --_mtable-regex-Mesoncommon/benchmark[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/b/{tenterskipToArgEnd} --_mtable-regex-Mesoncommon/import[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*/\1/m/{tenterskipToArgEnd}{_roleimported}executable(...)、library(...)、shared_library(...)、static_library(...)、both_library(...)、shared_module(...)、jar(...)生成buildB标签custom_target(...)生成customcalias_target(...)、run_target(...)生成runrbenchmark(...)生成benchmarkbimport(...)生成modulem并附带imported角色。这些规则与单元测试 Units/parser-meson.r/simple-meson.d/expected.tags 一一对应foolib shared_library(foo,...)同时产生variable等号左侧foolib与build字符串参数foo两个标签这是 Meson 构建脚本中最常见的双重标签现象。配置数据的提取cfgdata 与 cfgvarcfgdataD与cfgvarC是 6.2.0 版本新增的能力用于从configuration_data()与conf.set(...)中提取配置项。其实现横跨三个表并借助 optscriptPostScript 风格的嵌入式脚本维护状态。configuration_data()的进入规则optlib/meson.ctags--_mtable-regex-Mesoncommon/(configuration_data)[ \t\n]*\([ \t\n]*//{tenterconfigBody}{{ lastvar false ne { lastvar :name /cfgdata lastvar _tagloc _tag _commit ... } { ... } ifelse }}其逻辑为当main表刚识别过name 赋值main表会把变量名存入lastvar后紧跟configuration_data()时为等号左侧变量生成cfgdata标签而不再重复生成variable标签通过_markplaceholder标记原始变量位置。测试 Units/parser-meson.r/config.d/expected.tags 验证了这一点conf configuration_data()只产生cfgdata标签conf没有额外的variable标签。配置变量的提取规则位于common表optlib/meson.ctags--_mtable-regex-Mesoncommon/([a-zA-Z_][a-zA-Z0-9_]*)\.(set(_quoted|10)?)[ \t\n]*\(([^]*[^\\])[ \t\n]*//{{ cfgdict \1 known { \4 /cfgvar 4 _tag _commit cfgdict \1 get scope: } if }}该规则匹配conf.set(KEY, ...)、conf.set_quoted(KEY, ...)、conf.set10(KEY, ...)三种形式并仅当左侧对象名conf是已知的cfgdata记录在cfgdict字典中时才生成cfgvar标签。这正是 Units/parser-meson.r/config.d/input.meson取自 systemd 的meson.build中conf.set_quoted(PROJECT_URL, ...)能产生PROJECT_URL标签、且带cfgdata:conf作用域字段的原因PROJECT_URL input.meson /^conf.set_quoted(PROJECT_URL, https:\/\/systemd.io\/)$/; cfgvar cfgdata:confcfgvar标签的scope:字段指向所属的cfgdata对象cfgdata:conf实现了配置项的归属关联。configBody、configElt、configValue三个表则处理configuration_data({...})内联字典写法Units/parser-meson.r/config-inline.d/input.meson 取自 insights-client 项目其中configElt通过KEY:捕获键名生成cfgvar。选项文件的解析meson_options.txt除meson.build外Universal Ctags 还支持 Meson 的选项文件meson_options.txt由独立的 optlib/mesonOptions.ctags 解析器实现。其声明与 kind 体系如下--langdefMesonOptions --map-MesonOptions(meson_options.txt) --kinddef-MesonOptionss,string,strings --kinddef-MesonOptionsb,boolean,booleans --kinddef-MesonOptionsc,combo,combos --kinddef-MesonOptionsi,integer,integers --kinddef-MesonOptionsa,array,arrays --kinddef-MesonOptionsf,feature,features六种 kind 对应 Meson 选项的六种类型string、boolean、combo、integer、array、feature。核心匹配规则只有一条多行正则optlib/mesonOptions.ctags--mline-regex-MesonOptions/^option[ \t\n]*\([ \t\n]*([^]*[^\\])[ \t\n]*,[ \t\n]*type[ \t\n]*:[ \t\n]*([a-z])//{{ \1 \2 cvn 1 { _tag } stopped { pop pop pop } { _commit pop } ifelse }}它匹配形如option(name, type : string, ...)的声明\1是选项名\2是类型字符串通过 optscript 的cvn将类型字符串转换为 kind 字母若_tag因 kind 无效而被stopped捕获则清理栈兼容未知类型。该解析器是仓库中 optscript 脚本能力的一个测试床testbed见 optlib/mesonOptions.ctags 的注释。对应的测试目录为 Units/simple-meson-options.d其输入取自 QEMU 源码树的meson_options.txt。使用限制与注意事项版本门槛cfgdataD与cfgvarC两个 kind 带{version1}标记从 Universal Ctags 6.2.0 起可用旧版本无法生成这两类标签。可通过 docs/news/6-2-0.rst 确认该能力随 6.2.0 引入。只处理字符串字面量无论是project()、subdir()还是set()解析器只捕获单引号字符串形式的参数动态表达式如变量拼接、files()返回不会被识别为标签名。排除变量赋值正则用([^]|$)排除比较因此if x y这类比较不会被误判为变量定义。转义处理字符串正则中[^\\]表示字符串参数不允许以反斜杠结尾避免误截含有转义字符的字符串仓库测试 Units/parser-meson.r/escape-in-string.d 专门覆盖了反斜杠与的处理对应 docs/news/6-2-0.rst 中的相关修复记录。性能设计common表中有一条跳过规则optlib/meson.ctags--_mtable-regex-Mesoncommon/[df-hkm-qt-z][a-zA-Z0-9_]*//它快速跳过dependency、find_program、get_option、include_directories等不会产生标签的函数调用这些调用一般返回变量变量名已在main表捕获是解析器的优化手段避免为大量无关函数调用付出正则匹配开销。结合 CI 与测试验证该解析器的行为由 Units/parser-meson.r 下的若干测试目录保证每个目录包含input*.meson输入、args.ctags参数与expected.tags期望输出simple-meson.d覆盖project/variable/subdir/build/test/custom/run/benchmark等基本 kindconfig.d取自 systemd 的meson.build验证cfgdata/cfgvar与作用域关联config-inline.d取自 insights-client验证configuration_data({...})内联字典写法modules.d验证import(...)模块标签及imported角色escape-in-string.d验证字符串转义与运算符边界。可手动复现测试$ cd Units $ ./run.sh parser-meson.r测试框架说明见 docs/testing-parser.rst。此外docs/contributions.rst 以 Meson 解析器作为 optlib 解析器的示例表明它在项目内部也被视为 optlib 编写模式的参考实现。延伸阅读通用 ctags 用法与输出格式ctags(1)JSON 输出规范ctags-json-output(5)客户端工具readtags 等ctags-client-tools(7)optlib 编写指南docs/optlib.rst 与 ctags-optlib(7)optscript嵌入式脚本说明docs/optscript.rst解析器测试方法docs/testing-parser.rst版本更新记录docs/news/6-2-0.rst含 Mesoncfgdata/cfgvar引入记录与 docs/news/6-0-0.rstMeson/MesonOptions 作为 optlib 首次引入赞分享开发工具CLI【免费下载链接】ctagsA maintained ctags implementation项目地址https://gitcode.com/gh_mirrors/ct/ctags点击查看免费下载相关推荐Universal Ctags 的 Inko 解析器详解基于 Optlib 正则多表的状态机式标签生成Universal Ctags 的 Inko 解析器详解基于 Optlib 正则多表的状态机式标签生成 本篇技术指南围绕 Universal Ctags ht开发工具CLIUniversal Ctags 完整指南维护中的 ctags 实现、optlib 语言扩展与多平台构建实战Universal Ctags 完整指南维护中的 ctags 实现、optlib 语言扩展与多平台构建实战 Universal Ctags简称 u ctag开发工具CLIUniversal Ctags 对 EmacsLisp 源码的标签生成语言选择、Kind 体系与 definer 字段实战Universal Ctags 对 EmacsLisp 源码的标签生成语言选择、Kind 体系与 definer 字段实战 Universal Ctags 为开发工具CLI上一篇【免费下载】 PyCINRAD中国新一代天气雷达数据处理与可视化利器下一篇retrying高级用法组合重试策略与回调函数的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表