diff --git a/backends.py b/backends.py index 1fe98b50e..3338c7e70 100644 --- a/backends.py +++ b/backends.py @@ -248,7 +248,7 @@ class Backend(): fname = [os.path.join(self.environment.get_build_dir(), self.get_target_filename(t.get_exe()))] is_cross = self.environment.is_cross_build() if is_cross: - exe_wrapper = self.environment.cross_info.get('exe_wrapper', None) + exe_wrapper = self.environment.cross_info.config['binaries'].get('exe_wrapper', None) else: exe_wrapper = None ts = TestSerialisation(t.get_name(), fname, is_cross, exe_wrapper, diff --git a/compilers.py b/compilers.py index 23c260f33..38d9b33cc 100644 --- a/compilers.py +++ b/compilers.py @@ -326,7 +326,7 @@ int main(int argc, char **argv) { varname = 'sizeof ' + element varname = varname.replace(' ', '_') if self.is_cross: - val = env.cross_info.get(varname) + val = env.cross_info.config['properties'][varname] if val is not None: if isinstance(val, int): return val @@ -363,7 +363,7 @@ int main(int argc, char **argv) { varname = 'alignment ' + typename varname = varname.replace(' ', '_') if self.is_cross: - val = env.cross_info.get(varname) + val = env.cross_info.config['properties'][varname] if val is not None: if isinstance(val, int): return val @@ -399,7 +399,7 @@ int main(int argc, char **argv) { varname = 'has function ' + funcname varname = varname.replace(' ', '_') if self.is_cross: - val = env.cross_info.get(varname) + val = env.cross_info.config['properties'].get(varname, None) if val is not None: if isinstance(val, bool): return val diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt index 2d2ee62ef..273d29320 100644 --- a/cross/ubuntu-armhf.txt +++ b/cross/ubuntu-armhf.txt @@ -1,11 +1,14 @@ -name = 'linux' +[binaries] +# we could set exe_wrapper = qemu-arm-static but to test the case +# when cross compiled binaries can't be built we don't do that c = '/usr/bin/arm-linux-gnueabihf-gcc' cpp = '/usr/bin/arm-linux-gnueabihf-g++' ar = '/usr/arm-linux-gnueabihf/bin/ar' strip = '/usr/arm-linux-gnueabihf/bin/strip' +pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +[properties] root = '/usr/arm-linux-gnueabihf' -pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' sizeof_int = 4 sizeof_wchar_t = 4 @@ -17,3 +20,7 @@ alignment_double = 4 # Don't know if this is correct... has_function_printf = true has_function_hfkerhisadf = false + +[hostmachine] +name = 'linux' +cpu = 'arm' diff --git a/cross/ubuntu-mingw.txt b/cross/ubuntu-mingw.txt index 76a15a8c3..248151f97 100644 --- a/cross/ubuntu-mingw.txt +++ b/cross/ubuntu-mingw.txt @@ -1,8 +1,20 @@ -name = 'windows' +# Something crazy: compiling on Linux a crosscompiler that +# runs on Windows and generates code for iOS. + +[binaries] exe_wrapper = 'wine' # A command used to run generated executables. c = '/usr/bin/i686-w64-mingw32-gcc' cpp = '/usr/bin/i686-w64-mingw32-g++' ar = '/usr/bin/i686-w64-mingw32-ar' strip = '/usr/bin/i686-w64-mingw32-strip' +[properties] root = '/usr/i686-w64-mingw32' + +[hostmachine] +name = 'windows' +cpu = 'x86' + +[targetmachine] +name='darwin' +cpu='arm' diff --git a/environment.py b/environment.py index 905f20004..987dbc86e 100644 --- a/environment.py +++ b/environment.py @@ -16,6 +16,7 @@ import re import coredata from glob import glob from compilers import * +import configparser build_filename = 'meson.build' @@ -90,7 +91,7 @@ class Environment(): cross = self.is_cross_build() if (not cross and mesonlib.is_windows()) \ - or (cross and self.cross_info['name'] == 'windows'): + or (cross and self.cross_info.has_host() and self.cross_info.config['hostmachine']['name'] == 'windows'): self.exe_suffix = 'exe' self.import_lib_suffix = 'lib' self.shared_lib_suffix = 'dll' @@ -101,7 +102,7 @@ class Environment(): else: self.exe_suffix = '' if (not cross and mesonlib.is_osx()) or \ - (cross and self.cross_info['name'] == 'darwin'): + (cross and self.cross_info.has_host() and self.cross_info.config['hostmachine']['name'] == 'darwin'): self.shared_lib_suffix = 'dylib' else: self.shared_lib_suffix = 'so' @@ -151,10 +152,10 @@ class Environment(): def detect_c_compiler(self, want_cross): evar = 'CC' if self.is_cross_build() and want_cross: - compilers = [self.cross_info['c']] + compilers = [self.cross_info.config['binaries']['c']] ccache = [] is_cross = True - exe_wrap = self.cross_info.get('exe_wrapper', None) + exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None) elif evar in os.environ: compilers = os.environ[evar].split() ccache = [] @@ -269,10 +270,10 @@ class Environment(): def detect_cpp_compiler(self, want_cross): evar = 'CXX' if self.is_cross_build() and want_cross: - compilers = [self.cross_info['cpp']] + compilers = [self.cross_info.config['binaries']['cpp']] ccache = [] is_cross = True - exe_wrap = self.cross_info.get('exe_wrapper', None) + exe_wrap = self.cross_info.config['binaries'].get('exe_wrapper', None) elif evar in os.environ: compilers = os.environ[evar].split() ccache = [] @@ -447,7 +448,7 @@ class Environment(): def detect_static_linker(self, compiler): if compiler.is_cross: - linker = self.cross_info['ar'] + linker = self.cross_info.config['binaries']['ar'] else: evar = 'AR' if evar in os.environ: @@ -587,49 +588,42 @@ def get_args_from_envvars(lang): class CrossBuildInfo(): def __init__(self, filename): - self.items = {} + self.config = {} self.parse_datafile(filename) - if not 'name' in self: - raise EnvironmentException('Cross file must specify "name" (e.g. "linux", "darwin" or "windows".') + if not 'properties' in self.config: + raise EnvironmentError('Cross file is missing "properties".') + if not 'binaries' in self.config: + raise EnvironmentError('Cross file is missing "binaries".') def ok_type(self, i): return isinstance(i, str) or isinstance(i, int) or isinstance(i, bool) def parse_datafile(self, filename): + config = configparser.ConfigParser() + config.read(filename) # This is a bit hackish at the moment. - for i, line in enumerate(open(filename)): - linenum = i+1 - line = line.strip() - if line == '': - continue - if '=' not in line: - raise EnvironmentException('Malformed line in cross file %s:%d.' % (filename, linenum)) - (varname, value) = line.split('=', 1) - varname = varname.strip() - if ' ' in varname or '\t' in varname or "'" in varname or '"' in varname: - raise EnvironmentException('Malformed variable name in cross file %s:%d.' % (filename, linenum)) - try: - res = eval(value, {'true' : True, 'false' : False}) - except Exception: - raise EnvironmentException('Malformed line in cross file %s:%d.' % (filename, linenum)) - if self.ok_type(res): - self.items[varname] = res - elif isinstance(res, list): - for i in res: - if not self.ok_type(i): - raise EnvironmentException('Malformed line in cross file %s:%d.' % (filename, linenum)) - self.items[varname] = res - else: - raise EnvironmentException('Malformed line in cross file %s:%d.' % (filename, linenum)) - - def __getitem__(self, ind): - try: - return self.items[ind] - except KeyError: - raise EnvironmentException('Cross file does not specify variable "%s".' % ind) + for s in config.sections(): + self.config[s] = {} + for entry in config[s]: + value = config[s][entry] + if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry: + raise EnvironmentException('Malformed variable name %s in cross file..' % varname) + try: + res = eval(value, {'true' : True, 'false' : False}) + except Exception: + raise EnvironmentException('Malformed value in cross file variable %s.' % varname) + if self.ok_type(res): + self.config[s][entry] = res + elif isinstance(res, list): + for i in res: + if not self.ok_type(i): + raise EnvironmentException('Malformed value in cross file variable %s.' % varname) + self.items[varname] = res + else: + raise EnvironmentException('Malformed value in cross file variable %s.' % varname) - def __contains__(self, item): - return item in self.items + def has_host(self): + return 'hostmachine' in self.config - def get(self, *args, **kwargs): - return self.items.get(*args, **kwargs) + def has_target(self): + return 'targetmachine' in self.config diff --git a/interpreter.py b/interpreter.py index de3b19905..c74a900a0 100644 --- a/interpreter.py +++ b/interpreter.py @@ -323,7 +323,7 @@ class Host(InterpreterObject): def get_name_method(self, args, kwargs): if self.environment.is_cross_build(): - return self.environment.cross_info.get('name') + return self.environment.cross_info.config['hostmachine']['name'] return platform.system().lower() def is_big_endian_method(self, args, kwargs): @@ -735,7 +735,7 @@ class MesonMain(InterpreterObject): def has_exe_wrapper_method(self, args, kwargs): if self.is_cross_build_method(None, None): - return 'exe_wrap' in self.build.environment.cross_info + return 'exe_wrap' in self.build.environment.cross_info.config['binaries'] return True # This is semantically confusing. def is_cross_build_method(self, args, kwargs): diff --git a/ninjabackend.py b/ninjabackend.py index 9f8175c04..74d09ddc7 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -1268,7 +1268,7 @@ rule FORTRAN_DEP_HACK symname = os.path.join(targetdir, target_name + '.symbols') elem = NinjaBuildElement(symname, 'SHSYM', target_name) if self.environment.is_cross_build(): - elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info['name']) + elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info.config['hostmachine']['name']) elem.write(outfile) def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]):