构建与使用 Avalonia 本地 NuGet 包:CreateNugetPackages 与 BuildToNuGetCache 实战指南
2026/9/10 2:47:27 网站建设 项目流程

构建与使用 Avalonia 本地 NuGet 包:CreateNugetPackages 与 BuildToNuGetCache 实战指南

【免费下载链接】AvaloniaDevelop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The future of .NET UI项目地址: https://gitcode.com/GitHub_Trending/ava/Avalonia

本篇指南围绕 Avalonia 仓库的 docs/nuget.md 展开,系统讲解如何通过 Nuke 构建脚本在本地生成 Avalonia 的 NuGet 包(CreateNugetPackages目标),以及如何借助BuildToNuGetCache目标把构建产物直接打入本机 NuGet 全局缓存,从而在二次开发、改源码调试、验证本地修改时快速获得可用的包。读完本文,你将掌握跨平台的包构建命令、版本与构建配置控制,以及绕过本地 feed 配置直接消费自编译 Avalonia 的完整套路。

一、构建本地 NuGet 包的整体流程

Avalonia 的仓库构建体系基于 Nuke(.NET Universal Build Automation)。CreateNugetPackages是产出最终.nupkg的核心目标,它在 nukebuild/Build.cs 中定义,依赖链如下:

CreateNugetPackages └─ CreateIntermediateNugetPackages (对解决方案执行 dotnet pack,产出中间包) └─ Compile (先编译整个解决方案)

从 nukebuild/Build.cs 的源码可以看到,CreateIntermediateNugetPackages会对根目录的dirs.projParameters.MSBuildSolution,定义于 nukebuild/BuildParameters.cs)执行DotNetPack,随后CreateNugetPackages目标完成三道关键工序:

  1. 修补 Build.Tasks:通过BuildTasksPatcher.PatchBuildTasksInPackage使用 ILRepack 工具对Avalonia.Build.Tasks中间包进行处理;
  2. 合并子包:读取 nukebuild/numerge.json 中的合并配置,使用 Numerge 的NugetPackageMerger.MergeAvalonia.Build.TasksAvalonia.GeneratorsAvalonia.Analyzers.CSharpAvalonia.Analyzers.VisualBasicAvalonia.Analyzers.CodeFixes.CSharp等子包合并进主Avalonia包(MergeAll: true),同时也合并Avalonia.Win32.AutomationAvalonia.Win32
  3. 生成引用程序集:调用RefAssemblyGenerator.GenerateRefAsmsInPackageAvalonia.<version>.nupkg与其配套的.snupkg生成 ref 程序集。

最终产物会被放入artifacts\nuget目录(NugetRoot = ArtifactsDir / "nuget",见 nukebuild/BuildParameters.cs)。

二、三种调用方式与跨平台命令

1. 仓库内置构建脚本(推荐用于 CI 化、无全局工具环境)

Windows(PowerShell):

.\build.ps1 CreateNugetPackages

Linux/macOS:

./build.sh CreateNugetPackages

这两个脚本位于仓库根目录,其引导逻辑是:优先使用本机已安装且与 global.json(当前要求 SDK10.0.201)匹配的 dotnet CLI;若不可用则自动下载对应版本的 SDK 到.nuke/temp。随后编译 nukebuild/_build.csproj 并用dotnet run --project nukebuild/_build.csproj --no-build -- <目标参数>把命令行参数透传给 Nuke(见 build.sh、build.ps1)。

2. Nuke 全局工具(跨平台一致,推荐日常开发)

如果你安装了 Nuke 的 dotnet global tool(命令为nuke),可以直接:

nuke CreateNugetPackages

本文后续命令统一假设你已安装 Nuke 全局工具,因为它跨平台调用方式一致;你随时可以用./build.sh.\build.ps1替换其中的nuke(注意平台相关脚本路径不同)。

构建成功后,生成的 NuGet 包位于artifacts\nuget目录。

三、控制构建配置与包版本

1. 使用 Release 配置构建

默认情况下包以 Debug 配置构建。若要生成 Release 版本,添加--configuration参数:

nuke CreateNugetPackages --configuration Release

该参数对应 nukebuild/BuildParameters.cs 中声明的[Parameter(Name = "configuration")],且默认值本身就是"Release"(见 nukebuild/BuildParameters.cs),也就是说不传该参数时其实默认就是 Release;显式传入Debug等值可以覆盖默认行为。配置值会通过ApplySettingCore中的SetConfiguration注入到每个 dotnet 命令(nukebuild/Build.cs)。

2. 强制指定 NuGet 版本

默认的包版本号来自 build/SharedVersion.props 中的<Version>节点(当前仓库为12.2.999),由BuildParameters.GetVersion()读取(见 nukebuild/BuildParameters.cs)。想临时指定版本,使用--force-nuget-version

nuke CreateNugetPackages --force-nuget-version 11.4.0

该参数对应[Parameter(Name = "force-nuget-version")](nukebuild/BuildParameters.cs),其优先级高于版本文件:Version = b.ForceNugetVersion ?? GetVersion()(nukebuild/BuildParameters.cs)。指定的版本会同时作为PackageVersionMSBuild 属性注入到打包过程(nukebuild/Build.cs)。在 Azure CI 环境中,若未发布分支,版本还会被追加-cibuild<BuildId>-alpha后缀(nukebuild/BuildParameters.cs)。

此外,仓库根目录的 Directory.Packages.props(Central Package Management)负责统一管理依赖包版本,构建 Avalonia 自身的包时依赖清单即由此集中约束。

四、直接构建到本机 NuGet 缓存(BuildToNuGetCache)

1. 为什么需要它:CreateNugetPackages 的几个坑

直接用CreateNugetPackages产出包再消费,会遇到三类典型问题:

  • 需要自行搭建本地 NuGet feed:必须配置NuGet.Config指向本地源,才能让消费项目还原到这些包;
  • Avalonia.Native 缺失:在非 macOS 操作系统上构建时,Avalonia.Native(基于 Xcode 项目的原生宿主)不会被编译,导致使用Avalonia.Desktop时报 NuGet 错误。这是因为原生编译目标CompileNative带有OnlyWhenStatic(() => EnvironmentInfo.IsOsx)的平台限制(见 nukebuild/Build.cs);
  • 容易引入版本管理混乱:手改版本号、忘记覆盖旧版本等,都会让“我这包是哪次编译的”变成难题。

2. 一键命令

为解决上述问题,仓库提供了BuildToNuGetCache目标:

nuke --target BuildToNuGetCache --configuration Release

该命令会:

  1. 先执行CreateNugetPackages生成完整包(依赖关系见 nukebuild/Build.cs);
  2. 把每个.nupkg解压到本机 NuGet 全局缓存目录(通常为~/.nuget/packages)下的<包id小写>/9999.0.0-localbuild/路径,并写入.nupkg.metadata文件(见 nukebuild/Build.cs)。

包版本统一为9999.0.0-localbuild,该常量定义于 nukebuild/BuildParameters.cs(public const string LocalBuildVersion = "9999.0.0-localbuild")。当isPackingToLocalCache为真时,BuildParameters会把Version强制替换为该常量(nukebuild/BuildParameters.cs)。

与此同时,ApplySettingCore会在打包到本地缓存时自动附加一组 MSBuild 属性(nukebuild/Build.cs):

属性作用
ForcePackAvaloniaNativeTrue强制打入 Avalonia.Native 原生包,规避非 macOS 平台缺包问题
SkipObscurePlatformsTrue跳过次要平台目标,加快打包
SkipBuildingSamplesTrue跳过示例工程,只关注库本体
SkipBuildingTestsTrue跳过测试工程,显著缩短构建链路

3. 消费本地修改的工作流

每次修改 Avalonia 源码后,只需再次运行:

nuke --target BuildToNuGetCache --configuration Release

新包会替换~/.nuget/packages下的旧包并重置缓存,MSBuild 在下一次还原时自动拾取最新内容,无需手动清理缓存或维护本地 feed。这特别适合“改源码 → 跑本地 demo/测试 → 验证效果”的迭代循环,例如配合 samples/Sandbox 或 tests/BuildTests(该测试目录专门用于验证打包后的 Avalonia 能被外部工程正确编译、甚至原生 AOT 运行,见 nukebuild/Build.cs 的VerifyXamlCompilation)。

仓库还提供了现成的快捷脚本 nukebuild/build-to-cache.sh,等价于:

dotnet run --project nukebuild/_build.csproj -- --target BuildToNuGetCache --skip CompileHtmlPreviewer Compile Clean

它额外跳过了CompileHtmlPreviewerCompileClean等前置目标,进一步缩短本地迭代耗时。

4. 注意事项

  • BuildToNuGetCache会把包写入全局用户缓存(Linux/macOS 为~/.nuget/packages,Windows 为%USERPROFILE%\.nuget\packages),该目录下的9999.0.0-localbuild包是“本地构建专用版本”,与官方发布版本互不干扰;
  • 若你的消费工程启用了NuGetAudit或严格版本约束,请确保它允许还原9999.0.0-localbuild这样的预发布版本号;
  • 该目标内部通过SettingsUtility.GetGlobalPackagesFolder(Settings.LoadDefaultSettings(RootDirectory))解析全局包目录(nukebuild/Build.cs),若你自定义过 NuGet 配置,实际目录以该解析结果为准。

五、验证与调试:配套的测试基建

构建与打包的正确性在仓库中是有测试保障的:

  • tests/BuildTests 是一组专门的外部消费工程(含BuildTests.DesktopBuildTests.BrowserBuildTests.AndroidBuildTests.iOSBuildTests.FSharpBuildTests.NativeAotBuildTests.WpfHybrid等),CI 会用刚打包出的 Avalonia 版本还原并编译它们,再通过XamlCompilationVerifier校验程序集内嵌 XAML 是否被正确编译(nukebuild/Build.cs);
  • nukebuild/numerge.json 是包合并的“事实来源”,如果你手动检查artifacts\nuget下的产物结构,会发现主Avalonia包内集成了生成器与分析器组件,这是MergeAll: true的直接体现。

六、常见问题速查

问题解决方案
非 macOS 平台使用Avalonia.Desktop报原生包缺失改用BuildToNuGetCache(会自动设置ForcePackAvaloniaNative=True),或参考 native/Avalonia.Native/README.md 在支持的平台自行编译原生库
想发布 Release 包--configuration Release
想用自定义版本号--force-nuget-version <版本>
产物位置artifacts\nuget(中间产物在build-intermediate\nuget
不想配置本地 feed直接用BuildToNuGetCache写入全局缓存,消费方以9999.0.0-localbuild还原

总而言之:日常源码调试优先使用BuildToNuGetCache,发布/分发场景使用CreateNugetPackages--configuration--force-nuget-version精确控制产物;两条路径都由 nukebuild/Build.cs 与 nukebuild/BuildParameters.cs 统一驱动,理解这几个文件即可完全掌控 Avalonia 的本地打包链路。

【免费下载链接】AvaloniaDevelop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The future of .NET UI项目地址: https://gitcode.com/GitHub_Trending/ava/Avalonia

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询