【问题标题】:Converting from qmake to cmake, how do I find libraries in the same way?从 qmake 转换为 cmake,我如何以相同的方式找到库?
【发布时间】:2020-12-02 00:58:37
【问题描述】:

在 qmake 我可以有这样的东西:

LIBS += -lopengl32 \
    -lglu32 

这将自动找到 OpenGL 和 GLU 并将其链接到我的应用程序。我怎样才能在cmake中做同样的事情?是不是很简单:

target_link_libraries(${TARGET_NAME} opengl32 glu32)

如果是这样,cmake 如何知道在哪里可以找到这些库?有没有办法做到这一点,而不是涉及find_libraries 调用?以上(如果可行的话)会让我感到焦虑。

【问题讨论】:

  • CMake 命令target_link_libraries 只是将库名称传递给链接器。反过来,链接器会搜索 predefined 位置中的库以及由link_directories 命令添加的库。此功能似乎与 QMake 中 LIBS 提供的功能非常相似,不是吗? CMake 命令find_package 为搜索一些 库提供了更灵活的方式。这种方式是跨平台的,甚至适用于安装到自定义(用户定义)位置的库。

标签: c++ qt cmake qmake


【解决方案1】:

是的,有办法。

关于您提供的样本:

target_link_libraries(${TARGET_NAME} opengl32 glu32)

在这种情况下,当您仅列出要链接的库时,CMake 只会将它们传递给链接器,而无需任何额外工作;是链接器,必须找到它们。

关于 CMake 包含库的方式:

但是,CMake 可以为您提供更多帮助。请看下面的代码 sn-p,它代表了在 CMake 中查找库的首选方式:

#NOTE: this is a complete & working CMakeLists.txt

project(my_opengl_program)

set(TARGET_NAME ${PROJECT_NAME})
set(TARGET_SOURCES my_opengl_program.cpp my_opengl_program.h)

add_executable(${TARGET_NAME} ${TARGET_SOURCES})

find_package(OpenGL REQUIRED)
target_link_libraries(${TARGET_NAME} OpenGL::GL OpenGL::GLU)

不要直接使用find_library,而是使用find_package。它会找到您需要的库(通过在内部使用find_library)并为您设置各种有用的变量。

此外,大多数包还将定义所谓的导入库,在您的情况下,OpenGL::GLOpenGL::GLU 可用于链接。与 CMake 目标 链接的美妙之处在于,您的可执行文件将从用于链接的目标继承所有相关的编译/链接要求。当然,“导入库”也是 CMake 目标 :)

请注意,您的可执行文件有没有个额外的编译/链接选项、包含目录、编译定义等。一切必要的东西都继承自OpenGL::GLOpenGL::GLU

CMake 还为many standard libraries 提供包(向下滚动到“查找模块”)。

关于搜索库

您始终可以直接使用find_library,在这种情况下,您有责任处理图书馆提出的所有要求。

确定搜索库的位置可能相当复杂,并且由各种CMake 变量以及传递给find_library 的参数驱动。在最简单的情况下,当没有相关的CMAKE_* 变量被更改,并且使用基本语法调用 find_library 时,例如:

find_library(GL_LIB opengl32)
fund_library(GLU_LIB glu32)

搜索openGL32glu32 将由CMAKE_SYSTEM_PREFIX_PATHCMAKE_SYSTEM_LIBRARY_PATH CMake 变量控制。

最后,这里是find_libraryfind_packagecmake supported libraries(向下滚动到“查找模块”)、target_link_libraries 的完整文档

[更新]

find_library 与 find_package

有人提出了关于find_libraryfind_package 之间区别的问题。

简而言之,这两个命令不是“竞争”而是“互补”。有人可能会将find_library 视为包含库的低级接口。在这种情况下,find_package 将是一个更高级别的接口,更易于使用。另一方面,find_package 需要库维护者或直接来自 CMake 的额外支持。

深入挖掘问题:

假设某个库是使用 find_library (SOME_OTHER_LIB some_other_lib_name)。如果找到了库,变量SOME_OTHER_LIB 将包含库的路径,这足以用于链接,使用target_link_libraries

但是要真正使用该库,源需要包含SOME_OTHER_LIB 特定的标头,即需要引入另一个find_path(...) 来定位标头,然后是target_include_directories(...)。另外,库所需的编译选项也需要以某种方式提取,并使用target_compile_options(...)引入

当然,如果在多个地方使用了 SOME_OTHER_LIB,则必须全部使用target_include_directoriestarget_compile_optionstarget_link_libraries

必须对使用的每个外部库重复相同的过程。

人们可以快速发现这种模式,而这正是find_package 派上用场的地方。所有底层工作都对最终用户(即使用 CMake 的开发人员)隐藏,并且为她/他提供了一个干净统一的界面。缺点是find_package 需要一种“驱动程序”,它将“驱动”包含外部库的过程。 CMake 直接支持的所有库都可以在cmake-modules 上找到(向下滚动到“查找模块”)。

锦上添花,几乎所有 find 模块还创建所谓的“导入库”(OpenGL::GLOpenGL::GLU 在您的情况下),它们是包含第 3 方库的所有要求的 cmake 目标。所有这些数据都是通过链接导入库来继承的,从而使代码更加简洁。

不幸的是,对于创建的导入库的命名没有“强制措施”(只是指南),因此唯一的解决方案是查看文档。对于OpenGL 模块,可以在FindOpenGL 页面找到。

【讨论】:

  • 这是一个很棒的细分!太感谢了。我想我的问题是,从概念上讲,包与库的区别是什么?我怎么知道 OpenGL 是可以在我的系统上作为包找到的东西?那么我怎么知道它有 OpenGL::GLOpenGL::GLU 作为子库?
  • 嗨,很抱歉回答迟了,但迟到总比没有好:) 我已经更新了答案,包括您在评论中提出的问题。干杯!
猜你喜欢
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-03
相关资源
最近更新 更多