Chapter 2. Tutorial

Table of Contents

Hello, world

Hello, world

By far the simplest way to generate makefiles using Bakefile is to use so-called presets which are prepared skeletons of bakefiles that get you started quickly. Let's see how it works on an example of the famous Hello, world program written in C and implemented in the hello.c file:

#include <stdio.h>

int main()
{
  printf("Hello, world!\n");
  return 0;
}

The bakefile needed to compile it,hello.bkl, looks like this:

<?xml version="1.0"?>
<makefile>

  <include file="presets/simple.bkl"/>
  
  <exe id="hello" template="simple">
    <sources>hello.c</sources>
  </exe>

</makefile>

Presets are included using the include directive. The structure of the file name is always the same: presets/NAME-OF-PRESET.bkl. In general, you can combine several presets, but in practice you must be careful when doing so. It's always a good idea to read the code for the preset before using it. The "simple" preset we include here defines a DEBUG option and a template called simple. Generated makefiles will allow the user to build all targets that are based on this template as either debug or release build.

Let's generate some makefiles now. The bakefile command is used to do it. For example:

$ bakefile -f msvc hello.bkl

That's all. This will creates VC++ makefile makefile.vc. Of course, you can change the name of output file if you don't like the default:

$ bakefile -f msvc -o makefile hello.bkl

Bakefile will also generate the Makefile.in files used by Autoconf:

$ bakefile -f autoconf hello.bkl

These are templates for makefiles. Autoconf also requires a configure.ac script (previously, configure.in), but Bakefile will not generate this for you. This script checks for platform features necessary to build the program; see the autoconf manual for details.

When producing autoconf format output, Bakefile will also generate a file called autoconf_inc.m4 which defines macros needed by the generated Makefile.in files. To use this, call the AC_BAKEFILE macro within your configure.ac script.

A minimal configure.ac script for our example program would look like this:

AC_PREREQ(2.53)
AC_INIT([hello], [1.0], [author@example.com])
dnl pass some unique file file to AC_CONFIG_SRCDIR
AC_CONFIG_SRCDIR([autoconf_inc.m4])
AC_CANONICAL_HOST
DEBUG=0
AC_BAKEFILE([m4_include(autoconf_inc.m4)])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Note the part that sets the DEBUG variable. Any options declared in your bakefile must be set to some default value before calling AC_BAKEFILE. The simple.bkl preset defines the DEBUG option, so we have to give it a default value here.

While the above code will work, there's a better way to handle the debug option:

AC_PREREQ(2.53)
AC_INIT([hello], [1.0], [author@example.com])
dnl pass some unique file file to AC_CONFIG_SRCDIR
AC_CONFIG_SRCDIR([autoconf_inc.m4])
AC_CANONICAL_HOST

AC_ARG_ENABLE(debug,
              [  --enable-debug          Enable debugging information],
              USE_DEBUG="$enableval", USE_DEBUG="no")

if test $USE_DEBUG = yes ; then 
  DEBUG=1
  dnl Bakefile doesn't touch {C,CPP,CXX,LD}FLAGS in autoconf format, we
  dnl have to do it ourselves. This will work with many compilers
  dnl (but not all, proper configure script would check if the compiler
  dnl supports it):
  CFLAGS="$CFLAGS -g"
else
  DEBUG=0
fi

AC_BAKEFILE([m4_include(autoconf_inc.m4)])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

You are ready to generate Autoconf's configure script now:

$ bakefilize --copy && aclocal && autoconf