2009-09-03

Build a project with Vala

This post is about using Vala in a project but in the end provide the C code for the releases. I think that this is very essential and that releasing source code to be build from Vala is wrong. Vala will always rewrite the code to GObjects in C, but has already proven that compiling the same code from two different versions of Vala will fail. So when you are doing releases with Vala you will break your releases sooner or later. Another good point is when the Vala code is compiled on top of patched vapi files, doing only C compilation with the releases will drop the requirement to apply them.

I'll take as example the Autotools, if you are using a different tool-chain you can surely adapt it. The idea is simple, the Vala sources are only compiled in maintainer mode. When you compile the application from the development branch you will usually have a script called autogen.sh to build the configure script that will automatically be executed with the parameter --enable-maintainer-mode. When providing the distribution tarball that is created with make distcheck, the configure script will not be run with that parameter (except if specified by hand) and the source files to build from will be filled in with the C filenames.

The example below is very generic and can be copy/pasted but should be adapted.

Autoconf script

1. The initialization of Automake and the maintainer mode in the autoconf script. The Automake version is checked for 1.11 which is the first version that comes with Vala support. The extra dist-bzip2 argument is there to provide an extra bzipped distribution tarball as you guessed it.
AM_INIT_AUTOMAKE([1.11 dist-bzip2])
AM_MAINTAINER_MODE()
2. The check for Vala only on maintainer mode. The AM_PROG_VALAC defines the variable VALAC that can be reused inside the Makefile.am files and accepts an optional version check.
if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
AM_PROG_VALAC([0.7.4])
if test "x$VALAC" = "x" ; then
AC_MSG_ERROR([Cannot find the "valac" compiler in your PATH])
fi
fi
3. It is possible to sum up the build configuration at the end of the autoconf script.
echo
echo "Build Configuration:"
echo
echo "* Maintainer Mode: $USE_MAINTAINER_MODE"
if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
echo
echo " * Vala: $VALAC"
echo
fi

Automake script

1. The declaration of the Vala sources and their respective compiled C sources.
product_VALASOURCES = \
obj1.vala \
obj2.vala \
main.vala

product_VALABUILTSOURCES = $(product_VALASOURCES:.vala=.c) product.h
2. Use the special BUILT_SOURCES variable to build given targets before running a dist with e.g. make distcheck. This usually done in maintainer mode, as in this case to be sure the releases won't have anything to do with Vala.
if MAINTAINER_MODE
PACKAGES = --pkg=gtk+-2.0
BUILT_SOURCES = vala.stamp
vala.stamp: $(product_VALASOURCES)
$(VALAC) --vapidir=$(srcdir) $(PACKAGES) $^ -C -H product.h
touch $@
endif
3. The final sources for the product are filled in with the generated Vala sources. The Vala sources are not passed to any SOURCES which is why they are passed to the special EXTRA_DIST variable.
product_SOURCES = \
random-source.c \
random-header.h \
$(product_VALABUILTSOURCES)

EXTRA_DIST = $(product_VALASOURCES)
if MAINTAINER_MODE
CLEANFILES = \
$(BUILT_SOURCES) \
$(product_VALABUILTSOURCES)
endif

That's it

There are many existent Vala projects nowadays from where you can pick up new ideas, and this post is just an example amongst many others. The full example is available in the xfce4-vala bindings.

Update: I corrected some mistakes seen in green in the script portions. If VALAC is unset the configure script must quit otherwise the resulting Makefiles will have empty commands instead of /usr/bin/valac. Also the generated header file must be passed to product_VALABUILTSOURCES otherwise it would have been left out from distributions as it wans't passed to any product_SOURCES nor EXTRA_DIST variables.