summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2017-11-14 15:08:35 -0800
committerJussi Pakkanen <jpakkane@gmail.com>2017-11-30 22:34:27 +0200
commit6f25e93b524ec827a55c13632c9ff23a20d8d3c2 (patch)
tree5ac3f4638928f8201a8641efaeb8a3263c9ced7d
parentecba22965d438e94a260c6c5d00a034a8d144904 (diff)
downloadmeson-6f25e93b524ec827a55c13632c9ff23a20d8d3c2.tar.gz
cross: Implement support for loading cross files from system paths
One thing that makes cross compiling with meson a pain is the need for cross files. The problem is not with cross files themselves (they're actually rather brilliant in that they allow for a much greater deal of flexibility than autotools hardcoded paths approach) but that each user needs to reimplement them themselves, when for most people what they really want is a cross file that could be provided by their distro, all they really want is the correct toolchain. This patch is the first stop to making it easier for distros to ship their own cross files (and for users to put their's somewhere safe so they don't get `git clean`ed. It allows the cross files (on Linux and *BSD) to be stored in home and system paths (~/.config/meson/cross, /usr/share/meson/cross, and /usr/local/share/meson/cross), and to be loaded by simply by specificying --cross-file. With this patch meson will check the locations its always checked first, (is cross file absolute, or is it relative to $PWD), then will check ~/.config/meson/cross, /usr/local/share/meson/cross, /usr/share/meson/cross, (or $XDG_CONFIG_PATH and $XDG_DATA_DIRS) for the files, raising an exception if it cannot find the specified cross file. Fixes #2283
-rw-r--r--docs/markdown/Cross-compilation.md26
-rw-r--r--docs/markdown/snippets/system-wide-cross-files.md20
-rw-r--r--mesonbuild/coredata.py46
-rwxr-xr-xrun_unittests.py46
4 files changed, 134 insertions, 4 deletions
diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md
index f68b1f575..c1ad317c7 100644
--- a/docs/markdown/Cross-compilation.md
+++ b/docs/markdown/Cross-compilation.md
@@ -257,3 +257,29 @@ then you can access that using the `meson` object like this:
myvar = meson.get_cross_property('somekey')
# myvar now has the value 'somevalue'
```
+
+## Cross file locations
+
+As of version 0.44.0 meson supports loading cross files from system locations
+on Linux and the BSDs. This will be $XDG_DATA_DIRS/meson/cross, or if
+XDG_DATA_DIRS is undefined, then /usr/local/share/meson/cross and
+/usr/share/meson/cross will be tried in that order, for system wide cross
+files. User local files can be put in $XDG_DATA_HOME/meson/cross, or
+~/.local/share/meson/cross if that is undefined.
+
+The order of locations tried is as follows:
+ - A file relative to the local dir
+ - The user local location
+ - The system wide locations in order
+
+Linux and BSD distributions are encouraged to ship cross files either with
+their cross compiler toolchain packages or as a standalone package, and put
+them in one of the system paths referenced above.
+
+These files can be loaded automatically without adding a path to the cross
+file. For example, if a ~/.local/share/meson/cross contains a file called x86-linux,
+then the following command would start a cross build using that cross files:
+
+```sh
+meson builddir/ --cross-file x86-linux
+```
diff --git a/docs/markdown/snippets/system-wide-cross-files.md b/docs/markdown/snippets/system-wide-cross-files.md
new file mode 100644
index 000000000..66c454fb3
--- /dev/null
+++ b/docs/markdown/snippets/system-wide-cross-files.md
@@ -0,0 +1,20 @@
+## System wide and user local cross files
+
+Meson has gained the ability to load cross files from predefined locations
+without passing a full path on Linux and the BSD OSes. User local files will be
+loaded from `$XDG_DATA_HOME/meson/cross`, or if XDG_DATA_HOME is undefined,
+`~/.local/share/meson/cross` will be used.
+
+For system wide paths the values of `$XDG_DATA_DIRS` + `/meson/cross` will be used,
+if XDG_DATA_DIRS is undefined then `/usr/local/share/meson/cross:/usr/share/meson/cross`
+will be used instead.
+
+A file relative to the current working directory will be tried first, then the
+user specific path will be tried before the system wide paths.
+
+Assuming that a file x86-linux is located in one of those places a cross build
+can be started with:
+
+```sh
+meson builddir/ --cross-file x86-linux
+```
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 401211a6b..68b1abf69 100644
--- 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 @@ class CoreData:
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 @@ class CoreData:
# 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
index 8af872e26..5b3b3e119 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -19,10 +19,12 @@ import shlex
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 @@ endian = 'little'
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):
'''