diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2021-10-04 11:12:29 -0400 |
---|---|---|
committer | Eli Schwartz <eschwartz93@gmail.com> | 2021-10-08 17:47:35 -0400 |
commit | 329d111709ab5c5140f75f29c7176c9546de5770 (patch) | |
tree | 101c75a8dab9b02784d8401cb1d6877f0f241a05 | |
parent | 5316c7df62926d49149053b5d8ccfb4a0042856e (diff) | |
download | meson-329d111709ab5c5140f75f29c7176c9546de5770.zip meson-329d111709ab5c5140f75f29c7176c9546de5770.tar.gz meson-329d111709ab5c5140f75f29c7176c9546de5770.tar.bz2 |
python: Add platlibdir and purelibdir options
-rw-r--r-- | docs/markdown/Builtin-options.md | 20 | ||||
-rw-r--r-- | docs/markdown/Python-module.md | 6 | ||||
-rw-r--r-- | docs/markdown/snippets/python_install_path.md | 12 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 8 | ||||
-rw-r--r-- | mesonbuild/mesonlib/universal.py | 2 | ||||
-rw-r--r-- | mesonbuild/modules/python.py | 17 | ||||
-rw-r--r-- | test cases/python/7 install path/meson.build | 10 | ||||
-rw-r--r-- | test cases/python/7 install path/test.json | 6 | ||||
-rw-r--r-- | test cases/python/7 install path/test.py | 0 | ||||
-rw-r--r-- | unittests/datatests.py | 7 |
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 |