diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b89cfca..ce047a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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: | diff --git a/README.md b/README.md index b95508c..7537236 100644 --- a/README.md +++ b/README.md @@ -508,7 +508,7 @@ HOST_LC_ALL= %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 ``` **參數說明:** @@ -516,6 +516,7 @@ dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile= - `-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 預先編譯。這會在建置時提前將部分程式碼編譯為原生機器碼,減少執行時即時編譯的負擔,能**顯著縮短應用程式的冷啟動時間**,讓喚出輸入框的反應更迅速。 發佈完成後,編譯好的單一執行檔會生成在以下路徑: diff --git a/src/InputBox.GameInput.Native/README.md b/src/InputBox.GameInput.Native/README.md index 2312f19..ac3a83f 100644 --- a/src/InputBox.GameInput.Native/README.md +++ b/src/InputBox.GameInput.Native/README.md @@ -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 全部存在。 - 同一支驗證腳本也會呼叫 `InputBoxGameInputProbeRuntime` 做無硬體 smoke test;GameInput runtime 初始化可成功或失敗,但 probe 必須可安全回報 ABI,且 native 回報的指標大小與跨 ABI 結構大小必須與受控端 mirror 相符。 - 若 GameInput runtime 可用,驗證腳本會再執行 native lifecycle stress smoke,反覆建立 context、註冊/解除回呼、重新整理裝置與銷毀 context。runtime 不可用時此壓力測試可略過,但 export/probe 驗證仍必須通過。 diff --git a/src/InputBox/InputBox.csproj b/src/InputBox/InputBox.csproj index 40a8d38..5d0a0c7 100644 --- a/src/InputBox/InputBox.csproj +++ b/src/InputBox/InputBox.csproj @@ -17,6 +17,7 @@ 在法律允許的最大範圍內,作者已放棄所有著作權及相關權利(CC0 1.0) ..\InputBox.GameInput.Native\InputBox.GameInput.Native.vcxproj ..\InputBox.GameInput.Native\bin\x64\$(Configuration)\InputBox.GameInput.Native.dll + InputBox.GameInput.Native.dll @@ -73,15 +74,37 @@ SkipUnchangedFiles="true" /> + + + + + BeforeTargets="ComputeResolvedFilesToPublishList" + Condition="'$(OS)' == 'Windows_NT' and '$(RuntimeIdentifier)' == 'win-x64'"> - + + $(GameInputNativeShimFileName) + native + PreserveNewest + + + + + + + <_GameInputNativeShimBundleItem Include="@(FilesToBundle)" + Condition="'%(FilesToBundle.RelativePath)' == '$(GameInputNativeShimFileName)' and '%(FilesToBundle.AssetType)' == 'native'" /> +