0

I am trying to learn OpenGL, and I am a bit stuck with linking necessary libraries. NOTE: I use WSL, trying to build an executable for Windows with CMake and mingw-w64 (i686-w64-mingw32-g++ compiler).

Here is my folder structure:

build/
    CMakeCache.txt
    etc.
lib/
    include/
        GLFW/
            glfw3.h
            glfw3native.h
    libglfw3.a
src/
    main.cpp
.gitignore
CMakeLists.txt

I want to compile the main.cpp file, and link it with libglfw3.a (64-bit Windows pre-compiled binary from lib-mingw-w64 directory)

My main.cpp is a sample code from GLFW website: https://www.glfw.org/documentation.html

#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;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.18.4)
project(opengl-triangle)

add_executable(triangle src/main.cpp)

target_include_directories(triangle PUBLIC lib/include)

find_library(
    GLFW_LIB
    NAMES glfw3
    HINTS "${CMAKE_SOURCE_DIR}/lib"
    NO_DEFAULT_PATH
)
if(NOT GLFW_LIB)
  message(FATAL_ERROR "GLFW library not found")
endif()

target_link_libraries(
    triangle
    ${GLFW_LIB}
)

When I try to build my project I get this:

$ make
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/d/Programming/Projects/opengl-test/build
Scanning dependencies of target triangle
[ 50%] Building CXX object CMakeFiles/triangle.dir/src/main.cpp.o
[100%] Linking CXX executable triangle
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x17): undefined reference to `glfwInit'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x56): undefined reference to `glfwCreateWindow'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x64): undefined reference to `glfwTerminate'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x76): undefined reference to `glfwMakeContextCurrent'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x81): undefined reference to `glfwWindowShouldClose'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x96): undefined reference to `_imp__glClear@4'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0xa6): undefined reference to `glfwSwapBuffers'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0xab): undefined reference to `glfwPollEvents'
/usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0xb2): undefined reference to `glfwTerminate'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/triangle.dir/build.make:104: triangle] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/triangle.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

If I understand correctly, this is a linking error. However, in CMakeLists.txt I linked the library to my executable with target_link_libraries. Why there are undefined references?

I tried to build the same with MinGW without WSL, tried to link the library with full path: target_link_libraries(triangle "/mnt/d/Programming/Projects/opengl-test/lib/libglfw3.a"). Tried this answer (wrapped #include statement in extern "C". Results are the same.

I also tried to use different compiler (cmake .. -D CMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -D CMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++), and undefined references changed:

Scanning dependencies of target triangle
[ 50%] Building CXX object CMakeFiles/triangle.dir/src/main.cpp.o
[100%] Linking CXX executable triangle
/usr/bin/x86_64-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x8a): undefined reference to `__imp_glClear'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0x10f): undefined reference to `__imp_CreateDCW'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0x14e): undefined reference to `__imp_GetDeviceCaps'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0x1a3): undefined reference to `__imp_DeleteDC'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0x2e3): undefined reference to `__imp_GetDeviceCaps'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0x8db): undefined reference to `__imp_GetDeviceCaps'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xd68): undefined reference to `__imp_CreateDCW'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xd77): undefined reference to `__imp_GetDeviceGammaRamp'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xd80): undefined reference to `__imp_DeleteDC'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xe78): undefined reference to `__imp_CreateDCW'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xe87): undefined reference to `__imp_SetDeviceGammaRamp'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_monitor.c.obj):win32_monitor.c:(.text+0xe90): undefined reference to `__imp_DeleteDC'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x1e5): undefined reference to `__imp_CreateDIBSection'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x21f): undefined reference to `__imp_CreateBitmap'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x2c8): undefined reference to `__imp_DeleteObject'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x350): undefined reference to `__imp_DeleteObject'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x3e4): undefined reference to `__imp_CreateRectRgn'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(win32_window.c.obj):win32_window.c:(.text+0x41b): undefined reference to `__imp_DeleteObject'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x14a): undefined reference to `__imp_SwapBuffers'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x3f6): undefined reference to `__imp_ChoosePixelFormat'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x404): undefined reference to `__imp_SetPixelFormat'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0xb2f): undefined reference to `__imp_DescribePixelFormat'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x108f): undefined reference to `__imp_DescribePixelFormat'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x10aa): undefined reference to `__imp_SetPixelFormat'
/usr/bin/x86_64-w64-mingw32-ld: ../lib/libglfw3.a(wgl_context.c.obj):wgl_context.c:(.text+0x1386): undefined reference to `__imp_DescribePixelFormat'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/triangle.dir/build.make:104: triangle] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/triangle.dir/all] Error 2
make: *** [Makefile:103: all] Error 2
Kirill
  • 1
  • 1
  • What is the value of the `${GLFW_LIB}`? i.e., if you add `message(STATUS "GLFW_LIB: ${GLFW_LIB}")` at the end of CMakeLists.txt, what would be the output? – gordan.sikic Jul 08 '23 at 17:46
  • @gordan.sikic `-- GLFW_LIB: /mnt/d/Programming/Projects/opengl-test/lib/libglfw3.a` – Kirill Jul 08 '23 at 17:55
  • what will be the output related to link phase if you executed `make VERBOSE=1`? – gordan.sikic Jul 08 '23 at 18:02
  • @gordan.sikic `[100%] Linking CXX executable triangle /usr/bin/cmake -E cmake_link_script CMakeFiles/triangle.dir/link.txt --verbose=1 /usr/bin/i686-w64-mingw32-g++ CMakeFiles/triangle.dir/src/main.cpp.o -o triangle ../lib/libglfw3.a /usr/bin/i686-w64-mingw32-ld: CMakeFiles/triangle.dir/src/main.cpp.o:main.cpp:(.text+0x17): undefined reference to glfwInit` ... – Kirill Jul 09 '23 at 04:47

1 Answers1

0

Well, the solution is to link two more libraries (opengl32 and gdi32) and to use x86_64-w64-mingw32-g++ compiler.

The working CMakeLists.txt:

cmake_minimum_required(VERSION 3.18.4)
project(opengl-triangle)

add_executable(triangle src/main.cpp)

target_include_directories(triangle PUBLIC lib/include)

find_library(
    GLFW_LIB
    NAMES glfw3
    HINTS "${CMAKE_SOURCE_DIR}/lib"
    NO_DEFAULT_PATH
)
if(NOT GLFW_LIB)
  message(FATAL_ERROR "GLFW library not found")
endif()

target_link_libraries(
    triangle
    ${GLFW_LIB}
    opengl32
    gdi32
)
Kirill
  • 1
  • 1