summaryrefslogtreecommitdiffstats
path: root/build/moz.configure/checks.configure
diff options
context:
space:
mode:
Diffstat (limited to 'build/moz.configure/checks.configure')
-rw-r--r--build/moz.configure/checks.configure144
1 files changed, 144 insertions, 0 deletions
diff --git a/build/moz.configure/checks.configure b/build/moz.configure/checks.configure
new file mode 100644
index 000000000..8c2dbc0cc
--- /dev/null
+++ b/build/moz.configure/checks.configure
@@ -0,0 +1,144 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Templates implementing some generic checks.
+# ==============================================================
+
+# Declare some exceptions. This is cumbersome, but since we shouldn't need a
+# lot of them, let's stack them all here. When adding a new one, put it in the
+# _declare_exceptions template, and add it to the return statement. Then
+# destructure in the assignment below the function declaration.
+@template
+@imports(_from='__builtin__', _import='Exception')
+def _declare_exceptions():
+ class FatalCheckError(Exception):
+ '''An exception to throw from a function decorated with @checking.
+ It will result in calling die() with the given message.
+ Debugging messages emitted from the decorated function will also be
+ printed out.'''
+ return (FatalCheckError,)
+
+(FatalCheckError,) = _declare_exceptions()
+
+del _declare_exceptions
+
+# Helper to display "checking" messages
+# @checking('for foo')
+# def foo():
+# return 'foo'
+# is equivalent to:
+# def foo():
+# log.info('checking for foo... ')
+# ret = foo
+# log.info(ret)
+# return ret
+# This can be combined with e.g. @depends:
+# @depends(some_option)
+# @checking('for something')
+# def check(value):
+# ...
+# An optional callback can be given, that will be used to format the returned
+# value when displaying it.
+@template
+def checking(what, callback=None):
+ def decorator(func):
+ def wrapped(*args, **kwargs):
+ log.info('checking %s... ', what)
+ with log.queue_debug():
+ error, ret = None, None
+ try:
+ ret = func(*args, **kwargs)
+ except FatalCheckError as e:
+ error = e.message
+ display_ret = callback(ret) if callback else ret
+ if display_ret is True:
+ log.info('yes')
+ elif display_ret is False or display_ret is None:
+ log.info('no')
+ else:
+ log.info(display_ret)
+ if error is not None:
+ die(error)
+ return ret
+ return wrapped
+ return decorator
+
+
+# Template to check for programs in $PATH.
+# - `var` is the name of the variable that will be set with `set_config` when
+# the program is found.
+# - `progs` is a list (or tuple) of program names that will be searched for.
+# It can also be a reference to a @depends function that returns such a
+# list. If the list is empty and there is no input, the check is skipped.
+# - `what` is a human readable description of what is being looked for. It
+# defaults to the lowercase version of `var`.
+# - `input` is a string reference to an existing option or a reference to a
+# @depends function resolving to explicit input for the program check.
+# The default is to create an option for the environment variable `var`.
+# This argument allows to use a different kind of option (possibly using a
+# configure flag), or doing some pre-processing with a @depends function.
+# - `allow_missing` indicates whether not finding the program is an error.
+# - `paths` is a list of paths or @depends function returning a list of paths
+# that will cause the given path(s) to be searched rather than $PATH. Input
+# paths may either be individual paths or delimited by os.pathsep, to allow
+# passing $PATH (for example) as an element.
+#
+# The simplest form is:
+# check_prog('PROG', ('a', 'b'))
+# This will look for 'a' or 'b' in $PATH, and set_config PROG to the one
+# it can find. If PROG is already set from the environment or command line,
+# use that value instead.
+@template
+@imports(_from='mozbuild.shellutil', _import='quote')
+def check_prog(var, progs, what=None, input=None, allow_missing=False,
+ paths=None):
+ if input:
+ # Wrap input with type checking and normalization.
+ @depends(input)
+ def input(value):
+ if not value:
+ return
+ if isinstance(value, str):
+ return (value,)
+ if isinstance(value, (tuple, list)) and len(value) == 1:
+ return value
+ configure_error('input must resolve to a tuple or a list with a '
+ 'single element, or a string')
+ else:
+ option(env=var, nargs=1,
+ help='Path to %s' % (what or 'the %s program' % var.lower()))
+ input = var
+ what = what or var.lower()
+
+ # Trick to make a @depends function out of an immediate value.
+ progs = dependable(progs)
+ paths = dependable(paths)
+
+ @depends_if(input, progs, paths)
+ @checking('for %s' % what, lambda x: quote(x) if x else 'not found')
+ def check(value, progs, paths):
+ if progs is None:
+ progs = ()
+
+ if not isinstance(progs, (tuple, list)):
+ configure_error('progs must resolve to a list or tuple!')
+
+ for prog in value or progs:
+ log.debug('%s: Trying %s', var.lower(), quote(prog))
+ result = find_program(prog, paths)
+ if result:
+ return result
+
+ if not allow_missing or value:
+ raise FatalCheckError('Cannot find %s' % what)
+
+ @depends_if(check, progs)
+ def normalized_for_config(value, progs):
+ return ':' if value is None else value
+
+ set_config(var, normalized_for_config)
+
+ return check