Try   HackMD

wkbre Linux 系統下跨 Windows(MinGW) 平台源碼建構筆記

學習如何將 wkbre 軟體跨平台源碼建構至 Windows(MinGW) 平台

智慧財產授權條款

除另外標註之內容外本作品的內容以《Creative Commons 姓名標示-相同方式分享》授權條款第 4.0 國際版或其任意更近期版本釋出供大眾於授權範圍內自由使用

重現環境

以下說明應該能重現本筆記之結果的環境細節:

作業系統

Ubuntu 23.10 AMD64

wkbre

第 c58f5fff 修訂版(revision)

CMake

3.27.4-1(來源:Ubuntu 23.10 軟體庫)

MinGW-w64 工具鏈(toolchain)

12.3.0-9ubuntu1+25.3(來源:Ubuntu 23.10 軟體庫)

操作過程

以下說明重現本筆記成果的操作過程:

啟動一文字界面終端機應用軟體

本筆記撰寫當下使用的是 KDE 桌面環境得 Konsole 應用軟體

切換作業目錄至要存放 wkbre 軟體源碼的目錄

執行下列命令以切換作業目錄至要存放 wkbre 軟體源碼的目錄:

cd /path/to/wkbre/srcdir/hosting/folder

將 wkbre 軟體的 Git 版控庫(repository)拓製(clone)到本地

執行下列命令將 wkbre 軟體的 Git 版控庫拓製到本地:

git clone https://github.com/AdrienTD/wkbre.git

您可以使用 --depth git clone 命令選項來限縮獲取的變更歷史深度

切換作業目錄(working directory)至 wkbre 軟體的來源程式碼(source code)目錄

執行下列命令以切換作業目錄至 wkbre 軟體的來源程式碼目錄:

cd wkbre

已知問題規避方案(WORKAROUND):修正 bzip2 子目錄不適當的 CMakeLists.txt 檔案名稱

因 bzip2 子目錄的 CMakeLists.txt 檔案於區分大小寫的作業系統(如 Linux)下會無法被 CMake 讀到故需要執行下列命令手動修正檔案名稱:

mv bzip2/CMakeLists.{TXT,txt}

附註:

已知問題規避方案:修正不適當的標頭檔案(header file)檔案路徑

因源碼引用的 C/C++ 程式語言標頭檔案於區分大小寫以及使用正斜線(/)作為檔案路徑目錄分隔符的作業系統(如 Linux)下會無法被 C/C++ 預處理器讀到故需要執行下列命令手動修正檔案路徑:

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[@]}"

附註: 此修正已提交為 Fix Linux MinGW cross-build incompatibilities by brlin-tw · Pull Request #1 · AdrienTD/wkbre 上游專案合併請求的一部分

已知問題規避方案:修正不適當的 Resource Compiler 輸入檔中的檔案路徑

因 Resource Compiler 輸入檔參照的外部檔案路徑於使用正斜線(/)作為檔案路徑目錄分隔符的作業系統(如 Linux)下會無法被 windres 程序讀到故需要執行下列命令手動修正檔案路徑:

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

附註: 此修正已提交為 Fix Linux MinGW cross-build incompatibilities by brlin-tw · Pull Request #1 · AdrienTD/wkbre 上游專案合併請求的一部分

已知問題規避方案:套用 ImVec4 資料類型變數傳入程式修正

  1. 當前作業目錄(current working directory)創建一 fix-imvec4-rvalue-type.patch 程式修正檔(patch file),新增下列內容後保存:

    ​​​​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.");
    ​​​​ 	}
    
  2. 執行下列命令以套用程式修正:

    ​​​​patch_opts=(
    ​​​​    # 將程式修正檔中的檔案路徑移除一個路徑組成元件
    ​​​​    --strip=1
    ​​​​)
    ​​​​patch "${patch_opts[@]}" <fix-imvec4-rvalue-type.patch
    

創建軟體建構用檔案存放目錄(build directory)

為避免源碼建構用檔案與軟體源碼檔案混在一起,執行下列命令以創建軟體建構用檔案存放目錄:

mkdir_opts=(
    # 在目錄(及其親目錄)已存在情境下不報錯
    --parents
)
mkdir "${mkdir_opts[@]}" build

切換作業目錄至軟體建構用檔案存放目錄

執行下列命令以切換作業目錄至軟體建構用檔案存放目錄:

cd build

安裝 CMake 軟體建構系統檔案生成器

以 root 身份執行下列命令以安裝 CMake 軟體建構系統檔案生成器:

apt install cmake

安裝 MinGW-w64 跨平台軟體建構工具鏈

以 root 身份執行下列命令以安裝 MinGW-w64 跨平台軟體建構工具鏈:

apt install mingw-w64

設計 MinGW-w64 的 CMake 工具鏈定義檔(toolchain file)

於當前作業目錄創建一 TC-mingw.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 軟體建構系統的建構規則檔:

cmake_opts=(
    # 定義 `CMAKE_TOOLCHAIN_FILE` CMake 快取項目的值
    -DCMAKE_TOOLCHAIN_FILE=TC-mingw.cmake
    
    # 不編入測試邏輯
    -DWKBRE_RELEASE=TRUE
)
cmake "${cmake_opts[@]}" ..

您可以透過 -G cmake 命令選項以指定其他軟體建構系統(如 Ninja)的源碼建構用檔案

建構軟體

執行下列命令以開始進行軟體建構:

make_opts=(
    # 使用系統中央處理器(CPU)的執行緒數進行平行建構
    --jobs="$(nproc)"
)
make "${make_opts[@]}"

順利的話您應可以於命令輸出中看到軟體主程式被成功建構:


    ...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

且可於當前作業目錄中看到被建構的軟體主程式檔案:

$ ls -l 
total 2052

    ...stripped...

-rwxrwxr-x 1 brlin brlin 2012049 Jan  7 20:51 wkbre.exe

引入執行時期需要的 Windows 程式庫

執行下列命令引入執行時期所需要的 Windows 程式庫:

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 \
    .

注意: 如果您要將軟體複製到其他系統使用請改用 cp 命令複製完整的程式庫檔案

安裝 Wine Windows API 相容層

以 root 身份執行下列命令以安裝 Wine Windows API 相容層:

apt install wine

執行建構好的軟體

執行下列命令即可嘗試執行建構好的軟體:

wine wkbre.exe

缺少遊戲資料檔案的錯誤對話框的螢幕截圖

常用操作

以下說明進行本筆記之操作時可能會用到的常用操作:

移除 Git 版控庫所有未被版本控制系統追蹤(untracked)的檔案

  1. 切換作業目錄至 Git 版控庫的作業副本(working copy)目錄中

  2. 執行下列命令以移除 Git 版控庫所有未被版本控制系統追蹤(untracked)的檔案:

    ​​​​git_clean_opts=(
    ​​​​    # 遞迴地移除未被版本控制系統追蹤的(untracked)目錄中的檔案
    ​​​​    -d
    
    ​​​​    # 啟用檔案刪除功能
    ​​​​    -f
    
    ​​​​    # 連同被(.gitignore 檔案/Git 配置)排除追蹤的檔案一起清理
    ​​​​    -x
    ​​​​)
    ​​​​git clean "${git_clean_opts[@]}"
    

重設 Git 版控庫作業副本中尚未提交進版控庫的內容變更

  1. 執行下列命令以切換作業目錄至 Git 版控庫的作業副本目錄中:

    ​​​​cd /path/to/wkbre
    
  2. 執行下列命令以重設作業副本目錄中尚未提交進版控庫的內容變更:

    ​​​​git_reset_opts=(
    ​​​​    # 除 HEAD 指標外還要重設作業副本中的被追蹤檔案內容
    ​​​​    --hard
    ​​​​)
    ​​​​git reset "${git_reset_opts[@]}"
    

清理 GNU Make 軟體建構系統的源碼建構中間產物(intermediate build artifacts)

  1. 執行下列命令以切換作業目錄至 wkbre 軟體的軟體建構用檔案存放目錄中:

    ​​​​cd /path/to/wkbre/build
    
  2. 執行下列命令以清理 GNU Make 軟體建構系統的源碼建構中間產物:

    ​​​​make clean
    

查看當前 Git 版本庫 HEAD 指標指向的修訂版與作業副本之間的內容差異

  1. 執行下列命令以切換作業目錄至 Git 版控庫的作業副本目錄中:

    ​​​​cd /path/to/wkbre
    
  2. 執行下列命令以查看當前 Git 版本庫 HEAD 指標指向的修訂版與作業副本之間的內容差異:

    ​​​​git diff
    

參考資料

以下列舉撰寫本文章期間所參考的第三方資料:


除另外標註之內容外本作品的內容以《Creative Commons 姓名標示-相同方式分享》授權條款第 4.0 國際版或其任意更近期版本釋出供大眾於授權範圍內自由使用