如何使macdeployqt在复制QtWebEngineCore框架时更改QtWebEngineProcess.app内的库名称

How to make macdeployqt change the library names inside QtWebEngineProcess.app when it copies over QtWebEngineCore framework

编辑:使用 Qt 5.9.1,安装 Homebrew

根据此 other question 中的评论,我们正在尝试使用 macdeployqt 来准备基于 Qt 的应用程序的 OSX 包的分发。

此工具正确地复制了包内的所有 Qt 依赖项(甚至一些非 Qt 库)。它还会更改应用程序本身和复制的库中的依赖库名称。

它也成功复制了QtWebEngineProcess.app包含在QtWebEngineCore.frameworkHelpers文件夹中的QtWebEngineCore.framework ].

问题

一个问题是它没有更改依赖库名称inside QtWebEngineProcess,所以包是不可重定位的(因为QtWebEngineProcess通过仅在开发机器上有效的绝对路径引用其依赖库)。 尝试在 "client" 机器上 运行 应用程序,因此会出现错误:

dyld: Library not loaded: /usr/local/Cellar/qt/5.9.1/lib/QtWebEngineCore.framework/Versions/5/QtWebEngineCore Referenced from: Business.app/Contents/Frameworks/QtWebEngineCore.framework/Helpers/QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess

我们尝试手动修复此应用程序,方法是编辑 QtWebEngineProcess,将 Qt 库路径的绝对部分替换为 @loader_path/../../../../../../../../Frameworks/

这只会将问题向前推进:现在 QtWebEngineProcess 似乎正确地加载了它的依赖库,但是依赖库本身不能再加载它们的依赖库,因为它们的安装名称正在开始@executable_pathQtWebEngineProcess 可执行文件与 Business 可执行文件位于不同的文件夹中。因此错误:

dyld: Library not loaded: @executable_path/../Frameworks/QtQuick.framework/Versions/5/QtQuick
Referenced from: Business.app/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/QtWebEngineCore


当涉及到使用 Qt 的网络引擎的应用程序时,macdeployqt 是否损坏?

有没有办法让它工作而无需手动重新更改捆绑包中的所有 Qt 安装名称?

到目前为止 macdeployqt 在本地机器上对我来说工作正常。 在 CI 上,您可能会遇到工件以某种方式损坏的问题。

如果您使用 cp -rzip 复制您的应用程序而没有 -y 选项,则会发生这种情况,然后所有符号链接都将在应用程序内部解析,并且它将无法工作,因为是 QtWebEngineProcess 的许多副本。如果您签署应用程序,它也会破坏您的签名。

解决方案是改用 cp -azip -r -y - 最后一个对我有用,而不是使用工件插件。

根据 Dmitry 对原始问题的评论之一,我终于花时间用 Qt 5.9.1 的官方发行版测试 OS X,事实证明他是对的。 macdeployqt 与 Qt 的官方二进制文件一起分发可以很好地处理 QtWebEngineProcess.app。

homebrew 安装的 Qt 分发的此实用程序的版本是伪造的,至少在 5.9.1

我制作了以下脚本,它使用 install_name_tool 修复了这些路径:

#!/bin/bash
set -x -e

pushd MyApp.app/Contents/Frameworks/QtWebEngineCore.framework/Helpers/QtWebEngineProcess.app/Contents/MacOS

for LIB in QtGui QtCore QtWebEngineCore QtQuick QtWebChannel QtQml QtNetwork QtPositioning
do
    OLD_PATH=`otool -L QtWebEngineProcess | grep ${LIB} | cut -f 1 -d ' '`
    NEW_PATH="@loader_path/../../../../../../../${LIB}.framework/${LIB}"
    install_name_tool -change ${OLD_PATH} ${NEW_PATH} QtWebEngineProcess
done

popd

请注意,当用作 install_name_tool 参数时,${OLD_PATH} 周围缺少引号。这是因为 OLD_PATH 的值在路径周围有一些额外的空格,不应保留这些空格。如果 Qt 是通过 Homebrew 安装的,那么缺少引号通常是无害的,因为这些路径不包含空格。但是,这可以改进。

重要:此修复足以使简单浏览器(来自 Qt 示例)运行。但是在更高级的项目中,可能需要更多的操作。