mitsuba-renderer / nanogui

Minimalistic C++/Python GUI library for OpenGL, GLES2/3, Metal, and WebAssembly/WebGL
Other
1.57k stars 196 forks source link

build error ubuntu: /usr/bin/ld: cannot find -lGL #103

Open wildeyevr opened 2 years ago

wildeyevr commented 2 years ago

[ 63%] Linking CXX shared library libnanogui.so /usr/bin/ld: cannot find -lGL collect2: error: ld returned 1 exit status make[2]: [CMakeFiles/nanogui.dir/build.make:629: libnanogui.so] Error 1 make[1]: [CMakeFiles/Makefile2:330: CMakeFiles/nanogui.dir/all] Error 2 make: *** [Makefile:130: all] Error 2

ashpil commented 2 years ago

I'm running into this as well, my understand that (at least for me) this is due to an issue with how OpenGL is accessed on Wayland and how you technically have to go through libglvnd.

svenevs commented 2 years ago

I took a brief look at this, it does seem to be platform specific. The GLFW build docs explain

Note that the glfw target does not depend on OpenGL, as GLFW loads any OpenGL, OpenGL ES or Vulkan libraries it needs at runtime. If your application calls OpenGL directly, instead of using a modern extension loader library, use the OpenGL CMake package.

find_package(OpenGL REQUIRED)

If OpenGL is found, the OpenGL::GL target is added to your project, containing library and include directory paths. Link against this like any other library.

target_link_libraries(myapp OpenGL::GL)

That said, since I'm not able to reproduce this error, and am also not personally very familiar with the changes in the OpenGL context scenario, I think those docs are actually a little bit outdated.

  1. Are you able to build successfully if you configure cmake with -DNANOGUI_BUILD_GLAD=ON? It defaults to OFF unless on Windows. Please do this with a clean cmake build directory.
  2. Near line 453 of CMakeLists.txt, just after the add_library(nanogui ...) call, can you try adding the following?

    find_package(OpenGL REQUIRED)
    message(STATUS "NanoGUI: gl pref: ${OpenGL_GL_PREFERENCE}")
    if (TARGET OpenGL::OpenGL)
      message(STATUS "NanoGUI: using OpenGL::OpenGL")
      target_link_libraries(nanogui PUBLIC OpenGL::OpenGL)
    else()
      message(STATUS "NanoGUI: using OpenGL::GL")
      target_link_libraries(nanogui PUBLIC OpenGL::GL)
    endif()

    and report back (a) if it works and (b) which printed, OpenGL::OpenGL or OpenGL::GL as well as what gl pref was? (Please don't set NANOGUI_BUILD_GLAD=ON for this test, doing so in a clean build directory).

The CMake docs on find_package(OpenGL) are a bit confusing. The linux specific section verbiage makes me believe that to do it correctly, you need to check the OpenGL_GL_PREFERENCE, but I'm not sure. They say if legacy is not available, then OpenGL::GL points to OpenGL::OpenGL (glvnd), but if both are available then I think you force legacy if you always use OpenGL::GL?

ashpil commented 2 years ago

I'm not sure if I'm experiencing the same exact issue as the OP, as I am not on Ubuntu, but I am getting the same error, so I will try to continue this issue and answer @svenevs questions. If OP is on the latest Ubuntu, which is Wayland, then we might be experiencing the same issue - because this is the problem I am encountering when trying to compile on a Wayland-only machine.

  1. No. Same error.
  2. This does not work, and logs
    CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
    Could NOT find OpenGL (missing: OPENGL_glx_LIBRARY)

    This issue makes sense in my context - as GLX does not exist on Wayland. Replacing the find_package(OpenGL REQUIRED) line with find_package(OpenGL REQUIRED COMPONENTS OpenGL) (that is telling FindOpenGL that we only care about the OpenGL core libary, and not GLX or EGL) fixes the issue, and prints

-- Found OpenGL: /usr/lib64/libOpenGL.so  found components: OpenGL 
-- NanoGUI: gl pref: GLVND
-- NanoGUI: using OpenGL::OpenGL

Of course to actually have the next step, make, work, we'd need to replace the original problematic list(APPEND NANOGUI_LIBS GL) line.

ashpil commented 2 years ago

Now if OP is indeed running into the same issue as me due to being on Wayland, they will run into another error upon fixing the previous one.

/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_get_fd'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_keyboard_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_output_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_compositor_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_buffer_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_set_user_data'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_get_user_data'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_disconnect'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_destroy'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_dispatch_pending'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_pointer_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_add_listener'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_data_device_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_roundtrip'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_flush'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_callback_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_connect'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_region_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_subsurface_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_subcompositor_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_prepare_read'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_data_device_manager_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_read_events'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_registry_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_seat_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_shm_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_get_version'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_surface_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_display_cancel_read'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_proxy_marshal_flags'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_data_source_interface'
/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: libnanogui.so: undefined reference to `wl_shm_pool_interface'

Since obviously nanogui doesn't manually call Wayland functions, I imagine this is something to do with how nanogui subsumes glfw into itself (can't find any documentation about why this is done), and although it correctly carries over the X dependencies, it fails to properly select the Wayland dependencies on Wayland systems. I wonder if there's some more elegant way to ensure platform-appropriate GLFW dependencies are used.

wildeyevr commented 2 years ago

Hey all... I appreciate you all looking into the issue... will mess around with this at some point today and report back

wildeyevr commented 2 years ago

Hey svenevs...

  1. does not fix the issue as ashpil mentioned...
  2. -- NanoGUI: gl pref: GLVND -- NanoGUI: using OpenGL::OpenGL run with a clean build dir

I'm on Ubuntu 20.04.3 LTS (Focal Fossa) by the way

wildeyevr commented 2 years ago

FYI Had a friend build on Ubuntu 21.10 impish with success... he has some ideas on the issue will follow up...

svenevs commented 2 years ago

Hmmm, ok, thanks for the responses it's very helpful! So it seems like there's potentially two different things going on here, but the solution seems to also be related.

# My understanding is this fixes the original issue on 20.04
find_package(OpenGL REQUIRED COMPONENTS OpenGL)
target_link_libraries(nanogui PUBLIC OpenGL::OpenGL)
# note, not the PR solution, will break superbuild consumers (see below)

What's not clear to me is if this is supposed to be getting avoided on wayland altogether. Maybe the above gets guarded by checking XDG_SESSION_TYPE environment variable and not doing it if it is Wayland?

I did some trial and error but am actually failing to obtain a wayland session on this rig (nvidia drivers, wasn't able to get around it...). I will be able to test off a live usb of ubuntu in february if you poke me (away next week). Some additional things worth trying for diagnosing wayland:

  1. If you cd ext/glfw and mkdir build; cd build; cmake .. -DGLFW_USE_WAYLAND=ON after compilation there should be ./examples/gears or others. Do those run as expected? I anticipate you will hit the same issue.
    • If that is not successful, do you get different results on the main glfw/glfw repository? If so the fork of glfw should get updated again. There seem to be some wayland updates in their src/CMakeLists.txt.
  2. You could try using an external GLFW, presumably ubuntu packaged this up right with wayland support. #104 should help with that, and it currently doesn't do anything with the cmake OpenGL package. But if I'm understanding right, you'll run into the same error.

I imagine this is something to do with how nanogui subsumes glfw into itself (can't find any documentation about why this is done)

The TL;DR is it's part of "superbuilds", mitsuba-renderer and tev are some examples. There's also historical reasons, but basically dependency management with CXX has always been a nightmare so usually projects vendor their own.

The way the glfw fork works is by patching glfw add_library(glfw_objects OBJECT, OBJECT being the key. Then for the most part everything that was target glfw is now replaced with glfw_objects so that nanogui consume the $<TARGET_OBJECTS:glfw_objects>. CMake doesn't let you do this without object libraries. Nanogui does the same thing with object libraries, allowing parent projects to consume its objects directly if they so desire. It is worth mentioning that if you link against something else that also links against glfw, you will get problems and must use an external glfw with nanogui (since the symbols will now be defined twice).

So for consuming projects doing superbuilds, linking against OpenGL::OpenGL may be something we should avoid in favor of appending the underlying library to the list of nanogui libraries to link against. Right now the nanogui targets are not setup in a way where using those targets on nanogui is OK, it'll fix nanogui but not the parent projects.

Hope that clarifies things a bit, sorry if it is not clear it's late but wanted to explain a bit of the different moving parts.

ashpil commented 2 years ago

Thank you for moving this forward so quickly!

  1. Works as expected. I use glfw on Wayland a ton and have never had issues with it, so I am imagining what is going on here is a nanogui specific issue.
  2. So this actually makes the build succeed (once I make the necessary OpenGL cmake changes), though running the nanogui examples produces no result. That is, the binary runs and doesn't exit, and the process appears in top, just no window appears. Not sure if this is a peculiarity of Wayland or my tiling window manager. But NANOGUI_BUILD_GLFW is a neat flag, and might help as a temporary workaround on some systems. The name leaves a bit to be desired, though -- wasn't sure if that meant that I somehow had to integrate my own windowing library to get nanogui to work, or what. Perhaps USE_EXTERNAL_GLFW would be more illustrative of the actual use case.

The way the glfw fork works is by patching glfw add_library(glfw_objects OBJECT, OBJECT being the key. Then for the most part everything that was target glfw is now replaced with glfw_objects so that nanogui consume the $<TARGET_OBJECTS:glfw_objects>. CMake doesn't let you do this without object libraries. Nanogui does the same thing with object libraries, allowing parent projects to consume its objects directly if they so desire. It is worth mentioning that if you link against something else that also links against glfw, you will get problems and must use an external glfw with nanogui (since the symbols will now be defined twice).

Thanks for the explanation, this makes more sense now. Though I'm not convinced this is worth it, given how it becomes harder to stay up to date with the latest glfw changes, and make sure its platform requirements are appropriately passed through.

So for consuming projects doing superbuilds, linking against OpenGL::OpenGL may be something we should avoid in favor of appending the underlying library to the list of nanogui libraries to link against. Right now the nanogui targets are not setup in a way where using those targets on nanogui is OK, it'll fix nanogui but not the parent projects.

Perhaps then this can be ameliorated by using the Cache variables FindOpenGL provides. OPENGL_opengl_LIBRARY seems to be set on my system, and I imagine OPENGL_gl_LIBRARY is set on other ones. FindOpenGL appears to set the variables necessary to tell which one to use.

RolandHughes commented 2 years ago

Try building and using WaylandGUI that is a fork I started focusing only on ARM Linux but it doesn't force ARM on you. At least two of the examples should work for you. Make certain libglvnd isn't installed anywhere on your system. ldd your example binaries to ensure they are linked against the correct libraries.

wildeyevr commented 2 years ago

Hey all... just to followup here... it builds fine on Ubuntu 21.10 impish... so this is solved for me at least

wjakob commented 2 years ago

Sorry for joining the party very late -- are there any concrete suggestions on how to change the CMake build system so that it works for Wayland? I am still based on X11 and things are fine there.

RolandHughes commented 2 years ago

I left off with the work I did for WaylandGUI which is a fork of this. Had to drop all of the unnecessary platforms, MAC/Apple, Windows, etc. The Apple/Mac support is what screwed the pooch. I haven't touched it since this thread. My project used Elements for the final product. I used NanoGUI inside of a Docker container for the board verification software and everybody abandoned Wayland.

Having said that.

Another on this thread will be picking up some work on WaylandGUI shortly if they haven't already done so. They hit the same wall in their project and they don't have the option of using a Docker container. Both myself and Toradex advised them on finding the smallest Wayland compatible library they could and wedging it into their existing UI library.

Sadly I don't have my test system set up anymore nor do I currently have the time to devote to WaylandGUI. That's a personal project that got pushed down the queue.

As long as you continue to support Apple/MAC with that custom EGLS (or whatever custom that got added for the platform) you will never work on Wayland. That relies on an API that simply isn't there. If you want Wayland you have to abandon Apple or at least abandon everything currently in place for Apple because it wasn't well done. It's "worked for an application" code not "works for a project" code.

If memory serves, I had at least two of the demo programs working under Wayland with WaylandGUI.

ashpil commented 2 years ago

@wjakob #135 should do it, or at least the baseline (building and running without crash) of it.