2 # Copyright (C) 2017 Karl Linden
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
8 # 1. Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 from waflib
import Configure
, Logs
, Options
, Utils
33 # A list of AutoOptions. It is local to each module, so all modules that
34 # use AutoOptions need to run both opt.load and conf.load. In contrast
35 # to the define and style options this does not need to and cannot be
36 # declared in the OptionsContext, because it is needed both for the
37 # options and the configure phase.
42 This class represents an auto option that can be used in conjunction
43 with the waf build system. By default it adds options --foo and
44 --no-foo respectively to turn on or off foo respectively.
45 Furthermore it incorporats logic and checks that are required for
48 An option can have an arbitrary number of dependencies that must be
49 present for the option to be enabled. An option can be enabled or
50 disabled by default. Here is how the logic works:
51 1. If the option is explicitly disabled, through --no-foo, then no
52 checks are made and the option is disabled.
53 2. If the option is explicitly enabled, through --foo, then check
54 for all required dependencies, and if some of them are not
55 found, then print a fatal error telling the user there were
57 3. Otherwise, if the option is enabled by default, then check for
58 all dependencies. If all dependencies are found the option is
59 enabled. Otherwise it is disabled.
60 4. Lastly, if no option was given and the option is disabled by
61 default, then no checks are performed and the option is
64 To add a dependency to an option use the check, check_cfg and
65 find_program methods of this class. The methods are merely small
66 wrappers around their configuration context counterparts and behave
67 identically. Note that adding dependencies is done in the options
68 phase and not in the configure phase, although the checks are
69 acutally executed during the configure phase.
71 Custom check functions can be added using the add_function method.
72 As with the other checks the check function will be invoked during
73 the configuration. Refer to the documentation of the add_function
76 When all checks have been made and the class has made a decision the
77 result is saved in conf.env['NAME'] where 'NAME' by default is the
78 uppercase of the name argument to __init__, with hyphens replaced by
79 underscores. This default can be changed with the conf_dest argument
82 The class will define a preprocessor symbol with the result. The
83 default name is WITH_NAME, to not collide with the standard define
84 of check_cfg, but it can be changed using the define argument to
85 __init__. It can also be changed globally using
86 set_auto_options_define.
89 def __init__(self
, opt
, name
, help=None, default
=True,
90 conf_dest
=None, define
=None, style
=None):
92 Class initializing method.
96 name name of the option, e.g. alsa
97 help help text that will be displayed in --help output
98 conf_dest conf.env variable to define to the result
99 define the preprocessor symbol to define with the result
100 style the option style to use; see below for options
103 # The dependencies to check for. The elements are on the form
104 # (func, k, kw) where func is the function or function name that
105 # is used for the check and k and kw are the arguments and
106 # options to give the function.
109 # Whether or not the option should be enabled. None indicates
110 # that the checks have not been performed yet.
116 help_comment
= ' (enabled by default if possible)'
118 help_comment
= ' (disabled by default)'
119 option_help
= help + help_comment
120 no_option_help
= None
122 option_help
= no_option_help
= optparse
.SUPPRESS_HELP
124 self
.dest
= 'auto_option_' + name
126 self
.default
= default
128 safe_name
= Utils
.quote_define_name(name
)
129 self
.conf_dest
= conf_dest
or safe_name
131 default_define
= opt
.get_auto_options_define()
132 self
.define
= define
or default_define
% safe_name
135 style
= opt
.get_auto_options_style()
141 # --foo=yes | --foo=no
143 # --foo[=yes] | --foo=no or --no-foo
145 # --enable-foo | --disble-foo
147 # --with-foo | --without-foo
148 if style
in ['plain', 'yesno', 'yesno_and_hack']:
149 self
.no_option
= '--no-' + name
150 self
.yes_option
= '--' + name
151 elif style
== 'enable':
152 self
.no_option
= '--disable-' + name
153 self
.yes_option
= '--enable-' + name
154 elif style
== 'with':
155 self
.no_option
= '--without-' + name
156 self
.yes_option
= '--with-' + name
158 opt
.fatal('invalid style')
160 if style
in ['yesno', 'yesno_and_hack']:
165 choices
=['auto', 'no', 'yes'],
173 action
='store_const',
180 action
='store_const',
185 def check(self
, *k
, **kw
):
186 self
.deps
.append(('check', k
, kw
))
187 def check_cfg(self
, *k
, **kw
):
188 self
.deps
.append(('check_cfg', k
, kw
))
189 def find_program(self
, *k
, **kw
):
190 self
.deps
.append(('find_program', k
, kw
))
192 def add_function(self
, func
, *k
, **kw
):
194 Add a custom function to be invoked as part of the
195 configuration. During the configuration the function will be
196 invoked with the configuration context as first argument
197 followed by the arugments to this method, except for the func
198 argument. The function must print a 'Checking for...' message,
199 because it is referred to if the check fails and this option is
202 On configuration error the function shall raise
203 conf.errors.ConfigurationError.
205 self
.deps
.append((func
, k
, kw
))
207 def _check(self
, conf
, required
):
209 This private method checks all dependencies. It checks all
210 dependencies (even if some dependency was not found) so that the
211 user can install all missing dependencies in one go, instead of
212 playing the infamous hit-configure-hit-configure game.
214 This function returns True if all dependencies were found and
219 for (f
,k
,kw
) in self
.deps
:
220 if hasattr(f
, '__call__'):
221 # This is a function supplied by add_function.
227 func
= getattr(conf
, f
)
231 except conf
.errors
.ConfigurationError
:
234 Logs
.error('The above check failed, but the '
235 'checkee is required for %s.' %
240 def configure(self
, conf
):
242 This function configures the option examining the command line
243 option. It sets self.enable to whether this options should be
244 enabled or not, that is True or False respectively. If not all
245 dependencies were found self.enable will be False.
246 conf.env['NAME'] and a preprocessor symbol will be defined with
249 If the option was desired but one or more dependencies were not
250 found the an error message will be printed for each missing
253 This function returns True on success and False on if the option
254 was requested but cannot be enabled.
256 # If the option has already been configured once, do not
257 # configure it again.
258 if self
.enable
!= None:
261 argument
= getattr(Options
.options
, self
.dest
)
265 elif argument
== 'yes':
266 retvalue
= self
.enable
= self
._check
(conf
, True)
268 self
.enable
= self
.default
and self
._check
(conf
, False)
271 conf
.env
[self
.conf_dest
] = self
.enable
272 conf
.define(self
.define
, int(self
.enable
))
275 def summarize(self
, conf
):
277 This function displays a result summary with the help text and
278 the result of the configuration.
282 conf
.msg(self
.help, 'yes', color
='GREEN')
284 conf
.msg(self
.help, 'no', color
='YELLOW')
288 This function declares necessary variables in the option context.
289 The reason for saving variables in the option context is to allow
290 autooptions to be loaded from modules (which will receive a new
291 instance of this module, clearing any global variables) with a
292 uniform style and default in the entire project.
294 Call this function through opt.load('autooptions').
296 if not hasattr(opt
, 'auto_options_style'):
297 opt
.auto_options_style
= 'plain'
298 if not hasattr(opt
, 'auto_options_define'):
299 opt
.auto_options_define
= 'WITH_%s'
303 Decorator: attach a new option function to Options.OptionsContext.
305 :param f: method to bind
308 setattr(Options
.OptionsContext
, f
.__name
__, f
)
311 def add_auto_option(self
, *k
, **kw
):
313 This function adds an AutoOption to the options context. It takes
314 the same arguments as the initializer funtion of the AutoOptions
317 option
= AutoOption(self
, *k
, **kw
)
318 auto_options
.append(option
)
322 def get_auto_options_define(self
):
324 This function gets the default define name. This default can be
325 changed through set_auto_optoins_define.
327 return self
.auto_options_define
330 def set_auto_options_define(self
, define
):
332 This function sets the default define name. The default is
333 'WITH_%s', where %s will be replaced with the name of the option in
336 self
.auto_options_define
= define
339 def get_auto_options_style(self
):
341 This function gets the default option style, which will be used for
342 the subsequent options.
344 return self
.auto_options_style
347 def set_auto_options_style(self
, style
):
349 This function sets the default option style, which will be used for
350 the subsequent options.
352 self
.auto_options_style
= style
355 def apply_auto_options_hack(self
):
357 This function applies the hack necessary for the yesno_and_hack
358 option style. The hack turns --foo into --foo=yes and --no-foo into
361 It must be called before options are parsed, that is before the
364 for option
in auto_options
:
365 # With the hack the yesno options simply extend plain options.
366 if option
.style
== 'yesno_and_hack':
367 for i
in range(1, len(sys
.argv
)):
368 if sys
.argv
[i
] == option
.yes_option
:
369 sys
.argv
[i
] = option
.yes_option
+ '=yes'
370 elif sys
.argv
[i
] == option
.no_option
:
371 sys
.argv
[i
] = option
.yes_option
+ '=no'
374 def summarize_auto_options(self
):
376 This function prints a summary of the configuration of the auto
377 options. Obviously, it must be called after
378 conf.load('autooptions').
380 for option
in auto_options
:
381 option
.summarize(self
)
385 This configures all auto options. Call it through
386 conf.load('autooptions').
389 for option
in auto_options
:
390 if not option
.configure(conf
):
393 conf
.fatal('Some requested options had unsatisfied ' +
395 'See the above configuration for details.')