构建与使用 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.proj(Parameters.MSBuildSolution,定义于 nukebuild/BuildParameters.cs)执行DotNetPack,随后CreateNugetPackages目标完成三道关键工序:
- 修补 Build.Tasks:通过
BuildTasksPatcher.PatchBuildTasksInPackage使用 ILRepack 工具对Avalonia.Build.Tasks中间包进行处理; - 合并子包:读取 nukebuild/numerge.json 中的合并配置,使用 Numerge 的
NugetPackageMerger.Merge把Avalonia.Build.Tasks、Avalonia.Generators、Avalonia.Analyzers.CSharp、Avalonia.Analyzers.VisualBasic、Avalonia.Analyzers.CodeFixes.CSharp等子包合并进主Avalonia包(MergeAll: true),同时也合并Avalonia.Win32.Automation到Avalonia.Win32; - 生成引用程序集:调用
RefAssemblyGenerator.GenerateRefAsmsInPackage为Avalonia.<version>.nupkg与其配套的.snupkg生成 ref 程序集。
最终产物会被放入artifacts\nuget目录(NugetRoot = ArtifactsDir / "nuget",见 nukebuild/BuildParameters.cs)。
二、三种调用方式与跨平台命令
1. 仓库内置构建脚本(推荐用于 CI 化、无全局工具环境)
Windows(PowerShell):
.\build.ps1 CreateNugetPackagesLinux/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该命令会:
- 先执行
CreateNugetPackages生成完整包(依赖关系见 nukebuild/Build.cs); - 把每个
.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):
| 属性 | 值 | 作用 |
|---|---|---|
ForcePackAvaloniaNative | True | 强制打入 Avalonia.Native 原生包,规避非 macOS 平台缺包问题 |
SkipObscurePlatforms | True | 跳过次要平台目标,加快打包 |
SkipBuildingSamples | True | 跳过示例工程,只关注库本体 |
SkipBuildingTests | True | 跳过测试工程,显著缩短构建链路 |
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它额外跳过了CompileHtmlPreviewer、Compile、Clean等前置目标,进一步缩短本地迭代耗时。
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.Desktop、BuildTests.Browser、BuildTests.Android、BuildTests.iOS、BuildTests.FSharp、BuildTests.NativeAot、BuildTests.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),仅供参考