Repository Wiki
BeyondDimension/SteamTools

辅助工具项目与开源依赖

本文介绍 WattToolkit(原 SteamTools)解决方案中支撑主应用构建的辅助工程与开源依赖管理机制,包括中央包管理(Central Package Management, CPM)、目标框架矩阵 .props 脚本、本地维护的 Avalonia 分支(vendored fork)项目,以及强名称签名、NuGet 源配置等构建辅助文件。

目的与范围

本页面覆盖仓库结构与依赖治理这一主题,即:主应用代码之外、但决定主应用如何编译与链接开源组件的所有辅助资产。具体包括:

  • WattToolkit.slnx 解决方案组织方式
  • 中央包管理文件 src/Directory.Packages.props 及其向 ref/DirectoryPackages 的转发导入
  • src/TFM_NETX*.props 目标框架(Target Framework Moniker, TFM)矩阵脚本族
  • 本地维护的 Avalonia 内部分支项目(src/Avalonia.*.Internals 等)
  • 强名称密钥(.snk)、NuGet.Config、global.json 等构建配置

不在本页覆盖、留给兄弟页面的内容:主应用的功能架构(如账号、加速、脚本服务等)各自有独立页面;Avalonia 分支项目内部某个具体补丁的实现细节同样按主题拆分。

概述

WattToolkit 是一个跨平台桌面应用,其仓库采用了两条并行的依赖策略:

  1. 外部的 NuGet 依赖通过中央包管理(CPM)统一管理:版本号集中在 Directory.Packages.props 中声明,各 .csproj 只写包名不写版本,避免版本漂移。值得注意的是,本仓库的 CPM 文件本身又通过 Import 转发到 ref/DirectoryPackages/Directory.Packages.props,即把"第三方包版本清单"外置到 ref/ 引用目录中。
  2. 对上游开源框架(Avalonia)的关键缺口直接本地维护分支:当官方包无法满足需求(例如需要访问 Skia 内部类型、扩展字体管理接口)时,仓库在 src/ 下放置了多个 Avalonia.* 项目,作为编译期内联的补丁层参与解决方案构建,而不是等待上游发版。

这种"外置版本清单 + 内联框架补丁"的组合,使主应用可以在不 fork 整个上游仓库的情况下,精确控制依赖版本并修补框架行为。

架构

下图展示辅助工程与开源依赖在整个构建体系中的位置(节点均对应仓库中真实存在的文件/项目):

Loading diagram...

要点解读:

  • WattToolkit.slnx 是解决方案入口,把主应用项目与 src/Avalonia.* 分支项目纳入同一编译批次,使框架补丁与业务代码同步编译、同步发布。
  • Directory.Packages.props 是纯转发文件:它本身不声明任何包,只做一次 Import,把真正的版本清单放在 ref/DirectoryPackages/ 下。ref/ 是仓库的"引用资产"目录(其中还存在 ref/Directory.Build.props),用于集中承载可外置的构建输入。
  • TFM_NETX*.props 是一组目标框架矩阵脚本(TFM_NETX、TFM_NETX_SINGLE、TFM_NETX_WINDOWS、TFM_NETX_WITH_ALL、TFM_NETX_WITH_DESKTOP、TFM_NETX_WITH_WINDOWS),从命名可推断用于按"单目标 / 桌面 / Windows / 全平台"等维度组合 TargetFrameworks,让不同项目按需选择平台矩阵,避免每个 .csproj 重复罗列 TFM。这些脚本的内容未在本次证据采集中读取,具体属性定义请直接查阅对应文件。
  • 强名称密钥双份:根目录同时存在 avalonia.snk 与 WattToolkit.snk,前者供本地 Avalonia 分支项目签名(使其与官方程序集身份兼容),后者供应用自身程序集签名。

辅助工程与依赖分层

中央包管理:两层结构

仓库实际的 CPM 入口文件只有 3 行:

xml
<Project> <Import Project="..\ref\DirectoryPackages\Directory.Packages.props" /> </Project>

Source: Directory.Packages.props

这行 Import 的设计意图是把第三方版本清单从 src/ 源码树中剥离:src/ 下所有项目经由 MSBuild 的目录级联机制自动继承 src/Directory.Packages.props,而真正的包版本表位于 ref/DirectoryPackages/。其收益与代价如下:

  • 收益:版本治理点单一;ref/ 目录可独立更新(例如仅升级依赖时只动 ref/)。
  • 代价:ref/DirectoryPackages/Directory.Packages.props 成为构建的硬性前置依赖——本次采集中对该路径的直接读取返回"文件不存在",说明它依赖仓库检出方式(如子模块/引用还原)才能就位;若未还原,src/ 下所有项目的包解析都会失败。

目标框架矩阵:TFM_NETX*.props 族

src/ 下存在六个 TFM 脚本:

文件推断职责(依据命名,内容未读取)
TFM_NETX.props基础脚本,定义统一的 .NET 目标框架代数
TFM_NETX_SINGLE.props单目标框架(单一 RID/平台)组合
TFM_NETX_WINDOWS.props仅 Windows 目标
TFM_NETX_WITH_WINDOWS.props多目标 + 包含 Windows
TFM_NETX_WITH_DESKTOP.props多目标 + 桌面平台族
TFM_NETX_WITH_ALL.props全支持平台矩阵

Sources:

设计意图:跨平台项目最容易失控的地方就是每个 .csproj 各写一份 TargetFrameworks 列表。将其收敛为可 Import 的命名组合后,"平台支持范围"成为仓库级策略而非项目级散落配置。

本地维护的 Avalonia 分支项目

src/ 下观察到以下 Avalonia 相关项目,它们不是 NuGet 引用,而是解决方案内的源码项目:

项目采集中观察到的关键文件补丁方向(依据文件名推断)
Avalonia.Base.InternalsDrawingContextExtensions.cs暴露 Base 层内部绘制 API
Avalonia.Controls.Internals(仅见 .csproj)控件层内部类型
Avalonia.Skia.InternalsSkiaPlatform2.cs、IFontManagerImpl2.cs、SKTypefaceCollection.cs、SKTypefaceCollectionCache.cs、ImmutableBitmap.cs、PlatformRenderInterface.cs、ClassicDesktopStyleApplicationLifetime.cs、DrawingContextExtensions.csSkia 渲染后端扩展:字体管理第二接口、字形集合缓存、平台渲染接口
Avalonia.DesktopAppBuilderDesktopExtensions.cs桌面宿主启动扩展
Avalonia.Native(仅见 .csproj)macOS 原生后端
Avalonia.Diagnostics(仅见 .csproj)诊断工具
Avalonia.WebView2WebView2.csWebView2 控件封装

Sources:

命名规律值得注意:SkiaPlatform2、IFontManagerImpl2 这类带 2 后缀的类型名表明补丁策略是新增并行实现而非修改原类型——原 Avalonia 类型保持不变,分支项目提供增强版(如 IFontManagerImpl2 扩展字体管理能力、SKTypefaceCollectionCache 为字形集合加缓存层)。这降低了与上游合并的冲突面。

这些项目使用根目录的 avalonia.snk 签名,从而与官方 Avalonia 程序集保持一致的身份,使主应用对它们的引用可以无缝替换官方 NuGet 包。

使用示例

示例:项目如何接入中央包管理与 TFM 矩阵(机制示意)

在 src/ 下的任何项目中,无需显式引用,MSBuild 会自动级联应用 src/Directory.Build.props 与 src/Directory.Packages.props;项目文件中按需 Import 对应的 TFM 组合脚本即可继承平台矩阵。这是隐式机制,无项目内代码片段可摘录——入口即上述 3 行转发文件。

示例:根目录辅助配置资产

仓库根目录的辅助文件清单(采集中实际观察到的完整根目录列表):

text
1avalonia.snk 2crowdin.yml 3global.json 4LICENSE 5NuGet.Config 6README.en.md 7README.md 8WattToolkit.slnx 9WattToolkit.snk

Source: NuGet.Config

其中 crowdin.yml 表明本地化文案通过 Crowdin 平台协作,global.json 锁定 .NET SDK 版本,NuGet.Config 控制 NuGet 源解析行为(其具体源列表未在本次采集中读取)。

配置文件一览

文件/目录类型默认行为说明
src/Directory.Packages.propsXML (MSBuild)转发导入CPM 入口,3 行,不含任何包版本
ref/DirectoryPackages/Directory.Packages.propsXML (MSBuild)(外置)真正的第三方包版本清单,位于 ref/ 引用目录
src/Directory.Build.propsXML (MSBuild)(未读取)src/ 树通用构建属性
ref/Directory.Build.propsXML (MSBuild)(未读取)ref/ 树通用构建属性
src/TFM_NETX*.props(6 个)XML (MSBuild)(未读取)目标框架矩阵组合脚本
global.jsonJSON(未读取).NET SDK 版本锁定
NuGet.ConfigXML(未读取)NuGet 源与包解析配置
avalonia.snk / WattToolkit.snk二进制—强名称签名密钥(分别为 Avalonia 分支项目与应用自身)
crowdin.ymlYAML(未读取)Crowdin 本地化平台集成

标注"(未读取)"的项表示本次证据采集未覆盖其内容,此处仅登记其存在与角色定位,不做内容性断言。

失败模式与注意事项

  • ref/DirectoryPackages 未还原导致构建失败:由于 src/Directory.Packages.props 硬依赖 ..\ref\DirectoryPackages\Directory.Packages.props,且采集中该路径直接读取失败(未在当前检出中找到),克隆仓库后若 ref/ 引用目录未完整还原,所有 src/ 项目将在 NuGet 还原阶段失败。排查时应首先确认该文件是否就位。
  • Avalonia 分支项目的上游漂移风险:src/Avalonia.* 项目与官方 Avalonia 版本必须保持 ABI 兼容(同 avalonia.snk 签名才可替换)。升级 Avalonia 依赖版本时,需要同步核对分支项目中的补丁(尤其 SKTypefaceCollection 系列与 IFontManagerImpl2)是否仍与上游内部结构匹配。
  • 并行实现的命名约定:SkiaPlatform2/IFontManagerImpl2 采用"原名 + 2"的并行实现策略。扩展此层时建议沿用该约定,避免直接改写上游类型造成合并冲突。
  • 证据边界说明:本页对 TFM_NETX*.props 的属性定义、NuGet.Config 的源列表、global.json 的 SDK 版本、以及各 Avalonia 分支项目的 .csproj 引用关系均未做源码级验证,上述表格中的相应描述属待查项,不应作为二次开发的唯一依据。

相关链接

Sources

(1 files)