从零到 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 .