mesonbuild: allow multiple --cross-file options Just like --native-file, allow multiple --cross-file options. This is mostly unifying the logic between cross_files and config_files. Upstream-Status: Backport [will be in 0.50.1] Signed-off-by: Ross Burton diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 40402513..4b9bcb59 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -726,8 +726,7 @@ class Backend: deps = [os.path.join(self.build_to_src, df) for df in self.interpreter.get_build_def_files()] if self.environment.is_cross_build(): - deps.append(os.path.join(self.build_to_src, - self.environment.coredata.cross_file)) + deps.extend(self.environment.coredata.cross_files) deps.append('meson-private/coredata.dat') if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')): deps.append(os.path.join(self.build_to_src, 'meson_options.txt')) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index c3f5a745..ff810683 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -201,8 +201,8 @@ class UserFeatureOption(UserComboOption): return self.value == 'auto' -def load_configs(filenames): - """Load native files.""" +def load_configs(filenames, subdir): + """Load configuration files from a named subdirectory.""" def gen(): for f in filenames: f = os.path.expanduser(os.path.expandvars(f)) @@ -215,7 +215,7 @@ def load_configs(filenames): os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')), ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':') for path in paths: - path_to_try = os.path.join(path, 'meson', 'native', f) + path_to_try = os.path.join(path, 'meson', subdir, f) if os.path.isfile(path_to_try): yield path_to_try break @@ -291,7 +291,7 @@ class CoreData: self.compiler_options = {} self.base_options = {} self.external_preprocess_args = {} # CPPFLAGS only - self.cross_file = self.__load_cross_file(options.cross_file) + self.cross_files = self.__load_config_files(options.cross_file) self.compilers = OrderedDict() self.cross_compilers = OrderedDict() self.deps = OrderedDict() @@ -301,52 +301,14 @@ class CoreData: @staticmethod def __load_config_files(filenames): + # Need to try and make the passed filenames absolute because when the + # files are parsed later we'll have chdir()d. if not filenames: return [] filenames = [os.path.abspath(os.path.expanduser(os.path.expanduser(f))) for f in filenames] return filenames - @staticmethod - def __load_cross_file(filename): - """Try to load the cross file. - - If the filename is None return None. If the filename is an absolute - (after resolving variables and ~), return that absolute path. Next, - check if the file is relative to the current source dir. If the path - still isn't resolved do the following: - Windows: - - Error - *: - - $XDG_DATA_HOME/meson/cross (or ~/.local/share/meson/cross if - undefined) - - $XDG_DATA_DIRS/meson/cross (or - /usr/local/share/meson/cross:/usr/share/meson/cross if undefined) - - Error - - Non-Windows follows the Linux path and will honor XDG_* if set. This - simplifies the implementation somewhat. - """ - if filename is None: - return None - filename = os.path.expanduser(os.path.expandvars(filename)) - if os.path.isabs(filename): - return filename - path_to_try = os.path.abspath(filename) - if os.path.isfile(path_to_try): - return path_to_try - if sys.platform != 'win32': - paths = [ - os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')), - ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':') - for path in paths: - path_to_try = os.path.join(path, 'meson', 'cross', filename) - if os.path.isfile(path_to_try): - return path_to_try - raise MesonException('Cannot find specified cross file: ' + filename) - - raise MesonException('Cannot find specified cross file: ' + filename) - def sanitize_prefix(self, prefix): if not os.path.isabs(prefix): raise MesonException('prefix value {!r} must be an absolute path' @@ -558,8 +520,8 @@ def read_cmd_line_file(build_dir, options): options.cmd_line_options = d properties = config['properties'] - if options.cross_file is None: - options.cross_file = properties.get('cross_file', None) + if not options.cross_file: + options.cross_file = ast.literal_eval(properties.get('cross_file', '[]')) if not options.native_file: # This will be a string in the form: "['first', 'second', ...]", use # literal_eval to get it into the list of strings. @@ -570,7 +532,7 @@ def write_cmd_line_file(build_dir, options): config = CmdLineFileParser() properties = {} - if options.cross_file is not None: + if options.cross_file: properties['cross_file'] = options.cross_file if options.native_file: properties['native_file'] = options.native_file diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 6d86daf9..406ab8b8 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -355,8 +355,8 @@ class Environment: self.machines = MachineInfos() # Will be fully initialized later using compilers later. self.machines.detect_build() - if self.coredata.cross_file: - self.cross_info = CrossBuildInfo(self.coredata.cross_file) + if self.coredata.cross_files: + self.cross_info = CrossBuildInfo(self.coredata.cross_files) if 'exe_wrapper' in self.cross_info.config['binaries']: from .dependencies import ExternalProgram self.exe_wrapper = ExternalProgram.from_bin_list( @@ -373,7 +373,7 @@ class Environment: if self.coredata.config_files: self.config_info = coredata.ConfigData( - coredata.load_configs(self.coredata.config_files)) + coredata.load_configs(self.coredata.config_files, 'native')) else: self.config_info = coredata.ConfigData() @@ -1113,13 +1113,8 @@ class CrossBuildInfo: def ok_type(self, i): return isinstance(i, (str, int, bool)) - def parse_datafile(self, filename): - config = configparser.ConfigParser() - try: - with open(filename, 'r') as f: - config.read_file(f, filename) - except FileNotFoundError: - raise EnvironmentException('File not found: %s.' % filename) + def parse_datafile(self, filenames): + config = coredata.load_configs(filenames, 'cross') # This is a bit hackish at the moment. for s in config.sections(): self.config[s] = {} diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 56a0e9a7..f0a1ae19 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -27,7 +27,9 @@ from .mesonlib import MesonException def add_arguments(parser): coredata.register_builtin_arguments(parser) - parser.add_argument('--cross-file', default=None, + parser.add_argument('--cross-file', + default=[], + action='append', help='File describing cross compilation environment.') parser.add_argument('--native-file', default=[], diff --git a/run_unittests.py b/run_unittests.py index e6874b25..1d247291 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -529,7 +529,7 @@ class InternalTests(unittest.TestCase): config.write(configfile) configfile.flush() configfile.close() - detected_value = mesonbuild.environment.CrossBuildInfo(configfile.name).need_exe_wrapper() + detected_value = mesonbuild.environment.CrossBuildInfo((configfile.name,)).need_exe_wrapper() os.unlink(configfilename) desired_value = not detected_value @@ -541,7 +541,7 @@ class InternalTests(unittest.TestCase): configfilename = configfile.name config.write(configfile) configfile.close() - forced_value = mesonbuild.environment.CrossBuildInfo(configfile.name).need_exe_wrapper() + forced_value = mesonbuild.environment.CrossBuildInfo((configfile.name,)).need_exe_wrapper() os.unlink(configfilename) self.assertEqual(forced_value, desired_value)