build: Fix detection of Boost.Log compile flags
Change-Id: Ifdd5c485930a0bc50c1cbd76525947b001b44822
Refs: #2513
diff --git a/.waf-tools/boost.py b/.waf-tools/boost.py
index 9e2c0bd..6b27bce 100644
--- a/.waf-tools/boost.py
+++ b/.waf-tools/boost.py
@@ -69,6 +69,17 @@
int main() { boost::system::error_code c; }
'''
+PTHREAD_CODE = '''
+#include <pthread.h>
+int main() {
+ pthread_t th;
+ pthread_create(&th, 0, 0, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0);
+}
+'''
+
BOOST_THREAD_CODE = '''
#include <boost/thread.hpp>
int main() { boost::thread t; }
@@ -305,6 +316,66 @@
return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
+@conf
+def _check_pthread_flag(self, *k, **kw):
+ '''
+ Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode
+
+ Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
+ boost/thread.hpp will trigger a #error if -pthread isn't used:
+ boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
+ is not turned on. Please set the correct command line options for
+ threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
+
+ Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4
+ '''
+
+ var = kw.get('uselib_store', 'BOOST')
+
+ self.start_msg('Checking the flags needed to use pthreads')
+
+ # The ordering *is* (sometimes) important. Some notes on the
+ # individual items follow:
+ # (none): in case threads are in libc; should be tried before -Kthread and
+ # other compiler flags to prevent continual compiler warnings
+ # -lpthreads: AIX (must check this before -lpthread)
+ # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+ # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
+ # -pthreads: Solaris/GCC
+ # -mthreads: MinGW32/GCC, Lynx/GCC
+ # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+ # doesn't hurt to check since this sometimes defines pthreads too;
+ # also defines -D_REENTRANT)
+ # ... -mt is also the pthreads flag for HP/aCC
+ # -lpthread: GNU Linux, etc.
+ # --thread-safe: KAI C++
+ if Utils.unversioned_sys_platform() == "sunos":
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+ boost_pthread_flags = ["-pthreads", "-lpthread", "-mt", "-pthread"]
+ else:
+ boost_pthread_flags = ["-lpthreads", "-Kthread", "-kthread", "-llthread", "-pthread",
+ "-pthreads", "-mthreads", "-lpthread", "--thread-safe", "-mt"]
+
+ for boost_pthread_flag in boost_pthread_flags:
+ try:
+ self.env.stash()
+ self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
+ self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
+ self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False)
+
+ self.end_msg(boost_pthread_flag)
+ return
+ except self.errors.ConfigurationError:
+ self.env.revert()
+ self.end_msg('None')
@conf
def check_boost(self, *k, **kw):
@@ -356,32 +427,26 @@
Logs.pprint('CYAN', ' shared libs : %s' % libs)
Logs.pprint('CYAN', ' static libs : %s' % stlibs)
+ def has_shlib(lib):
+ return params['lib'] and lib in params['lib']
+ def has_stlib(lib):
+ return params['stlib'] and lib in params['stlib']
+ def has_lib(lib):
+ return has_shlib(lib) or has_stlib(lib)
+ if has_lib('thread'):
+ # not inside try_link to make check visible in the output
+ self._check_pthread_flag(k, kw)
def try_link():
- if (params['lib'] and 'system' in params['lib']) or \
- params['stlib'] and 'system' in params['stlib']:
+ if has_lib('system'):
self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
- if (params['lib'] and 'thread' in params['lib']) or \
- params['stlib'] and 'thread' in params['stlib']:
+ if has_lib('thread'):
self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
-
- def is_log_mt():
- '''Check if found boost_log library is multithread-safe'''
- for lib in libs:
- if lib.startswith('boost_log'):
- lib_log = lib
- break
- return '-mt' in lib_log
-
- if params['lib'] and 'log' in params['lib']:
- self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
- if not is_log_mt():
+ if has_lib('log'):
+ if not has_lib('thread'):
self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
- self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
- if params['stlib'] and 'log' in params['stlib']:
- # Static linking is assumed by default
- if not is_log_mt():
- self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
+ if has_shlib('log'):
+ self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
if params.get('linkage_autodetect', False):