Advertisement

[C++][Linker] Undefined references to GLFW / Vulkan

Started by September 15, 2018 06:59 PM
3 comments, last by METROIDHunter_ 6 years, 2 months ago

I've decided to branch out from Java and try learning C++ with Vulkan because it sounded like fun, but I've had a lot of trouble linking the libraries for GLFW and Vulkan. I'm following a tutorial on vulkan-tutorial.com which uses Visual Studio for the project. I've tried Visual Studio, Eclipse CDT, Code::Blocks, and command line compilation using MinGW G++, but every single method complains about undefined references to GLFW and Vulkan members. Here's the code in main.cpp:
   


#define GLFW_INCLUDE_VULKAN
    #include <GLFW/glfw3.h>

    #define GLM_FORCE_RADIANS
    #define GLM_FORCE_DEPTH_ZERO_TO_ONE
    #include <glm/vec4.hpp>
    #include <glm/mat4x4.hpp>

    #include <iostream>

    int main() {
        glfwInit();

        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);

        uint32_t extensionCount = 0;
        vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

        std::cout << extensionCount << " extensions supported\n";

        glm::mat4 matrix;
        glm::vec4 vec;
        auto test = matrix * vec;

        while(!glfwWindowShouldClose(window)) {
            glfwPollEvents();
        }

        glfwDestroyWindow(window);

        glfwTerminate();

        return 0;
    }

Here are the commands being used to compile the code:

   


g++ -std=c++11 -fexceptions -g -IC:/glfw-3.2.1/include -IC:/glm-0.9.9.1/glm -IC:/VulkanSDK/1.1.82.1/Include -c "src/main.cpp"
    g++ -LC:/glfw-3.2.1/lib-mingw-w64 -LC:/VulkanSDK/1.1.82.1/Lib -o VulkanTest.exe main.o -lglfw3 -lvulkan-1

The first command compiles the .cpp into a .o successfully, but the second command gives me errors from the linker. Every single reference I made to a member from Vulkan or GLFW is undefined. (Path has been shortened for easier reading)


    [omitted]/src/main.cpp:12: undefined reference to `glfwInit'
    [omitted]/src/main.cpp:14: undefined reference to `glfwWindowHint'
    [omitted]/src/main.cpp:15: undefined reference to `glfwCreateWindow'
    [omitted]/src/main.cpp:18: undefined reference to `vkEnumerateInstanceExtensionProperties@12'
    [omitted]/src/main.cpp:26: undefined reference to `glfwWindowShouldClose'
    [omitted]/src/main.cpp:27: undefined reference to `glfwPollEvents'
    [omitted]/src/main.cpp:30: undefined reference to `glfwDestroyWindow'
    [omitted]/src/main.cpp:32: undefined reference to `glfwTerminate'

It seems like the linker can't find the library files I provided with -L and -l, but if I change -lglfw3 to -llibglfw3.a or -lglwf3.dll, I get this:

   


   [omitted]/mingw32/bin/ld.exe: cannot find -llibglfw3.a


or


    [omitted]/mingw32/bin/ld.exe: cannot find -lglfw3.dll

Leading me to think that the linker DID find the libraries at first, since it didn't complain about being unable to find the library - but why can't it find sources for the references to GLFW / Vulkan functions? I have no idea what's happening. Is it finding the library files?

I'm using GLFW 3.2.1, Vulkan SDK 1.1.82.1, MingW GCC version 6.3.0, and I'm running on Windows 10 Pro 64-bit.

AMD Ryzen R5 1400; NVidia GeForce GTX 1060 6GB; 16GB DDR4

Quirky.

The compilation means the headers are likely being found, otherwise there would be errors about undeclared types and functions. 

The lack of errors about the libraries mean the files are probably being found and parsed.

My next guess would be name mangling. Do the headers have proper guards for extern "C" { ... } around them?  The @12 at the end of one line suggests that may be a partial culprit. After that, I'd guess at other compiler options or differences between your default settings and the library's settings. Also MingW 6.3.0 is approaching two years old, you might consider updating but that wouldn't immediately explain the problem you describe.

You might want to use a tool to examine the binaries, you might use dumpbin or a similar tool to look at your object files and verify the names the linker is looking for are the same ones that are expected.

Advertisement

Hi, thanks for your reply. I also doubt an outdated version of MingW has to do with the problem, because I used Visual C++ in Visual Studio 2017 and it gave the same output.

I examined the glfw3 header file and found this at the beginning of the file:


#ifdef __cplusplus
extern "C" {
#endif

...and this at the end:


#ifdef __cplusplus
}
#endif

The vulkan.h header file did NOT have this "extern "C" " guard. It may be worth noting that vulkan.h is included from within glfw3.h when I define GLFW_INCLUDE_VULKAN at the top of my main class, shown by these lines from glfw3.h:


 #elif defined(GLFW_INCLUDE_VULKAN)
  #include <vulkan/vulkan.h>

I ran dumpbin on main.o. I saw what looked like references to GLM functions, but absolutely nothing from GLFW or Vulkan. Here's the output:


Dump of file main.o

File Type: COFF OBJECT

  Summary

           4 .bss
           4 .ctors
           0 .data
         6C7 .debug_abbrev
          98 .debug_aranges
        4EBF .debug_info
         5F9 .debug_line
          88 .debug_ranges
         14D .debug_str
          A4 .eh_frame
          38 .eh_frame$_ZN3glm3matILi4ELi4EfLNS_9qualifierE0EE6lengthEv
          40 .eh_frame$_ZN3glm3matILi4ELi4EfLNS_9qualifierE0EEC1Ev
          38 .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EE6lengthEv
          38 .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Ef
          38 .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Effff
          38 .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Ev
          3C .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EEmLIfEERS2_RKNS0_ILi4ET_LS1_0EEE
          3C .eh_frame$_ZN3glm3vecILi4EfLNS_9qualifierE0EEpLIfEERS2_RKNS0_ILi4ET_LS1_0EEE
          38 .eh_frame$_ZN3glm6detail16compute_vec4_addIfLNS_9qualifierE0ELb0EE4callERKNS_3vecILi4EfLS2_0EEES7_
          38 .eh_frame$_ZN3glm6detail16compute_vec4_mulIfLNS_9qualifierE0ELb0EE4callERKNS_3vecILi4EfLS2_0EEES7_
          38 .eh_frame$_ZN3glmmlIfLNS_9qualifierE0EEENS_3matILi4ELi4ET_XT0_EE8col_typeERKS4_RKNS4_8row_typeE
          38 .eh_frame$_ZN3glmmlIfLNS_9qualifierE0EEENS_3vecILi4ET_XT0_EEERKS4_S6_
          38 .eh_frame$_ZN3glmplIfLNS_9qualifierE0EEENS_3vecILi4ET_XT0_EEERKS4_S6_
          38 .eh_frame$_ZNK3glm3matILi4ELi4EfLNS_9qualifierE0EEixEi
          38 .eh_frame$_ZNK3glm3vecILi4EfLNS_9qualifierE0EEixEi
          B8 .rdata
          24 .rdata$zzz
         16C .text
           C .text$_ZN3glm3matILi4ELi4EfLNS_9qualifierE0EE6lengthEv
          30 .text$_ZN3glm3matILi4ELi4EfLNS_9qualifierE0EEC1Ev
           C .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EE6lengthEv
          34 .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Ef
          34 .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Effff
           C .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EEC1Ev
          64 .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EEmLIfEERS2_RKNS0_ILi4ET_LS1_0EEE
          64 .text$_ZN3glm3vecILi4EfLNS_9qualifierE0EEpLIfEERS2_RKNS0_ILi4ET_LS1_0EEE
          60 .text$_ZN3glm6detail16compute_vec4_addIfLNS_9qualifierE0ELb0EE4callERKNS_3vecILi4EfLS2_0EEES7_
          60 .text$_ZN3glm6detail16compute_vec4_mulIfLNS_9qualifierE0ELb0EE4callERKNS_3vecILi4EfLS2_0EEES7_
         1B4 .text$_ZN3glmmlIfLNS_9qualifierE0EEENS_3matILi4ELi4ET_XT0_EE8col_typeERKS4_RKNS4_8row_typeE
          54 .text$_ZN3glmmlIfLNS_9qualifierE0EEENS_3vecILi4ET_XT0_EEERKS4_S6_
          54 .text$_ZN3glmplIfLNS_9qualifierE0EEENS_3vecILi4ET_XT0_EEERKS4_S6_
          40 .text$_ZNK3glm3matILi4ELi4EfLNS_9qualifierE0EEixEi
          68 .text$_ZNK3glm3vecILi4EfLNS_9qualifierE0EEixEi

 

AMD Ryzen R5 1400; NVidia GeForce GTX 1060 6GB; 16GB DDR4

I've managed to solve the problem myself. Turns out that using an ancient version of MingW was the problem! Originally I downloaded MingW from here, which was recommended by the guide on MingW's wiki. I had no idea at the time that it installed such an old version of MingW.

I uninstalled MingW 6.3.0 and found my way over to https://sourceforge.net/projects/mingw-w64/ where I downloaded and installed version 8.1.0.

At first the compiler began complaining about undefined references to things like "__imp_CreateDCW", "__imp_SwapBuffers", and many other functions originating from libglfw3.a. I recognized these as GDI functions from some research I'd done before I made my post here, and I added gdi32 to the list of libraries for linking. Now my build commands look like this:


g++ -std=c++11 -fexceptions -g -IC:/glfw-3.2.1/include -IC:/glm-0.9.9.1/glm -IC:/VulkanSDK/1.1.82.1/Include -c "src/main.cpp"
g++ -LC:/glfw-3.2.1/lib-mingw-w64 -LC:/VulkanSDK/1.1.82.1/Lib -o VulkanTest.exe main.o -lglfw3 -lvulkan-1 -lgdi32

It compiles without warnings or errors and the executable runs perfectly fine.

My IDEs (Code::Blocks, Eclipse CDT, and Visual Studio 2017) still throw errors: Code::Blocks and VS 2017 about undefined references to GLFW members, and Eclipse CDT about trying to build an i386 object file into an i386:x86-64 output file. I may post here again if I learn something that may be useful to future newbies such as myself, searching the internet for solutions to their problems. In the meantime, I can use Sublime or Visual Studio Code for writing my code and my script to build it.

AMD Ryzen R5 1400; NVidia GeForce GTX 1060 6GB; 16GB DDR4

This topic is closed to new replies.

Advertisement