From 99aa282582496787ea866616fd2bebb182bdcf1d Mon Sep 17 00:00:00 2001
From: perditavojo <117562794+perditavojo@users.noreply.github.com>
Date: Sat, 23 May 2026 22:19:55 +0800
Subject: [PATCH 1/2] =?UTF-8?q?fix(gameinput):=20=E4=BF=AE=E6=AD=A3=20nati?=
=?UTF-8?q?ve=20shim=20=E5=96=AE=E6=AA=94=E7=99=BC=E5=B8=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
改用 ResolvedFileToPublish 將 GameInput native shim 納入 self-contained single-file bundle,並新增 bundle guard 與 release 輸出檢查,避免發布成缺少 shim 的單檔。
---
.github/workflows/release.yml | 17 ++++++++++++++
src/InputBox.GameInput.Native/README.md | 4 +++-
src/InputBox/InputBox.csproj | 31 +++++++++++++++++++++----
3 files changed, 47 insertions(+), 5 deletions(-)
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/src/InputBox.GameInput.Native/README.md b/src/InputBox.GameInput.Native/README.md
index 2312f19..d389087 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` 發佈時把 Release shim 加入 `ResolvedFileToPublish`,並以 `AssetType=native` 納入 self-contained single-file bundle。
+- `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'" />
+
From 30e9e861a7c99f66a7e08f9fdf45a120139819dc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 23 May 2026 22:52:09 +0000
Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E4=BF=AE=E6=AD=A3=20GameInput=20na?=
=?UTF-8?q?tive=20shim=20=E7=99=BC=E4=BD=88=E8=AA=AA=E6=98=8E=E8=88=87=20I?=
=?UTF-8?q?ncludeNativeLibrariesForSelfExtract=20=E5=8F=83=E6=95=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Agent-Logs-Url: https://github.com/rubujo/InputBox/sessions/dc7cf28c-5f6a-4105-89fc-c0355cb258c1
Co-authored-by: perditavojo <117562794+perditavojo@users.noreply.github.com>
---
README.md | 3 ++-
src/InputBox.GameInput.Native/README.md | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
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 d389087..ac3a83f 100644
--- a/src/InputBox.GameInput.Native/README.md
+++ b/src/InputBox.GameInput.Native/README.md
@@ -69,7 +69,7 @@ DLL 載入規則必須維持保守:
## 建置與發佈
- 原生 shim 由 `InputBox.GameInput.Native.vcxproj` 建置。
-- `src/InputBox/InputBox.csproj` 會在 `win-x64` 發佈時把 Release shim 加入 `ResolvedFileToPublish`,並以 `AssetType=native` 納入 self-contained single-file bundle。
+- `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 全部存在。