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