blob: a6cdabef9c43dcb9e877830cda0e9e167d3496db [file] [log] [blame]
akmhoquec52a46c2014-02-17 21:13:16 -06001#!/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.
dmcoomescf8d0ed2017-02-21 11:39:01 -060033It can also provide default arguments to the --boost-mt command-line arguments.
akmhoquec52a46c2014-02-17 21:13:16 -060034Everything 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
dmcoomescf8d0ed2017-02-21 11:39:01 -060040 So before calling `conf.check_boost` you might want to disabling by adding
41 conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
akmhoqueeb764c52014-03-11 16:01:09 -050042 Errors:
akmhoquec52a46c2014-02-17 21:13:16 -060043 - boost might also be compiled with /MT, which links the runtime statically.
akmhoqueeb764c52014-03-11 16:01:09 -050044 If you have problems with redefined symbols,
akmhoquec52a46c2014-02-17 21:13:16 -060045 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
dmcoomescf8d0ed2017-02-21 11:39:01 -060055from waflib.TaskGen import feature, after_method
akmhoquec52a46c2014-02-17 21:13:16 -060056
Davide Pesaventoede59632022-08-26 20:35:44 -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 Pesaventof75bfda2019-11-10 18:34:13 -050059
akmhoquec52a46c2014-02-17 21:13:16 -060060BOOST_VERSION_FILE = 'boost/version.hpp'
61BOOST_VERSION_CODE = '''
62#include <iostream>
63#include <boost/version.hpp>
akmhoqueeb764c52014-03-11 16:01:09 -050064int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; }
akmhoquec52a46c2014-02-17 21:13:16 -060065'''
dmcoomescf8d0ed2017-02-21 11:39:01 -060066
67BOOST_ERROR_CODE = '''
Yingdi Yu40cd1c32014-04-17 15:02:17 -070068#include <boost/system/error_code.hpp>
69int main() { boost::system::error_code c; }
70'''
dmcoomescf8d0ed2017-02-21 11:39:01 -060071
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
Yingdi Yu40cd1c32014-04-17 15:02:17 -070087BOOST_THREAD_CODE = '''
88#include <boost/thread.hpp>
89int main() { boost::thread t; }
90'''
akmhoquec52a46c2014-02-17 21:13:16 -060091
dmcoomescf8d0ed2017-02-21 11:39:01 -060092BOOST_LOG_CODE = '''
93#include <boost/log/trivial.hpp>
Davide Pesaventof75bfda2019-11-10 18:34:13 -050094int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
95'''
96
97BOOST_LOG_SETUP_CODE = '''
98#include <boost/log/trivial.hpp>
dmcoomescf8d0ed2017-02-21 11:39:01 -060099#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 Pesaventof75bfda2019-11-10 18:34:13 -0500105 BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
dmcoomescf8d0ed2017-02-21 11:39:01 -0600106}
107'''
108
akmhoquec52a46c2014-02-17 21:13:16 -0600109# 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):
akmhoqueeb764c52014-03-11 16:01:09 -0500139 opt = opt.add_option_group('Boost Options')
akmhoquec52a46c2014-02-17 21:13:16 -0600140 opt.add_option('--boost-includes', type='string',
141 default='', dest='boost_includes',
dmcoomescf8d0ed2017-02-21 11:39:01 -0600142 help='''path to the directory where the boost includes are,
143 e.g., /path/to/boost_1_55_0/stage/include''')
akmhoquec52a46c2014-02-17 21:13:16 -0600144 opt.add_option('--boost-libs', type='string',
145 default='', dest='boost_libs',
dmcoomescf8d0ed2017-02-21 11:39:01 -0600146 help='''path to the directory where the boost libs are,
147 e.g., path/to/boost_1_55_0/stage/lib''')
akmhoquec52a46c2014-02-17 21:13:16 -0600148 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',
dmcoomescf8d0ed2017-02-21 11:39:01 -0600152 help='''select libraries with tags (gd for debug, static is automatically added),
153 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500154 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
akmhoquec52a46c2014-02-17 21:13:16 -0600155 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',
dmcoomescf8d0ed2017-02-21 11:39:01 -0600158 help='force a toolset e.g. msvc, vc90, \
159 gcc, mingw, mgw45 (default: auto)')
akmhoquec52a46c2014-02-17 21:13:16 -0600160 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',
dmcoomescf8d0ed2017-02-21 11:39:01 -0600163 help='select the lib python with this version \
164 (default: %s)' % py_version)
akmhoquec52a46c2014-02-17 21:13:16 -0600165
166
167@conf
168def __boost_get_version_file(self, d):
dmcoomescf8d0ed2017-02-21 11:39:01 -0600169 if not d:
170 return None
akmhoquec52a46c2014-02-17 21:13:16 -0600171 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()
dmcoomescf8d0ed2017-02-21 11:39:01 -0600183 except EnvironmentError:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500184 Logs.error('Could not read the file %r' % node.abspath())
akmhoquec52a46c2014-02-17 21:13:16 -0600185 else:
Yingdi Yu40cd1c32014-04-17 15:02:17 -0700186 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
akmhoqueeb764c52014-03-11 16:01:09 -0500187 m1 = re_but1.search(txt)
Yingdi Yu40cd1c32014-04-17 15:02:17 -0700188 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
akmhoqueeb764c52014-03-11 16:01:09 -0500189 m2 = re_but2.search(txt)
akmhoqueeb764c52014-03-11 16:01:09 -0500190 if m1 and m2:
191 return (m1.group(1), m2.group(1))
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500192 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
akmhoquec52a46c2014-02-17 21:13:16 -0600193
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
dmcoomescf8d0ed2017-02-21 11:39:01 -0600199 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
akmhoquec52a46c2014-02-17 21:13:16 -0600200 if self.__boost_get_version_file(d):
201 return d
202 if includes:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500203 self.end_msg('headers not found in %s' % includes, 'YELLOW')
akmhoquec52a46c2014-02-17 21:13:16 -0600204 self.fatal('The configuration failed')
205 else:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500206 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
akmhoquec52a46c2014-02-17 21:13:16 -0600207 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:
dmcoomescf8d0ed2017-02-21 11:39:01 -0600234 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
235 if not d:
236 continue
akmhoquec52a46c2014-02-17 21:13:16 -0600237 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 Pesaventof75bfda2019-11-10 18:34:13 -0500249 self.end_msg('libs not found in %s' % libs, 'YELLOW')
akmhoquec52a46c2014-02-17 21:13:16 -0600250 self.fatal('The configuration failed')
251 else:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500252 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
akmhoquec52a46c2014-02-17 21:13:16 -0600253 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)
dmcoomescf8d0ed2017-02-21 11:39:01 -0600267 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
akmhoquec52a46c2014-02-17 21:13:16 -0600268 toolset = self.boost_get_toolset(kw.get('toolset', ''))
dmcoomescf8d0ed2017-02-21 11:39:01 -0600269 toolset_pat = '(-%s[0-9]{0,3})' % toolset
270 version = '-%s' % self.env.BOOST_VERSION
akmhoquec52a46c2014-02-17 21:13:16 -0600271
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
dmcoomescf8d0ed2017-02-21 11:39:01 -0600284 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
akmhoquec52a46c2014-02-17 21:13:16 -0600299
dmcoomescf8d0ed2017-02-21 11:39:01 -0600300 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 Pesaventof75bfda2019-11-10 18:34:13 -0500322 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
dmcoomescf8d0ed2017-02-21 11:39:01 -0600323 self.fatal('The configuration failed')
324 return libs
akmhoquec52a46c2014-02-17 21:13:16 -0600325
dmcoomescf8d0ed2017-02-21 11:39:01 -0600326 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 Pesaventof75bfda2019-11-10 18:34:13 -0500363 if Utils.unversioned_sys_platform() == 'sunos':
dmcoomescf8d0ed2017-02-21 11:39:01 -0600364 # 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 Pesaventof75bfda2019-11-10 18:34:13 -0500371 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
dmcoomescf8d0ed2017-02-21 11:39:01 -0600372 else:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500373 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
374 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
dmcoomescf8d0ed2017-02-21 11:39:01 -0600375
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 Pesaventof75bfda2019-11-10 18:34:13 -0500381 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
dmcoomescf8d0ed2017-02-21 11:39:01 -0600382 self.end_msg(boost_pthread_flag)
383 return
384 except self.errors.ConfigurationError:
385 self.env.revert()
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500386 self.end_msg('none')
akmhoquec52a46c2014-02-17 21:13:16 -0600387
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
dmcoomescf8d0ed2017-02-21 11:39:01 -0600399 params = {
400 'lib': k and k[0] or kw.get('lib', None),
401 'stlib': kw.get('stlib', None)
402 }
akmhoquec52a46c2014-02-17 21:13:16 -0600403 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 Pesaventof75bfda2019-11-10 18:34:13 -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 Newberryf1a8ee62018-04-05 22:01:15 -0700416
Davide Pesaventof75bfda2019-11-10 18:34:13 -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
akmhoquec52a46c2014-02-17 21:13:16 -0600429
dmcoomescf8d0ed2017-02-21 11:39:01 -0600430 if not params['lib'] and not params['stlib']:
akmhoquec52a46c2014-02-17 21:13:16 -0600431 return
dmcoomescf8d0ed2017-02-21 11:39:01 -0600432 if 'static' in kw or 'static' in params:
433 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
akmhoquec52a46c2014-02-17 21:13:16 -0600434 self.start_msg('Checking boost libs')
dmcoomescf8d0ed2017-02-21 11:39:01 -0600435 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 Pesaventof75bfda2019-11-10 18:34:13 -0500440 self.end_msg(' '.join(libs + stlibs))
akmhoquec52a46c2014-02-17 21:13:16 -0600441 if Logs.verbose:
442 Logs.pprint('CYAN', ' path : %s' % path)
dmcoomescf8d0ed2017-02-21 11:39:01 -0600443 Logs.pprint('CYAN', ' shared libs : %s' % libs)
444 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
akmhoquec52a46c2014-02-17 21:13:16 -0600445
dmcoomescf8d0ed2017-02-21 11:39:01 -0600446 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)
akmhoquec52a46c2014-02-17 21:13:16 -0600455
456 def try_link():
dmcoomescf8d0ed2017-02-21 11:39:01 -0600457 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 Pesaventof75bfda2019-11-10 18:34:13 -0500461 if has_lib('log') or has_lib('log_setup'):
dmcoomescf8d0ed2017-02-21 11:39:01 -0600462 if not has_lib('thread'):
463 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500464 if has_shlib('log') or has_shlib('log_setup'):
dmcoomescf8d0ed2017-02-21 11:39:01 -0600465 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Davide Pesaventof75bfda2019-11-10 18:34:13 -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)
akmhoquec52a46c2014-02-17 21:13:16 -0600470
471 if params.get('linkage_autodetect', False):
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500472 self.start_msg('Attempting to detect boost linkage flags')
akmhoquec52a46c2014-02-17 21:13:16 -0600473 toolset = self.boost_get_toolset(kw.get('toolset', ''))
dmcoomescf8d0ed2017-02-21 11:39:01 -0600474 if toolset in ('vc',):
akmhoquec52a46c2014-02-17 21:13:16 -0600475 # 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 Pesaventof75bfda2019-11-10 18:34:13 -0500494 self.env['CXXFLAGS_%s' % var] += cxxflags
akmhoquec52a46c2014-02-17 21:13:16 -0600495 try:
496 try_link()
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500497 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
dmcoomescf8d0ed2017-02-21 11:39:01 -0600498 exc = None
akmhoquec52a46c2014-02-17 21:13:16 -0600499 break
dmcoomescf8d0ed2017-02-21 11:39:01 -0600500 except Errors.ConfigurationError as e:
akmhoquec52a46c2014-02-17 21:13:16 -0600501 self.env.revert()
dmcoomescf8d0ed2017-02-21 11:39:01 -0600502 exc = e
akmhoquec52a46c2014-02-17 21:13:16 -0600503
dmcoomescf8d0ed2017-02-21 11:39:01 -0600504 if exc is not None:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500505 self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc)
akmhoquec52a46c2014-02-17 21:13:16 -0600506 self.fatal('The configuration failed')
507 else:
Davide Pesaventof75bfda2019-11-10 18:34:13 -0500508 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
akmhoquec52a46c2014-02-17 21:13:16 -0600509 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 Pesaventof75bfda2019-11-10 18:34:13 -0500515 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
akmhoquec52a46c2014-02-17 21:13:16 -0600516 self.fatal('The configuration failed')
517 self.end_msg('ok')
dmcoomescf8d0ed2017-02-21 11:39:01 -0600518
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