blob: 4eddec7a1120684fba63ffe440d52225d020391d [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
Eric Newberry25038f32018-04-05 21:57:30 -070057BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
Junxiao Shi7d054272016-08-04 17:00:41 +000058BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080059BOOST_VERSION_FILE = 'boost/version.hpp'
60BOOST_VERSION_CODE = '''
61#include <iostream>
62#include <boost/version.hpp>
Alexander Afanasyevdafdc372014-03-03 15:58:44 +000063int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080064'''
Junxiao Shi7d054272016-08-04 17:00:41 +000065
66BOOST_ERROR_CODE = '''
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070067#include <boost/system/error_code.hpp>
68int main() { boost::system::error_code c; }
69'''
Junxiao Shi7d054272016-08-04 17:00:41 +000070
71PTHREAD_CODE = '''
72#include <pthread.h>
73static void* f(void*) { return 0; }
74int main() {
75 pthread_t th;
76 pthread_attr_t attr;
77 pthread_attr_init(&attr);
78 pthread_create(&th, &attr, &f, 0);
79 pthread_join(th, 0);
80 pthread_cleanup_push(0, 0);
81 pthread_cleanup_pop(0);
82 pthread_attr_destroy(&attr);
83}
84'''
85
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070086BOOST_THREAD_CODE = '''
87#include <boost/thread.hpp>
88int main() { boost::thread t; }
89'''
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -080090
Junxiao Shi7d054272016-08-04 17:00:41 +000091BOOST_LOG_CODE = '''
92#include <boost/log/trivial.hpp>
93#include <boost/log/utility/setup/console.hpp>
94#include <boost/log/utility/setup/common_attributes.hpp>
95int main() {
96 using namespace boost::log;
97 add_common_attributes();
98 add_console_log(std::clog, keywords::format = "%Message%");
99 BOOST_LOG_TRIVIAL(debug) << "log is working" << std::endl;
100}
101'''
102
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800103# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
104PLATFORM = Utils.unversioned_sys_platform()
105detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
106detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
107detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
108BOOST_TOOLSETS = {
109 'borland': 'bcb',
110 'clang': detect_clang,
111 'como': 'como',
112 'cw': 'cw',
113 'darwin': 'xgcc',
114 'edg': 'edg',
115 'g++': detect_mingw,
116 'gcc': detect_mingw,
117 'icpc': detect_intel,
118 'intel': detect_intel,
119 'kcc': 'kcc',
120 'kylix': 'bck',
121 'mipspro': 'mp',
122 'mingw': 'mgw',
123 'msvc': 'vc',
124 'qcc': 'qcc',
125 'sun': 'sw',
126 'sunc++': 'sw',
127 'tru64cxx': 'tru',
128 'vacpp': 'xlc'
129}
130
131
132def options(opt):
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000133 opt = opt.add_option_group('Boost Options')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800134 opt.add_option('--boost-includes', type='string',
135 default='', dest='boost_includes',
Junxiao Shi7d054272016-08-04 17:00:41 +0000136 help='''path to the directory where the boost includes are,
137 e.g., /path/to/boost_1_55_0/stage/include''')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800138 opt.add_option('--boost-libs', type='string',
139 default='', dest='boost_libs',
Junxiao Shi7d054272016-08-04 17:00:41 +0000140 help='''path to the directory where the boost libs are,
141 e.g., path/to/boost_1_55_0/stage/lib''')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800142 opt.add_option('--boost-mt', action='store_true',
143 default=False, dest='boost_mt',
144 help='select multi-threaded libraries')
145 opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
Junxiao Shi7d054272016-08-04 17:00:41 +0000146 help='''select libraries with tags (gd for debug, static is automatically added),
147 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesaventofd674012019-02-06 02:00:12 -0500148 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800149 help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
150 opt.add_option('--boost-toolset', type='string',
151 default='', dest='boost_toolset',
Junxiao Shi7d054272016-08-04 17:00:41 +0000152 help='force a toolset e.g. msvc, vc90, \
153 gcc, mingw, mgw45 (default: auto)')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800154 py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
155 opt.add_option('--boost-python', type='string',
156 default=py_version, dest='boost_python',
Junxiao Shi7d054272016-08-04 17:00:41 +0000157 help='select the lib python with this version \
158 (default: %s)' % py_version)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800159
160
161@conf
162def __boost_get_version_file(self, d):
Junxiao Shi7d054272016-08-04 17:00:41 +0000163 if not d:
164 return None
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800165 dnode = self.root.find_dir(d)
166 if dnode:
167 return dnode.find_node(BOOST_VERSION_FILE)
168 return None
169
170@conf
171def boost_get_version(self, d):
172 """silently retrieve the boost version number"""
173 node = self.__boost_get_version_file(d)
174 if node:
175 try:
176 txt = node.read()
Junxiao Shi7d054272016-08-04 17:00:41 +0000177 except EnvironmentError:
Davide Pesaventofd674012019-02-06 02:00:12 -0500178 Logs.error('Could not read the file %r' % node.abspath())
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800179 else:
Junxiao Shi7d054272016-08-04 17:00:41 +0000180 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000181 m1 = re_but1.search(txt)
Junxiao Shi7d054272016-08-04 17:00:41 +0000182 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000183 m2 = re_but2.search(txt)
Alexander Afanasyevdafdc372014-03-03 15:58:44 +0000184 if m1 and m2:
185 return (m1.group(1), m2.group(1))
Davide Pesaventofd674012019-02-06 02:00:12 -0500186 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800187
188@conf
189def boost_get_includes(self, *k, **kw):
190 includes = k and k[0] or kw.get('includes', None)
191 if includes and self.__boost_get_version_file(includes):
192 return includes
Junxiao Shi7d054272016-08-04 17:00:41 +0000193 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800194 if self.__boost_get_version_file(d):
195 return d
196 if includes:
Davide Pesaventofd674012019-02-06 02:00:12 -0500197 self.end_msg('headers not found in %s' % includes, 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800198 self.fatal('The configuration failed')
199 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500200 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800201 self.fatal('The configuration failed')
202
203
204@conf
205def boost_get_toolset(self, cc):
206 toolset = cc
207 if not cc:
208 build_platform = Utils.unversioned_sys_platform()
209 if build_platform in BOOST_TOOLSETS:
210 cc = build_platform
211 else:
212 cc = self.env.CXX_NAME
213 if cc in BOOST_TOOLSETS:
214 toolset = BOOST_TOOLSETS[cc]
215 return isinstance(toolset, str) and toolset or toolset(self.env)
216
217
218@conf
219def __boost_get_libs_path(self, *k, **kw):
220 ''' return the lib path and all the files in it '''
221 if 'files' in kw:
222 return self.root.find_dir('.'), Utils.to_list(kw['files'])
223 libs = k and k[0] or kw.get('libs', None)
224 if libs:
225 path = self.root.find_dir(libs)
226 files = path.ant_glob('*boost_*')
227 if not libs or not files:
Junxiao Shi7d054272016-08-04 17:00:41 +0000228 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
229 if not d:
230 continue
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800231 path = self.root.find_dir(d)
232 if path:
233 files = path.ant_glob('*boost_*')
234 if files:
235 break
236 path = self.root.find_dir(d + '64')
237 if path:
238 files = path.ant_glob('*boost_*')
239 if files:
240 break
241 if not path:
242 if libs:
Davide Pesaventofd674012019-02-06 02:00:12 -0500243 self.end_msg('libs not found in %s' % libs, 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800244 self.fatal('The configuration failed')
245 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500246 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800247 self.fatal('The configuration failed')
248
249 self.to_log('Found the boost path in %r with the libraries:' % path)
250 for x in files:
251 self.to_log(' %r' % x)
252 return path, files
253
254@conf
255def boost_get_libs(self, *k, **kw):
256 '''
257 return the lib path and the required libs
258 according to the parameters
259 '''
260 path, files = self.__boost_get_libs_path(**kw)
Junxiao Shi7d054272016-08-04 17:00:41 +0000261 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800262 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Junxiao Shi7d054272016-08-04 17:00:41 +0000263 toolset_pat = '(-%s[0-9]{0,3})' % toolset
264 version = '-%s' % self.env.BOOST_VERSION
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800265
266 def find_lib(re_lib, files):
267 for file in files:
268 if re_lib.search(file.name):
269 self.to_log('Found boost lib %s' % file)
270 return file
271 return None
272
273 def format_lib_name(name):
274 if name.startswith('lib') and self.env.CC_NAME != 'msvc':
275 name = name[3:]
276 return name[:name.rfind('.')]
277
Junxiao Shi7d054272016-08-04 17:00:41 +0000278 def match_libs(lib_names, is_static):
279 libs = []
280 lib_names = Utils.to_list(lib_names)
281 if not lib_names:
282 return libs
283 t = []
284 if kw.get('mt', False):
285 t.append('-mt')
286 if kw.get('abi', None):
287 t.append('%s%s' % (is_static and '-s' or '-', kw['abi']))
288 elif is_static:
289 t.append('-s')
290 tags_pat = t and ''.join(t) or ''
291 ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN
292 ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800293
Junxiao Shi7d054272016-08-04 17:00:41 +0000294 for lib in lib_names:
295 if lib == 'python':
296 # for instance, with python='27',
297 # accepts '-py27', '-py2', '27' and '2'
298 # but will reject '-py3', '-py26', '26' and '3'
299 tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'])
300 else:
301 tags = tags_pat
302 # Trying libraries, from most strict match to least one
303 for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext),
304 'boost_%s%s%s%s$' % (lib, tags, version, ext),
305 # Give up trying to find the right version
306 'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext),
307 'boost_%s%s%s$' % (lib, tags, ext),
308 'boost_%s%s$' % (lib, ext),
309 'boost_%s' % lib]:
310 self.to_log('Trying pattern %s' % pattern)
311 file = find_lib(re.compile(pattern), files)
312 if file:
313 libs.append(format_lib_name(file.name))
314 break
315 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500316 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
Junxiao Shi7d054272016-08-04 17:00:41 +0000317 self.fatal('The configuration failed')
318 return libs
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800319
Junxiao Shi7d054272016-08-04 17:00:41 +0000320 return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
321
322@conf
323def _check_pthread_flag(self, *k, **kw):
324 '''
325 Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode
326
327 Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3,
328 boost/thread.hpp will trigger a #error if -pthread isn't used:
329 boost/config/requires_threads.hpp:47:5: #error "Compiler threading support
330 is not turned on. Please set the correct command line options for
331 threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)"
332
333 Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4
334 '''
335
336 var = kw.get('uselib_store', 'BOOST')
337
338 self.start_msg('Checking the flags needed to use pthreads')
339
340 # The ordering *is* (sometimes) important. Some notes on the
341 # individual items follow:
342 # (none): in case threads are in libc; should be tried before -Kthread and
343 # other compiler flags to prevent continual compiler warnings
344 # -lpthreads: AIX (must check this before -lpthread)
345 # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
346 # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
347 # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
348 # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads)
349 # -pthreads: Solaris/GCC
350 # -mthreads: MinGW32/GCC, Lynx/GCC
351 # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
352 # doesn't hurt to check since this sometimes defines pthreads too;
353 # also defines -D_REENTRANT)
354 # ... -mt is also the pthreads flag for HP/aCC
355 # -lpthread: GNU Linux, etc.
356 # --thread-safe: KAI C++
Davide Pesaventofd674012019-02-06 02:00:12 -0500357 if Utils.unversioned_sys_platform() == 'sunos':
Junxiao Shi7d054272016-08-04 17:00:41 +0000358 # On Solaris (at least, for some versions), libc contains stubbed
359 # (non-functional) versions of the pthreads routines, so link-based
360 # tests will erroneously succeed. (We need to link with -pthreads/-mt/
361 # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
362 # a function called by this macro, so we could check for that, but
363 # who knows whether they'll stub that too in a future libc.) So,
364 # we'll just look for -pthreads and -lpthread first:
Davide Pesaventofd674012019-02-06 02:00:12 -0500365 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
Junxiao Shi7d054272016-08-04 17:00:41 +0000366 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500367 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
368 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
Junxiao Shi7d054272016-08-04 17:00:41 +0000369
370 for boost_pthread_flag in boost_pthread_flags:
371 try:
372 self.env.stash()
373 self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag]
374 self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag]
Davide Pesaventofd674012019-02-06 02:00:12 -0500375 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
Junxiao Shi7d054272016-08-04 17:00:41 +0000376 self.end_msg(boost_pthread_flag)
377 return
378 except self.errors.ConfigurationError:
379 self.env.revert()
Davide Pesaventofd674012019-02-06 02:00:12 -0500380 self.end_msg('none')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800381
382@conf
383def check_boost(self, *k, **kw):
384 """
385 Initialize boost libraries to be used.
386
387 Keywords: you can pass the same parameters as with the command line (without "--boost-").
388 Note that the command line has the priority, and should preferably be used.
389 """
390 if not self.env['CXX']:
391 self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
392
Junxiao Shi7d054272016-08-04 17:00:41 +0000393 params = {
394 'lib': k and k[0] or kw.get('lib', None),
395 'stlib': kw.get('stlib', None)
396 }
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800397 for key, value in self.options.__dict__.items():
398 if not key.startswith('boost_'):
399 continue
400 key = key[len('boost_'):]
401 params[key] = value and value or kw.get(key, '')
402
403 var = kw.get('uselib_store', 'BOOST')
404
Davide Pesaventofd674012019-02-06 02:00:12 -0500405 if not self.env.DONE_FIND_BOOST_COMMON:
406 self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False)
407 if self.env.DPKG_ARCHITECTURE:
408 deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH'])
409 BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip())
Eric Newberry25038f32018-04-05 21:57:30 -0700410
Davide Pesaventofd674012019-02-06 02:00:12 -0500411 self.start_msg('Checking boost includes')
412 self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
413 versions = self.boost_get_version(inc)
414 self.env.BOOST_VERSION = versions[0]
415 self.env.BOOST_VERSION_NUMBER = int(versions[1])
416 self.end_msg('%d.%d.%d' % (int(versions[1]) / 100000,
417 int(versions[1]) / 100 % 1000,
418 int(versions[1]) % 100))
419 if Logs.verbose:
420 Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var])
421
422 self.env.DONE_FIND_BOOST_COMMON = True
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800423
Junxiao Shi7d054272016-08-04 17:00:41 +0000424 if not params['lib'] and not params['stlib']:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800425 return
Junxiao Shi7d054272016-08-04 17:00:41 +0000426 if 'static' in kw or 'static' in params:
427 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800428 self.start_msg('Checking boost libs')
Junxiao Shi7d054272016-08-04 17:00:41 +0000429 path, libs, stlibs = self.boost_get_libs(**params)
430 self.env['LIBPATH_%s' % var] = [path]
431 self.env['STLIBPATH_%s' % var] = [path]
432 self.env['LIB_%s' % var] = libs
433 self.env['STLIB_%s' % var] = stlibs
Davide Pesaventofd674012019-02-06 02:00:12 -0500434 self.end_msg(' '.join(libs + stlibs))
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800435 if Logs.verbose:
436 Logs.pprint('CYAN', ' path : %s' % path)
Junxiao Shi7d054272016-08-04 17:00:41 +0000437 Logs.pprint('CYAN', ' shared libs : %s' % libs)
438 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800439
Junxiao Shi7d054272016-08-04 17:00:41 +0000440 def has_shlib(lib):
441 return params['lib'] and lib in params['lib']
442 def has_stlib(lib):
443 return params['stlib'] and lib in params['stlib']
444 def has_lib(lib):
445 return has_shlib(lib) or has_stlib(lib)
446 if has_lib('thread'):
447 # not inside try_link to make check visible in the output
448 self._check_pthread_flag(k, kw)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800449
450 def try_link():
Junxiao Shi7d054272016-08-04 17:00:41 +0000451 if has_lib('system'):
452 self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
453 if has_lib('thread'):
454 self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
455 if has_lib('log'):
456 if not has_lib('thread'):
457 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
458 if has_shlib('log'):
459 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
460 self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False)
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800461
462 if params.get('linkage_autodetect', False):
Davide Pesaventofd674012019-02-06 02:00:12 -0500463 self.start_msg('Attempting to detect boost linkage flags')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800464 toolset = self.boost_get_toolset(kw.get('toolset', ''))
Junxiao Shi7d054272016-08-04 17:00:41 +0000465 if toolset in ('vc',):
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800466 # disable auto-linking feature, causing error LNK1181
467 # because the code wants to be linked against
468 self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
469
470 # if no dlls are present, we guess the .lib files are not stubs
471 has_dlls = False
472 for x in Utils.listdir(path):
473 if x.endswith(self.env.cxxshlib_PATTERN % ''):
474 has_dlls = True
475 break
476 if not has_dlls:
477 self.env['STLIBPATH_%s' % var] = [path]
478 self.env['STLIB_%s' % var] = libs
479 del self.env['LIB_%s' % var]
480 del self.env['LIBPATH_%s' % var]
481
482 # we attempt to play with some known-to-work CXXFLAGS combinations
483 for cxxflags in (['/MD', '/EHsc'], []):
484 self.env.stash()
Davide Pesaventofd674012019-02-06 02:00:12 -0500485 self.env['CXXFLAGS_%s' % var] += cxxflags
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800486 try:
487 try_link()
Davide Pesaventofd674012019-02-06 02:00:12 -0500488 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
Junxiao Shi7d054272016-08-04 17:00:41 +0000489 exc = None
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800490 break
Junxiao Shi7d054272016-08-04 17:00:41 +0000491 except Errors.ConfigurationError as e:
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800492 self.env.revert()
Junxiao Shi7d054272016-08-04 17:00:41 +0000493 exc = e
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800494
Junxiao Shi7d054272016-08-04 17:00:41 +0000495 if exc is not None:
Davide Pesaventofd674012019-02-06 02:00:12 -0500496 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 -0800497 self.fatal('The configuration failed')
498 else:
Davide Pesaventofd674012019-02-06 02:00:12 -0500499 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800500 self.fatal('The configuration failed')
501 else:
502 self.start_msg('Checking for boost linkage')
503 try:
504 try_link()
505 except Errors.ConfigurationError as e:
Davide Pesaventofd674012019-02-06 02:00:12 -0500506 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
Alexander Afanasyeva1ae0a12014-01-28 15:21:02 -0800507 self.fatal('The configuration failed')
508 self.end_msg('ok')
Junxiao Shi7d054272016-08-04 17:00:41 +0000509
510
511@feature('cxx')
512@after_method('apply_link')
513def install_boost(self):
514 if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'):
515 return
516 install_boost.done = True
517 inst_to = getattr(self, 'install_path', '${BINDIR}')
518 for lib in self.env.LIB_BOOST:
519 try:
520 file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST)
521 self.bld.install_files(inst_to, self.bld.root.find_node(file))
522 except:
523 continue
524install_boost.done = False