1 # boost.m4: Locate Boost headers and libraries for autoconf-based projects.
2 # Copyright (C) 2007 Benoit Sigoure <tsuna@lrde.epita.fr>
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # This file provides several macros to use the various Boost libraries.
24 # The first macro is BOOST_REQUIRE. It will simply check if it's possible to
25 # find the Boost headers of a given (optional) minimum version and it will
26 # define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to
27 # your configure so that users can specify non standard locations.
29 m4_pattern_forbid([^_?BOOST_])
31 # BOOST_REQUIRE([VERSION])
32 # ------------------------
33 # Look for Boost. If version is given, it must either be a literal of the form
34 # "X.Y" where X and Y are integers or a variable "$var".
35 # Defines the value BOOST_CPPFLAGS. This macro only checks for headers with
36 # the required version, it does not check for any of the Boost libraries.
37 # FIXME: Add a 2nd optionnal argument so that it's not fatal if Boost isn't found
38 # and add an AC_DEFINE to tell whether HAVE_BOOST.
39 AC_DEFUN([BOOST_REQUIRE],
40 [dnl First find out what kind of argument we have.
41 dnl If we have an empty argument, there is no constraint on the version of
42 dnl Boost to use. If it's a literal version number, we can split it in M4 (so
43 dnl the resulting configure script will be smaller/faster). Otherwise we do
44 dnl the splitting at runtime.
46 [^ *$], [m4_pushdef([BOOST_VERSION_REQ], [])dnl
49 boost_version_subminor=0
51 [^[0-9]+\([-._][0-9]+\)*$],
52 [m4_pushdef([BOOST_VERSION_REQ], [ version >= $1])dnl
53 boost_version_major=m4_bregexp([$1], [^\([0-9]+\)], [\1])
54 boost_version_minor=m4_bregexp([$1], [^[0-9]+[-._]\([0-9]+\)], [\1])
55 boost_version_subminor=m4_bregexp([$1], [^[0-9]+[-._][0-9]+[-._]\([0-9]+\)], [\1])
58 [m4_pushdef([BOOST_VERSION_REQ], [])dnl
59 boost_version_major=`expr "X$1" : 'X\([[^-._]]*\)'`
60 boost_version_minor=`expr "X$1" : 'X[[0-9]]*[[-._]]\([[^-._]]*\)'`
61 boost_version_subminor=`expr "X$1" : 'X[[0-9]]*[[-._]][[0-9]]*[[-._]]\([[0-9]]*\)'`
62 case $boost_version_major:$boost_version_minor in #(
63 *: | :* | *[[^0-9]]*:* | *:*[[^0-9]]*)
64 AC_MSG_ERROR([[Invalid argument for REQUIRE_BOOST: `$1']])
68 [m4_fatal(Invalid argument: `$1')]
71 [AS_HELP_STRING([--with-boost=DIR],
72 [prefix of Boost]BOOST_VERSION_REQ[ @<:@guess@:>@])])dnl
73 AC_CACHE_CHECK([for Boost headers[]BOOST_VERSION_REQ],
76 AC_LANG_PUSH([C++])dnl
78 test x"$boost_version_subminor" != x \
79 && boost_subminor_chk="|| (B_V_MAJ == $boost_version_major \
80 && B_V_MIN == $boost_version_minor \
81 && B_V_SUB % 100 < $boost_version_subminor)"
82 for boost_inc in "$with_boost/include" '' \
83 /opt/local/include /usr/local/include /opt/include /usr/include \
84 "$with_boost" C:/Boost/include
86 test -e "$boost_inc" || continue
87 boost_save_CPPFLAGS=$CPPFLAGS
88 test x"$boost_inc" != x && CPPFLAGS="$CPPFLAGS -I$boost_inc"
89 m4_pattern_allow([^BOOST_VERSION$])dnl
90 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <boost/version.hpp>
92 # error BOOST_VERSION is not defined
94 #define B_V_MAJ (BOOST_VERSION / 10000)
95 #define B_V_MIN (BOOST_VERSION / 100 % 1000)
96 #define B_V_SUB (BOOST_VERSION % 100)
97 #if (B_V_MAJ < $boost_version_major) \
98 || (B_V_MAJ == $boost_version_major \
99 && B_V_MIN / 100 % 1000 < $boost_version_minor) $boost_subminor_chk
100 # error Boost headers version < $1
102 ]])], [boost_cv_inc_path=yes], [boost_cv_version=no])
103 CPPFLAGS=$boost_save_CPPFLAGS
104 if test x"$boost_cv_inc_path" = xyes; then
105 if test x"$boost_inc" != x; then
106 boost_cv_inc_path=$boost_inc
111 AC_LANG_POP([C++])dnl
113 case $boost_cv_inc_path in #(
115 AC_MSG_ERROR([Could not find Boost headers[]BOOST_VERSION_REQ])
121 BOOST_CPPFLAGS="-I$boost_cv_inc_path"
124 AC_SUBST([BOOST_CPPFLAGS])dnl
125 AC_CACHE_CHECK([for Boost's header version],
126 [boost_cv_lib_version],
127 [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl
128 boost_cv_lib_version=unknown
129 boost_sed_version='/^.*BOOST_LIB_VERSION.*"\([[^"]]*\)".*$/!d;s//\1/'
130 boost_version_hpp="$boost_inc/boost/version.hpp"
131 test -e "$boost_version_hpp" \
132 && boost_cv_lib_version=`sed "$boost_sed_version" "$boost_version_hpp"`
134 m4_popdef([BOOST_VERSION_REQ])dnl
138 # BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND])
139 # --------------------------------------------------------------------------
140 # Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for
141 # some parts of the Boost library which are only made of headers and don't
142 # require linking (such as Boost.Foreach).
144 # Default ACTION-IF-NOT-FOUND: Fail with a fatal error.
146 # Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_<HEADER-NAME> in
147 # case of success # (where HEADER-NAME is written LIKE_THIS, e.g.,
148 # HAVE_BOOST_FOREACH_HPP).
149 AC_DEFUN([BOOST_FIND_HEADER],
150 [AC_REQUIRE([BOOST_REQUIRE])dnl
151 AC_LANG_PUSH([C++])dnl
152 boost_save_CPPFLAGS=$CPPFLAGS
153 CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
154 AC_CHECK_HEADER([$1],
155 [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1],
156 [Define to 1 if you have <$1>])])],
157 [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])])
158 CPPFLAGS=$boost_save_CPPFLAGS
159 AC_LANG_POP([C++])dnl
160 ])# BOOST_FIND_HEADER
163 # BOOST_FIND_LIB([LIB-NAME], [PREFERED-RT-OPT], [HEADER-NAME], [CXX-TEST])
164 # ------------------------------------------------------------------------
165 # Look for the Boost library LIB-NAME (e.g., LIB-NAME = `thread', for
166 # libboost_thread). Check that HEADER-NAME works and check that
167 # libboost_LIB-NAME can link with the code CXX-TEST.
169 # Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above).
171 # Boost libraries typically come compiled with several flavors (with different
172 # runtime options) so PREFERED-RT-OPT is the prefered suffix. A suffix is one
173 # or more of the following letters: sgdpn (in that order). s = static
174 # runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build,
175 # n = (unsure) STLPort build without iostreams from STLPort (it looks like `n'
176 # must always be used along with `p'). Additionally, PREFERED-RT-OPT can
177 # start with `mt-' to indicate that there is a preference for multi-thread
178 # builds. Some sample values for PREFERED-RT-OPT: (nothing), mt, d, mt-d, gdp
179 # ... If you want to make sure you have a specific version of Boost
180 # (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro.
181 AC_DEFUN([BOOST_FIND_LIB],
182 [AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl
183 AC_REQUIRE([BOOST_REQUIRE])dnl
184 AC_LANG_PUSH([C++])dnl
185 AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl
186 AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl
187 AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl
188 BOOST_FIND_HEADER([$3])
189 boost_save_CPPFLAGS=$CPPFLAGS
190 CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
191 # Now let's try to find the library. The algorithm is as follows: first look
192 # for a given library name according to the user's PREFERED-RT-OPT. For each
193 # library name, we prefer to use the ones that carry the tag (toolset name).
194 # Each library is searched through the various standard paths were Boost is
195 # usually installed. If we can't find the standard variants, we try to
196 # enforce -mt (for instance on MacOSX, libboost_threads.dylib doesn't exist
197 # but there's -obviously- libboost_threads-mt.dylib).
198 AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib],
201 mt | mt-) boost_mt=-mt; boost_rtopt=;; #(
202 mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$2" : 'Xmt-*\(.*\)'`;; #(
203 *) boost_mt=; boost_rtopt=$2;;
205 # If the PREFERED-RT-OPT are not empty, prepend a `-'.
206 case $boost_rtopt in #(
207 *[[a-z0-9A-Z]]*) boost_rtopt="-$boost_rtopt";;
209 # Check whether we do better use `mt' even though we weren't ask to.
210 if test x"$boost_mt" = x; then
211 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
212 #if defined _REENTRANT || defined _MT || defined __MT__
215 # error MT not needed
217 ]])], [boost_mt=-mt])
219 # Generate the test file.
220 AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3>], [$4])])
222 # Don't bother to ident the 6 nested for loops, only the 2 insidemost ones
224 for boost_tag_ in -$boost_cv_lib_tag ''; do
225 for boost_ver_ in -$boost_cv_lib_version ''; do
226 for boost_mt_ in $boost_mt -mt ''; do
227 for boost_rtopt_ in $boost_rtopt '' -d; do
229 boost_$1$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \
230 boost_$1$boost_tag_$boost_mt_$boost_ver_ \
231 boost_$1$boost_tag_$boost_rtopt_$boost_ver_ \
232 boost_$1$boost_tag_$boost_mt_ \
233 boost_$1$boost_tag_$boost_ver_
235 # Avoid testing twice the same lib
236 case $boost_failed_libs in #(
237 *@$boost_lib@*) continue;;
239 boost_save_LIBS=$LIBS
240 LIBS="-l$boost_lib $LIBS"
241 for boost_ldpath in "$with_boost/lib" '' \
242 /opt/local/lib /usr/local/lib /opt/lib /usr/lib \
243 "$with_boost" C:/Boost/lib /lib /usr/lib64 /lib64
245 test -e "$boost_ldpath" || continue
246 boost_save_LDFLAGS=$LDFLAGS
247 test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath"
248 dnl First argument of AC_LINK_IFELSE left empty because the test file is
249 dnl generated only once above (before we start the for loops).
251 [Boost_lib=yes], [Boost_lib=no])
252 if test x"$Boost_lib" = xyes; then
253 Boost_lib_LDFLAGS="-L$boost_ldpath"
254 Boost_lib_LIBS="-l$boost_lib"
257 boost_failed_libs="$boost_failed_libs@$boost_lib@"
259 LDFLAGS=$boost_save_LDFLAGS
261 LIBS=$boost_save_LIBS
268 AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])
269 AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])
270 CPPFLAGS=$boost_save_CPPFLAGS
271 AS_VAR_POPDEF([Boost_lib])dnl
272 AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl
273 AS_VAR_POPDEF([Boost_lib_LIBS])dnl
274 AC_LANG_POP([C++])dnl
278 # _BOOST_FIND_COMPILER_TAG()
279 # --------------------------
280 # Internal. When Boost is installed without --layout=system, each library
281 # filename will hold a suffix that encodes the compiler used during the
282 # build. The Boost build system seems to call this a `tag'.
283 AC_DEFUN([_BOOST_FIND_COMPILER_TAG],
284 [AC_REQUIRE([AC_PROG_CXX])dnl
285 AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag],
286 [AC_LANG_PUSH([C++])dnl
287 boost_cv_lib_tag=unknown
288 # The following tests are mostly inspired by boost/config/auto_link.hpp
289 # The list is sorted to most recent/common to oldest compiler (in order
290 # to increase the likelihood of finding the right compiler with the
291 # least number of compilation attempt).
292 # Beware that some tests are sensible to the order (for instance, we must
293 # look for MinGW before looking for GCC3).
294 # I used one compilation test per compiler with a #error to recognize
295 # each compiler so that it works even when cross-compiling (let me know
296 # if you know a better approach).
297 # Known missing tags (known from Boost's tools/build/v2/tools/common.jam):
298 # como, edg, kcc, bck, mp, sw, tru, xlc
299 # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines
300 # the same defines as GCC's).
302 "defined __GNUC__ && __GNUC__ == 4 && !defined __ICC @ gcc4" \
303 "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \
304 && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
305 || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \
306 "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC @ gcc3" \
307 "defined _MSC_VER && _MSC_VER >= 1400 @ vc80" \
308 "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \
309 "defined __BORLANDC__ @ bcb" \
310 "defined __ICL @ iw" \
311 "defined __ICC && (defined __unix || defined __unix__) @ il" \
312 "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \
313 "defined __GNUC__ && __GNUC__ == 2 @ gcc2" \
314 "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \
315 "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \
316 "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \
317 "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8"
319 boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '`
320 boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'`
321 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
325 # error $boost_tag_test
327 ]])], [boost_cv_lib_tag=$boost_tag; break], [])
329 AC_LANG_POP([C++])dnl
331 if test x"$boost_cv_lib_tag" = xunknown; then
332 AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]])
335 ])# _BOOST_FIND_COMPILER_TAG