aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Le Bihan <eric.le.bihan.dev@free.fr>2019-11-09 12:45:51 +0100
committerJussi Pakkanen <jpakkane@gmail.com>2019-11-19 16:32:12 +0200
commit815563841aefea1f440cf32565e43114ace9483b (patch)
treeb643d7c07f7213902ca7c0742a245f613832ffd4
parentffdacc4c9c8eb1733afa4b3c9aaa6062ab82ede4 (diff)
downloadmeson-815563841aefea1f440cf32565e43114ace9483b.zip
meson-815563841aefea1f440cf32565e43114ace9483b.tar.gz
meson-815563841aefea1f440cf32565e43114ace9483b.tar.bz2
Fix cross-compilation of D programs
Since version 9.1, GCC provides support for the D programming language. Thus it is easy to build a cross-compiler for D, such as aarch64-unknown-linux-gnu-gdc. However to cross-compile a Meson project using D, using a cross build definition such as the following is not enough: ``` [binaries] d = '/path/to/aarch64-unknown-linux-gnu-gdc' exe_wrapper = '/path/to/qemu-aarch64-static' [properties] needs_exe_wrapper = true [host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'cortex-a53' endian = 'little' ``` Indeed, "exe_wrapper" is not be taken into account. Build will fail with: ``` Executables created by D compiler /path/to/aarch64-uknown-linux-gnu-gdc are not runnable. ``` This patch fixes this by reworking: - detect_d_compiler() to properly get exe_wrapper and D compilers and detect the one available. - Dcompiler to properly handle exe_wrapper.
-rw-r--r--mesonbuild/compilers/d.py21
-rw-r--r--mesonbuild/environment.py142
2 files changed, 86 insertions, 77 deletions
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index c9e8b44..907aeec 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -413,11 +413,13 @@ class DCompiler(Compiler):
}
def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', arch, **kwargs):
+ info: 'MachineInfo', arch, is_cross, exe_wrapper, **kwargs):
self.language = 'd'
super().__init__(exelist, version, for_machine, info, **kwargs)
self.id = 'unknown'
self.arch = arch
+ self.exe_wrapper = exe_wrapper
+ self.is_cross = is_cross
def sanity_check(self, work_dir, environment):
source_name = os.path.join(work_dir, 'sanity.d')
@@ -428,7 +430,14 @@ class DCompiler(Compiler):
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('D compiler %s can not compile programs.' % self.name_string())
- if subprocess.call(output_name) != 0:
+ if self.is_cross:
+ if self.exe_wrapper is None:
+ # Can't check if the binaries run so we have to assume they do
+ return
+ cmdlist = self.exe_wrapper.get_command() + [output_name]
+ else:
+ cmdlist = [output_name]
+ if subprocess.call(cmdlist) != 0:
raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string())
def needs_static_linker(self):
@@ -602,8 +611,8 @@ class GnuDCompiler(DCompiler, GnuCompiler):
LINKER_PREFIX = GnuCompiler.LINKER_PREFIX
def __init__(self, exelist, version, for_machine: MachineChoice,
- info: 'MachineInfo', arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, arch, **kwargs)
+ info: 'MachineInfo', is_cross, exe_wrapper, arch, **kwargs):
+ DCompiler.__init__(self, exelist, version, for_machine, info, is_cross, exe_wrapper, arch, **kwargs)
self.id = 'gcc'
default_warn_args = ['-Wall', '-Wdeprecated']
self.warn_args = {'0': [],
@@ -651,7 +660,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompi
def __init__(self, exelist, version, for_machine: MachineChoice,
info: 'MachineInfo', arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, arch, **kwargs)
+ DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'llvm'
self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
@@ -693,7 +702,7 @@ class DmdDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompil
def __init__(self, exelist, version, for_machine: MachineChoice,
info: 'MachineInfo', arch, **kwargs):
- DCompiler.__init__(self, exelist, version, for_machine, info, arch, **kwargs)
+ DCompiler.__init__(self, exelist, version, for_machine, info, arch, False, None, **kwargs)
self.id = 'dmd'
self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt']
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index f53f17f..0763e7d 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -1337,30 +1337,6 @@ class Environment:
def detect_d_compiler(self, for_machine: MachineChoice):
info = self.machines[for_machine]
- exelist = self.binaries[for_machine].lookup_entry('d')
- # Search for a D compiler.
- # We prefer LDC over GDC unless overridden with the DC
- # environment variable because LDC has a much more
- # up to date language version at time (2016).
- if exelist is not None:
- if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')):
- raise EnvironmentException(
- 'Meson does not support {} as it is only a DMD frontend for another compiler.'
- 'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.'.format(exelist[-1]))
- else:
- for d in self.default_d:
- if shutil.which(d):
- exelist = [d]
- break
- else:
- raise EnvironmentException('Could not find any supported D compiler.')
-
- try:
- p, out = Popen_safe(exelist + ['--version'])[0:2]
- except OSError:
- raise EnvironmentException('Could not execute D compiler "%s"' % ' '.join(exelist))
- version = search_version(out)
- full_version = out.split('\n', 1)[0]
# Detect the target architecture, required for proper architecture handling on Windows.
c_compiler = {}
@@ -1372,55 +1348,79 @@ class Environment:
if is_msvc and arch == 'x86':
arch = 'x86_mscoff'
- if 'LLVM D compiler' in out:
- # LDC seems to require a file
- m = self.machines[for_machine]
- if m.is_windows() or m.is_cygwin():
- if is_msvc:
- linker = MSVCDynamicLinker(for_machine, version=version)
+ popen_exceptions = {}
+ is_cross = not self.machines.matches_build_machine(for_machine)
+ results, ccache, exe_wrap = self._get_compilers('d', for_machine)
+ for exelist in results:
+ # Search for a D compiler.
+ # We prefer LDC over GDC unless overridden with the DC
+ # environment variable because LDC has a much more
+ # up to date language version at time (2016).
+ if not isinstance(exelist, list):
+ exelist = [exelist]
+ if os.path.basename(exelist[-1]).startswith(('ldmd', 'gdmd')):
+ raise EnvironmentException(
+ 'Meson does not support {} as it is only a DMD frontend for another compiler.'
+ 'Please provide a valid value for DC or unset it so that Meson can resolve the compiler by itself.'.format(exelist[-1]))
+ try:
+ p, out = Popen_safe(exelist + ['--version'])[0:2]
+ except OSError as e:
+ popen_exceptions[' '.join(exelist + ['--version'])] = e
+ continue
+ version = search_version(out)
+ full_version = out.split('\n', 1)[0]
+
+ if 'LLVM D compiler' in out:
+ # LDC seems to require a file
+ m = self.machines[for_machine]
+ if m.is_windows() or m.is_cygwin():
+ if is_msvc:
+ linker = MSVCDynamicLinker(for_machine, version=version)
+ else:
+ # Getting LDC on windows to give useful linker output when not
+ # doing real work is painfully hard. It ships with a version of
+ # lld-link, so just assume that we're going to use lld-link
+ # with it.
+ _, o, _ = Popen_safe(['lld-link.exe', '--version'])
+ linker = ClangClDynamicLinker(for_machine, version=search_version(o))
else:
- # Getting LDC on windows to give useful linker output when not
- # doing real work is painfully hard. It ships with a version of
- # lld-link, so just assume that we're going to use lld-link
- # with it.
- _, o, _ = Popen_safe(['lld-link.exe', '--version'])
- linker = ClangClDynamicLinker(for_machine, version=search_version(o))
- else:
- with tempfile.NamedTemporaryFile(suffix='.d') as f:
- linker = self._guess_nix_linker(
- exelist, for_machine,
- compilers.LLVMDCompiler.LINKER_PREFIX,
- extra_args=[f.name])
- return compilers.LLVMDCompiler(
- exelist, version, for_machine, info, arch,
- full_version=full_version, linker=linker)
- elif 'gdc' in out:
- linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
- return compilers.GnuDCompiler(
- exelist, version, for_machine, info, arch,
- full_version=full_version, linker=linker)
- elif 'The D Language Foundation' in out or 'Digital Mars' in out:
- # DMD seems to require a file
- m = self.machines[for_machine]
- if m.is_windows() or m.is_cygwin():
- if is_msvc:
- linker = MSVCDynamicLinker(for_machine, version=version)
- elif arch == 'x86':
- linker = OptlinkDynamicLinker(for_machine, version=full_version)
+ with tempfile.NamedTemporaryFile(suffix='.d') as f:
+ linker = self._guess_nix_linker(
+ exelist, for_machine,
+ compilers.LLVMDCompiler.LINKER_PREFIX,
+ extra_args=[f.name])
+ return compilers.LLVMDCompiler(
+ exelist, version, for_machine, info, arch,
+ full_version=full_version, linker=linker)
+ elif 'gdc' in out:
+ linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
+ return compilers.GnuDCompiler(
+ exelist, version, for_machine, info, arch, is_cross, exe_wrap,
+ full_version=full_version, linker=linker)
+ elif 'The D Language Foundation' in out or 'Digital Mars' in out:
+ # DMD seems to require a file
+ m = self.machines[for_machine]
+ if m.is_windows() or m.is_cygwin():
+ if is_msvc:
+ linker = MSVCDynamicLinker(for_machine, version=version)
+ elif arch == 'x86':
+ linker = OptlinkDynamicLinker(for_machine, version=full_version)
+ else:
+ # DMD ships with lld-link
+ _, o, _ = Popen_safe(['lld-link.exe', '--version'])
+ linker = ClangClDynamicLinker(for_machine, version=search_version(o))
else:
- # DMD ships with lld-link
- _, o, _ = Popen_safe(['lld-link.exe', '--version'])
- linker = ClangClDynamicLinker(for_machine, version=search_version(o))
- else:
- with tempfile.NamedTemporaryFile(suffix='.d') as f:
- linker = self._guess_nix_linker(
- exelist, for_machine,
- compilers.LLVMDCompiler.LINKER_PREFIX,
- extra_args=[f.name])
- return compilers.DmdDCompiler(
- exelist, version, for_machine, info, arch,
- full_version=full_version, linker=linker)
- raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+ with tempfile.NamedTemporaryFile(suffix='.d') as f:
+ linker = self._guess_nix_linker(
+ exelist, for_machine,
+ compilers.LLVMDCompiler.LINKER_PREFIX,
+ extra_args=[f.name])
+ return compilers.DmdDCompiler(
+ exelist, version, for_machine, info, arch,
+ full_version=full_version, linker=linker)
+ raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
+
+ self._handle_exceptions(popen_exceptions, compilers)
def detect_swift_compiler(self, for_machine):
exelist = self.binaries.host.lookup_entry('swift')