Repository: mesonbuild/meson

Issue:
Cross compilation presets
I'm not sure this is a good idea, maybe Meson could be shipped with cross compilation presets on Linux distributions. For example on Fedora, there are mingw, arm(linux/none) compilers, etc.
So while calling meson like this:
```
meson srcdir builddir --cross-file mingw32
```
Meson could look into two path, the current one and and a global one like /etc/meson.d/.
That may help new comers.
The difficulties I see here are:
 - who provides this files Meson or the distribution?
 - when installing with pip 

One other solution would be to share them on github.


Discussion:
I think it's a great idea, but with some changes:

New option `--cross-preset fedora-mingw64`, and we ship the presets with Meson. Initially, we can add presets for Fedora, Ubuntu, Debian and people can contribute more.

I myself have found it annoying to use cross info files because I have to copy the same file into every project.
+1, need this feature.
It should be shipped with Meson rather than any distribution per se because the latter may lead to fragmentation; the (bigger) distributions could already modify the code at will in their own internal repos if, for any reason, they would have to change the defaults. By having meson do this, smaller distributions can also refer/use to it. You also only need to provide the simplest and most logical path in my opinion, not every corner case.
The next package release of Debian will ship with a Debian specific cross file generator. For details [see this link](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859177).

We can extend that to other cases after it has seen some use and we know what it should actually do.
I think it would be great if the toolchains could ship the meson files (i.e. there is a specific directory for such files).
Also a place in say `~/.config` for user specific crossfiles would be nice.
I think presets could address some needs not served by a cross file generator (e.g. microcontroller style embedded projects where a toolchain could be used in quite different ways).

Resolving patch:
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 import pickle, os, uuid
+import sys
 from pathlib import PurePath
 from collections import OrderedDict
 from .mesonlib import MesonException, commonpath
@@ -172,10 +173,7 @@ def __init__(self, options):
         self.external_preprocess_args = {} # CPPFLAGS only
         self.external_args = {} # CPPFLAGS + CFLAGS
         self.external_link_args = {} # CFLAGS + LDFLAGS (with MSVC: only LDFLAGS)
-        if options.cross_file is not None:
-            self.cross_file = os.path.join(os.getcwd(), options.cross_file)
-        else:
-            self.cross_file = None
+        self.cross_file = self.__load_cross_file(options.cross_file)
         self.wrap_mode = options.wrap_mode
         self.compilers = OrderedDict()
         self.cross_compilers = OrderedDict()
@@ -184,6 +182,46 @@ def __init__(self, options):
         # Only to print a warning if it changes between Meson invocations.
         self.pkgconf_envvar = os.environ.get('PKG_CONFIG_PATH', '')
 
+    @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:
+            Linux + BSD:
+                - $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
+            *:
+                - Error
+        BSD follows the Linux path and will honor XDG_* if set. This simplifies
+        the implementation somewhat, especially since most BSD users wont set
+        those environment variables.
+        """
+        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.exists(path_to_try):
+            return path_to_try
+        if sys.platform == 'linux' or 'bsd' in sys.platform.lower():
+            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.exists(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'
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -19,10 +19,12 @@
 import subprocess
 import re, json
 import tempfile
+import textwrap
 import os
 import shutil
 import sys
 import unittest
+from unittest import mock
 from configparser import ConfigParser
 from glob import glob
 from pathlib import PurePath
@@ -2223,6 +2225,50 @@ def test_reconfigure(self):
         self.init(testdir, ['-Db_lto=true'], default_args=False)
         self.build('reconfigure')
 
+    def test_cross_file_system_paths(self):
+        testdir = os.path.join(self.common_test_dir, '1 trivial')
+        cross_content = textwrap.dedent("""\
+            [binaries]
+            c = '/usr/bin/cc'
+            ar = '/usr/bin/ar'
+            strip = '/usr/bin/ar'
+
+            [properties]
+
+            [host_machine]
+            system = 'linux'
+            cpu_family = 'x86'
+            cpu = 'i686'
+            endian = 'little'
+            """)
+
+        with tempfile.TemporaryDirectory() as d:
+            dir_ = os.path.join(d, 'meson', 'cross')
+            os.makedirs(dir_)
+            with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
+                f.write(cross_content)
+            name = os.path.basename(f.name)
+
+            with mock.patch.dict(os.environ, {'XDG_DATA_HOME': d}):
+                self.init(testdir, ['--cross-file=' + name], inprocess=True)
+                self.wipe()
+
+            with mock.patch.dict(os.environ, {'XDG_DATA_DIRS': d}):
+                os.environ.pop('XDG_DATA_HOME', None)
+                self.init(testdir, ['--cross-file=' + name], inprocess=True)
+                self.wipe()
+
+        with tempfile.TemporaryDirectory() as d:
+            dir_ = os.path.join(d, '.local', 'share', 'meson', 'cross')
+            os.makedirs(dir_)
+            with tempfile.NamedTemporaryFile('w', dir=dir_, delete=False) as f:
+                f.write(cross_content)
+            name = os.path.basename(f.name)
+
+            with mock.patch('mesonbuild.coredata.os.path.expanduser', lambda x: x.replace('~', d)):
+                self.init(testdir, ['--cross-file=' + name], inprocess=True)
+                self.wipe()
+
 
 class LinuxArmCrossCompileTests(BasePlatformTests):
     '''


Test patch: