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):
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
00117 for p in possible_dirs:
00118 glob_files = glob("%s*"%(os.path.join(p, "libboost*")))
00119 if (len(glob_files) > 0):
00120 return p
00121
00122 return None
00123
00124 def extract_versions(dir, is_default_search_location):
00125 version_paths = [os.path.join(dir, "version.hpp"),
00126 os.path.join(dir, "boost", "version.hpp")]
00127 glob_dirs = glob("%s*"%(os.path.join(dir, "boost-")))
00128 [version_paths.append(os.path.join(gdir, "boost", "version.hpp")) for gdir in glob_dirs]
00129
00130 versions = []
00131
00132 for p in version_paths:
00133 ver_string = ""
00134 if (os.path.isfile(p)):
00135 fh = open(p,"r")
00136 lines = fh.readlines()
00137 fh.close()
00138 for line in lines:
00139 if line.find("#define BOOST_VERSION ") > -1:
00140 def_string = line.split()
00141 ver_string = def_string[2]
00142 ver_int = int(ver_string)
00143 patch = ver_int % 100
00144 minor = ver_int / 100 % 1000
00145 major = ver_int / 100000
00146 include_dir = os.path.split(os.path.split(p)[0])[0]
00147 root_dir = os.path.split(dir)[0]
00148 lib_dir = find_lib_dir(root_dir)
00149 versions.append(Version(major, minor, patch, root_dir, include_dir, lib_dir, is_default_search_location))
00150
00151 return versions
00152
00153 def find_versions(search_paths):
00154 vers = []
00155
00156 for path, system in search_paths:
00157 path = os.path.join(path, "include")
00158 pvers = extract_versions(path, system)
00159 [vers.append(ver) for ver in pvers]
00160
00161 if (len(vers) == 0):
00162 return None
00163
00164 if (boost_version is not None):
00165 for v in vers:
00166 if (v.major == boost_version[0] and v.minor == boost_version[1] and v.patch == boost_version[2]):
00167 return [v]
00168
00169 raise BoostError('Could not find boost version %s required by ROS_BOOST_VERSION environment variable'%(boost_version))
00170
00171 vers.sort()
00172 return vers
00173
00174 def find_boost(search_paths):
00175 result = find_versions(search_paths)
00176 if result is None:
00177 return None
00178 if len(result) > 1:
00179 sys.stderr.write("WARN, found multiple boost versions '%s', using latest"%result)
00180 return result[-1]
00181
00182 def search_paths(sysroot):
00183 _search_paths = [(sysroot+'/usr', True),
00184 (sysroot+'/usr/local', True),
00185 (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True),
00186 (None if 'CPATH' not in os.environ else os.environ['CPATH'], True),
00187 (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True),
00188 (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True),
00189 (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)]
00190
00191 search_paths = []
00192 for (str, system) in _search_paths:
00193 if (str is not None):
00194 dirs = str.split(':')
00195 for dir in dirs:
00196 if (len(dir) > 0):
00197 if (dir.endswith('/include')):
00198 dir = dir[:-len('/include')]
00199 search_paths.append((dir, system))
00200 return search_paths
00201
00202 def lib_dir(ver):
00203 return ver.lib_dir
00204
00205 def find_lib(ver, name, full_lib = link_static):
00206 global lib_suffix
00207 global link_static
00208
00209 dynamic_search_paths = []
00210 static_search_paths = []
00211
00212 if (ver.is_system_install):
00213 dynamic_search_paths = ["libboost_%s-mt.%s"%(name, lib_suffix),
00214 "libboost_%s.%s"%(name, lib_suffix)]
00215 static_search_paths = ["libboost_%s-mt.a"%(name),
00216 "libboost_%s.a"%(name)]
00217 else:
00218 dynamic_search_paths = ["libboost_%s*%s_%s*.%s"%(name, ver.major, ver.minor, lib_suffix),
00219 "libboost_%s-mt*.%s"%(name, lib_suffix),
00220 "libboost_%s*.%s"%(name, lib_suffix)]
00221 static_search_paths = ["libboost_%s*%s_%s*.a"%(name, ver.major, ver.minor),
00222 "libboost_%s-mt*.a"%(name),
00223 "libboost_%s*.a"%(name)]
00224
00225
00226 if (name == "python"):
00227 python_ver = platform.python_version().split('.')
00228 dynamic_search_paths = ["libboost_%s-mt-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix),
00229 "libboost_%s-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths
00230 static_search_paths = ["libboost_%s-mt-py%s%s.a"%(name, python_ver[0], python_ver[1]),
00231 "libboost_%s-py%s%s.a"%(name, python_ver[0], python_ver[1])] + static_search_paths
00232
00233 search_paths = static_search_paths if link_static else dynamic_search_paths
00234
00235 dir = lib_dir(ver)
00236
00237 if dir is None:
00238 raise BoostError('Could not locate library [%s], version %s'%(name, ver))
00239
00240 for p in search_paths:
00241 globstr = os.path.join(dir, p)
00242 libs = glob(globstr)
00243 if (len(libs) > 0):
00244 if (full_lib):
00245 return libs[0]
00246 else:
00247 return os.path.basename(libs[0])
00248
00249 raise BoostError('Could not locate library [%s], version %s in lib directory [%s]'%(name, ver, dir))
00250
00251 def include_dirs(ver, prefix = ''):
00252 if ver.is_system_install or no_L_or_I:
00253 return ""
00254
00255 return " %s%s"%(prefix, ver.include_dir)
00256
00257 def cflags(ver):
00258 return include_dirs(ver, '-I')
00259
00260 def lib_dir_flags(ver):
00261 if not ver.is_default_search_location:
00262 dir = lib_dir(ver)
00263 return ' -L%s -Wl,-rpath,%s'%(dir, dir)
00264
00265 return ''
00266
00267 def lib_flags(ver, name):
00268 lib = find_lib(ver, name)
00269 if (link_static):
00270 return ' %s'%(lib)
00271 else:
00272
00273 return ' -l%s'%(os.path.splitext(lib)[0][len('lib'):])
00274
00275 def lflags(ver, libs):
00276 s= lib_dir_flags(ver) + " "
00277 for lib in libs:
00278 s += lib_flags(ver, lib) + " "
00279 return s
00280
00281 def libs(ver, libs):
00282 s = ""
00283 for lib in libs:
00284 s += find_lib(ver, lib, True) + " "
00285 return s
00286
00287 def lib_dirs(ver):
00288 if (ver.is_default_search_location or no_L_or_I):
00289 return ""
00290
00291 return lib_dir(ver)
00292
00293 OPTIONS = ['libs', 'include_dirs', 'lib_dirs', 'cflags', 'lflags', 'root', 'print_versions', 'version']
00294
00295 def check_one_option(options, key):
00296 for k in dir(options):
00297 if (k in OPTIONS):
00298 v = getattr(options, k)
00299 if (k != key and v):
00300 raise BoostError("Only one option (excepting sysroot) is allowed at a time")
00301
00302 def main():
00303 if (len(sys.argv) < 2):
00304 print_usage_and_exit()
00305
00306 parser = OptionParser()
00307 parser.add_option("-l", "--libs", dest="libs", type="string", help="")
00308 parser.add_option("-i", "--include_dirs", dest="include_dirs", action="store_true", default=False, help="")
00309 parser.add_option("-d", "--lib_dirs", dest="lib_dirs", action="store_true", help="")
00310 parser.add_option("-c", "--cflags", dest="cflags", action="store_true", default=False, help="")
00311 parser.add_option("-f", "--lflags", dest="lflags", type="string", help="")
00312 parser.add_option("-r", "--root", dest="root", action="store_true", default=False, help="")
00313 parser.add_option("-p", "--print_versions", dest="print_versions", action="store_true", default=False, help="")
00314 parser.add_option("-v", "--version", dest="version", action="store_true", default=False, help="")
00315 parser.add_option("-s", "--sysroot", dest="sysroot", type="string", default='', help="Location of the system root (usually toolchain root).")
00316
00317 (options, args) = parser.parse_args()
00318
00319 if (options.print_versions):
00320 check_one_option(options, 'print_versions')
00321 for ver in find_versions(search_paths(options.sysroot)):
00322 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00323 return
00324
00325 ver = find_boost(search_paths(options.sysroot))
00326
00327 if ver is None:
00328 raise BoostError("Cannot find boost in any of %s"%search_paths(options.sysroot))
00329 sys.exit(0)
00330
00331 if options.version:
00332 check_one_option(options, 'version')
00333 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00334 return
00335
00336 if ver.major < 1 or (ver.major == 1 and ver.minor < 37):
00337 raise BoostError('Boost version %s.%s.%s does not meet the minimum requirements of boost 1.37.0'%(ver.major, ver.minor, ver.patch))
00338
00339
00340
00341 output = ""
00342 if (options.root):
00343 check_one_option(options, 'root')
00344 output = ver.root
00345 elif (options.libs):
00346 check_one_option(options, 'libs')
00347 output = libs(ver, options.libs.split(','))
00348 elif (options.include_dirs):
00349 check_one_option(options, 'include_dirs')
00350 output = include_dirs(ver)
00351 elif (options.lib_dirs):
00352 check_one_option(options, 'lib_dirs')
00353 output = lib_dirs(ver)
00354 elif (options.cflags):
00355 check_one_option(options, 'cflags')
00356 output = cflags(ver)
00357 elif (options.lflags):
00358 check_one_option(options, 'lflags')
00359 output = lflags(ver, options.lflags.split(','))
00360 else:
00361 print_usage_and_exit()
00362
00363 print(output.strip())
00364
00365 if __name__ == "__main__":
00366 main()
00367