Compiling Raylib programs with SCons

If you like writing programs in C, are interested in game development and don’t enjoy all those complicated and ancient build systems I think I’ve got something of interest to you. I belive there is something enjoyable in the simple setup I’m describing below. Hope you will enjoy as well.

Raylib

Raylib is a C library made by @Ray San. On the Raylib’s website it says ‘raylib is a simple and easy-to-use library to learn video games programming’. Whole API can be browsed here. It does abstract a lot of things important for game developement. It’s important to note because if you chose to write something in C, performance is something you might care about. High level abstraction usually takes a toll on performance. In this case mostly because you are not tuning small parts of your code to suit your needs. Raylib wants to abstract those parts to make the learning easier. In the end you have the power of C (which basically allows you to write performant code) and high level abstraction Raylib library provides you. That’s a good starting point to write cool software, enjoyable for the end user.

SCons

If you ever installed Raylib you know it comes packed with configured Notepad++ and a MinGW so you can load an example source file, press F6 and that’s enough to compile your first Raylib program. Great for beginners. It takes the building process out of the equation. At some point it’s important to understand the build process so you can add other libraries to your program. Setting up build environment is a hassle though. That’s where SCons comes in.

SCons is a build system written in Python. It also uses Python as its Makefile language. If you know a bit of Python the syntax will be familiar. If you don’t - don’t worry. Python is a simple but powerful scripting language. It’s really popular nowadays. You will benefit from learning a bit of it (but I’m not going to go through the Python syntax in this article). I found using SCons more convenient than make or CMake. Hopefully you will too.

I’m sorry for this small derail. Lets get started, shall we?

Raylib you may now kiss SCons

Ok lets start with a basic projects folder structure - please come back to it if what I’m writing below seems confusing:

--- /mr_banana_project
   |-- /build
   |  |-- /debug
   |  |-- /release
   |-- /libs
   |  |-- /raylib
   |  |  |-- /include
   |  |  |-- /libs
   |  |  |  |-- /android
   |  |  |  |-- /html5
   |  |  |  |-- /linux
   |  |  |  |-- /osx
   |  |  |  |-- /rpi
   |  |  |  |-- /win32
   |  |-- /lib2
   |-- /obj
   |-- /src
   |-- SConstruct

Above you can see pretty typical folder structure for a small software project.

Your source files go into /mr_banana_project/src.

Compiled projects go into /mr_banana_project/build/debug or …/release depending if the final or debug software is being built. Libraries are held in their corresponding folders. For example Raylib goes into /libs/raylib folder with its /include and /libs folders. Former holds the header files and latter the compiled libraries for specific platforms. Notice Raylib has libraries for: Android, HTML 5, Linux, OSX, Raspberry Pi and Windows - sweet! Those two folders in /raylib were copied from the installation directory of the Raylib itself. After installing Raylib you will find those here: C:\raylib\raylib\release (Raylib installs directly onto C drive by default).

You can also see that in the main directory of the project there is one file called SConstruct. That’s the Makefile SCons uses.

Lets take a look:

env = Environment(
  tools = ['mingw'],
  CXXFLAGS = ['-g', '-std=c99'],
  CPPPATH = ['./libs/raylib/include', './libs/easing'],
  LIBPATH = ['./libs/raylib/libs/win32/mingw32'],
  LIBS = [ \
    'raylib' \
    ,'glfw3' \
    ,'opengl32' \
    ,'gdi32' \
    ,'openal32' \
    ,'winmm' \
  ]
)


env.Object(target='./obj/main.o', source='./src/main.c')

env.Program( \
    target='./build/release/main' , \
    source=[ \
    './obj/main.o' \
    ,'./obj/easing.o' \
    ] \
)

So the basic things are Object and Program commands.

Object builds an object file so it’s basically preprocessing and compiling the unit (simplification but lets say a unit is one source file). If your source file doesn’t have any dependencies or you don’t need to pass any arguments to the compiler you can run those without the env. prefix - we will come back to this.

Program links all of the object files and creates final executable. Looking at the arguments of Program you can probably easily discern that it will take main.o and easing.o and output an executable to build/release/ with a name main.

The Environment allows you to create well… an environment in which the program will be compiled. You can set compile flags, header files directory, library directories and even which compiler it should use. I use this file on Windows and by default it wanted to compile with Visual Studios compiler. I wanted to use MinGW. Simple tools = [‘mingw’] was enough. You build IN a specific environment by appending env. to the command.

At the first glance a build system built with Python seems like an attempt at abstracting the build process but SCons achieves verbosity with simplicity. You can learn and see the compiling process even though you are not linking files by hand. The Object command is just preprocessing and compiling. Program is the linking part. Those are basic stages of making an executable. Those are things you should know even if you are writing websites in Django.

Read through this SConstruct. It’s really basic. It allows linking with all of the libs Raylib needs. It also uses easing library written by Auerhaus Development (I used it because at the time of writing I didn’t knew Raylib has easings functions built in…). It also uses Raygui library which is a graphical user interface library also written by @Ray San. Since it’s just a header file I have put it in /raylib/include folder. This directory is already covered by SConstruct which means I can freely include it in my files.

After installing SCons you just need to navigate to the folder in which SConstruct file is located and the following command in a terminal:

scons

By doing so SCons will invoke the command line compiler command. You can see exactly what SCons is doing which I believe is useful, especially when it’s fails to build and you have to debug the compiling process itself.

I know I barely scratched the surface. Depending on where you are with your skill and knowledge this article might be helpful or just confusing. Feel free to give me feedback and ask questions.

Hopefully soon, I will be able to write about the first program I’m writing with Raylib.