7.7 KiB
7.7 KiB
构建与部署
所属项目: free-code .NET 10 重写 文档类型: 构建设计 来源章节: DESIGN-NET10-PART3.md § 23 上级文档: 测试与构建总览
概述
构建目标是跨 5 个平台的 AOT 原生二进制,输出单文件、无运行时依赖的可执行文件。MSBuild 通过 Directory.Build.props 统一管理全局属性,build.sh 封装多平台批量发布,install.sh 提供一键下载安装体验。
原始 TypeScript 项目使用 Bun 打包为单一 JavaScript bundle。.NET 重写的 AOT 路径在启动时间和内存占用上接近原生,同时消除了 Bun 运行时依赖。
23.1 MSBuild 配置
Directory.Build.props(全局属性)
所有子项目自动继承这些属性,无需在每个 .csproj 中重复声明。
<!-- Directory.Build.props -->
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>13.0</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<AotPublish>true</AotPublish>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>partial</TrimMode>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<EnableAotAnalyzer>true</EnableAotAnalyzer>
<Version>1.0.0</Version>
<AssemblyName>free-code</AssemblyName>
<RootNamespace>FreeCode</RootNamespace>
</PropertyGroup>
</Project>
关键属性说明:
| 属性 | 值 | 作用 |
|---|---|---|
AotPublish |
true |
启用 AOT 原生编译 |
PublishSingleFile |
true |
输出单一可执行文件 |
PublishTrimmed |
true |
裁剪未使用的程序集 |
TrimMode |
partial |
部分裁剪,保留反射入口点 |
JsonSerializerIsReflectionEnabledByDefault |
false |
强制使用 Source Generator 序列化 |
EnableAotAnalyzer |
true |
编译期检测 AOT 不兼容代码 |
LangVersion |
13.0 |
C# 13 特性(primary constructors、集合表达式等) |
FreeCode.csproj(主项目)
<!-- FreeCode.csproj (主项目) -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FreeCode.Core\FreeCode.Core.csproj" />
<ProjectReference Include="..\FreeCode.Engine\FreeCode.Engine.csproj" />
<ProjectReference Include="..\FreeCode.Tools\FreeCode.Tools.csproj" />
<ProjectReference Include="..\FreeCode.Commands\FreeCode.Commands.csproj" />
<ProjectReference Include="..\FreeCode.ApiProviders\FreeCode.ApiProviders.csproj" />
<ProjectReference Include="..\FreeCode.Mcp\FreeCode.Mcp.csproj" />
<ProjectReference Include="..\FreeCode.Lsp\FreeCode.Lsp.csproj" />
<ProjectReference Include="..\FreeCode.Bridge\FreeCode.Bridge.csproj" />
<ProjectReference Include="..\FreeCode.Services\FreeCode.Services.csproj" />
<ProjectReference Include="..\FreeCode.Tasks\FreeCode.Tasks.csproj" />
<ProjectReference Include="..\FreeCode.Skills\FreeCode.Skills.csproj" />
<ProjectReference Include="..\FreeCode.Plugins\FreeCode.Plugins.csproj" />
<ProjectReference Include="..\FreeCode.Features\FreeCode.Features.csproj" />
<ProjectReference Include="..\FreeCode.State\FreeCode.State.csproj" />
<ProjectReference Include="..\FreeCode.TerminalUI\FreeCode.TerminalUI.csproj" />
</ItemGroup>
</Project>
主项目引用全部 15 个子项目,自身仅包含 Program.cs 入口,所有业务逻辑分布在各子项目库中。
23.2 构建脚本
build.sh(多平台批量构建)
#!/bin/bash
# build.sh — 多平台构建
set -euo pipefail
VERSION="${1:-$(git describe --tags --always)}"
OUTPUT_DIR="./dist"
# 构建目标平台
PLATFORMS=(
"osx-arm64"
"osx-x64"
"linux-x64"
"linux-arm64"
"win-x64"
)
for PLATFORM in "${PLATFORMS[@]}"; do
echo "Building for $PLATFORM..."
RID="${PLATFORM}"
dotnet publish src/FreeCode/FreeCode.csproj \
-c Release \
-r "$RID" \
-o "$OUTPUT_DIR/$PLATFORM" \
/p:VersionPrefix="$VERSION" \
/p:AotPublish=true \
/p:PublishSingleFile=true \
/p:PublishTrimmed=true
# 重命名二进制
if [[ "$PLATFORM" == win-* ]]; then
mv "$OUTPUT_DIR/$PLATFORM/free-code.exe" \
"$OUTPUT_DIR/$PLATFORM/free-code-$VERSION-$PLATFORM.exe"
else
chmod +x "$OUTPUT_DIR/$PLATFORM/free-code"
mv "$OUTPUT_DIR/$PLATFORM/free-code" \
"$OUTPUT_DIR/$PLATFORM/free-code-$VERSION-$PLATFORM"
fi
echo "✓ $PLATFORM done"
done
echo "All builds complete in $OUTPUT_DIR/"
脚本逻辑说明:
- 版本号优先读取命令行参数,fallback 到
git describe --tags --always - 遍历 5 个 RID,每个平台独立调用
dotnet publish - 输出产物按
free-code-{VERSION}-{PLATFORM}格式命名 - Windows 平台保留
.exe后缀,其余平台添加可执行权限
23.3 安装脚本
install.sh(一键安装)
#!/bin/bash
# install.sh — 一键安装
set -euo pipefail
# 检测平台
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS-$ARCH" in
Darwin-arm64) PLATFORM="osx-arm64" ;;
Darwin-x86_64) PLATFORM="osx-x64" ;;
Linux-x86_64) PLATFORM="linux-x64" ;;
Linux-aarch64) PLATFORM="linux-arm64" ;;
*) echo "Unsupported platform: $OS-$ARCH"; exit 1 ;;
esac
INSTALL_DIR="$HOME/.free-code/bin"
mkdir -p "$INSTALL_DIR"
# 下载
BINARY_URL="https://github.com/paoloanzn/free-code/releases/latest/download/free-code-latest-$PLATFORM"
echo "Downloading free-code for $PLATFORM..."
curl -fsSL "$BINARY_URL" -o "$INSTALL_DIR/free-code"
chmod +x "$INSTALL_DIR/free-code"
# 添加到 PATH
if ! echo "$PATH" | grep -q "$INSTALL_DIR"; then
SHELL_RC="$HOME/.zshrc"
[ -f "$HOME/.bashrc" ] && SHELL_RC="$HOME/.bashrc"
echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> "$SHELL_RC"
echo "Added $INSTALL_DIR to PATH in $SHELL_RC"
fi
echo "✓ free-code installed to $INSTALL_DIR/free-code"
echo " Run 'free-code' to start"
安装流程:
- 通过
uname -s和uname -m检测当前平台 - 从 GitHub Releases 下载对应 RID 的预编译二进制
- 安装到
~/.free-code/bin/free-code - 自动检测 shell 配置文件(优先
.zshrc,fallback.bashrc)并追加 PATH
23.4 目标平台矩阵
| RID | 操作系统 | 架构 | 说明 |
|---|---|---|---|
osx-arm64 |
macOS | Apple Silicon | M1/M2/M3 Mac |
osx-x64 |
macOS | Intel x64 | Intel Mac |
linux-x64 |
Linux | x86-64 | 主流 Linux 服务器 |
linux-arm64 |
Linux | AArch64 | Raspberry Pi、AWS Graviton 等 |
win-x64 |
Windows | x64 | Windows 10/11 |
23.5 发布参数说明
| dotnet publish 参数 | 含义 |
|---|---|
-c Release |
Release 配置,开启优化 |
-r {RID} |
目标运行时,指定后产物为自包含 |
/p:AotPublish=true |
AOT 原生编译,消除 JIT 开销 |
/p:PublishSingleFile=true |
将所有资源打包为单一可执行文件 |
/p:PublishTrimmed=true |
裁剪未引用的程序集,减小体积 |
/p:VersionPrefix={VERSION} |
注入版本号到程序集元数据 |
AOT 编译将 IL 代码提前编译为目标平台原生机器码,启动时间从 JIT 模式的数百毫秒降至个位数毫秒,与原始 Bun 构建产物的冷启动时间相当。