\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 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 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 Makefile.am: Consider adding the COPYING file to the version contro Makefile.am: for your code, to avoid questions about which license Makefile.am: installing './depcomp' /usr/share/automake-1.15/am/depend2.am: error: am__fastdepCC does not a ... /usr/share/automake-1.15/am/depend2.am: AM_PROG_AS, AM_PROG_GCJ, AM /usr/share/automake-1.15/am/depend2.am: to 'configure.ac' and run 'ac 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 n /usr/share/automake-1.15/am/depend2.am: The usual way to define ' /usr/share/automake-1.15/am/depend2.am: to 'configure.ac' and run /usr/share/automake-1.15/am/depend2.am: error: AMDEP does not appea /usr/share/automake-1.15/am/depend2.am: The usual way to define ' /usr/share/automake-1.15/am/depend2.am: AC_PROG_CC, AC_PROG_CXX /usr/share/automake-1.15/am/depend2.am: AM_PROG_AS, AM_PROG_GCJ /usr/share/automake-1.15/am/depend2.am: to 'configure.ac' and run 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} \end{frame} \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 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} \begin{description} \item[install] takes care on DESTDIR environment variable \end{description} \end{block} \begin{block}{dist} \begin{description} \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{description} \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} \begin{description} \item[AUTHORS, ChangeLog, COPYING, INSTALL, NEWS, README] are mandatory text files, that describe the project \item[autogen.sh] is an (optional) one-liner script \item[Makefile.am] are two lines and even simpler than the inital Makefile \item[configure.ac] a template can be generated with 'autoscan' at least AM\_INIT\_AUTOMAKE needs to be added manually. \end{description} \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 #include #include #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 #include #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} \end{frame} \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 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}[fragile] \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}[fragile] \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}[fragile] \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?} \begin{itemize} \item libtool wants to install its m4 scripts into the project. \item This is useful if you pass the project to other people that might have other versions of libtool installed on their machine. \item prepare a directory for these scripts in 'autogen.sh': \end{itemize} \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} \begin{itemize} \item Remember, the .pc file contains the paths where the library and headers are installed. \item These paths are defined by './configure' parameters. So we have to generate a template 'fib/fib.pc.in': \end{itemize} \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}