Don't require an exe_wrapper when cross-compiling 32-bit on 64-bit

Almost all 64-bit x86 OSes can run 32-bit x86 binaries natively. Detect
that case and don't require an exe wrapper.
pull/516/head
Nirbheek Chauhan 9 years ago
parent a76693f338
commit c0765b0e8d
  1. 7
      mesonbuild/backend/backends.py
  2. 8
      mesonbuild/backend/ninjabackend.py
  3. 46
      mesonbuild/environment.py
  4. 27
      mesonbuild/interpreter.py

@ -315,7 +315,9 @@ class Backend():
fname = exe.fullpath fname = exe.fullpath
else: else:
fname = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))] fname = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))]
is_cross = self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler() is_cross = self.environment.is_cross_build() and \
self.environment.cross_info.need_cross_compiler() and \
self.environment.cross_info.need_exe_wrapper()
if is_cross: if is_cross:
exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
else: else:
@ -366,8 +368,9 @@ class Backend():
def exe_object_to_cmd_array(self, exe): def exe_object_to_cmd_array(self, exe):
if self.environment.is_cross_build() and \ if self.environment.is_cross_build() and \
self.environment.cross_info.need_exe_wrapper() and \
isinstance(exe, build.BuildTarget) and exe.is_cross: isinstance(exe, build.BuildTarget) and exe.is_cross:
if 'exe_wrapper' not in self.environment.cross_info: if 'exe_wrapper' not in self.environment.cross_info.config:
s = 'Can not use target %s as a generator because it is cross-built\n' s = 'Can not use target %s as a generator because it is cross-built\n'
s += 'and no exe wrapper is defined. You might want to set it to native instead.' s += 'and no exe wrapper is defined. You might want to set it to native instead.'
s = s % exe.name s = s % exe.name

@ -394,9 +394,11 @@ int dummy;
if isinstance(texe, build.Executable): if isinstance(texe, build.Executable):
abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe)) abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe))
deps.append(self.get_target_filename(texe)) deps.append(self.get_target_filename(texe))
if self.environment.is_cross_build() \ if self.environment.is_cross_build() and \
and self.environment.cross_info.config['binaries'].get('exe_wrapper', None) is not None: self.environment.cross_info.need_exe_wrapper():
cmd += [self.environment.cross_info.config['binaries']['exe_wrapper']] exe_wrap = self.environment.cross_info.config['binaries'].get('exe_wrapper', None)
if exe_wrap is not None:
cmd += [exe_wrap]
cmd.append(abs_exe) cmd.append(abs_exe)
else: else:
cmd.append(target.command) cmd.append(target.command)

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os, re, subprocess import os, re, subprocess, platform
from . import coredata, mesonlib from . import coredata, mesonlib
from .compilers import * from .compilers import *
import configparser import configparser
@ -52,6 +52,26 @@ def detect_ninja():
if p.returncode == 0: if p.returncode == 0:
return n return n
def detect_cpu_family():
"""
Python is inconsistent in its platform module.
It returns different values for the same cpu.
For x86 it might return 'x86', 'i686' or somesuch.
Do some canonicalization.
"""
trial = platform.machine().lower()
if trial.startswith('i') and trial.endswith('86'):
return 'x86'
if trial.startswith('arm'):
return 'arm'
if trial == 'amd64':
return 'x86_64'
# Add fixes here as bugs are reported.
return trial
def detect_system():
return platform.system().lower()
class Environment(): class Environment():
private_dir = 'meson-private' private_dir = 'meson-private'
@ -181,7 +201,10 @@ class Environment():
compilers = [self.cross_info.config['binaries']['c']] compilers = [self.cross_info.config['binaries']['c']]
ccache = [] ccache = []
is_cross = True is_cross = True
if self.cross_info.need_exe_wrapper():
exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None) exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
else:
exe_wrap = []
elif evar in os.environ: elif evar in os.environ:
compilers = os.environ[evar].split() compilers = os.environ[evar].split()
ccache = [] ccache = []
@ -239,7 +262,10 @@ class Environment():
if self.is_cross_build() and want_cross: if self.is_cross_build() and want_cross:
compilers = [self.cross_info['fortran']] compilers = [self.cross_info['fortran']]
is_cross = True is_cross = True
if self.cross_info.need_exe_wrapper():
exe_wrap = self.cross_info.get('exe_wrapper', None) exe_wrap = self.cross_info.get('exe_wrapper', None)
else:
exe_wrap = []
elif evar in os.environ: elif evar in os.environ:
compilers = os.environ[evar].split() compilers = os.environ[evar].split()
is_cross = False is_cross = False
@ -308,7 +334,10 @@ class Environment():
compilers = [self.cross_info.config['binaries']['cpp']] compilers = [self.cross_info.config['binaries']['cpp']]
ccache = [] ccache = []
is_cross = True is_cross = True
if self.cross_info.need_exe_wrapper():
exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None) exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None)
else:
exe_wrap = []
elif evar in os.environ: elif evar in os.environ:
compilers = os.environ[evar].split() compilers = os.environ[evar].split()
ccache = [] ccache = []
@ -364,7 +393,10 @@ class Environment():
if self.is_cross_build() and want_cross: if self.is_cross_build() and want_cross:
exelist = [self.cross_info['objc']] exelist = [self.cross_info['objc']]
is_cross = True is_cross = True
if self.cross_info.need_exe_wrapper():
exe_wrap = self.cross_info.get('exe_wrapper', None) exe_wrap = self.cross_info.get('exe_wrapper', None)
else:
exe_wrap = []
else: else:
exelist = self.get_objc_compiler_exelist() exelist = self.get_objc_compiler_exelist()
is_cross = False is_cross = False
@ -394,7 +426,10 @@ class Environment():
if self.is_cross_build() and want_cross: if self.is_cross_build() and want_cross:
exelist = [self.cross_info['objcpp']] exelist = [self.cross_info['objcpp']]
is_cross = True is_cross = True
if self.cross_info.need_exe_wrapper():
exe_wrap = self.cross_info.get('exe_wrapper', None) exe_wrap = self.cross_info.get('exe_wrapper', None)
else:
exe_wrap = []
else: else:
exelist = self.get_objcpp_compiler_exelist() exelist = self.get_objcpp_compiler_exelist()
is_cross = False is_cross = False
@ -700,3 +735,12 @@ class CrossBuildInfo():
# But not when cross compiling a cross compiler. # But not when cross compiling a cross compiler.
def need_cross_compiler(self): def need_cross_compiler(self):
return 'host_machine' in self.config return 'host_machine' in self.config
def need_exe_wrapper(self):
if self.has_host() and detect_cpu_family() == 'x86_64' and \
self.config['host_machine']['cpu_family'] == 'x86' and \
self.config['host_machine']['system'] == detect_system():
# Can almost always run 32-bit binaries on 64-bit natively if the
# host and build systems are the same
return False
return True

@ -322,24 +322,14 @@ class BuildMachine(InterpreterObject):
'endian' : self.endian_method, 'endian' : self.endian_method,
}) })
# Python is inconsistent in its platform module.
# It returns different values for the same cpu.
# For x86 it might return 'x86', 'i686' or somesuch.
# Do some canonicalization.
def cpu_family_method(self, args, kwargs): def cpu_family_method(self, args, kwargs):
trial = platform.machine().lower() return environment.detect_cpu_family()
if trial.startswith('i') and trial.endswith('86'):
return 'x86'
if trial.startswith('arm'):
return 'arm'
# Add fixes here as bugs are reported.
return trial
def cpu_method(self, args, kwargs): def cpu_method(self, args, kwargs):
return platform.machine().lower() return platform.machine().lower()
def system_method(self, args, kwargs): def system_method(self, args, kwargs):
return platform.system().lower() return environment.detect_system()
def endian_method(self, args, kwargs): def endian_method(self, args, kwargs):
return sys.byteorder return sys.byteorder
@ -883,9 +873,16 @@ class MesonMain(InterpreterObject):
return self.interpreter.environment.build_dir return self.interpreter.environment.build_dir
def has_exe_wrapper_method(self, args, kwargs): def has_exe_wrapper_method(self, args, kwargs):
if self.is_cross_build_method(None, None) and 'binaries' in self.build.environment.cross_info.config: if self.is_cross_build_method(None, None) and \
return 'exe_wrap' in self.build.environment.cross_info.config['binaries'] 'binaries' in self.build.environment.cross_info.config and \
return True # This is semantically confusing. self.build.environment.cross_info.need_exe_wrapper():
exe_wrap = self.build.environment.cross_info.config['binaries'].get('exe_wrap', None)
if exe_wrap is None:
return False
# We return True when exe_wrap is defined, when it's not needed, and
# when we're compiling natively. The last two are semantically confusing.
# Need to revisit this.
return True
def is_cross_build_method(self, args, kwargs): def is_cross_build_method(self, args, kwargs):
return self.build.environment.is_cross_build() return self.build.environment.is_cross_build()

Loading…
Cancel
Save