Quire.Package
1.0.0
dotnet add package Quire.Package --version 1.0.0
NuGet\Install-Package Quire.Package -Version 1.0.0
<PackageReference Include="Quire.Package" Version="1.0.0" />
<PackageVersion Include="Quire.Package" Version="1.0.0" />
<PackageReference Include="Quire.Package" />
paket add Quire.Package --version 1.0.0
#r "nuget: Quire.Package, 1.0.0"
#:package Quire.Package@1.0.0
#addin nuget:?package=Quire.Package&version=1.0.0
#tool nuget:?package=Quire.Package&version=1.0.0
Quire.Package
Quire.Package 是面向游戏和应用程序的 .NET 10 资源打包与读取工具。它将多个源目录中的文件和可选 Meta 整理成 .asset 资源包,支持压缩、加密、超大文件以及发布后的增量修补。
项目提供两个独立的安装产物:
| 名称 | 类型 | 用途 |
|---|---|---|
quire-cli |
.NET CLI 工具,也可发布为 Native AOT 可执行文件 | 初始化项目、扫描文件、构建全量或增量包、查看、校验和解包 |
Quire.Package |
NuGet 类库,命名空间为 Quire.Package |
在应用程序中加载资源包目录、读取内容和 Meta、按需读取及并发读取 |
应用程序只需引用 Quire.Package;资源构建在开发机或构建服务器上通过 quire-cli 完成。两个发布项目均无第三方 NuGet 运行时依赖;LZ4 核心源码内嵌,许可证随程序集和 NuGet 发布。
主要能力:
- 使用
quire.project.yml将多个目录编排为多个资源包,支持多级路径前缀、包含/排除模式和.assetignore。 - 每次构建记录一个 Tag,可基于指定 Tag 生成内容变更或仅 Meta 变更的补丁。
- 采用 64 位长度与偏移,支持超过 4 GiB 的文件;流式读取无需把整个文件放入内存。
- 支持 LZ4 压缩和可选 AES-256-GCM 内容加密。
- Meta 支持 string、int64、double、bool 及对应数组,读取时使用明确类型的 API。
- 按目录加载基础包和补丁,支持并发读取、并发解包,以及可选内存映射读取。
资源包后缀为 .asset,头部 magic 为 8 字节 ASCII PK.QUIRE。这是全新格式及 API,不兼容原 GameResource.Package 和中间版本 GASSET01 文件;升级时需要完整重打,不能基于旧格式 Tag 生成增量。资源包不提供写入、删除、移动、保存或空间回收 API。
阅读入口:安装 CLI · 安装类库 · 快速上手 · CLI 命令 · C# API · 源码构建与发布
安装 quire-cli
使用 .NET 工具安装方式时,需要 .NET 10 SDK;SDK 已包含运行所需的 .NET 运行时。可以用 dotnet --list-sdks 查看 SDK。安装 Native AOT 可执行文件后,运行 CLI 不需要 .NET SDK 或运行时。
以下 NuGet 安装命令适用于本项目对应版本已经发布到所用包源的情况;尚未发布时,可使用下文的本地 .nupkg 安装方式。源码中的当前版本为 1.0.0,指定版本时请以实际发布版本为准。
全局安装
dotnet tool install --global quire-cli
quire-cli -h
安装后可在任意目录调用 quire-cli。全局工具目录需要在 PATH 中:Windows 通常为 %USERPROFILE%\.dotnet\tools,Linux/macOS 通常为 $HOME/.dotnet/tools。首次安装后可重新打开终端。
升级或卸载:
dotnet tool update --global quire-cli
dotnet tool uninstall --global quire-cli
需要固定版本时,在安装或更新命令后加 --version 1.0.0。
项目本地安装
在使用资源工具的项目根目录执行;已有工具清单时省略第一条命令:
dotnet new tool-manifest
dotnet tool install quire-cli
dotnet tool run quire-cli -- -h
将 .config/dotnet-tools.json 纳入版本管理,团队成员或构建服务器取得项目后执行:
dotnet tool restore
dotnet tool run quire-cli -- package -project ./quire.project.yml -jobs 5
本地安装的工具通过 dotnet tool run quire-cli -- ... 调用;下文简写为 quire-cli ... 的命令可以替换成这种形式。
从本地 NuGet 包安装
已有本项目的 .nupkg 时,将其放入本地包目录。以下示例假设工具包位于 ./artifacts/packages;从源码生成包的方法见从源码构建和发布。
dotnet tool install quire-cli --tool-path ./.tools --add-source ./artifacts/packages --version 1.0.0
# Windows PowerShell
./.tools/quire-cli.exe -h
Linux/macOS 使用 ./.tools/quire-cli -h。--tool-path 指定的目录不会自动加入 PATH,因此使用该目录中的完整命令路径。
如果只希望从本地包目录安装,可创建 nuget.local.config,并将上面安装命令的 --add-source 替换为 --configfile ./nuget.local.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="QuireLocal" value="./artifacts/packages" />
</packageSources>
</configuration>
配置中的相对包目录以这个 NuGet 配置文件所在目录为基准。
使用 Native AOT 可执行文件
取得与操作系统和架构匹配的 Native AOT 发布产物后,可以直接运行。例如 Windows x64:
./quire-cli.exe -h
./quire-cli.exe init ./MyAssets
Linux x64:
chmod +x ./quire-cli
./quire-cli -h
./quire-cli init ./MyAssets
可以将可执行文件放入 PATH 中的目录,之后直接使用 quire-cli。自行编译 Native AOT 所需的 SDK、C++ 工具链和发布命令见Native AOT 发布。
安装 Quire.Package
消费项目需要面向 .NET 10 或兼容的更高版本。类库不依赖 CLI,程序部署时只需携带类库及要加载的 .asset 文件。
从 NuGet 安装
在使用该类库的 C# 项目目录中执行:
dotnet add package Quire.Package
也可以指定项目和版本:
dotnet add ./MyGame/MyGame.csproj package Quire.Package --version 1.0.0
对应的项目引用为:
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Quire.Package" Version="1.0.0" />
</ItemGroup>
在 Visual Studio 中,也可通过“管理 NuGet 程序包”选择发布了本项目的包源,搜索并安装 Quire.Package。C# 代码使用 using Quire.Package;。
使用本地包或源码引用
包尚未上传到 NuGet 源时,可先在本仓库目录生成类库包,再安装到消费项目:
dotnet pack src/Quire.Package/Quire.Package.csproj -c Release -o artifacts/packages
dotnet add ./MyGame/MyGame.csproj package Quire.Package --source ./artifacts/packages --version 1.0.0
将 ./MyGame/MyGame.csproj 替换为实际消费项目路径。后续构建或换一台机器还原时,也需要能访问这个包源;可以在消费项目的 NuGet.Config 中配置本地目录或私有 NuGet 源。
若消费项目与源码一同开发,可以直接添加项目引用,省去打 NuGet 包的步骤。在本仓库目录执行:
dotnet add ./MyGame/MyGame.csproj reference ./src/Quire.Package/Quire.Package.csproj
同一消费项目选择 NuGet 引用或项目引用中的一种即可。仓库中的 examples 项目 使用项目引用。
快速上手
下面的命令始终在 MyAssets 的上一级目录执行,假设 quire-cli 已安装并能直接调用。
1. 初始化资源项目
quire-cli init ./MyAssets
初始化会生成带完整注释的 MyAssets/quire.project.yml 和三个空源目录:
MyAssets/
quire.project.yml
assets/
common/
shared/
locale/
默认配置把 common 和 shared 合并到 common.asset,把 locale 放入 locale.asset。没有资源变更的包不会生成空 .asset 文件。
2. 添加资源和可选 Meta
创建 MyAssets/assets/common/settings.txt:
resolution=1920x1080
quality=high
在旁边创建 settings.txt.meta:
name=settings
revision=1
scale=1.0
enabled=true
tags=["configuration","example"]
levels=[1,2,3]
weights=[0.25,0.75]
switches=[true,false]
Meta 可省略。此例的源文件经过 prefix: common/data 映射,包内路径是 common/data/settings.txt,读取时使用这个逻辑路径。
3. 打包、检查和解包
quire-cli package -project ./MyAssets/quire.project.yml -jobs 5
quire-cli inspect ./MyAssets/dist
quire-cli verify ./MyAssets/dist
quire-cli unpackage ./MyAssets/dist ./Unpacked -jobs 5
package 输出本次 TagID 和资源包路径。文件位于 MyAssets/dist/<TagID>/common.asset,构建记录位于 MyAssets/.asset/。解包后可以在 Unpacked/common/data/settings.txt 及其 .meta 中看到还原结果;解包目标需要不存在或为空。
4. 在 C# 程序中读取
创建一个消费项目并安装类库;本地包使用前一节的 --source 方式:
dotnet new console -n QuireReader -f net10.0
dotnet add ./QuireReader/QuireReader.csproj package Quire.Package
将 QuireReader/Program.cs 替换为:
using System.Text;
using Quire.Package;
string directory = args.Length > 0 ? args[0] : "./MyAssets/dist";
using var assets = await AssetPackageSet.OpenDirectoryAsync(directory);
const string path = "common/data/settings.txt";
AssetInfo info = assets.GetInfo(path);
Console.WriteLine($"{info.Path}: {info.Length} bytes");
AssetMetadata meta = await assets.ReadMetadataAsync(path);
Console.WriteLine($"Name: {meta.GetString("name")}");
Console.WriteLine($"Revision: {meta.GetInt64("revision")}");
using AssetData file = await assets.ReadAsync(path);
Console.WriteLine(Encoding.UTF8.GetString(file.Data.Span));
在同一工作目录运行:
dotnet run --project ./QuireReader/QuireReader.csproj -- ./MyAssets/dist
CLI 命令和参数
quire-cli 自身的参数采用单横线;dotnet 的参数仍使用它自己的语法。查看帮助使用 quire-cli -h。
| 命令 | 用途 | 示例 |
|---|---|---|
init |
初始化完整的多包配置和源目录 | quire-cli init ./MyAssets |
package |
构建资源包,不带基准 Tag 时为全量构建 | quire-cli package -project ./MyAssets/quire.project.yml -jobs 5 |
diff |
与指定 Tag 比较,列出本次需打包的内容或 Meta | quire-cli diff -project ./MyAssets/quire.project.yml -base-tag TAG_ID |
tags |
查看该项目的本地构建记录 | quire-cli tags -project ./MyAssets/quire.project.yml |
inspect |
查看目录中的物理包和最终有效资源路径 | quire-cli inspect ./MyAssets/dist |
verify |
校验目录中的所有包,包括被后续包覆盖的内容 | quire-cli verify ./MyAssets/dist |
unpackage |
并发解包最终有效资源及 Meta | quire-cli unpackage ./MyAssets/dist ./Unpacked -jobs 5 |
示例中的 TAG_ID 需要替换为 package 或 tags 输出的实际 TagID。
| 参数 | 适用命令 | 默认值或要求 |
|---|---|---|
-project PATH |
package、diff、tags |
可选,默认当前工作目录中的 quire.project.yml |
-base-tag TAG |
package、diff |
package 可选;diff 必填 |
-jobs N |
package、diff、unpackage |
可选,默认逻辑处理器数与 8 的较小值,范围 1–256;打包时还受 YAML 内存预算约束 |
-pwd VALUE |
package、diff、inspect、verify、unpackage |
可选,直接提供非空密码;加密包需要有效密码来源 |
-pwd-env NAME |
同上 | 可选,从指定环境变量读取密码,与 -pwd 互斥 |
init 的目录参数可省略,默认当前目录;inspect 和 verify 必须指定一个资源包目录;unpackage 必须依次指定源包目录和目标目录。读取类命令不依赖 quire.project.yml。
package -jobs 控制压缩/加密工作线程;diff 接受相同的构建选项,但不会执行压缩或写包;unpackage -jobs 控制同时解包的文件数。路径含空格时使用引号,例如 -project "./Game Assets/quire.project.yml"。
memory-mib、block-size 由 YAML 配置;源文件读取和数据写入并发使用内部默认值,没有对应的公开 CLI 参数。
项目配置
quire-cli init ./MyAssets
quire-cli package -project ./MyAssets/quire.project.yml -jobs 5
init 不指定目录时使用当前目录。它创建 quire.project.yml 和配置引用的 assets/common、assets/shared、assets/locale 空目录;模板包含全部配置字段、一个合并两个源目录的包、另一个独立包、过滤规则及使用说明。已有配置不会被覆盖,已有资源文件会保留。添加资源后执行 package 即可构建。
所有相对路径以 quire.project.yml 所在目录为基准。源目录可以在项目目录之外。prefix 支持 common/data 等多级相对路径,也可以是空字符串。
version: 1
output: ./dist
compression: true
build:
memory-mib: 128
block-size: 262144
encryption:
enabled: false
key-environment: QUIRE_KEY
packages:
- name: common
sources:
- directory: ./assets/common
prefix: common/data
- directory: ../shared/config
prefix: config
- name: textures
compression: true
sources:
- directory: ./assets/images
prefix: game/textures
include:
- "**/*.png"
exclude:
- "**/draft/**"
压缩仅有 true/false,开启后使用独立 LZ4 块,压缩无收益的块保存原始数据。不同分包可以覆盖全局同一路径;同一分包内重复映射报错。
YAML 支持两空格缩进的块映射、块序列、普通/单引号/双引号标量和注释。不支持锚点、别名、自定义标签、多行标量或流式集合,未知设置和不支持的语法会报错。没有 state 或 metadata.format 设置。
可直接运行 API 基础示例,演示打开目录、读取文件、读取八种 Meta 类型、延迟加载与流式按需读取:
dotnet run --project src/quire-cli -c Release -- package -project examples/quire.project.yml
dotnet run --project examples/Quire.Package.Examples.csproj -c Release -- examples/dist
固定 property=value Meta
player.png 对应 player.png.meta。没有 sidecar 表示没有 Meta,空 sidecar 表示存在空 Meta。
name=player
offsetX=-16
scale=1.0
visible=true
tags=["hero","blue"]
frames=[1,2,3]
weights=[0.25,0.75]
enabled=[true,false]
code:string=001
emptyIds:int64[]=[]
只支持 string、int64、double、bool 及其各自数组。每行一个属性,使用第一个 = 分隔;空行和以 # 开始的整行注释被忽略。值内的 =、# 保留。字符串可以不加引号;双引号字符串和数组里的字符串使用标准 JSON 字符串转义,但不接受 JSON 对象作为另一种 Meta 文件格式。
未标注的整数是 int64,小数和指数形式是 double,true/false 是 bool,其余普通文本是 string。显式类型使用 name:type=value。未标注空数组是 string[],其他空数组必须标注类型。数值数组提升为 double[] 时不允许整数精度丢失。禁止重复键、非有限浮点数、对象、嵌套数组、混合类型数组和 null 元素。字符串 null 本身可以作为普通文本。
源 sidecar 和编码后的 Meta 分别限制为 1 MiB,键名最多 1024 UTF-8 字节。编码按 UTF-8 键名排序,调整排版或行顺序不会产生补丁。运行时使用专用二进制字段表,不依赖序列化器或反射。
.assetignore
项目根目录的 .assetignore 应用于每个源目录的相对路径;源目录及子目录中的规则追加生效。支持 *、?、**、!、根锚定 /、目录后缀 /、整行注释及开头的 \# / \! 转义。
**/*.tmp
**/*.psd
!textures/keep.psd
draft/
已排除的目录直接剪枝;重新包含子文件需要先包含其父目录。规则区分大小写。当前项目的 .asset/、输出目录、项目配置和规则文件不作为资源。符号链接和 junction 不参与扫描。忽略资源时其 Meta 一并忽略;单独忽略 sidecar 等价于本次源没有 Meta。未被忽略的孤立 sidecar 报错,扫描/权限错误使构建失败。
Tag 和增量构建
quire-cli package -project ./quire.project.yml
quire-cli package -project ./quire.project.yml -base-tag <TagID>
quire-cli package -project ./quire.project.yml -pwd "your-password"
quire-cli diff -project ./quire.project.yml -base-tag <TagID>
quire-cli tags -project ./quire.project.yml
quire-cli inspect ./dist
quire-cli verify ./dist -pwd "your-password"
每次成功构建生成 GUID TagId。指定 -base-tag 时,以该 Tag 的有效资源清单比较内容 SHA-256、规范化 Meta 摘要、分包位置和编码策略。删除源文件不生成删除记录;仅删除 sidecar 不移除旧 Meta。完整内容替换同时替换该资源的 Meta 状态。Meta-only 记录替换整份 Meta,不合并字段。编码策略或加密凭据变化会重新写入相关内容。
增量是文件级的;大文件内容变化会重新写入整个文件。扫描默认重新计算内容摘要,不仅依赖时间戳。实际打包再次计算摘要,源内容变化时失败。发布构建应使用稳定的源目录;各文件的读取检查不等同于文件系统原子快照。
构建状态固定在配置文件旁的 .asset/:
.asset/
tags/<TagId>/tag.json 构建记录
tags/<TagId>/files.idx 完整有效清单
temp/ 临时索引
key.salt 加密凭据指纹的派生盐(加密项目)
build.lock 项目构建互斥
dist/<TagId>/<name>.asset
Tag 记录保存继承后有效的资源状态,不建立运行时依赖图。同一构建的分包共享 TagId 和 UTC 时间。本地时间比已有 Tag 小时递增到最新 Tag 之后;跨机器构建应保持系统时钟一致。
包先写入临时文件,完成校验、头部及持久化刷新后重命名。分包在暂存目录构建完毕后发布整个 Tag 输出目录,最后提交本地 Tag。失败不发布 Tag;若输出已完成但 Tag 提交失败,CLI 报告保留的完整产物位置。无变化构建仍创建 Tag,但不输出空补丁。
解包
quire-cli unpackage ./dist ./unpacked
quire-cli unpackage ./encrypted-dist ./unpacked -pwd "your-password" -jobs 8
quire-cli unpackage ./encrypted-dist ./unpacked -pwd-env QUIRE_KEY -jobs 4
package 替代原来的 build 命令,原命令名不再接受。unpackage 的两个位置参数依次是资源包目录和目标目录,不需要项目配置。源目录递归加载 .asset,按包头时间和相对文件名顺序应用覆盖,导出最终有效的资源视图。解包完整增量版本时,需要将基础包和相关补丁一起放在源目录中;仅有 Meta-only 记录而无内容的路径不会被导出。
文件按包内路径还原,例如 common/data/player.png 输出为 unpacked/common/data/player.png。有 Meta 时生成对应的 player.png.meta,仍使用 property=value 格式,以类型标注保留八种类型、空数组及浮点精度;空 Meta 导出为空 sidecar,没有 Meta 则不生成 sidecar。注释、原始排版和源目录分组不保存在包中,因此不会还原。再次打包时,可以将解包目录设为源目录并使用空 prefix,避免重复添加路径前缀。
目标必须是不存在或为空的目录,且与源目录互不包含。解包通过流式读取写入目标旁的暂存目录,同时验证每个导出文件的完整 SHA-256 和加密块认证;全部成功后重命名发布。每个导出文件只读取一遍,内存不随单个资源文件大小增长,支持超过 4 GiB 的文件。取消或失败会等待并发任务退出并清理暂存内容,已有目标文件不会被覆盖。源、目标及其祖先目录中的符号链接/junction 不受支持;当前文件系统无法表示的名称或文件/目录冲突会报错。
unpackage -jobs N 控制同时解包的资源文件数,范围为 1–256,默认取逻辑处理器数与 8 的较小值。每个任务独立读取、解压、解密、校验并写出文件及 Meta,单文件仍按块顺序流式处理。-jobs 1 可用于顺序解包。解包校验最终有效资源;如需检查被覆盖的历史内容,使用 verify。
目录加载与读取
using Quire.Package;
using var assets = await AssetPackageSet.OpenDirectoryAsync("./dist",
new AssetReadOptions { Password = password }, cancellationToken);
AssetInfo info = assets.GetInfo("common/data/player.png");
AssetMetadata meta = await assets.ReadMetadataAsync(info.Path, cancellationToken);
long offsetX = meta.GetInt64("offsetX");
using AssetData loaded = await assets.ReadAsync(info.Path, cancellationToken);
ReadOnlyMemory<byte> bytes = loaded.Data;
// 大文件:流或范围读取,长度和偏移均为 long。
using Stream stream = assets.OpenRead("video/intro.mp4");
int count = await assets.ReadAtAsync("video/intro.mp4", offset, destination, cancellationToken);
默认递归扫描 .asset 文件;跳过 .asset 状态目录、以 .tmp 结尾的暂存目录和符号链接。Recursive=false 可限制为当前目录。正式包损坏、缺密钥或不可读会使打开失败,并报告具体文件。
排序先按包头时间,再按相对文件路径的 Ordinal 顺序。较晚内容记录覆盖内容与 Meta,较晚 Meta-only 记录只覆盖 Meta。找不到任何内容的孤立 Meta-only 路径不会成为可读资源。枚举返回有效文件,目录由路径前缀查询,不维护空目录记录。
未出现在补丁中的路径保持已加载的状态。例如先加载 A(a=1)、B(a=2),再加载基于 A 生成且省略 a 的 C,结果仍为 a=2。运行库不会推断应移除哪些包;连续发布通常以上次发布 Tag 为比较基准。
同一个集合支持多线程和原生异步读取。各流位置独立;同一流禁止重叠 Read/Seek/Dispose。关闭集合后拒绝新操作,已经打开的流/枚举继续持有底层文件租约。AssetData 使用池化缓冲,Dispose 后 Data 失效;Meta 为独立不可变对象,可以继续使用。
Meta 的 Get/TryGet 为明确类型访问。数值及布尔数组返回只读 Span,字符串数组返回只读集合。数值字段访问不装箱、不分配;字符串按需解码并缓存在该 Meta 对象内。
MaxBufferedAssetBytes 默认 32 MiB,是单次完整加载的限制,不是并发总内存限制。索引常驻上限默认每包 64 MiB,超过则分页;页缓存每包默认 8 MiB,Meta 缓存整个集合默认 4 MiB 编码字节,解码字符串和调用者持有的结果另占内存。
完整缓冲读取检查内容 SHA-256。局部/流读取验证块结构及加密认证,完整内容校验使用 Verify/VerifyAsync,它会检查所有物理包,包括被后续包覆盖的内容。
加密与路径保护
CLI 参数统一使用单横线,例如 -project ./quire.project.yml、-jobs 5。package、diff、unpackage、inspect 和 verify 均支持直接传入 -pwd "your-password",也可以使用 -pwd-env VARIABLE,两者不能同时指定。支持 -pwd=VALUE 语法,以 - 开头的密码使用这种写法。显式密码选项不能是空值,CLI 不会在日志或构建记录中保存密码。
package 和 diff 的密码选项覆盖 quire.project.yml 的 encryption.key-environment;未指定时继续从配置的环境变量读取。是否加密仍由 encryption.enabled 控制,在关闭加密的项目中传入密码选项会报错。读取和解包命令无需项目配置,直接使用传入的密码来源。
资源内容可选 AES-256-GCM。密码只在打开每个物理包时通过 PBKDF2-SHA256(600000 次)派生;各包使用独立随机盐。内容、索引和 Meta 使用独立域和分组子密钥。不同包密码可通过 PasswordProvider(AssetPackageInfo) 提供。
未加密时,路径、字段名和 Meta 值仍通过公开参数派生的 AES-GCM 密钥编码,避免磁盘区域直接出现明文。这个公开模式是可逆保护,不是保密或发布者认证。持有读取器的人可以恢复这些数据。真正保密需要启用加密并提供外部密码;公开 TagId、时间及必要布局字段用于加载。
并行构建与性能
package -jobs 控制压缩/加密工作线程;源文件读取并发固定为内部默认值 4,数据写入并发为 1,不单独暴露 CLI 参数。单个大文件也会分块进入共同的工作队列。quire.project.yml 的 build.memory-mib 限制工作缓冲配置,默认 128 MiB,范围 8–65536;资源清单、路径和源 Meta 的内存随记录数增长,另行计算。所选并发与块大小超出预算时会报错。
build.block-size 支持 65536、131072、262144、524288、1048576,默认 262144。这两个设置只从 YAML 读取,不提供对应 CLI 参数。改变块大小会重写相关资源,单纯改变内存预算不会产生内容补丁。数据偏移和块表均支持 64 位;当前实现支持 little-endian .NET 平台,超大包建议 64 位进程。
读取后端基准和结论见 benchmarks/README.md,字节布局见 FORMAT.md。
默认 ReadMode = AssetReadMode.RandomAccess。实测热缓存下未加密随机读取获益明显的场景可显式使用 AssetReadMode.MemoryMapped。映射按需由操作系统调页,资源内容仍通过受控缓冲访问;映射后端的异步读取可能同步完成,页错误也可能阻塞调用线程。加密并发与冷盘场景应按实际负载选择。
NuGet 工具与 Native AOT 发布
NuGet 工具和独立原生程序共用同一套命令。项目默认启用 AOT;生成跨平台托管 NuGet 工具时显式关闭 AOT,该工具使用 .NET 10 运行时:
dotnet pack src/quire-cli/quire-cli.csproj -c Release -p:PublishAot=false -o artifacts/packages
dotnet tool install quire-cli --tool-path artifacts/quire-tool --add-source artifacts/packages --version 1.0.0
发布为 Native AOT 独立单文件:
dotnet publish src/quire-cli/quire-cli.csproj -c Release -r win-x64 -p:PublishProfile=NativeAot -o artifacts/native/win-x64
产物为 quire-cli.exe,无需安装 .NET 运行时。在 Linux 本机使用 -r linux-x64,产物名为 quire-cli;Native AOT 需要在对应操作系统上构建。Windows 需要 Visual Studio 的“使用 C++ 的桌面开发”工作负载(MSVC 链接器和 Windows SDK);Linux 需要 clang 与 zlib 开发包。平台条件见 Native AOT 编译前提。
CLI 的 JSON 读写使用编译期生成的类型信息,默认关闭 JSON 反射序列化;项目模板嵌入可执行文件。Native AOT 本身生成独立原生可执行文件,不再叠加托管单文件打包选项。上述命令生成本地发布产物,NuGet 服务器推送仍是独立发布步骤。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 57 | 10/27/2026 |