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
10
#def set_options(opt):
11
# opt.tool_options('boost')
15
# # ... (e.g. conf.check_tool('g++'))
16
# conf.check_tool('boost')
17
# conf.check_boost(lib='signals filesystem', kind='STATIC_BOTH', score_version=(-1000, 1000), tag_minscore=1000)
21
# * find_includes should be called only once!
24
######## boost update ###########
25
## ITA: * the method get_boost_version_number does work
26
## * the rest of the code has not really been tried
27
# * make certain a demo is provided (in demos/adv for example)
29
import os.path, glob, types, re, sys
30
import Configure, config_c, Options, Utils, Logs
32
from Configure import conf
36
#include <boost/version.hpp>
37
int main() { std::cout << BOOST_VERSION << std::endl; }
40
boost_libpath = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
41
boost_cpppath = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
43
STATIC_NOSTATIC = 'nostatic'
45
STATIC_ONLYSTATIC = 'onlystatic'
47
is_versiontag = re.compile('^\d+_\d+_?\d*$')
48
is_threadingtag = re.compile('^mt$')
49
is_abitag = re.compile('^[sgydpn]+$')
50
is_toolsettag = re.compile('^(acc|borland|como|cw|dmc|darwin|gcc|hp_cxx|intel|kylix|msvc|qcc|sun|vacpp)\d*$')
53
opt.add_option('--boost-includes', type='string', default='', dest='boostincludes', help='path to the boost directory where the includes are e.g. /usr/local/include/boost-1_35')
54
opt.add_option('--boost-libs', type='string', default='', dest='boostlibs', help='path to the directory where the boost libs are e.g. /usr/local/lib')
56
def string_to_version(s):
57
version = s.split('.')
58
if len(version) < 3: return 0
59
return int(version[0])*100000 + int(version[1])*100 + int(version[2])
61
def version_string(version):
62
major = version / 100000
63
minor = version / 100 % 1000
64
minor_minor = version % 100
66
return "%d_%d" % (major, minor)
68
return "%d_%d_%d" % (major, minor, minor_minor)
70
def libfiles(lib, pattern, lib_paths):
72
for lib_path in lib_paths:
73
libname = pattern % ('boost_' + lib + '*')
74
result += glob.glob(lib_path + '/' + libname)
78
def get_boost_version_number(self, dir):
79
"""silently retrieve the boost version number"""
81
return self.run_c_code(compiler='cxx', code=boost_code, includes=dir, execute=1, env=self.env.copy(), type='cprogram', compile_mode='cxx', compile_filename='test.cpp')
82
except Configure.ConfigurationError, e:
85
def set_default(kw, var, val):
89
def tags_score(tags, kw):
93
see http://www.boost.org/doc/libs/1_35_0/more/getting_started/unix-variants.html 6.1
97
'threading': kw['tag_threading'],
99
'toolset': kw['tag_toolset'],
100
'version': kw['tag_version']
103
if kw['tag_toolset'] is None:
105
toolset = v['CXX_NAME']
107
version_no = v['CXX_VERSION'].split('.')
108
toolset += version_no[0]
109
if len(version_no) > 1:
110
toolset += version_no[1]
111
needed_tags['toolset'] = toolset
115
if is_versiontag.match(tag): found_tags['version'] = tag
116
if is_threadingtag.match(tag): found_tags['threading'] = tag
117
if is_abitag.match(tag): found_tags['abi'] = tag
118
if is_toolsettag.match(tag): found_tags['toolset'] = tag
120
for tagname in needed_tags.iterkeys():
121
if needed_tags[tagname] is not None and tagname in found_tags:
122
if re.compile(needed_tags[tagname]).match(found_tags[tagname]):
123
score += kw['score_' + tagname][0]
125
score += kw['score_' + tagname][1]
129
def validate_boost(self, kw):
130
ver = kw.get('version', '')
132
for x in 'min_version max_version version'.split():
133
set_default(kw, x, ver)
135
set_default(kw, 'lib', '')
136
kw['lib'] = Utils.to_list(kw['lib'])
138
set_default(kw, 'env', self.env)
140
set_default(kw, 'libpath', boost_libpath)
141
set_default(kw, 'cpppath', boost_cpppath)
143
for x in 'tag_threading tag_version tag_toolset'.split():
144
set_default(kw, x, None)
145
set_default(kw, 'tag_abi', '^[^d]*$')
147
set_default(kw, 'score_threading', (10, -10))
148
set_default(kw, 'score_abi', (10, -10))
149
set_default(kw, 'score_toolset', (1, -1))
150
set_default(kw, 'score_version', (100, -100))
152
set_default(kw, 'score_min', 0)
153
set_default(kw, 'static', STATIC_NOSTATIC)
154
set_default(kw, 'found_includes', False)
155
set_default(kw, 'min_score', 0)
157
set_default(kw, 'errmsg', 'not found')
158
set_default(kw, 'okmsg', 'ok')
161
def find_boost_includes(self, kw):
163
check every path in kw['cpppath'] for subdir
164
that either starts with boost- or is named boost.
166
Then the version is checked and selected accordingly to
167
min_version/max_version. The highest possible version number is
170
If no versiontag is set the versiontag is set accordingly to the
171
selected library and CPPPATH_BOOST is set.
173
boostPath = getattr(Options.options, 'boostincludes', '')
175
boostPath = [os.path.normpath(os.path.expandvars(os.path.expanduser(boostPath)))]
177
boostPath = Utils.to_list(kw['cpppath'])
179
min_version = string_to_version(kw.get('min_version', ''))
180
max_version = string_to_version(kw.get('max_version', '')) or (sys.maxint - 1)
183
for include_path in boostPath:
184
boost_paths = glob.glob(os.path.join(include_path, 'boost*'))
185
for path in boost_paths:
186
pathname = os.path.split(path)[-1]
188
if pathname == 'boost':
190
ret = self.get_boost_version_number(path)
191
elif pathname.startswith('boost-'):
192
ret = self.get_boost_version_number(path)
195
if ret != -1 and ret >= min_version and ret <= max_version and ret > version:
200
self.fatal('boost headers not found! (required version min: %s max: %s)'
201
% (kw['min_version'], kw['max_version']))
204
found_version = version_string(version)
205
versiontag = '^' + found_version + '$'
206
if kw['tag_version'] is None:
207
kw['tag_version'] = versiontag
208
elif kw['tag_version'] != versiontag:
209
warn('boost header version %r and tag_version %r do not match!' % (versiontag, kw['tag_version']))
211
env['CPPPATH_BOOST'] = boost_path
212
env['BOOST_VERSION'] = found_version
213
self.found_includes = 1
214
ret = 'Version %s (%s)' % (found_version, boost_path)
218
def find_boost_library(self, lib, kw):
220
def find_library_from_list(lib, files):
221
lib_pattern = re.compile('.*boost_(.*?)\..*')
222
result = (None, None)
223
resultscore = kw['min_score'] - 1
225
m = lib_pattern.search(file, 1)
228
libtags = libname.split('-')[1:]
229
currentscore = tags_score(libtags, kw)
230
if currentscore > resultscore:
231
result = (libname, file)
232
resultscore = currentscore
235
lib_paths = getattr(Options.options, 'boostlibs', '')
237
lib_paths = [os.path.normpath(os.path.expandvars(os.path.expanduser(lib_paths)))]
239
lib_paths = Utils.to_list(kw['libpath'])
241
v = kw.get('env', self.env)
243
(libname, file) = (None, None)
244
if kw['static'] in [STATIC_NOSTATIC, STATIC_BOTH]:
245
st_env_prefix = 'LIB'
246
files = libfiles(lib, v['shlib_PATTERN'], lib_paths)
247
(libname, file) = find_library_from_list(lib, files)
248
if libname is None and kw['static'] in [STATIC_ONLYSTATIC, STATIC_BOTH]:
249
st_env_prefix = 'STATICLIB'
250
files = libfiles(lib, v['staticlib_PATTERN'], lib_paths)
251
(libname, file) = find_library_from_list(lib, files)
252
if libname is not None:
253
v['LIBPATH_BOOST_' + lib.upper()] = os.path.split(file)[0]
254
v[st_env_prefix + '_BOOST_' + lib.upper()] = 'boost_'+libname
256
self.fatal('lib boost_' + lib + ' not found!')
259
def check_boost(self, *k, **kw):
261
This should be the main entry point
269
- toolsettag - None or a regexp
270
- threadingtag - None or a regexp
271
- abitag - None or a regexp
272
- versiontag - WARNING: you should rather use version or min_version/max_version
273
- static - look for static libs (values:
274
'nostatic' or STATIC_NOSTATIC - ignore static libs (default)
275
'both' or STATIC_BOTH - find static libs, too
276
'onlystatic' or STATIC_ONLYSTATIC - find only static libs
281
* the scores are tuples (match_score, nomatch_score)
282
match_score is the added to the score if the tag is matched
283
nomatch_score is added when a tag is found and does not match
287
self.validate_boost(kw)
290
if not kw.get('found_includes', None):
291
self.check_message_1(kw.get('msg_includes', 'boost headers'))
292
ret = self.find_boost_includes(kw)
294
except Configure.ConfigurationError, e:
296
self.check_message_2(kw['errmsg'], 'YELLOW')
297
if 'mandatory' in kw:
301
self.fatal('the configuration failed (see config.log)')
304
self.check_message_2(kw.get('okmsg_includes', ret))
306
for lib in kw['lib']:
307
self.check_message_1('library boost_'+lib)
309
self.find_boost_library(lib, kw)
310
except Configure.ConfigurationError, e:
312
self.check_message_2(kw['errmsg'], 'YELLOW')
313
if 'mandatory' in kw:
317
self.fatal('the configuration failed (see config.log)')
320
self.check_message_2(kw['okmsg'])