Bug 1269517 - Implement check_header in Python configure. r=glandium

MozReview-Commit-ID: 1AypZg3f79a
This commit is contained in:
Chris Manchester 2016-07-26 15:27:19 -07:00
Родитель 55afa58b7a
Коммит 726b97efc8
4 изменённых файлов: 171 добавлений и 4 удалений

Просмотреть файл

@ -85,6 +85,13 @@ def android_platform(target, android_version, ndk):
add_old_configure_assignment('android_platform', android_platform)
@depends(android_platform)
def extra_toolchain_flags(platform_dir):
if not platform_dir:
return []
return ['-idirafter',
os.path.join(platform_dir, 'usr', 'include')]
@depends(target, host, ndk, '--with-android-toolchain',
'--with-android-gnu-compiler-version')
@checking('for the Android toolchain directory', lambda x: x or 'not found')

Просмотреть файл

@ -32,8 +32,6 @@ def try_compile(includes=None, body='', language='C++', flags=None, check_msg=No
return 0;
}
''' % body)
flags = flags or []
flags.append('-c')
if check_msg:
def checking_fn(fn):
@ -42,9 +40,17 @@ def try_compile(includes=None, body='', language='C++', flags=None, check_msg=No
def checking_fn(fn):
return fn
@depends(cxx_compiler, c_compiler)
def get_flags():
if flags:
return flags[:]
@depends(cxx_compiler, c_compiler, extra_toolchain_flags)
@checking_fn
def check(cxx_info, c_info):
def check(cxx_info, c_info, extra_flags):
flags = get_flags() or []
flags += extra_flags
flags.append('-c')
info = {
'C': c_info,
'C++': cxx_info,
@ -53,3 +59,52 @@ def try_compile(includes=None, body='', language='C++', flags=None, check_msg=No
language, source, flags,
onerror=lambda: None)
return check
# Checks for the presence of the given header on the target system by compiling
# a test program including that header. The return value of the template is a
# check function returning True if the header is present, and None if it is not.
# The value of this check function is also used to set a variable (with set_define)
# corresponding to the checked header. For instance, HAVE_MALLOC_H will be set in
# defines if check_header if called with 'malloc.h' as input and malloc.h is
# present on the target.
# - `header` is the header, as a file name, to check for.
# - `language` is the language selection, so that the appropriate compiler is
# used.
# - `flags` are the flags to be passed to the compiler, in addition to `-c`.
# - `includes` are additional includes, as file names, to appear before the
# header checked for.
# - `when` is a depends function that if present will make performing the check
# conditional on the value of that function.
@template
def check_header(header, language='C++', flags=None, includes=None, when=None):
when = when or depends('--help')(lambda _: True)
if includes:
includes = includes[:]
else:
includes = []
includes.append(header)
@depends_when(try_compile(includes=includes, language=language, flags=flags,
check_msg='for %s' % header), when=when)
def have_header(value):
if value is not None:
return True
header_var = 'HAVE_%s' % (header.upper()
.replace('-', '_')
.replace('/', '_')
.replace('.', '_'))
set_define(header_var, have_header)
return have_header
# A convenience wrapper for check_header for checking multiple headers.
# returns an array of the resulting checks in order corresponding to the
# provided headers.
# - `headers` are the headers to be checked.
# - `kwargs` are keyword arguments passed verbatim to check_header.
@template
def check_headers(*headers, **kwargs):
checks = []
for header in headers:
checks.append(check_header(header, **kwargs))
return checks

Просмотреть файл

@ -55,6 +55,11 @@ set_config('HAVE_YASM', have_yasm)
# Until the YASM variable is not necessary in old-configure.
add_old_configure_assignment('YASM', have_yasm)
@depends('--help')
def extra_toolchain_flags(_):
# This value will be overriden for android builds, where
# extra flags are required to do basic checks.
return []
# Android NDK
# ==============================================================

Просмотреть файл

@ -60,6 +60,9 @@ class TestHeaderChecks(unittest.TestCase):
compiler=os.path.abspath('/usr/bin/mockcc'),
wrapper=[],
)
@depends('--help')
def extra_toolchain_flags(_):
return []
''')
config = {}
@ -150,5 +153,102 @@ class TestHeaderChecks(unittest.TestCase):
checking whether -fknown-flag works... yes
'''))
def test_check_header(self):
expected_test_content = textwrap.dedent('''\
#include <foo.h>
int
main(void)
{
;
return 0;
}
''')
cmd = textwrap.dedent('''\
check_header('foo.h')
''')
config, out, status = self.do_compile_test(cmd,
expected_test_content=expected_test_content)
self.assertEqual(status, 0)
self.assertEqual(config, {'DEFINES': {'HAVE_FOO_H': True}})
self.assertEqual(out, textwrap.dedent('''\
checking for foo.h... yes
'''))
def test_check_header_include(self):
expected_test_content = textwrap.dedent('''\
#include <std.h>
#include <bar.h>
#include <foo.h>
int
main(void)
{
;
return 0;
}
''')
cmd = textwrap.dedent('''\
have_foo = check_header('foo.h', includes=['std.h', 'bar.h'])
set_config('HAVE_FOO_H', have_foo)
''')
config, out, status = self.do_compile_test(cmd,
expected_test_content=expected_test_content)
self.assertEqual(status, 0)
self.assertEqual(config, {
'HAVE_FOO_H': True,
'DEFINES': {
'HAVE_FOO_H': True,
}
})
self.assertEqual(out, textwrap.dedent('''\
checking for foo.h... yes
'''))
def test_check_headers_multiple(self):
cmd = textwrap.dedent('''\
baz_bar, quux_bar = check_headers('baz/foo-bar.h', 'baz-quux/foo-bar.h')
set_config('HAVE_BAZ_BAR', baz_bar)
set_config('HAVE_QUUX_BAR', quux_bar)
''')
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(config, {
'HAVE_BAZ_BAR': True,
'HAVE_QUUX_BAR': True,
'DEFINES': {
'HAVE_BAZ_FOO_BAR_H': True,
'HAVE_BAZ_QUUX_FOO_BAR_H': True,
}
})
self.assertEqual(out, textwrap.dedent('''\
checking for baz/foo-bar.h... yes
checking for baz-quux/foo-bar.h... yes
'''))
def test_check_headers_not_found(self):
cmd = textwrap.dedent('''\
baz_bar, quux_bar = check_headers('baz/foo-bar.h', 'baz-quux/foo-bar.h',
flags=['-funknown-flag'])
set_config('HAVE_BAZ_BAR', baz_bar)
set_config('HAVE_QUUX_BAR', quux_bar)
''')
config, out, status = self.do_compile_test(cmd)
self.assertEqual(status, 0)
self.assertEqual(config, {'DEFINES': {}})
self.assertEqual(out, textwrap.dedent('''\
checking for baz/foo-bar.h... no
checking for baz-quux/foo-bar.h... no
'''))
if __name__ == '__main__':
main()