blob: 4b2ede536a6135aad2d881cc7c04f149cf12be7c [file] [log] [blame]
Junxiao Shi2222a612015-06-06 08:01:38 -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
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050016 or, if you have waf >= 1.6.2
Junxiao Shi2222a612015-06-06 08:01:38 -070017$ ./waf update --files=boost
18
19When using this tool, the wscript will look like:
20
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050021 def options(opt):
22 opt.load('compiler_cxx boost')
Junxiao Shi2222a612015-06-06 08:01:38 -070023
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050024 def configure(conf):
25 conf.load('compiler_cxx boost')
26 conf.check_boost(lib='system filesystem')
Junxiao Shi2222a612015-06-06 08:01:38 -070027
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050028 def build(bld):
29 bld(source='main.cpp', target='app', use='BOOST')
Junxiao Shi2222a612015-06-06 08:01:38 -070030
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 Afanasyev20c85cb2018-03-09 17:50:14 -050033It can also provide default arguments to the --boost-mt command-line arguments.
Junxiao Shi2222a612015-06-06 08:01:38 -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 Afanasyev20c85cb2018-03-09 17:50:14 -050040 So before calling `conf.check_boost` you might want to disabling by adding
41 conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
Junxiao Shi2222a612015-06-06 08:01:38 -070042 Errors:
43 - boost might also be compiled with /MT, which links the runtime statically.
44 If you have problems with redefined symbols,
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050045 self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
46 self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
Junxiao Shi2222a612015-06-06 08:01:38 -070047Passing `--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 Afanasyev20c85cb2018-03-09 17:50:14 -050055from waflib.TaskGen import feature, after_method
Junxiao Shi2222a612015-06-06 08:01:38 -070056
Eric Newberry5820ed32018-04-05 21:59:52 -070057BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050058BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
Davide Pesaventoae37cf32019-02-20 18:19:22 -050059
Junxiao Shi2222a612015-06-06 08:01:38 -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 Afanasyev20c85cb2018-03-09 17:50:14 -050066
67BOOST_ERROR_CODE = '''
Junxiao Shi2222a612015-06-06 08:01:38 -070068#include <boost/system/error_code.hpp>
69int main() { boost::system::error_code c; }
70'''
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050071
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
Junxiao Shi2222a612015-06-06 08:01:38 -070087BOOST_THREAD_CODE = '''
88#include <boost/thread.hpp>
89int main() { boost::thread t; }
90'''
91
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050092BOOST_LOG_CODE = '''
93#include <boost/log/trivial.hpp>
Davide Pesaventoae37cf32019-02-20 18:19:22 -050094int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; }
95'''
96
97BOOST_LOG_SETUP_CODE = '''
98#include <boost/log/trivial.hpp>
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -050099#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 Pesaventoae37cf32019-02-20 18:19:22 -0500105 BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working";
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500106}
107'''
108
Junxiao Shi2222a612015-06-06 08:01:38 -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 = {
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500115 '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'
Junxiao Shi2222a612015-06-06 08:01:38 -0700135}
136
137
138def options(opt):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500139 opt = opt.add_option_group('Boost Options')
140 opt.add_option('--boost-includes', type='string',
141 default='', dest='boost_includes',
142 help='''path to the directory where the boost includes are,
143 e.g., /path/to/boost_1_55_0/stage/include''')
144 opt.add_option('--boost-libs', type='string',
145 default='', dest='boost_libs',
146 help='''path to the directory where the boost libs are,
147 e.g., path/to/boost_1_55_0/stage/lib''')
148 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',
152 help='''select libraries with tags (gd for debug, static is automatically added),
153 see doc Boost, Getting Started, chapter 6.1''')
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500154 opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect',
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500155 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',
158 help='force a toolset e.g. msvc, vc90, \
159 gcc, mingw, mgw45 (default: auto)')
160 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',
163 help='select the lib python with this version \
164 (default: %s)' % py_version)
Junxiao Shi2222a612015-06-06 08:01:38 -0700165
166
167@conf
168def __boost_get_version_file(self, d):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500169 if not d:
170 return None
171 dnode = self.root.find_dir(d)
172 if dnode:
173 return dnode.find_node(BOOST_VERSION_FILE)
174 return None
Junxiao Shi2222a612015-06-06 08:01:38 -0700175
176@conf
177def boost_get_version(self, d):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500178 """silently retrieve the boost version number"""
179 node = self.__boost_get_version_file(d)
180 if node:
181 try:
182 txt = node.read()
183 except EnvironmentError:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500184 Logs.error('Could not read the file %r' % node.abspath())
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500185 else:
186 re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M)
187 m1 = re_but1.search(txt)
188 re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M)
189 m2 = re_but2.search(txt)
190 if m1 and m2:
191 return (m1.group(1), m2.group(1))
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500192 return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':')
Junxiao Shi2222a612015-06-06 08:01:38 -0700193
194@conf
195def boost_get_includes(self, *k, **kw):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500196 includes = k and k[0] or kw.get('includes', None)
197 if includes and self.__boost_get_version_file(includes):
198 return includes
199 for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
200 if self.__boost_get_version_file(d):
201 return d
202 if includes:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500203 self.end_msg('headers not found in %s' % includes, 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500204 self.fatal('The configuration failed')
205 else:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500206 self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500207 self.fatal('The configuration failed')
Junxiao Shi2222a612015-06-06 08:01:38 -0700208
209
210@conf
211def boost_get_toolset(self, cc):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500212 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)
Junxiao Shi2222a612015-06-06 08:01:38 -0700222
223
224@conf
225def __boost_get_libs_path(self, *k, **kw):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500226 ''' 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:
234 for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
235 if not d:
236 continue
237 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 Pesaventoae37cf32019-02-20 18:19:22 -0500249 self.end_msg('libs not found in %s' % libs, 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500250 self.fatal('The configuration failed')
251 else:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500252 self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500253 self.fatal('The configuration failed')
Junxiao Shi2222a612015-06-06 08:01:38 -0700254
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500255 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
Junxiao Shi2222a612015-06-06 08:01:38 -0700259
260@conf
261def boost_get_libs(self, *k, **kw):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500262 '''
263 return the lib path and the required libs
264 according to the parameters
265 '''
266 path, files = self.__boost_get_libs_path(**kw)
267 files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
268 toolset = self.boost_get_toolset(kw.get('toolset', ''))
269 toolset_pat = '(-%s[0-9]{0,3})' % toolset
270 version = '-%s' % self.env.BOOST_VERSION
271
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
284 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
299
300 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 Pesaventoae37cf32019-02-20 18:19:22 -0500322 self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500323 self.fatal('The configuration failed')
324 return libs
325
326 return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
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
Junxiao Shi2222a612015-06-06 08:01:38 -0700340 '''
Junxiao Shi2222a612015-06-06 08:01:38 -0700341
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500342 var = kw.get('uselib_store', 'BOOST')
Junxiao Shi2222a612015-06-06 08:01:38 -0700343
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500344 self.start_msg('Checking the flags needed to use pthreads')
Junxiao Shi2222a612015-06-06 08:01:38 -0700345
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500346 # 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 Pesaventoae37cf32019-02-20 18:19:22 -0500363 if Utils.unversioned_sys_platform() == 'sunos':
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500364 # 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 Pesaventoae37cf32019-02-20 18:19:22 -0500371 boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread']
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500372 else:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500373 boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread',
374 '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt']
Junxiao Shi2222a612015-06-06 08:01:38 -0700375
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500376 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 Pesaventoae37cf32019-02-20 18:19:22 -0500381 self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True)
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500382 self.end_msg(boost_pthread_flag)
383 return
384 except self.errors.ConfigurationError:
385 self.env.revert()
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500386 self.end_msg('none')
Junxiao Shi2222a612015-06-06 08:01:38 -0700387
388@conf
389def check_boost(self, *k, **kw):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500390 """
391 Initialize boost libraries to be used.
Junxiao Shi2222a612015-06-06 08:01:38 -0700392
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500393 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")')
Junxiao Shi2222a612015-06-06 08:01:38 -0700398
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500399 params = {
400 'lib': k and k[0] or kw.get('lib', None),
401 'stlib': kw.get('stlib', None)
402 }
403 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, '')
Junxiao Shi2222a612015-06-06 08:01:38 -0700408
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500409 var = kw.get('uselib_store', 'BOOST')
Junxiao Shi2222a612015-06-06 08:01:38 -0700410
Davide Pesaventoae37cf32019-02-20 18:19:22 -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 Newberry5820ed32018-04-05 21:59:52 -0700416
Davide Pesaventoae37cf32019-02-20 18:19:22 -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
Junxiao Shi2222a612015-06-06 08:01:38 -0700429
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500430 if not params['lib'] and not params['stlib']:
431 return
432 if 'static' in kw or 'static' in params:
433 Logs.warn('boost: static parameter is deprecated, use stlib instead.')
434 self.start_msg('Checking boost libs')
435 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 Pesaventoae37cf32019-02-20 18:19:22 -0500440 self.end_msg(' '.join(libs + stlibs))
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500441 if Logs.verbose:
442 Logs.pprint('CYAN', ' path : %s' % path)
443 Logs.pprint('CYAN', ' shared libs : %s' % libs)
444 Logs.pprint('CYAN', ' static libs : %s' % stlibs)
445
446 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)
455
456 def try_link():
457 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 Pesaventoae37cf32019-02-20 18:19:22 -0500461 if has_lib('log') or has_lib('log_setup'):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500462 if not has_lib('thread'):
463 self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS']
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500464 if has_shlib('log') or has_shlib('log_setup'):
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500465 self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK']
Davide Pesaventoae37cf32019-02-20 18:19:22 -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 Afanasyev20c85cb2018-03-09 17:50:14 -0500470
471 if params.get('linkage_autodetect', False):
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500472 self.start_msg('Attempting to detect boost linkage flags')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500473 toolset = self.boost_get_toolset(kw.get('toolset', ''))
474 if toolset in ('vc',):
475 # 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 Pesaventoae37cf32019-02-20 18:19:22 -0500494 self.env['CXXFLAGS_%s' % var] += cxxflags
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500495 try:
496 try_link()
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500497 self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var]))
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500498 exc = None
499 break
500 except Errors.ConfigurationError as e:
501 self.env.revert()
502 exc = e
503
504 if exc is not None:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500505 self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc)
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500506 self.fatal('The configuration failed')
507 else:
Davide Pesaventoae37cf32019-02-20 18:19:22 -0500508 self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500509 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 Pesaventoae37cf32019-02-20 18:19:22 -0500515 self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW')
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500516 self.fatal('The configuration failed')
517 self.end_msg('ok')
Junxiao Shi2222a612015-06-06 08:01:38 -0700518
519
Alexander Afanasyev20c85cb2018-03-09 17:50:14 -0500520@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