Fix the detection of the toolset name for GCC.
[boost.m4.git] / build-aux / boost.m4
blob756f4f0da0e4962600ee0ae53cfb28220270ee18
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/>.
17 # serial 1
19 # ------ #
20 # README #
21 # ------ #
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.
45 m4_bmatch([$1],
46   [^ *$], [m4_pushdef([BOOST_VERSION_REQ], [])dnl
47            boost_version_major=0
48            boost_version_minor=0
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])
57   [^\$[a-zA-Z_]+$],
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']])
65          ;;
66      esac
68   [m4_fatal(Invalid argument: `$1')]
69 )dnl
70 AC_ARG_WITH([boost],
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],
74     [boost_cv_inc_path],
75     [boost_cv_inc_path=no
76 AC_LANG_PUSH([C++])dnl
77     boost_subminor_chk=
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
85     do
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>
91 #ifndef BOOST_VERSION
92 # error BOOST_VERSION is not defined
93 #endif
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
101 #endif
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
107         fi
108         break
109       fi
110     done
111 AC_LANG_POP([C++])dnl
112     ])
113     case $boost_cv_inc_path in #(
114       no)
115         AC_MSG_ERROR([Could not find Boost headers[]BOOST_VERSION_REQ])
116         ;;#(
117       yes)
118         BOOST_CPPFLAGS=
119         ;;#(
120       *)
121         BOOST_CPPFLAGS="-I$boost_cv_inc_path"
122         ;;
123     esac
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"`
133     ])
134 m4_popdef([BOOST_VERSION_REQ])dnl
135 ])# BOOST_REQUIRE
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],
199   [Boost_lib=no
200   case "$2" in #(
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;;
204   esac
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";;
208   esac
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__
213 /* use -mt */
214 #else
215 # error MT not needed
216 #endif
217 ]])], [boost_mt=-mt])
218   fi
219   # Generate the test file.
220   AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3>], [$4])])
221   boost_failed_libs=
222 # Don't bother to ident the 6 nested for loops, only the 2 insidemost ones
223 # matter.
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
228   for boost_lib in \
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_
234   do
235     # Avoid testing twice the same lib
236     case $boost_failed_libs in #(
237       *@$boost_lib@*) continue;;
238     esac
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
244     do
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).
250       AC_LINK_IFELSE([],
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"
255         break 6
256       else
257         boost_failed_libs="$boost_failed_libs@$boost_lib@"
258       fi
259       LDFLAGS=$boost_save_LDFLAGS
260     done
261     LIBS=$boost_save_LIBS
262   done
263 done
264 done
265 done
266 done
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
275 ])# BOOST_FIND_LIB
278 # --------------------------------------- #
279 # Checks for the various Boost libraries. #
280 # --------------------------------------- #
282 # List of boost libraries: http://www.boost.org/libs/libraries.htm
283 # The page http://beta.boost.org/doc/libs is useful: it gives the first release
284 # version of each library (among other things).
287 # BOOST_CONVERSION()
288 # ------------------
289 # Look for Boost.Conversion (cast / lexical_cast)
290 AC_DEFUN([BOOST_CONVERSION],
291 [BOOST_FIND_HEADER([boost/cast.hpp])
292 BOOST_FIND_HEADER([boost/lexical_cast.hpp])
293 ])# BOOST_CONVERSION
296 # BOOST_FILESYSTEM([PREFERED-RT-OPT])
297 # -----------------------------------
298 # Look for Boost.Filesystem.  For the documentation of PREFERED-RT-OPT, see the
299 # documentation of BOOST_FIND_LIB above.
300 AC_DEFUN([BOOST_FILESYSTEM],
301 [BOOST_FIND_LIB([filesystem], [$1],
302                 [boost/filesystem.hpp], [boost::filesystem::path p;])
303 ])# BOOST_FILESYSTEM
306 # BOOST_FOREACH()
307 # ---------------
308 # Look for Boost.Foreach
309 AC_DEFUN([BOOST_FOREACH],
310 [BOOST_FIND_HEADER([boost/foreach.hpp])])
313 # BOOST_FORMAT()
314 # ------------------
315 # Look for Boost.Format
316 # Note: we can't check for boost/format/format_fwd.hpp because the header isn't
317 # standalone.  It can't be compiled because it triggers the following error:
318 # boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std'
319 #                                                  does not name a type
320 AC_DEFUN([BOOST_FORMAT],
321 [BOOST_FIND_HEADER([boost/format.hpp])])
324 # BOOST_GRAPH([PREFERED-RT-OPT])
325 # ------------------------------
326 # Look for Boost.Graphs.  For the documentation of PREFERED-RT-OPT, see the
327 # documentation of BOOST_FIND_LIB above.
328 AC_DEFUN([BOOST_GRAPH],
329 [BOOST_FIND_LIB([graph], [$1],
330                 [boost/graph/adjacency_list.hpp], [boost::adjacency_list g;])
331 ])# BOOST_GRAPH
334 # BOOST_THREADS([PREFERED-RT-OPT])
335 # --------------------------------
336 # Look for Boost.Threads.  For the documentation of PREFERED-RT-OPT, see the
337 # documentation of BOOST_FIND_LIB above.
338 AC_DEFUN([BOOST_THREADS],
339 [BOOST_FIND_LIB([thread], [$1],
340                 [boost/thread.hpp], [boost::thread t; boost::mutex m;])
341 ])# BOOST_THREADS
344 # BOOST_UTILITY()
345 # ---------------
346 # Look for Boost.Utility (noncopyable, result_of, base-from-member idiom,
347 # etc.)
348 AC_DEFUN([BOOST_UTILITY],
349 [BOOST_FIND_HEADER([boost/utility.hpp])])
352 # BOOST_VARIANT()
353 # ---------------
354 # Look for Boost.Variant.
355 AC_DEFUN([BOOST_VARIANT],
356 [BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp])
357 BOOST_FIND_HEADER([boost/variant.hpp])])
359 # _BOOST_gcc_test(MAJOR, MINOR)
360 # -----------------------------
361 # Internal helper for _BOOST_FIND_COMPILER_TAG.
362 m4_define([_BOOST_gcc_test],
363 ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl
365 # _BOOST_FIND_COMPILER_TAG()
366 # --------------------------
367 # Internal.  When Boost is installed without --layout=system, each library
368 # filename will hold a suffix that encodes the compiler used during the
369 # build.  The Boost build system seems to call this a `tag'.
370 AC_DEFUN([_BOOST_FIND_COMPILER_TAG],
371 [AC_REQUIRE([AC_PROG_CXX])dnl
372 AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag],
373 [AC_LANG_PUSH([C++])dnl
374   boost_cv_lib_tag=unknown
375   # The following tests are mostly inspired by boost/config/auto_link.hpp
376   # The list is sorted to most recent/common to oldest compiler (in order
377   # to increase the likelihood of finding the right compiler with the
378   # least number of compilation attempt).
379   # Beware that some tests are sensible to the order (for instance, we must
380   # look for MinGW before looking for GCC3).
381   # I used one compilation test per compiler with a #error to recognize
382   # each compiler so that it works even when cross-compiling (let me know
383   # if you know a better approach).
384   # Known missing tags (known from Boost's tools/build/v2/tools/common.jam):
385   #   como, edg, kcc, bck, mp, sw, tru, xlc
386   # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines
387   # the same defines as GCC's).
388   # TODO: Move the test on GCC 4.3 up once it's released.
389   for i in \
390     _BOOST_gcc_test(4, 2) \
391     _BOOST_gcc_test(4, 1) \
392     _BOOST_gcc_test(4, 0) \
393     "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \
394      && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \
395          || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \
396     _BOOST_gcc_test(3, 4) \
397     _BOOST_gcc_test(3, 3) \
398     "defined _MSC_VER && _MSC_VER >= 1400 @ vc80" \
399     _BOOST_gcc_test(3, 2) \
400     "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \
401     _BOOST_gcc_test(3, 1) \
402     _BOOST_gcc_test(3, 0) \
403     "defined __BORLANDC__ @ bcb" \
404     "defined __ICC && (defined __unix || defined __unix__) @ il" \
405     "defined __ICL @ iw" \
406     "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \
407     _BOOST_gcc_test(4, 3) \
408     _BOOST_gcc_test(2, 95) \
409     "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \
410     "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \
411     "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \
412     "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8"
413   do
414     boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '`
415     boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'`
416     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
417 #if $boost_tag_test
418 /* OK */
419 #else
420 # error $boost_tag_test
421 #endif
422 ]])], [boost_cv_lib_tag=$boost_tag; break], [])
423   done
424 AC_LANG_POP([C++])dnl
426   if test x"$boost_cv_lib_tag" = xunknown; then
427     AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]])
428     boost_cv_lib_tag=
429   fi
430 ])# _BOOST_FIND_COMPILER_TAG