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, multiarch=''):
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     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     # Boost.Python needs some special handling on some systems (Karmic), since it may have per-python-version libs
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         # Cut off "lib" and extension (.so/.a/.dylib/etc.)
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             


rosboost_cfg
Author(s): Josh Faust
autogenerated on Thu Mar 9 2017 05:00:39