Using Autotools for a new shared library
What I want to do is to create a new shared library called libxxx
that links against another shared library called libzzz
, this shared library has an independent "pkg-config"-like tool, let's say it's called "zzz-config" which gives the cflags needed by the compilation phase when using the libzzz
.
What I want to do is:
- Create configure/makefile, etc.. using autotools like automake, autoconf, etc;
- It must use the
zzz-config
script cited above; - It must generate automatic dependencies for sources;
- It must have a mode for buildi开发者_开发问答ng debug (with no optimization) and release (with optimizations) builds;
- The sources are in C++;
- It must target for a shared library;
- It must read sources for a
src
directory and put compiled files in another directory
I've read almost all available tutorials for autotools but I was not able to figure a way to do that, if you can point some example would be very kindly.
Thank you !
It's fairly easy to do this with the autotools. A few things to note: libzzz might provide a macro to do most of the work for you. For example, glib provides a macro named AM_PATH_GLIB_2_0 that is installed along with the library, so that you merely need to invoke it in your configure.ac. (Note that the macro is misnamed, since it stomps on automake's namespace, but that is another issue entirely.) Here's a sample configure.ac and Makefile.am that does what you want (see below for remarks on debug and release builds):
configure.ac:
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.66]) AC_INIT([libxxx], [0.0.0], [alice@bob.com]) AC_CONFIG_SRCDIR([libxxx.cc]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign]) LT_INIT AC_PROG_CXX # Checks for libraries. # If libzzz has an autoconf macro use it. Otherwise: AC_PATH_PROG([ZZZ_CONFIG],[zzz-config],[none]) AS_IF([test x"$ZZZ_CONFIG" = xnone],[ AC_MSG_ERROR([zzz-config not found in PATH]) ]) CPPFLAGS="$CPPFLAGS $(zzz-config -cflags)" LIBS="$(zzz-config -libs) $LIBS" # Totally unnecessary: we're not linking # If zzz-config is found, we can probably assume that # libzzz is installed, but check anyway: AC_CHECK_LIB([zzz],[main],[],[AC_MSG_ERROR([libzzz required])]) # Checks for header files. AC_CHECK_HEADERS([zzz.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT
Makefile.am
lib_LTLIBRARIES = libxxx.la libxxx_la_SOURCES = libxxx.cc include_HEADERS = xxx.h libxxx_la_LDFLAGS = -version-info 0:0:0
In terms of doing debug or release builds, there are lots of ways to do that with the autotools that do not involve editing the build scripts at all. The canonical way to do it is to set CXXFLAGS when you invoke configure (eg pass CXXFLAGS=-O2 CPPFLAGS=-DNDEBUG as arguments to configure to get a release build). You can also set your system up so that everything you install in /usr/local will be a release build by writing those assignments into /usr/local/share/config.site while everything built for install in $HOME will be a debug build by writing 'CXXFLAGS="-g -O0"' into $HOME/share/config.site. You could invoke AC_HEADER_ASSERT in configure.ac if you want to give the user a --disable-assert option at configure time to turn off assertions (but it's really just as easy for the user to put -DNDEBUG into CPPFLAGS). Another nice thing you can do is exploit automake's VPATH builds to configure distinct build directories where each is configured appropriately.
However, if you really feel the need to add the functionality into your build scripts, you can try putting something like this in configure.ac:
AC_ARG_ENABLE([debug],AS_HELP_STRING([--enable-debug], [configure a debug build]), [CXXFLAGS="$CXXFLAGS -g -O0"]) AC_ARG_ENABLE([release],AS_HELP_STRING([--enable-release], [configure a release build]), [CPPFLAGS="$CPPFLAGS -DNDEBUG"] [CXXFLAGS="$CXXFLAGS -O2"])
Note that this is not reliable and may cause confusion to the user. For example, if the user is using a config.site to set CPPFLAGS to -DDEBUG but invokes --enable-release, then CPPFLAGS will include "-DDEBUG -DNDEBUG". If you try to completely reset CPPFLAGS in response to --enable-release, then the -I flags needed for libzzz will be lost. You can avoid that last problem by AC_SUBST'ing LIBZZZ_CFLAGS and making modifications to Makefile.am, but it really is just easier to educate your user to set CPPFLAGS and CXXFLAGS when they invoke configure.
See more in my answer here: https://stackoverflow.com/a/4680578/140750
I would also stay away from autotools.
As well, my experiences with Cmake have been less than stellar. Things may have changed, but the documentation was just not there when I was trying to learn it a while back.
I tend to use scons: http://www.scons.org/
That said I don't know how well it performs on large projects, (i.e. thousands or more files). For smaller or medium projects it's fine though.
You could also try qmake, but I'd only recommend that if you were using Qt.
My suggestion is to use CMake instead of autotools
. It's much easier to work with and it will also create platform-dependent projects to work with (i.e. Makefile-based projects, Visual Studio projects, Eclipse CDT projects, etc.).
It will also create debug
or release
projects, depending on the CMAKE_BUILD_TYPE
variable value.
Creating the libxxx
library is as simple as:
add_library(libxxx SHARED ${LIBXXX_SOURCES})
where LIBXXX_SOURCES
is a variable that holds the sources.
Linking the two libraries is just as easy (see target_link_libraries):
target_link_libraries(libxxx libzzz)
To get the compilation flags from the zzz-config
script you would use the execute_process command like so:
execute_process(COMMAND ./zzz-config
WORKING_DIRECTORY "<your_working_directory>"
OUTPUT_VARIABLE ZZZ_FLAGS)
Then you can set the CMAKE_C_FLAGS
or the CMAKE_CXX_FLAGS
variable to setup the required compilation flags.
精彩评论