blob: 4b2ede536a6135aad2d881cc7c04f149cf12be7c [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
Eric Newberryc14a8ac2018-04-05 16:46:51 -070057BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080058BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
Davide Pesavento6ecc3f82019-02-17 22:23:08 -050059
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>
Davide Pesavento6ecc3f82019-02-17 22:23:08 -050094int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
95'''
96
97BOOST_LOG_SETUP_CODE = '''
98#include <boost/log/trivial.hpp>
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -080099#include <boost/log/utility/setup/console.hpp>
100#include <boost/log/utility/setup/common_attributes.hpp>
101int main() {
102 using namespace boost::log;
103 add_common_attributes();
104 add_console_log(std::clog, keywords::format = "%Message%");
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500105 BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800106}
107'''
108
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800109# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
110PLATFORM = Utils.unversioned_sys_platform()
111detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
112detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
113detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
114BOOST_TOOLSETS = {
115 'borland': 'bcb',
116 'clang': detect_clang,
117 'como': 'como',
118 'cw': 'cw',
119 'darwin': 'xgcc',
120 'edg': 'edg',
121 'g++': detect_mingw,
122 'gcc': detect_mingw,
123 'icpc': detect_intel,
124 'intel': detect_intel,
125 'kcc': 'kcc',
126 'kylix': 'bck',
127 'mipspro': 'mp',
128 'mingw': 'mgw',
129 'msvc': 'vc',
130 'qcc': 'qcc',
131 'sun': 'sw',
132 'sunc++': 'sw',
133 'tru64cxx': 'tru',
134 'vacpp': 'xlc'
135}
136
137
138def options(opt):
139 opt = opt.add_option_group('Boost Options')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800140 opt.add_option('--boost-includes', type='string',
141 default='', dest='boost_includes',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800142 help='''path to the directory where the boost includes are,
143 e.g., /path/to/boost_1_55_0/stage/include''')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800144 opt.add_option('--boost-libs', type='string',
145 default='', dest='boost_libs',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800146 help='''path to the directory where the boost libs are,
147 e.g., path/to/boost_1_55_0/stage/lib''')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800148 opt.add_option('--boost-mt', action='store_true',
149 default=False, dest='boost_mt',
150 help='select multi-threaded libraries')
151 opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800152 help='''select libraries with tags (gd for debug, static is automatically added),
153 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500154 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800155 help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
156 opt.add_option('--boost-toolset', type='string',
157 default='', dest='boost_toolset',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800158 help='force a toolset e.g. msvc, vc90, \
159 gcc, mingw, mgw45 (default: auto)')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800160 py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
161 opt.add_option('--boost-python', type='string',
162 default=py_version, dest='boost_python',
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800163 help='select the lib python with this version \
164 (default: %s)' % py_version)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800165
166
167@conf
168def __boost_get_version_file(self, d):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800169 if not d:
170 return None
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800171 dnode = self.root.find_dir(d)
172 if dnode:
173 return dnode.find_node(BOOST_VERSION_FILE)
174 return None
175
176@conf
177def boost_get_version(self, d):
178 """silently retrieve the boost version number"""
179 node = self.__boost_get_version_file(d)
180 if node:
181 try:
182 txt = node.read()
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800183 except EnvironmentError:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500184 Logs.error('Could not read the file %r' % node.abspath())
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800185 else:
Davide Pesavento1bdef282014-04-08 20:59:50 +0200186 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800187 m1 = re_but1.search(txt)
Davide Pesavento1bdef282014-04-08 20:59:50 +0200188 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800189 m2 = re_but2.search(txt)
Alexander Afanasyeve1724c42014-02-26 22:00:54 -0800190 if m1 and m2:
191 return (m1.group(1), m2.group(1))
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500192 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800193
194@conf
195def boost_get_includes(self, *k, **kw):
196 includes = k and k[0] or kw.get('includes', None)
197 if includes and self.__boost_get_version_file(includes):
198 return includes
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800199 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800200 if self.__boost_get_version_file(d):
201 return d
202 if includes:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500203 self.end_msg('headers not found in %s' % includes, 'YELLOW')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800204 self.fatal('The configuration failed')
205 else:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500206 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800207 self.fatal('The configuration failed')
208
209
210@conf
211def boost_get_toolset(self, cc):
212 toolset = cc
213 if not cc:
214 build_platform = Utils.unversioned_sys_platform()
215 if build_platform in BOOST_TOOLSETS:
216 cc = build_platform
217 else:
218 cc = self.env.CXX_NAME
219 if cc in BOOST_TOOLSETS:
220 toolset = BOOST_TOOLSETS[cc]
221 return isinstance(toolset, str) and toolset or toolset(self.env)
222
223
224@conf
225def __boost_get_libs_path(self, *k, **kw):
226 ''' return the lib path and all the files in it '''
227 if 'files' in kw:
228 return self.root.find_dir('.'), Utils.to_list(kw['files'])
229 libs = k and k[0] or kw.get('libs', None)
230 if libs:
231 path = self.root.find_dir(libs)
232 files = path.ant_glob('*boost_*')
233 if not libs or not files:
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800234 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
235 if not d:
236 continue
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800237 path = self.root.find_dir(d)
238 if path:
239 files = path.ant_glob('*boost_*')
240 if files:
241 break
242 path = self.root.find_dir(d + '64')
243 if path:
244 files = path.ant_glob('*boost_*')
245 if files:
246 break
247 if not path:
248 if libs:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500249 self.end_msg('libs not found in %s' % libs, 'YELLOW')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800250 self.fatal('The configuration failed')
251 else:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500252 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800253 self.fatal('The configuration failed')
254
255 self.to_log('Found the boost path in %r with the libraries:' % path)
256 for x in files:
257 self.to_log(' %r' % x)
258 return path, files
259
260@conf
261def boost_get_libs(self, *k, **kw):
262 '''
263 return the lib path and the required libs
264 according to the parameters
265 '''
266 path, files = self.__boost_get_libs_path(**kw)
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800267 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800268 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800269 toolset_pat = '(-%s[0-9]{0,3})' % toolset
270 version = '-%s' % self.env.BOOST_VERSION
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800271
272 def find_lib(re_lib, files):
273 for file in files:
274 if re_lib.search(file.name):
275 self.to_log('Found boost lib %s' % file)
276 return file
277 return None
278
279 def format_lib_name(name):
280 if name.startswith('lib') and self.env.CC_NAME != 'msvc':
281 name = name[3:]
282 return name[:name.rfind('.')]
283
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800284 def match_libs(lib_names, is_static):
285 libs = []
286 lib_names = Utils.to_list(lib_names)
287 if not lib_names:
288 return libs
289 t = []
290 if kw.get('mt', False):
291 t.append('-mt')
292 if kw.get('abi', None):
293 t.append('%s%s' % (is_static and '-s' or '-', kw['abi']))
294 elif is_static:
295 t.append('-s')
296 tags_pat = t and ''.join(t) or ''
297 ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN
298 ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800299
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800300 for lib in lib_names:
301 if lib == 'python':
302 # for instance, with python='27',
303 # accepts '-py27', '-py2', '27' and '2'
304 # but will reject '-py3', '-py26', '26' and '3'
305 tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'])
306 else:
307 tags = tags_pat
308 # Trying libraries, from most strict match to least one
309 for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext),
310 'boost_%s%s%s%s$' % (lib, tags, version, ext),
311 # Give up trying to find the right version
312 'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext),
313 'boost_%s%s%s$' % (lib, tags, ext),
314 'boost_%s%s$' % (lib, ext),
315 'boost_%s' % lib]:
316 self.to_log('Trying pattern %s' % pattern)
317 file = find_lib(re.compile(pattern), files)
318 if file:
319 libs.append(format_lib_name(file.name))
320 break
321 else:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500322 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800323 self.fatal('The configuration failed')
324 return libs
325
326 return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800327
Alexander Afanasyev85093982016-03-08 14:03:54 -0800328@conf
329def _check_pthread_flag(self, *k, **kw):
330 '''
331 Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode
332
333 Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
334 boost/thread.hpp will trigger a #error if -pthread isn't used:
335 boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
336 is not turned on. Please set the correct command line options for
337 threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
338
339 Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4
340 '''
341
342 var = kw.get('uselib_store', 'BOOST')
343
344 self.start_msg('Checking the flags needed to use pthreads')
345
346 # The ordering *is* (sometimes) important. Some notes on the
347 # individual items follow:
348 # (none): in case threads are in libc; should be tried before -Kthread and
349 # other compiler flags to prevent continual compiler warnings
350 # -lpthreads: AIX (must check this before -lpthread)
351 # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
352 # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
353 # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
354 # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
355 # -pthreads: Solaris/GCC
356 # -mthreads: MinGW32/GCC, Lynx/GCC
357 # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
358 # doesn't hurt to check since this sometimes defines pthreads too;
359 # also defines -D_REENTRANT)
360 # ... -mt is also the pthreads flag for HP/aCC
361 # -lpthread: GNU Linux, etc.
362 # --thread-safe: KAI C++
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500363 if Utils.unversioned_sys_platform() == 'sunos':
Alexander Afanasyev85093982016-03-08 14:03:54 -0800364 # On Solaris (at least, for some versions), libc contains stubbed
365 # (non-functional) versions of the pthreads routines, so link-based
366 # tests will erroneously succeed. (We need to link with -pthreads/-mt/
367 # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
368 # a function called by this macro, so we could check for that, but
369 # who knows whether they'll stub that too in a future libc.) So,
370 # we'll just look for -pthreads and -lpthread first:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500371 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
Alexander Afanasyev85093982016-03-08 14:03:54 -0800372 else:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500373 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
374 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
Alexander Afanasyev85093982016-03-08 14:03:54 -0800375
376 for boost_pthread_flag in boost_pthread_flags:
377 try:
378 self.env.stash()
379 self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
380 self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500381 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
Alexander Afanasyev85093982016-03-08 14:03:54 -0800382 self.end_msg(boost_pthread_flag)
383 return
384 except self.errors.ConfigurationError:
385 self.env.revert()
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500386 self.end_msg('none')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800387
388@conf
389def check_boost(self, *k, **kw):
390 """
391 Initialize boost libraries to be used.
392
393 Keywords: you can pass the same parameters as with the command line (without "--boost-").
394 Note that the command line has the priority, and should preferably be used.
395 """
396 if not self.env['CXX']:
397 self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
398
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800399 params = {
400 'lib': k and k[0] or kw.get('lib', None),
401 'stlib': kw.get('stlib', None)
402 }
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800403 for key, value in self.options.__dict__.items():
404 if not key.startswith('boost_'):
405 continue
406 key = key[len('boost_'):]
407 params[key] = value and value or kw.get(key, '')
408
409 var = kw.get('uselib_store', 'BOOST')
410
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500411 if not self.env.DONE_FIND_BOOST_COMMON:
412 self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False)
413 if self.env.DPKG_ARCHITECTURE:
414 deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH'])
415 BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip())
Eric Newberryc14a8ac2018-04-05 16:46:51 -0700416
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500417 self.start_msg('Checking boost includes')
418 self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
419 versions = self.boost_get_version(inc)
420 self.env.BOOST_VERSION = versions[0]
421 self.env.BOOST_VERSION_NUMBER = int(versions[1])
422 self.end_msg('%d.%d.%d' % (int(versions[1]) / 100000,
423 int(versions[1]) / 100 % 1000,
424 int(versions[1]) % 100))
425 if Logs.verbose:
426 Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
427
428 self.env.DONE_FIND_BOOST_COMMON = True
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800429
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800430 if not params['lib'] and not params['stlib']:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800431 return
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800432 if 'static' in kw or 'static' in params:
433 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800434 self.start_msg('Checking boost libs')
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800435 path, libs, stlibs = self.boost_get_libs(**params)
436 self.env['LIBPATH_%s' % var] = [path]
437 self.env['STLIBPATH_%s' % var] = [path]
438 self.env['LIB_%s' % var] = libs
439 self.env['STLIB_%s' % var] = stlibs
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500440 self.end_msg(' '.join(libs + stlibs))
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800441 if Logs.verbose:
442 Logs.pprint('CYAN', ' path : %s' % path)
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800443 Logs.pprint('CYAN', ' shared libs : %s' % libs)
444 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800445
Alexander Afanasyev85093982016-03-08 14:03:54 -0800446 def has_shlib(lib):
447 return params['lib'] and lib in params['lib']
448 def has_stlib(lib):
449 return params['stlib'] and lib in params['stlib']
450 def has_lib(lib):
451 return has_shlib(lib) or has_stlib(lib)
452 if has_lib('thread'):
453 # not inside try_link to make check visible in the output
454 self._check_pthread_flag(k, kw)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800455
456 def try_link():
Alexander Afanasyev85093982016-03-08 14:03:54 -0800457 if has_lib('system'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800458 self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
Alexander Afanasyev85093982016-03-08 14:03:54 -0800459 if has_lib('thread'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800460 self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500461 if has_lib('log') or has_lib('log_setup'):
Alexander Afanasyev85093982016-03-08 14:03:54 -0800462 if not has_lib('thread'):
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800463 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500464 if has_shlib('log') or has_shlib('log_setup'):
Alexander Afanasyev85093982016-03-08 14:03:54 -0800465 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500466 if has_lib('log_setup'):
467 self.check_cxx(fragment=BOOST_LOG_SETUP_CODE, use=var, execute=False)
468 else:
469 self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800470
471 if params.get('linkage_autodetect', False):
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500472 self.start_msg('Attempting to detect boost linkage flags')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800473 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800474 if toolset in ('vc',):
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800475 # disable auto-linking feature, causing error LNK1181
476 # because the code wants to be linked against
477 self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
478
479 # if no dlls are present, we guess the .lib files are not stubs
480 has_dlls = False
481 for x in Utils.listdir(path):
482 if x.endswith(self.env.cxxshlib_PATTERN % ''):
483 has_dlls = True
484 break
485 if not has_dlls:
486 self.env['STLIBPATH_%s' % var] = [path]
487 self.env['STLIB_%s' % var] = libs
488 del self.env['LIB_%s' % var]
489 del self.env['LIBPATH_%s' % var]
490
491 # we attempt to play with some known-to-work CXXFLAGS combinations
492 for cxxflags in (['/MD', '/EHsc'], []):
493 self.env.stash()
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500494 self.env['CXXFLAGS_%s' % var] += cxxflags
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800495 try:
496 try_link()
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500497 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800498 exc = None
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800499 break
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800500 except Errors.ConfigurationError as e:
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800501 self.env.revert()
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800502 exc = e
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800503
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800504 if exc is not None:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500505 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 -0800506 self.fatal('The configuration failed')
507 else:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500508 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800509 self.fatal('The configuration failed')
510 else:
511 self.start_msg('Checking for boost linkage')
512 try:
513 try_link()
514 except Errors.ConfigurationError as e:
Davide Pesavento6ecc3f82019-02-17 22:23:08 -0500515 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
Alexander Afanasyev2aa39622014-01-22 11:51:11 -0800516 self.fatal('The configuration failed')
517 self.end_msg('ok')
Alexander Afanasyeve6f0e912016-02-25 23:42:36 -0800518
519
520@feature('cxx')
521@after_method('apply_link')
522def install_boost(self):
523 if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'):
524 return
525 install_boost.done = True
526 inst_to = getattr(self, 'install_path', '${BINDIR}')
527 for lib in self.env.LIB_BOOST:
528 try:
529 file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST)
530 self.bld.install_files(inst_to, self.bld.root.find_node(file))
531 except:
532 continue
533install_boost.done = False