2013-07-16 11:28:28 +00:00
|
|
|
import os
|
2015-07-26 13:00:47 +00:00
|
|
|
import inflector
|
2013-11-24 14:49:34 +00:00
|
|
|
from waflib.ConfigSet import ConfigSet
|
2013-12-04 17:57:29 +00:00
|
|
|
from waflib import Utils
|
2013-07-16 11:28:28 +00:00
|
|
|
|
|
|
|
__all__ = [
|
|
|
|
"check_pkg_config", "check_cc", "check_statement", "check_libs",
|
|
|
|
"check_headers", "compose_checks", "check_true", "any_version",
|
2014-09-03 21:44:38 +00:00
|
|
|
"load_fragment", "check_stub", "check_ctx_vars", "check_program"]
|
2013-07-16 11:28:28 +00:00
|
|
|
|
|
|
|
any_version = None
|
|
|
|
|
|
|
|
def even(n):
|
|
|
|
return n % 2 == 0
|
|
|
|
|
|
|
|
def __define_options__(dependency_identifier):
|
2015-07-26 13:00:47 +00:00
|
|
|
return inflector.define_dict(dependency_identifier)
|
2013-07-16 11:28:28 +00:00
|
|
|
|
|
|
|
def __merge_options__(dependency_identifier, *args):
|
2015-07-26 13:00:47 +00:00
|
|
|
options_accu = inflector.storage_dict(dependency_identifier)
|
2013-07-16 11:28:28 +00:00
|
|
|
options_accu['mandatory'] = False
|
|
|
|
[options_accu.update(arg) for arg in args if arg]
|
|
|
|
return options_accu
|
|
|
|
|
2013-12-04 17:57:29 +00:00
|
|
|
def _filter_cc_arguments(ctx, opts):
|
|
|
|
if ctx.env.DEST_OS != Utils.unversioned_sys_platform():
|
|
|
|
# cross compiling, remove execute=True if present
|
2013-12-06 09:28:52 +00:00
|
|
|
if opts.get('execute'):
|
2013-12-04 17:57:29 +00:00
|
|
|
opts['execute'] = False
|
|
|
|
return opts
|
2013-07-16 11:28:28 +00:00
|
|
|
|
2014-09-03 21:44:38 +00:00
|
|
|
def check_program(name, var):
|
|
|
|
def fn(ctx, dependency_identifier):
|
|
|
|
return ctx.find_program(name, var=var, mandatory=False)
|
|
|
|
return fn
|
|
|
|
|
2013-07-16 11:28:28 +00:00
|
|
|
def check_libs(libs, function):
|
|
|
|
libs = [None] + libs
|
|
|
|
def fn(ctx, dependency_identifier):
|
|
|
|
for lib in libs:
|
|
|
|
kwargs = lib and {'lib': lib} or {}
|
|
|
|
if function(ctx, dependency_identifier, **kwargs):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
return fn
|
|
|
|
|
|
|
|
def check_statement(header, statement, **kw_ext):
|
|
|
|
def fn(ctx, dependency_identifier, **kw):
|
2013-12-26 15:45:01 +00:00
|
|
|
headers = header
|
|
|
|
if not isinstance(headers, list):
|
|
|
|
headers = [header]
|
|
|
|
hs = "\n".join(["#include <{0}>".format(h) for h in headers])
|
|
|
|
fragment = ("{0}\n"
|
|
|
|
"int main(int argc, char **argv)\n"
|
|
|
|
"{{ {1}; return 0; }}").format(hs, statement)
|
2013-07-16 11:28:28 +00:00
|
|
|
opts = __merge_options__(dependency_identifier,
|
|
|
|
{'fragment':fragment},
|
|
|
|
__define_options__(dependency_identifier),
|
|
|
|
kw_ext, kw)
|
2013-12-04 17:57:29 +00:00
|
|
|
return ctx.check_cc(**_filter_cc_arguments(ctx, opts))
|
2013-07-16 11:28:28 +00:00
|
|
|
return fn
|
|
|
|
|
|
|
|
def check_cc(**kw_ext):
|
|
|
|
def fn(ctx, dependency_identifier, **kw):
|
|
|
|
options = __merge_options__(dependency_identifier,
|
|
|
|
__define_options__(dependency_identifier),
|
|
|
|
kw_ext, kw)
|
2013-12-04 17:57:29 +00:00
|
|
|
return ctx.check_cc(**_filter_cc_arguments(ctx, options))
|
2013-07-16 11:28:28 +00:00
|
|
|
return fn
|
|
|
|
|
|
|
|
def check_pkg_config(*args, **kw_ext):
|
|
|
|
def fn(ctx, dependency_identifier, **kw):
|
|
|
|
argsl = list(args)
|
2013-11-25 09:54:41 +00:00
|
|
|
packages = args[::2]
|
|
|
|
verchecks = args[1::2]
|
|
|
|
sargs = []
|
|
|
|
for i in range(0, len(packages)):
|
|
|
|
if i < len(verchecks):
|
|
|
|
sargs.append(packages[i] + ' ' + verchecks[i])
|
|
|
|
else:
|
|
|
|
sargs.append(packages[i])
|
2013-07-16 11:28:28 +00:00
|
|
|
pkgc_args = ["--libs", "--cflags"]
|
|
|
|
if ctx.dependency_satisfied('static-build'):
|
|
|
|
pkgc_args += ["--static"]
|
|
|
|
|
|
|
|
defaults = {
|
|
|
|
'path': ctx.env.PKG_CONFIG,
|
|
|
|
'package': " ".join(packages),
|
|
|
|
'args': sargs + pkgc_args }
|
|
|
|
opts = __merge_options__(dependency_identifier, defaults, kw_ext, kw)
|
2013-11-24 14:49:34 +00:00
|
|
|
|
|
|
|
# Warning! Megahack incoming: when parsing flags in `parse_flags` waf
|
|
|
|
# uses append_unique. This appends the flags only if they aren't
|
|
|
|
# already present in the list. This causes breakage if one checks for
|
|
|
|
# multiple pkg-config packages in a single call as stuff like -lm is
|
|
|
|
# added only at its first occurrence.
|
|
|
|
original_append_unique = ConfigSet.append_unique
|
|
|
|
ConfigSet.append_unique = ConfigSet.append_value
|
|
|
|
result = bool(ctx.check_cfg(**opts))
|
|
|
|
ConfigSet.append_unique = original_append_unique
|
|
|
|
|
2015-07-26 13:00:47 +00:00
|
|
|
defkey = inflector.define_key(dependency_identifier)
|
2014-10-25 20:51:41 +00:00
|
|
|
if result:
|
|
|
|
ctx.define(defkey, 1)
|
|
|
|
else:
|
2015-02-21 19:22:28 +00:00
|
|
|
ctx.add_optional_message(dependency_identifier,
|
|
|
|
"'{0}' not found".format(" ".join(sargs)))
|
2013-07-16 11:28:28 +00:00
|
|
|
ctx.undefine(defkey)
|
2013-11-24 14:49:34 +00:00
|
|
|
return result
|
2013-07-16 11:28:28 +00:00
|
|
|
return fn
|
|
|
|
|
2015-03-06 10:01:53 +00:00
|
|
|
def check_headers(*headers, **kw_ext):
|
2013-07-16 11:28:28 +00:00
|
|
|
def undef_others(ctx, headers, found):
|
|
|
|
not_found_hs = set(headers) - set([found])
|
|
|
|
for not_found_h in not_found_hs:
|
2015-07-26 13:00:47 +00:00
|
|
|
ctx.undefine(inflector.define_key(not_found_h))
|
2013-07-16 11:28:28 +00:00
|
|
|
|
|
|
|
def fn(ctx, dependency_identifier):
|
|
|
|
for header in headers:
|
|
|
|
defaults = {'header_name': header, 'features': 'c cprogram'}
|
2015-03-06 10:01:53 +00:00
|
|
|
options = __merge_options__(dependency_identifier, defaults, kw_ext)
|
2013-07-16 11:28:28 +00:00
|
|
|
if ctx.check(**options):
|
|
|
|
undef_others(ctx, headers, header)
|
2015-07-26 13:00:47 +00:00
|
|
|
ctx.define(inflector.define_key(dependency_identifier), 1)
|
2013-07-16 11:28:28 +00:00
|
|
|
return True
|
|
|
|
undef_others(ctx, headers, None)
|
|
|
|
return False
|
|
|
|
return fn
|
|
|
|
|
|
|
|
def check_true(ctx, dependency_identifier):
|
2015-07-26 13:00:47 +00:00
|
|
|
ctx.define(inflector.define_key(dependency_identifier), 1)
|
2013-07-16 11:28:28 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
def check_ctx_vars(*variables):
|
|
|
|
def fn(ctx, dependency_identifier):
|
|
|
|
missing = []
|
|
|
|
for variable in variables:
|
|
|
|
if variable not in ctx.env:
|
|
|
|
missing.append(variable)
|
|
|
|
|
|
|
|
if any(missing):
|
|
|
|
ctx.add_optional_message(dependency_identifier,
|
|
|
|
'missing {0}'.format(', '.join(missing)))
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
|
|
|
return fn
|
|
|
|
|
|
|
|
def check_stub(ctx, dependency_identifier):
|
2015-07-26 13:00:47 +00:00
|
|
|
ctx.undefine(inflector.define_key(dependency_identifier))
|
2013-07-16 11:28:28 +00:00
|
|
|
return False
|
|
|
|
|
|
|
|
def compose_checks(*checks):
|
|
|
|
def fn(ctx, dependency_identifier):
|
|
|
|
return all([check(ctx, dependency_identifier) for check in checks])
|
|
|
|
return fn
|
|
|
|
|
|
|
|
def load_fragment(fragment):
|
|
|
|
file_path = os.path.join(os.path.dirname(__file__), '..', 'fragments',
|
|
|
|
fragment)
|
|
|
|
fp = open(file_path,"r")
|
|
|
|
fragment_code = fp.read()
|
|
|
|
fp.close()
|
|
|
|
return fragment_code
|