rosboost_cfg.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 # Copyright (c) 2010, Willow Garage, Inc.
00005 # All rights reserved.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions
00009 # are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #    notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #    copyright notice, this list of conditions and the following
00015 #    disclaimer in the documentation and/or other materials provided
00016 #    with the distribution.
00017 #  * Neither the name of Willow Garage, Inc. nor the names of its
00018 #    contributors may be used to endorse or promote products derived
00019 #    from this software without specific prior written permission.
00020 #
00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 # POSSIBILITY OF SUCH DAMAGE.
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   # prefer lib64 unless explicitly specified in the environment
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     # Boost.Python needs some special handling on some systems (Karmic), since it may have per-python-version libs
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         # Cut off "lib" and extension (.so/.a/.dylib/etc.)
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             


rosboost_cfg
Author(s): Josh Faust
autogenerated on Mon Oct 6 2014 06:50:53