首页 > 解决方案 > 使用 CMake 在 MacOS 应用程序中链接 GLFW 的正确方法是什么?

问题描述

我是 CMake 新手,无法让我的简单 MacOS 应用程序(此时只是学习 OpenGL 教程)链接到 GLFW 所需的 MacOS 框架。我所有的代码都在main.cpp里面,我正在使用生成的高兴源文件。我的源代码树如下所示:

.
├── CMakeLists.txt
├── glad
│  └── glad.h
├── glad.c
├── KHR
│  └── khrplatform.h
└── main.cpp

这是我的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

project(simple_repro)

set(CMAKE_CXX_STANDARD 17)

find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)

add_executable(app1 main.cpp glad.c)
target_include_directories(app1 PRIVATE
  ${CMAKE_SOURCE_DIR}
  ${GLFW_INCLUDE_DIRS}
)

target_link_libraries(app1 ${GLFW_STATIC_LDFLAGS})

当我构建时,我得到这个错误:

/Library/Developer/CommandLineTools/usr/bin/c++  -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/app1.dir/main.cpp.o CMakeFiles/app1.dir/glad.c.o -o app1  -L/usr/local/lib -lglfw3 -framework -lCocoa -framework -lIOKit -framework -lCoreFoundation -lCocoa -lIOKit -lCoreFoundation
ld: framework not found -lCocoa
clang: error: linker command failed with exit code 1 (use -v to see invocation)

从表面上看,原因很明显:在链接器命令中,框架部分${GLFW_STATIC_LDFLAGS}被破坏了。框架的名称是前置的-l,它们是重复的。供参考,pkg_search_module调用后,GLFW_STATIC_LDFLAGS是:

-L/usr/local/lib;-lglfw3;-framework;Cocoa;-framework;IOKit;-framework;CoreFoundation

请注意,我无法控制它的格式;它由pkg_search_module.

我认为如果框架部分扩展为:

-framework Cocoa -framework IOKit -framework CoreFoundation

我会做生意的。但相反,它的出现是

-framework -lCocoa -framework -lIOKit -framework -lCoreFoundation -lCocoa -lIOKit -lCoreFoundation

所以我的问题的核心是:我需要做什么才能从 的输出中生成正确的链接器命令pkg_search_module?我用谷歌搜索了我能想到的所有东西,并尝试了很多东西,但无济于事。我探索的一些亮点:

pkg_search_module(GLFW REQUIRED IMPORTED_TARGET glfw3)
...
target_link_libraries(app1 PUBLIC PkgConfig::GLFW)

这导致在链接器命令中基本上没有对 MacOS 框架的引用以及(正如我所料)一堆核心平台未定义的符号:

/Library/Developer/CommandLineTools/usr/bin/c++  -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/app1.dir/main.cpp.o CMakeFiles/app1.dir/glad.c.o -o app1  /usr/local/lib/libglfw3.a
Undefined symbols for architecture x86_64:
  "_CFArrayAppendValue", referenced from:
      __glfwInitJoysticksNS in libglfw3.a(cocoa_joystick.m.o)
      _matchCallback in libglfw3.a(cocoa_joystick.m.o)
  "_CFArrayCreateMutable", referenced from:
... and many pages more

/Library/Developer/CommandLineTools/usr/bin/c++  -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/usr/local/lib;-lglfw3;-framework;Cocoa;-framework;IOKit;-framework;CoreFoundation CMakeFiles/app1.dir/main.cpp.o CMakeFiles/app1.dir/glad.c.o -o app1  /usr/local/lib/libglfw3.a
ld: warning: directory not found for option '-L/usr/local/lib;-lglfw3;-framework;Cocoa;-framework;IOKit;-framework;CoreFoundation'

非常感谢您在确定什么咒语将从pkg_search_module输出中生成正确的链接器命令的任何帮助。

编辑:为了回应 Tsyvarev 下面的评论,我将 CMakeLists.txt 更改为:

cmake_minimum_required(VERSION 3.5)

project(simple_repro)

set(CMAKE_CXX_STANDARD 17)

find_package(PkgConfig REQUIRED)
pkg_check_modules(GLFW REQUIRED glfw3)

add_executable(app1 main.cpp glad.c)
target_include_directories(app1 PRIVATE
  ${CMAKE_SOURCE_DIR}
  ${GLFW_INCLUDE_DIRS}
)

target_link_libraries(app1 ${GLFW_LIBRARIES})

message(STATUS "GLFW_LIBRARIES is ${GLFW_LIBRARIES}")

target_compile_options(app1 PUBLIC ${GLFW_CFLAGS_OTHER})

这会输出-- GLFW_LIBRARIES is glfw3并生成此链接器命令,该命令不包含 glfw3 的完整路径,也不包含所需的系统框架:

/usr/local/Cellar/cmake/3.21.2/bin/cmake -E cmake_link_script CMakeFiles/app1.dir/link.txt --verbose=1
/Library/Developer/CommandLineTools/usr/bin/c++  -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/app1.dir/main.cpp.o CMakeFiles/app1.dir/glad.c.o -o app1  -lglfw3

这是pkg_search_module调用后的 GLFW_* 变量的完整列表,以防万一:

-- GLFW_CFLAGS=-I/usr/local/include
-- GLFW_CFLAGS_I=
-- GLFW_CFLAGS_OTHER=
-- GLFW_FOUND=1
-- GLFW_INCLUDEDIR=/usr/local/include
-- GLFW_INCLUDE_DIRS=/usr/local/include
-- GLFW_LDFLAGS=-L/usr/local/lib;-lglfw3
-- GLFW_LDFLAGS_OTHER=
-- GLFW_LIBDIR=/usr/local/lib
-- GLFW_LIBRARIES=glfw3
-- GLFW_LIBRARY_DIRS=/usr/local/lib
-- GLFW_LIBS=
-- GLFW_LIBS_L=
-- GLFW_LIBS_OTHER=
-- GLFW_LIBS_PATHS=
-- GLFW_LINK_LIBRARIES=/usr/local/lib/libglfw3.a
-- GLFW_MODULE_NAME=glfw3
-- GLFW_PREFIX=/usr/local
-- GLFW_STATIC_CFLAGS=-I/usr/local/include
-- GLFW_STATIC_CFLAGS_I=
-- GLFW_STATIC_CFLAGS_OTHER=
-- GLFW_STATIC_INCLUDE_DIRS=/usr/local/include
-- GLFW_STATIC_LDFLAGS=-L/usr/local/lib;-lglfw3;-framework;Cocoa;-framework;IOKit;-framework;CoreFoundation
-- GLFW_STATIC_LDFLAGS_OTHER=-framework;Cocoa;-framework;IOKit;-framework;CoreFoundation
-- GLFW_STATIC_LIBDIR=
-- GLFW_STATIC_LIBRARIES=glfw3
-- GLFW_STATIC_LIBRARY_DIRS=/usr/local/lib
-- GLFW_STATIC_LIBS=
-- GLFW_STATIC_LIBS_L=
-- GLFW_STATIC_LIBS_OTHER=
-- GLFW_STATIC_LIBS_PATHS=
-- GLFW_VERSION=3.3.4
-- GLFW_glfw3_INCLUDEDIR=
-- GLFW_glfw3_LIBDIR=
-- GLFW_glfw3_PREFIX=
-- GLFW_glfw3_VERSION=
-- __pkg_config_arguments_GLFW=REQUIRED;glfw3
-- __pkg_config_checked_GLFW=1
-- pkgcfg_lib_GLFW_glfw3=/usr/local/lib/libglfw3.a

标签: c++macoscmakeglfw

解决方案


最后,我放弃了 pkg-config 并最终让它与 find_package 一起工作。这是我最终得到的 CMakeLists.txt,基于GLFW 指南

cmake_minimum_required(VERSION 3.5)

project(simple_repro)

set(CMAKE_CXX_STANDARD 17)

find_package(glfw3 3.3 REQUIRED)

add_executable(app1 main.cpp glad.c)
target_include_directories(app1 PRIVATE
  ${CMAKE_SOURCE_DIR}
)

target_link_libraries(app1 glfw)

find_package(OpenGL REQUIRED)
target_link_libraries(app1 OpenGL::GL)

推荐阅读