iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
Software Development

30 天 CMake 跨平台之旅系列 第 28

[Day 28] Cross Compile Windows Binaries

  • 分享至 

  • xImage
  •  

本日內容

  • Build Windows Toolchain
  • 來寫 CMake Toolchain File 吧
  • Hello World!
  • Cross Compile!
  • 預告

Day 28 - Colab

今天會用到 Day 27 介紹的內容
在 Linux 將 MinGW-w64 toolchain build 出來並 cross compile Windows 版本的可執行檔!

Build Windows Toolchain

我們會用 Day 27 已經裝好的 crosstool-NG, 將 x86_64-w64-mingw32 cross config 加入 toolchain

做完必要的設定後 (請見 Day 27), 我們就直接來 build toolchain 吧

ct-ng build

需要 build 1 個多小時...
https://ithelp.ithome.com.tw/upload/images/20230928/20161950hy95AVUrPM.png

來寫 CMake Toolchain File 吧

上一篇有提過, toolchain package 的命名規則通常是 <arch>[endian][-vendor]-<kernel>[-os], 以今天的 toolchain x86_64-w64-mingw32 來說, 就可以拆解成

  • Arch: x86_64
  • kernel: w64
  • OS: mingw32

接著我們就可以用該名稱去找我們的 cross compiler 了
不過我們不需要完整的路徑, 只需要將 CMAKE_FIND_ROOT_PATH 設為 Toolchain Directory 即可, CMake 會自動去底下找指定的 cross compiler

x86_64-w64-mingw32.cmake

set(CMAKE_SYSTEM_NAME Windows)

set(CMAKE_C_COMPILER /root/x-tools/x86_64-w64-mingw32/bin/x86_64-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER /root/x-tools/x86_64-w64-mingw32/bin/x86_64-w64-mingw32-g++)

set(CMAKE_FIND_ROOT_PATH /root/x-tools/x86_64-w64-mingw32)

set(CMAKE_SYSROOT /root/x-tools/x86_64-w64-mingw32/x86_64-w64-mingw32/sysroot)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  • CMAKE_FIND_ROOT_PATH
    • 會讓 find_*() 系列的搜尋路徑都加上該 prefix
    • 搜尋規則視下面的 CMAKE_FIND_ROOT_PATH_MODE_* 決定
  • CMAKE_FIND_ROOT_PATH_MODE_* 系列會影響對應的 find_*() 搜尋路徑
    • 有 3 種設定: NEVER, ONLY, BOTH
    • NEVER
      • 不會搜尋 CMAKE_FIND_ROOT_PATH prefix 路徑
    • ONLY
      • 僅搜尋 CMAKE_FIND_ROOT_PATH prefix 路徑
    • BOTH
      • 先搜尋 CMAKE_FIND_ROOT_PATH prefix 路徑再搜尋沒有 prefix 的路徑
  • CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
    • 通常會設為 NEVER
    • find_program() 是為了控制 cmake build 的流程, 所以會找 build host 的 programs
  • CMAKE_FIND_ROOT_PATH_MODE_LIBRARY, CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
    • 通常會設為 ONLY
    • 因為我們是 cross build, 所以需要讓 cross compiler 能夠找到 build target 的 libraries 和 headers

Hello World!

一樣, 我們寫一個簡單的 Hello World 來試試 binary 是否能在目標系統執行

CMakeLists.txt

cmake_minimum_required(VERSION 3.25)
project(ItHome2023 CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQURIED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(Main main.cpp)

main.cpp

#include <iostream>

int main() {
 std::cout << "Hello World!" << std::endl; 
}

最後我們將寫好的 toolchain file x86_64-w64-mingw32.cmake 放到 toolchain 底下

這樣就準備完成啦!

Cross Compile!

我們可以設定 cache variable CMAKE_TOOLCHAIN_FILE

cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain/x86_64-w64-mingw32.cmake

或是直接用 --toolchain option

cmake -S . -B build --toolchain=toolchain/x86_64-w64-mingw32.cmake

Build 完後 (cmake --build build), 我們來看看產出的執行檔
https://ithelp.ithome.com.tw/upload/images/20230928/20161950uMWtVKPwqU.png

可以看到 Windows 的執行檔格式 .exe
並且確認了無法在 Linux 執行
https://ithelp.ithome.com.tw/upload/images/20230928/20161950Jli2icSi9k.png

所以, 我們將 Main.exe 下載到 Windows 系統上執行
https://ithelp.ithome.com.tw/upload/images/20230928/20161950QlPFKgRymM.png

就能看到熟悉的 Hello World! 了🎉🎉🎉

至此, 我們終於解決了 Day 2 時, 無法將 Linux-built binary 的執行檔給 Windows 使用的問題了

預告

雖然我們已經成功 cross compile 了, 但是跨平台之旅還沒有結束!
下一篇, 我們會用 Day 22 介紹過的方法打包我們的 Windows executable, 並讓使用者可以用安裝檔進行安裝!


上一篇
[Day 27] Cross Compile 行前準備
下一篇
[Day 29] Windows Installer
系列文
30 天 CMake 跨平台之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言