在 Mac 上配齐鸿蒙 PC Qt 交叉编译环境——从 brew 到第一个 libhello_qt_ohos.so 的真实路径

欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/

这篇专门写给"就想在自己的 Mac 上把鸿蒙 PC Qt 适配环境配齐"的开发者:怎么用 brew、怎么处理 Apple Silicon 的奇葩问题、踩过 macOS 特有的几个坑怎么绕。

全程在我自己的 MacBook Pro(M3 Max / macOS 26)上重做了一遍,所有命令真实可复制


一、能不能在 Mac 上做这件事?

先回答最常被问的——,但不是"完美"。

维度Linux 服务器Mac
Qt-OHOS 官方支持✅ 一等公民⚠️ 二等公民(host 工具要自己处理)
包管理yum / apt 系统包齐全brew 缺一些 cross-compile 工具
OHOS clang 工具链✅ 官方有 Linux x64 版✅ 官方也有 darwin x64 / arm64 版
host moc/uic/rcc⚠️ Qt-OHOS 自带 .exe(要软链系统 Qt5)⚠️ Qt-OHOS 自带 .exe(同样要替换)
调试设备需要远程到本机调✅ 直接 hdc list targets
编译速度(M3 Max)8 核云主机 < 16 核 M3✅ 本机编译反而更快
Apple Silicon 兼容n/a⚠️ 部分 host 工具要用 Rosetta 跑 x64
磁盘消耗不心疼⚠️ 占本机 6-10 GB

适合 Mac 的场景

  • 自己一个人做适配实验
  • 没有云服务器预算
  • 想本机一站式开发 + 调试
  • 习惯 macOS 工作流

不适合 Mac 的场景

  • 团队多人共享构建环境(用服务器)
  • 同时要编译 5+ Qt 应用(云主机 8 核 + 大内存更稳)
  • CI/CD 流水线(用 Linux Docker)

我自己是两套都配——本机调试方便,服务器跑 batch。但只有 Mac 也完全能起步


二、整体方案:一图看懂

在这里插入图片描述

总耗时:约 45 分钟(绝大部分时间在等下载)。


三、阶段 1:brew 装系统包(5 分钟)

3.1 前置:先有 Xcode Command Line Tools

# 验证
xcode-select -p
# 期望输出:/Library/Developer/CommandLineTools 或 .../Xcode.app/...
# 没有的话:
xcode-select --install

3.2 brew 装 5 个核心包

brew install cmake ninja qt@5 patchelf wget

为什么是这 5 个

作用不装会怎样
cmake大多数 Qt 项目用 cmake直接干不了
ninja比 make 快 2-3 倍能用 make 替代但慢
qt@5host 用的 moc/uic/rcc(不是真的链接它跑)见阶段 4
patchelf改 ELF 文件头(4KB 对齐等)部分应用装不上设备
wget下大文件比 curl 顺手不装也行,用 curl 也行

⚠️ 关键提醒brew install qt@5 不是装 Qt 给鸿蒙用的——它是给 host 用的(编译期需要的 moc/uic/rcc 工具)。鸿蒙 Qt 用的是阶段 3 的 Qt-OHOS。

3.3 brew 装完后的实际路径

不同芯片路径不一样,记一下

# Apple Silicon (M1/M2/M3)
brew --prefix qt@5
# /opt/homebrew/opt/qt@5

ls /opt/homebrew/opt/qt@5/bin/
# moc / uic / rcc / qmake / lrelease ...

# Intel Mac
# /usr/local/opt/qt@5/bin/...

后面所有路径都按 Apple Silicon 写——Intel Mac 把 /opt/homebrew/ 换成 /usr/local/ 即可。

3.4 把 qt@5 加 PATH

brew install qt@5 默认不会自动加 PATH——它是 keg-only 的:

echo 'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 验证
which moc-qt5  # 或 which moc
moc -v   # Qt 5.15.x

四、阶段 2:装 OHOS Native SDK(12 分钟)

4.1 下载

OHOS SDK 全套约 2.8 GB,用华为云国内镜像(直连官方很慢):

cd ~
mkdir -p ohos-download && cd ohos-download

# 下载(5.0.1-Release 是 API 12 / HarmonyOS 5.0 对应)
wget https://repo.huaweicloud.com/openharmony/os/5.0.1-Release/ohos-sdk-windows_linux-public.tar.gz

# 等带宽,国内电信光纤通常 10-30 MB/s,约 5-10 分钟

在这里插入图片描述

⚠️ 看着包名不对劲?——这个包名叫 windows_linux但解压后里面其实分了 Windows / Linux / Mac 三套子包

tar -xzf ohos-sdk-windows_linux-public.tar.gz
ls ohos-sdk/
# darwin/  linux/  windows/   ← Mac 用 darwin

4.2 解压目标版本到约定路径

mkdir -p ~/ohos-sdk/12

# Mac 用 darwin 那个目录
ls ohos-sdk/darwin/
# native-darwin-x64-xxxx.zip   ← 这个
# previewer-darwin-x64-xxxx.zip
# toolchains-darwin-x64-xxxx.zip
# ets-linux-x64-xxxx.zip
# ...

# 我们最关心 native(C/C++ 交叉编译器)
unzip ohos-sdk/darwin/native-darwin-x64-*.zip -d ~/ohos-sdk/12/
ls ~/ohos-sdk/12/
# native/    ← 出现

4.3 验证 clang 能跑

~/ohos-sdk/12/native/llvm/bin/clang --version
# 期望输出:OHOS LLVM version 15.x.x
#          Target: aarch64-linux-ohos

⚠️ Apple Silicon 用户的隐藏问题

OHOS SDK 的 darwin 版是 x64 编译的(没有 arm64 原生版)。在 Apple Silicon 上跑会走 Rosetta 翻译——慢但能用。

file ~/ohos-sdk/12/native/llvm/bin/clang
# Mach-O 64-bit executable x86_64    ← 是 x64

如果 Rosetta 没装会报错:

zsh: bad CPU type in executable

装上:

softwareupdate --install-rosetta --agree-to-license

性能影响:Rosetta 大约慢 15-30%。编译一个中等 Qt 项目(如 DiffPDF)原本 5 分钟,Apple Silicon 上要 6-7 分钟。能接受


五、阶段 3:拉 Qt-OHOS 5.12.12(20 分钟)

5.1 git-lfs 准备

Qt-OHOS 用 git-lfs 存预编译产物(500+ MB):

brew install git-lfs
git lfs install   # 首次运行要 init 一下

5.2 clone 仓库

在这里插入图片描述

sudo mkdir -p /opt/qt-ohos
sudo chown $(whoami):staff /opt/qt-ohos
cd /opt/qt-ohos

git clone https://atomgit.com/OpenHarmonyPCDeveloper/ohos_Qt5.12.12.git .
# git-lfs 会拉一个 .zip
# 国内 atomgit 速度通常 5-15 MB/s

5.3 解压预编译包

# 拉下来的是个 zip 文件
ls qt_ohos_release/
# qt-5.12.12-ohos_release_xxx.zip

unzip qt_ohos_release/qt-5.12.12-ohos_release_*.zip -d qt-5.12.12-ohos/

ls qt-5.12.12-ohos/qt-5.12.12-ohos/
# bin/  doc/  include/  lib/  mkspecs/  phrasebooks/  plugins/  translations/

5.4 关键检查:host 工具的真相

ls /opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/bin/
# moc.exe   ← ⚠️ Windows 二进制!
# uic.exe
# rcc.exe
# qmake.exe
# lrelease.exe
# ...

所有 host 工具都是 .exe 后缀 —— 因为 Qt-OHOS 当时是在 Windows 上发布的。

file 一下确认:

file /opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/bin/moc.exe
# PE32+ executable (console) x86-64, for MS Windows
# ↑ Windows 二进制,Mac 直接跑不了

这是 Mac 用户的第一个真正硬骨头


六、阶段 4:用 brew 的 qt@5 替换掉 Qt-OHOS 自带的 host 工具(关键 1 分钟)

6.1 思路

Qt-OHOS 包里的 moc.exe 跑不了——但 brew 装的 qt@5 里有 macOS 原生的 moc让它替身

QT_BIN=/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/bin
HOST_QT=/opt/homebrew/opt/qt@5/bin

# 备份原 .exe(万一以后要研究)
for t in moc uic rcc qmake lrelease; do
    mv "$QT_BIN/${t}.exe" "$QT_BIN/${t}.exe.bak"
    ln -sf "$HOST_QT/${t}" "$QT_BIN/${t}.exe"
done

# 验证
ls -la "$QT_BIN/" | grep -E "moc|uic|rcc"
# moc.exe -> /opt/homebrew/opt/qt@5/bin/moc    ← 软链上了
# moc.exe.bak                                   ← 备份在

6.2 验证替身能跑

/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/bin/moc.exe -v
# 期望输出:moc 5.15.x   ← 是 brew 的 qt@5(macOS 原生)

⚠️ 大问号:Qt-OHOS 是 5.12.12,brew 的 qt@5 是 5.15.x——moc ABI 错位会不会出问题?

会有概率出问题,参考 《10 个 Qt 应用适配实战总结》 8 大坑里讲的 moc ABI 降级问题。绝大部分项目能跑,少数(用了 Qt 5.15 才有的 moc 特性的)会闪退。

遇到时的解决方案

# brew 装老版 qt@5.12(如果还能找到)
brew install qt@5.12  # ⚠️ 这个 formula 可能已被移除

# 或者编译一个 Qt 5.12.12 host
# (本仓库的 LiteIDE 移植里有详细做法)

七、阶段 5:环境变量永久化(2 分钟)

不写永久化,每次开新终端都要重新 export,会疯。

cat >> ~/.zshrc <<'EOF'

# ===== HarmonyOS Qt Cross-Compile Environment =====
export OHOS_SDK_ROOT=$HOME/ohos-sdk/12
export QT_OHOS_ROOT=/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos

# host Qt5 工具优先(确保 cmake 找到 moc)
export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"

# hdc 加进 PATH(如果之前没加)
export PATH="$HOME/Library/Huawei/Sdk/openharmony/12/toolchains:$PATH"

# OHOS clang 路径(CMake 会用)
export OHOS_NATIVE_HOME=$OHOS_SDK_ROOT/native

# 让 CMake 找到 Qt-OHOS(FIND_ROOT_PATH_MODE_PACKAGE=BOTH 需要)
export Qt5_DIR=$QT_OHOS_ROOT/lib/cmake/Qt5

# ===== END HarmonyOS Qt =====

EOF

source ~/.zshrc

# 验证
echo $OHOS_SDK_ROOT
echo $QT_OHOS_ROOT
echo $Qt5_DIR

八、阶段 6:Hello World 端到端验证(5-10 分钟)

环境装好了,必须真的编一个东西跑起来才算配齐。

8.1 建工程

mkdir -p ~/dev/hello-qt-ohos/src && cd ~/dev/hello-qt-ohos

8.2 src/main.cpp

#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QLabel label("Hello, HarmonyOS PC + Qt!\nThis is built on macOS.");
    label.setStyleSheet("font-size: 24px; padding: 40px; "
                        "color: white; background: #1a1a1a;");
    label.setAlignment(Qt::AlignCenter);
    label.show();
    return app.exec();
}

8.3 CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(hello_qt CXX)
set(CMAKE_CXX_STANDARD 17)

# Qt5 - 这一行是 Mac 上 OHOS 交叉编译的关键
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

# 仓库 8 大坑里的 #4:禁用资源压缩绕开 zlib 符号缺失
set(CMAKE_AUTORCC_OPTIONS "--no-compress")

find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets)

# 注意:是 SHARED 不是 executable
add_library(hello_qt SHARED src/main.cpp)

target_link_libraries(hello_qt PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets)

# 给 main 加 T 标记(鸿蒙 ELF 加载器要的)
set_target_properties(hello_qt PROPERTIES PREFIX "lib")
target_link_options(hello_qt PRIVATE "-Wl,-z,now")

8.4 toolchain-ohos.cmake

# Mac 上指向 OHOS clang 的 CMake toolchain
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(OHOS_SDK $ENV{OHOS_SDK_ROOT})
set(QT_OHOS $ENV{QT_OHOS_ROOT})

set(CMAKE_C_COMPILER   ${OHOS_SDK}/native/llvm/bin/clang)
set(CMAKE_CXX_COMPILER ${OHOS_SDK}/native/llvm/bin/clang++)

set(CMAKE_C_FLAGS_INIT "--target=aarch64-linux-ohos")
set(CMAKE_CXX_FLAGS_INIT "--target=aarch64-linux-ohos -stdlib=libc++")

# 让 find_package 找到 Qt-OHOS
set(CMAKE_FIND_ROOT_PATH ${QT_OHOS})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# 关键:让 PACKAGE 模式能跨越 root_path
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)

8.5 编译

cmake -G Ninja \
    -B build \
    -DCMAKE_TOOLCHAIN_FILE=$(pwd)/toolchain-ohos.cmake \
    -DCMAKE_BUILD_TYPE=Release

ninja -C build

期望输出

[1/4] Building CXX object CMakeFiles/hello_qt.dir/hello_qt_autogen/mocs_compilation.cpp.o
[2/4] Automatic MOC for target hello_qt
[3/4] Building CXX object CMakeFiles/hello_qt.dir/src/main.cpp.o
[4/4] Linking CXX shared library libhello_qt.so

✅ 完成

8.6 ELF 5 项体检

cd build

# 1. file 体检
file libhello_qt.so
# 期望:ELF 64-bit LSB shared object, ARM aarch64, ...

# 2. ELF Class
readelf -h libhello_qt.so | grep Class
# 期望:ELF64

# 3. T main 符号(鸿蒙 ELF 加载器入口)
nm libhello_qt.so | grep " T main"
# 期望:xxxxxx T main

# 4. 依赖
readelf -d libhello_qt.so | grep NEEDED
# 期望:含 Qt5Core / Qt5Gui / Qt5Widgets / libc++.so / libGLESv3.so

# 5. LOAD 段 4KB 对齐
readelf -l libhello_qt.so | grep LOAD
# 期望:Align 都是 0x1000(4096)

5 项全过 → 环境完美

8.7 推到真机跑

# 推 .so 到设备
hdc file send build/libhello_qt.so /data/local/tmp/

# 这一步光推上去还不够——需要 HAP 工程作壳
# 参考仓库 QtOhosDemo-壳模板/ 怎么把 .so 集成

完整的 HAP 集成步骤超出本文范围——下一篇见。


在这里插入图片描述

九、macOS 特有的几个坑(绕过指南)

9.1 Rosetta 没装 → clang 跑不起来

zsh: bad CPU type in executable

修复

softwareupdate --install-rosetta --agree-to-license

9.2 brew 装的 qt@5 是 keg-only → moc 找不到

moc: command not found

原因:brew 不自动把 qt@5 加 PATH。

修复:见 3.4 节,手动加 PATH。

9.3 cmake 找不到 Qt5

CMake Error: Qt5 not found

原因:用了 CMAKE_PREFIX_PATH 但在 toolchain 模式下被忽略。

修复:用 Qt5_DIR 而不是 CMAKE_PREFIX_PATH(见阶段 5 的环境变量)。

9.4 ninja 编译时报 xcrun: error: invalid active developer path

原因:CMake 仍然在调 macOS 系统的 ld 而不是 OHOS clang 的。

修复:toolchain.cmake 里加:

set(CMAKE_OSX_SYSROOT "")
set(CMAKE_OSX_DEPLOYMENT_TARGET "")

强制清空 macOS 特有的 SDK 引用。

9.5 ld 链接报 unsupported file format 类错误

原因:链接器优先选了 Xcode 的 ld 而不是 OHOS 的。

修复:toolchain.cmake 里强制指定:

set(CMAKE_LINKER ${OHOS_SDK}/native/llvm/bin/ld.lld)

9.6 git-lfs 拉 Qt-OHOS 时报 smudge filter lfs failed

原因:git-lfs 没 init。

修复

brew reinstall git-lfs
git lfs install

然后重新 clone。


十、配完后的环境长这样

~/.zshrc 里多了 6 行环境变量

~/ohos-sdk/12/
  └─ native/
      ├─ llvm/bin/clang         ← aarch64 交叉编译器
      ├─ llvm/bin/clang++
      ├─ llvm/bin/ld.lld
      └─ sysroot/                ← OHOS 头文件 + 库

/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/
  ├─ bin/
  │   ├─ moc.exe → /opt/homebrew/opt/qt@5/bin/moc      ← 软链
  │   ├─ uic.exe → /opt/homebrew/opt/qt@5/bin/uic
  │   ├─ rcc.exe → /opt/homebrew/opt/qt@5/bin/rcc
  │   ├─ qmake.exe → /opt/homebrew/opt/qt@5/bin/qmake
  │   ├─ moc.exe.bak                                    ← 原 Windows 二进制备份
  │   └─ ...
  ├─ include/
  ├─ lib/
  │   ├─ libQt5Core.so          ← aarch64 ELF
  │   ├─ libQt5Gui.so
  │   ├─ libQt5Widgets.so
  │   └─ ...
  └─ mkspecs/

/opt/homebrew/opt/qt@5/
  └─ bin/
      ├─ moc                     ← Mac 原生(host 编译用)
      ├─ uic
      ├─ rcc
      └─ qmake

总磁盘占用:约 5.5 GB(OHOS SDK 2.8G + Qt-OHOS 2.0G + qt@5 700M)。


十一、一份"如果今天我重装一遍"的精简清单

把整篇浓缩成 12 步:

# === 1. Xcode CLI Tools ===
xcode-select --install
softwareupdate --install-rosetta --agree-to-license

# === 2. brew 装系统包 ===
brew install cmake ninja qt@5 patchelf wget git-lfs
git lfs install

# === 3. PATH 加 qt@5 ===
echo 'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"' >> ~/.zshrc

# === 4. 下 OHOS SDK ===
mkdir -p ~/ohos-download && cd $_
wget https://repo.huaweicloud.com/openharmony/os/5.0.1-Release/ohos-sdk-windows_linux-public.tar.gz
tar -xzf ohos-sdk-*.tar.gz
mkdir -p ~/ohos-sdk/12
unzip ohos-sdk/darwin/native-darwin-x64-*.zip -d ~/ohos-sdk/12/

# === 5. 拉 Qt-OHOS ===
sudo mkdir -p /opt/qt-ohos && sudo chown $(whoami):staff /opt/qt-ohos
cd /opt/qt-ohos
git clone https://atomgit.com/OpenHarmonyPCDeveloper/ohos_Qt5.12.12.git .
unzip qt_ohos_release/qt-5.12.12-ohos_release_*.zip -d qt-5.12.12-ohos/

# === 6. 软链 host 工具替换 .exe ===
QT_BIN=/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos/bin
HOST_QT=/opt/homebrew/opt/qt@5/bin
for t in moc uic rcc qmake lrelease; do
    mv "$QT_BIN/${t}.exe" "$QT_BIN/${t}.exe.bak"
    ln -sf "$HOST_QT/${t}" "$QT_BIN/${t}.exe"
done

# === 7. 环境变量永久化 ===
cat >> ~/.zshrc <<'EOF'
export OHOS_SDK_ROOT=$HOME/ohos-sdk/12
export QT_OHOS_ROOT=/opt/qt-ohos/qt-5.12.12-ohos/qt-5.12.12-ohos
export OHOS_NATIVE_HOME=$OHOS_SDK_ROOT/native
export Qt5_DIR=$QT_OHOS_ROOT/lib/cmake/Qt5
EOF
source ~/.zshrc

# === 8. 验证 ===
moc -v                      # Qt 5.15.x
$OHOS_SDK_ROOT/native/llvm/bin/clang --version   # OHOS LLVM 15
ls $QT_OHOS_ROOT/lib/libQt5Core.so   # aarch64 ELF

# === 9-12. Hello World 工程 ===
# 见第八章

十二、几个真问题(自问自答)

Q:能用 Linux 虚拟机吗?
A:能,但不推荐——VM 性能损失 + IO 慢,体验比 Rosetta 还差。

Q:在 macOS 26 / Sequoia 上验证过吗?
A:本文是在 macOS 26 / Apple Silicon M3 Max 上写的,验证过。

Q:Apple Silicon vs Intel Mac 哪个更顺?
A:编译速度 Apple Silicon 快很多(M3 比同时代 Intel 快 50%+),但唯一不利是要走 Rosetta 跑 OHOS clang,编译过程慢 15-30%。综合起来 Apple Silicon 还是赢。

Q:可以装 Qt-OHOS 5.15 吗?
A:目前官方只放出了 Qt-OHOS 5.12.12。如果你想用 5.15,要自己交叉编译——成本极高,不推荐。

Q:硬盘空间紧张能省吗?
A:可以只解压 native-darwin-x64.zip 这一个子包(700 MB),整个 SDK 的 2.8 GB 解压完可以删掉。

Q:能换其他 Linux 发行版的 OHOS SDK 吗?
A:不能。Mac 上必须darwin 子目录里那个版本,不是 linux 的。

Q:所有 Qt-OHOS 包里的 .exe 都要替换吗?
A:只需要替换编译期会被调用的:moc / uic / rcc / qmake / lrelease。运行期不会调它们。


十三、写在最后

Mac 上配 Qt 交叉编译环境这事,最大的心理障碍不是技术,是"Mac 不是官方支持的主机平台"

但实际操作下来:

  • ✅ brew 装齐所有 Mac 侧的工具
  • ✅ OHOS 官方有 darwin 子包(虽然是 x64 + Rosetta)
  • ✅ Qt-OHOS 自带的 .exe host 工具用 brew 的 qt@5 替身就行
  • ✅ 一遍配完之后和 Linux 上的体验几乎一样

配完之后你可以在 Mac 上跑通仓库里的 10 个 Qt 适配项目(DiffPDF / KDiff3 / LiteIDE / nomacs / glogg / NitroShare / qjackctl / QElectroTech / NotePad-- / IronLog)——我自己就是这么做的。

如果你卡在某一步,欢迎来 https://harmonypc.csdn.net/——有人撞过同一面 Mac 特有的墙。

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐