Article One - Setup

Project Creation

Creating a Vala project is as easy as creating a Vala source file and running the compiler, valac, on it. However, Vala also ships with a tool called vala-gen-project which generates a full Autotools project including support for internationalization via Gettext. We will be using this to begin our project, Brickval, which will be a simple breakout clone. To start we simply create the projects directory and then execute vala-gen-project in the directory:

mkdir -p ~/dev/brickval
cd ~/dev/brickval
vala-gen-project

The last command will bring up the Vala Project Generator window. From this window you may choose the type of application (GTK+ or Console), and enter in various meta-data about the project. Fill out the window so it looks something like the following (the directory is already the correct one):

Vala Project Generator

In particular, ensure that the application type is Console. We will not be using GTK+ for this project. Listing the directory back in the terminal will now show the results of vala-gen-project 's labors.

Autotools Configuration

While the project that vala-gen-project generates is fully functional we will be making additional changes to the template it provided to customize it to the needs of our project.

Configure.ac

The first file we will be editing is configure.ac. The following listing shows the modified configure.ac file for our project's use:

AC_INIT([brickval], [0.1.0], [me@lesharris.com], [brickval])
AC_CONFIG_SRCDIR([src/Makefile.am])
AC_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE([dist-bzip2])
AM_MAINTAINER_MODE

AC_PROG_CC
AM_PROG_CC_C_O
AC_DISABLE_STATIC
AC_PROG_LIBTOOL

AC_PATH_PROG(VALAC, valac, valac)
AC_SUBST(VALAC)

AH_TEMPLATE([GETTEXT_PACKAGE], [Package name for gettext])
GETTEXT_PACKAGE=brickval
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE")
AC_SUBST(GETTEXT_PACKAGE)
AM_GLIB_GNU_GETTEXT
IT_PROG_INTLTOOL([0.35.0])

AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)

GLIB_REQUIRED=2.12.0
SDL_REQUIRED=1.2.0
GEE_REQUIRED=0.1.3

PKG_CHECK_MODULES(BRICKVAL, glib-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED gee-1.0 > $GEE_REQUIRED)
AC_SUBST(BRICKVAL_CFLAGS)
AC_SUBST(BRICKVAL_LIBS)

VALA_PACKAGES="--pkg gee-1.0 "
SDL_AUX_LIBS=""

PKG_CHECK_MODULES(SDL, sdl >= $SDL_REQUIRED)
AC_SUBST(SDL_CFLAGS)
AC_SUBST(SDL_LIBS)
VALA_PACKAGES="$VALA_PACKAGES--pkg sdl "

AC_CHECK_HEADERS(SDL/SDL_gfxPrimitives.h,
        SDL_AUX_LIBS="$SDL_AUX_LIBS-lSDL_gfx ",
        AC_MSG_ERROR([SDL_gfx required but not found.])
        )
VALA_PACKAGES="$VALA_PACKAGES--pkg sdl-gfx "

AC_CHECK_HEADERS(SDL/SDL_image.h,
        SDL_AUX_LIBS="$SDL_AUX_LIBS-lSDL_image ",
        AC_MSG_ERROR([SDL_image required but not found.])
        )
VALA_PACKAGES="$VALA_PACKAGES--pkg sdl-image "

AC_CHECK_HEADERS(SDL/SDL_mixer.h,
        SDL_AUX_LIBS="$SDL_AUX_LIBS-lSDL_mixer ",
        AC_MSG_ERROR([SDL_mixer required but not found.])
        )
VALA_PACKAGES="$VALA_PACKAGES--pkg sdl-mixer "

AC_CHECK_HEADERS(SDL/SDL_ttf.h,
        SDL_AUX_LIBS="$SDL_AUX_LIBS-lSDL_ttf ",
        AC_MSG_ERROR([SDL_ttf required but not found.])
        )
VALA_PACKAGES="$VALA_PACKAGES--pkg sdl-ttf "

AC_SUBST(SDL_AUX_LIBS)
AC_SUBST(VALA_PACKAGES)

AC_CONFIG_FILES([Makefile
        data/Makefile
        data/backgrounds/Makefile
        data/sprites/Makefile
        src/Makefile
        po/Makefile.in])

AC_OUTPUT

Open the original configure.ac that vala-gen-project generated and compare the two. The main additions are some additional modules that are checked in PKG_CHECK_MODULES, some extra Makefiles in AC_CONFIG_FILES, two new variables VALA_PACKAGES and SDL_AUX_LIBS, and a bunch of AC_CHECK_HEADER stuff in the middle. If this looks alarming to you, don't panic! Remember that you only have to do this once, and also, that it is not as bad as it might appear.

If you understand everything here feel free to skip to the next section.

For those that are still here this is what's going on in the configure.ac file. Most modern linux distributions ship with a utility called pkg-config which provides an easy way to lookup various compiler options that a particular library needs. PKG_CHECK_MODULES in our configure.ac script simply checks for these libraries and ensures we have the correct versions of them installed. It then stores their compiler option information in BRICKVAL_CFLAGS and BRICKVAL_LIBS.

Brickval also depends on a variety of SDL auxiliary libraries that do not show up in pkg-config so we check for their existence via AC_CHECK_HEADERS. We make the slightly naive assumption that if the header file exists then the correct version of the library is installed. This is most likely the case but is still a potential issue. If the header file is there then it adds the compiler option for that library into SDL_AUX_LIBS , otherwise it will print an error and stop configuration.

At this point you should notice the VALA_PACKAGES variable. This is actually superfluous for this program since all libraries are needed and none are optional. What this demonstrates is a way to dynamically generate the package list needed for valac from the configure script itself. If the library is installed then it's vala package gets added to the VALA_PACKAGES variable which will be used later in our Makefile to pass these packages to the compiler.

Finally, we added some additional Makefiles in AC_CONFIG_FILES that brickval will be using. These new additions mostly involve how we install our graphics data. The additional src/Makefile addition will be explained in the next section.

Makefile.am

The way that vala-gen-project creates the Makefile.am file sets the project up in such a way that the generated executable is created in the top-most directory of the project. For Brickval, we will follow a more traditional approach and have executable generate inside the src subdirectory. Because of this our Makefile.am is simplified from the stock one:

SUBDIRS = src po data

EXTRA_DIST = \
        intltool-extract.in \
        intltool-update.in \
        intltool-merge.in

DISTCLEANFILES = \
        intltool-extract \
        intltool-update \
        intltool-merge \
        po/.intltool-merge-cache

This tells autotools that there are more makefiles in the src, po, and data subdirectories that it will need to execute in order to build the project. It also adds some extra files that get distributed with the final package.

data/Makefile.am

The folder for this Makefile.am doesn't yet exist so lets create it as well as the subdirectories we will need for it later:

mkdir -p data/sprites
mkdir data/backgrounds
cd data

Now create the Makefile.am file with your favorite text editor and place the following into it:

SUBDIRS = sprites backgrounds

Well since we created the subdirectories lets get some images to put into them:

wget http://www.lesharris.com/valagamedev/gfx.tar.gz

These graphics are from the Deadfish theme for LBreakout2 and were created by Johannes Kroll (j-kroll (at) gmx (punkt) de). Untar the file wherever you please and move the bg.png file into the backgrounds subdirectory and the rest into the sprites subdirectory.

Even though the data is there we still need to tell autotools that this data needs to be installed somewhere. We will do that now.

data/backgrounds/Makefile.am

The Makefile.am's for the graphics files are very simple since they simply tell specify which files should go where. Create the Makefile.am and edit it to look like the following:

Backgroundsdir = $(datadir)/brickval/backgrounds

Backgrounds_DATA = \
        bg.png

EXTRA_DIST = \
        $(Backgrounds_DATA)

data/sprites/Makefile.am

We now will do essentially the same operation in the sprites subdirectory. Create and edit the Makefile.am and put this in it:

Spritesdir = $(datadir)/brickval/sprites

Sprites_DATA = \
        bricks.png \
        extras.png \
        life.png \
        paddle.png

EXTRA_DIST = \
        $(Sprites_DATA)

src/Makefile.am

Whew, we are almost done creating these Makefile.am's! There is just one left and it is the most complex since it is the one that actually compiles the vala code. It's listing is as follows:

VALA_CFLAGS = \
        --vapidir ../vapi \
        --pkg config \
        $(VALA_PACKAGES)

AM_CPPFLAGS = \
        -DDATADIR=\"$(datadir)\" \
        -DPACKAGE_DATADIR=\""$(datadir)/brickval"\" \
        -DSPRITE_DIR=\""$(datadir)/brickval/sprites"\" \
        -DBACKGROUND_DIR=\""$(datadir)/brickval/backgrounds"\" \
        -DPACKAGE_LOCALEDIR=\""$(datadir)/locale"\" \
        $(BRICKVAL_CFLAGS) \
        $(SDL_CFLAGS) \
        -include $(CONFIG_HEADER)

BUILT_SOURCES = brickval.vala.stamp

bin_PROGRAMS = brickval

brickval_VALASOURCES = \
        brickval.vala

brickval_SOURCES = \
        $(brickval_VALASOURCES:.vala=.c) \
        $(brickval_VALASOURCES:.vala=.h)

brickval.vala.stamp: $(brickval_VALASOURCES)
        $(VALAC) -C $(VALA_CFLAGS) $^
        touch $@

brickval_LDADD = \
        $(BRICKVAL_LIBS) \
        $(SDL_LIBS)     \
        $(SDL_AUX_LIBS)

The first section of this file defines the compiler flags that we will pass to the Vala compiler, valac. We will discuss vapidir and the config package in a later section, but notice that this is where we put our VALA_PACKAGES variable that we created in the configure.ac file to use. The second section defines several constants that will be defined at compile time for our project. These, too, are closely related to the mysterious config package that will be discussed later. This is also where the compiler flags for gcc, the C compiler, are placed.

Much of the rest of this file is autotools boilerplate and is generated for you by vala-gen-project (I simply moved it to this Makefile.am). However two sections in particular are of interest to you. The first is brickval_VALASOURCES. This is where you specify all the source files that will be used to create the application. Right now we only have brickval.vala in there. Since brickval.vala doesn't actually exist yet, lets change main.vala to brickval.vala:

mv main.vala brickval.vala

There we go, much better. The last section you should be aware of is the brickval_LDADD section. This is where we put the variables that hold the compiler library options, in our case the libraries for Brickval itself and SDL.

Congratulations, the build environment is setup! However, we are not quite done yet. There is still that mysterious vapidir and config package to deal with.

Config.vapi

Traditionally, autotools creates a config.h file that can be used in C and C++ programs to hold various configuration and metadata that is created during the configuration process. This allows the information autotools discovered in the configuration process to be used in the application code itself. This is very useful and can be used for a wide variety of things. However, since this is a C header, and we are coding in Vala, there is a problem. At first blush it appears we can't use this file or any constants defined as compiler options in our program!

Luckily, there is a solution to this problem. To make this information usable by our vala program we will create a special vala file called a .vapi file. These files are generally used as a Vala description of a C library and lets the C library be utilized in a vala program. For this case though, we will simply use it to defined a bunch of constant strings and use an attribute to tell the Vala compiler to scan through our config.h file and use the values it finds to supply the values for these constant strings.

First we need to create the directory for our config.vapi file:

cd ~/dev/brickval
mkdir vapi

And now we need to create the config.vapi file in our newly created directory and fill it with the following information:

[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
namespace Config {
        public const string GETTEXT_PACKAGE;
        public const string SPRITE_DIR;
        public const string BACKGROUND_DIR;
        public const string PACKAGE_DATADIR;
        public const string PACKAGE_LOCALEDIR;
        public const string PACKAGE_NAME;
        public const string PACKAGE_VERSION;
        public const string VERSION;
}

Remember back in our src/Makefile.am that we passed an additional vapi directory and package to the vala compiler. Now you know what those were doing. The vapidir vala compiler option adds an additional directory that valac will search for packages and the --pkg config option tells valac to use the package we just created.

Notice also that not only do we have access to any definition we want to use in config.h, we also can have access to any constants that are passed to gcc directly. Such is the case with the BACKGROUND_DIR and SPRITE_DIR constants. We do not expose all the constants that are possible, just the constants that this program will currently use. If you want to use a particular constant in your vala program, it must be defined also in the config.vapi file.

Conclusion

Well that was a long, hard slog. This is probably the least fun part of a Vala project: setting it up! However, it is quick and takes longer to explain than to actually do once you get the hang of it. The best part about this process is that you really only have to do it once and then just add bits and pieces to it as your project grows.

In the next article we will actually start writing code, and at the end of it, you will have a simple graphics demonstration that uses sprites. I think you'll be impressed at how quick and easy Vala makes this happen!

Projects/Vala/GameDevelopmentSeries/Setup (last edited 2013-11-22 16:48:25 by WilliamJonMcCann)