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 import sys
00035 import os
00036 import string
00037 from glob import glob
00038 import subprocess
00039 import platform
00040 from optparse import OptionParser
00041 from cStringIO import StringIO
00042
00043 lib_suffix = "so"
00044 if (sys.platform == "darwin"):
00045 lib_suffix = "dylib"
00046
00047 link_static = 'ROS_BOOST_LINK' in os.environ and os.environ['ROS_BOOST_LINK'] == "static"
00048 if (link_static):
00049 lib_suffix = "a"
00050
00051 no_L_or_I = 'ROS_BOOST_NO_L_OR_I' in os.environ
00052
00053 boost_version = None
00054 if ('ROS_BOOST_VERSION' in os.environ and len(os.environ['ROS_BOOST_VERSION']) > 0):
00055 ver = os.environ['ROS_BOOST_VERSION']
00056 ver = ver.split('.')
00057
00058 boost_version = [int(v) for v in ver]
00059 if (len(boost_version) == 2):
00060 boost_version.append(0)
00061
00062 def print_usage_and_exit():
00063 print >> sys.stderr, "Usage: rosboost-cfg --lflags [thread,regex,graph,...]"
00064 print >> sys.stderr, " rosboost-cfg --cflags"
00065 print >> sys.stderr, " rosboost-cfg --libs [thread,regex,graph,...]"
00066 print >> sys.stderr, " rosboost-cfg --include_dirs"
00067 print >> sys.stderr, " rosboost-cfg --lib_dirs"
00068 print >> sys.stderr, " rosboost-cfg --root"
00069 sys.exit(1)
00070
00071 class BoostError(Exception):
00072 def __init__(self, value):
00073 self.value = value
00074 def __str__(self):
00075 return repr(self.value)
00076
00077 class Version(object):
00078 def __init__(self, major, minor, patch, root, include_dir, lib_dir, is_default_search_location):
00079 self.major = major
00080 self.minor = minor
00081 self.patch = patch
00082 self.root = root
00083 self.include_dir = include_dir
00084 self.lib_dir = lib_dir
00085 self.is_default_search_location = is_default_search_location
00086 self.is_system_install = os.path.split(self.include_dir)[0] == self.root
00087
00088 def __cmp__(self, other):
00089 if (self.major != other.major):
00090 if self.major < other.major:
00091 return -1
00092 else:
00093 return 1
00094 if (self.minor != other.minor):
00095 if self.minor < other.minor:
00096 return -1
00097 else:
00098 return 1
00099 if (self.patch != other.patch):
00100 if self.patch < other.patch:
00101 return -1
00102 else:
00103 return 1
00104
00105 return 0
00106 def __repr__(self):
00107 return repr((self.major, self.minor, self.patch, self.root, self.include_dir, self.is_default_search_location, self.is_system_install))
00108
00109 def find_lib_dir(root_dir):
00110
00111 if ('ROS_BOOST_LIB_DIR_NAME' in os.environ):
00112 possible_dirs = [os.path.join(root_dir, os.environ['ROS_BOOST_LIB_DIR_NAME'])]
00113 else:
00114 possible_dirs = [os.path.join(root_dir, "lib64"), os.path.join(root_dir, "lib")]
00115
00116 for p in possible_dirs:
00117 glob_files = glob("%s*"%(os.path.join(p, "libboost*")))
00118 if (len(glob_files) > 0):
00119 return p
00120
00121 return None
00122
00123 def extract_versions(dir, is_default_search_location):
00124 version_paths = [os.path.join(dir, "version.hpp"),
00125 os.path.join(dir, "boost", "version.hpp")]
00126 glob_dirs = glob("%s*"%(os.path.join(dir, "boost-")))
00127 [version_paths.append(os.path.join(gdir, "boost", "version.hpp")) for gdir in glob_dirs]
00128
00129 versions = []
00130
00131 for p in version_paths:
00132 ver_string = ""
00133 if (os.path.isfile(p)):
00134 fh = open(p,"r")
00135 lines = fh.readlines()
00136 fh.close()
00137 for line in lines:
00138 if line.find("#define BOOST_VERSION ") > -1:
00139 def_string = line.split()
00140 ver_string = def_string[2]
00141 ver_int = int(ver_string)
00142 patch = ver_int % 100
00143 minor = ver_int / 100 % 1000
00144 major = ver_int / 100000
00145 include_dir = os.path.split(os.path.split(p)[0])[0]
00146 root_dir = os.path.split(dir)[0]
00147 lib_dir = find_lib_dir(root_dir)
00148 versions.append(Version(major, minor, patch, root_dir, include_dir, lib_dir, is_default_search_location))
00149
00150 return versions
00151
00152 def find_versions(search_paths):
00153 vers = []
00154
00155 for path, system in search_paths:
00156 path = os.path.join(path, "include")
00157 pvers = extract_versions(path, system)
00158 [vers.append(ver) for ver in pvers]
00159
00160 if (len(vers) == 0):
00161 return None
00162
00163 if (boost_version is not None):
00164 for v in vers:
00165 if (v.major == boost_version[0] and v.minor == boost_version[1] and v.patch == boost_version[2]):
00166 return [v]
00167
00168 raise BoostError('Could not find boost version %s required by ROS_BOOST_VERSION environment variable'%(boost_version))
00169
00170 vers.sort()
00171 return vers
00172
00173 def find_boost(search_paths):
00174 result = find_versions(search_paths)
00175 if result is None:
00176 return None
00177 return result[-1]
00178
00179 def search_paths(sysroot):
00180 _search_paths = [(sysroot+'/usr', True),
00181 (sysroot+'/usr/local', True),
00182 (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True),
00183 (None if 'CPATH' not in os.environ else os.environ['CPATH'], True),
00184 (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True),
00185 (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True),
00186 (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)]
00187
00188 search_paths = []
00189 for (str, system) in _search_paths:
00190 if (str is not None):
00191 dirs = str.split(':')
00192 for dir in dirs:
00193 if (len(dir) > 0):
00194 if (dir.endswith('/include')):
00195 dir = dir[:-len('/include')]
00196 search_paths.append((dir, system))
00197 return search_paths
00198
00199 def lib_dir(ver):
00200 return ver.lib_dir
00201
00202 def find_lib(ver, name, full_lib = link_static):
00203 global lib_suffix
00204 global link_static
00205
00206 dynamic_search_paths = []
00207 static_search_paths = []
00208
00209 if (ver.is_system_install):
00210 dynamic_search_paths = ["libboost_%s-mt.%s"%(name, lib_suffix),
00211 "libboost_%s.%s"%(name, lib_suffix)]
00212 static_search_paths = ["libboost_%s-mt.a"%(name),
00213 "libboost_%s.a"%(name)]
00214 else:
00215 dynamic_search_paths = ["libboost_%s*%s_%s*.%s"%(name, ver.major, ver.minor, lib_suffix),
00216 "libboost_%s-mt*.%s"%(name, lib_suffix),
00217 "libboost_%s*.%s"%(name, lib_suffix)]
00218 static_search_paths = ["libboost_%s*%s_%s*.a"%(name, ver.major, ver.minor),
00219 "libboost_%s-mt*.a"%(name),
00220 "libboost_%s*.a"%(name)]
00221
00222
00223 if (name == "python"):
00224 python_ver = platform.python_version().split('.')
00225 dynamic_search_paths = ["libboost_%s-mt-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix),
00226 "libboost_%s-py%s%s.%s"%(name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths
00227 static_search_paths = ["libboost_%s-mt-py%s%s.a"%(name, python_ver[0], python_ver[1]),
00228 "libboost_%s-py%s%s.a"%(name, python_ver[0], python_ver[1])] + static_search_paths
00229
00230 search_paths = static_search_paths if link_static else dynamic_search_paths
00231
00232 dir = lib_dir(ver)
00233
00234 if (dir is None):
00235 raise BoostError('Could not locate library [%s]'%(name))
00236
00237 for p in search_paths:
00238 globstr = os.path.join(dir, p)
00239 libs = glob(globstr)
00240 if (len(libs) > 0):
00241 if (full_lib):
00242 return libs[0]
00243 else:
00244 return os.path.basename(libs[0])
00245
00246 raise BoostError('Could not locate library [%s] in lib directory [%s]'%(name, dir))
00247
00248 def include_dirs(ver, prefix = ''):
00249 if (ver.is_system_install or no_L_or_I):
00250 return ""
00251
00252 return " %s%s"%(prefix, ver.include_dir)
00253
00254 def cflags(ver):
00255 return include_dirs(ver, '-I')
00256
00257 def lib_dir_flags(ver):
00258 if (not ver.is_default_search_location):
00259 dir = lib_dir(ver)
00260 return ' -L%s -Wl,-rpath,%s'%(dir, dir)
00261
00262 return ''
00263
00264 def lib_flags(ver, name):
00265 lib = find_lib(ver, name)
00266 if (link_static):
00267 return ' %s'%(lib)
00268 else:
00269
00270 return ' -l%s'%(os.path.splitext(lib)[0][len('lib'):])
00271
00272 def lflags(ver, libs):
00273 s = StringIO()
00274 print >> s, lib_dir_flags(ver),
00275 for lib in libs:
00276 print >> s, lib_flags(ver, lib),
00277
00278 return s.getvalue()
00279
00280 def libs(ver, libs):
00281 s = StringIO()
00282 for lib in libs:
00283 print >> s, find_lib(ver, lib, True),
00284
00285 return s.getvalue()
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