Merge pull request #9989 from ePirat/epirat-fix-uscore-prefix-detection
Fix underscore detection
This commit is contained in:
commit
efc7604ca2
|
@ -900,9 +900,10 @@ class CLikeCompiler(Compiler):
|
|||
return self.compiles(t, env, extra_args=extra_args,
|
||||
dependencies=dependencies)
|
||||
|
||||
def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
|
||||
def _symbols_have_underscore_prefix_searchbin(self, env: 'Environment') -> bool:
|
||||
'''
|
||||
Check if the compiler prefixes an underscore to global C symbols
|
||||
Check if symbols have underscore prefix by compiling a small test binary
|
||||
and then searching the binary for the string,
|
||||
'''
|
||||
symbol_name = b'meson_uscore_prefix'
|
||||
code = '''#ifdef __cplusplus
|
||||
|
@ -914,10 +915,10 @@ class CLikeCompiler(Compiler):
|
|||
#endif
|
||||
'''
|
||||
args = self.get_compiler_check_args(CompileCheckMode.COMPILE)
|
||||
n = 'symbols_have_underscore_prefix'
|
||||
n = '_symbols_have_underscore_prefix_searchbin'
|
||||
with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p:
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError(f'BUG: Unable to compile {n!r} check: {p.stdout}')
|
||||
raise RuntimeError(f'BUG: Unable to compile {n!r} check: {p.stderr}')
|
||||
if not os.path.isfile(p.output_name):
|
||||
raise RuntimeError(f'BUG: Can\'t find compiled test code for {n!r} check')
|
||||
with open(p.output_name, 'rb') as o:
|
||||
|
@ -925,13 +926,79 @@ class CLikeCompiler(Compiler):
|
|||
# Check if the underscore form of the symbol is somewhere
|
||||
# in the output file.
|
||||
if b'_' + symbol_name in line:
|
||||
mlog.debug("Symbols have underscore prefix: YES")
|
||||
mlog.debug("Underscore prefix check found prefixed function in binary")
|
||||
return True
|
||||
# Else, check if the non-underscored form is present
|
||||
elif symbol_name in line:
|
||||
mlog.debug("Symbols have underscore prefix: NO")
|
||||
mlog.debug("Underscore prefix check found non-prefixed function in binary")
|
||||
return False
|
||||
raise RuntimeError(f'BUG: {n!r} check failed unexpectedly')
|
||||
raise RuntimeError(f'BUG: {n!r} check did not find symbol string in binary')
|
||||
|
||||
def _symbols_have_underscore_prefix_define(self, env: 'Environment') -> T.Optional[bool]:
|
||||
'''
|
||||
Check if symbols have underscore prefix by querying the
|
||||
__USER_LABEL_PREFIX__ define that most compilers provide
|
||||
for this. Return if functions have underscore prefix or None
|
||||
if it was not possible to determine, like when the compiler
|
||||
does not set the define or the define has an unexpected value.
|
||||
'''
|
||||
delim = '"MESON_HAVE_UNDERSCORE_DELIMITER" '
|
||||
code = f'''
|
||||
#ifndef __USER_LABEL_PREFIX__
|
||||
#define MESON_UNDERSCORE_PREFIX unsupported
|
||||
#else
|
||||
#define MESON_UNDERSCORE_PREFIX __USER_LABEL_PREFIX__
|
||||
#endif
|
||||
{delim}MESON_UNDERSCORE_PREFIX
|
||||
'''
|
||||
with self._build_wrapper(code, env, mode='preprocess', want_output=False, temp_dir=env.scratch_dir) as p:
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError(f'BUG: Unable to preprocess _symbols_have_underscore_prefix_define check: {p.stdout}')
|
||||
symbol_prefix = p.stdout.partition(delim)[-1].rstrip()
|
||||
|
||||
mlog.debug(f'Queried compiler for function prefix: __USER_LABEL_PREFIX__ is "{symbol_prefix!s}"')
|
||||
if symbol_prefix == '_':
|
||||
return True
|
||||
elif symbol_prefix == '':
|
||||
return False
|
||||
else:
|
||||
return None
|
||||
|
||||
def _symbols_have_underscore_prefix_list(self, env: 'Environment') -> T.Optional[bool]:
|
||||
'''
|
||||
Check if symbols have underscore prefix by consulting a hardcoded
|
||||
list of cases where we know the results.
|
||||
Return if functions have underscore prefix or None if unknown.
|
||||
'''
|
||||
m = env.machines[self.for_machine]
|
||||
# Darwin always uses the underscore prefix, not matter what
|
||||
if m.is_darwin():
|
||||
return True
|
||||
# Windows uses the underscore prefix on x86 (32bit) only
|
||||
if m.is_windows() or m.is_cygwin():
|
||||
return m.cpu_family == 'x86'
|
||||
return None
|
||||
|
||||
|
||||
def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
|
||||
'''
|
||||
Check if the compiler prefixes an underscore to global C symbols
|
||||
'''
|
||||
# First, try to query the compiler directly
|
||||
result = self._symbols_have_underscore_prefix_define(env)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
# Else, try to consult a hardcoded list of cases we know
|
||||
# absolutely have an underscore prefix
|
||||
result = self._symbols_have_underscore_prefix_list(env)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
# As a last resort, try search in a compiled binary, which is the
|
||||
# most unreliable way of checking this, see #5482
|
||||
return self._symbols_have_underscore_prefix_searchbin(env)
|
||||
|
||||
|
||||
def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]:
|
||||
patterns = [] # type: T.List[str]
|
||||
|
|
|
@ -383,6 +383,23 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
|
|||
def get_argument_syntax(self) -> str:
|
||||
return 'msvc'
|
||||
|
||||
def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
|
||||
'''
|
||||
Check if the compiler prefixes an underscore to global C symbols.
|
||||
|
||||
This overrides the Clike method, as for MSVC checking the
|
||||
underscore prefix based on the compiler define never works,
|
||||
so do not even try.
|
||||
'''
|
||||
# Try to consult a hardcoded list of cases we know
|
||||
# absolutely have an underscore prefix
|
||||
result = self._symbols_have_underscore_prefix_list(env)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
# As a last resort, try search in a compiled binary
|
||||
return self._symbols_have_underscore_prefix_searchbin(env)
|
||||
|
||||
|
||||
class MSVCCompiler(VisualStudioLikeCompiler):
|
||||
|
||||
|
|
13
run_tests.py
13
run_tests.py
|
@ -40,7 +40,7 @@ from mesonbuild import mesonlib
|
|||
from mesonbuild import mesonmain
|
||||
from mesonbuild import mtest
|
||||
from mesonbuild import mlog
|
||||
from mesonbuild.environment import Environment, detect_ninja
|
||||
from mesonbuild.environment import Environment, detect_ninja, detect_machine_info
|
||||
from mesonbuild.coredata import backendlist, version as meson_version
|
||||
from mesonbuild.mesonlib import OptionKey, setup_vsenv
|
||||
|
||||
|
@ -153,6 +153,17 @@ def get_fake_env(sdir='', bdir=None, prefix='', opts=None):
|
|||
env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library
|
||||
return env
|
||||
|
||||
def get_convincing_fake_env_and_cc(bdir, prefix):
|
||||
'''
|
||||
Return a fake env and C compiler with the fake env
|
||||
machine info properly detected using that compiler.
|
||||
Useful for running compiler checks in the unit tests.
|
||||
'''
|
||||
env = get_fake_env('', bdir, prefix)
|
||||
cc = compilers.detect_c_compiler(env, mesonlib.MachineChoice.HOST)
|
||||
# Detect machine info
|
||||
env.machines.host = detect_machine_info({'c':cc})
|
||||
return (env, cc)
|
||||
|
||||
Backend = Enum('Backend', 'ninja vs xcode')
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ from mesonbuild.scripts import destdir_join
|
|||
from mesonbuild.wrap.wrap import PackageDefinition, WrapException
|
||||
|
||||
from run_tests import (
|
||||
Backend, exe_suffix, get_fake_env
|
||||
Backend, exe_suffix, get_fake_env, get_convincing_fake_env_and_cc
|
||||
)
|
||||
|
||||
from .baseplatformtests import BasePlatformTests
|
||||
|
@ -1546,6 +1546,32 @@ class AllPlatformTests(BasePlatformTests):
|
|||
self.build()
|
||||
self.run_tests()
|
||||
|
||||
def test_underscore_prefix_detection_list(self) -> None:
|
||||
'''
|
||||
Test the underscore detection hardcoded lookup list
|
||||
against what was detected in the binary.
|
||||
'''
|
||||
env, cc = get_convincing_fake_env_and_cc(self.builddir, self.prefix)
|
||||
expected_uscore = cc._symbols_have_underscore_prefix_searchbin(env)
|
||||
list_uscore = cc._symbols_have_underscore_prefix_list(env)
|
||||
if list_uscore is not None:
|
||||
self.assertEqual(list_uscore, expected_uscore)
|
||||
else:
|
||||
raise SkipTest('No match in underscore prefix list for this platform.')
|
||||
|
||||
def test_underscore_prefix_detection_define(self) -> None:
|
||||
'''
|
||||
Test the underscore detection based on compiler-defined preprocessor macro
|
||||
against what was detected in the binary.
|
||||
'''
|
||||
env, cc = get_convincing_fake_env_and_cc(self.builddir, self.prefix)
|
||||
expected_uscore = cc._symbols_have_underscore_prefix_searchbin(env)
|
||||
define_uscore = cc._symbols_have_underscore_prefix_define(env)
|
||||
if define_uscore is not None:
|
||||
self.assertEqual(define_uscore, expected_uscore)
|
||||
else:
|
||||
raise SkipTest('Did not find the underscore prefix define __USER_LABEL_PREFIX__')
|
||||
|
||||
@skipIfNoPkgconfig
|
||||
def test_pkgconfig_static(self):
|
||||
'''
|
||||
|
|
Loading…
Reference in New Issue