# wkbre Linux 系統下跨 Windows(MinGW) 平台源碼建構筆記 學習如何將 [wkbre 軟體](https://github.com/AdrienTD/wkbre/tree/master)跨平台源碼建構至 Windows(MinGW) 平台 [TOC] ## 智慧財產授權條款 除另外標註之內容外本作品的內容以[《Creative Commons 姓名標示-相同方式分享》授權條款第 4.0 國際版](https://creativecommons.org/licenses/by-sa/4.0/deed.zh_TW)或其任意更近期版本釋出供大眾*於授權範圍內*自由使用 ## 重現環境 以下說明應該能重現本筆記之結果的環境細節: ### 作業系統 Ubuntu 23.10 AMD64 ### wkbre [第 c58f5fff <ruby>修訂版<rp>(</rp><rt>revision</rt><rp>)</rp></ruby>](https://github.com/AdrienTD/wkbre/commit/c58f5fffeed624c7fc4f36801bb30ea72668aece) ### CMake 3.27.4-1(來源:Ubuntu 23.10 軟體庫) ### MinGW-w64 <ruby>工具鏈<rp>(</rp><rt>toolchain</rt><rp>)</rp></ruby> 12.3.0-9ubuntu1+25.3(來源:Ubuntu 23.10 軟體庫) ## 操作過程 以下說明重現本筆記成果的操作過程: ### 啟動一文字界面終端機應用軟體 本筆記撰寫當下使用的是 KDE 桌面環境得 Konsole 應用軟體 ### 切換作業目錄至要存放 wkbre 軟體源碼的目錄 執行下列命令以切換作業目錄至要存放 wkbre 軟體源碼的目錄: ```bash cd /path/to/wkbre/srcdir/hosting/folder ``` ### 將 wkbre 軟體的 Git <ruby>版控庫<rp>(</rp><rt>repository</rt><rp>)</rp></ruby><ruby>拓製<rp>(</rp><rt>clone</rt><rp>)</rp></ruby>到本地 執行下列命令將 wkbre 軟體的 Git 版控庫拓製到本地: ```bash git clone https://github.com/AdrienTD/wkbre.git ``` 您可以使用 `--depth` `git clone` 命令選項來限縮獲取的變更歷史深度 ### 切換<ruby>作業目錄<rp>(</rp><rt>working directory</rt><rp>)</rp></ruby>至 wkbre 軟體的<ruby>來源程式碼<rp>(</rp><rt>source code</rt><rp>)</rp></ruby>目錄 執行下列命令以切換作業目錄至 wkbre 軟體的來源程式碼目錄: ```bash cd wkbre ``` ### <ruby>已知問題規避方案<rp>(</rp><rt>WORKAROUND</rt><rp>)</rp></ruby>:修正 bzip2 子目錄不適當的 CMakeLists.txt 檔案名稱 因 bzip2 子目錄的 CMakeLists.txt 檔案於區分大小寫的作業系統(如 Linux)下會無法被 CMake 讀到故需要執行下列命令手動修正檔案名稱: ```bash mv bzip2/CMakeLists.{TXT,txt} ``` :::info **附註:** * `{TXT,txt}` 為 Bash 的<ruby>曲括號展開<rp>(</rp><rt>brace expansion</rt><rp>)</rp></ruby>語法 * 此修正已提交為 [Fix Linux MinGW cross-build incompatibilities by brlin-tw · Pull Request #1 · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/pull/1) 上游專案合併請求的一部分 ::: ### 已知問題規避方案:修正不適當的<ruby>標頭檔案<rp>(</rp><rt>header file</rt><rp>)</rp></ruby>檔案路徑 因源碼引用的 C/C++ 程式語言標頭檔案於區分大小寫以及使用正斜線(/)作為檔案路徑目錄分隔符的作業系統(如 Linux)下會無法被 C/C++ 預處理器讀到故需要執行下列命令手動修正檔案路徑: ```bash find_opts=( # 比對完整檔案名稱(whole file name)(即路徑) -path ./build # 上述目錄表達式不走訪 -prune -or # 比對普通檔案 -type f # 比對下列任一不區分大小寫的 C/C++ 程式碼檔案名稱式樣 '(' -iname '*.c' -or -iname '*.h' -or -iname '*.cpp' -or -iname '*.hpp' ')' # 輸出的檔案路徑序列以空字元(null character)分隔以避免特殊檔案名稱影響執行結果 -print0 ) xargs_opts=( # 輸入的資料為以空字元分隔的檔案路徑序列 --null # 印出會被執行的命令以方便查看整個命令流水線(command pipeline)的行為 --verbose # 宣告後方的位置依賴引數(positional arguments)均非 xargs 的命令選項 -- ) sed_opts=( # 直接修改檔案而非輸出到標準輸出裝置(stdout) --in-place # 使用較為通用的擴展版正規表達式(E.R.E.)而非基本版正規表達式(B.R.E.)語法 --regexp-extended # 修正大小寫不正確的標頭檔路徑 --expression='s@^#include[[:space:]]+<Windows.h>@#include <windows.h>@g' --expression='s@^#include[[:space:]]+<gl/gl\.h>@#include <GL/gl.h>@g' --expression='s@^#include[[:space:]]+<gl/glu\.h>@#include <GL/glu.h>@g' # 修正目錄分隔符不正確的標頭檔路徑 --expression='s@^#include[[:space:]]+"..\\global\.h"@#include "../global.h"@g' ) find . "${find_opts[@]}" \ | xargs "${xargs_opts[@]}" \ sed "${sed_opts[@]}" ``` :::info **附註:** 此修正已提交為 [Fix Linux MinGW cross-build incompatibilities by brlin-tw · Pull Request #1 · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/pull/1) 上游專案合併請求的一部分 ::: ### 已知問題規避方案:修正不適當的 Resource Compiler 輸入檔中的檔案路徑 因 Resource Compiler 輸入檔參照的外部檔案路徑於使用正斜線(/)作為檔案路徑目錄分隔符的作業系統(如 Linux)下會無法被 `windres` 程序讀到故需要執行下列命令手動修正檔案路徑: ```bash sed_opts=( # 直接修改檔案而非輸出到標準輸出裝置(stdout) --in-place # 使用較為通用的擴展版正規表達式(E.R.E.)而非基本版正規表達式(B.R.E.)語法 --regexp-extended # 修正目錄分隔符不正確的資源檔案路徑 --expression='s@\.\\\\icon\.ico@./icon.ico@g' --expression='s@redata\\@redata/@g' ) sed "${sed_opts[@]}" wkbre.rc ``` :::info **附註:** 此修正已提交為 [Fix Linux MinGW cross-build incompatibilities by brlin-tw · Pull Request #1 · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/pull/1) 上游專案合併請求的一部分 ::: ### 已知問題規避方案:套用 ImVec4 資料類型變數傳入程式修正 1. 於<ruby>當前作業目錄<rp>(</rp><rt>current working directory</rt><rp>)</rp></ruby>創建一 fix-imvec4-rvalue-type.patch <ruby>程式修正檔<rp>(</rp><rt>patch file</rt><rp>)</rp></ruby>,新增下列內容後保存: ```diff diff --git a/wkbre.cpp b/wkbre.cpp index 1f2b2dc..6c65000 100644 --- a/wkbre.cpp +++ b/wkbre.cpp @@ -2401,7 +2401,8 @@ bool IGPlayerChooser(char *popupid, goref *p) ImGui::AlignTextToFramePadding(); if (!p->valid()) { - OldColorButton("color", ImVec4(1, 1, 1, 1)); + ImVec4 color(1, 1, 1, 1); + OldColorButton("color", color); ImGui::SameLine(); ImGui::Text("Click me to select a player."); } ``` 1. 執行下列命令以套用程式修正: ```bash patch_opts=( # 將程式修正檔中的檔案路徑移除一個路徑組成元件 --strip=1 ) patch "${patch_opts[@]}" <fix-imvec4-rvalue-type.patch ``` :::info **附註:** 本修正與 [draft: Fix "cannot bind non-const lvalue reference of type ‘ImVec4&’ to an rvalue of type ‘ImVec4’" compilation error by brlin-tw · Pull Request #2 · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/pull/2/commits/da17ecf199bd8757c896faf81b515588c15321f9) 上游專案合併請求效果等價 ::: ### 創建<ruby>軟體建構用檔案存放目錄<rp>(</rp><rt>build directory</rt><rp>)</rp></ruby> 為避免源碼建構用檔案與軟體源碼檔案混在一起,執行下列命令以創建軟體建構用檔案存放目錄: ```bash mkdir_opts=( # 在目錄(及其親目錄)已存在情境下不報錯 --parents ) mkdir "${mkdir_opts[@]}" build ``` ### 切換作業目錄至軟體建構用檔案存放目錄 執行下列命令以切換作業目錄至軟體建構用檔案存放目錄: ```bash cd build ``` ### 安裝 CMake 軟體建構系統檔案生成器 *以 root 身份*執行下列命令以安裝 CMake 軟體建構系統檔案生成器: ```bash apt install cmake ``` ### 安裝 MinGW-w64 跨平台軟體建構工具鏈 *以 root 身份*執行下列命令以安裝 MinGW-w64 跨平台軟體建構工具鏈: ```bash apt install mingw-w64 ``` ### 設計 MinGW-w64 的 CMake <ruby>工具鏈定義檔<rp>(</rp><rt>toolchain file</rt><rp>)</rp></ruby> 於當前作業目錄創建一 TC-mingw.cmake 檔案,新增下列內容後保存: ```cmake # CMake toolchain file for cross-compiling in MinGW # Cross Compiling With CMake — Mastering CMake # https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-win32) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-win32) # where is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) # adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) ``` ### 產生軟體建構系統檔案 執行下列命令以產生 GNU Make 軟體建構系統的建構規則檔: ```bash cmake_opts=( # 定義 `CMAKE_TOOLCHAIN_FILE` CMake 快取項目的值 -DCMAKE_TOOLCHAIN_FILE=TC-mingw.cmake # 不編入測試邏輯 -DWKBRE_RELEASE=TRUE ) cmake "${cmake_opts[@]}" .. ``` :::info 您可以透過 `-G` `cmake` 命令選項以指定其他軟體建構系統(如 Ninja)的源碼建構用檔案 ::: ### 建構軟體 執行下列命令以開始進行軟體建構: ```bash make_opts=( # 使用系統中央處理器(CPU)的執行緒數進行平行建構 --jobs="$(nproc)" ) make "${make_opts[@]}" ``` 順利的話您應可以於命令輸出中看到軟體主程式被成功建構: ```output ...stripped... [ 92%] Building CXX object CMakeFiles/wkbre.dir/script/value.cpp.obj wkbre/script/objCreation.cpp:28:44: warning: multi-character character constant [-Wmultichar] 28 | if( *((uint*)(word[0])) == '_DNE' ) | ^~~~~~ [ 94%] Building CXX object CMakeFiles/wkbre.dir/imgui/imgui_demo.cpp.obj [ 95%] Building CXX object CMakeFiles/wkbre.dir/imgui/imgui_draw.cpp.obj wkbre/script/package.cpp:29:44: warning: multi-character character constant [-Wmultichar] 29 | if( *((uint*)(word[0])) == '_DNE' ) | ^~~~~~ [ 97%] Building CXX object CMakeFiles/wkbre.dir/imgui/imgui_widgets.cpp.obj [ 98%] Building RC object CMakeFiles/wkbre.dir/wkbre.rc.res [100%] Linking CXX executable wkbre.exe [100%] Built target wkbre ``` 且可於當前作業目錄中看到被建構的軟體主程式檔案: ```output $ ls -l total 2052 ...stripped... -rwxrwxr-x 1 brlin brlin 2012049 Jan 7 20:51 wkbre.exe ``` ### 引入執行時期需要的 Windows 程式庫 執行下列命令引入執行時期所需要的 Windows 程式庫: ```bash ln_opts=( # 創建象徵式連結(symbolic link)而非硬連結(hard link) --symbolic # 如果連結以存在就直接取代 --force ) # 將指定的檔案於當前作業目錄創建同名的象徵式連結 ln "${ln_opts[@]}" \ /usr/lib/gcc/x86_64-w64-mingw32/12-win32/libgcc_s_seh-1.dll \ /usr/lib/gcc/x86_64-w64-mingw32/12-win32/libstdc++-6.dll \ . ``` :::info **注意:** 如果您要將軟體複製到其他系統使用請改用 `cp` 命令複製完整的程式庫檔案 ::: ### 安裝 Wine Windows API 相容層 *以 root 身份*執行下列命令以安裝 Wine Windows API 相容層: ```bash apt install wine ``` ### 執行建構好的軟體 執行下列命令即可嘗試執行建構好的軟體: ```bash wine wkbre.exe ``` ![缺少遊戲資料檔案的錯誤對話框的螢幕截圖](https://hackmd.io/_uploads/HJEI-QudT.png "缺少遊戲資料檔案的錯誤對話框的螢幕截圖") ## 常用操作 以下說明進行本筆記之操作時可能會用到的常用操作: ### 移除 Git 版控庫所有未被版本控制系統追蹤(untracked)的檔案 1. 切換作業目錄至 Git 版控庫的<ruby>作業副本<rp>(</rp><rt>working copy</rt><rp>)</rp></ruby>目錄中 1. 執行下列命令以移除 Git 版控庫所有<ruby>未被版本控制系統追蹤<rp>(</rp><rt>untracked</rt><rp>)</rp></ruby>的檔案: ```bash git_clean_opts=( # 遞迴地移除未被版本控制系統追蹤的(untracked)目錄中的檔案 -d # 啟用檔案刪除功能 -f # 連同被(.gitignore 檔案/Git 配置)排除追蹤的檔案一起清理 -x ) git clean "${git_clean_opts[@]}" ``` ### 重設 Git 版控庫作業副本中尚未提交進版控庫的內容變更 1. 執行下列命令以切換作業目錄至 Git 版控庫的作業副本目錄中: ```bash cd /path/to/wkbre ``` 1. 執行下列命令以重設作業副本目錄中尚未提交進版控庫的內容變更: ```bash git_reset_opts=( # 除 HEAD 指標外還要重設作業副本中的被追蹤檔案內容 --hard ) git reset "${git_reset_opts[@]}" ``` ### 清理 GNU Make 軟體建構系統的<ruby>源碼建構中間產物<rp>(</rp><rt>intermediate build artifacts</rt><rp>)</rp></ruby> 1. 執行下列命令以切換作業目錄至 wkbre 軟體的軟體建構用檔案存放目錄中: ```bash cd /path/to/wkbre/build ``` 1. 執行下列命令以清理 GNU Make 軟體建構系統的源碼建構中間產物: ```bash make clean ``` ### 查看當前 Git 版本庫 HEAD 指標指向的修訂版與作業副本之間的內容差異 1. 執行下列命令以切換作業目錄至 Git 版控庫的作業副本目錄中: ```bash cd /path/to/wkbre ``` 1. 執行下列命令以查看當前 Git 版本庫 HEAD 指標指向的修訂版與作業副本之間的內容差異: ```bash git diff ``` ## 參考資料 以下列舉撰寫本文章期間所參考的第三方資料: * [wkbre/README.md at master · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/blob/master/README.md) 說明軟體的相關資訊與基本的源碼建構說明 * [wkbre/docs/codedoc.txt at master · AdrienTD/wkbre](https://github.com/AdrienTD/wkbre/blob/master/docs/codedoc.txt) 說明軟體的進一步源碼建構細節 * [Cross Compiling With CMake — Mastering CMake](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html) 說明如何使用 CMake 以進行跨 MinGW 平台建構 * git-clean(1) 的使用手冊頁面(manpage) 說明 `git clean` 命令的用途與相關命令選項 * cmake(1) 的使用手冊頁面(manpage) 說明 `cmake` 命令的用途與相關命令選項 * [Replace Text Recursively in Linux | ChatGPT](https://chat.openai.com/share/5d3bea6c-07fa-4445-a923-fea4f64ef904) 說明如何於 Linux 作業系統中遞迴地替換純文字文件的特定<ruby>式樣<rp>(</rp><rt>pattern</rt><rp>)</rp></ruby>的文字 * find(1) 的使用手冊頁面(manpage) 說明 `find` 命令的用途與相關命令選項 * xargs(1) 的使用手冊頁面(manpage) 說明 `xargs` 命令的用途與相關命令選項 * [Ubuntu – 軟體包內容搜尋結果 -- gl/gl.h](https://packages.ubuntu.com/search?searchon=contents&keywords=gl%2Fgl.h&mode=&suite=kinetic&arch=any) 列舉所有提供 gl/gl.h 結尾的檔案的 Ubuntu 軟體包 * [Ubuntu – 軟體包內容搜尋結果 -- gl/glu.h](https://packages.ubuntu.com/search?searchon=contents&keywords=gl%2Fglu.h&mode=&suite=kinetic&arch=any) 列舉所有提供 gl/glu.h 結尾的檔案的 Ubuntu 軟體包 * windres(1) 的使用手冊頁面(manpage) 說明 `windres` 命令的用途與相關命令選項 * [修正編譯器錯誤 | ChatGPT](https://chat.openai.com/share/81ac77f4-24df-4514-aff4-4a5f6de6e18f) 說明如何修正 `ImVec4` 資料類型變數傳入邏輯編譯報錯 --- 除另外標註之內容外本作品的內容以[《Creative Commons 姓名標示-相同方式分享》授權條款第 4.0 國際版](https://creativecommons.org/licenses/by-sa/4.0/deed.zh_TW)或其任意更近期版本釋出供大眾*於授權範圍內*自由使用 <style> /* 調大旁註文字的字元大小 */ rt{ font-size: 10pt; } </style>