How to include Boost in GNU Autotools project? - c++

My project compiles using GNU autotools (aclocal && autoconf && ./configure && make). I'd like to use Boost, and I'd like for other people to be able to compile it as well.
Should I put Boost in my project's dir, or rely on the system's Boost?
How should I tell autotools to use Boost? I've Googled and found many m4 files that claim to do this - but where should I put those m4 files? I can stash one in my /usr/share/aclocal dir, but that doesn't help someone else who wants to compile the project using ./configure && make.

The Archive has AX_BOOST_*.
I switched to boost.m4 for some time, but it is so painfully slow I could edit a Makefile with the full Boost path by hand in vim before boost.m4 finished testing for the second library.
I went back to the Archive and was happy to learn the boost macros are being actively maintained again; then I proceeded to purge boost.m4 from every one of my projects.
Relevant excerpts from a use case (assuming the ax_boost_*.m4 files are in subdir m4):
./bootstrap
aclocal -I m4 --install
...
./configure.ac
...
AC_CONFIG_MACRO_DIR([m4])
...
AX_BOOST_BASE([1.48],, [AC_MSG_ERROR([libfoo needs Boost, but it was not found in your system])])
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
...
./Makefile.am
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = bootstrap ...
SUBDIRS = ... src ...
...
./src/Makefile.am
AM_CPPFLAGS = \
... \
$(BOOST_CPPFLAGS) \
...
...
AM_LDFLAGS = ... \
$(BOOST_LDFLAGS)
...
lib_LTLIBRARIES = libFoo.la
...
libFoo_la_LIBADD = \
... \
$(BOOST_FILESYSTEM_LIB) \
$(BOOST_SYSTEM_LIB) \
...

There's an excellent boost.m4 macro that you can include in your project in the m4 subdirectory. These macros are located with AC_CONFIG_MACRO_DIR([m4]) in configure.ac.
Add ACLOCAL_AMFLAGS = -I m4 --install to the top-level Makefile.am, used by automake.
Here's why it's such a good macro:
BOOST_REQUIRE([1.54],[ACTION-IF-NOT-FOUND])
This will define BOOST_CPPFLAGS which you can add to CPPFLAGS, use in an AC_SUBST, etc.
For individual Boost components, it's possible to specify debug builds, static builds, etc. But the (typically) multi-threaded, dynamic libraries are best, e.g.,
BOOST_FILESYSTEM([mt])
will define BOOST_FILESYSTEM_LIBS and BOOST_FILESYSTEM_LDFLAGS. As another bonus, if the library relies on, say, Boost.System, then these library dependencies are automatically added to the LIBS, LDFLAGS, etc.
You should just specify that a Boost installation is required rather than trying to distribute it. It's easily built and installed from source, or from precompiled packages. The former takes a long time, but it's best to have an 'optimized' build on the system. There's a lot of software that can make use of a (robust and optimized) Boost implementation.
Then use the BOOST_REQUIRE error message if there's no acceptable version available.

I'd definitely rely on the system's Boost installation. IIRC, the last time I built Boost it required non-standard tools (wrt the portable tools required for autoconf) for Boost to build. It also took a long time.
AC_CONFIG_MACRO_DIR is where those .m4 files go
AC_CONFIG_MACRO_DIR([m4])
where the macros are in the "m4" directory. I'd expect the various Boost .m4 macros to have some way of telling configure what Boost package to look for (for multiple Boost installations) and where it is (nonstandard installations).

Related

Disabling cxx support for libtool after calling AC_PROG_CXX

For my project (library), I use configure with libtool and automake to build under linux hosts. The library consists of a C API, as well as an optional C++ extension. So, since
AC_PROG_CXX must be called globally, I use automake conditionals:
*configure.ac*:
AC_PROG_CC
AC_PROG_CXX
AM_PROG_AR
LT_INIT
... some tests to figure out 'build_cxx' ...
AC_CONDITIONAL([CXX], [ test x$build_cxx = xyes ])
And inside Makefile.am
sources = files.c
if CXX then
cxx_sources = files.cpp
else
cxx_sources =
endif
sources = $sources $cxx_sources
The whole thing, however, does not work when configure is not able to locate g++ (which practically kills the extra logic for the c++ extension). After some research, I've come down to the conclusion that AC_PROG_CXX somehow tells libtool to assume that c++ support. I was also surprised to realise that if AC_PROG_CXX fails, it sets CXX to 'g++'!!!
Anyway, calling AC_PROG_CXX conditionally produces errors like 'am_fastdepCXX is never defined', which seems logical to me. The worst thing is that the error is not shown while configure is running, but it appears later in the linking phase, in to form of 'unknown libtool option -o' (ouch).
The full source code can be found here -> http://bitbucket.org/sdlu/sdlu/src
Can somebody help me?
Thanks in advance...
It's an Automake limitation, it doesn't care about the condition when choosing the linker.
One work-around is to conditionally rewrite the _LINK command, as suggested in this mailing list post:
if USE_CXX
cxx_sources = ...
else
cxx_sources =
libSDLU_la_LINK = $(LINK) $(libSDLU_la_CFLAGS) $(libSDLU_la_LDFLAGS)
endif
Another way (suggested in the same discussion) is to put the C++ sources in a utility library that is built and added conditionally, then added to the main library:
if CXX
noinst_LTLIBRARIES = libSDLUxx.la
libSDLUxx_la_SOURCES = src/cxx/SDLU_CButton.cxx \
src/cxx/SDLU_CIniHandler.cxx \
src/cxx/SDLU_CRenderer.cxx \
src/cxx/SDLU_CSprite.cxx \
src/cxx/SDLU_CTexture.cxx \
src/cxx/SDLU_CWindow.cxx
libSDLU_la_LIBADD = libSDLUxx.la
endif
Some unrelated notes
Do not put generated files (Makefile.in, configure, etc) into source control.
Add a bootstrap script that invokes the autotools to generate things.
Prefer pkg-config (i.e. PKG_CHECK_MODULES(SDL2, sdl2)) over hand-crafted autoconf macros (i.e. AM_PATH_SDL2);
Do not install autoheaders (i.e. SDLU_config.h.in). It makes your library incompatible with every autoconf-based software, as you are re-defining PACKAGE, VERSION, and all library-detection macros. See my answer in this question for examples on how to do it.
I would have the C++ API built and installed as an independent, optional library; drop the sdlu-config script altogether, then write sdluxx.pc that requires sdlu. Do not bother checking if the C++ compiler works, if the user passed --enable-cxx he knows what he's doing; I prefer to have the build fail than silently have an incomplete library.
I don't think it is a good idea to interfere in the handling of the CXX variable.
Use your own variable BUILD_CXX
AC_CONDITIONAL([BUILD_CXX], [ test x$build_cxx = xyes ])here
and
if BUILD_CXX
# ....
endif

Boost.Regex with icu/unicode support

How to build Boost.Regex with icu/ unicode support? My compiler is GCC, and IDE is Eclipse C++. How to configure binary files with Eclipse?
I tried to do this "bjam --sHAVE_ICU=1 toolset=gcc". But it did not work.
When i check if icu support is enable with "bjam -has_icu", i still get "has icu builds : no".
I build Boost against ICU using -sICU_PATH=<icuRoot> and -sICU_LINK="-L<icuLibDir>".
I've seen Boost fail to properly detect ICU as well, and have needed to patch the file has_icu_test.cpp (simply return 0 from it's main() function). This will work if you know everything else is set up properly.
Solved the problem by adding directly include path of include ICU directory to cflags when executing b2. For instance:
./b2 --with-regex
cflags="-O0 -I\"$ICU_PATH/include\"
You also may need to add path of ICU lib and moreover full paths to libs to linker. Something like this:
export ICU_LINK="-L\"$ICU_PATH/lib\" -l\"$ICU_PATH/lib/libicudata.a\" -l\"$ICU_PATH/lib/libicui18n.a\" -l\"$ICU_PATH/lib/libicuuc.a\""
./b2 --with-regex
cflags="-O0 -I\"$ICU_PATH/include\"
-sICU_LINK=$ICU_LINK \
Behemoths and Juggernauts
On some unix, this worked for me:
./b2 link=static,shared -sICU_PATH=/usr/local install
In said system, ICU headers are installed in /usr/local/include and ICU libraries in /usr/local/lib
In order to test if you have ICU headers installed (say in /usr/local/include) see if the dir /usr/local/include/unicode/ exists and has lots of header files in it (e.g. symtable.h)
Note that when I followed general advice from then net and passed -sICU_LINK='-L/usr/local/lib' to boost's b2, ICU detection (version 1.62 and 1.63) failed.
In the previous answer, user "NuSkooler" mentions that patching boost file has_icu_test.cpp to simply return 0; short-circuits the test and boost believes all is genkhi with ICU and goes ahead with it.
However make sure you also delete all ICU-related function calls and header files from that file because it is usually the case that has_icu_test.cpp first fails to compile or link because ICU libraries or header files can not be found by boost internals.
With all these, I can confirm that Aegisub's configure now passes the ICU test for me.
(and all these because John Hurt sadly died and I tried to put subtitles in a clip of Heaven's Gate to give to a friend)
b.

Autotools: Including a prebuilt 3rd party library

I'm currently working to upgrade a set of c++ binaries that each use their own set of Makefiles to something more modern based off of Autotools. However I can't figure out how to include a third party library (eg. the Oracle Instant Client) into the build/packaging process.
Is this something really simple that I've missed?
Edit to add more detail
My current build environment looks like the following:
/src
/lib
/libfoo
... source and header files
Makefile
/oci #Oracle Instant Client
... header and shared libraries
Makefile
/bin
/bar
... source and header files
Makefile
Makefile
/build
/bin
/lib
build.sh
Today the top level build.sh does the following steps:
Runs each lib's Makefile and copies the output to /build/lib
Runs each binary's Makefile and copied the output to /build/bin
Each Makefile has a set of hardcoded paths to the various sibling directories. Needless to say this has become a nightmare to maintain. I have started testing out autotools but where I am stuck is figuring out the equivalent to copying /src/lib/oci/*.so to /build/lib for compile time linking and bundling into a distribution.
I figured out how to make this happen.
First I switched to a non recursive make.
Next I made the following changes to configure.am as per this page http://www.openismus.com/documents/linux/using_libraries/using_libraries
AC_ARG_WITH([oci-include-path],
[AS_HELP_STRING([--with-oci-include-path],
[location of the oci headers, defaults to lib/oci])],
[OCI_CFLAGS="-$withval"],
[OCI_CFLAGS="-Ilib/oci"])
AC_SUBST([OCI_CFLAGS])
AC_ARG_WITH([oci-lib-path],
[AS_HELP_STRING([--with-oci-lib-path],
[location of the oci libraries, defaults to lib/oci])],
[OCI_LIBS="-L$withval -lclntsh -lnnz11"],
[OCI_LIBS='-L./lib/oci -lclntsh -lnnz11'])
AC_SUBST([OCI_LIBS])
In the Makefile.am you then use the following lines (assuming a binary named foo)
foo_CPPFLAGS = $(OCI_CFLAGS)
foo_LDADD = libnavycommon.la $(OCI_LIBS)
ocidir = $(libdir)
oci_DATA = lib/oci/libclntsh.so.11.1 \
lib/oci/libnnz11.so \
lib/oci/libocci.so.11.1 \
lib/oci/libociicus.so \
lib/oci/libocijdbc11.so
The autotools are not a package management system, and attempting to put that type of functionality in is a bad idea. Rather than incorporating the third party library into your distribution, you should simply have the configure script check for its existence and abort if the required library is not available. The onus is on the user to satisfy the dependency. You can then release a binary package that will allow the user to use the package management system to simplify dependency resolution.

Include a (header-only) library in an autotools project

I want to integrate a header-only C++ library in my Autotools project. Since the library uses Autoconf and Automake, I use AC_CONFIG_SUBDIRS in configure.ac and added the library dir to the SUBDIRS = line in Makefile.am.
My question is: how do I prevent the header library from being installed by make install? I'm building a single binary, so my users don't need these headers.
I'd prefer not to tamper with the library, so I can fetch upgrade by just untarring the new version.
Here is an idea.
Move all the third-party libraries you do not want to see installed into a subdirectory called noinst/. So for instance if you want to ship your project with something like Boost, unpack it into the directory noinst/boost/. Use AC_CONFIG_SUBDIRS([noinst/boost]). Inside noinst/Makefile.am, do something like this:
SUBDIRS = boost
# Override Automake's installation targets with the command ":" that does nothing.
install:; #:
install-exec:; #:
install-data:; #:
uninstall:; #:
The effect is that whenever some of the recursive "make install*" or "make uninstall" commands are run from the top-level directory, the recursion will stop in noinst/ and not visit its subdirectories. Other recursive commands (like "make", "make clean" or "make dist") will still recurse into the subdirectories.
You could of course override install: and friends directly into the third-party package, and avoid the extra noinst/ directory. But if you are like me, you don't want to tamper with third-party packages to ease their update.
Also a nice property of the above setup is that if someone goes into noinst/boost/ and decide to run make install, it will work. It just does not occur by default when they install your package.
just came across a similar problem and found the solution in the automake manual:
noinst_HEADERS would be the right variable to use in a directory containing only headers and no associated library or program
Andreas
Don't use SUBDIRS then. The following hack may work:
all-local:
${MAKE} -C thatlib all
Of course it would be best if the library remained in its own directory outside of your project, and you just point to it via CFLAGS/LIBS flags.

Howto create software package in Unix/Linux?

How can we create a software package, so that
after extracting our software tar ball user can do
the typical steps?
$ gunzip < mycode.tar.gz | tar xvf -
$ ./configure
$ make
$ make install
An alternative to the hard to understand GNU/Autools is CMake.
http://www.cmake.org/cmake/help/examples.html
e.g. KDE is using it.
Look into the GNU autoconf/automake toolchain. Here's a free tutorial/book.
In the old days, this process was done by hand. Each Makefile was written by hand (the file make uses as a sort of script). This became problematic when it came to portability, and so the configure script was made. The ./configure script was written by hand for each project as well. Eventually this was automated by GNU with their autotools package. This consists of autoconf, automake, and a few others. While alternatives exist, particularly for make, autotools is most widely used. ...At least on GNU/Linux systems. Alternatives include the already mentioned CMake, Boost.Build, Boost.Jam, SCons, and more.
Use autotools to create the configure script (which will generate the Makefile necessary for the last two steps), then make a tarball with all your code and stuff in it.
rpmbuild is a command to build rpm packages
man page
tutorial
Autotools.
You'll need to write a configure.ac and a Makefile.am scripts.
Configure.ac is pretty easy and can be mostly autogenerated from running 'autoscan' on your source code. That will generate a 'configure.scan' file that you'll need to tweak to generate the final configure.ac file.
The Automake.am file is all based off of conventions. You'll probably need something like:
AUTOMAKE_OPTIONS = foreign subdir-objects
AM_CXXFLAGS = -std=c++11 -static-libstdc++ -Wall -Werror \
-Wfatal-errors -I blah
AM_LDFLAGS = blah
bin_PROGRAMS = mybinary
mybinary_SOURCES = \
blah.h blah.cc
everything is based on a naming schema:
dist vs nodist = should it be built
inst vs noinst = should it be installed
DATA = data files
MANS = man pages
SOURCES = source code
so dist_noinst_DATA is for data files required for building but are not installed.
Once you have both of those files you usually need to run something like:
aclocal && autoheader && automake --add-missing && autoconf
to setup autotools files required for building. This can be put in a shell script and run prior to running ./configure.