If you have a project that uses Vala and autotools, you are probably using automake 1.11′s native support for the language.
Overall, automake’s support is great. But there are a few oddities that I’ve worked around and thought I’d share here.
Declaring a preferred valac version
Let’s say your project expects valac-0.14. But sometimes people have more than one valac installed, and valac-0.14 may not be their default valac compiler. The AM_PROG_VALAC
macro only looks for ‘valac’ in PATH
, so you’ll end up with whatever default compiler the user has.
Instead, create an acinclude.m4 file in your project directory. Copy the AM_PROG_VALAC
macro from /usr/share/aclocal-1.11/vala.m4 into it. Then:
- Change the name to something like
MY_PROG_VALAC
- Change the
AC_PATH_PROG
line to something like:AC_PATH_PROGS([VALAC], [valac-0.14 valac], [])
- Change the
AM_PROG_VALAC
call in configure.ac to beMY_PROG_VALAC
instead
Now configure will first look for the ‘valac-0.14′ executable and then fallback to plain old ‘valac’.
Stop shipping C code
For a long time, I shipped the valac-generated C code with my release tarballs because I did not want distributors to have to deal with valac churn. But nowadays, especially with valac’s six month release cycle, things are calmer.
Not shipping the C code makes tarballs smaller (over 20% in my case), makes it easier for distros to grab upstream patches (they don’t have to create a C patch from your Vala patch), lets you use Vala conditionals (more about that below), and means you’re not shipping something different than you yourself are using.
This only requires a simple change. In each source directory that contains Vala code, add the following bits to its Makefile.am (for the purposes of this example, your Makefile.am is creating the program foo):
- Separate out all your .vala code files into a separate variable called
foo_VALASOURCES
. If you want, you can then use this variable in yourfoo_SOURCES
variable, so you don’t have to specify them twice. - Add the following dist-hook:
dist-hook: cd $(distdir) && \ rm $(foo_VALASOURCES:.vala=.c) foo_vala.stamp
This will delete the generated C code and stamp file when creating a dist tarball.
Use Vala conditionals
One problem with shipping the generated C code is that you can’t use #ifdefs
in your code. This is because Vala does not have a version of #ifdef
that will “fall through” to the C code. Whether a conditional block of code gets used or not is always decided at valac compilation time.
And since your tarball consumers were compiling the C code, you couldn’t use Vala conditionals. To have an optional project dependency, you had to write little C wrapper functions that did use real C #ifdefs
and then call them from Vala. Which is a pain.
But now that you’re shipping straight Vala code, all compilers of your program can now have Vala conditionals decided at compilation time.
Let’s say you have an optional dependency on libunity:
- In your configure.ac, find the block of code that deals with having successfully detected libunity and add the following line:
AC_SUBST(UNITY_VALAFLAGS, ["--pkg unity -D HAVE_UNITY"])
- In your Makefile.am files, add
$(UNITY_VALAFLAGS)
toAM_VALAFLAGS
- In your Makefile.am files, add a new dependency to each of your stamp files:
foo_vala.stamp: $(top_srcdir)/config.h
- In your Vala code itself, you can now surround your libunity-using code blocks with
#ifs
:#if HAVE_UNITY ... #endif
The first step declares the HAVE_UNITY
symbol if we’re using libunity. If we’re not, that line won’t ever be reached and UNITY_VALAFLAGS
will be empty. The only other interesting bit is step three, which ensures that when ./configure
is re-run, valac will also be re-run to pick up any new symbol definitions.