blob: a6cdabef9c43dcb9e877830cda0e9e167d3496db [file] [log] [blame]
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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.
Junxiao Shi7d054272016-08-04 17:00:41 +000033It can also provide default arguments to the --boost-mt command-line arguments.
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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
Junxiao Shi7d054272016-08-04 17:00:41 +000040 So before calling `conf.check_boost` you might want to disabling by adding
41 conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
Alexander Afanasyevdafdc372014-03-03 15:58:44 +000042 Errors:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080043 - boost might also be compiled with /MT, which links the runtime statically.
Alexander Afanasyevdafdc372014-03-03 15:58:44 +000044 If you have problems with redefined symbols,
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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
Junxiao Shi7d054272016-08-04 17:00:41 +000055from waflib.TaskGen import feature, after_method
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080056
Davide Pesaventof6625002022-07-31 17:15:02 -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 Pesavento77f1c762019-02-19 03:20:49 -050059
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080060BOOST_VERSION_FILE = 'boost/version.hpp'
61BOOST_VERSION_CODE = '''
62#include <iostream>
63#include <boost/version.hpp>
Alexander Afanasyevdafdc372014-03-03 15:58:44 +000064int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080065'''
Junxiao Shi7d054272016-08-04 17:00:41 +000066
67BOOST_ERROR_CODE = '''
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070068#include <boost/system/error_code.hpp>
69int main() { boost::system::error_code c; }
70'''
Junxiao Shi7d054272016-08-04 17:00:41 +000071
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 Afanasyevb78bc4d2014-04-09 21:20:52 -070087BOOST_THREAD_CODE = '''
88#include <boost/thread.hpp>
89int main() { boost::thread t; }
90'''
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080091
Junxiao Shi7d054272016-08-04 17:00:41 +000092BOOST_LOG_CODE = '''
93#include <boost/log/trivial.hpp>
Davide Pesavento77f1c762019-02-19 03:20:49 -050094int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
95'''
96
97BOOST_LOG_SETUP_CODE = '''
98#include <boost/log/trivial.hpp>
Junxiao Shi7d054272016-08-04 17:00:41 +000099#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 Pesavento77f1c762019-02-19 03:20:49 -0500105 BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
Junxiao Shi7d054272016-08-04 17:00:41 +0000106}
107'''
108
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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):
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000139 opt = opt.add_option_group('Boost Options')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800140 opt.add_option('--boost-includes', type='string',
141 default='', dest='boost_includes',
Junxiao Shi7d054272016-08-04 17:00:41 +0000142 help='''path to the directory where the boost includes are,
143 e.g., /path/to/boost_1_55_0/stage/include''')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800144 opt.add_option('--boost-libs', type='string',
145 default='', dest='boost_libs',
Junxiao Shi7d054272016-08-04 17:00:41 +0000146 help='''path to the directory where the boost libs are,
147 e.g., path/to/boost_1_55_0/stage/lib''')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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',
Junxiao Shi7d054272016-08-04 17:00:41 +0000152 help='''select libraries with tags (gd for debug, static is automatically added),
153 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesaventofd674012019-02-06 02:00:12 -0500154 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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',
Junxiao Shi7d054272016-08-04 17:00:41 +0000158 help='force a toolset e.g. msvc, vc90, \
159 gcc, mingw, mgw45 (default: auto)')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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',
Junxiao Shi7d054272016-08-04 17:00:41 +0000163 help='select the lib python with this version \
164 (default: %s)' % py_version)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800165
166
167@conf
168def __boost_get_version_file(self, d):
Junxiao Shi7d054272016-08-04 17:00:41 +0000169 if not d:
170 return None
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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()
Junxiao Shi7d054272016-08-04 17:00:41 +0000183 except EnvironmentError:
Davide Pesaventofd674012019-02-06 02:00:12 -0500184 Logs.error('Could not read the file %r' % node.abspath())
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800185 else:
Junxiao Shi7d054272016-08-04 17:00:41 +0000186 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000187 m1 = re_but1.search(txt)
Junxiao Shi7d054272016-08-04 17:00:41 +0000188 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000189 m2 = re_but2.search(txt)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000190 if m1 and m2:
191 return (m1.group(1), m2.group(1))
Davide Pesaventofd674012019-02-06 02:00:12 -0500192 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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
Junxiao Shi7d054272016-08-04 17:00:41 +0000199 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800200 if self.__boost_get_version_file(d):
201 return d
202 if includes:
Davide Pesaventofd674012019-02-06 02:00:12 -0500203 self.end_msg('headers not found in %s' % includes, 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800204 self.fatal('The configuration failed')
205 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500206 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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:
Junxiao Shi7d054272016-08-04 17:00:41 +0000234 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
235 if not d:
236 continue
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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 Pesaventofd674012019-02-06 02:00:12 -0500249 self.end_msg('libs not found in %s' % libs, 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800250 self.fatal('The configuration failed')
251 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500252 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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)
Junxiao Shi7d054272016-08-04 17:00:41 +0000267 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800268 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Junxiao Shi7d054272016-08-04 17:00:41 +0000269 toolset_pat = '(-%s[0-9]{0,3})' % toolset
270 version = '-%s' % self.env.BOOST_VERSION
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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
Junxiao Shi7d054272016-08-04 17:00:41 +0000284 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 Afanasyeva1ae0a12014-01-28 15:21:02 -0800299
Junxiao Shi7d054272016-08-04 17:00:41 +0000300 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 Pesaventofd674012019-02-06 02:00:12 -0500322 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
Junxiao Shi7d054272016-08-04 17:00:41 +0000323 self.fatal('The configuration failed')
324 return libs
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800325
Junxiao Shi7d054272016-08-04 17:00:41 +0000326 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 Pesaventofd674012019-02-06 02:00:12 -0500363 if Utils.unversioned_sys_platform() == 'sunos':
Junxiao Shi7d054272016-08-04 17:00:41 +0000364 # 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 Pesaventofd674012019-02-06 02:00:12 -0500371 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
Junxiao Shi7d054272016-08-04 17:00:41 +0000372 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500373 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
374 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
Junxiao Shi7d054272016-08-04 17:00:41 +0000375
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 Pesaventofd674012019-02-06 02:00:12 -0500381 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
Junxiao Shi7d054272016-08-04 17:00:41 +0000382 self.end_msg(boost_pthread_flag)
383 return
384 except self.errors.ConfigurationError:
385 self.env.revert()
Davide Pesaventofd674012019-02-06 02:00:12 -0500386 self.end_msg('none')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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
Junxiao Shi7d054272016-08-04 17:00:41 +0000399 params = {
400 'lib': k and k[0] or kw.get('lib', None),
401 'stlib': kw.get('stlib', None)
402 }
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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 Pesaventofd674012019-02-06 02:00:12 -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 Newberry25038f32018-04-05 21:57:30 -0700416
Davide Pesaventofd674012019-02-06 02:00:12 -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 Afanasyeva1ae0a12014-01-28 15:21:02 -0800429
Junxiao Shi7d054272016-08-04 17:00:41 +0000430 if not params['lib'] and not params['stlib']:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800431 return
Junxiao Shi7d054272016-08-04 17:00:41 +0000432 if 'static' in kw or 'static' in params:
433 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800434 self.start_msg('Checking boost libs')
Junxiao Shi7d054272016-08-04 17:00:41 +0000435 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 Pesaventofd674012019-02-06 02:00:12 -0500440 self.end_msg(' '.join(libs + stlibs))
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800441 if Logs.verbose:
442 Logs.pprint('CYAN', ' path : %s' % path)
Junxiao Shi7d054272016-08-04 17:00:41 +0000443 Logs.pprint('CYAN', ' shared libs : %s' % libs)
444 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800445
Junxiao Shi7d054272016-08-04 17:00:41 +0000446 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 Afanasyeva1ae0a12014-01-28 15:21:02 -0800455
456 def try_link():
Junxiao Shi7d054272016-08-04 17:00:41 +0000457 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 Pesavento77f1c762019-02-19 03:20:49 -0500461 if has_lib('log') or has_lib('log_setup'):
Junxiao Shi7d054272016-08-04 17:00:41 +0000462 if not has_lib('thread'):
463 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Davide Pesavento77f1c762019-02-19 03:20:49 -0500464 if has_shlib('log') or has_shlib('log_setup'):
Junxiao Shi7d054272016-08-04 17:00:41 +0000465 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Davide Pesavento77f1c762019-02-19 03:20:49 -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 Afanasyeva1ae0a12014-01-28 15:21:02 -0800470
471 if params.get('linkage_autodetect', False):
Davide Pesaventofd674012019-02-06 02:00:12 -0500472 self.start_msg('Attempting to detect boost linkage flags')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800473 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Junxiao Shi7d054272016-08-04 17:00:41 +0000474 if toolset in ('vc',):
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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 Pesaventofd674012019-02-06 02:00:12 -0500494 self.env['CXXFLAGS_%s' % var] += cxxflags
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800495 try:
496 try_link()
Davide Pesaventofd674012019-02-06 02:00:12 -0500497 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
Junxiao Shi7d054272016-08-04 17:00:41 +0000498 exc = None
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800499 break
Junxiao Shi7d054272016-08-04 17:00:41 +0000500 except Errors.ConfigurationError as e:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800501 self.env.revert()
Junxiao Shi7d054272016-08-04 17:00:41 +0000502 exc = e
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800503
Junxiao Shi7d054272016-08-04 17:00:41 +0000504 if exc is not None:
Davide Pesaventofd674012019-02-06 02:00:12 -0500505 self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800506 self.fatal('The configuration failed')
507 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500508 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -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 Pesaventofd674012019-02-06 02:00:12 -0500515 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800516 self.fatal('The configuration failed')
517 self.end_msg('ok')
Junxiao Shi7d054272016-08-04 17:00:41 +0000518
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