Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 Writing programs using SDL with linux and Makefiles
Index -> Programming, C++ -> C++ Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message

PostPosted: Sat Nov 26, 2005 8:32 pm   Post subject: Writing programs using SDL with linux and Makefiles

Since a quick google will provide lots of help for linux users of SDL I'm not going to cover that at all. Linux on the other hand is a completely different story; it's not extremely difficult to figure it out on your own but it can be a pain in the ass.

Disclaimer: There are many different linux distributions and many different ways of getting the job done. I use gentoo and gnome, so that's what will be used in this tutorial; however there shouldn't be any major differences if you use something else.

Installing SDL
Installing SDL is actually pretty strait forward, the easiest way is to download the tarball and extract it to a folder you find convienent.

Getting SDL wrote:

mkdir -p ~SDL//libsdl
cd ~/SDL/libsdl
tar -xvjpf SDL-1.2.9.tar.gz

** note you can get the file though Firefox or any other web browser and extract it however you wish. wget and tar are just quick and easy Razz

Now that we've got the source code it's just a simple ./configure, make, make install away! However therin lies the first challenge. In order to run make install you must have root privileges; the simplest way to do that would be using su or sudo, since I don't have sudo I use su. Since we don't need to be root to compile anything it's safer to wait until we need to run make install to become root, and we'll go back to being a normal user once we're done.
Installing wrote:

make install

There! Done just like that! The problem is that this gets you only the very basic libraries. To make things a lot more useful we'll also get the SDL_image library too
Get and install SDL_image wrote:

mkdir ~/SDL/SDL_image
cd ~/SDL/SDL_image
tar -xvjpf SDL_image-1.2.4.tar.gz
make install

Setting up a Project
When I say project I mean a project as an idea; not in some IDE or anything. I find that if I create a simple directory-tree to keep my source and object files organized it helps me keep track of things much easier. For this tutorial we're going to name our project "SDL_Test", and we're going to store all it's files in ~/SDL_Test.
Creating the 'Project' wrote:

mkdir ~/SDL_Test
cd ~/SDL_Test
mkdir Build
mkdir Source

It's fairly simple; source code goes in Source, the compiled code will go in Build. If your project requires lots of other resourses (sounds, graphics) create another directory to store them in. That way you can keep things seperated and easy to find. Since we only have one image it's easiest just to store it in the base directory

A directory structure is nice and all, but it isn't much of a program. So what we now need to do is write some code. We're going to have two files: main.cpp which will contain our main function, and global.h which will contain any includes we want to be assessible in any additional files we might want to add later. Both get saved in Source


#include "global.h"

int main (int argc, char **argv)
        // initialize SDL

        // set the title bar
        SDL_WM_SetCaption("SDL Test", "SDL Test");

        // create window
        SDL_Surface* screen = SDL_SetVideoMode(640, 480, 0, 0);

        /* load bitmap to temp surface */
        SDL_Surface* temp = IMG_Load("hello.png");

        /* convert bitmap to display format */
        SDL_Surface* bg = SDL_DisplayFormat(temp);

        /* free the temp surface */

        SDL_Event event;
        int gameover = 0;

        /* message pump */
        while (!gameover)
                /* look for an event */
                if (SDL_PollEvent(&event))
                        /* an event was found */
                        switch (event.type)
                                /* close button clicked */
                                case SDL_QUIT:
                                        gameover = 1;

                                /* handle the keyboard */
                                case SDL_KEYDOWN:
                                        switch (event.key.keysym.sym)
                                                case SDLK_ESCAPE:
                                                case SDLK_q:
                                                        gameover = 1;

                /* draw the background */
                SDL_BlitSurface(bg, NULL, screen, NULL);

                /* update the screen */
                SDL_UpdateRect(screen, 0, 0, 0, 0);

        /* free the background surface */

  // cleanup SDL
  return 0;


#include <iostream>

// SDL
#include <SDL.h>
#include <SDL_image.h>

We've got source code; we've got libraries. Surely we can just call the compiler directly and not worry about these makefile things right? Of course we can, but then what happens if you add another file? Or two? Or 20? It quickly becomes a nightmare to remember all those filenames and type them all just to compile a small change. Makefiles to the rescue!

A makefile allows you to say what files depend on what and how t obuild them, and then when you want to recompile after a small change only the things that need to be will be recompiled. So now when you change one file out of your 20 it'll only take a second or two to compile instead of the minute or more that all 20 might take.

There are lots of guides on writing makefiles on the web, and makefiles are WAY beyond my ability to write a thorough tutorial on, but for my projects I've written one makefile which is easy to extend and very straitforward


#   Default make file

#   Directories

#   Output
# default build settings
##  debug setup
CC_OPTS=-c -pipe -Wall -Wno-switch -ggdb -g3 
##  release setup
#C_OPTS=-c -pipe

#       SDL options
CC_SDL=-I/usr/local/include/SDL -D_REENTRANT
LN_SDL=-L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lSDL_image -lpthread

#   This is the default action

#   Object list
OBJ = $(B_DIR)/main.o

#   Objects
$(B_DIR)/main.o : $(S_DIR)/main.cpp $(S_DIR)/global.h
        $(CC) $(CC_OPTS) -o $(B_DIR)/main.o $(S_DIR)/main.cpp $(CC_SDL)

#   Main build rule     
Build : $(OBJ) Makefile
        $(CC) $(LN_OPTS) -o $(EXEC) $(OBJ) $(LN_SDL)

        rm -f $(B_DIR)/*

Now... it looks really complex and to be fair it kinda is; but a little bit of info makes it useful.
First we have our source and build directories. We set S_DIR and B_DIR because you could technically name your directories whatever you wanted, and S_DIR and B_DIR are nice and short.
Next up is the name of finished compiled program, though you can call it whatever I usually add .exec so I know that it's easy to tell it's an executable.
Then there are three important variables that are best left alone. CC_OPTS are compile options, LN_OPTS are link options, and CC is the compiler/linker. CC_OPTS and LN_OPTS are just standard options for whatever you choose as your compiler (here we're using g++, the GNU C++ compiler).
The SDL Options are taken from the ouput of sdl-config --cflags --libs. The output should look something like
john@sax ~/SDL_Test $ sdl-config --cflags --libs
-I/usr/local/include/SDL -D_REENTRANT
-L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lpthread
The first line is where we get our SDL_CC line from, the second SDL_LN; they are the SDL include directory and SDL libraries and library directories respectively. We add -lSDL_image to the linker because the SDL_image library is also used.

The rest of the file is instructions on what to build. The important parts are OBJ= which is a space seperated list of all the object files you have rules for, and the section listed as Objects. The OBJ list is quite simple, basically there should be a *.o for every source file you have. Object files (*.o) will be saved to the build directory so we need to put $(B_DIR) (the build directory shortcut) in from of each object file name.

In the Objects grouping things are a little more complex. Each f=source file has two lines, one which specifies what it depends on, and one to say how to build it.

$(B_DIR)/main.o : $(S_DIR)/main.cpp $(S_DIR)/global.h
Says that the object file main.o relies on main.cpp and global.h. If either main.cpp or global.h have changed since the last time we compiled recompile main.o.
$(CC) $(CC_OPTS) -o $(B_DIR)/main.o $(S_DIR)/main.cpp $(CC_SDL)
Says how to compile.

To add aditional files all you need to do is add the file to the OBJ list and copy/modify the lines for main.o; main.o becomes <filename.o>, main.cpp becomes <filename>.cpp, and any other required files go on the end of the first line just like $(S_DIR)/global.h

After that all that's left is the step for building the executable, it doesn't require any changes, and the command to clean all the intermediate files. The makefile given will work for out SDL_Test project without any modifications.

Compiling and testing
At this point it's actually pretty trivial; to compile we just need to type "make" in the base directory, and then to run the executable we just type "Build/SDL_Test.exec". We also need to copy a png file (any png file!) to the base directory or the program won't run right. Here's the commands:
Compiling nad Running wrote:


And the output:
Posted Image, might have been reduced in size. Click Image to view fullscreen.

Setting up SDL really isn't that difficult once you figure it out, and once you get a working makefile it's really easy to keep things working. Hopefully this will inspire some more people to check out SDL and/or linux Very Happy

resources SDL site
Display posts from previous:   
   Index -> Programming, C++ -> C++ Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 1 Posts ]
Jump to: