summaryrefslogtreecommitdiffstats
path: root/src/boost/tools/boostdep/depinst/depinst.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/tools/boostdep/depinst/depinst.py')
-rw-r--r--src/boost/tools/boostdep/depinst/depinst.py282
1 files changed, 282 insertions, 0 deletions
diff --git a/src/boost/tools/boostdep/depinst/depinst.py b/src/boost/tools/boostdep/depinst/depinst.py
new file mode 100644
index 000000000..6dfba36a7
--- /dev/null
+++ b/src/boost/tools/boostdep/depinst/depinst.py
@@ -0,0 +1,282 @@
+#!/usr/bin/env python
+
+# depinst.py - installs the dependencies needed to test
+# a Boost library
+#
+# Copyright 2016-2020 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+from __future__ import print_function
+
+import re
+import sys
+import os
+import argparse
+
+verbose = 0
+
+def vprint( level, *args ):
+
+ if verbose >= level:
+ print( *args )
+
+
+def is_module( m, gm ):
+
+ return ( 'libs/' + m ) in gm
+
+
+def module_for_header( h, x, gm ):
+
+ if h in x:
+
+ return x[ h ]
+
+ else:
+
+ # boost/function.hpp
+ m = re.match( 'boost/([^\\./]*)\\.h[a-z]*$', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/numeric/conversion.hpp
+ m = re.match( 'boost/([^/]*/[^\\./]*)\\.h[a-z]*$', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/numeric/conversion/header.hpp
+ m = re.match( 'boost/([^/]*/[^/]*)/', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ # boost/function/header.hpp
+ m = re.match( 'boost/([^/]*)/', h )
+
+ if m and is_module( m.group( 1 ), gm ):
+
+ return m.group( 1 )
+
+ vprint( 0, 'Cannot determine module for header', h )
+
+ return None
+
+
+def scan_header_dependencies( f, x, gm, deps ):
+
+ for line in f:
+
+ m = re.match( '[ \t]*#[ \t]*include[ \t]*["<](boost/[^">]*)[">]', line )
+
+ if m:
+
+ h = m.group( 1 )
+
+ mod = module_for_header( h, x, gm )
+
+ if mod:
+
+ if not mod in deps:
+
+ vprint( 1, 'Adding dependency', mod )
+ deps[ mod ] = 0
+
+
+def scan_directory( d, x, gm, deps ):
+
+ vprint( 1, 'Scanning directory', d )
+
+ if os.name == 'nt' and sys.version_info[0] < 3:
+ d = unicode( d )
+
+ for root, dirs, files in os.walk( d ):
+
+ for file in files:
+
+ fn = os.path.join( root, file )
+
+ vprint( 2, 'Scanning file', fn )
+
+ if sys.version_info[0] < 3:
+
+ with open( fn, 'r' ) as f:
+ scan_header_dependencies( f, x, gm, deps )
+
+ else:
+
+ with open( fn, 'r', encoding='latin-1' ) as f:
+ scan_header_dependencies( f, x, gm, deps )
+
+
+def scan_module_dependencies( m, x, gm, deps, dirs ):
+
+ vprint( 1, 'Scanning module', m )
+
+ for dir in dirs:
+ scan_directory( os.path.join( 'libs', m, dir ), x, gm, deps )
+
+
+def read_exceptions():
+
+ # exceptions.txt is the output of "boostdep --list-exceptions"
+
+ vprint( 1, 'Reading exceptions.txt' )
+
+ x = {}
+
+ module = None
+
+ with open( os.path.join( os.path.dirname( sys.argv[0] ), 'exceptions.txt' ), 'r' ) as f:
+
+ for line in f:
+
+ line = line.rstrip()
+
+ m = re.match( '(.*):$', line )
+
+ if m:
+
+ module = m.group( 1 ).replace( '~', '/' )
+
+ else:
+
+ header = line.lstrip()
+ x[ header ] = module
+
+ return x
+
+
+def read_gitmodules():
+
+ vprint( 1, 'Reading .gitmodules' )
+
+ gm = []
+
+ with open( '.gitmodules', 'r' ) as f:
+
+ for line in f:
+
+ line = line.strip()
+
+ m = re.match( 'path[ \t]*=[ \t]*(.*)$', line )
+
+ if m:
+
+ gm.append( m.group( 1 ) )
+
+ return gm
+
+def install_modules( modules, git_args ):
+
+ if len( modules ) == 0:
+ return
+
+ vprint( 0, 'Installing:', ', '.join(modules) )
+
+ modules = [ 'libs/' + m for m in modules ]
+
+ command = 'git submodule'
+
+ if verbose <= 0:
+ command += ' -q'
+
+ command += ' update --init ' + git_args + ' ' + ' '.join( modules )
+
+ vprint( 1, 'Executing:', command )
+ r = os.system( command );
+
+ if r != 0:
+ raise Exception( "The command '%s' failed with exit code %d" % (command, r) )
+
+
+def install_module_dependencies( deps, x, gm, git_args ):
+
+ modules = []
+
+ for m, i in deps.items():
+
+ if not i:
+
+ modules += [ m ]
+ deps[ m ] = 1 # mark as installed
+
+ if len( modules ) == 0:
+ return 0
+
+ install_modules( modules, git_args )
+
+ for m in modules:
+ scan_module_dependencies( m, x, gm, deps, [ 'include', 'src' ] )
+
+ return len( modules )
+
+
+if( __name__ == "__main__" ):
+
+ parser = argparse.ArgumentParser( description='Installs the dependencies needed to test a Boost library.' )
+
+ parser.add_argument( '-v', '--verbose', help='enable verbose output', action='count', default=0 )
+ parser.add_argument( '-q', '--quiet', help='quiet output (opposite of -v)', action='count', default=0 )
+ parser.add_argument( '-X', '--exclude', help="exclude a default subdirectory ('include', 'src', or 'test') from scan; can be repeated", metavar='DIR', action='append', default=[] )
+ parser.add_argument( '-N', '--ignore', help="exclude top-level dependency even when found in scan; can be repeated", metavar='LIB', action='append', default=[] )
+ parser.add_argument( '-I', '--include', help="additional subdirectory to scan; can be repeated", metavar='DIR', action='append', default=[] )
+ parser.add_argument( '-g', '--git_args', help="additional arguments to `git submodule update`", default='', action='store' )
+ parser.add_argument( '-u', '--update', help='update <library> before scanning', action='store_true' )
+ parser.add_argument( 'library', help="name of library to scan ('libs/' will be prepended)" )
+
+ args = parser.parse_args()
+
+ verbose = args.verbose - args.quiet
+
+ vprint( 2, '-X:', args.exclude )
+ vprint( 2, '-I:', args.include )
+ vprint( 2, '-N:', args.ignore )
+
+ x = read_exceptions()
+ vprint( 2, 'Exceptions:', x )
+
+ gm = read_gitmodules()
+ vprint( 2, '.gitmodules:', gm )
+
+ essentials = [ 'config', 'headers', '../tools/boost_install', '../tools/build', '../tools/cmake' ]
+
+ essentials = [ e for e in essentials if os.path.exists( 'libs/' + e ) ]
+
+ if args.update:
+ essentials.append( args.library )
+
+ install_modules( essentials, args.git_args )
+
+ m = args.library
+
+ deps = { m : 1 }
+
+ dirs = [ 'include', 'src', 'test' ]
+
+ for dir in args.exclude:
+ dirs.remove( dir )
+
+ for dir in args.include:
+ dirs.append( dir )
+
+ vprint( 1, 'Directories to scan:', *dirs )
+
+ scan_module_dependencies( m, x, gm, deps, dirs )
+
+ for dep in args.ignore:
+ if dep in deps:
+ vprint( 1, 'Ignoring dependency', dep )
+ del deps[dep]
+
+ vprint( 2, 'Dependencies:', deps )
+
+ while install_module_dependencies( deps, x, gm, args.git_args ):
+ pass