blob: a6cdabef9c43dcb9e877830cda0e9e167d3496db [file] [log] [blame]
Alexander Afanasyev7eb59112014-07-02 14:21:11 -07001#!/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 Afanasyevf3192eb2016-12-19 17:11:20 -080033It can also provide default arguments to the --boost-mt command-line arguments.
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070034Everything 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 Afanasyevf3192eb2016-12-19 17:11:20 -080040 So before calling `conf.check_boost` you might want to disabling by adding
41 conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070042 Errors:
43 - boost might also be compiled with /MT, which links the runtime statically.
44 If you have problems with redefined symbols,
45 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 Afanasyevf3192eb2016-12-19 17:11:20 -080055from waflib.TaskGen import feature, after_method
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070056
Davide Pesavento15a74422022-08-19 15:48:45 -040057BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/homebrew/lib', '/opt/local/lib', '/sw/lib', '/lib']
58BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/homebrew/include', '/opt/local/include', '/sw/include']
Davide Pesaventoc47774f2019-11-09 17:25:09 -050059
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070060BOOST_VERSION_FILE = 'boost/version.hpp'
61BOOST_VERSION_CODE = '''
62#include <iostream>
63#include <boost/version.hpp>
64int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
65'''
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -080066
67BOOST_ERROR_CODE = '''
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070068#include <boost/system/error_code.hpp>
69int main() { boost::system::error_code c; }
70'''
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -080071
72PTHREAD_CODE = '''
73#include <pthread.h>
74static void* f(void*) { return 0; }
75int main() {
76 pthread_t th;
77 pthread_attr_t attr;
78 pthread_attr_init(&attr);
79 pthread_create(&th, &attr, &f, 0);
80 pthread_join(th, 0);
81 pthread_cleanup_push(0, 0);
82 pthread_cleanup_pop(0);
83 pthread_attr_destroy(&attr);
84}
85'''
86
Alexander Afanasyev7eb59112014-07-02 14:21:11 -070087BOOST_THREAD_CODE = '''
88#include <boost/thread.hpp>
89int main() { boost::thread t; }
90'''
91
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -080092BOOST_LOG_CODE = '''
93#include <boost/log/trivial.hpp>
Davide Pesaventoc47774f2019-11-09 17:25:09 -050094int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
95'''
96
97BOOST_LOG_SETUP_CODE = '''
98#include <boost/log/trivial.hpp>
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Pesaventoc47774f2019-11-09 17:25:09 -0500105 BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800106}
107'''
108
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700109# 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 Afanasyev7eb59112014-07-02 14:21:11 -0700140 opt.add_option('--boost-includes', type='string',
141 default='', dest='boost_includes',
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800142 help='''path to the directory where the boost includes are,
143 e.g., /path/to/boost_1_55_0/stage/include''')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700144 opt.add_option('--boost-libs', type='string',
145 default='', dest='boost_libs',
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800146 help='''path to the directory where the boost libs are,
147 e.g., path/to/boost_1_55_0/stage/lib''')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700148 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800152 help='''select libraries with tags (gd for debug, static is automatically added),
153 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500154 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700155 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800158 help='force a toolset e.g. msvc, vc90, \
159 gcc, mingw, mgw45 (default: auto)')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700160 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800163 help='select the lib python with this version \
164 (default: %s)' % py_version)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700165
166
167@conf
168def __boost_get_version_file(self, d):
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800169 if not d:
170 return None
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700171 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800183 except EnvironmentError:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500184 Logs.error('Could not read the file %r' % node.abspath())
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700185 else:
186 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
187 m1 = re_but1.search(txt)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700188 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
189 m2 = re_but2.search(txt)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700190 if m1 and m2:
191 return (m1.group(1), m2.group(1))
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500192 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700193
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 Afanasyevf3192eb2016-12-19 17:11:20 -0800199 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700200 if self.__boost_get_version_file(d):
201 return d
202 if includes:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500203 self.end_msg('headers not found in %s' % includes, 'YELLOW')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700204 self.fatal('The configuration failed')
205 else:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500206 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700207 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800234 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
235 if not d:
236 continue
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700237 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 Pesaventoc47774f2019-11-09 17:25:09 -0500249 self.end_msg('libs not found in %s' % libs, 'YELLOW')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700250 self.fatal('The configuration failed')
251 else:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500252 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700253 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 Afanasyevf3192eb2016-12-19 17:11:20 -0800267 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700268 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800269 toolset_pat = '(-%s[0-9]{0,3})' % toolset
270 version = '-%s' % self.env.BOOST_VERSION
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700271
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 Afanasyevf3192eb2016-12-19 17:11:20 -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 Afanasyev7eb59112014-07-02 14:21:11 -0700299
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Pesaventoc47774f2019-11-09 17:25:09 -0500322 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800323 self.fatal('The configuration failed')
324 return libs
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700325
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800326 return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
327
328@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 Pesaventoc47774f2019-11-09 17:25:09 -0500363 if Utils.unversioned_sys_platform() == 'sunos':
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Pesaventoc47774f2019-11-09 17:25:09 -0500371 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800372 else:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500373 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
374 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Pesaventoc47774f2019-11-09 17:25:09 -0500381 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800382 self.end_msg(boost_pthread_flag)
383 return
384 except self.errors.ConfigurationError:
385 self.env.revert()
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500386 self.end_msg('none')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700387
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 Afanasyevf3192eb2016-12-19 17:11:20 -0800399 params = {
400 'lib': k and k[0] or kw.get('lib', None),
401 'stlib': kw.get('stlib', None)
402 }
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700403 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 Pesaventoc47774f2019-11-09 17:25:09 -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 Newberrye87d8e22018-04-05 22:04:02 -0700416
Davide Pesaventoc47774f2019-11-09 17:25:09 -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 Afanasyev7eb59112014-07-02 14:21:11 -0700429
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800430 if not params['lib'] and not params['stlib']:
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700431 return
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800432 if 'static' in kw or 'static' in params:
433 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700434 self.start_msg('Checking boost libs')
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Pesaventoc47774f2019-11-09 17:25:09 -0500440 self.end_msg(' '.join(libs + stlibs))
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700441 if Logs.verbose:
442 Logs.pprint('CYAN', ' path : %s' % path)
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800443 Logs.pprint('CYAN', ' shared libs : %s' % libs)
444 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700445
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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 Afanasyev7eb59112014-07-02 14:21:11 -0700455
456 def try_link():
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800457 if has_lib('system'):
458 self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
459 if has_lib('thread'):
460 self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500461 if has_lib('log') or has_lib('log_setup'):
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800462 if not has_lib('thread'):
463 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500464 if has_shlib('log') or has_shlib('log_setup'):
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800465 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Davide Pesaventoc47774f2019-11-09 17:25:09 -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 Afanasyev7eb59112014-07-02 14:21:11 -0700470
471 if params.get('linkage_autodetect', False):
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500472 self.start_msg('Attempting to detect boost linkage flags')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700473 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800474 if toolset in ('vc',):
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700475 # 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 Pesaventoc47774f2019-11-09 17:25:09 -0500494 self.env['CXXFLAGS_%s' % var] += cxxflags
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700495 try:
496 try_link()
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500497 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800498 exc = None
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700499 break
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800500 except Errors.ConfigurationError as e:
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700501 self.env.revert()
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800502 exc = e
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700503
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -0800504 if exc is not None:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500505 self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc)
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700506 self.fatal('The configuration failed')
507 else:
Davide Pesaventoc47774f2019-11-09 17:25:09 -0500508 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700509 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 Pesaventoc47774f2019-11-09 17:25:09 -0500515 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
Alexander Afanasyev7eb59112014-07-02 14:21:11 -0700516 self.fatal('The configuration failed')
517 self.end_msg('ok')
Alexander Afanasyevf3192eb2016-12-19 17:11:20 -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