0

I have a C++ project using VTK rendering which is build for Windows using MXE.
This project built just fine in the past. Now recently, the machine on which I build it was altered, mostly an additional hard drive added and a full update being done. Since then, my old build fails in the linking stage with the following errors:

[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

Which to me looks as if it is unable to locate the GLEW library files. (Note that all missing references have the prefix glew.)

My first attempt to fix this was to add something like

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

to my CMakeLists. (Note that I work seldomly with cmake and this and the following might be simply me not doing things properly.)
This results in

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)

Given that, I assumed that I need to set some variables here, since after all, I am supposed to use the GLEW libraries that come with MXE. Thus I prepended

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)

This resulted in the same error as before, despite GLEW_LIBRARIES being set.

Another failed attempt, based on an answer in Linking GLEW with CMake, was to add

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)

At this point I have the feeling that my approach might be wrong and instead of adding to CMakeLists, I might have to do something else. Possibly configuring MXE? After all, it has worked before without additional lines.
Or if my approach is correct, maybe my arguments aren't? The paths are existing files.
Does anybody have an idea what else to try?


Edit: Note that even without me linking, it is rather strange that it does not find GLEW at all, given that this system has GLEW installed as regular package:

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.

Edit: After what Some Programmer Dude and Tsyvarev wrotein the comments, my current setup looks somewhat like this:

...

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)

(with several of the lines most likely not being necessary).

The linker seems to find the library files (no error about not finding something), but the references are still undefined.

My thought was whether the library files actually specify the required symbols, if it might be some version incompatibility, so I executed

nm libglew32

and searched for "glewGenVertexArrays" in the output, and yes, exists:

0000000000003a68 B __glewGenVertexArrays

In order to give more information, here is the content of my CMakeLists.txt, without the additional lines for GLEW as mentioned above, and with some parts like the project name being replaced by something like <placeholder>:

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})

In this, core is a library which contains most of the classes of the project, basically everything but the main function.

Other than what was written before, I tried adding the library files explicitely in the last line above:

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)

doesn't work either.


Also, I noticed the following: during compilation, cmake creates a file CMakeFiles/GLEW_LIBRARY.dir/link.txt. This file contains

/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

which I find odd, given that there is no such file as libGLEW_LIBRARY.a.


Edit: I now also posted the question directly to the VTK forum, hoping that this might be a somewhat specific problem in regard to VTK: https://discourse.vtk.org/t/problems-with-linking-glew-in-mxe-build/7522

Aziuth
  • 3,652
  • 3
  • 18
  • 36
  • The CMake [`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html) function will not look in custom locations. You need to add the `PATHS` option to specify where to find the library. – Some programmer dude Dec 08 '21 at 13:23
  • @Someprogrammerdude Rewrote it as `find_package(GLEW REQUIRED PATHS "/opt/mxe/usr/x86_64-w64-mingw32.static/lib/")`, then got the message that it can find neither `GLEWConfig.cmake` nor `glew-config.cmake`. (Which exist nowhere in the folder structure.) I assume I have to trigger some installation? I found a glew directory with a `cmake_install.cmake` file, but I am hesitant to call it, especially since it is located in a folder of the wrong architecture (x86 linux instead of x86 windows). – Aziuth Dec 08 '21 at 13:48
  • Do you need the project (and the `CMakeLists.txt` file) to be portable? If not then you could just hard-code the directory paths and libraries. Otherwise you could use `find_package(GLEW REQUIRED)` and if not found set the variables to the hard-coded locations yourself, possibly also check files and directories to make sure. – Some programmer dude Dec 08 '21 at 13:56
  • @Someprogrammerdude Needs only to work for that specific target. However, doing it the second way sounds better to me. Do you happen to know the necessary hard-coded paths specific for GLEW? With the `find_library` command as in my question, the missing references are not resolved. – Aziuth Dec 08 '21 at 14:09
  • I know the specific paths to hard-code for *your* project, since you already mentioned them (`/opt/mxe/usr/x86_64-w64-mingw32.static/...`) :) The snippet where you set the `GLEW_*` variables, use that, then use those variables in the `target_include_directories` and `target_link_libraries`. – Some programmer dude Dec 08 '21 at 15:47
  • "... this system has GLEW installed as regular package" - So files under `/opt/mxe/usr` are provided by that regular package? Or these files corresponds to your custom installation? Am I correctly understand, that before "machine on which I build it was altered" your project doesn't have **explicit** linkage with GLEW? For fix "undefined reference" occurred in the **static** library `libvtkRenderingVolumeOpenGL2-8.2.a` you need to place linkage agains GLEW **after** linkage with that library. Your approach `link_libraries(${GLEW_LIBRARIES})` probably places GLEW before VTK, so it won't work. – Tsyvarev Dec 08 '21 at 16:42
  • @Someprogrammerdude I tried out some new lines and added the libraries specifically in `target_link_libraries`, see the latest edit of my question. It seems to find the libraries but the references are still undefined, despite the symbol existing in the library files. – Aziuth Dec 09 '21 at 15:03
  • @Tsyvarev Made sure that everything regarding VTK is done before GLEW and linked all libraries in one go using `target_link_libraries`, see the lastest edit of my question. – Aziuth Dec 09 '21 at 15:04
  • 1. Assuming you build with `make`, run the building with `make V=1`: it will show exact command lines which are executed. 2. In the output find out command line corresponding to the failed linkage. 3. Check, that the **command line** contains all required options: it has linkage with the glew library, that linkage comes after the last linkage with `libvtkRenderingVolumeOpenGL2-8.2.a`. If the command line looks good, then CMake is out of the question. If the command contains wrong option (or misses it), then concentrate of part of `CMakeLists.txt` which produces the wrong option. – Tsyvarev Dec 09 '21 at 16:09
  • @Tsyvarev The command line does indeed not feature the glew library files at all. What can be the reason for that? After all, `cmake` does not say it can't find them as it would if that was the case. Can I force `cmake` to add those to the `Makefile`? – Aziuth Dec 10 '21 at 13:02
  • Probably, you enriched with `glew` a **wrong** executable, not the one which causes the linkage error. The part of the error message you put into the question post doesn't contain any reference to the target which is failed to link. And the part of the code you show doesn't contain the name of the target which you link with. It is known that it is difficult to ask about fixing **other** code. But you could definitely add more information to your question post for make it clearer. – Tsyvarev Dec 10 '21 at 13:53
  • @Tsyvarev The project has only a single executable. However, it does have an intermediate library file - a lot of the classes are compiled into that library file, which then in turn is linked to the executable. I tried to add the glew libraries to the step where the library is build, but that does not work either. – Aziuth Dec 17 '21 at 11:42
  • @Tsyvarev Also, one thing I find suspicious: I looked into the CMakeFiles folder created by cmake, and it has a subfolder for GLEW, in which a file `libGLEW_LIBRARY.a` is mentioned. A file like that does not exist in the library folders - GLEW has three files `libGLEW.a`, `libglew32.a` and `libglew32s.a`. Could this be a version incompatibility? But it should not be, as VTK and GLEW both came with the MXE installation. – Aziuth Dec 17 '21 at 11:45
  • "and it has a subfolder for GLEW, in which a file `libGLEW_LIBRARY.a` is mentioned." - It is created by your `add_library(GLEW_LIBRARY glew32 glew glew32s)`. Not sure what do you want to achieve by that call. – Tsyvarev Dec 17 '21 at 11:47
  • @Tsyvarev It was an attempt, but I guess one that reflects on me usually not using `cmake`. Other than that, I just added most of the content of my `CMakeLists.txt` to my question. – Aziuth Dec 17 '21 at 12:17
  • Please, do the following: 1. Replace `` in your `CMakeLists.txt` with the actual values. E.g. knowing exact name of the executable would help in interpreting the output. 2. Remove everything from your build directory and run `cmake` again. This will remove artifacts like `CMakeFiles/GLEW_LIBRARY.dir` created from your previous attempts. 3. Build with `make V=1` and add to the question the exact command line used for the (failed) linker call. If that command line contains reference like `@link.txt` also add content of the referenced file. – Tsyvarev Dec 17 '21 at 13:02

1 Answers1

0

After quite a while I finally fixed it, although I am not sure why this fixed it.
In my code I had the initializing command

  VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

which I thought to be required.
Removing this line fixed the problem.

I have no idea why this is the case, as that should be a valid command, so if anybody has more insight into VTK and knows the answer, that would be appreciated.
My guess is that the MXE version of VTK is not meant for volume rendering.
I also have no idea why this problem only came to be after the computer was updated.

Aziuth
  • 3,652
  • 3
  • 18
  • 36