I'm going to introduce you a very nice alternative to make: the Shake build system
, by setting up a builder for your Vala
First of all, you need to know that Shake is a library
written in Haskell
, and it's meant to be a better replacement for make. Let's start by installing cabal
and then shake:
apt-get install cabal-install
cabal install shake
TL;DR; this is the final Build.hs file:
import Control.Applicative hiding ((*>))
app = "bestValaApp"
sources = words "file1.vala file2.vala file3.vala"
packages = words "gtk+-3.0 glib-2.0 gobject-2.0"
cc = "cc"
valac = "valac"
pkgconfig = "pkg-config"
csources = map (flip replaceExtension ".c") sources
cobjects = map (flip replaceExtension ".o") csources
main = shakeArgs shakeOptions $ do
app *> \out -> do
pkgconfigflags <- pkgConfig $ ["--libs"] ++ packages
sys cc "-fPIC -o" [out] pkgconfigflags cobjects
cobjects **> \out -> do
let cfile = replaceExtension out ".c"
pkgconfigflags <- pkgConfig $ ["--cflags"] ++ packages
sys cc "-ggdb -fPIC -c -o" [out, cfile] pkgconfigflags
csources *>> \_ -> do
let valapkgflags = prependEach "--pkg" packages
sys valac "-C -g" valapkgflags sources
prependEach x = foldr (\y a -> x:y:a) 
pkgConfig args = (words . fst) <$> (systemOutput pkgconfig args)
Just tweak app
to match your needs, chmod +x Build.hs
then run ./Build.hs
function splits a string by spaces to get a list of strings, e.g. ["file1.vala", "file2.vala", "file3.vala"]
variable maps .vala file names to .c file names. Same goes for cobjects. It's the equivalent of $(subst .vala,.c,$(SOURCES))
you'd do with make.
There it comes the main
. The shakeArgs shakeOptions
part will run shake with default options. Shake provides handy command line options similar to make, run ./Build.hs
-h for help.
The want [app]
tells shake we want to build the app
object by default. That's equivalent to the usual first make rule all: $(APP).
Then we define how to build the executable app with app *> \out -> do
. We tell shake the dependencies with need cobjects
. This is similar to $(APP): $(COBJECTS)
in make but not equivalent. In shake dependencies are not static
like in many other build systems. This is one of the most interesting shake features.
The rest is quite straightforward to understand.
Then we define how to build each .o object with cobjects **> \out -> do
. Here the out
variable contains the actual .o required to be built, equivalent to $@
in make. Then we need [cfile]
, in order to simulate %.o: %.c
like in make.
One more feature shake has out-of-the-box that make doesn't is how to generate more files from a single command
. With make you'd use a .stamp file due to valac generating several .c files out of .vala files. Then use the .stamp as dependency.
With shake instead we consistently define how to build .c files with csources *>> \_ -> do
, then shake will do the rest.
The shake project is very active. You can read this tutorial
to learn Haskell basics, and the reference docs
of shake. The author homepage
has links to cool presentations of the shake build system.