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 return result[-1]
00179
00180 def search_paths(sysroot):
00181 _search_paths = [(sysroot+'/usr', True),
00182 (sysroot+'/usr/local', True),
00183 (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True),
00184 (None if 'CPATH' not in os.environ else os.environ['CPATH'], True),
00185 (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True),
00186 (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True),
00187 (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)]
00188
00189 search_paths = []
00190 for (str, system) in _search_paths:
00191 if (str is not None):
00192 dirs = str.split(':')
00193 for dir in dirs:
00194 if (len(dir) > 0):
00195 if (dir.endswith('/include')):
00196 dir = dir[:-len('/include')]
00197 search_paths.append((dir, system))
00198 return search_paths
00199
00200 def lib_dir(ver):
00201 return ver.lib_dir
00202
00203 def find_lib(ver, name, full_lib = link_static):
00204 global lib_suffix
00205 global link_static
00206
00207 dynamic_search_paths = []
00208 static_search_paths = []
00209
00210 if (ver.is_system_install):
00211 dynamic_search_paths = ["libboost_%s-mt.%s"%(name, lib_suffix),
00212 "libboost_%s.%s"%(name, lib_suffix)]
00213 static_search_paths = ["libboost_%s-mt.a"%(name),
00214 "libboost_%s.a"%(name)]
00215 else:
00216 dynamic_search_paths = ["libboost_%s*%s_%s*.%s"%(name, ver.major, ver.minor, lib_suffix),
00217 "libboost_%s-mt*.%s"%(name, lib_suffix),
00218 "libboost_%s*.%s"%(name, lib_suffix)]
00219 static_search_paths = ["libboost_%s*%s_%s*.a"%(name, ver.major, ver.minor),
00220 "libboost_%s-mt*.a"%(name),
00221 "libboost_%s*.a"%(name)]
00222
00223
00224 if (name == "python"):
00225 python_ver = platform.python_version().split('.')
00226 dynamic_search_paths = ["libboost_%s-mt-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix),
00227 "libboost_%s-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths
00228 static_search_paths = ["libboost_%s-mt-py%s%s.a"%(name, python_ver[0], python_ver[1]),
00229 "libboost_%s-py%s%s.a"%(name, python_ver[0], python_ver[1])] + static_search_paths
00230
00231 search_paths = static_search_paths if link_static else dynamic_search_paths
00232
00233 dir = lib_dir(ver)
00234
00235 if dir is None:
00236 raise BoostError('Could not locate library [%s]'%(name))
00237
00238 for p in search_paths:
00239 globstr = os.path.join(dir, p)
00240 libs = glob(globstr)
00241 if (len(libs) > 0):
00242 if (full_lib):
00243 return libs[0]
00244 else:
00245 return os.path.basename(libs[0])
00246
00247 raise BoostError('Could not locate library [%s] in lib directory [%s]'%(name, dir))
00248
00249 def include_dirs(ver, prefix = ''):
00250 if ver.is_system_install or no_L_or_I:
00251 return ""
00252
00253 return " %s%s"%(prefix, ver.include_dir)
00254
00255 def cflags(ver):
00256 return include_dirs(ver, '-I')
00257
00258 def lib_dir_flags(ver):
00259 if not ver.is_default_search_location:
00260 dir = lib_dir(ver)
00261 return ' -L%s -Wl,-rpath,%s'%(dir, dir)
00262
00263 return ''
00264
00265 def lib_flags(ver, name):
00266 lib = find_lib(ver, name)
00267 if (link_static):
00268 return ' %s'%(lib)
00269 else:
00270
00271 return ' -l%s'%(os.path.splitext(lib)[0][len('lib'):])
00272
00273 def lflags(ver, libs):
00274 s= lib_dir_flags(ver) + " "
00275 for lib in libs:
00276 s += lib_flags(ver, lib) + " "
00277 return s
00278
00279 def libs(ver, libs):
00280 s = ""
00281 for lib in libs:
00282 s += find_lib(ver, lib, True) + " "
00283 return s
00284
00285 def lib_dirs(ver):
00286 if (ver.is_default_search_location or no_L_or_I):
00287 return ""
00288
00289 return lib_dir(ver)
00290
00291 OPTIONS = ['libs', 'include_dirs', 'lib_dirs', 'cflags', 'lflags', 'root', 'print_versions', 'version']
00292
00293 def check_one_option(options, key):
00294 for k in dir(options):
00295 if (k in OPTIONS):
00296 v = getattr(options, k)
00297 if (k != key and v):
00298 raise BoostError("Only one option (excepting sysroot) is allowed at a time")
00299
00300 def main():
00301 if (len(sys.argv) < 2):
00302 print_usage_and_exit()
00303
00304 parser = OptionParser()
00305 parser.add_option("-l", "--libs", dest="libs", type="string", help="")
00306 parser.add_option("-i", "--include_dirs", dest="include_dirs", action="store_true", default=False, help="")
00307 parser.add_option("-d", "--lib_dirs", dest="lib_dirs", action="store_true", help="")
00308 parser.add_option("-c", "--cflags", dest="cflags", action="store_true", default=False, help="")
00309 parser.add_option("-f", "--lflags", dest="lflags", type="string", help="")
00310 parser.add_option("-r", "--root", dest="root", action="store_true", default=False, help="")
00311 parser.add_option("-p", "--print_versions", dest="print_versions", action="store_true", default=False, help="")
00312 parser.add_option("-v", "--version", dest="version", action="store_true", default=False, help="")
00313 parser.add_option("-s", "--sysroot", dest="sysroot", type="string", default='', help="Location of the system root (usually toolchain root).")
00314
00315 (options, args) = parser.parse_args()
00316
00317 if (options.print_versions):
00318 check_one_option(options, 'print_versions')
00319 for ver in find_versions(search_paths(options.sysroot)):
00320 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00321 return
00322
00323 ver = find_boost(search_paths(options.sysroot))
00324
00325 if ver is None:
00326 raise BoostError("Cannot find boost in any of %s"%search_paths(options.sysroot))
00327 sys.exit(0)
00328
00329 if options.version:
00330 check_one_option(options, 'version')
00331 print('%s.%s.%s root=%s include_dir=%s'%(ver.major, ver.minor, ver.patch, ver.root, ver.include_dir))
00332 return
00333
00334 if ver.major < 1 or (ver.major == 1 and ver.minor < 37):
00335 raise BoostError('Boost version %s.%s.%s does not meet the minimum requirements of boost 1.37.0'%(ver.major, ver.minor, ver.patch))
00336
00337
00338
00339 output = ""
00340 if (options.root):
00341 check_one_option(options, 'root')
00342 output = ver.root
00343 elif (options.libs):
00344 check_one_option(options, 'libs')
00345 output = libs(ver, options.libs.split(','))
00346 elif (options.include_dirs):
00347 check_one_option(options, 'include_dirs')
00348 output = include_dirs(ver)
00349 elif (options.lib_dirs):
00350 check_one_option(options, 'lib_dirs')
00351 output = lib_dirs(ver)
00352 elif (options.cflags):
00353 check_one_option(options, 'cflags')
00354 output = cflags(ver)
00355 elif (options.lflags):
00356 check_one_option(options, 'lflags')
00357 output = lflags(ver, options.lflags.split(','))
00358 else:
00359 print_usage_and_exit()
00360
00361 print(output.strip())
00362
00363 if __name__ == "__main__":
00364 main()
00365