Irbis
Irbis

Reputation: 13369

GLFW - linker errors on UBuntu 14.04 LTS

I want to compile an example code from this site (at the bottom). I downloaded GLFW 3.0.4 source code and I built it in a custom location. I used a default settings and GLFW was built as a static library. My CMakeLists.txt looks like this:

cmake_minimum_required(VERSION 2.8)
project(glfw_test_project)

SET(CMAKE_CXX_FLAGS "-Wall -Werror -g -std=c++11")

find_package(OpenGL REQUIRED)

include_directories(/home/user/MyLibs/OpenGL/glfw-3.0.4/include)
link_directories(/home/user/MyLibs/OpenGL/glfw-3.0.4/build/src)

add_executable(glfw_test main.cpp)

target_link_libraries(glfw_test ${OPENGL_gl_LIBRARY})
target_link_libraries(glfw_test glfw3)

When I run make I get following info:

Linking CXX executable glfw_test
/usr/bin/ld: /home/user/MyLibs/OpenGL/glfw-3.0.4/build/src/libglfw3.a(x11_clipboard.c.o): undefined reference to symbol 'XConvertSelection'
//usr/lib/x86_64-linux-gnu/libX11.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [glfw_test] Error 1
make[1]: *** [CMakeFiles/glfw_test.dir/all] Error 2
make: *** [all] Error 2

What is wrong ?

Edit1 When I build GLFW as a dynamic library everything works fine. Then the last line in my CMakeLists.txt have to be replaced with:

target_link_libraries(glfw_test glfw)

What is wrong when using a static library ?

Upvotes: 4

Views: 9733

Answers (2)

VisorZ
VisorZ

Reputation: 566

I experienced the same problems on Ubuntu 14.04 LTS.

First: error adding symbols: DSO missing from command line shows a wrong order of linker command line parameters. This post made me realise that. You need to call $ make VERBOSE=1 to see the linker call and check it with your own eyes. Remember: TARGET_LINK_LIBRARIES() should be the last command in your CMakeLists.txt And have a look at this order explanation.

Second: if you build against static GLFW3 libraries all the X11 libraries are not automatically added to your linker call, as atsui already showed above. In the GLFW-Documentation you can find a cmake variable which should fit your needs: ${GLFW_STATIC_LIBRARIES}. To make use of it and enable a more automatic build process, let pkg-config find all dependencies for X11 libs:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(myProject)

FIND_PACKAGE( PkgConfig REQUIRED )
pkg_search_module( GLFW3 REQUIRED glfw3 ) # sets GLFW3 as prefix for glfw vars

# now ${GLFW3_INCLUDE_DIR}, ${GLFW3_LIBRARIES} and ${GLFW3_STATIC_LIBRARIES} 
# are set

INCLUDE_DIRECTORIES( ${GLFW3_INCLUDE_DIR} )
ADD_EXECUTABLE( myProject mySource.cpp )

TARGET_LINK_LIBRARIES( myProject ${GLFW_STATIC_LIBRARIES} )
# they include X11 libs

Now check the linker lib parameters again with $ make VERBOSE=1 and you should find many more X11 libs like: -lXrandr -lXi -lXrender -ldrm -lXdamage -lXxf86vm -lXext -lX11 and -lpthread.

Third: when linking against the shared library, the dependencies to X11 etc. are resolved dynamically. That is why you don't need to explicitly add X11 lib flags to the linker. In that case you only need: TARGET_LINK_LIBRARIES( myProject ${GLFW_LIBRARIES} )

Fourth: it happened to me, that some glfwCommands had undefined reference to - linker errors. I found out, that I installed GLFW3 in /usr/local/lib but the linker was given only the LD_LIBRARY_PATH environment variable which was only set to /usr/lib32. Adding the parameter -L/usr/local/lib solved the reference problem. To avoid it in future I've set LD_LIBRARY_PATH=/usr/lib32;/usr/local/lib;.

Hint: to check what values are in your GLFW cmake variables, print them during build:

FOREACH(item ${GLFW3_STATIC_LIBRARIES})
    MESSAGE(STATUS "  using lib: " ${item})
ENDFOREACH()

Upvotes: 6

atsui
atsui

Reputation: 1008

It seems that you resolved your own issue by rebuilding GLFW as a shared library and linking the example code with that. Instead, I'll try to answer your followup question about why it doesn't work when you try to link the static library.

Basically, if you want to link against the static library libglfw3.a, you need to link all of the dependent X11 libraries. You get an error linking the static library because you didn't specify any additional libraries to link, and CMake doesn't know what these dependencies are. You don't get an error when you link the shared library libglfw.so because the X11 libraries are linked to the shared library, and CMake knows to pull those in for you automatically.

If you want to use the static library, you can determine the necessary libraries to link as follows. According to the .pc file in GLFW, you can type this in the command-line to find out what these are:

pkg-config --static --libs x11 xrandr xi xxf86vm gl

If you translate this into a CMake command, it would look like this:

target_link_libraries( glfw_test glfw3 Xrandr Xrender Xi GL m dl drm Xdamage X11-xcb xcb-glx xcb-dri2 xcb-dri3 xcb-present xcb-sync xshmfence Xxf86vm Xfixes Xext X11 pthread xcb Xau Xdmcp)

So if you add this to the CMakeLists.txt, the example code should build without an issue.

By the way, you can automatically find the X11 libraries using CMake in the following way:

find_package(X11 REQUIRED)
target_link_libraries( my_program ${X11_LIBRARIES} )

However, the set of libraries stored in the X11_LIBRARIES variable will only contain a subset of the libraries needed for statically linking GLFW.

I'm not really sure how to properly handle static/dynamic linking in CMake, but I hope this helps.

Upvotes: 3

Related Questions