将 GLEW 与 cmake 链接的问题

Posted

技术标签:

【中文标题】将 GLEW 与 cmake 链接的问题【英文标题】:Problems linking GLEW with cmake 【发布时间】:2021-12-08 13:18:08 【问题描述】:

我有一个使用 VTK 渲染的 C++ 项目,该项目是使用 MXE 为 Windows 构建的。 这个项目在过去建造得很好。最近,我构建它的机器发生了变化,主要是添加了一个额外的硬盘驱动器并完成了完整的更新。从那时起,我的旧版本在链接阶段失败并出现以下错误:

[8%] Linking CXX executable <name>.exe
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):
vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4299):
undefined reference to `__imp___glewGenVertexArrays'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x42ae):
undefined reference to `__imp___glewGenBuffers'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4300):
undefined reference to `__imp___glewDeleteVertexArrays'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4323):
undefined reference to `__imp___glewBindBuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4331):
undefined reference to `__imp___glewDeleteBuffers'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4353):
undefined reference to `__imp___glewBindBuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x4361):
undefined reference to `__imp___glewDeleteBuffers'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x12cc3):
undefined reference to `__imp___glewBindVertexArray'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x12cd0):
undefined reference to `__imp___glewBindBuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x12f0d):
undefined reference to `__imp___glewBindVertexArray'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x12f1a):
undefined reference to `__imp___glewBindBuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x12f2b):
undefined reference to `__imp___glewBufferData'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text+0x1300d):
undefined reference to `__imp___glewBufferData'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text$_ZN18vtkVolumeStateRAIID1Ev[_ZN18vtkVolumeStateRAIID1Ev]+0x9):
undefined reference to `__imp___glewBindVertexArray'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLGPUVolumeRayCastMapper.cxx.obj):vtkOpenGLGPUVolumeRayCastMapper.cxx:(.text$_ZN18vtkVolumeStateRAIID1Ev[_ZN18vtkVolumeStateRAIID1Ev]+0x17):
undefined reference to `__imp___glewBindBuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLProjectedTetrahedraMapper.cxx.obj):vtkOpenGLProjectedTetrahedraMapper.cxx:(.text+0x43ea):
undefined reference to `__imp___glewDrawRangeElements'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLProjectedTetrahedraMapper.cxx.obj):vtkOpenGLProjectedTetrahedraMapper.cxx:(.text+0x4494):
undefined reference to `__imp___glewBlitFramebuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkOpenGLProjectedTetrahedraMapper.cxx.obj):vtkOpenGLProjectedTetrahedraMapper.cxx:(.text+0x48f7):
undefined reference to `__imp___glewBlitFramebuffer'
/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libvtkRenderingVolumeOpenGL2-8.2.a(vtkVolumeTexture.cxx.obj):vtkVolumeTexture.cxx:(.text+0x3349):
undefined reference to `__imp___glewTexSubImage3D'
collect2: error: ld returned 1 exit status

在我看来,它似乎无法找到 GLEW 库文件。 (请注意,所有缺失的引用都有前缀glew。)

我第一次尝试解决这个问题是添加类似的东西

find_package(GLEW REQUIRED)
include_directories($GLEW_INCLUDE_DIRS)
link_libraries($GLEW_LIBRARIES)

到我的 CMakeLists。 (请注意,我很少使用 cmake 工作,而这和以下可能只是我做事不正确。) 这导致

CMake Error at /opt/mxe/usr/x86_64-pc-linux-gnu/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:164 (message):
  Could NOT find GLEW (missing: GLEW_LIBRARIES) (found version "2.1.0")
Call Stack (most recent call first):
  /opt/mxe/usr/x86_64-pc-linux-gnu/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:445 (_FPHSA_FAILURE_MESSAGE)
  /opt/mxe/usr/x86_64-pc-linux-gnu/share/cmake-3.17/Modules/FindGLEW.cmake:207 (find_package_handle_standard_args)
  CMakeLists.txt:41 (find_package)

鉴于此,我假设我需要在这里设置一些变量,因为毕竟我应该使用 MXE 附带的 GLEW 库。所以我在前面加了

set(GLEW_INCLUDE_DIR "/opt/mxe/usr/x86_64-w64-mingw32.static/include/GL/")
set(GLEW_SHARED_LIBRARIES "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/glew32.lib")
set(GLEW_STATIC_LIBRARIES "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/glew32s.lib")
set(GLEW_LIBRARIES "optimized;/opt/mxe/usr/x86_64-w64-mingw32.static/lib/glew32s.lib;debug;optimized;/opt/mxe/usr/x86_64-w64-mingw32.static/lib/glew32s.lib")
# just to see if there is more information gained by this:
set(GLEW_VERBOSE)

尽管设置了GLEW_LIBRARIES,但仍会导致与以前相同的错误。

根据Linking GLEW with CMake 中的回答,另一个失败的尝试是添加

set(GLEW_LIBRARY "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/")
find_path(GLEW_INCLUDE_DIR glew.h)
find_library(GLEW_LIBRARY NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64)

在这一点上,我感觉我的方法可能是错误的,而不是添加到 CMakeLists,我可能不得不做 一些事情 其他。可能配置 MXE?毕竟,它以前没有额外的行就可以工作。 或者如果我的方法是正确的,也许我的论点不是?路径是现有文件。 有人知道还有什么可以尝试的吗?


编辑:请注意,即使没有我的链接,它根本找不到 GLEW 也很奇怪,因为该系统已将 GLEW 作为常规包安装:

sudo apt-get install -y libglew-dev
  Reading package lists... Done
  Building dependency tree       
  Reading state information... Done
  libglew-dev is already the newest version (2.1.0-4).
  0 upgraded, 0 newly installed, 0 to remove and 12 not upgraded.

编辑:根据 Some Programmer Dude 和 Tsyvarev 在 cmets 中所写的内容,我当前的设置看起来有点像这样:

...

find_package(VTK REQUIRED)
include($VTK_USE_FILE)

set(GLEW_INCLUDE_DIR "/opt/mxe/usr/x86_64-w64-mingw32.static/include/")
set(GLEW_LIBRARY "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/")
find_path(GLEW_INCLUDE_DIR GL/glew.h)
add_library(GLEW_LIBRARY glew32 glew glew32s)

include_directories("/opt/mxe/usr/x86_64-w64-mingw32.static/include/GL/" $GLEW_LIBRARY)
link_directories($GLEW_LIBRARY)

...

target_link_libraries(<MyExecutable> <other libraries> -lglew32s -lglew32 -lGLEW)

(有几行很可能不需要)。

链接器似乎找到了库文件(没有找到任何东西的错误),但引用仍然未定义。

我的想法是库文件是否真的指定了所需的符号,如果可能是某些版本不兼容,所以我执行了

nm libglew32

并在输出中搜索“glewGenVertexArrays”,是的,存在:

0000000000003a68 B __glewGenVertexArrays

为了提供更多信息,这里是我的 CMakeLists.txt 的内容,没有上面提到的 GLEW 的附加行,并且项目名称等某些部分被替换为 &lt;placeholder&gt; 之类的东西:

set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")

cmake_minimum_required(VERSION 3.1.0)

PROJECT(<name>)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt5 REQUIRED Core Gui Svg Widgets Xml)
find_package(Qt5 COMPONENTS Network REQUIRED)
find_package(BZip2 REQUIRED)

find_package(VTK REQUIRED)
include($VTK_USE_FILE)

qt5_add_resources(<name> resources.qrc)

include_directories (<some subdirectories>)
LINK_DIRECTORIES ( release /var/opt/mxe/usr/x86_64-w64-mingw32.static/qt5/lib /var/opt/mxe/usr/x86_64-w64-mingw32.static/lib/)
qt5_wrap_ui(UISrcs $UI_FILES )

set(APP_ICON_RESOURCE_WINDOWS <icon file>)

add_executable(<name> WIN32 main/main.cpp $APP_ICON_RESOURCE_WINDOWS)

qt5_use_modules(<name> Core Gui Svg Widgets Xml Network)

target_link_libraries(<name> core Qt5::Core Qt5::QWindowsIntegrationPlugin Qt5::QSvgPlugin $QT5ALL_LDFLAGS Qt5::Widgets Qt5::Xml Qt5::Svg Qt5::Gui Qt5::Network $QT5SVG_LIBRARIES -lQt5EventDispatcherSupport -lQt5AccessibilitySupport -lQt5FontDatabaseSupport -lQt5ThemeSupport -lQt5WindowsUIAutomationSupport $VTK_LIBRARIES -lfreetype -lharfbuzz_too -lfreetype_too $BZIP2_LIBRARIES)

在此,core 是一个包含项目大部分类的库,基本上除了 main 函数之外的所有类。

除了之前写的,我尝试在上面的最后一行显式添加库文件:

target_link_libraries(<name> <other libraries> /var/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libGLEW.a /var/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libglew32.a /var/opt/mxe/usr/x86_64-w64-mingw32.static/lib/libglew32s.a)

也不行。


另外,我注意到以下几点:在编译期间,cmake 创建了一个文件CMakeFiles/GLEW_LIBRARY.dir/link.txt。该文件包含

/var/opt/mxe/usr/bin/x86_64-w64-mingw32.static-ar qc libGLEW_LIBRARY.a CMakeFiles/GLEW_LIBRARY.dir/GLEW_LIBRARY_autogen/mocs_compilation.cpp.obj
/var/opt/mxe/usr/bin/x86_64-w64-mingw32.static-ranlib libGLEW_LIBRARY.a

我觉得很奇怪,因为没有像 libGLEW_LIBRARY.a 这样的文件。


编辑:我现在也将问题直接发布到 VTK 论坛,希望这可能是关于 VTK 的一些具体问题:https://discourse.vtk.org/t/problems-with-linking-glew-in-mxe-build/7522

【问题讨论】:

CMake find_package 函数不会查看自定义位置。您需要添加 PATHS 选项来指定在哪里可以找到库。 @Someprogrammerdude 将其重写为find_package(GLEW REQUIRED PATHS "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/"),然后得到消息,它既找不到GLEWConfig.cmake 也找不到glew-config.cmake。 (文件夹结构中不存在。)我假设我必须触发一些安装?我找到了一个带有 cmake_install.cmake 文件的 glew 目录,但我不愿调用它,特别是因为它位于错误架构的文件夹中(x86 linux 而不是 x86 windows)。 您需要可移植的项目(和CMakeLists.txt 文件)吗?如果没有,那么您可以对目录路径和库进行硬编码。否则,您可以使用find_package(GLEW REQUIRED),如果找不到,您可以自己将变量设置为硬编码位置,也可以检查文件和目录以确保。 @Someprogrammerdude 只需要为该特定目标工作。但是,第二种方式对我来说听起来更好。您是否碰巧知道 GLEW 特有的必要硬编码路径?在我的问题中使用find_library 命令,缺少的引用没有得到解决。 我知道 your 项目的硬编码的具体路径,因为你已经提到了它们 (/opt/mxe/usr/x86_64-w64-mingw32.static/...) :) 你设置 @987654353 的 sn-p @ 变量,使用它,然后在 target_include_directoriestarget_link_libraries 中使用这些变量。 【参考方案1】:

经过一段时间后,我终于修复了它,虽然我不确定为什么修复了它。 在我的代码中,我有初始化命令

  VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

我认为这是必需的。 删除此行解决了问题。

我不知道为什么会这样,因为这应该是一个有效的命令,所以如果有人对 VTK 有更深入的了解并知道答案,那将不胜感激。 我的猜测是,VTK 的 MXE 版本不适用于体绘制。 我也不知道为什么这个问题是在电脑更新之后才出现的。

【讨论】:

以上是关于将 GLEW 与 cmake 链接的问题的主要内容,如果未能解决你的问题,请参考以下文章

将 GLEW 与 CMake 连接起来

GLEW + cmake 链接失败“未定义对符号 glDrawElements 的引用”+“命令行中缺少 DSO”

如何在 CMake 中链接预编译库?

链接 GLEW 失败

XCode 链接静态库 (GLEW) 尝试 dylib 加载

我无法将 GLEW 库链接到我的 Xcode 项目