在 Qt 中使用 CMake 的主项目之前,您如何构建依赖库?

问题描述

我看过类似的问题,但没有找到适合这个基本场景的问题。我对 CMake 比较陌生。我有一个基于 CMake 的 Qt 5 项目。这是一个简单的测试应用程序;在构建过程中,我想构建并静态链接开源 Paho MQTT C 库和它的 C++ 包装器。这是两个独立的项目,具有自己的 CMakeLists.txt 文件

根据 Qt 的认设置,它会构建到源代码树之外的目录中。

我已将这些开源库的源代码树复制到我项目的父目录下,并编辑了顶级 CMakeLists.txt 文件以将它们添加到子目录中。

我还添加了 target_link_libraries。我可以自己获取 C 库来构建并链接到父项目,但是如果我添加 C++ 包装器,C++ 包装器的处理会抱怨它找不到 C 库......这是真的,因为它没有还没建好通过简单地使用 Qt 的“构建所有项目”菜单解决了对 C 库的类似抱怨,但是当添加 C++ 包装库时,这不起作用。包装器的 CMakeLists.txt 文件发出这个:

paho.mqtt.cpp/src/CMakeLists.txt 中的 CMake 错误:150(消息): 找不到 Paho MQTT C 库

果然它不存在,因为它在这个预处理完成时还没有被构建。

更新:这是我的顶级 CMakeLists.txt 文件,根据 Corristo 的建议进行了修订,该文件成功地让 CMake 解析了整个层次结构。项目现在建立。不过,我很困惑这里的最后两行结果是一个空字符串。对链接目录的类似尝试也是如此。

find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets required)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets required)

set(PROJECT_SOURCES
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
    task.h
    task.cpp
    task.ui
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(MQTTTest
        ${PROJECT_SOURCES}
    )
else()
    if(ANDROID)
        add_library(MQTTTest SHARED
            ${PROJECT_SOURCES}
        )
    else()
        add_executable(MQTTTest
            ${PROJECT_SOURCES}
        )
    endif()
endif()

add_subdirectory(paho.mqtt.c)
set(PAHO_MQTT_C_LIB paho-mqtt3a)
set(PAHO_MQTT_C_PATH "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c")
add_subdirectory(paho.mqtt.cpp)

target_link_libraries(MQTTTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_directories(MQTTTest PUBLIC
                        "${CMAKE_CURRENT_LIST_DIR}/build/paho.mqtt.c/src"
                        "${CMAKE_CURRENT_LIST_DIR}/build/paho.mqtt.cpp/src")

target_link_libraries(MQTTTest PUBLIC paho-mqtt3a)
target_link_libraries(MQTTTest PUBLIC paho-mqttpp3)

target_include_directories(MQTTTest PUBLIC
                        "${PROJECT_BINARY_DIR}"
                        "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c/src"
                        "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.cpp/src")

get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("Top-level include dirs = ${inc_dirs}")

enter image description here

解决方法

这是一个小技巧,但您可以利用这样一个事实:如果结果变量已经设置,CMake find_* 命令不会执行搜索。

paho.mqtt.cpp/src/CMakeLists.txt 文件中我们发现 find_library 的输出变量名为 PAHO_MQTT_C_LIB 并且包含目录应该在 PAHO_MQTT_C_INC_DIR 中,它在 {{ 3}}(这似乎是您使用的版本)本身是根据 PAHO_MQTT_C_PATH 计算的。

在两个 add_subdirectory 调用之间设置这两个变量应该可以完成这项工作:

add_subdirectory(paho.mqtt.c)
set(PAHO_MQTT_C_LIB paho-mqtt3a)
set(PAHO_MQTT_C_PATH "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c")
add_subdirectory(paho.mqtt.cpp)

这利用了 target_link_libraries 可以通过库文件(这是原始 paho.mqtt.cpp 项目所期望的)和现有 CMake 目标(这是我们替换它的目标)调用的事实.链接到 CMake 目标也会自动引入构建顺序依赖项,因此这同时确保了 c 库在 cpp 库之前构建。

但是,由于这依赖于 paho.mqtt.cpp 项目中使用的变量的名称以及 paho.mqtt.c 项目中库目标的目标名称,因此在您更新其中一个时可能会中断将这些库更新到更新版本。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...