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