1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
#!/usr/bin/env python3
# coding=utf-8
# Mathieu Courtois - EDF R&D, 2013 - http://www.code-aster.org
"""
When a project has a lot of options the 'waf configure' command line can be
very long and it becomes a cause of error.
This tool provides a convenient way to load a set of configuration parameters
from a local file or from a remote url.
The configuration parameters are stored in a Python file that is imported as
an extra waf tool can be.
Example:
$ waf configure --use-config-dir=http://www.anywhere.org --use-config=myconf1 ...
The file 'myconf1' will be downloaded from 'http://www.anywhere.org'
(or 'http://www.anywhere.org/wafcfg').
If the files are available locally, it could be:
$ waf configure --use-config-dir=/somewhere/myconfigurations --use-config=myconf1 ...
The configuration of 'myconf1.py' is automatically loaded by calling
its 'configure' function. In this example, it defines environment variables and
set options:
def configure(self):
self.env['CC'] = 'gcc-4.8'
self.env.append_value('LIBPATH', [...])
self.options.perlbinary = '/usr/local/bin/perl'
self.options.pyc = False
The corresponding command line should have been:
$ CC=gcc-4.8 LIBPATH=... waf configure --nopyc --with-perl-binary=/usr/local/bin/perl
This is an extra tool, not bundled with the default waf binary.
To add the use_config tool to the waf file:
$ ./waf-light --tools=use_config
When using this tool, the wscript will look like:
def options(opt):
opt.load('use_config')
def configure(conf):
conf.load('use_config')
"""
import sys
import os.path as osp
import os
local_repo = ''
"""Local repository containing additional Waf tools (plugins)"""
remote_repo = 'https://gitlab.com/ita1024/waf/raw/master/'
"""
Remote directory containing downloadable waf tools. The missing tools can be downloaded by using::
$ waf configure --download
"""
remote_locs = ['waflib/extras', 'waflib/Tools']
"""
Remote directories for use with :py:const:`waflib.extras.use_config.remote_repo`
"""
try:
from urllib import request
except ImportError:
from urllib import urlopen
else:
urlopen = request.urlopen
from waflib import Errors, Context, Logs, Utils, Options, Configure
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse
DEFAULT_DIR = 'wafcfg'
# add first the current wafcfg subdirectory
sys.path.append(osp.abspath(DEFAULT_DIR))
def options(self):
group = self.add_option_group('configure options')
group.add_option('--download', dest='download', default=False, action='store_true', help='try to download the tools if missing')
group.add_option('--use-config', action='store', default=None,
metavar='CFG', dest='use_config',
help='force the configuration parameters by importing '
'CFG.py. Several modules may be provided (comma '
'separated).')
group.add_option('--use-config-dir', action='store', default=DEFAULT_DIR,
metavar='CFG_DIR', dest='use_config_dir',
help='path or url where to find the configuration file')
def download_check(node):
"""
Hook to check for the tools which are downloaded. Replace with your function if necessary.
"""
pass
def download_tool(tool, force=False, ctx=None):
"""
Download a Waf tool from the remote repository defined in :py:const:`waflib.extras.use_config.remote_repo`::
$ waf configure --download
"""
for x in Utils.to_list(remote_repo):
for sub in Utils.to_list(remote_locs):
url = '/'.join((x, sub, tool + '.py'))
try:
web = urlopen(url)
try:
if web.getcode() != 200:
continue
except AttributeError:
pass
except Exception:
# on python3 urlopen throws an exception
# python 2.3 does not have getcode and throws an exception to fail
continue
else:
tmp = ctx.root.make_node(os.sep.join((Context.waf_dir, 'waflib', 'extras', tool + '.py')))
tmp.write(web.read(), 'wb')
Logs.warn('Downloaded %s from %s', tool, url)
download_check(tmp)
try:
module = Context.load_tool(tool)
except Exception:
Logs.warn('The tool %s from %s is unusable', tool, url)
try:
tmp.delete()
except Exception:
pass
continue
return module
raise Errors.WafError('Could not load the Waf tool')
def load_tool(tool, tooldir=None, ctx=None, with_sys_path=True):
try:
module = Context.load_tool_default(tool, tooldir, ctx, with_sys_path)
except ImportError as e:
if not ctx or not hasattr(Options.options, 'download'):
Logs.error('Could not load %r during options phase (download unavailable at this point)' % tool)
raise
if Options.options.download:
module = download_tool(tool, ctx=ctx)
if not module:
ctx.fatal('Could not load the Waf tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e))
else:
ctx.fatal('Could not load the Waf tool %r from %r (try the --download option?):\n%s' % (tool, sys.path, e))
return module
Context.load_tool_default = Context.load_tool
Context.load_tool = load_tool
Configure.download_tool = download_tool
def configure(self):
opts = self.options
use_cfg = opts.use_config
if use_cfg is None:
return
url = urlparse(opts.use_config_dir)
kwargs = {}
if url.scheme:
kwargs['download'] = True
kwargs['remote_url'] = url.geturl()
# search first with the exact url, else try with +'/wafcfg'
kwargs['remote_locs'] = ['', DEFAULT_DIR]
tooldir = url.geturl() + ' ' + DEFAULT_DIR
for cfg in use_cfg.split(','):
Logs.pprint('NORMAL', "Searching configuration '%s'..." % cfg)
self.load(cfg, tooldir=tooldir, **kwargs)
self.start_msg('Checking for configuration')
self.end_msg(use_cfg)
|