\subsection{About autotools}

\begin{frame}[fragile]
\frametitle{Autotools, aka GNU Build System}
\begin{itemize}
\item make software (builds) portable
\item well-known format for distribution
\item ease integration in distributions and build-systems
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{first attemp, keep it simple}
\begin{verbatim}
% cd
% mkdir hello
% cd hello
\end{verbatim}

'hello.c':
\begin{verbatim}
#include <stdio.h>

int main(int argc, char **argv)
{
	printf("Hello World\n");
	return 0;
}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{track changes with git}
\begin{verbatim}
% git init .
% git add hello.c
% git commit -sa
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Why not just 'make'? \#1}
\begin{verbatim}
hello:

install:
	install -d /usr/bin
	install hello /usr/bin/hello
\end{verbatim}

\begin{verbatim}
% git add Makefile
% git commit -sa
\end{verbatim}
what if the user doesn't want to install into /usr/bin?

edit the Makefile? introduce variables, .. :-/
\end{frame}

\begin{frame}[fragile]
\frametitle{Why not just 'make'? \#2}
use a template 'Makefile.in'
\begin{verbatim}
hello:

install:
	install -d @exec_prefix@
	install hello @exec_prefix@/hello
\end{verbatim}
and run './configure --exec-prefix=/opt/bin'
\end{frame}

\begin{frame}[fragile]
\frametitle{write configure by you own?}
\dots or use autoconf, it generates one for you, based on a configure.ac file.

'autoscan' can be used to generate an initial version:
\begin{verbatim}
% autoscan
% mv configure.scan configure.ac
% rm autoscan.log
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{configure.ac}
replace FULL-PACKAGE-NAME, VERSION and BUG-REPORT-ADDRESS with sane values

remove temporarily unneeded calls
\begin{verbatim}
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [manut@linutronix.de])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
\end{verbatim}
update git
\begin{verbatim}
git rm Makefile
git add Makefile.in
git add configure.ac
git commit -sa
\end{verbatim}
then run the following commands to generate the configure script
\begin{verbatim}
% autoconf
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{generate the Makefile}
\begin{verbatim}
% ./configure --exec-prefix=/opt/bin
\end{verbatim}
the generated Makefile:
\begin{verbatim}
hello:

install:
	install -d /opt/bin/hello
	install hello /opt/bin/hello
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{config.h \#1}
generate a 'config.h' that should be included on top of the other includes in
all files.

Insert the following m4 function call in 'configure.ac'
\begin{verbatim}
AC_CONFIG_HEADERS([config.h])
\end{verbatim}

and run
\begin{verbatim}
% autoreconf -sif
\end{verbatim}
to regenerate the 'configure' script and create a 'config.h.in' template.

Then run
\begin{verbatim}
% ./configure --exec-prefix=/opt/bin
\end{verbatim}
again to generate the 'Makefile' and 'config.h'
\end{frame}

\begin{frame}[fragile]
\frametitle{config.h \#2}
include 'config.h' in main.c and use the PACKAGE\_STRING define:
\begin{verbatim}
#include "config.h"
#include <stdio.h>

int main(int argc, char **argv)
{
	printf(PACKAGE_STRING "\n\n")
	printf("Hello World\n");
	return 0;
}
\end{verbatim}
\begin{verbatim}
% make
cc     hello.c   -o hello
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{reasons for automake}
rebuild the program:
\begin{verbatim}
% make
make: 'hello' is up to date.
% make clean
make: *** No rule to make target 'clean'.  Stop.
% git status
    Makefile
    autom4te.cache
    ...
\end{verbatim}
write 'clean', 'distclean', 'maintainerclean' targets?
\end{frame}

\begin{frame}[fragile]
\frametitle{automake}
describe input and output files in 'Makefile.am':
\begin{verbatim}
bin_PROGRAMS = hello
hello_SOURCES = hello.c
\end{verbatim}
add invocation of 'automake' to 'configure.ac':
\begin{verbatim}
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [manut@linutronix.de])
AM_INIT_AUTOMAKE
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Excurs: GNU project layout}
\begin{verbatim}
autoreconf -sif
configure.ac:6: installing './install-sh'
configure.ac:6: installing './missing'
Makefile.am: installing './INSTALL'
Makefile.am: error: required file './NEWS' not found
Makefile.am: error: required file './README' not found
Makefile.am: error: required file './AUTHORS' not found
Makefile.am: error: required file './ChangeLog' not found
Makefile.am: installing './COPYING' using GNU General Public License v3 file
Makefile.am:     Consider adding the COPYING file to the version control system
Makefile.am:     for your code, to avoid questions about which license your project uses
Makefile.am: installing './depcomp'
/usr/share/automake-1.15/am/depend2.am: error: am__fastdepCC does not appear in AM_CONDITIONAL
/usr/share/automake-1.15/am/depend2.am:   The usual way to define 'am__fastdepCC' is to add 'AC_PROG_CC'
/usr/share/automake-1.15/am/depend2.am:   to 'configure.ac' and run 'aclocal' and 'autoconf' again
/usr/share/automake-1.15/am/depend2.am: error: AMDEP does not appear in AM_CONDITIONAL
/usr/share/automake-1.15/am/depend2.am:   The usual way to define 'AMDEP' is to add one of the compiler tests
/usr/share/automake-1.15/am/depend2.am:     AC_PROG_CC, AC_PROG_CXX, AC_PROG_OBJC, AC_PROG_OBJCXX,
/usr/share/automake-1.15/am/depend2.am:     AM_PROG_AS, AM_PROG_GCJ, AM_PROG_UPC
/usr/share/automake-1.15/am/depend2.am:   to 'configure.ac' and run 'aclocal' and 'autoconf' again
Makefile.am: error: C source seen but 'CC' is undefined
Makefile.am:   The usual way to define 'CC' is to add 'AC_PROG_CC'
Makefile.am:   to 'configure.ac' and run 'autoconf' again.
autoreconf: automake failed with exit status: 1
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Excurs: GNU project layout}
'automake' generated some templates:
\begin{itemize}
\item COPYING
\item INSTALL
\end{itemize}
customize them if needed.

Some other files are mandatory, create them:
\begin{verbatim}
% touch NEWS README AUTHORS ChangeLog
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{remember 2nd part of the errors}
\begin{verbatim}
% autoreconf -sif
/usr/share/automake-1.15/am/depend2.am: error: am__fastdepCC does not appear in AM_CONDITIONAL
/usr/share/automake-1.15/am/depend2.am:   The usual way to define 'am__fastdepCC' is to add 'AC_PROG_CC'
/usr/share/automake-1.15/am/depend2.am:   to 'configure.ac' and run 'aclocal' and 'autoconf' again
/usr/share/automake-1.15/am/depend2.am: error: AMDEP does not appear in AM_CONDITIONAL
/usr/share/automake-1.15/am/depend2.am:   The usual way to define 'AMDEP' is to add one of the compiler tests
/usr/share/automake-1.15/am/depend2.am:     AC_PROG_CC, AC_PROG_CXX, AC_PROG_OBJC, AC_PROG_OBJCXX,
/usr/share/automake-1.15/am/depend2.am:     AM_PROG_AS, AM_PROG_GCJ, AM_PROG_UPC
/usr/share/automake-1.15/am/depend2.am:   to 'configure.ac' and run 'aclocal' and 'autoconf' again
Makefile.am: error: C source seen but 'CC' is undefined
Makefile.am:   The usual way to define 'CC' is to add 'AC_PROG_CC'
Makefile.am:   to 'configure.ac' and run 'autoconf' again.
autoreconf: automake failed with exit status: 1
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{which compiler should be used?}
to use autoconf to look for a C compiler add a function call to configure.ac:
\begin{verbatim}
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [manut@linutronix.de])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
\end{verbatim}
rerun autoconf
\begin{verbatim}
% autoreconf -sif
configure.ac:11: installing './compile'
\end{verbatim}


\begin{frame}[fragile]
\frametitle{generate a Makefile}
now a 'Makefile.in' that takes care on a lot of settings from './configure'
was generated!
\begin{verbatim}
% ./configure
% make
make  all-am
make[1]: Entering directory '/home/local/hello'
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc  -g -O2   -o hello hello.o
make[1]: Leaving directory '/home/local/hello'
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{update files in git}
\begin{verbatim}
% git rm --cached Makefile.in
% git add NEWS README AUTHORS ChangeLog INSTALL COPYING
% git add configure.ac Makefile.am
% git commit -s
\end{verbatim}
create a .gitignore file for autogenerated files:
\begin{verbatim}
% git status -s | sed "s#?? ##" > .gitignore
% git add .gitignore
% git commit -s
% git status
On branch master
nothing to commit, working directory clean
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{extend configure.ac}
with from autoscan suggested sanity checks for 'install' and the existence of
a source file:
\begin{verbatim}
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [manut@linutronix.de])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])

AC_PROG_CC
AC_PROG_INSTALL

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
\end{verbatim}
add the changes to git and rerun 'make'

All needed steps are executed automatically!
\end{frame}

\begin{frame}[fragile]
\frametitle{useful make targets}
\begin{block}{clean}
\begin{description}
\item[clean] deletes build outputs
\item[distclean] removes files generated by './configure'
\item[maintainer-clean] also deletes generated source code
\end{description}
\end{block}
\begin{block}{install}
\item[install] takes care on DESTDIR environment variable
\end{block}
\begin{block}{dist}
\item[dist] generates a hello-1.0.tar.gz
\item[distcheck] same as dist, but checks if the sw can be build with files
	included in the tarball.
\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{for your customers / distributions}
\begin{verbatim}
% tar xzf hello-1.0.tar.gz
% cd hello-1.0
% ./configure
% make
% sudo make install
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{for developers}
the typical workflow is
\begin{verbatim}
% git clone /home/devel/hello
% cd hello
% ./autogen.sh
% ./configure
% make
% sudo make install
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{autogen.sh}
\dots so let's create the missing 'autogen.sh' script:
\begin{verbatim}
#!/bin/sh
autoreconf -sif
\end{verbatim}
\begin{verbatim}
% chmod +x autogen.sh
% git add autogen.sh
% git commit -s
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{recap!}
\begin{verbatim}
% git clean -dxf
% ls
AUTHORS autogen.sh ChangeLog   configure.ac COPYING
hello.c INSTALL    Makefile.am NEWS         README
\end{verbatim}
'AUTHORS, ChangeLog, COPYING, INSTALL, NEWS' and 'README' are
mandatory text files, that describe the project.

'autogen.sh' is an (optional) one-liner script

'Makefile.am' are two lines and even simpler than the inital Makefile

'configure.ac' a template can be generated with 'autoscan' at least
'AM\_INIT\_AUTOMAKE' needs to be added manually.
\end{frame}

\begin{frame}[fragile]
\frametitle{let's extend our software}
\begin{enumerate}
\item add gui.c and gui.h to display text with ncurses
\item use pkg-config to specify compiler and linker options
\item make the gui an optional component
\end{enumerate}
\end{frame}

\begin{frame}[fragile]
\frametitle{gui.h}
\begin{verbatim}
int gui_init (void);
void gui_free (void);
int gui_display (char *msg);
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{gui.c}
\begin{verbatim}
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <curses.h>
#include <errno.h>
#include <string.h>
#include "gui.h"

static WINDOW *mainwin;

int gui_init (void) {
	mainwin = initscr ();
	if (!mainwin) return -ENOMEM;
	return 0;
}

void gui_free (void) {
	delwin (mainwin); endwin (); refresh ();
}

int gui_display (char *msg) {
	mvaddstr (strlen (msg), 33, msg); refresh ();
}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{hello.c}
\begin{verbatim}
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <unistd.h>
#include "gui.h"

int main (int argc, char **argv)
{
	printf (PACKAGE_STRING "\n\n");
	if (gui_init ()) {
		perror("init gui failed:");
		return -1;
	}
	gui_display ("Hello GUI!");
	sleep (10);
	gui_free ();
	return ret;
}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{How to find compiler and linker options?}
\begin{verbatim}
% cat /usr/lib/x86_64-linux-gnu/pkgconfig/ncurses.pc
prefix=/usr
exec_prefix=${prefix}
libdir=/usr/lib/x86_64-linux-gnu
includedir=${prefix}/include
abi_version=5
major_version=6
version=6.0.20160319

Name: ncurses
Description: ncurses 6.0 library
Version: ${version}
URL: http://invisible-island.net/ncurses
Requires.private:
Libs:  -L${libdir} -lncurses -ltinfo
Libs.private:
Cflags:  -D_GNU_SOURCE
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{pkg-config}
\dots more user friendly
\begin{verbatim}
% pkg-config --list-all | grep curses
menu                             menu - ncurses 6.0 add-on library
ncurses                          ncurses - ncurses 6.0 library
...
\end{verbatim}
we use 'ncurses' so let's retrieve the compiler and linker options:
\begin{verbatim}
% pkg-config --cflags ncurses
-D_GNU_SOURCE
% pkg-config --libs ncurses
-lncurses -ltinfo
\end{verbatim}

\begin{frame}[fragile]
\frametitle{simply add the output to Makefile.am?}
NO!! (but it will work on \_YOUR\_ machine)

what needs to be done on your customers machine?
\begin{itemize}
\item check if the ncurses.pc file is availabe
\item print an error if it's not installed
\item maybe the headers and libs are installed in another path
\item run pkg-config ncurses --libs/cflags and pass the output to Makefile.am
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{autoconf and pkg-config}
add a function call to configure.ac:
\begin{verbatim}
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [manut@linutronix.de])
AM_INIT_AUTOMAKE
AC_USE_SYSTEM_EXTENSIONS
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])

AC_PROG_CC
AC_PROG_INSTALL

PKG_CHECK_MODULES([NCURSES], [ncurses])

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
\end{verbatim}
the first argument of PKG\_CHECK\_MODULES specifies a variable name, the
second one the name of the package as displayed in pkg-config --list-all
\end{frame}

\begin{frame}[fragile]
\frametitle{if ncurses is not installed}
./configure produces a human readable error message
\begin{verbatim}
% ./configure
checking dependency style of gcc... (cached) gcc3
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for NCURSES... no
configure: error: Package requirements (ncurses) were not met:

No package 'ncurses' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables NCURSES_CFLAGS
and NCURSES_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
Makefile:318: recipe for target 'config.status' failed
make: *** [config.status] Error 1
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{final steps}
add compile and linker options to Makefile.am:
\begin{verbatim}
bin_PROGRAMS = hello
hello_SOURCES = hello.c gui.c gui.h
hello_CFLAGS = @NCURSES_CFLAGS@
hello_LDFLAGS = @NCURSES_LIBS@
\end{verbatim}
compile and test application:
\begin{verbatim}
% make
...
% ./hello
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{add changes to version control}
\begin{verbatim}
% git status
...
	gui.o
	hello-gui.o
	hello-hello.o
...
% echo '*.o' >> .gitignore
% git add gui.c gui.h Makefile.am configure.ac hello.c .gitignore
% git commit -s
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{gui as optional feature}
implement a './configure' switch '--with-gui'

only if this parameter is given, the existence of ncurses.pc is tested
and the gui components are build.
\end{frame}

\begin{frame}[fragile]
\frametitle{implement configure switch}
add this in 'configure.ac':
\begin{verbatim}
AC_ARG_WITH([gui], AS_HELP_STRING([--with-ncurses-gui], [Build with GUI]))
if test "x$with_gui" = "xyes"; then
  PKG_CHECK_MODULES([NCURSES], [ncurses],
                    [AC_DEFINE([HAVE_GUI],[1],["ncurses available"])])
fi
AM_CONDITIONAL([HAVE_GUI], [test x$with_gui = xyes])
\end{verbatim}
\begin{description}
\item[AC\_ARG\_WITH] adds the parameter to the configure script
\item[PKG\_CHECK\_MODULES] is extended to define HAVE\_GUI in config.h
\item[AM\_CONDITIONAL] exports a value as conditional to automake
\end{description}
\end{frame}

\begin{frame}
\frametitle{only build GUI if specified}
'Makefile.am':
\begin{verbatim}
bin_PROGRAMS = hello
hello_SOURCES = hello.c
hello_CFLAGS = @NCURSES_CFLAGS@
hello_LDFLAGS = @NCURSES_LIBS@
if HAVE_GUI
hello_SOURCES += gui.c gui.h
endif
\end{verbatim}
\end{frame}

\begin{frame}
\frametitle{only call gui if compiled in}
'hello.c':
\begin{verbatim}
...
#ifdef HAVE_GUI
#include "gui.h"
#endif
...
#ifdef HAVE_GUI
	ret = gui_init ();
	if (ret) {
		perror("init gui failed:");
		return ret;
	}

	gui_display ("Hello GUI!");
	sleep (10);

	gui_free ();
#endif
...
\end{verbatim}
\end{frame}

\begin{frame}
\frametitle{build with and without gui}
\begin{verbatim}
% ./configure --with-gui
...
% make
...
gcc -DHAVE_CONFIG_H -I.    -D_GNU_SOURCE -g -O2 -MT hello-hello.o...
mv -f .deps/hello-hello.Tpo .deps/hello-hello.Po
gcc -DHAVE_CONFIG_H -I.    -D_GNU_SOURCE -g -O2 -MT hello-gui.o -...
mv -f .deps/hello-gui.Tpo .deps/hello-gui.Po
gcc -D_GNU_SOURCE -g -O2 -lncurses -ltinfo  -o hello hello-hello....
...
% ./configure
...
% make
...
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT hello-hello.o -MD -MP -MF ...
mv -f .deps/hello-hello.Tpo .deps/hello-hello.Po
gcc  -g -O2   -o hello hello-hello.o
...
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{add changes to version control}
\begin{verbatim}
% git add Makefile.am configure.ac hello.c
% git commit -s
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{increase program version}
time to release a new version of our sw component, edit 'configure.ac':
\begin{verbatim}
AC_INIT([hello], [1.1], [manut@linutronix.de])
\end{verbatim}
add the version bump to vcs and release a tarball:
\begin{verbatim}
% git add configure.ac
% git commit -s
% make distcheck
===========================================
hello-1.1 archives ready for distribution:
hello-1.1.tar.gz
===========================================
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{libraries and libtoolize}
add a versioned library called 'libfib' to the project
\begin{verbatim}
% mkdir fib
% echo "SUBDIRS = fib" >> Makefile.am
\end{verbatim}
create an interface 'fib/fib.h':
\begin{verbatim}
unsigned int fibonacci (unsigned int fib);
\end{verbatim}
and 'fib/fib.c':
\begin{verbatim}
#include "fib.h"

unsigned int fibonacci (unsigned int fib) {
  if (fib == 0) return 0;
  else if (fib == 1) return 1;
  else return fibonacci (fib-1) + fibonacci (fib-2);
}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{Makefile.am for libfib}
'fib/Makefile.am':
\begin{verbatim}
lib_LTLIBRARIES = libfib.la
# 1) If the library source code has changed at all since the last update, then
#    increment revision ("c:r:a" becomes "c:r+1:a").
# 2) If any interfaces have been added, removed, or changed since the last
#    update, increment current, and set revision to 0.
# 3) If any interfaces have been added since the last public release,
#    then increment age.
# 4) If any interfaces have been removed or changed since the last public
#    release, then set age to 0.
libfib_la_LDFLAGS = -release @PACKAGE_VERSION@ -version-info 0:0:0
libfib_la_SOURCES = fib.c
include_HEADERS = fib.h
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{libtoolize and autoconf}
add libtoolize and new Makefile to 'configure.ac':
\begin{verbatim}
...
AC_USE_SYSTEM_EXTENSIONS
LT_INIT
AC_CONFIG_SRCDIR([hello.c])
...
AC_CONFIG_FILES([Makefile
                 fib/Makefile])
AC_OUTPUT
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{that's it?}
\dots no :( but autoreconf -sif is our friend!
\begin{verbatim}
% make
 cd . && /bin/bash /home/local/hello/missing automake-1.15 --gnu
configure.ac:5: error: required file './config.guess' not found
configure.ac:5:   'automake --add-missing' can install 'config.guess'
configure.ac:5: error: required file './config.sub' not found
configure.ac:5:   'automake --add-missing' can install 'config.sub'
configure.ac:5: error: required file './ltmain.sh' not found
Makefile:298: recipe for target 'Makefile.in' failed
make: *** [Makefile.in] Error 1
% autoreconf -sif
libtoolize: putting auxiliary files in '.'.
libtoolize: linking file './ltmain.sh'
libtoolize: Consider adding 'AC_CONFIG_MACRO_DIRS([m4])' to configure.ac,
libtoolize: and rerunning libtoolize and aclocal.
libtoolize: Consider adding '-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
configure.ac:4: installing './compile'
configure.ac:5: installing './config.guess'
configure.ac:5: installing './config.sub'
configure.ac:3: installing './missing'
Makefile.am: installing './depcomp'
% make
...
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{what about the m4 macros warnings?}
libtool wants to install its m4 scripts into the project.

This is useful if you pass the project to other people that might have other
versions of libtool installed on their machine.

prepare a directory for these scripts in 'autogen.sh':
\begin{verbatim}
#!/bin/sh
mkdir -p m4
autoreconf -sif
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{local libtoolize}
add a macro into 'configure.ac' that specifies the destination of the local
libtoolize scripts
\begin{verbatim}
...
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([hello.c])
...
\end{verbatim}
include this directory in 'Makefile.am' and regenerate everything:
\begin{verbatim}
% echo 'ACLOCAL_AMFLAGS = -I m4' >> Makefile.am
% ./autogen.sh
% make
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{do a test installation}
\begin{verbatim}
% make DESTDIR=`pwd`/tmp install
...
% find tmp
tmp/
tmp/usr
tmp/usr/local
tmp/usr/local/lib
tmp/usr/local/lib/libfib-1.1.so.0
tmp/usr/local/lib/libfib-1.1.so.0.0.0
tmp/usr/local/lib/libfib.la
tmp/usr/local/lib/libfib.so
tmp/usr/local/lib/libfib.a
tmp/usr/local/include
tmp/usr/local/include/fib.h
tmp/usr/local/bin
tmp/usr/local/bin/hello
\end{verbatim}
looks sane, but the pkg-config .pc file is missing
\end{frame}

\begin{frame}[fragile]
\frametitle{add a libfib pkg-config .pc file}
Remember, the .pc file contains the paths where the library and headers are
installed.

These paths are defined by './configure' parameters. So we have to generate
a template 'fib/fib.pc.in':
\begin{verbatim}
prefix=@prefix@
exec_prefix=@exec_prefix@
includedir=@includedir@

Name: libfib
Description: fibonacci library
Version: @VERSION@
Libs: -lfib
Cflags: -I${includedir}
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{generate fib.pc file from .in file}
add fib.pc to AC\_CONFIG\_FILES in 'configure.ac':
\begin{verbatim}
...
AC_CONFIG_FILES([Makefile
                 fib/Makefile
                 fib/fib.pc])
...
\end{verbatim}
config in 'fib/Makefile.am' to install the fib.pc file:
\begin{verbatim}
% echo 'pkgconfigdir = $(datadir)/pkgconfig' >> fib/Makefile.am
% echo 'pkgconfig_DATA = fib.pc' >> fib/Makefile.am
% make DESTDIR=`pwd`/tmp install
% find tmp | grep fib.pc
% tmp/usr/local/share/pkgconfig/fib.pc
% export PKG_CONFIG_PATH=tmp/usr/local/share/pkgconfig
% pkg-config --list-all | grep fib
fib                              libfib - fibonacci library
% pkg-config fib --cflags --libs
-I/usr/local/include -lfib
% pkg-config fib --modversion
1.1
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{make a new release \#1}
'configure.ac':
\begin{verbatim}
...
AC_INIT([hello], [2.0], [manut@linutronix.de])
...
\end{verbatim}
update '.gitignore' add the following lines:
\begin{verbatim}
config.guess
config.sub
.libs
*.lo
*.pc
*.la
*.tar.gz
libtool
ltmain.sh
m4/
\end{verbatim}
add changes to git:
\begin{verbatim}
% git add Makefile.am autogen.sh configure.ac .gitignore
% git add fib/Makefile.am fib/fib.c fib/fib.h fib/fib.pc.in
% git commit -s
\end{verbatim}
\end{frame}

\begin{frame}[fragile]
\frametitle{make a new release \#2}
\begin{verbatim}
% git clean -dxf
% ./autogen.sh
...
% ./configure --with-gui
...
% make distcheck
...
===========================================
hello-2.0 archives ready for distribution:
hello-2.0.tar.gz
===========================================
\end{verbatim}
\end{frame}

\begin{frame}
\frametitle{Conclusion}
\begin{itemize}
\item autotools looks complicated, because the generated tarballs contain
  auto generated files and a copy of the libtool m4 scripts, etc
\item only edit 'configure.ac' and 'Makefile.am' and your sources!
\item autotools projects are very portable
\item autotools defines a well-known standard howto build software, this
  makes packaging of software a lot easier.
\end{itemize}
\end{frame}
