blob: 9b9395ea019aaba10ececed07769b6ff6022d8f9 [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001#!/usr/bin/env python
2# encoding: utf-8
3#
4# partially based on boost.py written by Gernot Vormayr
5# written by Ruediger Sonderfeld <ruediger@c-plusplus.de>, 2008
6# modified by Bjoern Michaelsen, 2008
7# modified by Luca Fossati, 2008
8# rewritten for waf 1.5.1, Thomas Nagy, 2008
9# rewritten for waf 1.6.2, Sylvain Rouquette, 2011
10
11'''
12
13This is an extra tool, not bundled with the default waf binary.
14To add the boost tool to the waf file:
15$ ./waf-light --tools=compat15,boost
16 or, if you have waf >= 1.6.2
17$ ./waf update --files=boost
18
19When using this tool, the wscript will look like:
20
21 def options(opt):
22 opt.load('compiler_cxx boost')
23
24 def configure(conf):
25 conf.load('compiler_cxx boost')
26 conf.check_boost(lib='system filesystem')
27
28 def build(bld):
29 bld(source='main.cpp', target='app', use='BOOST')
30
31Options are generated, in order to specify the location of boost includes/libraries.
32The `check_boost` configuration function allows to specify the used boost libraries.
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080033It can also provide default arguments to the --boost-mt command-line arguments.
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080034Everything will be packaged together in a BOOST component that you can use.
35
36When using MSVC, a lot of compilation flags need to match your BOOST build configuration:
37 - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined.
38 Errors: C4530
39 - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080040 So before calling `conf.check_boost` you might want to disabling by adding
41 conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
Alexander Afanasyeve1724c42014-02-26 22:00:54 -080042 Errors:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080043 - boost might also be compiled with /MT, which links the runtime statically.
Alexander Afanasyeve1724c42014-02-26 22:00:54 -080044 If you have problems with redefined symbols,
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080045 self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
46 self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
47Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases.
48
49'''
50
51import sys
52import re
53from waflib import Utils, Logs, Errors
54from waflib.Configure import conf
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080055from waflib.TaskGen import feature, after_method
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080056
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080057BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu',
58 '/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
59BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080060BOOST_VERSION_FILE = 'boost/version.hpp'
61BOOST_VERSION_CODE = '''
62#include <iostream>
63#include <boost/version.hpp>
Alexander Afanasyeve1724c42014-02-26 22:00:54 -080064int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080065'''
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080066
67BOOST_ERROR_CODE = '''
Davide Pesavento1bdef282014-04-08 20:59:50 +020068#include <boost/system/error_code.hpp>
69int main() { boost::system::error_code c; }
70'''
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080071
Alexander Afanasyev85093982016-03-08 14:03:54 -080072PTHREAD_CODE = '''
73#include <pthread.h>
Davide Pesavento30552942016-03-21 02:53:17 +010074static void* f(void*) { return 0; }
Alexander Afanasyev85093982016-03-08 14:03:54 -080075int main() {
76 pthread_t th;
Davide Pesavento30552942016-03-21 02:53:17 +010077 pthread_attr_t attr;
78 pthread_attr_init(&attr);
79 pthread_create(&th, &attr, &f, 0);
Alexander Afanasyev85093982016-03-08 14:03:54 -080080 pthread_join(th, 0);
Davide Pesavento30552942016-03-21 02:53:17 +010081 pthread_cleanup_push(0, 0);
82 pthread_cleanup_pop(0);
83 pthread_attr_destroy(&attr);
Alexander Afanasyev85093982016-03-08 14:03:54 -080084}
85'''
86
Davide Pesavento1bdef282014-04-08 20:59:50 +020087BOOST_THREAD_CODE = '''
88#include <boost/thread.hpp>
89int main() { boost::thread t; }
90'''
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080091
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080092BOOST_LOG_CODE = '''
93#include <boost/log/trivial.hpp>
94#include <boost/log/utility/setup/console.hpp>
95#include <boost/log/utility/setup/common_attributes.hpp>
96int main() {
97 using namespace boost::log;
98 add_common_attributes();
99 add_console_log(std::clog, keywords::format = "%Message%");
100 BOOST_LOG_TRIVIAL(debug) << "log is working" << std::endl;
101}
102'''
103
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800104# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
105PLATFORM = Utils.unversioned_sys_platform()
106detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
107detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
108detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
109BOOST_TOOLSETS = {
110 'borland': 'bcb',
111 'clang': detect_clang,
112 'como': 'como',
113 'cw': 'cw',
114 'darwin': 'xgcc',
115 'edg': 'edg',
116 'g++': detect_mingw,
117 'gcc': detect_mingw,
118 'icpc': detect_intel,
119 'intel': detect_intel,
120 'kcc': 'kcc',
121 'kylix': 'bck',
122 'mipspro': 'mp',
123 'mingw': 'mgw',
124 'msvc': 'vc',
125 'qcc': 'qcc',
126 'sun': 'sw',
127 'sunc++': 'sw',
128 'tru64cxx': 'tru',
129 'vacpp': 'xlc'
130}
131
132
133def options(opt):
134 opt = opt.add_option_group('Boost Options')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800135 opt.add_option('--boost-includes', type='string',
136 default='', dest='boost_includes',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800137 help='''path to the directory where the boost includes are,
138 e.g., /path/to/boost_1_55_0/stage/include''')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800139 opt.add_option('--boost-libs', type='string',
140 default='', dest='boost_libs',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800141 help='''path to the directory where the boost libs are,
142 e.g., path/to/boost_1_55_0/stage/lib''')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800143 opt.add_option('--boost-mt', action='store_true',
144 default=False, dest='boost_mt',
145 help='select multi-threaded libraries')
146 opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800147 help='''select libraries with tags (gd for debug, static is automatically added),
148 see doc Boost, Getting Started, chapter 6.1''')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800149 opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect',
150 help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
151 opt.add_option('--boost-toolset', type='string',
152 default='', dest='boost_toolset',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800153 help='force a toolset e.g. msvc, vc90, \
154 gcc, mingw, mgw45 (default: auto)')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800155 py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
156 opt.add_option('--boost-python', type='string',
157 default=py_version, dest='boost_python',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800158 help='select the lib python with this version \
159 (default: %s)' % py_version)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800160
161
162@conf
163def __boost_get_version_file(self, d):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800164 if not d:
165 return None
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800166 dnode = self.root.find_dir(d)
167 if dnode:
168 return dnode.find_node(BOOST_VERSION_FILE)
169 return None
170
171@conf
172def boost_get_version(self, d):
173 """silently retrieve the boost version number"""
174 node = self.__boost_get_version_file(d)
175 if node:
176 try:
177 txt = node.read()
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800178 except EnvironmentError:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800179 Logs.error("Could not read the file %r" % node.abspath())
180 else:
Davide Pesavento1bdef282014-04-08 20:59:50 +0200181 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800182 m1 = re_but1.search(txt)
Davide Pesavento1bdef282014-04-08 20:59:50 +0200183 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800184 m2 = re_but2.search(txt)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800185 if m1 and m2:
186 return (m1.group(1), m2.group(1))
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800187 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(":")
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800188
189@conf
190def boost_get_includes(self, *k, **kw):
191 includes = k and k[0] or kw.get('includes', None)
192 if includes and self.__boost_get_version_file(includes):
193 return includes
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800194 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800195 if self.__boost_get_version_file(d):
196 return d
197 if includes:
198 self.end_msg('headers not found in %s' % includes)
199 self.fatal('The configuration failed')
200 else:
201 self.end_msg('headers not found, please provide a --boost-includes argument (see help)')
202 self.fatal('The configuration failed')
203
204
205@conf
206def boost_get_toolset(self, cc):
207 toolset = cc
208 if not cc:
209 build_platform = Utils.unversioned_sys_platform()
210 if build_platform in BOOST_TOOLSETS:
211 cc = build_platform
212 else:
213 cc = self.env.CXX_NAME
214 if cc in BOOST_TOOLSETS:
215 toolset = BOOST_TOOLSETS[cc]
216 return isinstance(toolset, str) and toolset or toolset(self.env)
217
218
219@conf
220def __boost_get_libs_path(self, *k, **kw):
221 ''' return the lib path and all the files in it '''
222 if 'files' in kw:
223 return self.root.find_dir('.'), Utils.to_list(kw['files'])
224 libs = k and k[0] or kw.get('libs', None)
225 if libs:
226 path = self.root.find_dir(libs)
227 files = path.ant_glob('*boost_*')
228 if not libs or not files:
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800229 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
230 if not d:
231 continue
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800232 path = self.root.find_dir(d)
233 if path:
234 files = path.ant_glob('*boost_*')
235 if files:
236 break
237 path = self.root.find_dir(d + '64')
238 if path:
239 files = path.ant_glob('*boost_*')
240 if files:
241 break
242 if not path:
243 if libs:
244 self.end_msg('libs not found in %s' % libs)
245 self.fatal('The configuration failed')
246 else:
247 self.end_msg('libs not found, please provide a --boost-libs argument (see help)')
248 self.fatal('The configuration failed')
249
250 self.to_log('Found the boost path in %r with the libraries:' % path)
251 for x in files:
252 self.to_log(' %r' % x)
253 return path, files
254
255@conf
256def boost_get_libs(self, *k, **kw):
257 '''
258 return the lib path and the required libs
259 according to the parameters
260 '''
261 path, files = self.__boost_get_libs_path(**kw)
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800262 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800263 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800264 toolset_pat = '(-%s[0-9]{0,3})' % toolset
265 version = '-%s' % self.env.BOOST_VERSION
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800266
267 def find_lib(re_lib, files):
268 for file in files:
269 if re_lib.search(file.name):
270 self.to_log('Found boost lib %s' % file)
271 return file
272 return None
273
274 def format_lib_name(name):
275 if name.startswith('lib') and self.env.CC_NAME != 'msvc':
276 name = name[3:]
277 return name[:name.rfind('.')]
278
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800279 def match_libs(lib_names, is_static):
280 libs = []
281 lib_names = Utils.to_list(lib_names)
282 if not lib_names:
283 return libs
284 t = []
285 if kw.get('mt', False):
286 t.append('-mt')
287 if kw.get('abi', None):
288 t.append('%s%s' % (is_static and '-s' or '-', kw['abi']))
289 elif is_static:
290 t.append('-s')
291 tags_pat = t and ''.join(t) or ''
292 ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN
293 ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800294
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800295 for lib in lib_names:
296 if lib == 'python':
297 # for instance, with python='27',
298 # accepts '-py27', '-py2', '27' and '2'
299 # but will reject '-py3', '-py26', '26' and '3'
300 tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'])
301 else:
302 tags = tags_pat
303 # Trying libraries, from most strict match to least one
304 for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext),
305 'boost_%s%s%s%s$' % (lib, tags, version, ext),
306 # Give up trying to find the right version
307 'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext),
308 'boost_%s%s%s$' % (lib, tags, ext),
309 'boost_%s%s$' % (lib, ext),
310 'boost_%s' % lib]:
311 self.to_log('Trying pattern %s' % pattern)
312 file = find_lib(re.compile(pattern), files)
313 if file:
314 libs.append(format_lib_name(file.name))
315 break
316 else:
317 self.end_msg('lib %s not found in %s' % (lib, path.abspath()))
318 self.fatal('The configuration failed')
319 return libs
320
321 return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800322
Alexander Afanasyev85093982016-03-08 14:03:54 -0800323@conf
324def _check_pthread_flag(self, *k, **kw):
325 '''
326 Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode
327
328 Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
329 boost/thread.hpp will trigger a #error if -pthread isn't used:
330 boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
331 is not turned on. Please set the correct command line options for
332 threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
333
334 Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4
335 '''
336
337 var = kw.get('uselib_store', 'BOOST')
338
339 self.start_msg('Checking the flags needed to use pthreads')
340
341 # The ordering *is* (sometimes) important. Some notes on the
342 # individual items follow:
343 # (none): in case threads are in libc; should be tried before -Kthread and
344 # other compiler flags to prevent continual compiler warnings
345 # -lpthreads: AIX (must check this before -lpthread)
346 # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
347 # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
348 # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
349 # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
350 # -pthreads: Solaris/GCC
351 # -mthreads: MinGW32/GCC, Lynx/GCC
352 # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
353 # doesn't hurt to check since this sometimes defines pthreads too;
354 # also defines -D_REENTRANT)
355 # ... -mt is also the pthreads flag for HP/aCC
356 # -lpthread: GNU Linux, etc.
357 # --thread-safe: KAI C++
358 if Utils.unversioned_sys_platform() == "sunos":
359 # On Solaris (at least, for some versions), libc contains stubbed
360 # (non-functional) versions of the pthreads routines, so link-based
361 # tests will erroneously succeed. (We need to link with -pthreads/-mt/
362 # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
363 # a function called by this macro, so we could check for that, but
364 # who knows whether they'll stub that too in a future libc.) So,
365 # we'll just look for -pthreads and -lpthread first:
366 boost_pthread_flags = ["-pthreads", "-lpthread", "-mt", "-pthread"]
367 else:
Davide Pesavento30552942016-03-21 02:53:17 +0100368 boost_pthread_flags = ["", "-lpthreads", "-Kthread", "-kthread", "-llthread", "-pthread",
Alexander Afanasyev85093982016-03-08 14:03:54 -0800369 "-pthreads", "-mthreads", "-lpthread", "--thread-safe", "-mt"]
370
371 for boost_pthread_flag in boost_pthread_flags:
372 try:
373 self.env.stash()
374 self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
375 self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
376 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False)
377
378 self.end_msg(boost_pthread_flag)
379 return
380 except self.errors.ConfigurationError:
381 self.env.revert()
382 self.end_msg('None')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800383
384@conf
385def check_boost(self, *k, **kw):
386 """
387 Initialize boost libraries to be used.
388
389 Keywords: you can pass the same parameters as with the command line (without "--boost-").
390 Note that the command line has the priority, and should preferably be used.
391 """
392 if not self.env['CXX']:
393 self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
394
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800395 params = {
396 'lib': k and k[0] or kw.get('lib', None),
397 'stlib': kw.get('stlib', None)
398 }
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800399 for key, value in self.options.__dict__.items():
400 if not key.startswith('boost_'):
401 continue
402 key = key[len('boost_'):]
403 params[key] = value and value or kw.get(key, '')
404
405 var = kw.get('uselib_store', 'BOOST')
406
407 self.start_msg('Checking boost includes')
408 self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800409 versions = self.boost_get_version(inc)
410 self.env.BOOST_VERSION = versions[0]
411 self.env.BOOST_VERSION_NUMBER = int(versions[1])
412 self.end_msg("%d.%d.%d" % (int(versions[1]) / 100000,
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800413 int(versions[1]) / 100 % 1000,
414 int(versions[1]) % 100))
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800415 if Logs.verbose:
416 Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
417
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800418 if not params['lib'] and not params['stlib']:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800419 return
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800420 if 'static' in kw or 'static' in params:
421 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800422 self.start_msg('Checking boost libs')
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800423 path, libs, stlibs = self.boost_get_libs(**params)
424 self.env['LIBPATH_%s' % var] = [path]
425 self.env['STLIBPATH_%s' % var] = [path]
426 self.env['LIB_%s' % var] = libs
427 self.env['STLIB_%s' % var] = stlibs
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800428 self.end_msg('ok')
429 if Logs.verbose:
430 Logs.pprint('CYAN', ' path : %s' % path)
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800431 Logs.pprint('CYAN', ' shared libs : %s' % libs)
432 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800433
Alexander Afanasyev85093982016-03-08 14:03:54 -0800434 def has_shlib(lib):
435 return params['lib'] and lib in params['lib']
436 def has_stlib(lib):
437 return params['stlib'] and lib in params['stlib']
438 def has_lib(lib):
439 return has_shlib(lib) or has_stlib(lib)
440 if has_lib('thread'):
441 # not inside try_link to make check visible in the output
442 self._check_pthread_flag(k, kw)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800443
444 def try_link():
Alexander Afanasyev85093982016-03-08 14:03:54 -0800445 if has_lib('system'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800446 self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
Alexander Afanasyev85093982016-03-08 14:03:54 -0800447 if has_lib('thread'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800448 self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
Alexander Afanasyev85093982016-03-08 14:03:54 -0800449 if has_lib('log'):
450 if not has_lib('thread'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800451 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Alexander Afanasyev85093982016-03-08 14:03:54 -0800452 if has_shlib('log'):
453 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800454 self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800455
456 if params.get('linkage_autodetect', False):
457 self.start_msg("Attempting to detect boost linkage flags")
458 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800459 if toolset in ('vc',):
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800460 # disable auto-linking feature, causing error LNK1181
461 # because the code wants to be linked against
462 self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
463
464 # if no dlls are present, we guess the .lib files are not stubs
465 has_dlls = False
466 for x in Utils.listdir(path):
467 if x.endswith(self.env.cxxshlib_PATTERN % ''):
468 has_dlls = True
469 break
470 if not has_dlls:
471 self.env['STLIBPATH_%s' % var] = [path]
472 self.env['STLIB_%s' % var] = libs
473 del self.env['LIB_%s' % var]
474 del self.env['LIBPATH_%s' % var]
475
476 # we attempt to play with some known-to-work CXXFLAGS combinations
477 for cxxflags in (['/MD', '/EHsc'], []):
478 self.env.stash()
479 self.env["CXXFLAGS_%s" % var] += cxxflags
480 try:
481 try_link()
482 self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var]))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800483 exc = None
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800484 break
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800485 except Errors.ConfigurationError as e:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800486 self.env.revert()
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800487 exc = e
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800488
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800489 if exc is not None:
490 self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=exc)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800491 self.fatal('The configuration failed')
492 else:
493 self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain")
494 self.fatal('The configuration failed')
495 else:
496 self.start_msg('Checking for boost linkage')
497 try:
498 try_link()
499 except Errors.ConfigurationError as e:
500 self.end_msg("Could not link against boost libraries using supplied options")
501 self.fatal('The configuration failed')
502 self.end_msg('ok')
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800503
504
505@feature('cxx')
506@after_method('apply_link')
507def install_boost(self):
508 if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'):
509 return
510 install_boost.done = True
511 inst_to = getattr(self, 'install_path', '${BINDIR}')
512 for lib in self.env.LIB_BOOST:
513 try:
514 file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST)
515 self.bld.install_files(inst_to, self.bld.root.find_node(file))
516 except:
517 continue
518install_boost.done = False