diff options
21 files changed, 49 insertions, 170 deletions
diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index f905d2c..b137166 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -340,15 +340,6 @@ These variables are set in environment in addition to those set using `meson.add schemas is compiled. This is automatically set when using `gnome.compile_schemas()`. Note that this requires GLib >= 2.64 when `gnome.compile_schemas()` is used in more than one directory. -- `PYTHONPATH` *Since 0.62.0* includes every directory where a python module is being - installed using [`python.install_sources()`](Python-module.md#install_sources) - and [`python.extension_module()`](Python-module.md#extension_module). Python - modules installed by other means, such as `install_data()` or `install_subdir()`, - will not be included and should be added to `PYTHONPATH` manually using - [`meson.add_devenv()`](Reference-manual_builtin_meson.md#mesonadd_devenv). - Note that when modules are installed into subdirectories the source tree - layout must match the installed tree layout otherwise `import subdir.mod` - cannot work. Since *Since 0.62.0* if bash-completion scripts are being installed and the shell is bash, they will be automatically sourced. diff --git a/docs/markdown/snippets/devenv.md b/docs/markdown/snippets/devenv.md index 104cfd9..bffa5fa 100644 --- a/docs/markdown/snippets/devenv.md +++ b/docs/markdown/snippets/devenv.md @@ -1,9 +1,3 @@ -## `PYTHONPATH` automatically defined in `meson devenv` - -`PYTHONPATH` now includes every directory where a python module is being -installed using [`python.install_sources()`](Python-module.md#install_sources) -and [`python.extension_module()`](Python-module.md#extension_module). - ## Bash completion scripts sourced in `meson devenv` If bash-completion scripts are being installed and the shell is bash, they will diff --git a/docs/yaml/functions/test.yaml b/docs/yaml/functions/test.yaml index bc9ad03..4e79167 100644 --- a/docs/yaml/functions/test.yaml +++ b/docs/yaml/functions/test.yaml @@ -50,7 +50,7 @@ kwargs_inherit: benchmark kwargs: is_parallel: type: bool - default: false + default: true description: | when false, specifies that no other test must be running at the same time as this test diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 8baa727..e6410c8 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -251,11 +251,9 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler): # be passed to a different compiler with a different set of default # search paths, such as when using Clang for C/C++ and gfortran for # fortran, - search_dir = self._get_search_dirs(env) search_dirs: T.List[str] = [] - if search_dir is not None: - for d in search_dir.split()[-1][len('libraries: ='):].split(':'): - search_dirs.append(f'-L{d}') + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') return search_dirs + ['-lstdc++'] @@ -270,11 +268,9 @@ class AppleClangCPPCompiler(ClangCPPCompiler): # be passed to a different compiler with a different set of default # search paths, such as when using Clang for C/C++ and gfortran for # fortran, - search_dir = self._get_search_dirs(env) search_dirs: T.List[str] = [] - if search_dir is not None: - for d in search_dir.split()[-1][len('libraries: ='):].split(':'): - search_dirs.append(f'-L{d}') + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') return search_dirs + ['-lc++'] @@ -430,11 +426,9 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): # be passed to a different compiler with a different set of default # search paths, such as when using Clang for C/C++ and gfortran for # fortran, - search_dir = self._get_search_dirs(env) search_dirs: T.List[str] = [] - if search_dir is not None: - for d in search_dir.split()[-1][len('libraries: ='):].split(':'): - search_dirs.append(f'-L{d}') + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') return ['-lstdc++'] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index ba2454d..a5d4b6a 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -215,11 +215,9 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler): # be passed to a different compiler with a different set of default # search paths, such as when using Clang for C/C++ and gfortran for # fortran, - search_dir = self._get_search_dirs(env) search_dirs: T.List[str] = [] - if search_dir is not None: - for d in search_dir.split()[-1][len('libraries: ='):].split(':'): - search_dirs.append(f'-L{d}') + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') return search_dirs + ['-lgfortran', '-lm'] def has_header(self, hname: str, prefix: str, env: 'Environment', *, @@ -482,11 +480,9 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler): # search paths, such as when using Clang for C/C++ and gfortran for # fortran, # XXX: Untested.... - search_dir = self._get_search_dirs(env) search_dirs: T.List[str] = [] - if search_dir is not None: - for d in search_dir.split()[-1][len('libraries: ='):].split(':'): - search_dirs.append(f'-L{d}') + for d in self.get_compiler_dirs(env, 'libraries'): + search_dirs.append(f'-L{d}') return search_dirs + ['-lflang', '-lpgmath'] class ArmLtdFlangFortranCompiler(FlangFortranCompiler): diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 04264e5..f063e4e 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -51,7 +51,7 @@ if T.TYPE_CHECKING: # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '0.62.0.rc1' +version = '0.62.0.rc2' backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode'] @@ -1036,7 +1036,7 @@ def load(build_dir: str) -> CoreData: obj = pickle.load(f) except (pickle.UnpicklingError, EOFError): raise MesonException(load_fail_msg) - except (ModuleNotFoundError, AttributeError): + except (TypeError, ModuleNotFoundError, AttributeError): raise MesonException( f"Coredata file {filename!r} references functions or classes that don't " "exist. This probably means that it was generated with an old " diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 8eebcbf..673a781 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -368,17 +368,17 @@ class GnomeModule(ExtensionModule): rv.append(script) if kwargs['gtk_update_icon_cache'] and not self.install_gtk_update_icon_cache: self.install_gtk_update_icon_cache = True - prog = self._get_native_binary(state, 'gtk4-update-icon-cache', 'gtk4', 'gtk4_update_icon_cache', required=False) + prog = state.find_program('gtk4-update-icon-cache', required=False) found = isinstance(prog, build.Executable) or prog.found() if not found: - prog = self._get_native_binary(state, 'gtk-update-icon-cache', 'gtk+-3.0', 'gtk_update_icon_cache') + prog = state.find_program('gtk4-update-icon-cache') icondir = os.path.join(datadir_abs, 'icons', 'hicolor') script = state.backend.get_executable_serialisation([prog, '-q', '-t', '-f', icondir]) script.skip_if_destdir = True rv.append(script) if kwargs['update_desktop_database'] and not self.install_update_desktop_database: self.install_update_desktop_database = True - prog = self._get_native_binary(state, 'update-desktop-database', 'desktop-file-utils', 'update_desktop_database') + prog = state.find_program('update-desktop-database') appdir = os.path.join(datadir_abs, 'applications') script = state.backend.get_executable_serialisation([prog, '-q', appdir]) script.skip_if_destdir = True diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 3eac33f..3bbccd1 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -23,7 +23,7 @@ from . import ExtensionModule from .. import mesonlib from .. import mlog from ..coredata import UserFeatureOption -from ..build import known_shmod_kwargs, EnvironmentVariables +from ..build import known_shmod_kwargs from ..dependencies import DependencyMethods, PkgConfigDependency, NotFoundDependency, SystemDependency, ExtraFrameworkDependency from ..dependencies.base import process_method_kw from ..environment import detect_cpu_family @@ -48,7 +48,6 @@ if T.TYPE_CHECKING: from ..interpreter import Interpreter from ..interpreter.kwargs import ExtractRequired from ..interpreterbase.interpreterbase import TYPE_var, TYPE_kwargs - from ..backends import InstallData class PythonIntrospectionDict(TypedDict): @@ -365,7 +364,6 @@ print(json.dumps({ 'paths': paths, 'sysconfig_paths': sysconfig.get_paths(), 'install_paths': install_paths, - 'sys_paths': sys.path, 'version': sysconfig.get_python_version(), 'platform': sysconfig.get_platform(), 'is_pypy': '__pypy__' in sys.builtin_module_names, @@ -400,20 +398,6 @@ class PythonExternalProgram(ExternalProgram): 'variables': {}, 'version': '0.0', } - self.devenv_pythonpath: T.Set[str] = set() - - def add_devenv_pythonpath(self, basedir: str, subdir: str, install_subdir: str) -> None: - # If we install python module into 'foo/bar' subdir, we need the last 2 - # parts of source dir to be ['foo', 'bar'] and set PYTHONPATH - # pointing grandparent directory. That way scripts will be able to - # `import foo.bar.something` just like when the are installed. - # If the source tree layout does not match installed layout there is - # nothing we can do. - install_subdir_parts = Path(install_subdir).parts - subdir_parts = Path(subdir).parts - if subdir_parts[-len(install_subdir_parts):] == install_subdir_parts: - pypath = os.path.join(basedir, *subdir_parts[:-len(install_subdir_parts)]) - self.devenv_pythonpath.add(pypath) def _check_version(self, version: str) -> bool: if self.name == 'python2': @@ -469,14 +453,6 @@ class PythonExternalProgram(ExternalProgram): # inside a venv, deb_system is *never* active hence info['paths'] may be wrong rel_path = self.info['sysconfig_paths'][key] - # Use python's path relative to prefix, and warn if that's not a location - # python will lookup for modules. - abs_path = Path(state.get_option('prefix'), rel_path) - sys_paths = [Path(i) for i in self.info['sys_paths']] - if abs_path not in sys_paths: - mlog.warning('Python files 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 @@ -522,10 +498,8 @@ class PythonInstallation(ExternalProgramHolder): subdir = kwargs.pop('subdir', '') if not isinstance(subdir, str): raise InvalidArguments('"subdir" argument must be a string.') + kwargs['install_dir'] = os.path.join(self.platlib_install_path, subdir) - self.held_object.add_devenv_pythonpath( - self.interpreter.environment.get_build_dir(), - self.interpreter.subdir, subdir) # On macOS and some Linux distros (Debian) distutils doesn't link # extensions against libpython. We call into distutils and mirror its @@ -580,19 +554,11 @@ class PythonInstallation(ExternalProgramHolder): def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File]]], kwargs: 'PyInstallKw') -> 'Data': tag = kwargs['install_tag'] or 'runtime' - pure = kwargs['pure'] - sources = self.interpreter.source_strings_to_files(args[0]) - install_subdir = kwargs['subdir'] - install_dir = self._get_install_dir_impl(pure, install_subdir) - builddir = self.interpreter.environment.get_build_dir() - srcdir = self.interpreter.environment.get_source_dir() - for src in sources: - basedir = builddir if src.is_built else srcdir - subdir = os.path.dirname(src.relative_name()) - self.held_object.add_devenv_pythonpath(basedir, subdir, install_subdir) - return self.interpreter.install_data_impl(sources, install_dir, + return self.interpreter.install_data_impl( + self.interpreter.source_strings_to_files(args[0]), + self._get_install_dir_impl(kwargs['pure'], kwargs['subdir']), mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python', - install_dir_name=self._get_install_dir_name_impl(pure, install_subdir)) + install_dir_name=self._get_install_dir_name_impl(kwargs['pure'], kwargs['subdir'])) @noPosargs @typed_kwargs('python_installation.install_dir', _PURE_KW, _SUBDIR_KW) @@ -660,18 +626,6 @@ class PythonModule(ExtensionModule): 'find_installation': self.find_installation, }) - def get_devenv(self) -> T.Optional[EnvironmentVariables]: - pythonpath = set() - for python in self.installations.values(): - version = python.info['version'] - if mesonlib.version_compare(version, '>=3.0'): - pythonpath |= python.devenv_pythonpath - if pythonpath: - env = EnvironmentVariables() - env.prepend('PYTHONPATH', list(pythonpath)) - return env - return None - # https://www.python.org/dev/peps/pep-0397/ @staticmethod def _get_win_pythonpath(name_or_path: str) -> T.Optional[str]: diff --git a/mesonbuild/modules/unstable_rust.py b/mesonbuild/modules/unstable_rust.py index f656cd8..85e49cf 100644 --- a/mesonbuild/modules/unstable_rust.py +++ b/mesonbuild/modules/unstable_rust.py @@ -194,7 +194,8 @@ class RustModule(ExtensionModule): inc_strs: T.List[str] = [] for i in kwargs['include_directories']: # bindgen always uses clang, so it's safe to hardcode -I here - inc_strs.extend([f'-I{x}' for x in i.to_string_list(state.environment.get_source_dir())]) + inc_strs.extend([f'-I{x}' for x in i.to_string_list( + state.environment.get_source_dir(), state.environment.get_build_dir())]) if self._bindgen_bin is None: self._bindgen_bin = state.find_program('bindgen') diff --git a/test cases/unit/39 python extmodule/blaster.py b/test cases/python/8 different python versions/blaster.py index 163b6d4..163b6d4 100755 --- a/test cases/unit/39 python extmodule/blaster.py +++ b/test cases/python/8 different python versions/blaster.py diff --git a/test cases/unit/39 python extmodule/ext/meson.build b/test cases/python/8 different python versions/ext/meson.build index b13bb32..b13bb32 100644 --- a/test cases/unit/39 python extmodule/ext/meson.build +++ b/test cases/python/8 different python versions/ext/meson.build diff --git a/test cases/unit/39 python extmodule/ext/tachyon_module.c b/test cases/python/8 different python versions/ext/tachyon_module.c index 68eda53..68eda53 100644 --- a/test cases/unit/39 python extmodule/ext/tachyon_module.c +++ b/test cases/python/8 different python versions/ext/tachyon_module.c diff --git a/test cases/unit/39 python extmodule/meson.build b/test cases/python/8 different python versions/meson.build index 5b44394..2655b06 100644 --- a/test cases/unit/39 python extmodule/meson.build +++ b/test cases/python/8 different python versions/meson.build @@ -5,8 +5,16 @@ py_mod = import('python') py = py_mod.find_installation(get_option('python'), required : false) +# CI images don't have 32-bit python2 for 32-bit windows, +# so this actually gets detected then fails +require = not ( + get_option('python') == 'python2' and + host_machine.system() == 'windows' and + host_machine.cpu() == 'x86' +) + if py.found() - py_dep = py.dependency(required : false) + py_dep = py.dependency(required: require) if py_dep.found() subdir('ext') diff --git a/test cases/unit/39 python extmodule/meson_options.txt b/test cases/python/8 different python versions/meson_options.txt index c85110d..c85110d 100644 --- a/test cases/unit/39 python extmodule/meson_options.txt +++ b/test cases/python/8 different python versions/meson_options.txt diff --git a/test cases/python/8 different python versions/test.json b/test cases/python/8 different python versions/test.json new file mode 100644 index 0000000..fe75a1c --- /dev/null +++ b/test cases/python/8 different python versions/test.json @@ -0,0 +1,13 @@ +{ + "matrix": { + "options": { + "python": [ + { "val": null }, + { "val": "python2" }, + { "val": "python3" }, + { "val": "pypy" }, + { "val": "pypy3" } + ] + } + } +} diff --git a/test cases/unit/91 devenv/meson.build b/test cases/unit/91 devenv/meson.build index f5c24d8..3b0bb6a 100644 --- a/test cases/unit/91 devenv/meson.build +++ b/test cases/unit/91 devenv/meson.build @@ -1,8 +1,4 @@ -project('devenv', 'c', - # Because Windows Python ships only with optimized libs, - # we must build this project the same way. - default_options : ['buildtype=release'], -) +project('devenv', 'c') meson.add_devenv('TEST_A=1') foo_dep = dependency('foo', fallback: 'sub') @@ -19,7 +15,3 @@ meson.add_devenv(env) # This exe links on a library built in another directory. On Windows this means # PATH must contain builddir/subprojects/sub to be able to run it. executable('app', 'main.c', dependencies: foo_dep, install: true) - -py = import('python').find_installation() -py.install_sources('src/mymod/mod.py', subdir: 'mymod') -subdir('src/mymod2') diff --git a/test cases/unit/91 devenv/src/mymod/mod.py b/test cases/unit/91 devenv/src/mymod/mod.py deleted file mode 100644 index 75d6edb..0000000 --- a/test cases/unit/91 devenv/src/mymod/mod.py +++ /dev/null @@ -1 +0,0 @@ -hello = 'world' diff --git a/test cases/unit/91 devenv/src/mymod2/meson.build b/test cases/unit/91 devenv/src/mymod2/meson.build deleted file mode 100644 index 95883fd..0000000 --- a/test cases/unit/91 devenv/src/mymod2/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -py.extension_module('mod2', 'mod2.c', - dependencies: py.dependency(), - subdir: 'mymod2', - install: true -) diff --git a/test cases/unit/91 devenv/src/mymod2/mod2.c b/test cases/unit/91 devenv/src/mymod2/mod2.c deleted file mode 100644 index fe8323e..0000000 --- a/test cases/unit/91 devenv/src/mymod2/mod2.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <Python.h> -#include <string.h> - -static PyObject *hello(PyObject *self, PyObject *args) { - return PyLong_FromLong(42); -} - -static PyMethodDef methods[] = {{"hello", hello, METH_NOARGS, "Hello World"}, - {NULL, NULL, 0, NULL}}; - -static struct PyModuleDef mod = {PyModuleDef_HEAD_INIT, "test", NULL, -1, - methods}; - -PyMODINIT_FUNC PyInit_mod2(void) { return PyModule_Create(&mod); } diff --git a/test cases/unit/91 devenv/test-devenv.py b/test cases/unit/91 devenv/test-devenv.py index 8273805..75497ff 100755 --- a/test cases/unit/91 devenv/test-devenv.py +++ b/test cases/unit/91 devenv/test-devenv.py @@ -1,15 +1,8 @@ #! /usr/bin/python import os -from pathlib import Path assert os.environ['MESON_DEVENV'] == '1' assert os.environ['MESON_PROJECT_NAME'] == 'devenv' assert os.environ['TEST_A'] == '1' assert os.environ['TEST_B'] == '0+1+2+3+4' - -from mymod.mod import hello -assert hello == 'world' - -from mymod2.mod2 import hello -assert hello() == 42 diff --git a/unittests/pythontests.py b/unittests/pythontests.py index c8efbdd..27716d7 100644 --- a/unittests/pythontests.py +++ b/unittests/pythontests.py @@ -26,48 +26,11 @@ class PythonTests(BasePlatformTests): Tests that verify compilation of python extension modules ''' - def test_versions(self): + def test_bad_versions(self): if self.backend is not Backend.ninja: raise unittest.SkipTest(f'Skipping python tests with {self.backend.name} backend') - testdir = os.path.join(self.src_root, 'test cases', 'unit', '39 python extmodule') - - # No python version specified, this will use meson's python - self.init(testdir) - self.build() - self.run_tests() - self.wipe() - - # When specifying a known name, (python2 / python3) the module - # will also try 'python' as a fallback and use it if the major - # version matches - try: - self.init(testdir, extra_args=['-Dpython=python2']) - self.build() - self.run_tests() - except unittest.SkipTest: - # python2 is not necessarily installed on the test machine, - # if it is not, or the python headers can't be found, the test - # will raise MESON_SKIP_TEST, we could check beforehand what version - # of python is available, but it's a bit of a chicken and egg situation, - # as that is the job of the module, so we just ask for forgiveness rather - # than permission. - pass - - self.wipe() - - for py in ('pypy', 'pypy3'): - try: - self.init(testdir, extra_args=['-Dpython=%s' % py]) - except unittest.SkipTest: - # Same as above, pypy2 and pypy3 are not expected to be present - # on the test system, the test project only raises in these cases - continue - - # We have a pypy, this is expected to work - self.build() - self.run_tests() - self.wipe() + testdir = os.path.join(self.src_root, 'test cases', 'python', '8 different python versions') # The test is configured to error out with MESON_SKIP_TEST # in case it could not find python |