with_selector.py (5056B)
1 from waflib.Configure import conf 2 from waflib.Errors import ConfigurationError 3 from waflib.Options import OptionsContext 4 from waflib import Context, Utils 5 import sys 6 7 all_optional = set() 8 9 all_default = {} 10 all_set = {'system': {}, 'bundle': {}} 11 12 def options(opt): 13 grp = opt.add_option_group('Dependency selection options') 14 grp.add_option('--all-bundled', dest='all_system', 15 action='store_const', const='bundle', 16 help="Use bundled libs where it's generally ok") 17 grp.add_option('--all-system', dest='all_system', 18 action='store_const', const='system', 19 help="Disable bundled libs where it's generally ok") 20 21 def configure(cfg): 22 if cfg.options.all_system: 23 x = all_set[cfg.options.all_system] 24 for k in x: 25 if getattr(cfg.options, k, None) == None: 26 setattr(cfg.options, k, x[k]) 27 28 29 30 def with_opt(ctx, name, variants, default, help=None, cross=False, 31 bundle_all=None, system_all=None): 32 grp = ctx.get_option_group('Dependency selection options') 33 help = help or 'Select %s' % name 34 help_tail = "\v[default: %r" % default 35 if bundle_all: help_tail += ', --all-bundled: %r' % bundle_all 36 if system_all: help_tail += ', --all-system: %r' % system_all 37 help_tail += ']' 38 39 def x(name, help): 40 wname = 'with_' + name 41 helpmsg = '%s: %s%s' % (help, ', '.join(variants), help_tail) 42 all_default[wname] = default 43 if bundle_all: all_set['bundle'][wname] = bundle_all 44 if system_all: all_set['system'][wname] = system_all 45 if 'none' in variants: all_optional.add(name) 46 47 grp.add_option('--with-'+name, dest=wname, action='store', help=helpmsg) 48 if 'none' in variants: 49 grp.add_option( 50 '--without-'+name, dest=wname, 51 action='store_const', const='none', 52 help='Disable %s (same as --with-%s=none)' % (name, name)) 53 54 x(name, help) 55 if cross: x(name + '-host', help + ' (for host)') 56 OptionsContext.with_opt = with_opt 57 58 def system_opt(ctx, name, help=None, cross=False, optional=False): 59 variants = ['bundle', 'system'] 60 if optional: 61 variants.append('none') 62 system = 'system,none' 63 else: 64 system = 'system' 65 with_opt(ctx, name, variants, help=help, cross=cross, 66 default='system,bundle', bundle_all='bundle', system_all=system) 67 OptionsContext.system_opt = system_opt 68 69 70 app = Context.g_module.APPNAME.upper() 71 72 def run_fun(ctx, fun, def_name): 73 if fun == None: 74 return 75 76 if isinstance(fun, str): 77 incl_dir = ctx.path.find_dir(fun) 78 if not incl_dir: 79 ctx.fatal('%s/%s not found. Are git submodules missing?' % 80 (ctx.path.abspath(), fun)) 81 82 ctx.env['SYSTEM_INCLUDES_' + def_name] = incl_dir.abspath() 83 return 84 85 return fun(ctx) 86 87 # crosscomp libs mess around with variants, so stash every variant 88 def save_envs(ctx): 89 stashed = set() 90 for k in ctx.all_envs: 91 stashed.add(k) 92 ctx.all_envs[k].stash() 93 return stashed 94 95 def revert_envs(ctx, stashed): 96 for k in stashed: 97 ctx.all_envs[k].revert() 98 99 def commit_envs(ctx, stashed): 100 for k in stashed: 101 ctx.all_envs[k].commit() 102 103 104 @conf 105 # chk_fun: if string, header only lib's include path 106 def with_chk(ctx, name, chks, cross=False, post_chk=None, define=None, 107 define_name=None): 108 def_name = define_name or Utils.quote_define_name(name) 109 envname = 'WITH_' + def_name 110 defines = 'DEFINES_' + def_name 111 112 if define == None and name in all_optional: 113 define = app + '_WITH_' + def_name 114 if 'none' not in chks: 115 chks['none'] = None 116 117 def x(name): 118 wname = 'with_' + name 119 opts = (getattr(ctx.options, wname) or all_default[wname]).split(',') 120 if opts == []: 121 ctx.fatal('No value specified for --with-%s' % name) 122 123 last_except = None 124 for opt in opts: 125 if not opt in chks: 126 ctx.fatal('Unknown option for --with-%s: %s' % (name, opt)) 127 128 saved = save_envs(ctx) 129 try: 130 run_fun(ctx, chks[opt], def_name) 131 ctx.env[envname] = opt 132 133 if define: 134 val = '%s=%s' % (define, opt != 'none' and 1 or 0) 135 ctx.env.append_value(defines, val) 136 if post_chk: post_chk(ctx) 137 ctx.msg('Using ' + name, opt, 138 color = opt != 'none' and 'GREEN' or 'YELLOW') 139 140 commit_envs(ctx, saved) 141 return 142 except ConfigurationError: 143 revert_envs(ctx, saved) 144 last_except = sys.exc_info() 145 146 if sys.hexversion < 0x3000000: 147 exec('raise last_except[0], last_except[1], last_except[2]') 148 else: 149 exec('raise last_except[0].with_traceback(last_except[1], last_except[2])') 150 151 x(name) 152 if cross: ctx.only_host_env(lambda bull,shit: x(name+'-host'))