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;
}
}
}
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
#include
s.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:
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:
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.
You aren't compiling
Game.cpp
. Try:The problem is that although you
#include
dGame.h
inmain.cpp
, it references functions that are defined inGame.cpp
. Without compiling that as well, the linker doesn't have the definitions required to make an executable.