从 qmake 转换为 cmake,如何以相同的方式查找库?

Converting from qmake to cmake, how do I find libraries in the same way?

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

LIBS += -lopengl32 \
    -lglu32 

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

target_link_libraries(${TARGET_NAME} opengl32 glu32)

如果是这样,cmake 如何知道在哪里可以找到这些库?有没有一种方法可以改为涉及 find_libraries 调用?以上(如果有效)会让我感到焦虑。

是的,有办法。

关于您提供的样本:

target_link_libraries(${TARGET_NAME} opengl32 glu32)

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

关于CMake包含库的方式:

但是,CMake 可能会帮助您更多。请查看以下代码片段,它代表了在 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)并为您设置各种有用的变量。

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

请注意,有 NO 额外的 compile/link 选项,包括目录、编译定义等...用于您的可执行文件。一切必要的东西都继承自 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_library, find_package, cmake supported libraries (scroll down to "Find Modules"), target_link_libraries

的完整文档

[更新]

find_library 对比 find_package

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

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

深入挖掘问题:

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

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

引入

当然,如果SOME_OTHER_LIB用在一处以上,则target_include_directoriestarget_compile_optionstarget_link_libraries都必须全部用到。

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

人们可以快速发现规律,这正是 find_package 派上用场的地方。所有 low-level 的工作对 end-user(即使用 CMake 的开发人员)都是隐藏的,并且 she/he 以干净统一的界面呈现。缺点是 find_package 需要一种“某种 driver” 来“驱动”包含外国图书馆的过程。 CMake 直接支持的所有库都可以在 cmake-modules 上找到(向下滚动到“查找模块”)。

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

不幸的是,对于创建的导入库的命名没有“强制执行”(只是指南),所以唯一的解决办法是检查文档。对于 OpenGL 模块,可以在 FindOpenGL 页面上找到。