Skip to content

Latest commit

 

History

History
289 lines (251 loc) · 24.6 KB

File metadata and controls

289 lines (251 loc) · 24.6 KB

SPEC-007:构建插件:配置、施工与校验的分工,运行时与规划期的义务

项 值
规范编号 SPEC-007
标题 构建插件:配置、施工与校验的分工,运行时与规划期的义务
状态 草案 v0.7
版本 0.7
最后修改 2026-10-01
对应实现 逐条标注。未注明版本的「已实现」条款对应 mcpp >= 2026.9.26.1;注明 mcpp#702 的条款对应 mcpp >= 2026.9.26.2;注明 mcpp#707、#708、#709、#711 的条款对应 mcpp >= 2026.9.27.1;注明 mcpp#723 的条款对应 mcpp >= 2026.9.28.1;注明 mcpp 2026.9.28.2 的条款对应该版本;§9 与注明 mcpp#734 的条款对应 mcpp >= 2026.9.28.3
相关设计文档 .agents/docs/2026-09-26-compile-database-and-issue-699-design.md(§5)、.agents/docs/2026-09-28-ecosystem-design-and-optimisation-plan.md(WS1、WS3)、.agents/docs/2026-09-28-build-cost-foreign-toolsets-and-library-surface-design.md(§3、§4)
相关 issue mcpp#699、mcpp#701、mcpp#702、mcpp#703、mcpp#707、mcpp#708、mcpp#709、mcpp#711、mcpp#734、mcpp#755
使用文档 docs/30 - build.mcpp、docs/31 - 编写规则包

本规范规定构建插件对引擎和对消费方承担的义务,以及引擎为此提供的机制。docs/31 说明怎样编写 插件,本规范规定插件必须满足什么。

规范用语与实现状态标记见 规范索引。只约束插件作者、引擎不做检查的条款标注 「作者义务」。

0. 适用范围

构建插件是为其他包的构建贡献工作的包,以及它导入消费方构建程序的模块(rule_module、 host-module)。

类别 例 贡献
规则包 rules-qt、rules-spirv、rules-cuda 代码生成,设备语言的编译
依赖适配包 deps-vcpkg、deps-cmake 把外部包管理器或外部构建系统的产物接入构建
分发成员 dist-wix、dist-apk 由链接产物生成可安装的分发物

项目自己的 build.mcpp 中的同类代码同样适用本规范。

分工。 mcpp 只提供通用机制:指令、action 的角色、stamp、运行时库的搜索与放置。某一个 工具(vcpkg、CMake、Qt)的知识只属于它的插件。插件遇到的缺口若是通用的,由 mcpp 以通用机制 补上(第 3.3 节的 prepare、第 4.1 节的 runtime_search_dir、第 4.3 节的 DLL 放置),而不 由插件绕过。

1. 三类工作

插件所做的每一件事属于且只属于下表的一类。

类 定义 发生在 机制
配置 决定构建的形状:编译哪些源、用哪些选项、链接什么、运行时在哪里找库 构建程序运行时,即规划期 指令(第 2 节)
施工 产生构建读取的文件:生成源码、编译设备代码、安装依赖前缀、打包 构建期 mcpp::action(第 3 节)
校验 判断环境或产物是否满足要求,不产生构建读取的文件 构建期 role = "check" 的 action
  • R1.1 施工必须声明为 action,禁止在构建程序运行期间进行。构建程序可以运行工具 来查询配置所需的答案(版本、选项、路径),禁止借此产生构建读取的文件。(作者义务; action 自 2026.8.5.1 已实现)
  • R1.2 校验必须是 check action。构建程序发现环境不完整(缺少一个 SDK 模块、缺少 一个库)时,必须用 mcpp::warning 报告,并输出它能确定的全部配置;禁止因环境不完整 以非零状态退出。编译或链接会在缺失处失败,位于该警告之后。(作者义务)
  • R1.3 配置必须只取决于构建程序声明的输入:包的清单、声明的载荷,以及 rerun_if_changed、rerun_if_changed_glob、rerun_if_env_changed 列出的文件、glob 与 环境变量。配置禁止依赖施工的结果,例如枚举一个安装前缀中由 action 产生的文件:规划 (mcpp emit build-database)与第一次构建都发生在施工之前,依赖施工结果的配置在第一次与 第二次构建之间不同。(作者义务;构建程序的重新运行依据落在一个 prepare action 声明的目录内 时,引擎给出一条警告并点名两者,已实现,mcpp#702)
  • R1.4 构建程序在规划与构建中必须行为相同。引擎不提供「正在规划」的信号,因为规划 所描述的计划与 mcpp build --configure-only 计算的计划相同(SPEC-005 R1.2)。(已实现)

2. 配置:指令

  • R2.1 下表中的配置必须用对应的指令表达;禁止用 link_flag、cxxflag 拼写表中 已有指令所表达的内容(例如以 -Wl,-rpath, 代替运行时搜索目录,以 -I 代替头文件目录)。 指令由引擎按平台渲染、去重,并进入缓存与构建数据库。(作者义务)

    配置 C++ 接口 线格式 自
    头文件目录 include_dir、include_dir_after include-dir、include-dir-after 协议 1
    编译选项 cxxflag、cflag cxxflag、cflag 协议 1
    宏 define cfg 协议 1
    链接库与库目录 link_lib、link_search link-lib、link-search 协议 1
    其他链接选项(含库的完整路径) link_flag link-flag 协议 8
    运行时搜索目录 runtime_search_dir runtime-search-dir 协议 12(mcpp#702)
    放到程序旁的文件 deploy deploy 协议 11
    生成的源 generated、source 与 role = "source" 的 action generated、source、action 协议 1
    重新运行构建程序的依据 rerun_if_changed、rerun_if_changed_glob、rerun_if_env_changed 同名 协议 1、2
    报告与探测 warning;fact、floor 同名 协议 5、7
  • R2.2 相对路径按声明它的包的根目录解析。插件禁止把宿主系统目录(/usr/include、 /usr/lib、/lib、C:\Windows\System32 及同类)声明为头文件、链接或运行时搜索目录;SDK 与工具的路径取自声明的载荷(mcpp::xpkg_dir)或依赖边(mcpp::dep_dir、mcpp::dep_bin)。 (作者义务;对图目标的链接,引擎检查 -L,mcpp#696 已实现)

  • R2.3 插件必须使用现行字段的指令,禁止依赖只为兼容而保留的字段 ([runtime] library_dirs,docs/04 §2.11)。(作者义务)

  • R2.4 链接选项的一个元素按 SPEC-004 §8 读成词,每个词原样到达链接器。插件禁止依赖 引擎内部的转义拼写(例如 '$$ORIGIN')。(已实现,mcpp#703;此前 ldflags 与 link_flag 中的 $ 会被宿主 shell 展开)

3. 施工:action

  • R3.1 action 的命令是 argv,禁止假定 shell。命令调用的工具必须列为输入;命令 自己发现的输入用 depfile 报告。(argv 与 depfile 已实现;工具作为输入是作者义务)

  • R3.2 action 必须在提交时命名它的输出文件,因为引擎在规划期确定源集合、指纹与模块 图。输出文件名在施工前无法得知的工作(安装一个前缀、解开一个 SDK)使用 prepare 角色。 (已实现;prepare 随 mcpp#702)

  • R3.3 角色:

    role 输出 顺序
    source 可编译的输出加入声明包的编译集 声明包的每条编译边等待它
    object 加入链接集 链接边消费它
    artifact 新文件,输入是链接产物 链接之后
    check 引擎写的 stamp 与编译并行;blocking = true 时声明包的编译边等待它
    prepare 引擎写的 stamp;命令填充它用 output_dir 声明的目录,构建按目录引用其内容 声明包的每条编译边与计划中的每条链接边(静态库归档除外)等待它

    prepare(已实现,mcpp#702)是施工,不是校验,任何只针对校验的策略都不作用于它;构建 输出以 PREPARE 标注它。它的产物由配置以目录为单位引用(include_dir、link_search、 runtime_search_dir),或以 link_flag 中的完整路径引用;这些名字在配置时确定,内容在施工 时到达。一个 prepare action 必须用 output_dir 声明它填充的目录(缺少时引擎拒绝该 action);命令成功而该目录不存在,或除该 action 的 stamp 之外不含任何文件时,引擎不写 stamp,并以指出该目录的消息使这条边失败。链接边等待所有 prepare,因为每个包的链接全局 指令并入整个计划共用的一份链接意图。

  • R3.4 check 只用于校验,禁止用来表示施工。(作者义务)

  • R3.5 check 与 prepare 的命令成功后,引擎创建或更新它们的 stamp,使 stamp 新于该 action 的每个输入;命令失败时不写 stamp。命令无需自己写 stamp。(创建自 2026.8.29.1 已实现;更新 已实现,mcpp#702;此前一个已存在的 stamp 不被更新,输入改变一次后该 action 在此后每次构建中都会重新运行)

  • R3.6 角色应当以常量书写(mcpp::roles::source、check、object、artifact、 prepare),使不认识该角色的旧引擎在编译构建程序时拒绝它;引擎拒绝未知的角色字符串,并列出 五个角色。(已实现,mcpp#702;此前引擎把未知的角色字符串当作 source)

  • R3.7 构建期不应访问网络:下载属于安装期(载荷的安装、依赖的解析)。一个必须在构建期 下载的 action(例如由包管理器取得源码)必须在其说明中写明,并在离线构建中 (--offline 或 MCPP_OFFLINE=1;前者在进程环境中设置后者,action 继承之)不访问网络: 从缓存完成,或以指出缺失内容的消息失败。(作者义务;环境传递 已实现)

  • R3.8 action 需要的环境变量与工作目录必须用 env(name, value) 与 cwd(dir) 声明 (协议 13),禁止写成命令中的 shell 语法(NAME=value cmd、cd dir &&),因为 R3.1 不假定 shell。引擎的 action 包装器在运行命令前设置它们:cwd 按声明包的根目录解析;声明的 输入、输出与 stamp 在规划时解析为绝对路径,不受 cwd 影响;命令参数原样传给命令,其中的 相对路径相对于 cwd。变量的值属于这条边的命令行,值改变时该 action 重新运行。两者都未 声明的 action,其命令行与协议 12 逐字节相同。(已实现,mcpp#708)

4. 运行时:程序依赖的共享库的查找

  • R4.1 一个目录中的共享库由施工产生(prepare)或文件名不定时,插件必须用 runtime_search_dir 声明该目录。引擎把它用于 ELF 与 Mach-O 的运行路径(RUNPATH/rpath, 从不作为 -L)、mcpp run 的加载路径、mcpp pack 的闭包搜索与运行时校验,并把依赖包的 声明传到消费方的可执行文件。(已实现,mcpp#702)
  • R4.2 一个在配置时已知的文件需要位于程序旁的某个相对位置时(Qt 的平台插件、Vulkan 的 ICD 清单),插件用 deploy。(已实现,协议 11)两个或更多来源为同一目的地各自声明 deploy 时,规划期不再把它当作错误拒绝:被声明的来源此时可能尚未生成,其内容无法比较。 引擎把它们合并为一条施工边,将每个来源都列为该边的输入;施工时(mcpp stage)逐字节核对 这些来源,字节相同则放置,不同则该边失败,消息点名每一个来源与该目的地。(已实现, mcpp#723)
  • R4.3 Windows 的可执行文件没有运行路径。mcpp run 通过 PATH 使用运行时搜索目录, mcpp pack 把闭包需要的 DLL 放到程序旁(已实现)。链接之后,引擎把程序直接或间接导入的、 位于其运行时搜索目录中的非系统 DLL 放到程序旁,使从构建目录直接启动的程序同样能找到它们; 闭包的求解与 mcpp pack 相同,DLL 在其目录中被替换后下一次构建再次放置。(已实现, mcpp#702)一个目的地只有一个写者:本条的放置以 R4.2 与工具链耦合运行时 DLL(toolchain- coupled)合并而成的部署清单为唯一权威,禁止写入该清单已经放置的名字。遇到清单已放置 的名字时,本条只比较该名字现有文件与运行时搜索目录中同名文件的字节,相同则不作声张,不同 则以警告点名这一差异,禁止覆盖清单已放置的文件。规划时在运行时搜索目录中找到的 DLL 同样是推导出的来源,让位于清单中声明的同名目的地,差异由本条的放置报告。(已实现, mcpp#723)这一清单是运行时放置解析器的答案(SPEC-006 §3.7.1):声明优先于工具链,工具链 优先于推导;MSVC C++ 运行时的名字按集合规则决定,不按搜索次序,且其差异不在每次链接时 警告,而由解析器作为打包缺陷说明一次。规划时尚不存在、由 prepare 在构建中填充的目录里的 运行时名字,由本条的放置以同一个解析器决定。(已实现,mcpp 2026.9.28.2)
  • R4.5 一条构建边在成功时有话要说(本条的放置比较出差异,或在两个目录提供的同名 DLL 之间 作了选择),必须写入该边的通告文件(构建目录下的 .mcpp-advice/<该边的输出>.advice), 而不是写到只在构建失败或 -v 时才显示的输出。构建成功后,引擎报告本次运行过的边的通告, 每个事实在一个进程中只报告一次,随后删除这些文件;完整构建路径与快速路径由同一个函数报告。 规划时对同一事实的第二次陈述禁止存在。(已实现,mcpp 2026.9.28.2)
  • R4.4 插件禁止在 link_flag 中写运行路径(-Wl,-rpath,...),必须使用 R4.1。 (作者义务)

5. 规划期的义务(mcpp emit build-database)

  • R5.1 规划运行构建程序,不运行任何 action(SPEC-005 R2.2)。插件遵守 R1.3 时,规划得出 的配置与构建相同。(已实现)
  • R5.2 一个包的构建程序在规划中失败时,该包只按其清单描述,并得到一条错误诊断;成员的 其余部分照常描述。插件遵守 R1.2 时,环境不完整不会使构建程序失败。(已实现,mcpp#702)
  • R5.3 规划不构建宿主工具(SPEC-005 R2.5)。全局工具库中已有的工具照常使用;没有的工具 被推迟,规划产生一条 note MCPP_BUILD_DATABASE_HOST_TOOL_DEFERRED,点名工具与其所属包, 请求它的构建程序收到该工具将被发布的路径。插件应当在 action 中运行宿主工具,而不是在 构建程序中运行,使规划不依赖工具是否已经构建。(引擎部分 已实现,mcpp#707;此前规划 构建宿主工具,构建失败时降级为警告,mcpp#702;「应当」为作者义务)

6. 环境与载荷

  • R6.1 插件驱动的工具与 SDK 必须声明为载荷([xlings] 或 [feature-xlings]),需要 时以目标轴选择器门控,并在构建程序中用 mcpp::xpkg_dir 取得路径。声明必须放在查询发生 的包上:xpkg_dir 为正在构建的包回答;host-module 的声明对编入它的每个构建程序可见 (docs/31)。(已实现)
  • R6.2 插件禁止****未经使用者指定探测宿主路径来寻找工具或 SDK:未声明且未被指定的 依赖不可复现。使用者指定的来源(构建程序的选项、[xlings.overrides]、 MCPP_XLINGS_OVERRIDE_<NS>_<NAME>、config.toml)可以是 PATH 上的程序,因为那是 一次被陈述并被记录的选择。无人指定时回落到 PATH 的插件必须报告它在用哪一个程序, 并指出使用者如何陈述它;这种回落应当被移除。(作者义务;0.19.0 起 mcpp-plugins 的 rules-spirv、rules-slang 以警告保留该回落至 2027-04-01)
  • R6.5 一个工具的来源必须按同一顺序决定,并且必须被记录(mcpp#755):
    1. 构建程序陈述的选择;2. 该成员历来读取的环境变量;3. 引擎的覆盖 ([xlings.overrides]);4. 声明的载荷。构建程序陈述了选择时,禁止请求该载荷——这 正是「构建程序自带工具即不下载」的含义。每一次解析必须以 mcpp::decision 陈述 主体、来源与值,官方通用库 mcpp.plugins.tool 实现本条,插件应当使用它而不是各自 实现。(已实现,mcpp 2026.10.1.3;mcpp.plugins.tool 为 mcpp-plugins 0.19.0)
  • R6.6 只有部分构建需要的工具,其载荷应当声明 provision = "on-request",并在 构建程序中以 mcpp::xpkg_request 请求:不需要它的构建因此不下载它。请求了载荷的那次 运行必须在不配置依赖该工具的任何东西的情况下返回(mcpp::xpkg_pending(),或 mcpp.plugins.tool 的 found::pending());引擎安装后会再次运行该程序。(已实现, mcpp 2026.10.1.3)
  • R6.3 插件的某个特性需要本包的程序在构建机器上运行时,应当在该特性上声明 [features.<f>] tools = ["<bin>"],而不是要求每个消费方在依赖边上重复写 tools。启用该 特性的消费方得到该工具,与边上写了 tools 相同(SPEC-004 §10.2)。(已实现,mcpp#709)
  • R6.4 一个需要随消费方发布、在消费方的目标上运行的程序(更新器、辅助进程)必须以依赖 边的 artifacts 取得(SPEC-004 §10.3),禁止以 tools 取得:tools 为构建机器构建, 交叉构建中得到错误架构的程序。action 以 ${mcpp.artifact:<依赖>/<目标>} 引用它的路径。 (已实现,mcpp#711)

7. 版本与兼容

  • R7.1 使用协议 N 的指令或角色的插件,必须写明第一个支持协议 N 的 mcpp 版本: mcpp 2026.9.28.3 起写在清单中,[package] mcpp = ">=<release>"(R9.8),此前写在文档中。索引测量该插件时,CI 所用的 mcpp 版本移到该版本;索引的 min_mcpp 不因此改变。旧引擎 编译该构建程序时因缺少函数或常量而失败,并指出其名称。(编译期失败 已实现)
  • R7.2 插件禁止依赖引擎内部的拼写与未写入文档的行为(R2.3、R2.4)。(作者义务)

8. 判据

  • R8.1 插件必须在它声明支持的每个平台上有一个在该平台运行的判据。# requires: gcc 只在 Linux 成立,不能作为 Windows 或 macOS 的判据。(作者义务)
  • R8.2 每个判据必须在它所验证的改动之前失败。(作者义务)
  • R8.3 插件应当有一个规划判据:它的一个消费方工程,在没有安装其载荷的机器上运行 mcpp emit build-database,得到一份文档,其中该插件只贡献警告,或只使声明它的包缺少 构建程序的指令(R5.2),而不是整次失败。(作者义务)

9. 引擎接口 mcpp.core、构建信息与插件的名字(mcpp#734)

插件分三层:引擎提供的 mcpp.core(L1);官方通用库 mcpp.plugins(L2),只基于 L1 编写, 由 feature plugins-core 提供;具体插件(L3),即官方的 mcpp.deps.*、mcpp.rules.*、 mcpp.dist.*、mcpp.tools.* 与第三方的 mcpp.<namespace>.*,基于 L1 或 L1 与 L2。依赖只 向下:L3 依赖 L2 或 L1,L2 依赖 L1,L1 不依赖任何一层。

  • R9.1 引擎提供给构建程序的接口名为 mcpp.core。mcpp 是它永久等价的写法:两者导出相同 的符号,构建程序可以使用任一写法或同时使用。等价不是兼容措施,不会被移除。(已实现)

  • R9.2 mcpp.core 只增不删。一个符号只有在弃用六个月之后才可以移除;含义的改变以新的符号 表达。每个符号标注引入它的协议版本。协议版本与 mcpp 版本的对应如下,构建插件以 mcpp 版本 表达需求(R9.8)。(已实现)

    协议 首个 mcpp 版本 引入的内容
    11 2026.9.12.3 deploy
    12 2026.9.26.2 prepare 角色、runtime_search_dir
    13 2026.9.27.1 action 的 env 与 cwd
    14 2026.9.28.3 mcpp.core、构建信息(R9.3)、mcpp::report(R9.4)
    15 2026.10.1.3 来源(R6.5、R6.6、R9.9):xpkg_source、xpkg_program、xpkg_request、xpkg_pending、phase、decision、toolchain
  • R9.3 构建信息以事实陈述解析出的工具链,不针对任何外部构建系统:tool(role)(这一行的 工具)、abi_tool(role)(目标 ABI 的原生工具,MSVC ABI 上为工具集的 cl、link、lib、 ml64 与 SDK 的 rc、mt)、tool_env()(引擎运行这些工具时的环境变量)、 toolset_identity()(不含路径的标识)、msvc_instance_dir()、ninja_program()、 cxx_runtime() 与 msvc_crt_linkage()。每个值取自引擎自身命令行所读的同一来源;不适用时 为空。把这些事实翻译成 CMake、vcpkg 等外部系统的写法是插件的职责。(已实现)

  • R9.4 构建程序以 mcpp::report({severity, message, impact, hint}) 陈述诊断。引擎按自身 诊断的形式呈现它,记入 --message-format json,degraded 在 --strict 下使构建失败,缓存 命中的运行再次报告它。mcpp::warning(text) 等价于只有消息的诊断。(已实现)

  • R9.5 mcpp stage --list <file> 在一个进程内放置 <源>\t<目的> 列表中的每一项,每个目的 地保持单文件放置的语义(R4.2)。程序的 deploy 条目在两条及以上时由一条这样的边放置。 (已实现)

  • R9.6 构建程序可导入的模块若以 mcpp. 开头,第二段为 core、plugins、deps、rules、 dist、tools 的名字只由命名空间为 mcpp 的包提供;其他包使用 mcpp.<自己的命名空间>.*。 引擎对违反者发出警告,因为它无法判断谁是官方(分支、私有镜像均属正当);mcpp-index 把同一 规则作为收录条件。保留的第二段只在本条增加。(引擎警告 已实现;索引收录条件见 mcpp-index)

  • R9.7 构建程序导入的模块若由某个依赖在未启用的 feature 之后提供,错误必须写出包名与 feature 名。只在出错时读取这些单元的模块声明。(已实现)

  • R9.8 包以 [package] mcpp = ">=<release>" 声明支持的最旧 mcpp 版本, [workspace.package] mcpp 为全部成员声明。低于下限的引擎在其他工作之前停止,写出包名、下限、 自身版本与升级命令;只接受 >= 形式。(已实现)

  • R9.9 构建程序可以陈述构建工具链,仅当该工程的 [toolchain] 写了 configure = "build.mcpp",且仅在工具链阶段(mcpp::phase() 为 "toolchain")。该阶段 在目标依赖图解析之前运行,禁止陈述工具链以外的任何指令:引擎拒绝并点名第一条不属于 该阶段的指令。陈述的键与 [toolchain] 表的键相同(spec、path、prefix、sysroot、 family、launcher、tool.<role>、origin),官方通用库 mcpp.plugins.toolchain 提供构造这些陈述的函数。编译并运行构建程序的是 bootstrap 工具链,因此一个无法使用的 自定义工具链必须仍能让构建程序运行并报告原因。(已实现,mcpp 2026.10.1.3)

10. 变更记录

版本 日期 变更
0.1 2026-09-26 首版草案(mcpp#699、#701、#702、#703)。
0.3 2026-09-27 随 mcpp 2026.9.27.1:新增 R3.8(action 的 env 与 cwd,协议 13,mcpp#708);R5.3 改为规划不构建宿主工具、缺失的工具以 note 推迟(mcpp#707);新增 R6.3(特性的 tools,mcpp#709)与 R6.4(artifacts 与 ${mcpp.artifact:},mcpp#711)。
0.4 2026-09-28 随 mcpp 2026.9.28.1:R4.2 同一目标的多个来源在放置时按内容核对,相同则放置一份,不同则失败并点名全部来源;R4.3 一个目标一个写入者,链接后的放置不覆盖另一写入者放在程序旁的文件(mcpp#723)。
0.5 2026-09-28 随 mcpp 2026.9.28.2:R4.3 的部署清单是运行时放置解析器的答案(SPEC-006 §3.7.1),MSVC C++ 运行时按集合规则决定,prepare 填充的目录中的运行时名字由同一解析器决定;新增 R4.5,构建边在成功时的通告,构建后报告一次(2026-09-28 设计 WS1、WS3)。
0.7 2026-10-01 随 mcpp 2026.10.1.3(mcpp#755):R6.2 改为禁止未经指定的宿主探测并要求报告回落;新增 R6.5(工具来源的顺序与记录)、R6.6(provision = "on-request" 与 xpkg_request)、R9.9(构建程序在工具链阶段陈述构建工具链);R9.2 的协议表新增第 15 行。
0.6 2026-09-28 随 mcpp 2026.9.28.3:新增 §9(mcpp#734),即 mcpp.core 与 mcpp 的永久等价、接口的稳定性与协议表、构建信息、结构化诊断、批量放置、插件模块的名字、缺失模块指出 feature、包的版本下限;R7.1 的版本写在清单中;变更记录移为 §10。
0.2 2026-09-26 随 mcpp 2026.9.26.2 落地:R1.3 的警告、R2.1 的 runtime_search_dir、R2.4、R3.3 的 prepare(目录须含文件;链接边等待所有 prepare)、R3.5、R3.6、R4.1、R4.3、R5.2、R5.3 标为已实现。