зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1269517 - Implement check_header in Python configure. r=glandium
MozReview-Commit-ID: 1AypZg3f79a
This commit is contained in:
Родитель
55afa58b7a
Коммит
726b97efc8
|
@ -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()
|
||||
|
|
Загрузка…
Ссылка в новой задаче