summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/test/configure/test_compile_checks.py')
-rw-r--r--python/mozbuild/mozbuild/test/configure/test_compile_checks.py403
1 files changed, 403 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/test/configure/test_compile_checks.py b/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
new file mode 100644
index 000000000..5913dbe3d
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/configure/test_compile_checks.py
@@ -0,0 +1,403 @@
+# 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/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import os
+import textwrap
+import unittest
+import mozpack.path as mozpath
+
+from StringIO import StringIO
+
+from buildconfig import topsrcdir
+from common import ConfigureTestSandbox
+from mozbuild.util import exec_
+from mozunit import main
+from test_toolchain_helpers import FakeCompiler
+
+
+class BaseCompileChecks(unittest.TestCase):
+ def get_mock_compiler(self, expected_test_content=None, expected_flags=None):
+ expected_flags = expected_flags or []
+ def mock_compiler(stdin, args):
+ args, test_file = args[:-1], args[-1]
+ self.assertIn('-c', args)
+ for flag in expected_flags:
+ self.assertIn(flag, args)
+
+ if expected_test_content:
+ with open(test_file) as fh:
+ test_content = fh.read()
+ self.assertEqual(test_content, expected_test_content)
+
+ return FakeCompiler()(None, args)
+ return mock_compiler
+
+ def do_compile_test(self, command, expected_test_content=None,
+ expected_flags=None):
+
+ paths = {
+ os.path.abspath('/usr/bin/mockcc'): self.get_mock_compiler(
+ expected_test_content=expected_test_content,
+ expected_flags=expected_flags),
+ }
+
+ base_dir = os.path.join(topsrcdir, 'build', 'moz.configure')
+
+ mock_compiler_defs = textwrap.dedent('''\
+ @depends(when=True)
+ def extra_toolchain_flags():
+ return []
+
+ include('%s/compilers-util.configure')
+
+ @compiler_class
+ @depends(when=True)
+ def c_compiler():
+ return namespace(
+ flags=[],
+ type='gcc',
+ compiler=os.path.abspath('/usr/bin/mockcc'),
+ wrapper=[],
+ language='C',
+ )
+
+ @compiler_class
+ @depends(when=True)
+ def cxx_compiler():
+ return namespace(
+ flags=[],
+ type='gcc',
+ compiler=os.path.abspath('/usr/bin/mockcc'),
+ wrapper=[],
+ language='C++',
+ )
+ ''' % mozpath.normsep(base_dir))
+
+ config = {}
+ out = StringIO()
+ sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'],
+ out, out)
+ sandbox.include_file(os.path.join(base_dir, 'util.configure'))
+ sandbox.include_file(os.path.join(base_dir, 'checks.configure'))
+ exec_(mock_compiler_defs, sandbox)
+ sandbox.include_file(os.path.join(base_dir, 'compile-checks.configure'))
+
+ status = 0
+ try:
+ exec_(command, sandbox)
+ sandbox.run()
+ except SystemExit as e:
+ status = e.code
+
+ return config, out.getvalue(), status
+
+
+class TestHeaderChecks(BaseCompileChecks):
+ def test_try_compile_include(self):
+ expected_test_content = textwrap.dedent('''\
+ #include <foo.h>
+ #include <bar.h>
+ int
+ main(void)
+ {
+
+ ;
+ return 0;
+ }
+ ''')
+
+ cmd = textwrap.dedent('''\
+ try_compile(['foo.h', 'bar.h'], language='C')
+ ''')
+
+ config, out, status = self.do_compile_test(cmd, expected_test_content)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {})
+
+ def test_try_compile_flags(self):
+ expected_flags = ['--extra', '--flags']
+
+ cmd = textwrap.dedent('''\
+ try_compile(language='C++', flags=['--flags', '--extra'])
+ ''')
+
+ config, out, status = self.do_compile_test(cmd, expected_flags=expected_flags)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {})
+
+ def test_try_compile_failure(self):
+ cmd = textwrap.dedent('''\
+ have_fn = try_compile(body='somefn();', flags=['-funknown-flag'])
+ set_config('HAVE_SOMEFN', have_fn)
+
+ have_another = try_compile(body='anotherfn();', language='C')
+ set_config('HAVE_ANOTHERFN', have_another)
+ ''')
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ 'HAVE_ANOTHERFN': True,
+ })
+
+ def test_try_compile_msg(self):
+ cmd = textwrap.dedent('''\
+ known_flag = try_compile(language='C++', flags=['-fknown-flag'],
+ check_msg='whether -fknown-flag works')
+ set_config('HAVE_KNOWN_FLAG', known_flag)
+ ''')
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {'HAVE_KNOWN_FLAG': True})
+ self.assertEqual(out, textwrap.dedent('''\
+ 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_conditional(self):
+ cmd = textwrap.dedent('''\
+ check_headers('foo.h', 'bar.h', when=never)
+ ''')
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(out, '')
+ self.assertEqual(config, {'DEFINES':{}})
+
+ 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
+ '''))
+
+
+class TestWarningChecks(BaseCompileChecks):
+ def get_warnings(self):
+ return textwrap.dedent('''\
+ set_config('_WARNINGS_CFLAGS', warnings_cflags)
+ set_config('_WARNINGS_CXXFLAGS', warnings_cxxflags)
+ ''')
+
+ def test_check_and_add_gcc_warning(self):
+ for flag, expected_flags in (
+ ('-Wfoo', ['-Werror', '-Wfoo']),
+ ('-Wno-foo', ['-Werror', '-Wfoo']),
+ ('-Werror=foo', ['-Werror=foo']),
+ ('-Wno-error=foo', ['-Wno-error=foo']),
+ ):
+ cmd = textwrap.dedent('''\
+ check_and_add_gcc_warning('%s')
+ ''' % flag) + self.get_warnings()
+
+ config, out, status = self.do_compile_test(
+ cmd, expected_flags=expected_flags)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': [flag],
+ '_WARNINGS_CXXFLAGS': [flag],
+ })
+ self.assertEqual(out, textwrap.dedent('''\
+ checking whether the C compiler supports {flag}... yes
+ checking whether the C++ compiler supports {flag}... yes
+ '''.format(flag=flag)))
+
+ def test_check_and_add_gcc_warning_one(self):
+ cmd = textwrap.dedent('''\
+ check_and_add_gcc_warning('-Wfoo', cxx_compiler)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': [],
+ '_WARNINGS_CXXFLAGS': ['-Wfoo'],
+ })
+ self.assertEqual(out, textwrap.dedent('''\
+ checking whether the C++ compiler supports -Wfoo... yes
+ '''))
+
+ def test_check_and_add_gcc_warning_when(self):
+ cmd = textwrap.dedent('''\
+ @depends(when=True)
+ def never():
+ return False
+ check_and_add_gcc_warning('-Wfoo', cxx_compiler, when=never)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': [],
+ '_WARNINGS_CXXFLAGS': [],
+ })
+ self.assertEqual(out, '')
+
+ cmd = textwrap.dedent('''\
+ @depends(when=True)
+ def always():
+ return True
+ check_and_add_gcc_warning('-Wfoo', cxx_compiler, when=always)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': [],
+ '_WARNINGS_CXXFLAGS': ['-Wfoo'],
+ })
+ self.assertEqual(out, textwrap.dedent('''\
+ checking whether the C++ compiler supports -Wfoo... yes
+ '''))
+
+ def test_add_gcc_warning(self):
+ cmd = textwrap.dedent('''\
+ add_gcc_warning('-Wfoo')
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': ['-Wfoo'],
+ '_WARNINGS_CXXFLAGS': ['-Wfoo'],
+ })
+ self.assertEqual(out, '')
+
+ def test_add_gcc_warning_one(self):
+ cmd = textwrap.dedent('''\
+ add_gcc_warning('-Wfoo', c_compiler)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': ['-Wfoo'],
+ '_WARNINGS_CXXFLAGS': [],
+ })
+ self.assertEqual(out, '')
+
+ def test_add_gcc_warning_when(self):
+ cmd = textwrap.dedent('''\
+ @depends(when=True)
+ def never():
+ return False
+ add_gcc_warning('-Wfoo', c_compiler, when=never)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': [],
+ '_WARNINGS_CXXFLAGS': [],
+ })
+ self.assertEqual(out, '')
+
+ cmd = textwrap.dedent('''\
+ @depends(when=True)
+ def always():
+ return True
+ add_gcc_warning('-Wfoo', c_compiler, when=always)
+ ''') + self.get_warnings()
+
+ config, out, status = self.do_compile_test(cmd)
+ self.assertEqual(status, 0)
+ self.assertEqual(config, {
+ '_WARNINGS_CFLAGS': ['-Wfoo'],
+ '_WARNINGS_CXXFLAGS': [],
+ })
+ self.assertEqual(out, '')
+
+
+if __name__ == '__main__':
+ main()