來(lái)源:https://blog.cuteserver.io/building-a-cmake-based-qt-app
介紹
在 Qt6 中,CMake 成為 Qt 的默認(rèn)構(gòu)建系統(tǒng),取代了 qmake。不幸的是,過(guò)渡并不順利。在第一個(gè) Qt6 版本中,缺少 Android 支持。iOS 需要原生 Xcode 項(xiàng)目,即使在 Qt 6.3 上,WebAssembly 仍處于技術(shù)預(yù)覽階段。
當(dāng)針對(duì) iOS、Android 和 WebAssembly 時(shí),CMake 的緩慢采用迫使許多開(kāi)發(fā)人員實(shí)施他們自己的自定義 CMake 工具鏈,以便在其項(xiàng)目所需的所有目標(biāo)平臺(tái)上構(gòu)建基于 Qt 的應(yīng)用程序。
這也是我的情況。我是Cute server的開(kāi)發(fā)者,它擴(kuò)展了 Qt 的信號(hào)和槽機(jī)制,使它們能夠在網(wǎng)絡(luò)上使用。使用 Cute,客戶端通過(guò)創(chuàng)建遠(yuǎn)程對(duì)象并與它們的信號(hào)和插槽進(jìn)行交互,就像它們是本地的一樣,而不是依賴于傳統(tǒng)的請(qǐng)求/響應(yīng)模型。Cute 項(xiàng)目為 Linux、macOS、Windows、iOS、Android 和 WebAssembly 提供基于 Linux 的服務(wù)器和客戶端 SDK,因此需要為不同的平臺(tái)構(gòu)建多個(gè)資產(chǎn)。
為了在所有需要的平臺(tái)上創(chuàng)建 Cute 服務(wù)器項(xiàng)目的資產(chǎn),我開(kāi)發(fā)了一個(gè) CMake 文件來(lái)為桌面構(gòu)建和一個(gè) CMake 工具鏈,它允許交叉編譯 iOS、Android 和 WebAssembly。
我想要一些獨(dú)立于 IDE 的東西。我還想要一個(gè)可以在 IDE 中或直接在命令行中使用的通用 CMake 解決方案。
CMake 資產(chǎn)在GitHub上可用,其中一個(gè)在屏幕上打印問(wèn)候消息的簡(jiǎn)單 Qt Quick 應(yīng)用程序使用 Cute 的 CMake 資產(chǎn)來(lái)定位許多平臺(tái)。
在這里,我們將展示如何在命令行上構(gòu)建桌面、iOS、Android 和 WebAssembly 的示例應(yīng)用程序。盡管使用基于英特爾的 mac 來(lái)構(gòu)建應(yīng)用程序,但 Linux 和 Windows 也是有效的構(gòu)建主機(jī)。
要將 macOS 用作構(gòu)建主機(jī),您應(yīng)該從在線安裝程序安裝 Xcode 和 Qt。下面的命令顯示了如何為所有支持的平臺(tái)構(gòu)建項(xiàng)目。
桌面
可以使用 Qt5 為桌面構(gòu)建應(yīng)用程序,如下所示:
# configure project
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/5.15.2/clang_64 \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make -j8
# run app
open App/MyApp.app
使用Qt6只是改變QT_SDK_DIRCMake變量的問(wèn)題,如下圖:
# configure project
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/6.2.3/macos \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make -j8
# run app
open App/MyApp.app
iOS
下面的命令使用 Qt5 為 iOS 模擬器構(gòu)建應(yīng)用程序(注意交叉編譯需要 CMake 工具鏈):
# configure project
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DAPPLE_IOS_TARGET=True \
-DAPPLE_IOS_SIMULATOR=True \
-DMIN_IOS_SDK_TARGET=12 \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/5.15.2/ios \
-DCMAKE_TOOLCHAIN_FILE=CMake/Cute.toolchain.cmake \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make -j8
# App/MyApp.app can be run on simulator
下面,我們使用 Qt6 為 iOS 設(shè)備構(gòu)建應(yīng)用程序(QT_HOST_PATH必需):
# configure project
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DAPPLE_IOS_TARGET=True \
-DAPPLE_IOS_DEVICE=True \
-DMIN_IOS_SDK_TARGET=13 \
-DQT_HOST_PATH=/Users/glauco/Programming/Qt/SDK/6.2.3/macos \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/6.2.3/ios \
-DCMAKE_TOOLCHAIN_FILE=CMake/Cute.toolchain.cmake \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make -j8
# App/MyApp.app can be run on devices
可以使用 CMake 變量中指定的代碼簽名身份對(duì)應(yīng)用程序進(jìn)行簽名APPLE_CODE_SIGN_IDENTITY。
安卓
Android 構(gòu)建使用了 Android 構(gòu)建工具 31.0.0 和 NDK 22.1.7171670。您可以通過(guò) Android Studio 安裝它們。如果沒(méi)有安裝java,可以定義JAVA_HOME環(huán)境變量使用Android Studio提供的java運(yùn)行環(huán)境。
Android 需要為多種架構(gòu)構(gòu)建。CMake 通過(guò)外部項(xiàng)目支持多種架構(gòu)。因此,工具鏈定義了許多目標(biāo)來(lái)為所有架構(gòu)創(chuàng)建資產(chǎn)。目標(biāo)MyApp-all為所有架構(gòu)構(gòu)建,并使用該androiddeployqt工具創(chuàng)建 Bundle/APK。下面顯示的命令使用 Qt5 創(chuàng)建 Android 應(yīng)用程序:
# configure project
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_TARGET=True \
-DANDROID_TARGET_SDK_VERSION=28 \
-DANDROID_SDK=/Users/glauco/Library/Android/sdk \
-DANDROID_BUILD_TOOLS_REVISION=31.0.0 \
-DANDROID_NDK=/Users/glauco/Library/Android/sdk/ndk/22.1.7171670 \
-DANDROID_ABIS='arm64-v8a;armeabi-v7a;x86;x86_64' \
-DKS_URL=/Users/glauco/Programming/AndroidKeystore/android.keystore \
-DKS_KEY_ALIAS=AndroidDeveloperKeystore \
-DKS_PASS_FILE=/Users/glauco/Programming/AndroidKeystore/keystore.pass \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/5.15.2 \
-DCMAKE_TOOLCHAIN_FILE=CMake/Cute.toolchain.cmake \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make MyApp-all -j8
# App/MyApp/android-build/build/outputs has apk and bundle folders
# containing debug apk for testing and bundle with release build
以下命令使用 Qt6 構(gòu)建 Android 應(yīng)用程序(QT_HOST_PATH必需):
# configure project
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_TARGET=True \
-DANDROID_TARGET_SDK_VERSION=31 \
-DANDROID_SDK=/Users/glauco/Library/Android/sdk \
-DANDROID_BUILD_TOOLS_REVISION=31.0.0 \
-DANDROID_NDK=/Users/glauco/Library/Android/sdk/ndk/22.1.7171670 \
-DANDROID_ABIS='arm64-v8a;armeabi-v7a;x86;x86_64' \
-DKS_URL=/Users/glauco/Programming/AndroidKeystore/android.keystore \
-DKS_KEY_ALIAS=AndroidDeveloperKeystore \
-DKS_PASS_FILE=/Users/glauco/Programming/AndroidKeystore/keystore.pass \
-DQT_HOST_PATH=/Users/glauco/Programming/Qt/SDK/6.3.0/macos \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/6.3.0 \
-DCMAKE_TOOLCHAIN_FILE=CMake/Cute.toolchain.cmake \
/Users/glauco/Programming/MyProjects/HelloWorld
# build
make MyApp-all -j8
# App/MyApp/android-build/build/outputs has apk and bundle folders
# containing debug apk for testing and bundle with release build
WebAssembly
Qt for WebAssembly 需要 Emscripten。以下命令在主機(jī)上設(shè)置 Emscripten:
# we are at /Users/glauco/Programming/Wasm
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install 3.1.6
./emsdk activate 3.1.6
echo 'source "/Users/glauco/Programming/Wasm/emsdk/emsdk_env.sh"' >> ~/.zprofile
下面的命令使用 Qt 6.3 為 WebAssembly 構(gòu)建應(yīng)用程序:
# configure project
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DWASM_TARGET=True \
-DWASM_SDK=/Users/glauco/Programming/Wasm/emsdk/upstream \
-DQT_SDK_DIR=/Users/glauco/Programming/Qt/SDK/6.3.0/wasm_32 \
-DQT_HOST_PATH=/Users/glauco/Programming/Qt/SDK/6.3.0/macos \
-DCMAKE_TOOLCHAIN_FILE=CMake/Cute.toolchain.cmake \
/Users/glauco/Programming/MyProjects/HelloWorld
# build project
make -j8
# load page on browser
emrun --browser firefox App/MyApp.html
結(jié)論
程序員用代碼解決問(wèn)題。查看 CMake 的最佳方式是作為一種用于對(duì)項(xiàng)目的構(gòu)建過(guò)程進(jìn)行編碼的編程語(yǔ)言。
通過(guò)將 CMake 視為一種編程語(yǔ)言,您可以在偶然發(fā)現(xiàn)構(gòu)建問(wèn)題時(shí)編寫(xiě)解決方案,而不是暫停并期待有人修復(fù)它。有了這個(gè)觀點(diǎn),一切皆有可能。