连接 GLEW 和 cmake 的问题

Problems linking GLEW with cmake

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

[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.

编辑:在一些程序员老兄和 Tsyvarev 在评论中写下的内容之后,我当前的设置看起来有点像这样:

...

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 的额外行,并且项目名称等部分被替换为 [=24] =]:

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

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

  VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

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

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