Search code examples
c++opengllinkerlinker-errorsglew

undefined reference to some OpenGL functions if they haven't been called in main


if I define a function, for example void draw(), containing glClear, glDrawArrays or glDrawElements (possibly the case for some other OpenGL functions as well) in a separate file to the main file, and then call draw() from the main function, there is an undefined reference error to the GL function that is used inside draw. The error does not occur if the same GL function is additionally called directly anywhere inside main (even if it's after the call to draw()). Also, the error does not occur with all GL functions, for example there is no error when calling glUniform1f(1,1).

As an example, I have a folder that contains main.cpp, draw.hpp, draw.cpp, a Makefile, an include folder and a lib folder.

main.cpp:

#define GLEW_STATIC
#include <GL/glew.h>

#include "draw.hpp"

int main()
{
    glewExperimental = GL_TRUE;
    glewInit();

    glClear(GL_COLOR_BUFFER_BIT);
    draw();
}

draw.hpp:

#pragma once

void draw();

draw.cpp:

#include "draw.hpp"

#define GLEW_STATIC
#include <GL/glew.h>

void draw()
{
    glClear(GL_COLOR_BUFFER_BIT);
}

Makefile:

a.exe: main.cpp draw.hpp draw.cpp
    g++ -c -o lib/libdraw.a draw.cpp -I./include
    g++ -o a.exe main.cpp -I./include -L./lib -lglew32 -lgdi32 -lopengl32 -ldraw

The include folder contains a GL folder with the glew headers. The lib folder contains the static glew library (and libdraw.a when that is compiled).

When calling make from cmd (that is make from MinGW-w64 if I'm not mistaken) with this configuration, everything compiles without errors, but if I remove glClear(GL_COLOR_BUFFER_BIT); from main, I get the undefined reference to 'glClear' error on the g++ -o a.exe main.cpp -I./include -L./lib -lglew32 -lgdi32 -lopengl32 -ldraw step.

I know this code does not make much sense, it is just an example. I would like to know how I can properly fix these errors any why they occur.


Solution

  • This is because -ldraw is last in the libraries. Each library is added to the binary to sort out unresolved externals, and then offers new dependencies. Given -ldraw is last, it can't add new dependencies, which get resolved.

    Move -ldraw to first of libraries.

    g++ -o a.exe main.cpp -I./include -L./lib -ldraw -lglew32 -lgdi32 -lopengl32