mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1292046 - Add a check that the compiler works with -c out of the box. r=chmanchester
The base compiler check in python configure does some preprocessing, which ensures the compiler works to some extent. Autoconf used to have a more complete test, doing a compile/link. We do have plenty of tests afterwards that do that anyways, but it's better if we fail early if the toolchain fails somehow. This refactors try_compile such that the *_compiler variable themselves can be used to trigger compiler tests. Eventually, we'll want something similar for preprocessing and possibly other invocations. This also removes similar tests from build/autoconf/toolchain.m4. --HG-- extra : rebase_source : c60d1d6e39b6bd2a377516687affd9b8932ebc12
This commit is contained in:
parent
6bdf5756ec
commit
afa6c4d5f3
@ -49,34 +49,11 @@ AC_DEFUN([MOZ_CROSS_COMPILER],
|
|||||||
[
|
[
|
||||||
echo "cross compiling from $host to $target"
|
echo "cross compiling from $host to $target"
|
||||||
|
|
||||||
_SAVE_CC="$CC"
|
|
||||||
_SAVE_CFLAGS="$CFLAGS"
|
|
||||||
_SAVE_LDFLAGS="$LDFLAGS"
|
|
||||||
|
|
||||||
if test -z "$HOST_AR_FLAGS"; then
|
if test -z "$HOST_AR_FLAGS"; then
|
||||||
HOST_AR_FLAGS="$AR_FLAGS"
|
HOST_AR_FLAGS="$AR_FLAGS"
|
||||||
fi
|
fi
|
||||||
AC_CHECK_PROGS(HOST_RANLIB, $HOST_RANLIB ranlib, ranlib, :)
|
AC_CHECK_PROGS(HOST_RANLIB, $HOST_RANLIB ranlib, ranlib, :)
|
||||||
AC_CHECK_PROGS(HOST_AR, $HOST_AR ar, ar, :)
|
AC_CHECK_PROGS(HOST_AR, $HOST_AR ar, ar, :)
|
||||||
CC="$HOST_CC"
|
|
||||||
CFLAGS="$HOST_CFLAGS"
|
|
||||||
LDFLAGS="$HOST_LDFLAGS"
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether the host c compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works])
|
|
||||||
AC_TRY_COMPILE([], [return(0);],
|
|
||||||
[ac_cv_prog_hostcc_works=1 AC_MSG_RESULT([yes])],
|
|
||||||
AC_MSG_ERROR([installation or configuration problem: host compiler $HOST_CC cannot create executables.]) )
|
|
||||||
|
|
||||||
CC="$HOST_CXX"
|
|
||||||
CFLAGS="$HOST_CXXFLAGS"
|
|
||||||
AC_MSG_CHECKING([whether the host c++ compiler ($HOST_CXX $HOST_CXXFLAGS $HOST_LDFLAGS) works])
|
|
||||||
AC_TRY_COMPILE([], [return(0);],
|
|
||||||
[ac_cv_prog_hostcxx_works=1 AC_MSG_RESULT([yes])],
|
|
||||||
AC_MSG_ERROR([installation or configuration problem: host compiler $HOST_CXX cannot create executables.]) )
|
|
||||||
|
|
||||||
CC=$_SAVE_CC
|
|
||||||
CFLAGS=$_SAVE_CFLAGS
|
|
||||||
LDFLAGS=$_SAVE_LDFLAGS
|
|
||||||
|
|
||||||
dnl AC_CHECK_PROGS manually goes through $PATH, and as such fails to handle
|
dnl AC_CHECK_PROGS manually goes through $PATH, and as such fails to handle
|
||||||
dnl absolute or relative paths. Relative paths wouldn't work anyways, but
|
dnl absolute or relative paths. Relative paths wouldn't work anyways, but
|
||||||
|
@ -60,7 +60,7 @@ def checking(what, callback=None):
|
|||||||
log.info('no')
|
log.info('no')
|
||||||
else:
|
else:
|
||||||
log.info(display_ret)
|
log.info(display_ret)
|
||||||
if error:
|
if error is not None:
|
||||||
die(error)
|
die(error)
|
||||||
return ret
|
return ret
|
||||||
return wrapped
|
return wrapped
|
||||||
|
@ -18,47 +18,14 @@
|
|||||||
# - `check_msg` is the message to be printed to accompany compiling the test
|
# - `check_msg` is the message to be printed to accompany compiling the test
|
||||||
# program.
|
# program.
|
||||||
@template
|
@template
|
||||||
@imports('textwrap')
|
|
||||||
def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None):
|
def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None):
|
||||||
includes = includes or []
|
compiler = {
|
||||||
source_lines = ['#include <%s>' % f for f in includes]
|
'C': c_compiler,
|
||||||
source = '\n'.join(source_lines) + '\n'
|
'C++': cxx_compiler,
|
||||||
source += textwrap.dedent('''\
|
}[language]
|
||||||
int
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
%s
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
''' % body)
|
|
||||||
|
|
||||||
if check_msg:
|
return compiler.try_compile(includes, body, flags, check_msg)
|
||||||
def checking_fn(fn):
|
|
||||||
return checking(check_msg, callback=lambda r: r is not None)(fn)
|
|
||||||
else:
|
|
||||||
def checking_fn(fn):
|
|
||||||
return fn
|
|
||||||
|
|
||||||
def get_flags():
|
|
||||||
if flags:
|
|
||||||
return flags[:]
|
|
||||||
|
|
||||||
@depends(cxx_compiler, c_compiler, extra_toolchain_flags)
|
|
||||||
@checking_fn
|
|
||||||
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,
|
|
||||||
}[language]
|
|
||||||
return try_invoke_compiler(info.wrapper + [info.compiler] + info.flags,
|
|
||||||
language, source, flags,
|
|
||||||
onerror=lambda: None)
|
|
||||||
return check
|
|
||||||
|
|
||||||
# Checks for the presence of the given header on the target system by compiling
|
# 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
|
# a test program including that header. The return value of the template is a
|
||||||
|
65
build/moz.configure/compilers-util.configure
Normal file
65
build/moz.configure/compilers-util.configure
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# -*- 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/.
|
||||||
|
|
||||||
|
@template
|
||||||
|
@imports('textwrap')
|
||||||
|
@imports(_from='mozbuild.configure', _import='DependsFunction')
|
||||||
|
def compiler_class(compiler):
|
||||||
|
class Compiler(DependsFunction):
|
||||||
|
# Generates a test program and attempts to compile it. In case of
|
||||||
|
# failure, the resulting check will return None. If the test program
|
||||||
|
# succeeds, it will return the output of the test program.
|
||||||
|
# - `includes` are the includes (as file names) that will appear at the
|
||||||
|
# top of the generated test program.
|
||||||
|
# - `body` is the code that will appear in the main function of the
|
||||||
|
# generated test program. `return 0;` is appended to the function
|
||||||
|
# body automatically.
|
||||||
|
# - `flags` are the flags to be passed to the compiler, in addition to
|
||||||
|
# `-c`.
|
||||||
|
# - `check_msg` is the message to be printed to accompany compiling the
|
||||||
|
# test program.
|
||||||
|
def try_compile(self, includes=None, body='', flags=None,
|
||||||
|
check_msg=None, onerror=lambda: None):
|
||||||
|
includes = includes or []
|
||||||
|
source_lines = ['#include <%s>' % f for f in includes]
|
||||||
|
source = '\n'.join(source_lines) + '\n'
|
||||||
|
source += textwrap.dedent('''\
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
%s
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
''' % body)
|
||||||
|
|
||||||
|
if check_msg:
|
||||||
|
def checking_fn(fn):
|
||||||
|
return checking(check_msg,
|
||||||
|
callback=lambda r: r is not None)(fn)
|
||||||
|
else:
|
||||||
|
def checking_fn(fn):
|
||||||
|
return fn
|
||||||
|
|
||||||
|
def get_flags():
|
||||||
|
if flags:
|
||||||
|
return flags[:]
|
||||||
|
|
||||||
|
@depends(self, extra_toolchain_flags)
|
||||||
|
@checking_fn
|
||||||
|
def func(compiler, extra_flags):
|
||||||
|
flags = get_flags() or []
|
||||||
|
flags += extra_flags
|
||||||
|
flags.append('-c')
|
||||||
|
|
||||||
|
return try_invoke_compiler(
|
||||||
|
compiler.wrapper + [compiler.compiler] + compiler.flags,
|
||||||
|
compiler.language, source, flags, onerror=onerror)
|
||||||
|
|
||||||
|
return func
|
||||||
|
|
||||||
|
compiler.__class__ = Compiler
|
||||||
|
return compiler
|
@ -171,6 +171,8 @@ add_old_configure_assignment('TOOLCHAIN_PREFIX', toolchain_prefix)
|
|||||||
|
|
||||||
# Compilers
|
# Compilers
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
|
include('compilers-util.configure')
|
||||||
|
|
||||||
def try_preprocess(compiler, language, source):
|
def try_preprocess(compiler, language, source):
|
||||||
return try_invoke_compiler(compiler, language, source, ['-E'])
|
return try_invoke_compiler(compiler, language, source, ['-E'])
|
||||||
|
|
||||||
@ -533,7 +535,7 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||||||
'C++': lambda: default_cxx_compilers(c_compiler),
|
'C++': lambda: default_cxx_compilers(c_compiler),
|
||||||
}[language]()
|
}[language]()
|
||||||
|
|
||||||
what='the %s %s compiler' % (host_or_target_str, language),
|
what='the %s %s compiler' % (host_or_target_str, language)
|
||||||
|
|
||||||
option(env=var, nargs=1, help='Path to %s' % what)
|
option(env=var, nargs=1, help='Path to %s' % what)
|
||||||
|
|
||||||
@ -736,6 +738,15 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||||||
add_old_configure_assignment(
|
add_old_configure_assignment(
|
||||||
'%s_VERSION' % var, delayed_getattr(valid_compiler, 'version'))
|
'%s_VERSION' % var, delayed_getattr(valid_compiler, 'version'))
|
||||||
|
|
||||||
|
valid_compiler = compiler_class(valid_compiler)
|
||||||
|
|
||||||
|
def compiler_error():
|
||||||
|
raise FatalCheckError('Failed compiling a simple %s source with %s'
|
||||||
|
% (language, what))
|
||||||
|
|
||||||
|
valid_compiler.try_compile(check_msg='%s works' % what,
|
||||||
|
onerror=compiler_error)
|
||||||
|
|
||||||
return valid_compiler
|
return valid_compiler
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||||||
import os
|
import os
|
||||||
import textwrap
|
import textwrap
|
||||||
import unittest
|
import unittest
|
||||||
|
import mozpack.path as mozpath
|
||||||
|
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
|
||||||
@ -44,32 +45,40 @@ class TestHeaderChecks(unittest.TestCase):
|
|||||||
expected_flags=expected_flags),
|
expected_flags=expected_flags),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base_dir = os.path.join(topsrcdir, 'build', 'moz.configure')
|
||||||
|
|
||||||
mock_compiler_defs = textwrap.dedent('''\
|
mock_compiler_defs = textwrap.dedent('''\
|
||||||
|
@depends('--help')
|
||||||
|
def extra_toolchain_flags(_):
|
||||||
|
return []
|
||||||
|
|
||||||
|
include('%s/compilers-util.configure')
|
||||||
|
|
||||||
|
@compiler_class
|
||||||
@depends('--help')
|
@depends('--help')
|
||||||
def c_compiler(_):
|
def c_compiler(_):
|
||||||
return namespace(
|
return namespace(
|
||||||
flags=[],
|
flags=[],
|
||||||
compiler=os.path.abspath('/usr/bin/mockcc'),
|
compiler=os.path.abspath('/usr/bin/mockcc'),
|
||||||
wrapper=[],
|
wrapper=[],
|
||||||
|
language='C',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@compiler_class
|
||||||
@depends('--help')
|
@depends('--help')
|
||||||
def cxx_compiler(_):
|
def cxx_compiler(_):
|
||||||
return namespace(
|
return namespace(
|
||||||
flags=[],
|
flags=[],
|
||||||
compiler=os.path.abspath('/usr/bin/mockcc'),
|
compiler=os.path.abspath('/usr/bin/mockcc'),
|
||||||
wrapper=[],
|
wrapper=[],
|
||||||
|
language='C++',
|
||||||
)
|
)
|
||||||
@depends('--help')
|
''' % mozpath.normsep(base_dir))
|
||||||
def extra_toolchain_flags(_):
|
|
||||||
return []
|
|
||||||
''')
|
|
||||||
|
|
||||||
config = {}
|
config = {}
|
||||||
out = StringIO()
|
out = StringIO()
|
||||||
sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'],
|
sandbox = ConfigureTestSandbox(paths, config, {}, ['/bin/configure'],
|
||||||
out, out)
|
out, out)
|
||||||
base_dir = os.path.join(topsrcdir, 'build', 'moz.configure')
|
|
||||||
sandbox.include_file(os.path.join(base_dir, 'util.configure'))
|
sandbox.include_file(os.path.join(base_dir, 'util.configure'))
|
||||||
sandbox.include_file(os.path.join(base_dir, 'checks.configure'))
|
sandbox.include_file(os.path.join(base_dir, 'checks.configure'))
|
||||||
exec_(mock_compiler_defs, sandbox)
|
exec_(mock_compiler_defs, sandbox)
|
||||||
|
Loading…
Reference in New Issue
Block a user