main.cpp:(.text+0x5f): undefined reference to

48,501

Solution 1

C and C++ have the concept of a "compilation unit", this is the source file which the compiler was invoked with and all of the code that it #includes.

GCC, MSVC and most other compilers will generate an intermediate "object file" (.o or .obj) for each compilation unit. These must then be combined together, along with any libraries, to form the final executable, in a step referred to as "linking".

With GCC there are a few ways to do this. Single command:

g++ -o app.exe file1.cpp file2.cpp

This compiles file1.cpp and file2.cpp separately (each is still a single compilation unit) to object files and then links the resulting object files to an executable called "app.exe" (you don't need the .exe extension, I'm just using it for clarity)

Or multiple commands:

g++ -o file1.o -c file1.cpp
g++ -o file2.o -c file2.cpp
g++ -o app.exe file1.o file2.o

This performs the compilation step on each cpp individually and then performs a separate link step with 'g++' acting as a front-end to each step. Note the -c in the first two lines, which tells it you want to compile C/C++ source to .object. The 3rd line, the compiler front-end recognizes you're asking it to compile object files, and figures out you want to do the link step.

The first method is often easiest for small projects, the second method is useful when you are using any kind of build system and things start to get complicated.

Solution 2

You aren't compiling Game.cpp. Try:

g++ -o main main.cpp Game.cpp -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2

The problem is that although you #included Game.h in main.cpp, it references functions that are defined in Game.cpp. Without compiling that as well, the linker doesn't have the definitions required to make an executable.

Share:
48,501
Admin
Author by

Admin

Updated on February 16, 2020

Comments

  • Admin
    Admin about 4 years

    I try to compile some exercise from a SDL guide.

    I compile like this:

    g++ -o main main.cpp -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
    

    and i get this:

    /tmp/cci2rYNF.o: In function `main':
    main.cpp:(.text+0x5f): undefined reference to `Game::init(char const*, int, int, int, int, int)'
    collect2: error: ld returned 1 exit status
    

    and my code is:

    main.cpp

    #include "Game.h"
    
    // our Game object
    Game* g_game = 0;
    
    int main(int argc, char* argv[])
    {
        g_game = new Game();
        g_game->init("Chapter 1", 100, 100, 640, 480, 0);
    
        while(g_game->running())
        {
        g_game->handleEvents();
        g_game->update();
        g_game->render();
        }
        g_game->clean();
    
        return 0;
    }
    

    Game.h

    #ifndef __Game__
    #define __Game__
    
    #include <SDL.h>
    
    class Game
    {
        public:
          Game() {}
          ~Game() {}
    
          bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
          void render(){}
          void update(){}
          void handleEvents(){}
          void clean(){}
    
          // a function to access the private running variable
          bool running() { return m_bRunning; }
    
        private:
    
          SDL_Window* m_pWindow;
          SDL_Renderer* m_pRenderer;
          bool m_bRunning;
    };
    
    #endif // defined(__Game__) */
    

    Game.cpp

    #include "Game.h"
    
    bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags)
    {
        // attempt to initialize SDL
        if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
        {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos,
        width, height, flags);
    
        if(m_pWindow != 0) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
            std::cout << "renderer creation success\n";
            SDL_SetRenderDrawColor(m_pRenderer,
            255,255,255,255);
            }
            else
            {
            std::cout << "renderer init fail\n";
            return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
        }
        else
        {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
        }
        std::cout << "init success\n";
        m_bRunning = true; // everything inited successfully, start main loop
    
        return true;
    }
    
    
    void Game::render()
    {
        SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
        SDL_RenderPresent(m_pRenderer); // draw to the screen
    }
    
    
    void Game::clean()
    {
        std::cout << "cleaning game\n";
        SDL_DestroyWindow(m_pWindow);
        SDL_DestroyRenderer(m_pRenderer);
        SDL_Quit();
    }
    
    void Game::handleEvents()
    {
        SDL_Event event;
        if(SDL_PollEvent(&event))
        {
          switch (event.type)
          {
            case SDL_QUIT:
              m_bRunning = false;
            break;
    
            default:
            break;
          }
        }
    }