-----Original Message-----Linux games programming HOWTO: Part 1
From: alex@accesinternet.com [mailto:alex@accesinternet.com]On Behalf Of Alexandre Courbot
Sent: Monday, May 24, 1999 1:08 PM
To: linuxgames@sunsite.auc.dk
Subject: Re: Hi everybody!(Please pardon the English mistakes)
This is the first part of the Linux games programming HOWTO. The goal of this part is to provide information on linux programming specificities and graphics libraries. I assume that you have basic knowledge in C. Linux advanced knowledge are not necessary(just the basics). All the development tools will be studied. Now.
1)The C/C++ compiler:GCC/G++.
The tool you must have :). GCC is a very performant, free software C compiler. It is normally installed on every linux system. It has a DOS/Windows port that is called DJGPP, and that is very performant too. GCC is a command line compiler, so you need an external editor (emacs is good) and you'll have to keep in mind some parameters.
GCC command line usefull parameters: > The "-o <name>" option is always used and sets the executable name. If you omit it, it will be a.out. > The "-Wall" option will warn you if it detects a non fatal incoherence in your code. Always use it: it's the best way to test your code quality.
Now we can make the classic Hello World on Linux: Edit a hello.c file:#include <stdio.h>
void main()
{
printf("Hello World! (From Linux)\n");
}
Now compile it:
[alex@bluefalcon]~/tut $gcc hello.c -Wall -o hello
(Note:[alex@bluefalcon]~/tut $ is my prompt, so don't type it ;), the command start at "gcc".)
And launch it:
[alex@bluefalcon]~/tut $./hello
Hello World! (From Linux)> The "-O<n>" option sets the level of optimisation. GCC can optimize your code, and do it well. <n> can go from 0 (no optimisation) to 3 (all optimisations). Others optimisation levels will be added in next versions.
> "-c" tells GCC to compile but not to link. This will create a .o file that you may link later.
Example:
hello.c:
#include <stdio.h>
void print_to_screen(char * s)
{
printf("%s\n",s);
}main.c:
#include <stdio.h>void print_to_screen(char * s); /* Used to avoid a warning */
void main()
{
char str[]="Hello World!";
print_to_screen(str);
}Now let's compile this:
[alex@bluefalcon]~/tut $gcc hello.c -c -o hello.o -Wall -O6
[alex@bluefalcon]~/tut $gcc main.c -c -o main.o -Wall -O6
[alex@bluefalcon]~/tut $ls *.o
hello.o main.o
[alex@bluefalcon]~/tut $gcc hello.o main.o -o hello
[alex@bluefalcon]~/tut $./hello
Hello World!gcc hello.o main.o -o hello just take the two object files and link them to make an executable.
> "-l<libname>" is used to link your program to a library. Linux use shared libraries to avoid code redundany in memory. Libraries are usually in 3 directories:
In /usr/X11R6/lib you will find the X window libraries, but we'll not use them for the moment.
- /lib for the core libraries,
- /usr/lib for the libraries that comes with your distribution,
- /usr/local/lib for the libraries you have compiled yourself.
In these directories, all libraries files are in the format lib<libname>.so.* or lib<libname>.a. The .so extension mean this library can be linked dynamically, the .a mean it can be linked statically. Let's see an example using the maths library:main.c:
#include <stdio.h>
#include <math.h> /* We include maths files headers */void main()
{
printf("%f\n",sqrt(2));
}If we try to compile like we used to do here is the result:
[alex@bluefalcon]~/tut $gcc main.c -o math
/tmp/ccc02939: In function `main':
/tmp/ccc02939(.text+0xb): undefined reference to `sqrt'
[alex@bluefalcon]~/tut $ls math
ls: math: No such file or directoryThat's because the sqrt funtion is in the m library:
[alex@bluefalcon]~/tut $ls /usr/lib/libm.*
/usr/lib/libm.a /usr/lib/libm.soSo we have to compile like this:
[alex@bluefalcon]~/tut $gcc main.c -o mathdynamic -lmOr if we want a static binary (Which will run even if the library is not on the system):
[alex@bluefalcon]~/tut $gcc main.c -o mathstatic -lm -staticHowever the static binary size is much more important than the dynamic one!
[alex@bluefalcon]~/tut $ls -l mathdynamic mathstatic
-rwxr-xr-x 1 alex alex 4194 mai 13 15:45 mathdynamic
-rwxr-xr-x 1 alex alex 117691 mai 13 15:45 mathstaticIf you want to check the links of an executable you can use ldd:
[alex@bluefalcon]~/tut $ldd mathdynamic
libm.so.6 => /lib/libm.so.6 (0x40013000)
libc.so.6 => /lib/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
[alex@bluefalcon]~/tut $ldd mathstatic
statically linked (ELF)...And if your libraries are in another directory you can add the "-L/usr/my_weird_directory/" to tell gcc to search libraries in that directory too.
The library concept is very important in linux programming, but we'll have many occasions to work with it later, so don't worry is it doesn't seems clear.
Last thing:if you prefer c++, just change gcc by g++ in the compile command line.
2)Getting documentation: The man pages.
The man pages are the best friend of the UNIX programmer. They provide you a complete documentation on all the functions you have on your system. For example, if you need help on the sqrt function just type:
[alex@bluefalcon]~/tut $man sqrt
Everything is explained: syntax, error codes, include files, library links,... The man pages are very clear and doesn't need other explanations. You may also find documentation in the /usr/doc directory.
3)The Makefile: The One That Will Save Your Fingers.
The problem is that a big application can have hundreds of .c files and link toa lot of libraries. In some case a compilation line can fill all the screen! Thanks to make and the Makefile you'll not have to type all of this. When you launch "make" it will search for a file named "Makefile":
[alex@bluefalcon]~/tut $make
make: *** No targets. Stop.For the moment we have no Makefile, so we got this output.
An example:
We'll use 3 .c and 1 .h files, plus a Makefile:hello.c:
#include <stdio.h>
#include "defines.h"
void say_hello()
{
printf("Hello World! The square root of 2 is %f!\n",sqrt_of(2));
}
math.c:
#include <stdio.h>
#include <math.h>
#include "defines.h"double sqrt_of(double x)
{
return(sqrt(x));
}main.c:
#include <stdio.h>
#include "defines.h"
void main()
{
say_hello();
}defines.h:
/* Fonctions prototypes to avoid compilation warnings */
void say_hello();
double sqrt_of(double x);Makefile:
CC=gcc
CFLAGS=-Wall -O6
LIBS=-lm
OBJECTS=math.o hello.o main.o
PROGRAM=helloall:$(OBJECTS)
$(CC) $(OBJECTS) $(LIBS) -o $(PROGRAM)clean:
rm -rf *.o $(PROGRAM)Some explanations:
-The 5 first lines are aliases definitions. Further in the Makefile, when we refer to $(OBJECTS) it will in fact refer to math.o, hello.o and main.o. The advantage of aliases is that you can easily change your compilation parameters.
-This Makefile has 2 targets, named "all" and "clean". On the same line as the target definition are the .o objects that must be generated by this target (for "all" its math.o, hello.o and main.o, for "clean" there are no objects). The $(CC) compiler will be launched with $(CFLAGS) as parameters, and will create the objects from the corresponding source files (math.c for math.o) if they have changed since the last compilation.
-The lines after the target definition MUST start by a tabulation. You can write UNIX shell command and use aliases. For example, the second line of "all" will link all the objects to the executable and "clean" will delete all the objects files and the executable.
-You must invoque "make" with the corresponding target. However, if you just type "make" it will build the first target ("all").Once you have typed all the files, compile them:
[alex@bluefalcon]~/tut $ls
Makefile defines.h hello.c main.c math.c
[alex@bluefalcon]~/tut $make
gcc -Wall -O6 -c math.c -o math.o
gcc -Wall -O6 -c hello.c -o hello.o
gcc -Wall -O6 -c main.c -o main.o
gcc math.o hello.o main.o -lm -o hello
[alex@bluefalcon]~/tut $ls
Makefile hello hello.o main.o math.o
defines.h hello.c main.c math.c
[alex@bluefalcon]~/tut $./hello
Hello World! The square root of 2 is 1.414214!
[alex@bluefalcon]~/tut $make clean
rm -rf *.o hello
[alex@bluefalcon]~/tut $ls
Makefile defines.h hello.c main.c math.c
[alex@bluefalcon]~/tut $The last thing to know on make: it can take a "-C <directory>" parameter. This will launch make in the directory you specified, and is very usefull is your program is divided into several directories.
Allright! You have the basics of linux programming! Let's now see more game-specific stuff!
4)The graphics libraries.
On UNIX system, the acces to video memory is locked to avoid system crash. You can't have direct acces to the video memory, unless you are root. So if you want to program graphic applications you'll certainly want to use a graphic library. The advantages are multiple, the main is that the libraries use all your video card acceleration.
There are several way to code graphics:
- You can use the svgalib, a console based graphic library that is certainly installed on your system, easy and powerfull, but require root privileges (so beware of crash!)
- Another way is to code with the Xlib, the X-Window library. In that case your program will have to be launched under X-Window and will be windowed. Performant, but Xlib is very complex. I don't plan to explain it in this tutorial.
- The best way! Recently new graphic libraries have appeared. The most used are:
- GGI: An excellent graphic library. The programs made with this library can be launched under the console or under X-Window, windowed or full screen, they can use Glide acceleration (without adding any code!), run on multi screen,.... Look at this and cry! GGI should be ported to Windows... one day (So you just need to recompile your app and it'll run under windows too!).
- SDL:This library is interesting because it works on linux and windows. Very good for multiplatform games.
- MESA:Mesa is a free, compatible implementation of OpenGL. If you want to do 3D OpenGL programming that's what you need. Mesa exist for many many system (including linux and windows) and support of course hardware acceleration.
That's all for this part. Please give me feedback, so I know what should be seen in the next part (I plan to make our first graphic app using svgalib and GGI). If you have problems with this part, please ask questions to the linux forum. English corrections are welcome!
Thank you for reading this tutorial.