|
|
|
---
|
|
|
|
short-description: A simple GUI tutorial
|
|
|
|
...
|
|
|
|
|
|
|
|
# Building a simple SDL2 app from scratch
|
|
|
|
|
|
|
|
This page shows from the ground up how to define and build an SDL2 gui
|
|
|
|
application using nothing but Meson. The document is written for
|
|
|
|
Windows, as it is the most complex platform, but the same basic ideas
|
|
|
|
should work on Linux and macOS as well.
|
|
|
|
|
|
|
|
The sample application is written in plain C as SDL 2 is also written
|
|
|
|
in C. If you prefer C++ instead, the conversion is fairly simple and
|
|
|
|
is left as an exercise to the reader.
|
|
|
|
|
|
|
|
This document assumes that you have already installed both Visual
|
|
|
|
Studio and Meson.
|
|
|
|
|
|
|
|
# Set up the build directory
|
|
|
|
|
|
|
|
First you need to create an empty directory for all your stuff. The
|
|
|
|
Visual Studio toolchain is a bit unusual in that it requires you to
|
|
|
|
run your builds from a specific shell. This can be found by opening
|
|
|
|
the application menu and then choosing `Visual Studio <year> -> x86_64
|
|
|
|
native tools command prompt`.
|
|
|
|
|
|
|
|
It will put you in a weird directory, so you need to go to your home
|
|
|
|
directory:
|
|
|
|
|
|
|
|
cd \users\yourusername
|
|
|
|
|
|
|
|
Typically you'd type `cd \users\` and then press the tabulator key to
|
|
|
|
make the shell autocomplete the username. Once that is done you can
|
|
|
|
create the directory.
|
|
|
|
|
|
|
|
mkdir sdldemo
|
|
|
|
cd sdldemo
|
|
|
|
|
|
|
|
# Creating the sample program
|
|
|
|
|
|
|
|
Now we need to create a source file and a Meson build definition file.
|
|
|
|
We're not going to use SDL at all, but instead start with a simple
|
|
|
|
program that only prints some text. Once we have it working we can
|
|
|
|
extend it to do graphics. The source goes into a file `sdlprog.c` and
|
|
|
|
has the following contents:
|
|
|
|
|
|
|
|
```c
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
printf("App is running.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The build definition goes to a file called `meson.build` and looks
|
|
|
|
like this:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('sdldemo', 'c')
|
|
|
|
|
|
|
|
executable('sdlprog', 'sdlprog.c')
|
|
|
|
```
|
|
|
|
|
|
|
|
With this done we can start the build with the following command:
|
|
|
|
|
|
|
|
meson setup builddir
|
|
|
|
|
|
|
|
Here `builddir` is the _build directory_, everything that is generated
|
|
|
|
during the build is put in that directory. When run, it should look
|
|
|
|
like this.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
The program is compiled with this:
|
|
|
|
|
|
|
|
meson compile -C builddir
|
|
|
|
|
|
|
|
The `-C` argument tells Meson where the configured build directory is.
|
|
|
|
|
|
|
|
The program will be in the build directory and can be run like this:
|
|
|
|
|
|
|
|
builddir\sdlprog
|
|
|
|
|
|
|
|
The output should look like this.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
# Upgrading the program to use SDL
|
|
|
|
|
|
|
|
The code needed to start SDL is a bit more complicated and we're not
|
|
|
|
going to go into how it works. Merely replace the contents of
|
|
|
|
`sdlprog.c` with the following:
|
|
|
|
|
|
|
|
```c
|
|
|
|
#include "SDL.h"
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
SDL_Window *window;
|
|
|
|
SDL_Renderer *renderer;
|
|
|
|
SDL_Surface *surface;
|
|
|
|
SDL_Event event;
|
|
|
|
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
|
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SDL_CreateWindowAndRenderer(320, 240, SDL_WINDOW_RESIZABLE, &window, &renderer)) {
|
|
|
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
SDL_PollEvent(&event);
|
|
|
|
if (event.type == SDL_QUIT) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
|
|
|
|
SDL_RenderClear(renderer);
|
|
|
|
SDL_RenderPresent(renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_DestroyRenderer(renderer);
|
|
|
|
SDL_DestroyWindow(window);
|
|
|
|
|
|
|
|
SDL_Quit();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Let's try to compile this by running `meson compile -C builddir` again.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
That fails. The reason for this is that we don't actually have SDL
|
|
|
|
currently available. We need to obtain it somehow. In more technical
|
|
|
|
terms SDL2 is an _external dependency_ and obtaining it is called
|
|
|
|
_dependency resolution_.
|
|
|
|
|
|
|
|
Meson has a web service for downloading and building (if needed)
|
|
|
|
dependencies called a WrapDB. It provides SDL2 so we can use it
|
|
|
|
directly. First we need to create a `subprojects` directory because in
|
|
|
|
Meson all subprojects like these must be stored in that directory for
|
|
|
|
consistency.
|
|
|
|
|
|
|
|
mkdir subprojects
|
|
|
|
|
|
|
|
Then we can install the dependency:
|
|
|
|
|
|
|
|
meson wrap install sdl2
|
|
|
|
|
|
|
|
It looks like this:
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
As a final step we need to update our build definition file to use the
|
|
|
|
newly obtained dependency.
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('sdldemo', 'c',
|
|
|
|
default_options: 'default_library=static')
|
|
|
|
|
|
|
|
sdl2_dep = dependency('sdl2')
|
|
|
|
|
|
|
|
executable('sdlprog', 'sdlprog.c',
|
|
|
|
win_subsystem: 'windows',
|
|
|
|
dependencies: sdl2_dep)
|
|
|
|
```
|
|
|
|
|
|
|
|
**NOTE:** If you're on Windows you need to include the sdl2main dependency as well; To do so you can modify the above build script like so:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('sdldemo', 'c',
|
|
|
|
default_options: 'default_library=static')
|
|
|
|
|
|
|
|
sdl2_dep = dependency('sdl2')
|
|
|
|
sdl2_main_dep = dependency('sdl2main')
|
|
|
|
|
|
|
|
executable('sdlprog', 'sdlprog.c',
|
|
|
|
win_subsystem: 'windows',
|
|
|
|
dependencies: [sdl2_dep, sdl2_main_dep])
|
|
|
|
```
|
|
|
|
|
|
|
|
In addition to the dependency this has a few other changes. First we
|
|
|
|
specify that we want to build helper libraries statically. For simple
|
|
|
|
projects like these it makes things simpler. We also need to tell
|
|
|
|
Meson that the program we are building is a Windows GUI
|
|
|
|
application rather than a console application.
|
|
|
|
|
|
|
|
This is all we need to do and can now run `meson compile` again. First
|
|
|
|
the system downloads and configures SDL2:
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
A bit later the compilation exits successfully.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
# Program is done
|
|
|
|
|
|
|
|
Now we can run the application with
|
|
|
|
|
|
|
|
builddir\sdlprog
|
|
|
|
|
|
|
|
The end result is a black SDL window.
|
|
|
|
|
|
|
|

|