我刚刚开始学习如何使用 CMake,我正在尝试将
glfw
文件包含到我的项目中。我真的试图推迟在 StackOverflow 上提问,但到目前为止,我已经花了 2 天时间阅读一个又一个教程,但毫无效果,所以我真的很感谢任何指导/帮助来为我指明正确的方向。
我的项目结构如下:
main.cpp
CMakeLists.txt
build
dependencies
- glfw
- lib
- libglfw.3.dylib
- include
- glfw3.h
- glfw3native.h
我从 https://www.glfw.org/download.html 下载了适用于 MacOS 的预构建二进制文件,并将头文件和
.dylib
文件移动到我的项目目录中。
我的
CMakeLists.txt
文件当前如下所示:
cmake_minimum_required(VERSION 3.27)
project(demo)
add_executable(demo main.cpp)
include_directories(${CMAKE_SOURCE_DIR}/dependencies/glfw/include)
link_directories(${CMAKE_SOURCE_DIR}/dependencies/glfw/lib)
if (APPLE)
target_link_libraries(demo PRIVATE
"-framework OpenGL"
)
endif()
add_library(glfw SHARED IMPORTED)
target_sources(glfw INTERFACE ${CMAKE_SOURCE_DIR}/dependencies/glfw/lib/libglfw.3.dylib)
target_link_libraries(demo INTERFACE glfw)
# set_target_properties(glfw PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/dependencies/glfw/lib/libglfw.3.dylib)
在 VSCode 上运行
CMake: Build
报告 glfw 存在未定义的符号。我知道这意味着我没有正确链接库,但我不知道哪里出了问题。
我对CMake的概念理解是:
include_directories
告诉 CMake 在哪里查找头文件,因此我可以使用 #include
预处理器指令。这在 main.cpp
中运行得很好,我可以 #include <glfw3.h>
,甚至可以看到函数和类型的 IntelliSense 提示。link_directories
告诉 CMake 在哪里寻找库。它实际上并不进行链接,只进行搜索。add_library(<name> <type> IMPORTED)
“引用位于项目外部的库文件”[源]。它创建了名为 <name>
的目标,使其在我的 CMake 项目中可用。 (在这种情况下,从技术上讲,该库不在项目目录“外部”,但我认为这并不重要,因为我只需提供二进制文件的完整路径。)target_sources
指定使用哪些文件来构建目标,也称为源文件。我不确定是否需要“构建”目标,因为它已经是预编译的二进制文件,所以我认为我在这里做错了什么。我还尝试使用 set_target_properties
函数(已注释掉),但它也不起作用(仍然出现未定义符号错误)。glfw
将 target_link_libraries
目标链接到我的主项目的目标。在我看来,这告诉链接器链接 glfw
目标。由于我指定了 (1) 在哪里搜索文件,以及 (2) 要搜索什么文件,所以它应该可以工作。之前,我在项目中使用
vcpkg
并在本地安装了glfw文件。我用过
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake)
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/vcpkg/packages/glfw3_arm64-osx/share/glfw3 ${CMAKE_PREFIX_PATH})
find_package(glfw3 CONFIG REQUIRED)
target_link_libraries(demo PRIVATE glfw)
target_include_directories(demo PRIVATE ${CMAKE_SOURCE_DIR}/vcpkg/packages/glfw3_arm64-osx/include/GLFW)
这实际上工作得很好,但我不喜欢链接静态
libglfw3.a
文件。我不想静态链接该文件,因为我知道它会影响可执行文件的整体文件大小。我想学习如何在运行时正确链接动态文件。
我真的很想学习如何很好地使用 CMake,并且不想被其明显的复杂性所打败,据我所知,它有自己的社区,里面有一些讨厌它的人。任何帮助我指明正确方向/说明“正确”做事方式(如果有的话)的帮助将不胜感激。我真的希望有一个关于如何使用 CMake 的清晰、明确的事实来源。如果有人可以提供最新的教程,那也是一件幸事。谢谢。
没关系,我自己想出来了。我正确链接了库,但没有设置运行时路径 (CMAKE_BUILD_RPATH) 变量。编译器需要设置 RPATH,以便在运行时能够正确找到
.dylib
文件。添加一行就解决了。
set(CMAKE_BUILD_RPATH ${CMAKE_SOURCE_DIR}/dependencies/glfw/lib/libglfw.3.dylib)
现在我明白需要 RPATH 来查找
.dll
文件及其等效项,我意识到这是一个相当微不足道的问题。
但我只是希望无论是谁投了反对票,至少能告诉我我哪里出错了/我如何能更好地提出我的问题,而不是仅仅投反对票,除了向我表明我问了一个“愚蠢”的问题之外,不提供任何帮助。
这就是我尽可能多地在 StackOverflow 上提问的原因之一,以免我的问题被贴上“坏”问题的标签,尽管我尽了最大努力遵循提问指南。