aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2021-10-04 11:12:29 -0400
committerEli Schwartz <eschwartz93@gmail.com>2021-10-08 17:47:35 -0400
commit329d111709ab5c5140f75f29c7176c9546de5770 (patch)
tree101c75a8dab9b02784d8401cb1d6877f0f241a05
parent5316c7df62926d49149053b5d8ccfb4a0042856e (diff)
downloadmeson-329d111709ab5c5140f75f29c7176c9546de5770.zip
meson-329d111709ab5c5140f75f29c7176c9546de5770.tar.gz
meson-329d111709ab5c5140f75f29c7176c9546de5770.tar.bz2
python: Add platlibdir and purelibdir options
-rw-r--r--docs/markdown/Builtin-options.md20
-rw-r--r--docs/markdown/Python-module.md6
-rw-r--r--docs/markdown/snippets/python_install_path.md12
-rw-r--r--mesonbuild/coredata.py8
-rw-r--r--mesonbuild/mesonlib/universal.py2
-rw-r--r--mesonbuild/modules/python.py17
-rw-r--r--test cases/python/7 install path/meson.build10
-rw-r--r--test cases/python/7 install path/test.json6
-rw-r--r--test cases/python/7 install path/test.py0
-rw-r--r--unittests/datatests.py7
10 files changed, 78 insertions, 10 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index 37bf715..41f8b84 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -260,3 +260,23 @@ The value is overridden in this order:
- Value from command line if set
Since 0.56.0 `warning_level` can also be defined per subproject.
+
+## Module options
+
+Some Meson modules have built-in options. They can be set by prefixing the option
+name with the module name: `-D<module>.<option>=<value>` (e.g. `-Dpython.platlibdir=/foo`).
+
+### Python module
+
+| Option | Default value | Possible values | Description |
+| ------ | ------------- | --------------- | ----------- |
+| platlibdir | | Directory path | Directory for site-specific, platform-specific files (Since 0.60.0) |
+| purelibdir | | Directory path | Directory for site-specific, non-platform-specific files (Since 0.60.0) |
+
+*Since 0.60.0* `python.platlibdir` and `python.purelibdir` options are used by
+python module methods `python.install_sources()` and `python.get_install_dir()`.
+By default Meson tries to detect the correct installation path, but make them
+relative to the installation `prefix`, which will often result in installed python
+modules to not be found by the interpreter unless `prefix` is `/usr` on Linux,
+or for example `C:\Python39` on Windows. These options can be absolute paths
+outside of `prefix`.
diff --git a/docs/markdown/Python-module.md b/docs/markdown/Python-module.md
index 5d7b5ed..0602955 100644
--- a/docs/markdown/Python-module.md
+++ b/docs/markdown/Python-module.md
@@ -128,6 +128,9 @@ Install actual python sources (`.py`).
All positional and keyword arguments are the same as for
[[install_data]], with the addition of the following:
+*Since 0.60.0* `python.platlibdir` and `python.purelibdir` options can be used
+to control the default installation path. See [Python module options](Builtin-options.md#python-module).
+
- `pure`: On some platforms, architecture independent files are
expected to be placed in a separate directory. However, if the
python sources should be installed alongside an extension module
@@ -154,6 +157,9 @@ directly, for example when using [[configure_file]].
This function accepts no arguments, its keyword arguments are the same
as [][`install_sources()`].
+*Since 0.60.0* `python.platlibdir` and `python.purelibdir` options can be used
+to control the default installation path. See [Python module options](Builtin-options.md#python-module).
+
**Returns**: A string
#### `language_version()`
diff --git a/docs/markdown/snippets/python_install_path.md b/docs/markdown/snippets/python_install_path.md
new file mode 100644
index 0000000..4f22e50
--- /dev/null
+++ b/docs/markdown/snippets/python_install_path.md
@@ -0,0 +1,12 @@
+## Override python installation paths
+
+The `python` module now has options to control where modules are installed:
+- python.platlibdir: Directory for site-specific, platform-specific files.
+- python.purelibdir: Directory for site-specific, non-platform-specific files.
+
+Those options are used by python module methods `python.install_sources()` and
+`python.get_install_dir()`. By default Meson tries to detect the correct installation
+path, but make them relative to the installation `prefix`, which will often result
+in installed python modules to not be found by the interpreter unless `prefix`
+is `/usr` on Linux, or for example `C:\Python39` on Windows. These new options
+can be absolute paths outside of `prefix`.
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index e852e4d..4c7b24c 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -1188,6 +1188,12 @@ BUILTIN_CORE_OPTIONS: 'KeyedOptionDictType' = OrderedDict([
(OptionKey('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)),
(OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])),
(OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
+
+ # Python module
+ (OptionKey('platlibdir', module='python'),
+ BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')),
+ (OptionKey('purelibdir', module='python'),
+ BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')),
])
BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items()))
@@ -1203,6 +1209,8 @@ BULITIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
OptionKey('sysconfdir'): {'/usr': '/etc'},
OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'},
OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
+ OptionKey('platlibdir', module='python'): {},
+ OptionKey('purelibdir', module='python'): {},
}
FORBIDDEN_TARGET_NAMES = {'clean': None,
diff --git a/mesonbuild/mesonlib/universal.py b/mesonbuild/mesonlib/universal.py
index 6eedd79..ebf9cb0 100644
--- a/mesonbuild/mesonlib/universal.py
+++ b/mesonbuild/mesonlib/universal.py
@@ -2100,7 +2100,7 @@ class OptionKey:
def __hash__(self) -> int:
return self._hash
- def _to_tuple(self):
+ def _to_tuple(self) -> T.Tuple[str, OptionType, str, str, MachineChoice, str]:
return (self.subproject, self.type, self.lang or '', self.module or '', self.machine, self.name)
def __eq__(self, other: object) -> bool:
diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py
index 1f948cf..58d805b 100644
--- a/mesonbuild/modules/python.py
+++ b/mesonbuild/modules/python.py
@@ -374,7 +374,7 @@ class PythonExternalProgram(ExternalProgram):
return mesonlib.version_compare(version, '>= 3.0')
return True
- def sanity(self) -> bool:
+ def sanity(self, state: T.Optional['ModuleState'] = None) -> bool:
# Sanity check, we expect to have something that at least quacks in tune
cmd = self.get_command() + ['-c', INTROSPECT_COMMAND]
p, stdout, stderr = mesonlib.Popen_safe(cmd)
@@ -392,19 +392,24 @@ class PythonExternalProgram(ExternalProgram):
variables = info['variables']
info['suffix'] = variables.get('EXT_SUFFIX') or variables.get('SO') or variables.get('.so')
self.info = T.cast('PythonIntrospectionDict', info)
- self.platlib = self._get_path('platlib')
- self.purelib = self._get_path('purelib')
+ self.platlib = self._get_path(state, 'platlib')
+ self.purelib = self._get_path(state, 'purelib')
return True
else:
return False
- def _get_path(self, key: str) -> None:
+ def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None:
+ if state:
+ value = state.get_option(f'{key}dir', module='python')
+ if value:
+ return value
user_dir = str(Path.home())
sys_paths = self.info['sys_paths']
rel_path = self.info['install_paths'][key][1:]
if not any(p.endswith(rel_path) for p in sys_paths if not p.startswith(user_dir)):
mlog.warning('Broken python installation detected. Python files',
- 'installed by Meson might not be found by python interpreter.',
+ 'installed by Meson might not be found by python interpreter.\n',
+ f'This warning can be avoided by setting "python.{key}dir" option.',
once=True)
return rel_path
@@ -697,7 +702,7 @@ class PythonModule(ExtensionModule):
raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules)))
return NonExistingExternalProgram()
else:
- sane = python.sanity()
+ sane = python.sanity(state)
if sane:
return python
diff --git a/test cases/python/7 install path/meson.build b/test cases/python/7 install path/meson.build
new file mode 100644
index 0000000..4a7df7e
--- /dev/null
+++ b/test cases/python/7 install path/meson.build
@@ -0,0 +1,10 @@
+project('install path',
+ default_options: [
+ 'python.purelibdir=/pure',
+ 'python.platlibdir=/plat'
+ ]
+)
+
+py = import('python').find_installation()
+py.install_sources('test.py')
+py.install_sources('test.py', pure: false)
diff --git a/test cases/python/7 install path/test.json b/test cases/python/7 install path/test.json
new file mode 100644
index 0000000..f03ada8
--- /dev/null
+++ b/test cases/python/7 install path/test.json
@@ -0,0 +1,6 @@
+{
+ "installed": [
+ {"type": "file", "file": "plat/test.py"},
+ {"type": "file", "file": "pure/test.py"}
+ ]
+}
diff --git a/test cases/python/7 install path/test.py b/test cases/python/7 install path/test.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/python/7 install path/test.py
diff --git a/unittests/datatests.py b/unittests/datatests.py
index b82ff1c..e440243 100644
--- a/unittests/datatests.py
+++ b/unittests/datatests.py
@@ -126,7 +126,8 @@ class DataTests(unittest.TestCase):
subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE))
subcontent1 = self._get_section_content("Directories", subsections[0], content)
subcontent2 = self._get_section_content("Core options", subsections[1], content)
- for subcontent in (subcontent1, subcontent2):
+ subcontent3 = self._get_section_content("Module options", sections, md)
+ for subcontent in (subcontent1, subcontent2, subcontent3):
# Find the option names
options = set()
# Match either a table row or a table heading separator: | ------ |
@@ -145,8 +146,8 @@ class DataTests(unittest.TestCase):
found_entries |= options
self.assertEqual(found_entries, {
- *(str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS),
- *(str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE),
+ *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS),
+ *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE),
})
# Check that `buildtype` table inside `Core options` matches how