implement and test a few compiler checks for D

- run
 - sizeof
 - alignment
 - has_header
pull/10331/head
Remi Thebault 3 years ago committed by Xavier Claessens
parent c16fdaeeca
commit f24ad87e05
  1. 101
      mesonbuild/compilers/d.py
  2. 50
      test cases/d/15 compiler run checks/meson.build
  3. 17
      test cases/d/15 compiler run checks/test_sizeof.d

@ -17,22 +17,27 @@ import re
import subprocess
import typing as T
from .. import mesonlib
from .. import mlog
from ..arglist import CompilerArgs
from ..linkers import RSPFileSyntax
from ..mesonlib import (
EnvironmentException, MachineChoice, version_compare, OptionKey, is_windows
)
from ..arglist import CompilerArgs
from ..linkers import RSPFileSyntax
from . import compilers
from .compilers import (
d_dmd_buildtype_args,
d_gdc_buildtype_args,
d_ldc_buildtype_args,
clike_debug_args,
Compiler,
CompileCheckMode,
)
from .mixins.gnu import GnuCompiler
if T.TYPE_CHECKING:
from ..dependencies import Dependency
from ..programs import ExternalProgram
from ..envconfig import MachineInfo
from ..environment import Environment
@ -678,6 +683,98 @@ class DCompiler(Compiler):
def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
return []
def _get_compile_extra_args(self, extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None) -> T.List[str]:
args = self._get_target_arch_args()
if extra_args:
if callable(extra_args):
extra_args = extra_args(CompileCheckMode.COMPILE)
if isinstance(extra_args, list):
args.extend(extra_args)
elif isinstance(extra_args, str):
args.append(extra_args)
return args
def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *,
extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult:
need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
extra_args = self._get_compile_extra_args(extra_args)
with self._build_wrapper(code, env, extra_args, dependencies, mode='link', want_output=True) as p:
if p.returncode != 0:
mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n')
return compilers.RunResult(False)
if need_exe_wrapper:
cmdlist = self.exe_wrapper.get_command() + [p.output_name]
else:
cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist)
except Exception as e:
mlog.debug(f'Could not run: {cmdlist} (error: {e})\n')
return compilers.RunResult(False)
mlog.debug('Program stdout:\n')
mlog.debug(so)
mlog.debug('Program stderr:\n')
mlog.debug(se)
return compilers.RunResult(True, pe.returncode, so, se)
def sizeof(self, typename: str, prefix: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
t = f'''
import std.stdio : writeln;
{prefix}
void main() {{
writeln(({typename}).sizeof);
}}
'''
res = self.run(t, env, extra_args=extra_args,
dependencies=dependencies)
if not res.compiled:
return -1
if res.returncode != 0:
raise mesonlib.EnvironmentException('Could not run sizeof test binary.')
return int(res.stdout)
def alignment(self, typename: str, prefix: str, env: 'Environment', *,
extra_args: T.Optional[T.List[str]] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> int:
if extra_args is None:
extra_args = []
t = f'''
import std.stdio : writeln;
{prefix}
void main() {{
writeln(({typename}).alignof);
}}
'''
res = self.run(t, env, extra_args=extra_args,
dependencies=dependencies)
if not res.compiled:
raise mesonlib.EnvironmentException('Could not compile alignment test.')
if res.returncode != 0:
raise mesonlib.EnvironmentException('Could not run alignment test binary.')
align = int(res.stdout)
if align == 0:
raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.')
return align
def has_header(self, hname: str, prefix: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
disable_cache: bool = False) -> T.Tuple[bool, bool]:
extra_args = self._get_compile_extra_args(extra_args)
code = f'''{prefix}
import {hname};
'''
return self.compiles(code, env, extra_args=extra_args,
dependencies=dependencies, mode='compile', disable_cache=disable_cache)
class GnuDCompiler(GnuCompiler, DCompiler):

@ -0,0 +1,50 @@
project('test-d-run-checks', 'd')
dc = meson.get_compiler('d')
run_sizeof = dc.run('int main() { return (void*).sizeof; }')
if run_sizeof.returncode() == 8
run_versions = ['Is64bits']
elif run_sizeof.returncode() == 4
run_versions = ['Is32bits']
endif
run_sizeof_exe = executable('run_sizeof', 'test_sizeof.d',
d_module_versions: run_versions,
)
test('test D compiler run', run_sizeof_exe)
sizeof_sizeof = dc.sizeof('void*')
if sizeof_sizeof == 8
run_versions = ['Is64bits']
elif sizeof_sizeof == 4
run_versions = ['Is32bits']
endif
sizeof_sizeof_exe = executable('sizeof_sizeof', 'test_sizeof.d',
d_module_versions: run_versions,
)
test('test D compiler sizeof', sizeof_sizeof_exe)
if not dc.has_header('std.stdio')
error('Could not find std.stdio import')
endif
if dc.has_header('not_a_d_module')
error('has_header inconsistent result')
endif
# same checks as C/C++ alignments (D has same alignment requirements as C)
# These tests should return the same value on all
# platforms. If (and when) they don't, fix 'em up.
if dc.alignment('char') != 1
error('Alignment of char misdetected.')
endif
dbl_alignment = dc.alignment('double')
if dbl_alignment == 8 or dbl_alignment == 4
message('Alignment of double ok.')
else
error('Alignment of double misdetected.')
endif

@ -0,0 +1,17 @@
module test_sizeof;
alias voidp = void*;
int main()
{
version(Is64bits) {
enum expectedSz = 8;
}
else version(Is32bits) {
enum expectedSz = 4;
}
else {
assert(false, "No version set!");
}
return expectedSz == voidp.sizeof ? 0 : 1;
}
Loading…
Cancel
Save