00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 from __future__ import print_function
00035
00036 import sys
00037 import os
00038 import string
00039 from glob import glob
00040 import subprocess
00041 import platform
00042 from optparse import OptionParser
00043
00044 lib_suffix = "so"
00045 if (sys.platform == "darwin"):
00046 lib_suffix = "dylib"
00047
00048 link_static = 'ROS_BOOST_LINK' in os.environ and os.environ['ROS_BOOST_LINK'] == "static"
00049 if (link_static):
00050 lib_suffix = "a"
00051
00052 no_L_or_I = 'ROS_BOOST_NO_L_OR_I' in os.environ
00053
00054 boost_version = None
00055 if ('ROS_BOOST_VERSION' in os.environ and len(os.environ['ROS_BOOST_VERSION']) > 0):
00056 ver = os.environ['ROS_BOOST_VERSION']
00057 ver = ver.split('.')
00058
00059 boost_version = [int(v) for v in ver]
00060 if (len(boost_version) == 2):
00061 boost_version.append(0)
00062
00063 def print_usage_and_exit():
00064 print("Usage: rosboost-cfg --lflags [thread,regex,graph,...]")
00065 print(" rosboost-cfg --cflags")
00066 print(" rosboost-cfg --libs [thread,regex,graph,...]")
00067 print(" rosboost-cfg --include_dirs")
00068 print(" rosboost-cfg --lib_dirs")
00069 print(" rosboost-cfg --root")
00070 sys.exit(1)
00071
00072 class BoostError(Exception):
00073 def __init__(self, value):
00074 self.value = value
00075 def __str__(self):
00076 return repr(self.value)
00077
00078 class Version(object):
00079 def __init__(self, major, minor, patch, root, include_dir, lib_dir, is_default_search_location):
00080 self.major = major
00081 self.minor = minor
00082 self.patch = patch
00083 self.root = root
00084 self.include_dir = include_dir
00085 self.lib_dir = lib_dir
00086 self.is_default_search_location = is_default_search_location
00087 self.is_system_install = os.path.split(self.include_dir)[0] == self.root
00088
00089 def __cmp__(self, other):
00090 if (self.major != other.major):
00091 if self.major < other.major:
00092 return -1
00093 else:
00094 return 1
00095 if (self.minor != other.minor):
00096 if self.minor < other.minor:
00097 return -1
00098 else:
00099 return 1
00100 if (self.patch != other.patch):
00101 if self.patch < other.patch:
00102 return -1
00103 else:
00104 return 1
00105
00106 return 0
00107 def __repr__(self):
00108 return repr((self.major, self.minor, self.patch, self.root, self.include_dir, self.is_default_search_location, self.is_system_install))
00109
00110 def find_lib_dir(root_dir, multiarch=''):
00111
00112 if ('ROS_BOOST_LIB_DIR_NAME' in os.environ):
00113 possible_dirs = [os.path.join(root_dir, os.environ['ROS_BOOST_LIB_DIR_NAME'])]
00114 else:
00115 possible_dirs = [os.path.join(root_dir, "lib64"), os.path.join(root_dir, "lib")]
00116 if multiarch:
00117 possible_dirs = [os.path.join(root_dir, "lib/%s" % multiarch)] + possible_dirs
00118
00119 for p in possible_dirs:
00120 glob_files = glob("%s*"%(os.path.join(p, "libboost*")))
00121 if (len(glob_files) > 0):
00122 return p
00123
00124 return None
00125
00126 def extract_versions(dir, is_default_search_location, multiarch=''):
00127 version_paths = [os.path.join(dir, "version.hpp"),
00128 os.path.join(dir, "boost", "version.hpp")]
00129 glob_dirs = glob("%s*"%(os.path.join(dir, "boost-")))
00130 [version_paths.append(os.path.join(gdir, "boost", "version.hpp")) for gdir in glob_dirs]
00131
00132 versions = []
00133
00134 for p in version_paths:
00135 ver_string = ""
00136 if (os.path.isfile(p)):
00137 fh = open(p,"r")
00138 lines = fh.readlines()
00139 fh.close()
00140 for line in lines:
00141 if line.find("#define BOOST_VERSION ") > -1:
00142 def_string = line.split()
00143 ver_string = def_string[2]
00144 ver_int = int(ver_string)
00145 patch = ver_int % 100
00146 minor = ver_int / 100 % 1000
00147 major = ver_int / 100000
00148 include_dir = os.path.split(os.path.split(p)[0])[0]
00149 root_dir = os.path.split(dir)[0]
00150 lib_dir = find_lib_dir(root_dir, multiarch)
00151 versions.append(Version(major, minor, patch, root_dir, include_dir, lib_dir, is_default_search_location))
00152
00153 return versions
00154
00155 def find_versions(search_paths, multiarch=''):
00156 vers = []
00157
00158 for path, system in search_paths:
00159 path = os.path.join(path, "include")
00160 pvers = extract_versions(path, system, multiarch)
00161 [vers.append(ver) for ver in pvers]
00162
00163 if (len(vers) == 0):
00164 return None
00165
00166 if (boost_version is not None):
00167 for v in vers:
00168 if (v.major == boost_version[0] and v.minor == boost_version[1] and v.patch == boost_version[2]):
00169 return [v]
00170
00171 raise BoostError('Could not find boost version %s required by ROS_BOOST_VERSION environment variable'%(boost_version))
00172
00173 vers.sort()
00174 return vers
00175
00176 def find_boost(search_paths, multiarch=''):
00177 result = find_versions(search_paths, multiarch)
00178 if result is None:
00179 return None
00180 if len(result) > 1:
00181 sys.stderr.write("WARN, found multiple boost versions '%s', using latest"%result)
00182 return result[-1]
00183
00184 def search_paths(sysroot):
00185 _search_paths = [(sysroot+'/usr', True),
00186 (sysroot+'/usr/local', True),
00187 (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True),
00188 (None if 'CPATH' not in os.environ else os.environ['CPATH'], True),
00189 (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True),
00190 (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True),
00191 (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)]
00192
00193 search_paths = []
00194 for (str, system) in _search_paths:
00195 if (str is not None):
00196 dirs = str.split(':')
00197 for dir in dirs:
00198 if (len(dir) > 0):
00199 if (dir.endswith('/include')):
00200 dir = dir[:-len('/include')]
00201 search_paths.append((dir, system))
00202 return search_paths
00203
00204 def lib_dir(ver):
00205 return ver.lib_dir
00206
00207 def find_lib(ver, name, full_lib = link_static):
00208 global lib_suffix
00209 global link_static
00210
00211 dynamic_search_paths = []
00212 static_search_paths = []
00213
00214 if (ver.is_system_install):
00215 dynamic_search_paths = ["libboost_%s-mt.%s"%(name, lib_suffix),
00216 "libboost_%s.%s"%(name, lib_suffix)]
00217 static_search_paths = ["libboost_%s-mt.a"%(name),
00218 "libboost_%s.a"%(name)]
00219 else:
00220 dynamic_search_paths = ["libboost_%s*%s_%s*.%s"%(name, ver.major, ver.minor, lib_suffix),
00221 "libboost_%s-mt*.%s"%(name, lib_suffix),
00222 "libboost_%s*.%s"%(name, lib_suffix)]
00223 static_search_paths = ["libboost_%s*%s_%s*.a"%(name, ver.major, ver.minor),
00224 "libboost_%s-mt*.a"%(name),
00225 "libboost_%s*.a"%(name)]
00226
00227
00228 if (name == "python"):
00229 python_ver = platform.python_version().split('.')
00230 dynamic_search_paths = ["libboost_%s-mt-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix),
00231 "libboost_%s-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths
00232 static_search_paths = ["libboost_%s-mt-py%s%s.a"%(name, python_ver[0], python_ver[1]),
00233 "libboost_%s-py%s%s.a"%(name, python_ver[0], python_ver[1])] + static_search_paths
00234
00235 search_paths = static_search_paths if link_static else dynamic_search_paths
00236
00237 dir = lib_dir(ver)
00238
00239 if dir is None:
00240 raise BoostError('Could not locate library [%s], version %s'%(name, ver))
00241
00242 for p in search_paths:
00243 globstr = os.path.join(dir, p)
00244 libs = glob(globstr)
00245 if (len(libs) > 0):
00246 if (full_lib):
00247 return libs[0]
00248 else:
00249 return os.path.basename(libs[0])
00250
00251 raise BoostError('Could not locate library [%s], version %s in lib directory [%s]'%(name, ver, dir))
00252
00253 def include_dirs(ver, prefix = ''):
00254 if ver.is_system_install or no_L_or_I:
00255 return ""
00256
00257 return " %s%s"%(prefix, ver.include_dir)
00258
00259 def cflags(ver):
00260 return include_dirs(ver, '-I')
00261
00262 def lib_dir_flags(ver):
00263 if not ver.is_default_search_location:
00264 dir = lib_dir(ver)
00265 return ' -L%s -Wl,-rpath,%s'%(dir, dir)
00266
00267 return ''
00268
00269 def lib_flags(ver, name):
00270 lib = find_lib(ver, name)
00271 if (link_static):
00272 return ' %s'%(lib)
00273 else:
00274
00275 return ' -l%s'%(os.path.splitext(lib)[0][len('lib'):])
00276
00277 def lflags(ver, libs):
00278 s= lib_dir_flags(ver) + " "
00279 for lib in libs:
00280 s += lib_flags(ver, lib) + " "
00281 return s
00282
00283 def libs(ver, libs):
00284 s = ""
00285 for lib in libs:
00286 s += find_lib(ver, lib, True) + " "
00287 return s
00288
00289 def lib_dirs(ver):
00290 if (ver.is_default_search_location or no_L_or_I):
00291 return ""
00292
00293 return lib_dir(ver)
00294
00295 OPTIONS = ['libs', 'include_dirs', 'lib_dirs', 'cflags', 'lflags', 'root', 'print_versions', 'version']
00296
00297 def check_one_option(options, key):
00298 for k in dir(options):
00299 if (k in OPTIONS):
00300 v = getattr(options, k)
00301 if (k != key and v):
00302 raise BoostError("Only one option (excepting sysroot) is allowed at a time")
00303
00304 def main():
00305 if (len(sys.argv) < 2):
00306 print_usage_and_exit()
00307
00308 parser = OptionParser()
00309 parser.add_option("-l", "--libs", dest="libs", type="string", help="")
00310 parser.add_option("-i", "--include_dirs", dest="include_dirs", action="store_true", default=False, help="")
00311 parser.add_option("-d", "--lib_dirs", dest="lib_dirs", action="store_true", help="")
00312 parser.add_option("-c", "--cflags", dest="cflags", action="store_true", default=False, help="")
00313 parser.add_option("-f", "--lflags", dest="lflags", type="string", help="")
00314 parser.add_option("-r", "--root", dest="root", action="store_true", default=False, help="")
00315 parser.add_option("-p", "--print_versions", dest="print_versions", action="store_true", default=False, help="")
00316 parser.add_option("-v", "--version", dest="version", action="store_true", default=False, help="")
00317 parser.add_option("-s", "--sysroot", dest="sysroot", type="string", default='', help="Location of the system root (usually toolchain root).")
00318 parser.add_option("-m", "--multiarch", dest="multiarch", type="string", default='', help="Name of multiarch to search below 'lib' folder for libraries.")
00319
00320 (options, args) = parser.parse_args()
00321
00322 if (options.print_versions):
00323 check_one_option(options, 'print_versions')
00324 for ver in find_versions(search_paths(options.sysroot), options.multiarch):
00325 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00326 return
00327
00328 ver = find_boost(search_paths(options.sysroot), options.multiarch)
00329
00330 if ver is None:
00331 raise BoostError("Cannot find boost in any of %s"%search_paths(options.sysroot))
00332 sys.exit(0)
00333
00334 if options.version:
00335 check_one_option(options, 'version')
00336 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00337 return
00338
00339 if ver.major < 1 or (ver.major == 1 and ver.minor < 37):
00340 raise BoostError('Boost version %s.%s.%s does not meet the minimum requirements of boost 1.37.0'%(ver.major, ver.minor, ver.patch))
00341
00342
00343
00344 output = ""
00345 if (options.root):
00346 check_one_option(options, 'root')
00347 output = ver.root
00348 elif (options.libs):
00349 check_one_option(options, 'libs')
00350 output = libs(ver, options.libs.split(','))
00351 elif (options.include_dirs):
00352 check_one_option(options, 'include_dirs')
00353 output = include_dirs(ver)
00354 elif (options.lib_dirs):
00355 check_one_option(options, 'lib_dirs')
00356 output = lib_dirs(ver)
00357 elif (options.cflags):
00358 check_one_option(options, 'cflags')
00359 output = cflags(ver)
00360 elif (options.lflags):
00361 check_one_option(options, 'lflags')
00362 output = lflags(ver, options.lflags.split(','))
00363 else:
00364 print_usage_and_exit()
00365
00366 print(output.strip())
00367
00368 if __name__ == "__main__":
00369 main()
00370