-1

I've been trying to build the GLFW example (from http://www.glfw.org/documentation.html) using CMake and MinGW on Windows 10.

However I keep having the following linker errors:

CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x17): undefined reference to `_imp__glfwInit'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x58): undefined reference to `_imp__glfwCreateWindow'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x68): undefined reference to `_imp__glfwTerminate'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x7c): undefined reference to `_imp__glfwMakeContextCurrent'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x89): undefined reference to `_imp__glfwWindowShouldClose'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xa0): undefined reference to `_imp__glClear@4'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xb0): undefined reference to `_imp__glfwSwapBuffers'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xb7): undefined reference to `_imp__glfwPollEvents'
CMakeFiles\opengl-test.dir/objects.a(main.cpp.obj):main.cpp:(.text+0xc0): undefined reference to `_imp__glfwTerminate'

Currently I'm trying to link dynamically but I have tried to do it with the static libraries and encountered a similar problem.

Here's the CMakeFile.txt that I'm using to build it:

cmake_minimum_required (VERSION 3.0)
project (opengl-test)

set (GCC_COMPILE_FLAGS "-Wall -Wextra")
set (GCC_LINK_FLAGS "-Llib -lglfw3dll -lopengl32 -lglu32")

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS}")

file (GLOB_RECURSE SRCS src/*.cpp src/*.cxx src/**/*.cpp src/**/*.cxx)
file (GLOB_RECURSE HEADERS src/*.h src/**/*.h)

MESSAGE("${SRCS}")
MESSAGE("${HEADERS}")

add_definitions(-DGLFW_DLL)

set (EXECUTABLE_OUTPUT_PATH ..)

include_directories ("${PROJECT_BINARY_DIR}")
link_directories ("${CMAKE_SOURCE_DIR}/lib")

add_executable (opengl-test ${SRCS} ${HEADERS})
target_include_directories(opengl-test PRIVATE include)

set_target_properties(opengl-test PROPERTIES LINKER_LANGUAGE CXX)

Here's the directory structure:

.
|   CMakeLists.txt
|   glfw3.dll
|   
+---build
+---include
|   \---GLFW
|           glfw3.h
|           glfw3native.h
|           
+---lib
|       libglfw3.a
|       libglfw3dll.a
|       
\---src
        main.cpp

I've already tried most of the solutions I could find but no one seems to have the same problem as their solutions often are things that I have already done. I'm using the precompiled libraries for mingw-32. I'd expect the undefined references to be in libglfw3dll.a but maybe I'm wrong. Is the actual DLL needed during linking?

I'm not very experienced with CMake so it could also be a beginner mistake in the CMakeFile.

Example code I'm trying to build:

#include "GLFW/glfw3.h"

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
MrPromethee
  • 721
  • 9
  • 18

1 Answers1

4

The easy way

I tried simply cloning glfw from github, and using your main.cpp. I ended up with something simpler like:

/
  CMakeLists.txt   (see below)
  glfw/            (cloned from github)
  src/main.cpp     (containing your main.cpp)

CMakeScripts.txt

cmake_minimum_required(VERSION 3.0)
project(opengl-test)

find_package(OpenGL REQUIRED)
add_subdirectory(glfw)

add_executable(gltest
    src/main.cpp
)
target_link_libraries(gltest
    glfw
    OpenGL::GL
)

This worked fine on mac at least.

I didn't put a lot of effort into how glfw was built, just letting it default to whatever when adding it with "add_subdirectory".

But you could just as easily, go to the glfw folder, and configure it to build how you want it, and then do cmake --build . --target install

Then change the line in the script from add_subdirectory to find_package(glfw REQUIRED)

Using an installation

Ok, so again with the same setup as above, but adding a directory, "install" to place pre-built libraries.

Then I went to the glfw directory and ran these commands:

mkdir build
cd build
cmake -DBUILD_SHARED_LIBS:BOOL=On -DCMAKE_INSTALL_PREFIX=`pwd`/../../install -DGLFW_BUILD_DOCS=OFF -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF ..
cmake --build . --config Release
cmake --build . --target install

Now I have:

.
./CMakeLists.txt
./glfw/...    # Actually, this could be outside of the tree, or deleted.
./install/include/GLFW/glfw3.h
./install/include/GLFW/glfw3native.h
./install/lib/cmake/glfw3/glfw3Config.cmake
./install/lib/cmake/glfw3/glfw3ConfigVersion.cmake
./install/lib/cmake/glfw3/glfw3Targets-noconfig.cmake
./install/lib/cmake/glfw3/glfw3Targets.cmake
./install/lib/libglfw.3.3.dylib
./install/lib/libglfw.3.dylib
./install/lib/libglfw.dylib
./install/lib/pkgconfig/glfw3.pc
./src/main.cpp

Which is closer to what you had but with a nice cmake installation script there too, which can be imported nicely.

New CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(opengl-test)

find_package(OpenGL REQUIRED)
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/install)
find_package(glfw3 REQUIRED)

add_executable(gltest
    src/main.cpp
)
target_link_libraries(gltest
    glfw
    OpenGL::GL
)

This builds, and I did have a bit of an issue with it locating the dylib, because it linked with it using some kinda weird relative path soname, where it looked for the dll in the relative lib/ folder. I ran from the install dir to test though, and it worked fine.

johnb003
  • 1,821
  • 16
  • 30