|
|
|
NavigationPersonal tools |
Autotools IntegrationThis website is deprecated!
Please refer and move articles to: http://trac.enlightenment.org/e/wiki/ This page has moved to http://trac.enlightenment.org/e/wiki/AutotoolsIntegration. Don't do any more edits here!
[edit] IntroductionThis document describes how to use and integrate autotools in EFL projects. It shows the common tree structure directories and details how to write configure.ac and Makefile.am files. It is not a complete tutorial on the autotools, but describes basic use, correct usage and some tricks. It also mention some m4 macros used in the EFL. [edit] Tree StructureThe usual tree directories structure of an EFL of program based on the EFL is:
project/
data/
doc/
src/
bin/
lib/
tests/
Some of the subdirectories might not be present (mainly tests subdirectory). For a program, the data/ subdirectory usually contains a theme/ subdirectory, which for edc files. [edit] AutoconfAll projects must contain the file configure.ac. This file must be processed by autoconf to produce a configure script file. The main purpose of that script file is to produce Makefile files, but can be used for a lot of other things too. The file configure.ac is in the subdirectory project/. This file should contain at least the following calls:
Hence, a very basic configure.ac file is: AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net]) AM_INIT_AUTOMAKE(1.6 dist-bzip2) AC_PROG_LIBTOOL AC_PROG_CC AC_CONFIG_FILES([]) AC_OUTPUT To create the configure script file, just run in the directory where configure.ac is located: autoconf The call AC_CONFIG_FILES should list all the files that configure must create. It transform a file named Foo.in into Foo and replace some parts of text of Foo.in (consider these parts as variables) by their value. That's the purpose of the configure script: replacing text by value. As the main purpose is to create Makefile files with the configure script, AC_CONFIG_FILES must list all the needed Makefile, one for each subdirectory of tree structure. Our configure.ac file is now: AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net]) AM_INIT_AUTOMAKE(1.6 dist-bzip2) AC_PROG_LIBTOOL AC_PROG_CC AC_CONFIG_FILES([ Makefile data/Makefile doc/Makefile src/Makefile src/bin/Makefile src/lib/Makefile src/tests/Makefile ]) AC_OUTPUT So, it will transform all the Makefile.in files into Makefile files. To create Makefile.in files, an easy way is to use automake. [edit] AutomakeThe purpose of automake is to transform Makefile.am files into Makefile.in files, these latter being transforms by the configure script (see previous section). So we have to create one Makefile.am for each Makefile which is listed in AC_CONFIG_FILES (in configure.ac). Some Makefile.am are just for going from a directory to a subdirectory. Then, the content of the Makefile.am is just: SUBDIRS = subdir1 subdir2 subdir3 The order is important. The Makefile file will go first insubdir1, then subdir2, then subdir3, then process the current directory. To process the current directory before one of the ub directory, just use '.' somewhere. For example, if we want to process the current directory before all the subdirectory (for some dependencies reasons), use: SUBDIRS = . subdir1 subdir2 subdir3 To clean the files correctly, the files Makefile.in must be removed the with maintainer-clean rule. For that, we have to add in each Makefile.am MAINTAINERCLEANFILES = Makefile.in [edit] Top level Makefile.amMAINTAINERCLEANFILES = Makefile.in SUBDIRS = src data doc [edit] Makefile.am in srcMAINTAINERCLEANFILES = Makefile.in SUBDIRS = lib bin tests [edit] Makefile.am in dataMAINTAINERCLEANFILES = Makefile.in SUBDIRS = theme Now, the remaining Makefile.am are data/theme/Makefile.am, doc/Makefile.am, src/bin/Makefile.am, src/lib/Makefile.am and src/tests/Makefile.am. [edit] Libtool, or how to easily create a libraryNow, we are going to see how to write src/lib/Makefile.am. In that directory, we consider the 3 files of our library: Foo.h, foo1.c and foo2.c. Foo.h is the exported header files, used for the API of our library. foo1.c and foo2.c contain the definition of the functions declared in Foo.h. We want:
The installation of the library files will be automatic. Here is src/lib/Makefile.am: MAINTAINERCLEANFILES = Makefile.in include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c So we add to lib_LTLIBRARIES one (or several) library name(s) sufixed by '.la'. For each of these library, we specify all the sources. [edit] The binaryNow, we want to create a binary named bar, which depends on libfoo. It's the same kind of stuff: we specify which program we want to create, and its source files. We suppose that the program bar is composed of 2 files: bar1.c and bar2.c. Here is src/bin/Makefile.am: MAINTAINERCLEANFILES = Makefile.in bin_PROGRAMS = bar bar_SOURCES = bar1.c bar2.c bar_DEPENDENCIES = $(top_builddir)/src/lib/libfoo.la [edit] Improvements of configure.ac and the Makefile.am'sWe can improve configure.ac in several ways. Here are some hints. [edit] Libtool is slooooowlibtool checks for C++ and fortran 77 compiler when the configure script is launched. To remove these checks, we add 2 calls before AC_PROG_LIBTOOL: AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net]) AC_CANONICAL_HOST AM_INIT_AUTOMAKE(1.6 dist-bzip2) define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl AC_PROG_LIBTOOL AC_PROG_CC AC_CONFIG_FILES([ Makefile data/Makefile doc/Makefile src/Makefile src/bin/Makefile src/lib/Makefile src/tests/Makefile ]) AC_OUTPUT [edit] Versioning of the Shared LibraryIt can be convenient to add a version in the shared library. It allow to separate the shared lib from different api (api expansion, api break, etc...). For more details about how to change the version, follow that link. Otherwise, we suppose that our configure.ac defines a variable named version_info: AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net]) AC_CANONICAL_HOST AM_INIT_AUTOMAKE(1.6 dist-bzip2) define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl AC_PROG_LIBTOOL dnl we just have set the version info, then: AC_SUBST(version_info) AC_PROG_CC AC_CONFIG_FILES([ Makefile data/Makefile doc/Makefile src/Makefile src/bin/Makefile src/lib/Makefile src/tests/Makefile ]) AC_OUTPUT and src/lib/Makefile.am is: MAINTAINERCLEANFILES = Makefile.in include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c libfoo_la_LDFLAGS = -version-info @version_info@ [edit] Usage of $prefix based directoryThe EFL might use, in his code, a directory which value is based on the value of the variable $prefix in configure (value that can be changed with the --prefix option of configure). For example, all the engines are in a subdif of $libdir/evas/modules/engines, and $libdir is equal to ${exec_prefix}/lib and ${exec_prefix} is equal to $prefix. The solution would be to pass to the preprocessor the value -DMY_LIB_DIR="${prefix}/lib/***" (so, a string) with AC_DEFINE in the configure.ac file. But, the value of $prefix is never defined in the configure script. You can write bad hack to find a solution, but the correct solution is to pass that value in the Makefile (actually, Makefile.am), because, at this configure time, the value of $prefix is known. To pass -DMY_LIB_DIR="${prefix}/lib/***" to the preprocessor in Makefile.am, you have 2 solutions:
For example, in the first case, our Makefile.am would be: MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = -DMY_LIB_DIR=\"$(libdir)\" include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c libfoo_la_LDFLAGS = -version-info @version_info@ Note that to have a C string, we must use \", otherwise automake will consider it as a string in your future Makefile. In the second example, our Makefile.am would be: MAINTAINERCLEANFILES = Makefile.in include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c libfoo_la_CPPFLAGS = -DMY_LIB_DIR=\"$(libdir)\" libfoo_la_LDFLAGS = -version-info @version_info@ These examples were for a library, but it is exactly the same for a binary. [edit] Usage of pkg-configYour program or library can depend on another library. If that library is sufficiently recent, it has a .pc file and pkg-config can be used to retrieve in a simple way the flags to pass to the preprocessor (all the needed -I and -D gcc options) and the flags to pass to the linker (-L and -l ld options). First, you have to detect the .pc file in configure.ac. Nowadays, all the linux distributions have an m4 macro for that: PKG_CHECK_MODULES. For example, if you want to detect eet, you can use: PKG_CHECK_MODULES([EET], [eet]) this macro tries to find the file eet.pc (eet because of the second parameter of that macro). If it is found, it puts in the variables EET_CFLAGS and EET_LIBS respectively the -I and -D options, and the -L and -l (and even more, like -pthread, for example) options (EET because of the first parameter of the macro). If eet.pc is not found, the configure scripts aborts and displays an error. Sometimes, it is useful not to abort. For that, you just have to use the third or fourth parameters. Another interest to use them is to display if eet is available or not. So our configure.ac is then:
AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE(1.6 dist-bzip2)
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
AC_PROG_LIBTOOL
dnl we just have set the version info, then:
AC_SUBST(version_info)
PKG_CHECK_MODULES([EET], [eet], [have_eet="yes"], [have_eet="no"])
AC_PROG_CC
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
src/Makefile
src/bin/Makefile
src/lib/Makefile
src/tests/Makefile
])
AC_OUTPUT
echo
echo
echo "------------------------------------------------------------------------"
echo "$PACKAGE_NAME $PACKAGE_VERSION"
echo "------------------------------------------------------------------------"
echo
echo "Configuration Options Summary:"
echo
echo " eet..........: ${have_eet}"
echo
You have also other usages of PKG_CHECK_MODULES:
In those cases, the MY_DEP_CFLAGS variable will have all the -D and -I options for all the libraries passed to PKG_CHECK_MODULES and MY_DEP_LIBS will have all the -L and -l options. Now, we just have to pass them in the Makefile.am that needs them. MY_DEP_CFLAGS to AM_CPPFLAGS or *_CPPFLAGS, and MY_DEP_LIBS to *_LIBADD (if it's a library) or *_LDADD (if it's a binary). In our example of the foo library: MAINTAINERCLEANFILES = Makefile.in include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c libfoo_la_CPPFLAGS = -DMY_LIB_DIR=\"$(libdir)\" @MY_DEP_CFLAGS@ libfoo_la_LIBADD = @MY_DEP_LIBS@ libfoo_la_LDFLAGS = -version-info @version_info@ [edit] Windows portIf the library is cross-platform and can be compiled on Windows with the autotools (for example with MSYS and MinGW), then we have to:
We can also pass another option to the linker to remove some warnings: --enable-auto-import, but we should do that when we are sure we are on Windows. For that, we just have to check the varialble $host_os. We must then add a call of AC_CANONICAL_HOST in configure.ac. The configure.ac script is then
AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE(1.6 dist-bzip2)
AC_LIBTOOL_WIN32_DLL
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
AC_PROG_LIBTOOL
dnl we just have set the version info, then:
AC_SUBST(version_info)
lt_enable_auto_import=""
case "$host_os" in
mingw* | cegcc*)
lt_enable_auto_import="-Wl,--enable-auto-import"
esac
AC_SUBST(lt_enable_auto_import)
PKG_CHECK_MODULES([EET], [eet], [have_eet="yes"], [have_eet="no"])
AC_PROG_CC
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
src/Makefile
src/bin/Makefile
src/lib/Makefile
src/tests/Makefile
])
AC_OUTPUT
echo
echo
echo "------------------------------------------------------------------------"
echo "$PACKAGE_NAME $PACKAGE_VERSION"
echo "------------------------------------------------------------------------"
echo
echo "Configuration Options Summary:"
echo
echo " eet..........: ${have_eet}"
echo
and src/lib/Makefile.am is: MAINTAINERCLEANFILES = Makefile.in include_HEADERS = Foo.h lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo1.c foo2.c libfoo_la_CPPFLAGS = -DMY_LIB_DIR=\"$(libdir)\" @MY_DEP_CFLAGS@ libfoo_la_LIBADD = @MY_DEP_LIBS@ libfoo_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ [edit] New features and deprecated macros
The non deprecated configure.ac script becomes:
AC_INIT([my_project], [0.1], [enlightenment-devel@lists.sourceforge.net])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE(1.10 dist-bzip2)
LT_PREREQ([2.2.6])
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
LT_INIT([win32-dll])
dnl we just have set the version info, then:
AC_SUBST(version_info)
lt_enable_auto_import=""
case "$host_os" in
mingw* | cegcc*)
lt_enable_auto_import="-Wl,--enable-auto-import"
esac
AC_SUBST(lt_enable_auto_import)
PKG_CHECK_MODULES([EET], [eet], [have_eet="yes"], [have_eet="no"])
AC_PROG_CC
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
src/Makefile
src/bin/Makefile
src/lib/Makefile
src/tests/Makefile
])
AC_OUTPUT
echo
echo
echo "------------------------------------------------------------------------"
echo "$PACKAGE_NAME $PACKAGE_VERSION"
echo "------------------------------------------------------------------------"
echo
echo "Configuration Options Summary:"
echo
echo " eet..........: ${have_eet}"
echo
[edit] M4 macros[edit] Usage of M4 Macros[edit] Documentation[edit] Unit tests[edit] Coverage[edit] Benchmark[edit] Layout of a configure.ac scriptThe autoconf documentation describes how to correctly write a configure.ac file. I have adopted the same way of writing configure.ac files, but i have also added some parts that are not mentioned. Here is what I usually do:
These 3 parts has been described above. Then:
Once it's done:
[edit] External links |