【问题标题】:Link to Qt in CMake --> cannot link to QML/QtQuick function在 CMake 中链接到 Qt --> 无法链接到 QML/QtQuick 函数
【发布时间】:2018-05-11 10:36:31
【问题描述】:

我们正在将一个相当大的代码库从 Ubuntu 14.04 迁移到 16.04。代码库使用 QML 和 QtQuick。

我们在依赖项中使用了 Qt v5.9.1(与系统中安装的 Qt 版本不同)。

编译时我们有以下未定义的引用:

/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `qrand()@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to
`QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent()@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QByteArray::mid(int, int) const@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QPainter::setOpacity(double)@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Qml.so.5.9.1:
undefined reference to `QXmlStreamReader::isCDATA() const@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QAnimationDriver::start()@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Qml.so.5.9.1:
undefined reference to `QLocale::toDate(QString const&, QString
const&) const@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QMetaType::unregisterConverterFunction(int,
int)@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QNetworkReply::finished()@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QMetaType::typeName(int)@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Qml.so.5.9.1:
undefined reference to `QXmlStreamReader::documentEncoding()
const@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QChar::toUpper(unsigned int)@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QTouchEvent::TouchPoint::state() const@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Quick.so.5.9.1:
undefined reference to `QElapsedTimer::start()@Qt_5'
/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/libQt5Qml.so.5.9.1:
undefined reference to `QDateTime::operator==(QDateTime const&)
const@Qt_5'

...它会永远持续下去。错误仅发生在 Qml / QtQuick 函数中,不会发生在其他模块(例如 QtCore、QtWidgets...不输出错误)

所以我们检查了我们的 CMakeLists.txt,这是 Qt 的链接方式:

set(CMAKE_INCLUDE_CURRENT_DIR ON) # Find includes in corresponding    build directories. set(CMAKE_AUTOMOC ON) # Instruct CMake to run moc    automatically when needed.
set(QT_DIR ../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64)
set(CMAKE_PREFIX_PATH ${QT_DIR})

find_package(Qt5Widgets        REQUIRED)
find_package(Qt5Core           REQUIRED)
find_package(Qt5Gui            REQUIRED)
find_package(Qt5OpenGL         REQUIRED)
find_package(Qt5Quick          REQUIRED)
find_package(Qt5Qml            REQUIRED)
find_package(Qt5QuickControls2 REQUIRED)

target_link_libraries(${PROJECT_NAME}
     ...
     Qt5::Widgets
     Qt5::Core
     Qt5::Gui
     Qt5::OpenGL
     Qt5::Quick
     Qt5::Qml
     Qt5::QuickControls2 )

仔细查看我们得到的 CMake 输出:

   Cannot generate a safe runtime search path for target ToolKitApp
because    files in some directories may conflict with libraries in
implicit    directories:

     runtime library [libQt5Sql.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib
     runtime library [libQt5OpenGL.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib
     runtime library [libQt5Widgets.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib
     runtime library [libQt5Gui.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib
     runtime library [libQt5Network.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib
     runtime library [libQt5Core.so.5] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
       /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib

   Some of these libraries may not be found correctly.

因此,Qt 的系统版本与我们在依赖项中使用的版本之间似乎存在不匹配——我们认为这是罪魁祸首。

所以我们修改了我们的 CMakeLists.txt,添加了 set(Qt5_DIR) ...):

set(CMAKE_PREFIX_PATH ${QT_DIR}) set(Qt5Widgets_DIR       
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5Widgets)
set(Qt5Core_DIR          
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5Core)
set(Qt5Gui_DIR           
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5Gui)
set(Qt5OpenGL_DIR        
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5OpenGL)
set(Qt5Quick_DIR         
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5Quick)
set(Qt5Qml_DIR           
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5Qml)
set(Qt5QuickControls2_DIR
../../Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake/Qt5QuickControls2)
find_package(Qt5Widgets        REQUIRED NO_DEFAULT_PATH)
find_package(Qt5Core           REQUIRED NO_DEFAULT_PATH)
find_package(Qt5Gui            REQUIRED NO_DEFAULT_PATH)
find_package(Qt5OpenGL         REQUIRED NO_DEFAULT_PATH)
find_package(Qt5Quick          REQUIRED NO_DEFAULT_PATH)
find_package(Qt5Qml            REQUIRED NO_DEFAULT_PATH)
find_package(Qt5QuickControls2 REQUIRED NO_DEFAULT_PATH)

但这并没有改善情况。

知道发生了什么吗?

------------------编辑------------------

我们对 CMakeLists.txt 做了如下修改

set(CMAKE_PREFIX_PATH   /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64)
find_package(Qt5 COMPONENTS Core Gui OpenGL Quick QmlQuickControls2)

message("Qt5               : " Qt5_DIR)
message("Qt5Core           : " Qt5Core_DIR)
message("Qt5Widgets        : " Qt5Widgets_DIR)
message("Qt5Gui            : " Qt5Gui_DIR)
message("Qt5OpenGL         : " Qt5OpenGL_DIR)
message("Qt5Quick          : " Qt5Quick_DIR)
message("Qt5Qml            : " Qt5Qml_DIR)
message("Qt5QuickControls2 : " Qt5QuickControls2_DIR)

没有改变行为,而是输出

Qt5               : /usr/lib/x86_64-linux-gnu/cmake
Qt5Core           : /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake
Qt5Widgets        : /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake
Qt5Gui            : /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake
Qt5OpenGL         : /home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64/lib/cmake
Qt5Quick          : /usr/lib/x86_64-linux-gnu/cmake
Qt5Qml            : /usr/lib/x86_64-linux-gnu/cmake
Qt5QuickControls2 : /usr/lib/x86_64-linux-gnu/cmake

确认 Qt 的系统/包版本与自定义/依赖项版本不匹配,但不提供解决方案。

【问题讨论】:

    标签: qt ubuntu cmake qml qtquick2


    【解决方案1】:

    根据您的输出,我猜您有以下设置:

    • 您通过包管理器安装了一些(但不是全部)Qt 5 库(包括开发文件)。
    • 但是,您可能没有安装 QtQuick(开发)库。
    • 另外,您在/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/ 中安装了Qt(我猜是通过官方Qt 安装程序安装的)。
    • 我猜你尝试编译和链接你家中的 Qt 版本。

    我认为您配置项目的方式(即您调用 cmake 的方式)有问题,因为 CMake 似乎首先在您的系统位置搜索 Qt 并且 - 当您在 @987654324 中设置一些变量时@ 文件,这迫使它也考虑在您的主目录中安装 - 有选择地链接到来自其他 Qt 安装的 Quick 库。这肯定会导致此类链接器错误,特别是如果系统 Qt 版本比您在家中安装的版本旧。

    长话短说:您是否尝试过调用 CMake,并在命令行上将 CMAKE_PREFIX_PATH 变量传递给它?在你的例子中,我想它应该是这样的:

    cmake \
        -DCMAKE_PREFIX_PATH=/home/onilsson/DevRoot/Dependencies/Qt/v5.9.1/5.9.1/gcc_64 \
        ..
    

    绝对不需要设置Qt5Core_DIR 等。根据我使用 Qt 和 CMake 的经验,当您需要设置这些时,您的设置有问题。

    【讨论】:

    • 马丁,感谢您的回答。阅读您的评论,您的分析看起来不错。我今天无法检查您的建议,但我明天会试一试。同时,您建议从命令行设置CMAKE_PREFIX_PATH,虽然我们已经在CMakeLists.txt中设置了它,但是命令行语句更强吗?
    • 据我所知:是的。在 CMake 中,有一些变量需要在配置过程的早期设置。此类变量需要通过-D 开关或Toolchain File 从外部设置。
    • 我们已经从命令行设置了 CMAKE_PREFIX_PATH,这并没有改变行为。虽然我们已经在消息中打印了 Qt5Core_DIR 等,但输出似乎证实了您的分析(检查帖子编辑)。
    • 这种奇怪的行为是否是由于另一个依赖项也使用 Qt,但是 Qt 的系统/包(不是我们的自定义/依赖项版本)并造成了这种不匹配?
    • 当然。不支持混合不同的 Qt 版本,并且除了其他奇怪的效果外,还可能导致此类链接错误。尝试根据自定义 Qt 版本编译所有依赖项。
    【解决方案2】:

    正如 Martin 所说,CMake 似乎链接到新系统中的库,而不是从旧系统移植的库。此外,您的新系统通过 Ubuntu/Debian Aptitude 包管理器安装了 Qt 库,并且缺少 qtdeclarative5-dev 和 qml 模块包(您可以使用 sudo apt install qtdeclarative5-dev qtquick* 在 Ubuntu 上安装它们)。 我猜测 CMake 没有链接到您的移植库的原因可能是因为所有权问题。您是否尝试在父目录中使用“ls -lah”命令检查所有权。所有权现在可能已分配给 root,您可以使用“sudo chown -R username:group Directory”命令更改它。

    【讨论】:

    • 我已经使用 sudo apt install qtdeclarative5-dev qtquick/asterisk ** 安装了其他软件包,但它似乎没有改变任何东西......我们还检查了我们的依赖关系的所有权和它们都设置为 **onilsson:onilsson。哼……
    猜你喜欢
    • 2020-06-19
    • 1970-01-01
    • 2022-10-07
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多