从零到 APK:在 Ubuntu 20.04 上搭建 Qt6 Android 交叉编译环境,覆盖 JDK、Android SDK/NDK、Qt6 for Android 安装,以及 CMake 配置、交叉编译、APK 打包全流程。
1. 环境概览
| 组件 | 版本 | 用途 |
|---|---|---|
| JDK | OpenJDK 17 | Android 构建工具链 |
| Android SDK | API 34, build-tools 34.0.0 | 编译 + 签名 |
| Android NDK | 25.2.9519653 | C++ 交叉编译工具链 |
| Qt6 Host | 6.5.3 gcc_64 | 提供 moc/uic/rcc 等主机工具 |
| Qt6 Android | 6.5.3 android_arm64_v8a | arm64 目标平台库 |
| CMake | 3.16+ | 构建系统(旧版有警告但可用) |
关键认知: Qt6 Android 交叉编译需要两个 Qt 安装——一个桌面版(Host,提供编译工具),一个 Android 版(Target,提供 arm64 库)。
2. JDK 安装
sudo apt install -y openjdk-17-jdk
# 验证
java -version # openjdk 17.0.x
javac -version # javac 17.0.x
版本要求: Qt6 需要 JDK 11+。推荐 JDK 17——LTS 版本,与 Android 构建工具兼容性最好。
3. Android SDK + NDK 安装
3.1 下载 commandline-tools
mkdir -p /opt/android/cmdline-tools
cd /tmp
curl -sL https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip \
-o cmdline-tools.zip
unzip -qo cmdline-tools.zip
mv cmdline-tools /opt/android/cmdline-tools/latest
3.2 安装 SDK 组件
export ANDROID_SDK_ROOT=/opt/android
export PATH=$PATH:/opt/android/cmdline-tools/latest/bin
# 接受许可
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT --licenses
# 安装平台 + 构建工具 + NDK
sdkmanager --sdk_root=$ANDROID_SDK_ROOT \
"platforms;android-34" \
"build-tools;34.0.0" \
"platform-tools" \
"ndk;25.2.9519653"
| 包 | 说明 |
|---|---|
platforms;android-34 |
Android 14 API |
build-tools;34.0.0 |
aapt, dx, zipalign 等 |
platform-tools |
adb, fastboot |
ndk;25.2.9519653 |
C/C++ 交叉编译工具链(~1.2G) |
NDK 版本选择: Qt6.5 官方推荐 NDK r25。不要用 r26+,cmake 路径结构有变化。
3.3 验证
ls $ANDROID_SDK_ROOT/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/ | head -5
# 应输出 aarch64-linux-android21-clang 等
4. Qt6 for Android 安装
使用 aqtinstall 下载官方预编译的 Qt6 Android arm64 包:
pip3 install aqtinstall
aqt install-qt linux android 6.5.3 android_arm64_v8a \
-m qt5compat qtcharts qtimageformats \
--outputdir /opt/Qt
注意:
qt5compat等可选模块按需安装。android_arm64_v8a 是最常用的目标 ABI(覆盖 99% 的现代 Android 设备)。
安装后的目录结构:
/opt/Qt/
├── 6.5.3/
│ ├── gcc_64/ ← 桌面 Host(提供 moc/uic/rcc)
│ └── android_arm64_v8a/ ← Android Target(arm64 库)
5. 环境变量配置
写入 /etc/profile.d/qt6.sh(或 ~/.bashrc):
# Android SDK/NDK
export ANDROID_SDK_ROOT=/opt/android
export ANDROID_NDK_ROOT=/opt/android/ndk/25.2.9519653
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# Qt6
export QT6_DIR=/opt/Qt/6.5.3/gcc_64
export QT_ANDROID_DIR=/opt/Qt/6.5.3/android_arm64_v8a
export PATH="$QT6_DIR/bin:$ANDROID_SDK_ROOT/platform-tools:$PATH"
加载生效:
source /etc/profile.d/qt6.sh
6. CMake 交叉编译
6.1 项目准备
最小 Qt6 项目(CMakeLists.txt):
cmake_minimum_required(VERSION 3.16)
project(MyApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_executable(MyApp main.cpp)
target_link_libraries(MyApp Qt6::Widgets)
6.2 配置
mkdir build-android && cd build-android
/opt/Qt/6.5.3/android_arm64_v8a/bin/qt-cmake \
-DQT_HOST_PATH=/opt/Qt/6.5.3/gcc_64 \
..
qt-cmake 做了什么:
qt-cmake = cmake \
-DCMAKE_TOOLCHAIN_FILE=<NDK路径>/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-23 \
-DQT_HOST_PATH=<主机Qt路径> \
-DCMAKE_PREFIX_PATH=<Android Qt路径>
⚠️ QT_HOST_PATH 是关键。 没有它,CMake 会报错:“To use a cross-compiled Qt, please set the QT_HOST_PATH”。
6.3 编译
cmake --build . -j$(nproc)
编译产物是 .so 文件(Android 动态库),位于 build-android/libMyApp_arm64-v8a.so。
7. APK 打包
交叉编译产出 .so 后,用 androiddeployqt 生成完整 APK:
7.1 项目模板
Qt6 Android 项目需要最小模板结构:
android/
├── AndroidManifest.xml ← 包名 / 权限 / Activity 声明
├── build.gradle ← Gradle 配置
├── res/ ← 图标等资源
│ └── values/
│ └── libs.xml
└── src/
└── org/qtproject/example/
└── MyApp.java ← Qt Activity
7.2 快速生成
# 用 Qt 提供的模板生成 Android 目录
mkdir -p android-build
cd android-build
/opt/Qt/6.5.3/android_arm64_v8a/bin/androiddeployqt \
--input android-MyApp-deployment-settings.json \
--output android-build \
--android-platform android-34 \
--jdk $JAVA_HOME
7.3 Gradle 构建
cd android-build
./gradlew assembleRelease
产物:android-build/build/outputs/apk/release/MyApp-release-unsigned.apk
签名后即可安装:
adb install MyApp-release.apk
8. 常见问题
Q: CMake 报 “old version of CMake”
WARNING: An old version of CMake is being used that cannot
automatically detect compiler attributes.
原因: CMake < 3.19 的 Android 工具链兼容性问题。 影响: 无——交叉编译仍然成功。只是 NDK 用硬编码而非探测来确定编译器标志。 解决: 升级 CMake ≥ 3.19,或在确认编译通过后忽略。
Q: “Please set QT_HOST_PATH”
CMake Error: To use a cross-compiled Qt, please set the
QT_HOST_PATH cache variable to the location of your host
Qt installation.
原因: 交叉编译时,moc/uic/rcc 等工具必须从主机 Qt 获取。
解决: cmake -DQT_HOST_PATH=/opt/Qt/6.5.3/gcc_64,或用 qt-cmake 自动处理。
Q: NDK r26 找不到 toolchain 文件
原因: NDK r26+ 改变了 cmake 工具链文件路径。 解决: 用 NDK 25.x——Qt6.5 官方推荐的版本。
Q: arm64-v8a vs armeabi-v7a vs x86_64
| ABI | 适用设备 | 建议 |
|---|---|---|
| arm64-v8a | 所有现代 Android 手机(2015+) | ✅ 默认选这个 |
| armeabi-v7a | 老旧 32 位设备(< 2015) | 可按需添加 |
| x86_64 | 模拟器 | 仅调试用 |
9. 完整验证脚本
#!/bin/bash
set -e
# 环境
export ANDROID_SDK_ROOT=/opt/android
export ANDROID_NDK_ROOT=/opt/android/ndk/25.2.9519653
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export QT_ANDROID_DIR=/opt/Qt/6.5.3/android_arm64_v8a
export QT_HOST_PATH=/opt/Qt/6.5.3/gcc_64
# 验证
echo "=== JDK ===" && java -version 2>&1 | head -1
echo "=== NDK ===" && ls "$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin" | head -1
echo "=== Qt Android ===" && "$QT_ANDROID_DIR/bin/qmake" --version | head -1
# 测试编译
mkdir -p /tmp/qt6-android-test && cd /tmp/qt6-android-test
cat > CMakeLists.txt << 'EOF'
cmake_minimum_required(VERSION 3.16)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Core)
add_library(test SHARED main.cpp)
target_link_libraries(test Qt6::Core)
EOF
echo '#include <QtCore/QtGlobal>' > main.cpp
mkdir -p build && cd build
"$QT_ANDROID_DIR/bin/qt-cmake" -DQT_HOST_PATH="$QT_HOST_PATH" .. > /dev/null 2>&1
cmake --build . -j$(nproc) > /dev/null 2>&1
echo "=== Cross-compile OK ==="
echo "Android arm64-v8a 构建环境就绪"
10. 环境总结
/opt/Qt/6.5.3/
├── gcc_64/ # 桌面版 Qt6 (Host) 782M
└── android_arm64_v8a/ # Android Qt6 (Target) 333M
/opt/android/
├── ndk/25.2.9519653/ # NDK 工具链 1.5G
├── platforms/android-34/ # SDK 平台 200M
├── build-tools/34.0.0/ # 构建工具 100M
└── platform-tools/ # adb 15M
磁盘: Qt5 485M + Qt6 782M + Android-Qt6 333M + SDK/NDK 2.1G = 3.7G
一命令编译 Android 应用:
/opt/Qt/6.5.3/android_arm64_v8a/bin/qt-cmake \
-DQT_HOST_PATH=/opt/Qt/6.5.3/gcc_64 .. && \
cmake --build .