Search code examples
openglcompiler-errorsglfwglad

Unable to compile OpenGL program in Ubuntu, due to GLAD errors


I installed GLWF succesfully. I can prove that since this program compiles:

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

Then i used these commands in order to install glad:

git clone https://github.com/Dav1dde/glad.git
cd glad
cmake ./
make
sudo cp -a include /usr/local/

When i tried to execute this program:

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

const char *vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";
const char *fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";

int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }


    // build and compile our shader program
    // ------------------------------------
    // vertex shader
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // fragment shader
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
         0.5f,  0.5f, 0.0f,  // top right
         0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left 
    };
    unsigned int indices[] = {  // note that we start from 0!
        0, 1, 3,  // first Triangle
        1, 2, 3   // second Triangle
    };
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0); 


    // uncomment this call to draw in wireframe polygons.
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // draw our first triangle
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
        //glDrawArrays(GL_TRIANGLES, 0, 6);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        // glBindVertexArray(0); // no need to unbind it every time 
 
        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

I got these errors:

/usr/bin/ld: /tmp/ccDMX5H7.o: in function `main':
triangle.c:(.text+0xe9): undefined reference to `gladLoadGLLoader'
/usr/bin/ld: triangle.c:(.text+0x12b): undefined reference to `glad_glCreateShader'
/usr/bin/ld: triangle.c:(.text+0x13f): undefined reference to `glad_glShaderSource'
/usr/bin/ld: triangle.c:(.text+0x162): undefined reference to `glad_glCompileShader'
/usr/bin/ld: triangle.c:(.text+0x173): undefined reference to `glad_glGetShaderiv'
/usr/bin/ld: triangle.c:(.text+0x19a): undefined reference to `glad_glGetShaderInfoLog'
/usr/bin/ld: triangle.c:(.text+0x1fd): undefined reference to `glad_glCreateShader'
/usr/bin/ld: triangle.c:(.text+0x211): undefined reference to `glad_glShaderSource'
/usr/bin/ld: triangle.c:(.text+0x234): undefined reference to `glad_glCompileShader'
/usr/bin/ld: triangle.c:(.text+0x245): undefined reference to `glad_glGetShaderiv'
/usr/bin/ld: triangle.c:(.text+0x26c): undefined reference to `glad_glGetShaderInfoLog'
/usr/bin/ld: triangle.c:(.text+0x2cf): undefined reference to `glad_glCreateProgram'
/usr/bin/ld: triangle.c:(.text+0x2de): undefined reference to `glad_glAttachShader'
/usr/bin/ld: triangle.c:(.text+0x2f7): undefined reference to `glad_glAttachShader'
/usr/bin/ld: triangle.c:(.text+0x310): undefined reference to `glad_glLinkProgram'
/usr/bin/ld: triangle.c:(.text+0x321): undefined reference to `glad_glGetProgramiv'
/usr/bin/ld: triangle.c:(.text+0x348): undefined reference to `glad_glGetProgramInfoLog'
/usr/bin/ld: triangle.c:(.text+0x3ab): undefined reference to `glad_glDeleteShader'
/usr/bin/ld: triangle.c:(.text+0x3bc): undefined reference to `glad_glDeleteShader'
/usr/bin/ld: triangle.c:(.text+0x4b9): undefined reference to `glad_glGenVertexArrays'
/usr/bin/ld: triangle.c:(.text+0x4d1): undefined reference to `glad_glGenBuffers'
/usr/bin/ld: triangle.c:(.text+0x4e9): undefined reference to `glad_glGenBuffers'
/usr/bin/ld: triangle.c:(.text+0x501): undefined reference to `glad_glBindVertexArray'
/usr/bin/ld: triangle.c:(.text+0x512): undefined reference to `glad_glBindBuffer'
/usr/bin/ld: triangle.c:(.text+0x528): undefined reference to `glad_glBufferData'
/usr/bin/ld: triangle.c:(.text+0x54b): undefined reference to `glad_glBindBuffer'
/usr/bin/ld: triangle.c:(.text+0x561): undefined reference to `glad_glBufferData'
/usr/bin/ld: triangle.c:(.text+0x584): undefined reference to `glad_glVertexAttribPointer'
/usr/bin/ld: triangle.c:(.text+0x5ad): undefined reference to `glad_glEnableVertexAttribArray'
/usr/bin/ld: triangle.c:(.text+0x5bb): undefined reference to `glad_glBindBuffer'
/usr/bin/ld: triangle.c:(.text+0x5ce): undefined reference to `glad_glBindVertexArray'
/usr/bin/ld: triangle.c:(.text+0x607): undefined reference to `glad_glClearColor'
/usr/bin/ld: triangle.c:(.text+0x630): undefined reference to `glad_glClear'
/usr/bin/ld: triangle.c:(.text+0x63e): undefined reference to `glad_glUseProgram'
/usr/bin/ld: triangle.c:(.text+0x64f): undefined reference to `glad_glBindVertexArray'
/usr/bin/ld: triangle.c:(.text+0x660): undefined reference to `glad_glDrawElements'
/usr/bin/ld: triangle.c:(.text+0x696): undefined reference to `glad_glDeleteVertexArrays'
/usr/bin/ld: triangle.c:(.text+0x6ae): undefined reference to `glad_glDeleteBuffers'
/usr/bin/ld: triangle.c:(.text+0x6c6): undefined reference to `glad_glDeleteBuffers'
/usr/bin/ld: triangle.c:(.text+0x6de): undefined reference to `glad_glDeleteProgram'
/usr/bin/ld: /tmp/ccDMX5H7.o: in function `framebuffer_size_callback(GLFWwindow*, int, int)':
triangle.c:(.text+0x764): undefined reference to `glad_glViewport'
collect2: error: ld returned 1 exit status

I compiled the program with this command:

g++ triangle.c -o triangle -Wall -lGL -lGLU -lglut -lGLEW -lglfw -lX11 -lXxf86vm -lXrandr -lpthread -lXi -ldl -lXinerama -lXcursor

EDIT: I used these two resources to perform the installation of the libraries: https://www.youtube.com/watch?v=ZwaHQ6c-ma0

https://shnoh171.github.io/gpu%20and%20gpu%20programming/2019/08/26/installing-glfw-on-ubuntu.html

EDIT 2: Because resources come and go, i will list the steps here:

GLEW/GLFW setup:

sudo apt update
sudo apt install build-essential
sudo apt install cmake
sudo apt install xorg-dev

download glfw source package https://www.glfw.org/download.html
unpack it in Desktop
go to unpacked directory

cmake -G "Unix Makefiles"
make
sudo make install

sudo apt-get install libx11-dev libglu1-mesa-dev freeglut3-dev libglew1.5 libglew1.5-dev libglu1-mesa libgl1-mesa-glx libgl1-mesa-dev libglfw3-dev libglfw3

make your own code and name it with extension .c
and then

gcc "source filename".c -o "filename" -Wall -lGL -lGLU -lglut -lGLEW -lglfw -lX11 -lXxf86vm -lXrandr -lpthread -lXi -ldl -lXinerama -lXcursor

also works with c++:

g++ "source filename".cpp -o "filename" -std=c++11 -Wall -lGL -lGLU -lglut -lGLEW -lglfw -lX11 -lXxf86vm -lXrandr -lpthread -lXi -ldl -lXinerama -lXcursor

And to install GLFW:

sudo apt-get install libglfw3
sudo apt-get install libglfw3-dev

Addition: GLAD can be installed with the following commands:

git clone https://github.com/Dav1dde/glad.git
cd glad
cmake ./
make
sudo cp -a include /usr/local/

Solution

  • Glad consists of multiple files:

    • A glad.h header file, which you have to include into your files
    • A glad.c source file which you have to compile together with your own source files.

    Judging from your error message, you forgot to also compile the glad.c source file. You can adapt your command line to something like:

    g++ triangle.c <GLADPATH>/glad.c -o triangle -Wall -lGL -lGLU -lglut -lGLEW -lglfw -lX11 -lXxf86vm -lXrandr -lpthread -lXi -ldl -lXinerama -lXcursor
    

    Replace <GLADPATH> with the path to the glad directory