Table of Contents
Maketools begin
maketools
Create directory structure:
mkdir dailutil; cd daiutil; mkdir config; mkdir build; mkdir test; mkdir src; mkdir tools; mkdir m4
daiutil/ ├── autogen.sh ├── m4 ├── config ├── build ├── test ├── src └── tools
Create autogen.sh
cat << 'EOF' > autogen.sh ; chmod +x autogen.sh #!/bin/sh autoreconf --force --install -I config -I m4 EOF
Create configure.ac
cat << 'EOF' > configure.ac
dnl Process this file with autoconf to produce a configure script.
# boiler plate
AC_PREREQ(2.59)
AC_INIT([ima_carpc], [0.10], [xuan-thuy.dang@dailabor.de])
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_MACRO_DIR([m4])
# Check the availability of main.cpp. For library only check src dir:
# AC_CONFIG_SRCDIR(src)
AC_CONFIG_SRCDIR(src/main.cpp)
AC_CANONICAL_SYSTEM
# automake initialization (mandatory) including a check for automake API version >= 1.9
#AM_INIT_AUTOMAKE([1.11])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AM_INIT_AUTOMAKE([subdir-objects])
# Option: This section should include macros which add command-line options to 'configure'.
# Check Programs needed for build process
#AM_PROG_AR
#AC_PROG_CC
AC_PROG_CXX # c++ support
AC_PROG_CXX([g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC QCC])
AC_PROG_CXXCPP
#AM_PROG_LEX
#AC_PROG_YACC
AC_PROG_LIBTOOL ## 2.2.6
# Libtools for making libraries
LT_PREREQ([2.2])
LT_INIT([dlopen])
# Debian resets this to no, but this break both Spot and the libtool
# test suite itself. Instead of requiring developer to install a
# non-patched version of Libtool on any Debian they use, we just
# cancel the effect of Debian's patch here.
link_all_deplibs=yes
link_all_deplibs_CXX=yes
### Macros to check the availability of Libraries, headers, etc.
### http://www.openismus.com/documents/linux/using_libraries/using_libraries.shtml
# use the C++ compiler for the following checks
AC_LANG([C++])
## check if log4cxx installed and make the lib paths available:
# LOG4CXX_CFLAGS LOG4CXX_LIBS. See m4/log4cxx.m4 script
#AC_CONFIG_LOG4CXX
## manually add dependency paths
# copy cross_lib_dep to .m4
#AC_CONFIG_LIB_DEP
### -Dxxx
### use AM_CONDITIONAL instead
#CPPFLAGS="$CPPFLAGS -DUCLIBC_OWRT -DGPS_DEBUG"
## Get LIBOONET library and include locations
AC_ARG_WITH([liboonet],
[AS_HELP_STRING([--with-liboonet],
[prefix location of the LIBOONET library, defaults to /usr])],
[OONET_PREFIX="$withval"],
[OONET_PREFIX='/usr'])
OONET_CPPFLAGS="-I$OONET_PREFIX/include"
OONET_LDFLAGS="-L$OONET_PREFIX/lib -loonet"
OONET_LIBS="-L$OONET_PREFIX/lib -loonet"
AC_SUBST([OONET_CPPFLAGS])
AC_SUBST([OONET_LDFLAGS])
AC_SUBST([OONET_LIBS])
## Get LIBDAIUTI library and include locations
AC_ARG_WITH([libdaiutil],
[AS_HELP_STRING([--with-libdaiutil],
[prefix location of the LIBDAIUTIL library, defaults to /usr])],
[DAIUTIL_PREFIX="$withval"],
[DAIUTIL_PREFIX='/usr'])
DAIUTIL_CPPFLAGS="-I$DAIUTIL_PREFIX/include"
DAIUTIL_LDFLAGS="-L$DAIUTIL_PREFIX/lib -ldaiutil"
DAIUTIL_LIBS="-L$DAIUTIL_PREFIX/lib -ldaiutil"
AC_SUBST([DAIUTIL_CPPFLAGS])
AC_SUBST([DAIUTIL_LDFLAGS])
AC_SUBST([DAIUTIL_LIBS])
## libgps: check and set GPSD_CFLAGS GPSD_LIBS.
#PKG_CHECK_MODULES(GPSD, libgps)
GPSD_LIBS="-lgps"
#AC_SUBST([GPSD_CPPFLAGS])
#AC_SUBST([GPSD_LDFLAGS])
AC_SUBST([GPSD_LIBS])
#CPPFLAGS="$CPPFLAGS -DUCLIBC_OWRT"
# Set -DUCLIBC_OWRT and put it in config.h.in
AM_CONDITIONAL([UCLIBC_OWRT], [test 1])
AC_DEFINE([UCLIBC_OWRT],[1],[Compile on openwrt_uclibc])
AM_CONDITIONAL([GPS_DEBUG], [test ])
AC_DEFINE([GPS_DEBUG],[0],[Test with gpsd ver. < 2.5])
## this extlib_dir is relative to abs_srcdir. Use $(top_srcdir) in Makefile.am to refer to other directories.
#AC_SUBST(EXTLIB_DIR, `pwd`/libext)
AC_SUBST(EXTLIB_DIR, `pwd`/libext)
# Hack source dir <----- convenient variable.
AC_SUBST(TOPSRC_DIR, `pwd`/src)
# use the C++ compiler for the following checks
AC_LANG([C++])
# Macros to check the availability of Headers
AC_HEADER_STDC
#AC_CHECK_HEADERS([string])
#AC_CHECK_HEADERS([iostream])
## Macros to check the availability of Typedefs and structs
AC_TYPE_SIZE_T
# Check Functions
# distribute additional compiler and linker flags
# --> set these variables instead of CXXFLAGS or LDFLAGS
AC_SUBST([AM_CXXFLAGS], [-Wall])
AC_SUBST([AM_LDFLAGS])
# Output stuffs: create configure, Makefile, etc.,
AC_CONFIG_HEADERS([config.h])
## Top-levle Makefile.am specifies recursive Makefile in 2 subfolder 'src' and 'examples'.
## Non-recursive Makefile.am in 'src' with subfolders.
# examples/Makefile
AC_CONFIG_FILES([
Makefile
src/Makefile
test/Makefile
])
AC_OUTPUT
EOF
Create Makefile.am
Blueprint for the generation of Makefiles
Top-level Makefile.am
Recursive make: top level Makefile.am specifies sub-dirs where other Makefile.am reside. No binary or source code in top-level folder.
cat<<EOF >Makefile.am ACLOCAL_AMFLAGS = -I m4 include $(top_srcdir)/Makecommon.am srcdir = @srcdir@ VPATH = @srcdir@ SUBDIRS = src test EXTRA_DIST = autogen.sh # Include this file in the distribution package dist_noinst_SCRIPTS = autogen.sh # Don't install this file to '--prefix-dir' EOF
src Makefile.am - Building binaries from src
We are building a library from source files. cd to src-dir.
cat<<EOF >Makefile.am include $(top_srcdir)/Makecommon.am srcdir = @srcdir@ VPATH = @srcdir@ ## we are building PROGRAMS. #bin_PROGRAMS = doit #doit_SOURCES = doit.c main.c ## we are building STATIC lib #lib_LIBRARIES = libzlib.a #libzlib_a_SOURCES = headers*.h source*.cpp ## Dynamic libs. lib_LTLIBRARIES = libdaiutil.la libdaiutil_la_SOURCES = EOF
Autogen and build
First time build
Work for me?
./autogen.sh make
Otherwise:
- run 'aclocal' to generate the m4-files
- run 'autoconf' to generate the configure script on the base of the configure.ac file
- run 'automake -a -c' to generate all still missing files with generic content (INSTALL and COPYING) and to generate the Makefile.in files that are used by the configure script to generate the final Makefiles
- run the generated local 'configure' script in order to create the final Makefiles (you can set the install directory via the –prefix=INSTALLPATH parameter of the script)
- run 'make' to build your programs and 'make install' to install the program in the usual or via the –prefix parameter of the configure-script defined install path
- with 'make dist' you can generate a packed source code distribution, which you can provide for download (e.g. with 'make dist-gzip' in .tar.gz format)
Further build
if configure.ac is changed (go to top dir): ./autogen.sh
if Makefile.am is changed (go to top dir): automake
then:
cd build ./../configure make
More complicated scenario
Setting compile and link FLAGS
A sample scenario is to separate headers*.h and put them in $src/include folder. A Makefile in src-dir must know about this.
1.) Define a variable to hold the location in configure.ac:
AC_SUBST(SRC_INCLUDE_DIR, `pwd`/include)
2.) In src-dir/Makefile.am, pass this location to compile flag of the specific binary:
libdaiutil_la_CPPFLAGS = -I @SRC_INCLUDE_DIR@\util
OR set the global FLAGS for all Makefile.
AM_CPPFLAGS = -I@SRC_INCLUDE_DIR@
Global FLAGS
One solution is to include a common makefile fragment on all your Makefile.ams:
include $(top_srcdir)/makecommon.am ... bin_PROGRAMS = foo foo_SOURCES = ...
In makecommon.mk:
AM_CXXFLAGS = -fpic -Wall -Wextra
Cross compiling
./configure --help ./configure CC=/home/t/s/arm-mv5sft-linux-gnueabi/SW3.2p1/bin/arm-mv5sft-linux-gnueabi-gcc CXX=/home/t/s/arm-mv5sft-linux-gnueabi/SW3.2p1/bin/arm-mv5sft-linux-gnueabi-g++ CFLAGS="-m32" LDFLAGS="-m32"--host=arm-mv5sft-linux-gnueabi --with-sysroot=/home/t/s/arm-mv5sft-linux-gnueabi/SW3.2p1/arm-mv5sft-linux-gnueabi/
Cross compiling script for android
source: https://gist.github.com/nddrylliog/4688209
#!/bin/sh
# I put all my dev stuff in here
export DEV_PREFIX=$HOME/Dev/
# Don't forget to adjust this to your NDK path
export ANDROID_NDK=${DEV_PREFIX}/android-ndk-r8d/
export CROSS_COMPILE=arm-linux-androideabi
# I chose the gcc-4.7 toolchain - works fine for me!
export ANDROID_PREFIX=${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.7/prebuilt/darwin-x86
# Apparently android-8 works fine, there are other versions, look them up
export SYSROOT=${ANDROID_NDK}/platforms/android-8/arch-arm
export CROSS_PATH=${ANDROID_PREFIX}/bin/${CROSS_COMPILE}
# Non-exhaustive lists of compiler + binutils
# Depending on what you compile, you might need more binutils than that
export CPP=${CROSS_PATH}-cpp
export AR=${CROSS_PATH}-ar
export AS=${CROSS_PATH}-as
export NM=${CROSS_PATH}-nm
export CC=${CROSS_PATH}-gcc
export CXX=${CROSS_PATH}-g++
export LD=${CROSS_PATH}-ld
export RANLIB=${CROSS_PATH}-ranlib
# This is just an empty directory where I want the built objects to be installed
export PREFIX=${DEV_PREFIX}/android/prefix
# Don't mix up .pc files from your host and build target
export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
# You can clone the full Android sources to get bionic if you want.. I didn't
# want to so I just got linker.h from here: http://gitorious.org/0xdroid/bionic
# Note that this was only required to build boehm-gc with dynamic linking support.
export CFLAGS="${CFLAGS} --sysroot=${SYSROOT} -I${SYSROOT}/usr/include -I${ANDROID_PREFIX}/include -I${DEV_PREFIX}/android/bionic"
export CPPFLAGS="${CFLAGS}"
export LDFLAGS="${LDFLAGS} -L${SYSROOT}/usr/lib -L${ANDROID_PREFIX}/lib"
./configure --host=${CROSS_COMPILE} --with-sysroot=${SYSROOT} --prefix=${PREFIX} "$@"
Including third-party Makefile
Structuring project
- we want to support sub-projects so:
- The top-level Makefile.am will include subdirs.
- Each sub-srcdir will have its own Makefile.am Sources.am and other project specific includes
Put generated binaries in a specific folder
bin_PROGRAMS = $(top_builddir)/bin/foo __top_builddir__bin_foo_SOURCES = ... __top_builddir__bin_foo_CPPFLAGS = ... __top_builddir__bin_foo_LDFLAGS = ...
Unsolved: Make libs available after build
I want libs go to lib-dir and headers go to include-dir
Solved: Files not found when build in separate build-dir
Solution: use $(topsrcdir). It always points to original top src-dir. ACSUBST(VAR, pwd) variables in configure.ac are resovled relative to build dirs. As a result, something will not be found in build-dir.
-- 1/ I discovered that, if we build the source in a separate directory, we need to fix some minor things: in Makefile.am I used to write: LIBTRAINING_DIR=../lib AM_CPPFLAGS = -I$(LIBTRAINING_DIR) [...] training_LDADD = ../lib/libtraining.la Now, thanks to the tries with 'make distcheck', I must be more strict: LIBTRAINING_SRCDIR=$(top_srcdir)/src/lib LIBTRAINING_BUILDDIR=$(top_builddir)/src/lib AM_CPPFLAGS = -I$(LIBTRAINING_SRCDIR) bin_PROGRAMS = training training_SOURCES = training.c internal_version.c training_LDADD = $(LIBTRAINING_BUILDDIR)/libtraining.la
Variables used to build
configure option --with-libname
This is convenient for crosscompiling and quick fix when user know where the libs were installed.
## Get LIBOONET library and include locations
# Provide --with-option with default sysroot (/usr)
AC_ARG_WITH([liboonet],
[AS_HELP_STRING([--with-liboonet],
[prefix location of the LIBOONET library, defaults to /usr])],
[OONET_PREFIX="$withval"],
[OONET_PREFIX='/usr'])
# Collect FLAGS
OONET_CPPFLAGS="-I$OONET_PREFIX/include"
OONET_LDFLAGS="-L$OONET_PREFIX/lib -loonet"
OONET_LIBS="-L$OONET_PREFIX/lib -loonet"
# Make FLAGS available in Makefile.am
AC_SUBST([OONET_CPPFLAGS])
AC_SUBST([OONET_LDFLAGS])
AC_SUBST([OONET_LIBS])
Using the AC_SUBST variables
Define Variables
53 # FLAGS 54 # Make AM_CXXFLAGS global or define in Makefile.am 55 # Makefile.am: AM_CXXFLAGS= -std=c++0x 56 AC_SUBST([AM_CXXFLAGS], [-Wall -std=c++0x])
Using them
include $(top_srcdir)/Makecommon.am include $(top_srcdir)/Sources.am srcdir = @srcdir@ VPATH = @srcdir@ ## global variable. Modified inside Makemodule.am by (+=) bin_PROGRAMS = carpcd man_MANS = ## openwrt cross ##AM_CPPFLAGS= $(GPSD_CFLAGS) ## host build AM_CPPFLAGS= -I@TOPSRC_DIR@ if GPS_DEBUG AM_CPPFLAGS += -DGPS_DEBUG endif if UCLIBC_OWRT AM_CPPFLAGS += -DUCLIBC_OWRT @OONET_CPPFLAGS@ @DAIUTIL_CPPFLAGS@ @YAJL_CPPFLAGS@ \ @LIBPHIDGET_CPPFLAGS@ \ $(GPSD_CPPFLAGS) endif carpcd_LDADD= @OONET_LIBS@ @DAIUTIL_LIBS@ @YAJL_LIBS@ \ @LIBPHIDGET_LIBS@ \ $(GPSD_LIBS) #AM_CPPFLAGS= -I@EXTLIB_DIR@ -I@TOPSRC_DIR@ #AM_CPPFLAGS= $(GPSD_CFLAGS) -I$(liboonet_incdir) -I$(libdaiutil_incdir) -I$(libyajl_incdir) #AM_LDFLAGS= $(GPSD_LIBS) @LOG4CXX_LIBS@ #carpcd_LDADD = $(liboonet_sla)/liboonet.la $(libdaiutil_la)/libdaiutil.la $(libyajl_la)/libyajl.la ## this .a works with static lib.. surprise! #carpcd_LDADD = $(liboonet_sla)/liboonet.a $(libdaiutil_la)/libdaiutil.a $(libyajl_la)/libyajl.a ##carpcd_LDFLAGS = -Wl,-Bstatic,-L$(libdaiutil_la)/,-ldaiutil.a,-Bdynamic carpcddir=$(bindir) #datadir=$(bindir) carpcd_SCRIPTS= carpcd.conf #dist_pkgdata_DATA = carpcd.conf carpcd_SOURCES = $(CARPCD_SRCS)
Other example
In configure.in…
PKGCHECKMODULES(LIBGLADE, libxml-2.0 >= 2.4.10
atk >= 1.0.0
gtk+-2.0 >= 2.0.0)
ACSUBST(LIBGLADELIBS) ACSUBST(LIBGLADECFLAGS)
and in Makefile.am.
INCLUDES = @LIBGLADECFLAGS@ libgladeLDADD = @LIBGLADE_LIBS@
Since autoconf defines Makefile variables for each substitution that it does, the last example could also be written as
INCLUDES = $(LIBGLADECFLAGS) libgladeLDADD = $(LIBGLADE_LIBS)
Srcs not copied to build_dir
see Autoconf Manual, chapter 4.7.3 Build Directories
Each Makefile.in should contain:
srcdir = @srcdir@ VPATH = @srcdir@
Due to VPATH limitations it might be necessary in certain cases to include the '$(srcdir)/' prefix in your Makefile.
AM_CPPFLAGS= -I@TOPSRC_DIR@ -I$(srcdir)/include
Conditional sources with AM_CONDITIONAL
When all else failed
rm -rf build/* autom4* aclocal.m4 configure
autoreconf --force --install -I config -I m4 <----- ./autoreconf
These are generated again:
[dang@localhost nfc_client_cpp]$ ./autogen.sh libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `config'. libtoolize: copying file `config/ltmain.sh' libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'. libtoolize: copying file `m4/libtool.m4' libtoolize: copying file `m4/ltoptions.m4' libtoolize: copying file `m4/ltsugar.m4' libtoolize: copying file `m4/ltversion.m4' libtoolize: copying file `m4/lt~obsolete.m4' configure.ac:13: installing 'config/config.guess' configure.ac:13: installing 'config/config.sub' configure.ac:16: installing 'config/install-sh' configure.ac:16: installing 'config/missing' src/Makefile.am: installing 'config/depcomp'
3rd package and maketools
CPPUNIT test
rpm -ql cppunit-devel cp /usr/share/aclocal/cppunit.m4 m4/
configure.in
dnl Process this file with autoconf to produce a configure script. AC_INIT(Makefile.am) AM_INIT_AUTOMAKE(money,0.1) AM_PATH_CPPUNIT(1.9.6) AC_PROG_CXX AC_PROG_CC AC_PROG_INSTALL AC_OUTPUT(Makefile)
Makefile.am
# Rules for the test code (use `make check` to execute) TESTS = MoneyApp check_PROGRAMS = $(TESTS) MoneyApp_SOURCES = Money.h MoneyTest.h MoneyTest.cpp MoneyApp.cpp MoneyApp_CXXFLAGS = $(CPPUNIT_CFLAGS) MoneyApp_LDFLAGS = $(CPPUNIT_LIBS) MoneyApp_LDFLAGS = -ldl