rosboost_cfg.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2010, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Willow Garage, Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 
34 from __future__ import print_function
35 
36 import os
37 import platform
38 import sys
39 from glob import glob
40 from optparse import OptionParser
41 
42 lib_suffix = 'so'
43 if (sys.platform == 'darwin'):
44  lib_suffix = 'dylib'
45 
46 link_static = 'ROS_BOOST_LINK' in os.environ and os.environ['ROS_BOOST_LINK'] == 'static'
47 if (link_static):
48  lib_suffix = 'a'
49 
50 no_L_or_I = 'ROS_BOOST_NO_L_OR_I' in os.environ
51 
52 boost_version = None
53 if ('ROS_BOOST_VERSION' in os.environ and len(os.environ['ROS_BOOST_VERSION']) > 0):
54  ver = os.environ['ROS_BOOST_VERSION']
55  ver = ver.split('.')
56 
57  boost_version = [int(v) for v in ver]
58  if (len(boost_version) == 2):
59  boost_version.append(0)
60 
61 
63  print('Usage: rosboost-cfg --lflags [thread,regex,graph,...]')
64  print(' rosboost-cfg --cflags')
65  print(' rosboost-cfg --libs [thread,regex,graph,...]')
66  print(' rosboost-cfg --include_dirs')
67  print(' rosboost-cfg --lib_dirs')
68  print(' rosboost-cfg --root')
69  sys.exit(1)
70 
71 
72 class BoostError(Exception):
73 
74  def __init__(self, value):
75  self.value = value
76 
77  def __str__(self):
78  return repr(self.value)
79 
80 
81 class Version(object):
82 
83  def __init__(self, major, minor, patch, root, include_dir, lib_dir, is_default_search_location):
84  self.major = major
85  self.minor = minor
86  self.patch = patch
87  self.root = root
88  self.include_dir = include_dir
89  self.lib_dir = lib_dir
90  self.is_default_search_location = is_default_search_location
91  self.is_system_install = os.path.split(self.include_dir)[0] == self.root
92 
93  def __cmp__(self, other):
94  if (self.major != other.major):
95  if self.major < other.major:
96  return -1
97  else:
98  return 1
99  if (self.minor != other.minor):
100  if self.minor < other.minor:
101  return -1
102  else:
103  return 1
104  if (self.patch != other.patch):
105  if self.patch < other.patch:
106  return -1
107  else:
108  return 1
109 
110  return 0
111 
112  def __repr__(self):
113  return repr((self.major, self.minor, self.patch, self.root, self.include_dir, self.is_default_search_location, self.is_system_install))
114 
115 
116 def find_lib_dir(root_dir, multiarch=''):
117  # prefer lib64 unless explicitly specified in the environment
118  if ('ROS_BOOST_LIB_DIR_NAME' in os.environ):
119  possible_dirs = [os.path.join(root_dir, os.environ['ROS_BOOST_LIB_DIR_NAME'])]
120  else:
121  possible_dirs = [os.path.join(root_dir, 'lib64'), os.path.join(root_dir, 'lib')]
122  if multiarch:
123  possible_dirs = [os.path.join(root_dir, 'lib/%s' % multiarch)] + possible_dirs
124 
125  for p in possible_dirs:
126  glob_files = glob('%s*' % (os.path.join(p, 'libboost*')))
127  if (len(glob_files) > 0):
128  return p
129 
130  return None
131 
132 
133 def extract_versions(dir, is_default_search_location, multiarch=''):
134  version_paths = [os.path.join(dir, 'version.hpp'),
135  os.path.join(dir, 'boost', 'version.hpp')]
136  glob_dirs = glob('%s*' % (os.path.join(dir, 'boost-')))
137  [version_paths.append(os.path.join(gdir, 'boost', 'version.hpp')) for gdir in glob_dirs]
138 
139  versions = []
140 
141  for p in version_paths:
142  ver_string = ''
143  if (os.path.isfile(p)):
144  fh = open(p, 'r')
145  lines = fh.readlines()
146  fh.close()
147  for line in lines:
148  if line.find('#define BOOST_VERSION ') > -1:
149  def_string = line.split()
150  ver_string = def_string[2]
151  ver_int = int(ver_string)
152  patch = ver_int % 100
153  minor = ver_int / 100 % 1000
154  major = ver_int / 100000
155  include_dir = os.path.split(os.path.split(p)[0])[0]
156  root_dir = os.path.split(dir)[0]
157  lib_dir = find_lib_dir(root_dir, multiarch)
158  versions.append(Version(major, minor, patch, root_dir, include_dir, lib_dir, is_default_search_location))
159 
160  return versions
161 
162 
163 def find_versions(search_paths, multiarch=''):
164  vers = []
165 
166  for path, system in search_paths:
167  path = os.path.join(path, 'include')
168  pvers = extract_versions(path, system, multiarch)
169  [vers.append(ver) for ver in pvers]
170 
171  if (len(vers) == 0):
172  return None
173 
174  if (boost_version is not None):
175  for v in vers:
176  if (v.major == boost_version[0] and v.minor == boost_version[1] and v.patch == boost_version[2]):
177  return [v]
178 
179  raise BoostError('Could not find boost version %s required by ROS_BOOST_VERSION environment variable' % (boost_version))
180 
181  vers.sort()
182  return vers
183 
184 
185 def find_boost(search_paths, multiarch=''):
186  result = find_versions(search_paths, multiarch)
187  if result is None:
188  return None
189  if len(result) > 1:
190  sys.stderr.write("WARN, found multiple boost versions '%s', using latest" % result)
191  return result[-1]
192 
193 
194 def search_paths(sysroot):
195  _search_paths = [(sysroot+'/usr', True),
196  (sysroot+'/usr/local', True),
197  (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True),
198  (None if 'CPATH' not in os.environ else os.environ['CPATH'], True),
199  (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True),
200  (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True),
201  (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)]
202 
203  search_paths = []
204  for (str, system) in _search_paths:
205  if (str is not None):
206  dirs = str.split(':')
207  for dir in dirs:
208  if (len(dir) > 0):
209  if (dir.endswith('/include')):
210  dir = dir[:-len('/include')]
211  search_paths.append((dir, system))
212  return search_paths
213 
214 
215 def lib_dir(ver):
216  return ver.lib_dir
217 
218 
219 def find_lib(ver, name, full_lib=link_static):
220  global lib_suffix
221  global link_static
222 
223  dynamic_search_paths = []
224  static_search_paths = []
225 
226  if (ver.is_system_install):
227  dynamic_search_paths = ['libboost_%s-mt.%s' % (name, lib_suffix),
228  'libboost_%s.%s' % (name, lib_suffix)]
229  static_search_paths = ['libboost_%s-mt.a' % (name),
230  'libboost_%s.a' % (name)]
231  else:
232  dynamic_search_paths = ['libboost_%s*%s_%s*.%s' % (name, ver.major, ver.minor, lib_suffix),
233  'libboost_%s-mt*.%s' % (name, lib_suffix),
234  'libboost_%s*.%s' % (name, lib_suffix)]
235  static_search_paths = ['libboost_%s*%s_%s*.a' % (name, ver.major, ver.minor),
236  'libboost_%s-mt*.a' % (name),
237  'libboost_%s*.a' % (name)]
238 
239  # Boost.Python needs some special handling on some systems (Karmic), since it may have per-python-version libs
240  if (name == 'python'):
241  python_ver = platform.python_version().split('.')
242  dynamic_search_paths = ['libboost_%s-mt-py%s%s.%s' % (name, python_ver[0], python_ver[1], lib_suffix),
243  'libboost_%s-py%s%s.%s' % (name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths
244  static_search_paths = ['libboost_%s-mt-py%s%s.a' % (name, python_ver[0], python_ver[1]),
245  'libboost_%s-py%s%s.a' % (name, python_ver[0], python_ver[1])] + static_search_paths
246 
247  search_paths = static_search_paths if link_static else dynamic_search_paths
248 
249  dir = lib_dir(ver)
250 
251  if dir is None:
252  raise BoostError('Could not locate library [%s], version %s' % (name, ver))
253 
254  for p in search_paths:
255  globstr = os.path.join(dir, p)
256  libs = glob(globstr)
257  if (len(libs) > 0):
258  if (full_lib):
259  return libs[0]
260  else:
261  return os.path.basename(libs[0])
262 
263  raise BoostError('Could not locate library [%s], version %s in lib directory [%s]' % (name, ver, dir))
264 
265 
266 def include_dirs(ver, prefix=''):
267  if ver.is_system_install or no_L_or_I:
268  return ''
269 
270  return ' %s%s' % (prefix, ver.include_dir)
271 
272 
273 def cflags(ver):
274  return include_dirs(ver, '-I')
275 
276 
277 def lib_dir_flags(ver):
278  if not ver.is_default_search_location:
279  dir = lib_dir(ver)
280  return ' -L%s -Wl,-rpath,%s' % (dir, dir)
281 
282  return ''
283 
284 
285 def lib_flags(ver, name):
286  lib = find_lib(ver, name)
287  if (link_static):
288  return ' %s' % (lib)
289  else:
290  # Cut off "lib" and extension (.so/.a/.dylib/etc.)
291  return ' -l%s' % (os.path.splitext(lib)[0][len('lib'):])
292 
293 
294 def lflags(ver, libs):
295  s = lib_dir_flags(ver) + ' '
296  for lib in libs:
297  s += lib_flags(ver, lib) + ' '
298  return s
299 
300 
301 def libs(ver, libs):
302  s = ''
303  for lib in libs:
304  s += find_lib(ver, lib, True) + ' '
305  return s
306 
307 
308 def lib_dirs(ver):
309  if (ver.is_default_search_location or no_L_or_I):
310  return ''
311 
312  return lib_dir(ver)
313 
314 
315 OPTIONS = ['libs', 'include_dirs', 'lib_dirs', 'cflags', 'lflags', 'root', 'print_versions', 'version']
316 
317 
318 def check_one_option(options, key):
319  for k in dir(options):
320  if (k in OPTIONS):
321  v = getattr(options, k)
322  if (k != key and v):
323  raise BoostError('Only one option (excepting sysroot) is allowed at a time')
324 
325 
326 def main():
327  if (len(sys.argv) < 2):
329 
330  parser = OptionParser()
331  parser.add_option('-l', '--libs', dest='libs', type='string', help='')
332  parser.add_option('-i', '--include_dirs', dest='include_dirs', action='store_true', default=False, help='')
333  parser.add_option('-d', '--lib_dirs', dest='lib_dirs', action='store_true', help='')
334  parser.add_option('-c', '--cflags', dest='cflags', action='store_true', default=False, help='')
335  parser.add_option('-f', '--lflags', dest='lflags', type='string', help='')
336  parser.add_option('-r', '--root', dest='root', action='store_true', default=False, help='')
337  parser.add_option('-p', '--print_versions', dest='print_versions', action='store_true', default=False, help='')
338  parser.add_option('-v', '--version', dest='version', action='store_true', default=False, help='')
339  parser.add_option('-s', '--sysroot', dest='sysroot', type='string', default='', help='Location of the system root (usually toolchain root).')
340  parser.add_option('-m', '--multiarch', dest='multiarch', type='string', default='', help="Name of multiarch to search below 'lib' folder for libraries.")
341 
342  (options, args) = parser.parse_args()
343 
344  if (options.print_versions):
345  check_one_option(options, 'print_versions')
346  for ver in find_versions(search_paths(options.sysroot), options.multiarch):
347  print('%s.%s.%s root=%s include_dir=%s' % (ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
348  return
349 
350  ver = find_boost(search_paths(options.sysroot), options.multiarch)
351 
352  if ver is None:
353  raise BoostError('Cannot find boost in any of %s' % search_paths(options.sysroot))
354  sys.exit(0)
355 
356  if options.version:
357  check_one_option(options, 'version')
358  print('%s.%s.%s root=%s include_dir=%s' % (ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
359  return
360 
361  if ver.major < 1 or (ver.major == 1 and ver.minor < 37):
362  raise BoostError('Boost version %s.%s.%s does not meet the minimum requirements of boost 1.37.0' % (ver.major, ver.minor, ver.patch))
363 
364  output = ''
365  if (options.root):
366  check_one_option(options, 'root')
367  output = ver.root
368  elif (options.libs):
369  check_one_option(options, 'libs')
370  output = libs(ver, options.libs.split(','))
371  elif (options.include_dirs):
372  check_one_option(options, 'include_dirs')
373  output = include_dirs(ver)
374  elif (options.lib_dirs):
375  check_one_option(options, 'lib_dirs')
376  output = lib_dirs(ver)
377  elif (options.cflags):
378  check_one_option(options, 'cflags')
379  output = cflags(ver)
380  elif (options.lflags):
381  check_one_option(options, 'lflags')
382  output = lflags(ver, options.lflags.split(','))
383  else:
385 
386  print(output.strip())
387 
388 
389 if __name__ == '__main__':
390  main()
def check_one_option(options, key)
def lib_flags(ver, name)
def find_versions(search_paths, multiarch='')
def find_lib(ver, name, full_lib=link_static)
def extract_versions(dir, is_default_search_location, multiarch='')
def find_boost(search_paths, multiarch='')
def __init__(self, major, minor, patch, root, include_dir, lib_dir, is_default_search_location)
Definition: rosboost_cfg.py:83
def find_lib_dir(root_dir, multiarch='')
def include_dirs(ver, prefix='')


rosboost_cfg
Author(s): Josh Faust
autogenerated on Thu Apr 30 2020 06:30:12