Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ jobs:
-p:PublishReadyToRun=true
-o out

- name: 驗證單檔發佈輸出
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$exePath = Join-Path "${{ env.PUBLISH_DIR }}" "${{ env.EXE_NAME }}"
$nativeShimPath = Join-Path "${{ env.PUBLISH_DIR }}" "${{ env.NATIVE_SHIM_NAME }}"

if (-not (Test-Path $exePath)) {
Write-Error "找不到單檔發佈執行檔:$exePath"
}

if (Test-Path $nativeShimPath) {
Write-Error "單檔發佈輸出不應包含可見的 GameInput native shim sidecar:$nativeShimPath"
}

Write-Host "單檔發佈輸出驗證通過:GameInput native shim 已由 MSBuild bundle guard 驗證,且未留下 sidecar DLL。"

- name: 自動產生第三方套件授權聲明(nuget-license)
shell: pwsh
run: |
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,14 +508,15 @@ HOST_LC_ALL=<locale> %command%
請開啟終端機或命令提示字元,並切換至原始碼目錄(即 `src\InputBox` 資料夾下),執行以下指令:

```bash
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:PublishReadyToRun=true
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:PublishReadyToRun=true
```

**參數說明:**
- `-c Release`:以 Release 模式進行建置。編譯器會對程式碼進行最大程度的最佳化,並移除除錯資訊,使應用程式執行速度更快、資源佔用更低。
- `-r win-x64`:指定目標執行階段為 Windows 64 位元作業系統。
- `--self-contained true`:啟用獨立式部署。這會將底層的 .NET 執行階段與應用程式一併打包,使用者**無需在電腦上預先安裝任何 .NET 環境**即可直接執行。
- `-p:PublishSingleFile=true`:啟用單一檔案發佈。會將應用程式本身及其所有依賴的函式庫全部打包進單一個 `.exe` 執行檔中,讓資料夾保持乾淨,方便使用者複製或分享。
- `-p:IncludeNativeLibrariesForSelfExtract=true`:讓 .NET host 在執行階段自動將 bundle 中的原生程式庫(例如 `InputBox.GameInput.Native.dll`)自解壓後載入。**win-x64 單一檔案發佈時此參數為必要項**,省略將導致 MSBuild 建置錯誤。
- `-p:PublishReadyToRun=true`:啟用 ReadyToRun 預先編譯。這會在建置時提前將部分程式碼編譯為原生機器碼,減少執行時即時編譯的負擔,能**顯著縮短應用程式的冷啟動時間**,讓喚出輸入框的反應更迅速。

發佈完成後,編譯好的單一執行檔會生成在以下路徑:
Expand Down
4 changes: 3 additions & 1 deletion src/InputBox.GameInput.Native/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ DLL 載入規則必須維持保守:
## 建置與發佈

- 原生 shim 由 `InputBox.GameInput.Native.vcxproj` 建置。
- `src/InputBox/InputBox.csproj` 會把 Release shim 以原生程式庫形式納入單檔發佈。
- `src/InputBox/InputBox.csproj` 會在 `win-x64` 發佈時把對應組態(`$(Configuration)`)的 shim 加入 `ResolvedFileToPublish`,並以 `AssetType=native` 納入 self-contained single-file bundle;建議使用 Release 組態發佈。
- `InputBox.GameInput.Native.dll` 不應以 `NativeLibrary` item 發佈;該 item 不會保證進入 .NET single-file 的 `FilesToBundle` 清單。
- `PublishSingleFile=true` 時必須同時設定 `IncludeNativeLibrariesForSelfExtract=true`,讓 bundled native shim 在執行階段由 .NET host 自解壓後載入。
- CI 與 release 在原生 shim 建置後必須執行 `tools/Validate-GameInputNativeShim.ps1`,確認 `GameInputNativeMethods` 使用的 `InputBoxGameInput*` exports 全部存在。
Comment thread
perditavojo marked this conversation as resolved.
- 同一支驗證腳本也會呼叫 `InputBoxGameInputProbeRuntime` 做無硬體 smoke test;GameInput runtime 初始化可成功或失敗,但 probe 必須可安全回報 ABI,且 native 回報的指標大小與跨 ABI 結構大小必須與受控端 mirror 相符。
- 若 GameInput runtime 可用,驗證腳本會再執行 native lifecycle stress smoke,反覆建立 context、註冊/解除回呼、重新整理裝置與銷毀 context。runtime 不可用時此壓力測試可略過,但 export/probe 驗證仍必須通過。
Expand Down
31 changes: 27 additions & 4 deletions src/InputBox/InputBox.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<Copyright>在法律允許的最大範圍內,作者已放棄所有著作權及相關權利(CC0 1.0)</Copyright>
<GameInputNativeShimProject>..\InputBox.GameInput.Native\InputBox.GameInput.Native.vcxproj</GameInputNativeShimProject>
<GameInputNativeShimPath>..\InputBox.GameInput.Native\bin\x64\$(Configuration)\InputBox.GameInput.Native.dll</GameInputNativeShimPath>
<GameInputNativeShimFileName>InputBox.GameInput.Native.dll</GameInputNativeShimFileName>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down Expand Up @@ -73,15 +74,37 @@
SkipUnchangedFiles="true" />
</Target>

<Target Name="RequireGameInputNativeShimSelfExtract"
BeforeTargets="ComputeResolvedFilesToPublishList"
Condition="'$(RuntimeIdentifier)' == 'win-x64' and '$(PublishSingleFile)' == 'true'">
<Error Condition="'$(IncludeNativeLibrariesForSelfExtract)' != 'true'"
Text="InputBox.GameInput.Native.dll must be bundled as a native library. Set IncludeNativeLibrariesForSelfExtract=true for win-x64 single-file publish." />
</Target>

<Target Name="IncludeGameInputNativeShimForPublish"
BeforeTargets="ComputeFilesToPublish"
Condition="'$(OS)' == 'Windows_NT' and Exists('$(VCTargetsPath)\Microsoft.Cpp.Default.props')">
BeforeTargets="ComputeResolvedFilesToPublishList"
Condition="'$(OS)' == 'Windows_NT' and '$(RuntimeIdentifier)' == 'win-x64'">
<Error Condition="!Exists('$(GameInputNativeShimPath)')"
Text="GameInput native shim not found at '$(GameInputNativeShimPath)'. Build $(GameInputNativeShimProject) before publish." />
<ItemGroup>
<NativeLibrary Include="$(GameInputNativeShimPath)"
CopyToPublishDirectory="PreserveNewest" />
<ResolvedFileToPublish Include="$(GameInputNativeShimPath)">
<RelativePath>$(GameInputNativeShimFileName)</RelativePath>
<AssetType>native</AssetType>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>

<Target Name="VerifyGameInputNativeShimSingleFileBundle"
AfterTargets="PrepareForBundle"
BeforeTargets="GenerateSingleFileBundle"
Condition="'$(RuntimeIdentifier)' == 'win-x64' and '$(PublishSingleFile)' == 'true'">
<ItemGroup>
<_GameInputNativeShimBundleItem Include="@(FilesToBundle)"
Condition="'%(FilesToBundle.RelativePath)' == '$(GameInputNativeShimFileName)' and '%(FilesToBundle.AssetType)' == 'native'" />
</ItemGroup>
<Error Condition="'@(_GameInputNativeShimBundleItem)' == ''"
Text="GameInput native shim was not included in the single-file bundle as a native asset." />
</Target>

<ItemGroup>
Expand Down
Loading