From d2e7250433e561725ff82b167739de903ca17a0f Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Sun, 16 Jun 2024 07:02:03 -0600 Subject: [PATCH 01/72] Update Users.md entry for fossil-lib --- docs/markdown/Users.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 19c4ea6438e4..70060ab05247 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -168,7 +168,7 @@ format files - [ThorVG](https://www.thorvg.org/), vector-based scenes and animations library - [Tilix](https://github.com/gnunn1/tilix), a tiling terminal emulator for Linux using GTK+ 3 - [Tizonia](https://github.com/tizonia/tizonia-openmax-il), a command-line cloud music player for Linux with support for Spotify, Google Play Music, YouTube, SoundCloud, TuneIn, Plex servers and Chromecast devices - - [Fossil Logic Standard](https://github.com/fossil-lib), a collection frameworks in C/C++, Objective-C and Objective-C++. + - [Fossil Logic](https://github.com/fossillogic), Fossil Logic is a cutting-edge software development company specializing in C/C++, Python, programming, Android development using Kotlin, and SQL solutions. - [UFJF-MLTK](https://github.com/mateus558/UFJF-Machine-Learning-Toolkit), A C++ cross-platform framework for machine learning algorithms development and testing - [Vala Language Server](https://github.com/benwaffle/vala-language-server), code intelligence engine for the Vala and Genie programming languages - [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala From dbfd3e8c41b96d40511f9a683d9718e2aca32275 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 26 Jun 2024 10:44:46 -0400 Subject: [PATCH 02/72] format: fix edge case with empty functions format was adding a new empty line each time when trying to split a long line containing a function with no arguments --- mesonbuild/mformat.py | 2 +- mesonbuild/mparser.py | 2 +- test cases/format/1 default/gh13242.meson | 4 +--- test cases/format/1 default/meson.build | 3 +++ 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index e20e45851820..42f562e7f278 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -744,7 +744,7 @@ def visit_BreakNode(self, node: mparser.BreakNode) -> None: self.exit_node(node) def split_if_needed(self, node: mparser.ArgumentNode) -> None: - if not node.is_multiline and self.length > self.config.max_line_length: + if len(node) and not node.is_multiline and self.length > self.config.max_line_length: arg = self.argument_stack[self.level] if len(self.argument_stack) > self.level else node if not arg.is_multiline: arg.is_multiline = True diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index ec08ccfb2583..50d720313495 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -377,7 +377,7 @@ def incorrect_order(self) -> bool: return self.order_error def __len__(self) -> int: - return self.num_args() # Fixme + return self.num_args() + self.num_kwargs() @dataclass(unsafe_hash=True) class ArrayNode(BaseNode): diff --git a/test cases/format/1 default/gh13242.meson b/test cases/format/1 default/gh13242.meson index b9122ec812d8..67f7dd1bb9e1 100644 --- a/test cases/format/1 default/gh13242.meson +++ b/test cases/format/1 default/gh13242.meson @@ -10,9 +10,7 @@ test( ) test( - should_fail: (settings.get('x', false) and not settings['y'] and dep.version( - - ).version_compare( + should_fail: (settings.get('x', false) and not settings['y'] and dep.version().version_compare( '>=1.2.3', )), ) diff --git a/test cases/format/1 default/meson.build b/test cases/format/1 default/meson.build index 35e5b9694fb8..83ae19aa0bde 100644 --- a/test cases/format/1 default/meson.build +++ b/test cases/format/1 default/meson.build @@ -10,6 +10,9 @@ meson_files = { 'gh13242': files('gh13242.meson'), } +# Ensure empty function are formatted correctly on long lines +a = '@0@@1@@2@@3@@4@'.format('one', 'two', 'three', 'four', 'five').strip().strip() + foreach name, f : meson_files test(name, meson_cmd, args: ['format', '--check-only', f]) endforeach From 87681980bc8f49d8f3dbbcb0db8944a487575e96 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 12:27:07 -0700 Subject: [PATCH 03/72] compilers: pass Environment to openmp_flags This will be needed by the Apple compiler --- mesonbuild/compilers/compilers.py | 8 ++++---- mesonbuild/compilers/fortran.py | 8 ++++---- mesonbuild/compilers/mixins/clang.py | 2 +- mesonbuild/compilers/mixins/elbrus.py | 4 ++-- mesonbuild/compilers/mixins/gnu.py | 4 ++-- mesonbuild/compilers/mixins/intel.py | 7 +++++-- mesonbuild/compilers/mixins/pgi.py | 2 +- mesonbuild/compilers/mixins/visualstudio.py | 4 ++-- mesonbuild/dependencies/misc.py | 10 +++++----- mesonbuild/linkers/linkers.py | 2 +- 10 files changed, 27 insertions(+), 24 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index c03f1fd372a0..08a596c7078c 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations @@ -936,11 +936,11 @@ def thread_flags(self, env: 'Environment') -> T.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]: return self.linker.thread_flags(env) - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language()) - def openmp_link_flags(self) -> T.List[str]: - return self.openmp_flags() + def openmp_link_flags(self, env: Environment) -> T.List[str]: + return self.openmp_flags(env) def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: return [] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index ad266e9751a9..3e332381d53b 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -256,7 +256,7 @@ def get_module_incdir_args(self) -> T.Tuple[str, ...]: def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-moddir=' + path] - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-xopenmp'] @@ -381,7 +381,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic '3': default_warn_args, 'everything': default_warn_args} - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-mp'] @@ -482,7 +482,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic '3': default_warn_args, 'everything': default_warn_args} - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-mp'] @@ -525,5 +525,5 @@ def get_preprocess_only_args(self) -> T.List[str]: def get_std_exe_link_args(self) -> T.List[str]: return self.get_always_args() - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-openmp'] diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index e9e83f28615f..a799e06a3c8e 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -123,7 +123,7 @@ def has_function(self, funcname: str, prefix: str, env: 'Environment', *, return super().has_function(funcname, prefix, env, extra_args=extra_args, dependencies=dependencies) - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: if mesonlib.version_compare(self.version, '>=3.8.0'): return ['-fopenmp'] elif mesonlib.version_compare(self.version, '>=3.7.0'): diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py index 10df3decb776..71cf722c8192 100644 --- a/mesonbuild/compilers/mixins/elbrus.py +++ b/mesonbuild/compilers/mixins/elbrus.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations @@ -89,5 +89,5 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] args.append('-std=' + std) return args - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-fopenmp'] diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 587b0cc6d885..4a9eb8848489 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -402,7 +402,7 @@ def get_default_include_dirs(self) -> T.List[str]: return gnulike_default_include_dirs(tuple(self.get_exelist(ccache=False)), self.language).copy() @abc.abstractmethod - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: pass def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]: @@ -585,7 +585,7 @@ def get_optimization_args(self, optimization_level: str) -> T.List[str]: def get_pch_suffix(self) -> str: return 'gch' - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-fopenmp'] def has_arguments(self, args: T.List[str], env: 'Environment', code: str, diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index d38a42ebbf52..902cc748145f 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -19,6 +19,9 @@ from .gnu import GnuLikeCompiler from .visualstudio import VisualStudioLikeCompiler +if T.TYPE_CHECKING: + from ...environment import Environment + # XXX: avoid circular dependencies # TODO: this belongs in a posix compiler class # NOTE: the default Intel optimization is -O2, unlike GNU which defaults to -O0. @@ -78,7 +81,7 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: def get_pch_name(self, name: str) -> str: return os.path.basename(name) + '.' + self.get_pch_suffix() - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: if mesonlib.version_compare(self.version, '>=15.0.0'): return ['-qopenmp'] else: @@ -154,7 +157,7 @@ def get_toolset_version(self) -> T.Optional[str]: version = int(v1 + v2) return self._calculate_toolset_version(version) - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['/Qopenmp'] def get_debug_args(self, is_debug: bool) -> T.List[str]: diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 0d8245a21540..71ad81f38a01 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -51,7 +51,7 @@ def get_pic_args(self) -> T.List[str]: return ['-fPIC'] return [] - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['-mp'] def get_optimization_args(self, optimization_level: str) -> T.List[str]: diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 4e2ce099fef4..abcedc7cbdae 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -204,10 +204,10 @@ def gen_pch_args(self, header: str, source: str, pchname: str) -> T.Tuple[str, T objname = os.path.splitext(source)[0] + '.obj' return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname] - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return ['/openmp'] - def openmp_link_flags(self) -> T.List[str]: + def openmp_link_flags(self, env: Environment) -> T.List[str]: return [] # FIXME, no idea what these should be. diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 72c7cf0a8825..e4da6976e7b6 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -95,18 +95,18 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No # No macro defined for OpenMP, but OpenMP 3.1 is supported. self.version = '3.1' self.is_found = True - self.compile_args = self.link_args = self.clib_compiler.openmp_flags() + self.compile_args = self.link_args = self.clib_compiler.openmp_flags(environment) return if self.clib_compiler.get_id() == 'pgi': # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported. self.version = '3.1' self.is_found = True - self.compile_args = self.link_args = self.clib_compiler.openmp_flags() + self.compile_args = self.link_args = self.clib_compiler.openmp_flags(environment) return try: openmp_date = self.clib_compiler.get_define( - '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0] + '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(environment), [self], disable_cache=True)[0] except mesonlib.EnvironmentException as e: mlog.debug('OpenMP support not available in the compiler') mlog.debug(e) @@ -134,8 +134,8 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No for name in header_names: if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: self.is_found = True - self.compile_args.extend(self.clib_compiler.openmp_flags()) - self.link_args.extend(self.clib_compiler.openmp_link_flags()) + self.compile_args.extend(self.clib_compiler.openmp_flags(environment)) + self.link_args.extend(self.clib_compiler.openmp_link_flags(environment)) break if not self.is_found: mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.') diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 7507f5ab7b6c..f5e808082f98 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -62,7 +62,7 @@ def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def thread_link_flags(self, env: 'Environment') -> T.List[str]: return [] - def openmp_flags(self) -> T.List[str]: + def openmp_flags(self, env: Environment) -> T.List[str]: return [] def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: From d86e5c52f47829aec4845910a26b59566c32ad61 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 15:33:53 -0700 Subject: [PATCH 04/72] dependencies/openmp: Set compile and link flags before testing In case the OpenMP definition adds things like preprocessor directives or include paths, like when building on MacOS with OpenMP from Homebrew. --- mesonbuild/dependencies/misc.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index e4da6976e7b6..68c37923307f 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -104,9 +104,13 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No self.compile_args = self.link_args = self.clib_compiler.openmp_flags(environment) return + # Set these now so they're available for the following compiler checks + self.compile_args.extend(self.clib_compiler.openmp_flags(environment)) + self.link_args.extend(self.clib_compiler.openmp_link_flags(environment)) + try: openmp_date = self.clib_compiler.get_define( - '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(environment), [self], disable_cache=True)[0] + '_OPENMP', '', self.env, [], [self], disable_cache=True)[0] except mesonlib.EnvironmentException as e: mlog.debug('OpenMP support not available in the compiler') mlog.debug(e) @@ -134,8 +138,6 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No for name in header_names: if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: self.is_found = True - self.compile_args.extend(self.clib_compiler.openmp_flags(environment)) - self.link_args.extend(self.clib_compiler.openmp_link_flags(environment)) break if not self.is_found: mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.') From 3cd2cee7756b462a4d5fb72373ebc7e4ced71e4f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 15:35:28 -0700 Subject: [PATCH 05/72] dependencies/openmp: use mlog.warning instead of open coding It was probably done this way originally since we didn't have the `fatal` keyword argument to avoid triggering the fatal-meson-warnings. While we're here, replace the use of a `if bool` with an `else` on the for loop. --- mesonbuild/dependencies/misc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 68c37923307f..f9a2e047aeae 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -139,8 +139,8 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: self.is_found = True break - if not self.is_found: - mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.') + else: + mlog.warning('OpenMP found but omp.h missing.', fatal=False) packages['openmp'] = OpenMPDependency From f900b3270be6572a2f2aeb6c080eae37187a7459 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 15:43:21 -0700 Subject: [PATCH 06/72] compilers|dependencies: Move Clang-CL specific logic out of OpenMP dep And into the Clang-CL mixin. --- mesonbuild/compilers/mixins/visualstudio.py | 7 +++++++ mesonbuild/dependencies/misc.py | 16 ++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index abcedc7cbdae..907ea07f0c7b 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -483,3 +483,10 @@ def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: return converted else: return dep.get_compile_args() + + def openmp_link_flags(self, env: Environment) -> T.List[str]: + # see https://github.com/mesonbuild/meson/issues/5298 + libs = self.find_library('libomp', env, []) + if libs is None: + raise mesonlib.MesonBugException('Could not find libomp') + return super().openmp_link_flags(env) + libs diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index f9a2e047aeae..ffccd708983d 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -105,8 +105,12 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No return # Set these now so they're available for the following compiler checks - self.compile_args.extend(self.clib_compiler.openmp_flags(environment)) - self.link_args.extend(self.clib_compiler.openmp_link_flags(environment)) + try: + self.compile_args.extend(self.clib_compiler.openmp_flags(environment)) + self.link_args.extend(self.clib_compiler.openmp_link_flags(environment)) + except mesonlib.MesonException as e: + mlog.warning('OpenMP support not available because:', str(e), fatal=False) + return try: openmp_date = self.clib_compiler.get_define( @@ -125,14 +129,6 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.') return - if self.clib_compiler.get_id() == 'clang-cl': - # this is necessary for clang-cl, see https://github.com/mesonbuild/meson/issues/5298 - clangcl_openmp_link_args = self.clib_compiler.find_library("libomp", self.env, []) - if not clangcl_openmp_link_args: - mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but libomp for clang-cl missing.') - return - self.link_args.extend(clangcl_openmp_link_args) - # Flang has omp_lib.h header_names = ('omp.h', 'omp_lib.h') for name in header_names: From 07ef85ee22bc87f8bafb805d2dce5688e7726db6 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 12:36:57 -0700 Subject: [PATCH 07/72] CI/MacOS: Add libomp --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 449504096a77..3b726315537a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -96,7 +96,7 @@ jobs: find /opt/homebrew/Cellar/python* -name EXTERNALLY-MANAGED -print0 | xargs -0 rm -vf # use python3 from homebrew because it is a valid framework, unlike the actions one: # https://github.com/actions/setup-python/issues/58 - - run: brew install pkg-config ninja llvm qt@5 boost ldc hdf5 openmpi lapack scalapack sdl2 boost-python3 gtk-doc zstd ncurses objfw + - run: brew install pkg-config ninja llvm qt@5 boost ldc hdf5 openmpi lapack scalapack sdl2 boost-python3 gtk-doc zstd ncurses objfw libomp - run: | python3 -m pip install --upgrade setuptools python3 -m pip install --upgrade pip From d6bddafa265ce8f6a1d1194c284acc39f4188e46 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 12 Apr 2024 10:53:52 -0700 Subject: [PATCH 08/72] compilers: Add support for OpenMP from homebrew with AppleClang Which requires injecting some extra paths and the `-Xpreprocess` flag, as well as extra search paths for libomp and the headers. Fixes: #7435 --- mesonbuild/_typing.py | 2 +- mesonbuild/compilers/c.py | 3 +- mesonbuild/compilers/cpp.py | 3 +- mesonbuild/compilers/mixins/apple.py | 57 ++++++++++++++++++++++++ test cases/common/184 openmp/meson.build | 3 -- 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 mesonbuild/compilers/mixins/apple.py diff --git a/mesonbuild/_typing.py b/mesonbuild/_typing.py index 05ff2b3da948..8336c46bd06d 100644 --- a/mesonbuild/_typing.py +++ b/mesonbuild/_typing.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Copyright © 2020-2023 Intel Corporation +# Copyright © 2020-2024 Intel Corporation """Meson specific typing helpers. diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 8fda3a5a508b..cbc1bea95d6e 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -10,6 +10,7 @@ from .. import mlog from ..mesonlib import MesonException, version_compare from .c_function_attributes import C_FUNC_ATTRIBUTES +from .mixins.apple import AppleCompilerMixin from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler from .mixins.xc16 import Xc16Compiler @@ -187,7 +188,7 @@ class ArmLtdClangCCompiler(ClangCCompiler): id = 'armltdclang' -class AppleClangCCompiler(ClangCCompiler): +class AppleClangCCompiler(AppleCompilerMixin, ClangCCompiler): """Handle the differences between Apple Clang and Vanilla Clang. diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 9467a35c58c1..5e8947bcec58 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -19,6 +19,7 @@ CompileCheckMode, ) from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES +from .mixins.apple import AppleCompilerMixin from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler from .mixins.ti import TICompiler @@ -337,7 +338,7 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler): id = 'armltdclang' -class AppleClangCPPCompiler(ClangCPPCompiler): +class AppleClangCPPCompiler(AppleCompilerMixin, ClangCPPCompiler): _CPP23_VERSION = '>=13.0.0' # TODO: We don't know which XCode version will include LLVM 17 yet, so diff --git a/mesonbuild/compilers/mixins/apple.py b/mesonbuild/compilers/mixins/apple.py new file mode 100644 index 000000000000..98c4bfa1a18b --- /dev/null +++ b/mesonbuild/compilers/mixins/apple.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2024 Intel Corporation + +"""Provides mixins for Apple compilers.""" + +from __future__ import annotations +import typing as T + +from ...mesonlib import MesonException + +if T.TYPE_CHECKING: + from ..._typing import ImmutableListProtocol + from ...environment import Environment + from ..compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + + +class AppleCompilerMixin(Compiler): + + """Handle differences between Vanilla Clang and the Clang shipped with XCode.""" + + __BASE_OMP_FLAGS: ImmutableListProtocol[str] = ['-Xpreprocessor', '-fopenmp'] + + def openmp_flags(self, env: Environment) -> T.List[str]: + """Flags required to compile with OpenMP on Apple. + + The Apple Clang Compiler doesn't have builtin support for OpenMP, it + must be provided separately. As such, we need to add the -Xpreprocessor + argument so that an external OpenMP can be found. + + :return: A list of arguments + """ + m = env.machines[self.for_machine] + assert m is not None, 'for mypy' + if m.cpu_family.startswith('x86'): + root = '/usr/local' + else: + root = '/opt/homebrew' + return self.__BASE_OMP_FLAGS + [f'-I{root}/opt/libomp/include'] + + def openmp_link_flags(self, env: Environment) -> T.List[str]: + m = env.machines[self.for_machine] + assert m is not None, 'for mypy' + if m.cpu_family.startswith('x86'): + root = '/usr/local' + else: + root = '/opt/homebrew' + + link = self.find_library('omp', env, [f'{root}/opt/libomp/lib']) + if not link: + raise MesonException("Couldn't find libomp") + return self.__BASE_OMP_FLAGS + link diff --git a/test cases/common/184 openmp/meson.build b/test cases/common/184 openmp/meson.build index 4cbe80616970..ab09b2c480d1 100644 --- a/test cases/common/184 openmp/meson.build +++ b/test cases/common/184 openmp/meson.build @@ -16,9 +16,6 @@ endif if cc.get_id() == 'clang' and host_machine.system() == 'windows' error('MESON_SKIP_TEST Windows clang does not support OpenMP.') endif -if host_machine.system() == 'darwin' - error('MESON_SKIP_TEST macOS does not support OpenMP.') -endif openmp = dependency('openmp') env = environment() From ef83d943d96c5d73c09bd6e2abbfdbb15ae73029 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 16:03:48 -0700 Subject: [PATCH 09/72] dependencies/openmp: Simplify error case Instead of making the variable optional, just return if we hit the error case, since that's all that's going to happen anyway --- mesonbuild/dependencies/misc.py | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index ffccd708983d..4011c60fb189 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -118,25 +118,24 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No except mesonlib.EnvironmentException as e: mlog.debug('OpenMP support not available in the compiler') mlog.debug(e) - openmp_date = None - - if openmp_date: - try: - self.version = self.VERSIONS[openmp_date] - except KeyError: - mlog.debug(f'Could not find an OpenMP version matching {openmp_date}') - if openmp_date == '_OPENMP': - mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.') - return + return - # Flang has omp_lib.h - header_names = ('omp.h', 'omp_lib.h') - for name in header_names: - if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: - self.is_found = True - break - else: - mlog.warning('OpenMP found but omp.h missing.', fatal=False) + try: + self.version = self.VERSIONS[openmp_date] + except KeyError: + mlog.debug(f'Could not find an OpenMP version matching {openmp_date}') + if openmp_date == '_OPENMP': + mlog.debug('This can be caused by flags such as gcc\'s `-fdirectives-only`, which affect preprocessor behavior.') + return + + # Flang has omp_lib.h + header_names = ('omp.h', 'omp_lib.h') + for name in header_names: + if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: + self.is_found = True + break + else: + mlog.warning('OpenMP found but omp.h missing.', fatal=False) packages['openmp'] = OpenMPDependency From 7b43a2e19613f3702935872b21b1020f7d8c6a9b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 26 Jun 2024 20:38:56 -0400 Subject: [PATCH 10/72] depfixer: fix darwin regression when install rpaths are used Fixes regression in commit 78e9009ff9d36925e04f329f9082841002ddd848. new_rpath is only set when install_rpath appears in meson.build. Before this commit, we treated new_rpath as a single string to pass to -add_rpath. This worked as long as new_rpath had a single rpath in it, though for ELF we explicitly supported multiple rpaths separated with ":" (as binutils ld is quite happy with that too). install_name_tool does not support paths with colons in it: ``` 21:12 Load command 19 cmd LC_RPATH cmdsize 40 path /bar:/baz:/eli:/ldap (offset 12) 21:12 Load command 20 cmd LC_RPATH cmdsize 24 path /foo (offset 12) 21:14 so the result is: do not use colons ``` After commit 78e9009ff9d36925e04f329f9082841002ddd848, we simply ended up with one load command for LC_RPATH per char in new_rpath, which was wrong in every possible case. What we actually need to do is pass every distinct rpath as a separate `-add_rpath` argument, so we split it on the colons instead. We do the same splitting to ensure proper diff'ability for ELF anyways... Fixes #13355 --- mesonbuild/scripts/depfixer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 71599f784e73..f0166bdc3481 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -406,7 +406,7 @@ def fix_darwin(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: str, f return new_rpaths: OrderedSet[str] = OrderedSet() if new_rpath: - new_rpaths.update(new_rpath) + new_rpaths.update(new_rpath.split(':')) # filter out build-only rpath entries, like in # fix_rpathtype_entry remove_rpaths = [x.decode('utf8') for x in rpath_dirs_to_remove] From dc1b4be6be321e39d21604ab4287c9ce972be4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Brzezi=C5=84ski?= Date: Fri, 28 Jun 2024 14:06:25 +0200 Subject: [PATCH 11/72] linkers: Fix AppleDynamicLinker not returning any rpaths to remove Fixes regression from commit 78e9009ff9d36925e04f329f9082841002ddd848. The above commit relied on rpath_dirs_to_remove being present and correctly filled, which was never the case for the AppleDynamicLinker. The result was that all the build-dir-only RPATHs were being carried over to the installed files. This commit implements returning the list of RPATHs to remove in AppleDynamicLinker, doing pretty much the same thing as what's in the GnuLikeDynamicLinkerMixin. Thanks to that, depfixer now correctly removes build-time Meson-created RPATHs, as it used to before 1.4.1. --- mesonbuild/linkers/linkers.py | 6 ++++-- .../darwin/1 rpath removal on install/bar.c | 5 +++++ .../1 rpath removal on install/foo/foo.c | 3 +++ .../1 rpath removal on install/foo/foo.h | 1 + .../1 rpath removal on install/foo/meson.build | 3 +++ .../1 rpath removal on install/meson.build | 8 ++++++++ unittests/baseplatformtests.py | 1 + unittests/darwintests.py | 18 ++++++++++++++++++ 8 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test cases/darwin/1 rpath removal on install/bar.c create mode 100644 test cases/darwin/1 rpath removal on install/foo/foo.c create mode 100644 test cases/darwin/1 rpath removal on install/foo/foo.h create mode 100644 test cases/darwin/1 rpath removal on install/foo/meson.build create mode 100644 test cases/darwin/1 rpath removal on install/meson.build diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index f5e808082f98..c3750ccc372f 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -819,17 +819,19 @@ def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, if not rpath_paths and not install_rpath and not build_rpath: return ([], set()) args: T.List[str] = [] + rpath_dirs_to_remove: T.Set[bytes] = set() # @loader_path is the equivalent of $ORIGIN on macOS # https://stackoverflow.com/q/26280738 origin_placeholder = '@loader_path' processed_rpaths = prepare_rpaths(rpath_paths, build_dir, from_dir) all_paths = mesonlib.OrderedSet([os.path.join(origin_placeholder, p) for p in processed_rpaths]) if build_rpath != '': - all_paths.add(build_rpath) + all_paths.update(build_rpath.split(':')) for rp in all_paths: + rpath_dirs_to_remove.add(rp.encode('utf8')) args.extend(self._apply_prefix('-rpath,' + rp)) - return (args, set()) + return (args, rpath_dirs_to_remove) def get_thinlto_cache_args(self, path: str) -> T.List[str]: return ["-Wl,-cache_path_lto," + path] diff --git a/test cases/darwin/1 rpath removal on install/bar.c b/test cases/darwin/1 rpath removal on install/bar.c new file mode 100644 index 000000000000..b2fd0a664457 --- /dev/null +++ b/test cases/darwin/1 rpath removal on install/bar.c @@ -0,0 +1,5 @@ +#include "foo/foo.h" + +void bar() { + foo(); +} \ No newline at end of file diff --git a/test cases/darwin/1 rpath removal on install/foo/foo.c b/test cases/darwin/1 rpath removal on install/foo/foo.c new file mode 100644 index 000000000000..e355ed4592d2 --- /dev/null +++ b/test cases/darwin/1 rpath removal on install/foo/foo.c @@ -0,0 +1,3 @@ +int foo() { + return 1 + 2; +} \ No newline at end of file diff --git a/test cases/darwin/1 rpath removal on install/foo/foo.h b/test cases/darwin/1 rpath removal on install/foo/foo.h new file mode 100644 index 000000000000..176e7a3be8bd --- /dev/null +++ b/test cases/darwin/1 rpath removal on install/foo/foo.h @@ -0,0 +1 @@ +int foo(); \ No newline at end of file diff --git a/test cases/darwin/1 rpath removal on install/foo/meson.build b/test cases/darwin/1 rpath removal on install/foo/meson.build new file mode 100644 index 000000000000..cc6fbe4e3d78 --- /dev/null +++ b/test cases/darwin/1 rpath removal on install/foo/meson.build @@ -0,0 +1,3 @@ +foo = library('foo', 'foo.c', + install: true, +) \ No newline at end of file diff --git a/test cases/darwin/1 rpath removal on install/meson.build b/test cases/darwin/1 rpath removal on install/meson.build new file mode 100644 index 000000000000..093d7deba3a8 --- /dev/null +++ b/test cases/darwin/1 rpath removal on install/meson.build @@ -0,0 +1,8 @@ +project('proj', 'c') + +subdir('foo') + +bar = library('bar', 'bar.c', + link_with: foo, + install: true, +) \ No newline at end of file diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index e94a2baac210..6e6a01d40fd3 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -78,6 +78,7 @@ def setUp(self): self.linuxlike_test_dir = os.path.join(src_root, 'test cases/linuxlike') self.objc_test_dir = os.path.join(src_root, 'test cases/objc') self.objcpp_test_dir = os.path.join(src_root, 'test cases/objcpp') + self.darwin_test_dir = os.path.join(src_root, 'test cases/darwin') # Misc stuff self.orig_env = os.environ.copy() diff --git a/unittests/darwintests.py b/unittests/darwintests.py index 7403104771b7..afc663a57ae1 100644 --- a/unittests/darwintests.py +++ b/unittests/darwintests.py @@ -100,6 +100,12 @@ def _get_darwin_versions(self, fname): self.assertIsNotNone(m, msg=out) return m.groups() + def _get_darwin_rpaths(self, fname: str) -> T.List[str]: + out = subprocess.check_output(['otool', '-l', fname], universal_newlines=True) + pattern = re.compile(r'path (.*) \(offset \d+\)') + rpaths = pattern.findall(out) + return rpaths + @skipIfNoPkgconfig def test_library_versioning(self): ''' @@ -154,3 +160,15 @@ def test_darwin_get_object_archs(self): from mesonbuild.mesonlib import darwin_get_object_archs archs = darwin_get_object_archs('/bin/cat') self.assertEqual(archs, ['x86_64', 'aarch64']) + + def test_darwin_meson_rpaths_removed_on_install(self): + testdir = os.path.join(self.darwin_test_dir, '1 rpath removal on install') + self.init(testdir) + self.build() + # Meson-created RPATHs are usually only valid in the build directory + rpaths = self._get_darwin_rpaths(os.path.join(self.builddir, 'libbar.dylib')) + self.assertListEqual(rpaths, ['@loader_path/foo']) + self.install() + # Those RPATHs are no longer valid and should not be present after installation + rpaths = self._get_darwin_rpaths(os.path.join(self.installdir, 'usr/lib/libbar.dylib')) + self.assertListEqual(rpaths, []) From ff5865c45c99bea40691e664ea13df99a1e2c1ac Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 1 Jul 2024 18:35:29 +0300 Subject: [PATCH 12/72] Bump version number for rc2. --- man/meson.1 | 2 +- mesonbuild/coredata.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/man/meson.1 b/man/meson.1 index 182ac17fce19..b6ceb2a27fbe 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "June 2024" "meson 1.5.0" "User Commands" +.TH MESON "1" "July 2024" "meson 1.5.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 7fb3bca023d8..6e7a2f501cc3 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -72,7 +72,7 @@ class SharedCMDOptions(Protocol): # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.5.0.rc1' +version = '1.5.0.rc2' # The next stable version when we are in dev. This is used to allow projects to # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when From c1e87af9f8aaa032b0ea78b4ba27513d5d37a369 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 2 Jul 2024 19:46:52 -0400 Subject: [PATCH 13/72] CI: mark cygwin as skipping frameworks/libgcrypt They have recently upgraded to libgcrypt 1.11 and it has inherited the gpg suite migration to pkg-config. --- test cases/frameworks/24 libgcrypt/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/24 libgcrypt/test.json b/test cases/frameworks/24 libgcrypt/test.json index de9b738f6c45..23af7d93189d 100644 --- a/test cases/frameworks/24 libgcrypt/test.json +++ b/test cases/frameworks/24 libgcrypt/test.json @@ -1,3 +1,3 @@ { - "expect_skip_on_jobname": ["azure", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "msys2"] } From 8b757b1f2d6f81d907f9d2bc60182185266a4aaa Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Tue, 2 Jul 2024 22:57:25 +0200 Subject: [PATCH 14/72] Python: fix limited API logic under GCC on Windows When building a limited API module on Windows the library to link with should be python3.dll, not python3X.dll. This was already the case for non-GCC, but should have been the case unconditionally. --- mesonbuild/dependencies/python.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index db4944bab777..883a29ad97f2 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -218,6 +218,8 @@ def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: if self.static: libpath = Path('libs') / f'libpython{vernum}.a' else: + if limited_api: + vernum = vernum[0] comp = self.get_compiler() if comp.id == "gcc": if imp_lower == 'pypy' and verdot == '3.8': @@ -228,8 +230,6 @@ def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: else: libpath = Path(f'python{vernum}.dll') else: - if limited_api: - vernum = vernum[0] if self.is_freethreaded: libpath = Path('libs') / f'python{vernum}t.lib' else: From 1ca002a78a48faaf74aa61fcd28b4f2fa5937b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Thu, 4 Jul 2024 12:04:31 +0300 Subject: [PATCH 15/72] linkers: Loosen the check for GNU interface style in LLD for Windows Don't require the string to be enclosed in parentheses. https://github.com/llvm/llvm-project/pull/97323 changed the LLD version printout to no longer be enclosed in parentheses, which made Meson fail to detect the linker style used here. The LLD change is being reverted in https://github.com/llvm/llvm-project/pull/97698 in order to fix building with existing Meson versions, but for the future, loosen the check slightly, to not require the parentheses. --- mesonbuild/linkers/detect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 1db3948c1c59..cd3c7b2efd0f 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -64,7 +64,7 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty p, o, _ = Popen_safe(compiler + check_args) if 'LLD' in o.split('\n', maxsplit=1)[0]: - if '(compatible with GNU linkers)' in o: + if 'compatible with GNU linkers' in o: return linkers.LLVMDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=search_version(o)) From f2112d0baa379e01d7ce8a961005f5b7c102d9a9 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 5 Jul 2024 13:52:40 -0400 Subject: [PATCH 16/72] Revert "Clarify mutable objects usage" This reverts commit 9f02d0a3e5a5ffc82256391c244b1af38e41ef78. It turns out that this does introduce a behavioral change in existing users of ConfigurationData, which it wasn't supposed to (it was supposed to preserve behavior there, and add a new *warning* for EnvironmentVariables). This breaks projects such as pulseaudio, libvirt, and probably more. Roll back the change and try again after 1.5.0 is released. Fixes: #13372 --- docs/markdown/Configuration.md | 2 +- docs/yaml/objects/cfg_data.yaml | 12 +++---- docs/yaml/objects/env.yaml | 13 ------- mesonbuild/interpreter/interpreterobjects.py | 26 ++++++-------- mesonbuild/interpreterbase/_unholder.py | 4 +-- mesonbuild/interpreterbase/baseobjects.py | 21 ------------ .../check_env.py | 7 ---- .../meson.build | 34 +------------------ .../failing/70 configuration immutable/input | 0 .../70 configuration immutable/meson.build | 12 +++++++ .../70 configuration immutable/test.json | 7 ++++ 11 files changed, 36 insertions(+), 102 deletions(-) delete mode 100755 test cases/common/113 interpreter copy mutable var on assignment/check_env.py create mode 100644 test cases/failing/70 configuration immutable/input create mode 100644 test cases/failing/70 configuration immutable/meson.build create mode 100644 test cases/failing/70 configuration immutable/test.json diff --git a/docs/markdown/Configuration.md b/docs/markdown/Configuration.md index b5875e55e6d9..48f071e6c9e4 100644 --- a/docs/markdown/Configuration.md +++ b/docs/markdown/Configuration.md @@ -39,7 +39,7 @@ use a single `configuration_data` object as many times as you like, but it becomes immutable after being passed to the `configure_file` function. That is, after it has been used once to generate output the `set` function becomes unusable and trying to call it causes an error. -*Since 1.5.0* Copy of immutable `configuration_data` is however mutable. +Copy of immutable `configuration_data` is still immutable. For more complex configuration file generation Meson provides a second form. To use it, put a line like this in your configuration file. diff --git a/docs/yaml/objects/cfg_data.yaml b/docs/yaml/objects/cfg_data.yaml index 069cadbf6eb1..03abb170970e 100644 --- a/docs/yaml/objects/cfg_data.yaml +++ b/docs/yaml/objects/cfg_data.yaml @@ -1,14 +1,10 @@ name: cfg_data long_name: Configuration data object description: | - This object encapsulates configuration values to be used for generating - configuration files. A more in-depth description can be found in the - [the configuration page](Configuration.md). - - This object becomes immutable after first use. This means that - calling set() or merge_from() will cause an error if this object has - already been used in any function arguments. However, assignment creates a - mutable copy. + This object encapsulates + configuration values to be used for generating configuration files. A + more in-depth description can be found in the [the configuration wiki + page](Configuration.md). methods: - name: set diff --git a/docs/yaml/objects/env.yaml b/docs/yaml/objects/env.yaml index 3b2e2a851b24..714da4fe422a 100644 --- a/docs/yaml/objects/env.yaml +++ b/docs/yaml/objects/env.yaml @@ -9,11 +9,6 @@ description: | on the same `varname`. Earlier Meson versions would warn and only the last operation took effect. - *Since 1.5.0* This object becomes immutable after first use. This means that - calling append(), prepend() or set() will cause a deprecation warning if this - object has already been used in any function arguments. However, assignment - creates a mutable copy. - example: | ```meson env = environment() @@ -23,14 +18,6 @@ example: | env.append('MY_PATH', '2') env.append('MY_PATH', '3') env.prepend('MY_PATH', '0') - - # Deprecated since 1.5.0 - run_command('script.py', env: env) - env.append('MY_PATH', '4') - - # Allowed and only env2 is modified - env2 = env - env2.append('MY_PATH', '4') ``` methods: diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 32f05bafb852..d5c1efaa8372 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -284,7 +284,6 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu def __init__(self, obj: mesonlib.EnvironmentVariables, interpreter: 'Interpreter'): super().__init__(obj, interpreter) - MutableInterpreterObject.__init__(self) self.methods.update({'set': self.set_method, 'unset': self.unset_method, 'append': self.append_method, @@ -309,14 +308,12 @@ def warn_if_has_name(self, name: str) -> None: @typed_kwargs('environment.set', ENV_SEPARATOR_KW) def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: name, values = args - self.check_used(self.interpreter, fatal=False) self.held_object.set(name, values, kwargs['separator']) @FeatureNew('environment.unset', '1.4.0') @typed_pos_args('environment.unset', str) @noKwargs def unset_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> None: - self.check_used(self.interpreter, fatal=False) self.held_object.unset(args[0]) @typed_pos_args('environment.append', str, varargs=str, min_varargs=1) @@ -324,7 +321,6 @@ def unset_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> None: def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: name, values = args self.warn_if_has_name(name) - self.check_used(self.interpreter, fatal=False) self.held_object.append(name, values, kwargs['separator']) @typed_pos_args('environment.prepend', str, varargs=str, min_varargs=1) @@ -332,7 +328,6 @@ def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSep def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: name, values = args self.warn_if_has_name(name) - self.check_used(self.interpreter, fatal=False) self.held_object.prepend(name, values, kwargs['separator']) @@ -343,7 +338,6 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'): super().__init__(obj, interpreter) - MutableInterpreterObject.__init__(self) self.methods.update({'set': self.set_method, 'set10': self.set10_method, 'set_quoted': self.set_quoted_method, @@ -355,31 +349,32 @@ def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'): }) def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder': - obj = ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter) + return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter) + + def is_used(self) -> bool: + return self.held_object.used + + def __check_used(self) -> None: if self.is_used(): - # Copies of used ConfigurationData used to be immutable. It is now - # allowed but we need this flag to print a FeatureNew warning if - # that happens. - obj.mutable_feature_new = True - return obj + raise InterpreterException("Can not set values on configuration object that has been used.") @typed_pos_args('configuration_data.set', str, (str, int, bool)) @typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS) def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: - self.check_used(self.interpreter) + self.__check_used() self.held_object.values[args[0]] = (args[1], kwargs['description']) @typed_pos_args('configuration_data.set_quoted', str, str) @typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS) def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None: - self.check_used(self.interpreter) + self.__check_used() escaped_val = '\\"'.join(args[1].split('"')) self.held_object.values[args[0]] = (f'"{escaped_val}"', kwargs['description']) @typed_pos_args('configuration_data.set10', str, (int, bool)) @typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS) def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: - self.check_used(self.interpreter) + self.__check_used() # bool is a subclass of int, so we need to check for bool explicitly. # We already have typed_pos_args checking that this is either a bool or # an int. @@ -442,7 +437,6 @@ def keys(self) -> T.List[str]: @noKwargs def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None: from_object = args[0] - self.check_used(self.interpreter) self.held_object.values.update(from_object.values) diff --git a/mesonbuild/interpreterbase/_unholder.py b/mesonbuild/interpreterbase/_unholder.py index e32b77fc7d4b..c62aafe8e97b 100644 --- a/mesonbuild/interpreterbase/_unholder.py +++ b/mesonbuild/interpreterbase/_unholder.py @@ -5,7 +5,7 @@ import typing as T -from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, HoldableTypes, MutableInterpreterObject +from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, HoldableTypes from .exceptions import InvalidArguments from ..mesonlib import HoldableObject, MesonBugException @@ -13,8 +13,6 @@ from .baseobjects import TYPE_var def _unholder(obj: InterpreterObject) -> TYPE_var: - if isinstance(obj, MutableInterpreterObject): - obj.mark_used() if isinstance(obj, ObjectHolder): assert isinstance(obj.held_object, HoldableTypes) return obj.held_object diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py index c6864a4788c5..9a119a98a75d 100644 --- a/mesonbuild/interpreterbase/baseobjects.py +++ b/mesonbuild/interpreterbase/baseobjects.py @@ -120,27 +120,6 @@ class MesonInterpreterObject(InterpreterObject): class MutableInterpreterObject: ''' Dummy class to mark the object type as mutable ''' - def __init__(self) -> None: - self.used = False - self.mutable_feature_new = False - - def mark_used(self) -> None: - self.used = True - - def is_used(self) -> bool: - return self.used - - def check_used(self, interpreter: Interpreter, fatal: bool = True) -> None: - from .decorators import FeatureDeprecated, FeatureNew - if self.is_used(): - if fatal: - raise InvalidArguments('Can not modify object after it has been used.') - FeatureDeprecated.single_use('Modify object after it has been used', '1.5.0', - interpreter.subproject, location=interpreter.current_node) - elif self.mutable_feature_new: - FeatureNew.single_use('Modify a copy of an immutable object', '1.5.0', - interpreter.subproject, location=interpreter.current_node) - self.mutable_feature_new = False HoldableTypes = (HoldableObject, int, bool, str, list, dict) TYPE_HoldableTypes = T.Union[TYPE_elementary, HoldableObject] diff --git a/test cases/common/113 interpreter copy mutable var on assignment/check_env.py b/test cases/common/113 interpreter copy mutable var on assignment/check_env.py deleted file mode 100755 index 034d2924331b..000000000000 --- a/test cases/common/113 interpreter copy mutable var on assignment/check_env.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys - -if sys.argv[1] not in os.environ: - exit(42) diff --git a/test cases/common/113 interpreter copy mutable var on assignment/meson.build b/test cases/common/113 interpreter copy mutable var on assignment/meson.build index 3d4f3b039c76..d414bfc74e0c 100644 --- a/test cases/common/113 interpreter copy mutable var on assignment/meson.build +++ b/test cases/common/113 interpreter copy mutable var on assignment/meson.build @@ -1,4 +1,4 @@ -project('foo', meson_version: '>=1.5') +project('foo') a = configuration_data() a.set('HELLO', 1) @@ -10,15 +10,6 @@ assert(b.has('HELLO'), 'Original config data should be set on copy') configure_file(output : 'b.h', configuration : b) -testcase expect_error('Can not modify object after it has been used.') - b.set('WORLD', 1) -endtestcase - -# A copy of immutable object is mutable. This should print FeatureNew warning -# if meson_version is lower than 1.5. -c = b -c.set('WORLD', 1) - # This should still work, as we didn't use the original above but a copy! a.set('WORLD', 1) @@ -26,26 +17,3 @@ assert(a.has('WORLD'), 'New config data should have been set') assert(not b.has('WORLD'), 'New config data set should not affect var copied earlier') configure_file(output : 'a.h', configuration : a) - -env1 = environment() -env1.set('FOO', '1') -env2 = env1 -env1.set('BAR', '1') - -# FOO should be in env1 and env2 -run_command('check_env.py', 'FOO', env: env1, check: true) -run_command('check_env.py', 'FOO', env: env2, check: true) - -# BAR should be only in env1 -run_command('check_env.py', 'BAR', env: env1, check: true) -assert(run_command('check_env.py', 'BAR', env: env2, check: false).returncode() == 42) - -# This should print deprecation warning but still work -env1.set('PLOP', '1') -run_command('check_env.py', 'PLOP', env: env1, check: true) - -# A copy of used env should be mutable and not print warning -env3 = env1 -env3.set('BAZ', '1') -run_command('check_env.py', 'PLOP', env: env3, check: true) -run_command('check_env.py', 'BAZ', env: env3, check: true) diff --git a/test cases/failing/70 configuration immutable/input b/test cases/failing/70 configuration immutable/input new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/failing/70 configuration immutable/meson.build b/test cases/failing/70 configuration immutable/meson.build new file mode 100644 index 000000000000..b6cac41265e0 --- /dev/null +++ b/test cases/failing/70 configuration immutable/meson.build @@ -0,0 +1,12 @@ +project('configuration_data is immutable') + +a = configuration_data() + +configure_file( + configuration : a, + input : 'input', + output : 'output', +) + +still_immutable = a +still_immutable.set('hello', 'world') diff --git a/test cases/failing/70 configuration immutable/test.json b/test cases/failing/70 configuration immutable/test.json new file mode 100644 index 000000000000..fc735fa38ece --- /dev/null +++ b/test cases/failing/70 configuration immutable/test.json @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/70 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." + } + ] +} From 140c557c87eeacd3173a1d22f6bc5f6d6c7933b1 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 5 Jul 2024 14:28:21 -0400 Subject: [PATCH 17/72] configuration_data: add test case for regression when merging a confdata Regression test for #13372 --- test cases/common/14 configure file/meson.build | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test cases/common/14 configure file/meson.build b/test cases/common/14 configure file/meson.build index 8e7d429c722c..036a562b796c 100644 --- a/test cases/common/14 configure file/meson.build +++ b/test cases/common/14 configure file/meson.build @@ -310,10 +310,16 @@ cdata = configuration_data({ 'A_UNDEFINED' : false, }) +# merging a confdata into another one should not mark the first as immutable +cdata_test = configuration_data() +cdata_test.merge_from(cdata) +cdata.set_quoted('A_PATH', '/random/path') + configure_file(output : 'config9a.h', configuration : cdata, ) + configure_file(output : 'config9b.h', configuration : { 'B_STRING' : '"foo"', From 0392722bfdeeb1fed977d4f70adc3c1d6c18b82b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 5 Jul 2024 16:57:11 -0400 Subject: [PATCH 18/72] Revert PR12972 as a regression. Revert "interpreter: when overriding a dependency make its name match" This reverts commit b1340e9bb1f243e4de8f2d89415a45ade476a3dc. Revert "dependency: define equality and hash operators for Dependency" This reverts commit 6d713e40f81512eadb0cc4654408d90cb22ba774. This caused some projects to fail to build, such as libplacebo and libepoxy. Taking libplacebo as the example, the produced build.ninja does not include libvulkan.so as a linker input for src/libplacebo.so.338. We are probably getting dependency hashing wrong somewhere. Unsure where exactly and unsure how to create a test case. We are also deep into rc2. Revert it for now and try to re-land these changes for 1.6. Bug: https://bugs.gentoo.org/935443 Fixes: #13352 --- mesonbuild/dependencies/base.py | 12 ------------ mesonbuild/interpreter/mesonmain.py | 13 +------------ .../common/98 subproject subdir/meson.build | 18 +----------------- 3 files changed, 2 insertions(+), 41 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 930dbe7f369d..9b218c6432b8 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2018 The Meson development team -# Copyright © 2024 Intel Corporation # This file contains the detection logic for external dependencies. # Custom logic for several other packages are in separate files. @@ -107,9 +106,6 @@ def _process_include_type_kw(cls, kwargs: T.Dict[str, T.Any]) -> str: return kwargs['include_type'] def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> None: - # This allows two Dependencies to be compared even after being copied. - # The purpose is to allow the name to be changed, but still have a proper comparison - self.__id = id(self) self.name = f'dep{id(self)}' self.version: T.Optional[str] = None self.language: T.Optional[str] = None # None means C-like @@ -128,14 +124,6 @@ def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> self.featurechecks: T.List['FeatureCheckBase'] = [] self.feature_since: T.Optional[T.Tuple[str, str]] = None - def __eq__(self, other: object) -> bool: - if not isinstance(other, Dependency): - return NotImplemented - return self.__id == other.__id - - def __hash__(self) -> int: - return self.__id - def __repr__(self) -> str: return f'<{self.__class__.__name__} {self.name}: {self.is_found}>' diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index fb18fa8b6806..4d1f427da210 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -1,9 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021-2024 Intel Corporation +# Copyright © 2021 Intel Corporation from __future__ import annotations -import copy import os import typing as T @@ -348,16 +347,6 @@ def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency] if not name: raise InterpreterException('First argument must be a string and cannot be empty') - # Make a copy since we're going to mutate. - # - # dep = declare_dependency() - # meson.override_dependency('foo', dep) - # meson.override_dependency('foo-1.0', dep) - # dep = dependency('foo') - # dep.name() # == 'foo-1.0' - dep = copy.copy(dep) - dep.name = name - optkey = OptionKey('default_library', subproject=self.interpreter.subproject) default_library = self.interpreter.coredata.get_option(optkey) assert isinstance(default_library, str), 'for mypy' diff --git a/test cases/common/98 subproject subdir/meson.build b/test cases/common/98 subproject subdir/meson.build index d2bafedf5119..ef053d86c41c 100644 --- a/test cases/common/98 subproject subdir/meson.build +++ b/test cases/common/98 subproject subdir/meson.build @@ -1,7 +1,3 @@ -# SPDX-License-Identifier: Apache-2.0 -# Copyright 2016-2023 The Meson Developers -# Copyright © 2024 Intel Corporation - project('proj', 'c') subproject('sub') libSub = dependency('sub', fallback: ['sub', 'libSub']) @@ -10,19 +6,7 @@ exe = executable('prog', 'prog.c', dependencies: libSub) test('subproject subdir', exe) # Verify the subproject has placed dependency override. -d = dependency('sub-1.0') - -# verify that the name is the overridden name -assert(d.name() == 'sub-1.0', 'name was not properly set, should have been "sub-1.0", but was @0@'.format(d.name())) - -# Verify that when a dependency object is used for two overrides, the correct -# name is used -meson.override_dependency('new-dep', d) -d2 = dependency('new-dep') -assert(d2.name() == 'new-dep', 'name was not properly set, should have been "new-dep", but was @0@'.format(d2.name())) - -# And that the old dependency wasn't changed -assert(d.name() == 'sub-1.0', 'original dependency was mutated.') +dependency('sub-1.0') # Verify we can now take 'sub' dependency without fallback, but only version 1.0. dependency('sub') From 5d417edd64093fd6f5c0df563f23b9586c93e1e3 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 8 Jul 2024 20:46:42 +0300 Subject: [PATCH 19/72] Bump version number for rc3. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 6e7a2f501cc3..afe4c1bd76b2 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -72,7 +72,7 @@ class SharedCMDOptions(Protocol): # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.5.0.rc2' +version = '1.5.0.rc3' # The next stable version when we are in dev. This is used to allow projects to # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when From 07777c725cf82a5ef4bb5c6d33fdcdbe3d688464 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 9 Jul 2024 19:02:09 -0300 Subject: [PATCH 20/72] nasm: Add -mms-bitfields to the list of ignored flags Fixes building Nasm objects with Meson's native language support, when depending against a library that exports that flag, like Glib. --- mesonbuild/compilers/asm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index bfe436b0b256..e25f18d6746d 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -75,7 +75,7 @@ def get_output_args(self, outputname: str) -> T.List[str]: def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: outargs: T.List[str] = [] for arg in args: - if arg == '-pthread': + if arg in {'-mms-bitfields', '-pthread'}: continue outargs.append(arg) return outargs From 183084a9e854ff627467279384330750016bad92 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 10 Jul 2024 20:25:01 +0300 Subject: [PATCH 21/72] Release 1.5.0 time. --- docs/markdown/Release-notes-for-1.5.0.md | 214 ++++++++++++++++++ docs/markdown/snippets/bztar_support.md | 4 - docs/markdown/snippets/cargo_dep_name.md | 19 -- docs/markdown/snippets/cargo_lock.md | 6 - docs/markdown/snippets/cmake_build_type.md | 15 -- docs/markdown/snippets/compiler_run.md | 4 - docs/markdown/snippets/find_library_name.md | 5 - .../snippets/find_program_version_argument.md | 12 - .../meson_configure_options_changes.md | 12 - docs/markdown/snippets/meson_format_cmd.md | 4 - .../snippets/null_terminated_string_arg.md | 13 -- docs/markdown/snippets/objfw_dep.md | 24 -- docs/markdown/snippets/pln_bsn_support.md | 11 - ...requires_kwarg_on_more_compiler_methods.md | 21 -- docs/markdown/snippets/test_interactive.md | 6 - docs/markdown/snippets/test_iteration.md | 5 - docs/markdown/snippets/test_max_lines.md | 6 - docs/markdown/snippets/ti_armclang.md | 3 - .../snippets/ti_c6000_compiler_support.md | 4 - .../snippets/wayland_stable_prot_version.md | 13 -- docs/sitemap.txt | 1 + mesonbuild/coredata.py | 2 +- 22 files changed, 216 insertions(+), 188 deletions(-) create mode 100644 docs/markdown/Release-notes-for-1.5.0.md delete mode 100644 docs/markdown/snippets/bztar_support.md delete mode 100644 docs/markdown/snippets/cargo_dep_name.md delete mode 100644 docs/markdown/snippets/cargo_lock.md delete mode 100644 docs/markdown/snippets/cmake_build_type.md delete mode 100644 docs/markdown/snippets/compiler_run.md delete mode 100644 docs/markdown/snippets/find_library_name.md delete mode 100644 docs/markdown/snippets/find_program_version_argument.md delete mode 100644 docs/markdown/snippets/meson_configure_options_changes.md delete mode 100644 docs/markdown/snippets/meson_format_cmd.md delete mode 100644 docs/markdown/snippets/null_terminated_string_arg.md delete mode 100644 docs/markdown/snippets/objfw_dep.md delete mode 100644 docs/markdown/snippets/pln_bsn_support.md delete mode 100644 docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md delete mode 100644 docs/markdown/snippets/test_interactive.md delete mode 100644 docs/markdown/snippets/test_iteration.md delete mode 100644 docs/markdown/snippets/test_max_lines.md delete mode 100644 docs/markdown/snippets/ti_armclang.md delete mode 100644 docs/markdown/snippets/ti_c6000_compiler_support.md delete mode 100644 docs/markdown/snippets/wayland_stable_prot_version.md diff --git a/docs/markdown/Release-notes-for-1.5.0.md b/docs/markdown/Release-notes-for-1.5.0.md new file mode 100644 index 000000000000..7dfea9af2b13 --- /dev/null +++ b/docs/markdown/Release-notes-for-1.5.0.md @@ -0,0 +1,214 @@ +--- +title: Release 1.5.0 +short-description: Release notes for 1.5.0 +... + +# New features + +Meson 1.5.0 was released on 10 July 2024 +## Support for `bztar` in `meson dist` + +The `bztar` format is now supported in `meson dist`. This format is also known +as `bzip2`. + +## Cargo dependencies names now include the API version + +Cargo dependencies names are now in the format `--rs`: +- `package_name` is defined in `[package] name = ...` section of the `Cargo.toml`. +- `version` is the API version deduced from `[package] version = ...` as follow: + * `x.y.z` -> 'x' + * `0.x.y` -> '0.x' + * `0.0.x` -> '0' + It allows to make different dependencies for uncompatible versions of the same + crate. +- `-rs` suffix is added to distinguish from regular system dependencies, for + example `gstreamer-1.0` is a system pkg-config dependency and `gstreamer-0.22-rs` + is a Cargo dependency. + +That means the `.wrap` file should have `dependency_names = foo-1-rs` in their +`[provide]` section when `Cargo.toml` has package name `foo` and version `1.2`. + +This is a breaking change (Cargo subprojects are still experimental), previous +versions were using `-rs` format. + +## Added support `Cargo.lock` file + +When a (sub)project has a `Cargo.lock` file at its root, it is loaded to provide +an automatic fallback for dependencies it defines, fetching code from +https://crates.io or git. This is identical as providing `subprojects/*.wrap`, +see [cargo wraps](Wrap-dependency-system-manual.md#cargo-wraps) dependency naming convention. + +## Meson now propagates its build type to CMake + +When the CMake build type variable, `CMAKE_BUILD_TYPE`, is not set via the +`add_cmake_defines` method of the [`cmake options` object](CMake-module.md#cmake-options-object), +it is inferred from the [Meson build type](Builtin-options.md#details-for-buildtype). +Build types of the two build systems do not match perfectly. The mapping from +Meson build type to CMake build type is as follows: + +- `debug` -> `Debug` +- `debugoptimized` -> `RelWithDebInfo` +- `release` -> `Release` +- `minsize` -> `MinSizeRel` + +No CMake build type is set for the `plain` Meson build type. The inferred CMake +build type overrides any `CMAKE_BUILD_TYPE` environment variable. + +## compiler.run() method is now available for all languages + +It used to be only implemented for C-like and D languages, but it is now available +for all languages. + +## dependencies created by compiler.find_library implement the `name()` method + +Previously, for a [[@dep]] that might be returned by either [[dependency]] or +[[compiler.find_library]], the method might or might not exist with no way +of telling. + +## New version_argument kwarg for find_program + +When finding an external program with `find_program`, the `version_argument` +can be used to override the default `--version` argument when trying to parse +the version of the program. + +For example, if the following is used: +```meson +foo = find_program('foo', version_argument: '-version') +``` + +meson will internally run `foo -version` when trying to find the version of `foo`. + +## Meson configure handles changes to options in more cases + +Meson configure now correctly handles updates to the options file without a full +reconfigure. This allows making a change to the `meson.options` or +`meson_options.txt` file without a reconfigure. + +For example, this now works: +```sh +meson setup builddir +git pull +meson configure builddir -Doption-added-by-pull=value +``` + +## New meson format command + +This command is similar to `muon fmt` and allows to format a `meson.build` +document. + +## Added support for GCC's `null_terminated_string_arg` function attribute + +You can now check if a compiler support the `null_terminated_string_arg` +function attribute via the `has_function_attribute()` method on the +[[@compiler]] object. + +```meson +cc = meson.get_compiler('c') + +if cc.has_function_attribute('null_terminated_string_arg') + # We have it... +endif +``` + +## A new dependency for ObjFW is now supported + +For example, you can create a simple application written using ObjFW like this: + +```meson +project('SimpleApp', 'objc') + +objfw_dep = dependency('objfw', version: '>= 1.0') + +executable('SimpleApp', 'SimpleApp.m', + dependencies: [objfw_dep]) +``` + +Modules are also supported. A test case using ObjFWTest can be created like +this: + +```meson +project('Tests', 'objc') + +objfwtest_dep = dependency('objfw', version: '>= 1.1', modules: ['ObjFWTest']) + +executable('Tests', ['FooTest.m', 'BarTest.m'], + dependencies: [objfwtest_dep]) +``` + +## Support of indexed `@PLAINNAME@` and `@BASENAME@` + +In `custom_target()` and `configure_file()` with multiple inputs, +it is now possible to specify index for `@PLAINNAME@` and `@BASENAME@` +macros in `output`: +``` +custom_target('target_name', + output: '@PLAINNAME0@.dl', + input: [dep1, dep2], + command: cmd) +``` + +## Required kwarg on more `compiler` methods + +The following `compiler` methods now support the `required` keyword argument: + +- `compiler.compiles()` +- `compiler.links()` +- `compiler.runs()` + +```meson +cc.compiles(valid, name: 'valid', required : true) +cc.links(valid, name: 'valid', required : true) +cc.run(valid, name: 'valid', required : true) + +assert(not cc.compiles(valid, name: 'valid', required : opt)) +assert(not cc.links(valid, name: 'valid', required : opt)) +res = cc.run(valid, name: 'valid', required : opt) +assert(res.compiled()) +assert(res.returncode() == 0) +assert(res.stdout() == '') +assert(res.stderr() == '') +``` + +## The Meson test program supports a new "--interactive" argument + +`meson test --interactive` invokes tests with stdout, stdin and stderr +connected directly to the calling terminal. This can be useful when running +integration tests that run in containers or virtual machines which can spawn a +debug shell if a test fails. + +## meson test now sets the `MESON_TEST_ITERATION` environment variable + +`meson test` will now set the `MESON_TEST_ITERATION` environment variable to the +current iteration of the test. This will always be `1` unless `--repeat` is used +to run the same test multiple times. + +## The Meson test program supports a new "--max-lines" argument + +By default `meson test` only shows the last 100 lines of test output from tests +that produce large amounts of output. This default can now be changed with the +new `--max-lines` option. For example, `--max-lines=1000` will increase the +maximum number of log output lines from 100 to 1000. + +## Basic support for TI Arm Clang (tiarmclang) + +Support for TI's newer [Clang-based ARM toolchain](https://www.ti.com/tool/ARM-CGT). + +## Support for Texas Instruments C6000 C/C++ compiler + +Meson now supports the TI C6000 C/C++ compiler use for the C6000 cpu family. +The example cross file is available in `cross/ti-c6000.txt`. + +## Wayland stable protocols can be versioned + +The wayland module now accepts a version number for stable protocols. + +```meson +wl_mod = import('unstable-wayland') + +wl_mod.find_protocol( + 'linux-dmabuf', + state: 'stable' + version: 1 +) +``` + diff --git a/docs/markdown/snippets/bztar_support.md b/docs/markdown/snippets/bztar_support.md deleted file mode 100644 index 3ee4a91add30..000000000000 --- a/docs/markdown/snippets/bztar_support.md +++ /dev/null @@ -1,4 +0,0 @@ -## Support for `bztar` in `meson dist` - -The `bztar` format is now supported in `meson dist`. This format is also known -as `bzip2`. diff --git a/docs/markdown/snippets/cargo_dep_name.md b/docs/markdown/snippets/cargo_dep_name.md deleted file mode 100644 index b769f2b9034f..000000000000 --- a/docs/markdown/snippets/cargo_dep_name.md +++ /dev/null @@ -1,19 +0,0 @@ -## Cargo dependencies names now include the API version - -Cargo dependencies names are now in the format `--rs`: -- `package_name` is defined in `[package] name = ...` section of the `Cargo.toml`. -- `version` is the API version deduced from `[package] version = ...` as follow: - * `x.y.z` -> 'x' - * `0.x.y` -> '0.x' - * `0.0.x` -> '0' - It allows to make different dependencies for uncompatible versions of the same - crate. -- `-rs` suffix is added to distinguish from regular system dependencies, for - example `gstreamer-1.0` is a system pkg-config dependency and `gstreamer-0.22-rs` - is a Cargo dependency. - -That means the `.wrap` file should have `dependency_names = foo-1-rs` in their -`[provide]` section when `Cargo.toml` has package name `foo` and version `1.2`. - -This is a breaking change (Cargo subprojects are still experimental), previous -versions were using `-rs` format. diff --git a/docs/markdown/snippets/cargo_lock.md b/docs/markdown/snippets/cargo_lock.md deleted file mode 100644 index e38c5ed35340..000000000000 --- a/docs/markdown/snippets/cargo_lock.md +++ /dev/null @@ -1,6 +0,0 @@ -## Added support `Cargo.lock` file - -When a (sub)project has a `Cargo.lock` file at its root, it is loaded to provide -an automatic fallback for dependencies it defines, fetching code from -https://crates.io or git. This is identical as providing `subprojects/*.wrap`, -see [cargo wraps](Wrap-dependency-system-manual.md#cargo-wraps) dependency naming convention. diff --git a/docs/markdown/snippets/cmake_build_type.md b/docs/markdown/snippets/cmake_build_type.md deleted file mode 100644 index af9e84dc8e85..000000000000 --- a/docs/markdown/snippets/cmake_build_type.md +++ /dev/null @@ -1,15 +0,0 @@ -## Meson now propagates its build type to CMake - -When the CMake build type variable, `CMAKE_BUILD_TYPE`, is not set via the -`add_cmake_defines` method of the [`cmake options` object](CMake-module.md#cmake-options-object), -it is inferred from the [Meson build type](Builtin-options.md#details-for-buildtype). -Build types of the two build systems do not match perfectly. The mapping from -Meson build type to CMake build type is as follows: - -- `debug` -> `Debug` -- `debugoptimized` -> `RelWithDebInfo` -- `release` -> `Release` -- `minsize` -> `MinSizeRel` - -No CMake build type is set for the `plain` Meson build type. The inferred CMake -build type overrides any `CMAKE_BUILD_TYPE` environment variable. diff --git a/docs/markdown/snippets/compiler_run.md b/docs/markdown/snippets/compiler_run.md deleted file mode 100644 index f4b0847a5dc4..000000000000 --- a/docs/markdown/snippets/compiler_run.md +++ /dev/null @@ -1,4 +0,0 @@ -## compiler.run() method is now available for all languages - -It used to be only implemented for C-like and D languages, but it is now available -for all languages. diff --git a/docs/markdown/snippets/find_library_name.md b/docs/markdown/snippets/find_library_name.md deleted file mode 100644 index e7b0e1a5bab2..000000000000 --- a/docs/markdown/snippets/find_library_name.md +++ /dev/null @@ -1,5 +0,0 @@ -## dependencies created by compiler.find_library implement the `name()` method - -Previously, for a [[@dep]] that might be returned by either [[dependency]] or -[[compiler.find_library]], the method might or might not exist with no way -of telling. diff --git a/docs/markdown/snippets/find_program_version_argument.md b/docs/markdown/snippets/find_program_version_argument.md deleted file mode 100644 index 99fe62109776..000000000000 --- a/docs/markdown/snippets/find_program_version_argument.md +++ /dev/null @@ -1,12 +0,0 @@ -## New version_argument kwarg for find_program - -When finding an external program with `find_program`, the `version_argument` -can be used to override the default `--version` argument when trying to parse -the version of the program. - -For example, if the following is used: -```meson -foo = find_program('foo', version_argument: '-version') -``` - -meson will internally run `foo -version` when trying to find the version of `foo`. diff --git a/docs/markdown/snippets/meson_configure_options_changes.md b/docs/markdown/snippets/meson_configure_options_changes.md deleted file mode 100644 index c86792ceb52a..000000000000 --- a/docs/markdown/snippets/meson_configure_options_changes.md +++ /dev/null @@ -1,12 +0,0 @@ -## Meson configure handles changes to options in more cases - -Meson configure now correctly handles updates to the options file without a full -reconfigure. This allows making a change to the `meson.options` or -`meson_options.txt` file without a reconfigure. - -For example, this now works: -```sh -meson setup builddir -git pull -meson configure builddir -Doption-added-by-pull=value -``` diff --git a/docs/markdown/snippets/meson_format_cmd.md b/docs/markdown/snippets/meson_format_cmd.md deleted file mode 100644 index 390f15d581c7..000000000000 --- a/docs/markdown/snippets/meson_format_cmd.md +++ /dev/null @@ -1,4 +0,0 @@ -## New meson format command - -This command is similar to `muon fmt` and allows to format a `meson.build` -document. diff --git a/docs/markdown/snippets/null_terminated_string_arg.md b/docs/markdown/snippets/null_terminated_string_arg.md deleted file mode 100644 index 2ba1755758f8..000000000000 --- a/docs/markdown/snippets/null_terminated_string_arg.md +++ /dev/null @@ -1,13 +0,0 @@ -## Added support for GCC's `null_terminated_string_arg` function attribute - -You can now check if a compiler support the `null_terminated_string_arg` -function attribute via the `has_function_attribute()` method on the -[[@compiler]] object. - -```meson -cc = meson.get_compiler('c') - -if cc.has_function_attribute('null_terminated_string_arg') - # We have it... -endif -``` diff --git a/docs/markdown/snippets/objfw_dep.md b/docs/markdown/snippets/objfw_dep.md deleted file mode 100644 index e65da2885b4a..000000000000 --- a/docs/markdown/snippets/objfw_dep.md +++ /dev/null @@ -1,24 +0,0 @@ -## A new dependency for ObjFW is now supported - -For example, you can create a simple application written using ObjFW like this: - -```meson -project('SimpleApp', 'objc') - -objfw_dep = dependency('objfw', version: '>= 1.0') - -executable('SimpleApp', 'SimpleApp.m', - dependencies: [objfw_dep]) -``` - -Modules are also supported. A test case using ObjFWTest can be created like -this: - -```meson -project('Tests', 'objc') - -objfwtest_dep = dependency('objfw', version: '>= 1.1', modules: ['ObjFWTest']) - -executable('Tests', ['FooTest.m', 'BarTest.m'], - dependencies: [objfwtest_dep]) -``` diff --git a/docs/markdown/snippets/pln_bsn_support.md b/docs/markdown/snippets/pln_bsn_support.md deleted file mode 100644 index 394339f1499d..000000000000 --- a/docs/markdown/snippets/pln_bsn_support.md +++ /dev/null @@ -1,11 +0,0 @@ -## Support of indexed `@PLAINNAME@` and `@BASENAME@` - -In `custom_target()` and `configure_file()` with multiple inputs, -it is now possible to specify index for `@PLAINNAME@` and `@BASENAME@` -macros in `output`: -``` -custom_target('target_name', - output: '@PLAINNAME0@.dl', - input: [dep1, dep2], - command: cmd) -``` diff --git a/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md b/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md deleted file mode 100644 index 693313c31413..000000000000 --- a/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md +++ /dev/null @@ -1,21 +0,0 @@ -## Required kwarg on more `compiler` methods - -The following `compiler` methods now support the `required` keyword argument: - -- `compiler.compiles()` -- `compiler.links()` -- `compiler.runs()` - -```meson -cc.compiles(valid, name: 'valid', required : true) -cc.links(valid, name: 'valid', required : true) -cc.run(valid, name: 'valid', required : true) - -assert(not cc.compiles(valid, name: 'valid', required : opt)) -assert(not cc.links(valid, name: 'valid', required : opt)) -res = cc.run(valid, name: 'valid', required : opt) -assert(res.compiled()) -assert(res.returncode() == 0) -assert(res.stdout() == '') -assert(res.stderr() == '') -``` diff --git a/docs/markdown/snippets/test_interactive.md b/docs/markdown/snippets/test_interactive.md deleted file mode 100644 index 907147fd9ca9..000000000000 --- a/docs/markdown/snippets/test_interactive.md +++ /dev/null @@ -1,6 +0,0 @@ -## The Meson test program supports a new "--interactive" argument - -`meson test --interactive` invokes tests with stdout, stdin and stderr -connected directly to the calling terminal. This can be useful when running -integration tests that run in containers or virtual machines which can spawn a -debug shell if a test fails. diff --git a/docs/markdown/snippets/test_iteration.md b/docs/markdown/snippets/test_iteration.md deleted file mode 100644 index 67daf278129d..000000000000 --- a/docs/markdown/snippets/test_iteration.md +++ /dev/null @@ -1,5 +0,0 @@ -## meson test now sets the `MESON_TEST_ITERATION` environment variable - -`meson test` will now set the `MESON_TEST_ITERATION` environment variable to the -current iteration of the test. This will always be `1` unless `--repeat` is used -to run the same test multiple times. diff --git a/docs/markdown/snippets/test_max_lines.md b/docs/markdown/snippets/test_max_lines.md deleted file mode 100644 index ea10fbb2791b..000000000000 --- a/docs/markdown/snippets/test_max_lines.md +++ /dev/null @@ -1,6 +0,0 @@ -## The Meson test program supports a new "--max-lines" argument - -By default `meson test` only shows the last 100 lines of test output from tests -that produce large amounts of output. This default can now be changed with the -new `--max-lines` option. For example, `--max-lines=1000` will increase the -maximum number of log output lines from 100 to 1000. diff --git a/docs/markdown/snippets/ti_armclang.md b/docs/markdown/snippets/ti_armclang.md deleted file mode 100644 index 7f0f912c0ed8..000000000000 --- a/docs/markdown/snippets/ti_armclang.md +++ /dev/null @@ -1,3 +0,0 @@ -## Basic support for TI Arm Clang (tiarmclang) - -Support for TI's newer [Clang-based ARM toolchain](https://www.ti.com/tool/ARM-CGT). diff --git a/docs/markdown/snippets/ti_c6000_compiler_support.md b/docs/markdown/snippets/ti_c6000_compiler_support.md deleted file mode 100644 index 03533e6091cd..000000000000 --- a/docs/markdown/snippets/ti_c6000_compiler_support.md +++ /dev/null @@ -1,4 +0,0 @@ -## Support for Texas Instruments C6000 C/C++ compiler - -Meson now supports the TI C6000 C/C++ compiler use for the C6000 cpu family. -The example cross file is available in `cross/ti-c6000.txt`. diff --git a/docs/markdown/snippets/wayland_stable_prot_version.md b/docs/markdown/snippets/wayland_stable_prot_version.md deleted file mode 100644 index 78d0a50d5c89..000000000000 --- a/docs/markdown/snippets/wayland_stable_prot_version.md +++ /dev/null @@ -1,13 +0,0 @@ -## Wayland stable protocols can be versioned - -The wayland module now accepts a version number for stable protocols. - -```meson -wl_mod = import('unstable-wayland') - -wl_mod.find_protocol( - 'linux-dmabuf', - state: 'stable' - version: 1 -) -``` diff --git a/docs/sitemap.txt b/docs/sitemap.txt index 04f7fdae344f..79fdeeffe70f 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -88,6 +88,7 @@ index.md Wrap-best-practices-and-tips.md Shipping-prebuilt-binaries-as-wraps.md Release-notes.md + Release-notes-for-1.5.0.md Release-notes-for-1.4.0.md Release-notes-for-1.3.0.md Release-notes-for-1.2.0.md diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index afe4c1bd76b2..642e33455bd9 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -72,7 +72,7 @@ class SharedCMDOptions(Protocol): # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.5.0.rc3' +version = '1.5.0' # The next stable version when we are in dev. This is used to allow projects to # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when From 082cf5de0c9b37c769822acd69e7270287a7e0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=C3=A4ssens?= Date: Fri, 12 Jul 2024 11:21:54 +0200 Subject: [PATCH 22/72] backend/backends: Fix type assertions in backend Test dependencies can be of type CustomTargetIndex, similar to other targets. (cherry picked from commit f5d66b4932f94fbe78058e617c2d83a454107008) --- mesonbuild/backend/backends.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index b664300f4006..454b90c704d3 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1169,7 +1169,7 @@ def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: def determine_windows_extra_paths( self, target: T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, programs.ExternalProgram, mesonlib.File, str], - extra_bdeps: T.Sequence[T.Union[build.BuildTarget, build.CustomTarget]]) -> T.List[str]: + extra_bdeps: T.Sequence[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]) -> T.List[str]: """On Windows there is no such thing as an rpath. We must determine all locations of DLLs that this exe @@ -1229,7 +1229,7 @@ def create_test_serialisation(self, tests: T.List['Test']) -> T.List[TestSeriali exe_wrapper = self.environment.get_exe_wrapper() machine = self.environment.machines[exe.for_machine] if machine.is_windows() or machine.is_cygwin(): - extra_bdeps: T.List[T.Union[build.BuildTarget, build.CustomTarget]] = [] + extra_bdeps: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]] = [] if isinstance(exe, build.CustomTarget): extra_bdeps = list(exe.get_transitive_build_target_deps()) extra_paths = self.determine_windows_extra_paths(exe, extra_bdeps) @@ -1426,7 +1426,7 @@ def get_testlike_targets(self, benchmark: bool = False) -> T.OrderedDict[str, T. continue result[arg.get_id()] = arg for dep in t.depends: - assert isinstance(dep, (build.CustomTarget, build.BuildTarget)) + assert isinstance(dep, (build.CustomTarget, build.BuildTarget, build.CustomTargetIndex)) result[dep.get_id()] = dep return result From 3f340d0c96bc74c1115b9b4594c9f1f4b2912b08 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Sun, 14 Jul 2024 17:39:30 +0200 Subject: [PATCH 23/72] Revert "Support armel/armhf builds on native arm64 hosts." This reverts commit cc201a539674babf46f726859587afb5ed6a6867. It's true that some aarch64 CPUs can run 32-bit ARM code, but some (especially high-end ones, those most likely to be running builds) cannot. It's better to assume that they can't, so builds don't unnecessarily fail due to attempting to run a sanity check executable. (cherry picked from commit 2fd7d64a50aa4f8a76d5b9ca13f7d8f8f40b959c) --- mesonbuild/environment.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index be40dbcfd4be..f71bf219cf64 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -512,8 +512,7 @@ def machine_info_can_run(machine_info: MachineInfo): return \ (machine_info.cpu_family == true_build_cpu_family) or \ ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \ - ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) or \ - ((true_build_cpu_family == 'aarch64') and (machine_info.cpu_family == 'arm')) + ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) class Environment: private_dir = 'meson-private' From df833b0512cd4e59c14205f6d9ff0d0642b3dd4f Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Thu, 11 Jul 2024 22:31:39 +0200 Subject: [PATCH 24/72] Revert various cross compile changes c1076241af11f10acac28d771688bb54c6b0b340 changed the logic in multiple places, in particular it looks like it was assumed that is_cross is always the same as need_exe_wrapper(), but that's not true. Also the commit only talks about mypy, so this was definitely not intended. This reverts all the cases where need_exe_wrapper() was introduced back to is_cross. The change in backends.py could be a correct simplification, but I don't know the code base enough, so reverting that too. See #13403 and #13410 (cherry picked from commit d9e2dd6c806b5edf0f686c088fff2b3836ba1624) --- mesonbuild/backend/backends.py | 3 ++- mesonbuild/compilers/cuda.py | 4 ++-- mesonbuild/compilers/d.py | 2 +- mesonbuild/compilers/mixins/clike.py | 4 ++-- mesonbuild/compilers/rust.py | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 454b90c704d3..4c7faa5aa380 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -568,7 +568,8 @@ def get_executable_serialisation( else: extra_paths = [] - if self.environment.need_exe_wrapper(exe_for_machine): + is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) + if is_cross_built and self.environment.need_exe_wrapper(): if not self.environment.has_exe_wrapper(): msg = 'An exe_wrapper is needed but was not found. Please define one ' \ 'in cross file and check the command and/or add it to PATH.' diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index dc9cf8addd35..a6049a8439cd 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -552,7 +552,7 @@ def sanity_check(self, work_dir: str, env: 'Environment') -> None: flags += self.get_ccbin_args(env.coredata.optstore) # If cross-compiling, we can't run the sanity check, only compile it. - if env.need_exe_wrapper(self.for_machine) and not env.has_exe_wrapper(): + if self.is_cross and not env.has_exe_wrapper(): # Linking cross built apps is painful. You can't really # tell if you should use -nostdlib or not and for example # on OSX the compiler binary is the same but you need @@ -574,7 +574,7 @@ def sanity_check(self, work_dir: str, env: 'Environment') -> None: raise EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') # Run sanity check (if possible) - if env.need_exe_wrapper(self.for_machine): + if self.is_cross: if not env.has_exe_wrapper(): return else: diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 46cffdd0fc43..907ee6fc1572 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -455,7 +455,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if pc.returncode != 0: raise EnvironmentException('D compiler %s cannot compile programs.' % self.name_string()) - if environment.need_exe_wrapper(self.for_machine): + if self.is_cross: if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 70e81a4b85d9..1fddb0f95dd1 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -278,7 +278,7 @@ def _sanity_check_impl(self, work_dir: str, environment: 'Environment', mode = CompileCheckMode.LINK if self.is_cross: binname += '_cross' - if environment.need_exe_wrapper(self.for_machine) and not environment.has_exe_wrapper(): + if not environment.has_exe_wrapper(): # Linking cross built C/C++ apps is painful. You can't really # tell if you should use -nostdlib or not and for example # on OSX the compiler binary is the same but you need @@ -308,7 +308,7 @@ def _sanity_check_impl(self, work_dir: str, environment: 'Environment', if pc.returncode != 0: raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.') # Run sanity check - if environment.need_exe_wrapper(self.for_machine): + if self.is_cross: if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index b130c58ee307..0ac07a8be763 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -86,7 +86,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if pc.returncode != 0: raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.') self._native_static_libs(work_dir, source_name) - if environment.need_exe_wrapper(self.for_machine): + if self.is_cross: if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return From c108d5b2588501b462695d4d10f2aa2fcd91394e Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 12 Jul 2024 06:34:32 +0200 Subject: [PATCH 25/72] Revert logic also in followup commit In 8d7ffe6e863834f0190e need_exe_wrapper() use was copied which was just reverted, so replace with is_cross there too, to keep things in sync. (cherry picked from commit 76bd5548ae185e10a6cf3925980e8a18955e5c66) --- mesonbuild/compilers/d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 907ee6fc1572..c478c040ba9c 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -447,7 +447,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: compile_cmdlist = self.exelist + self.get_output_args(output_name) + self._get_target_arch_args() + [source_name] # If cross-compiling, we can't run the sanity check, only compile it. - if environment.need_exe_wrapper(self.for_machine) and not environment.has_exe_wrapper(): + if self.is_cross and not environment.has_exe_wrapper(): compile_cmdlist += self.get_compile_only_args() pc = subprocess.Popen(compile_cmdlist, cwd=work_dir) From eba9e7efcf189306f5d8a7ab6406b05438a35988 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 12 Jul 2024 07:17:12 +0200 Subject: [PATCH 26/72] Make sure machine_info_can_run() isn't called on incomplete MachineInfo If need_exe_wrapper() is called while figuring out the language compiler, the MachineInfo isn't complete yet, so machine_info_can_run() would return False despite not cross compiling. Make sure this fails loudly. (cherry picked from commit a51d5f36da85c1652c20254a522a9448147c4fbf) --- mesonbuild/environment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index f71bf219cf64..74c482382264 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -509,6 +509,7 @@ def machine_info_can_run(machine_info: MachineInfo): if machine_info.system != detect_system(): return False true_build_cpu_family = detect_cpu_family({}) + assert machine_info.cpu_family is not None, 'called on incomplete machine_info' return \ (machine_info.cpu_family == true_build_cpu_family) or \ ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \ From 30f02e6563b730df735767c6ba0a7e01a137b9df Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 16 Jul 2024 10:21:43 +0200 Subject: [PATCH 27/72] rust: recursively pull proc-macro deps for rust targets aee941559 ("rust: recursively pull proc-macro dependencies as well") had to be reverted (in a66cb97e8) because it broke Mesa cross compilation. This happened because a C shared library was linked with a Rust C-ABI static library, which caused it to inherit the proc macro dependency the Rust static library was linked with. The right way to handle this is for only Rust targets to inherit proc macro dependencies from static libraries they link with. A Rust executable, library, or whatever will need the proc macros its Rust dependencies use, as illustrated in the test case that I've reintroduced here. I've verified that Mesa still cross compiles correctly with this change. The same failure was also identified by the "rust/21 transitive dependencies" test case, but only when cross compiling, so it wasn't caught by CI. Co-authored-by: Xavier Claessens (cherry picked from commit a05f6a260ef4882f82da38ff1818ca8391b15bd8) --- mesonbuild/build.py | 10 +++++----- test cases/rust/18 proc-macro/lib.rs | 8 ++++++++ test cases/rust/18 proc-macro/meson.build | 11 +++++++++++ test cases/rust/18 proc-macro/subdir/meson.build | 1 + .../rust/18 proc-macro/transitive-proc-macro.rs | 7 +++++++ .../rust/21 transitive dependencies/meson.build | 1 + 6 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 test cases/rust/18 proc-macro/lib.rs create mode 100644 test cases/rust/18 proc-macro/subdir/meson.build create mode 100644 test cases/rust/18 proc-macro/transitive-proc-macro.rs diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 071dbdfd4562..a1d9fbc16857 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1280,10 +1280,10 @@ def get_dependencies(self) -> OrderedSet[BuildTargetTypes]: if t not in result: result.add(t) if isinstance(t, StaticLibrary): - t.get_dependencies_recurse(result) + t.get_dependencies_recurse(result, include_proc_macros = self.uses_rust()) return result - def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True) -> None: + def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True, include_proc_macros: bool = False) -> None: # self is always a static library because we don't need to pull dependencies # of shared libraries. If self is installed (not internal) it already # include objects extracted from all its internal dependencies so we can @@ -1292,14 +1292,14 @@ def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include for t in self.link_targets: if t in result: continue - if t.rust_crate_type == 'proc-macro': + if not include_proc_macros and t.rust_crate_type == 'proc-macro': continue if include_internals or not t.is_internal(): result.add(t) if isinstance(t, StaticLibrary): - t.get_dependencies_recurse(result, include_internals) + t.get_dependencies_recurse(result, include_internals, include_proc_macros) for t in self.link_whole_targets: - t.get_dependencies_recurse(result, include_internals) + t.get_dependencies_recurse(result, include_internals, include_proc_macros) def get_source_subdir(self): return self.subdir diff --git a/test cases/rust/18 proc-macro/lib.rs b/test cases/rust/18 proc-macro/lib.rs new file mode 100644 index 000000000000..5242886cc5e4 --- /dev/null +++ b/test cases/rust/18 proc-macro/lib.rs @@ -0,0 +1,8 @@ +extern crate proc_macro_examples; +use proc_macro_examples::make_answer; + +make_answer!(); + +pub fn func() -> u32 { + answer() +} diff --git a/test cases/rust/18 proc-macro/meson.build b/test cases/rust/18 proc-macro/meson.build index c5f0dfc82aee..e8b28eda144e 100644 --- a/test cases/rust/18 proc-macro/meson.build +++ b/test cases/rust/18 proc-macro/meson.build @@ -31,3 +31,14 @@ main = executable( ) test('main_test2', main) + +subdir('subdir') + +staticlib = static_library('staticlib', 'lib.rs', + link_with: pm_in_subdir, + rust_dependency_map : {'proc_macro_examples3' : 'proc_macro_examples'} +) + +executable('transitive-proc-macro', 'transitive-proc-macro.rs', + link_with: staticlib, +) diff --git a/test cases/rust/18 proc-macro/subdir/meson.build b/test cases/rust/18 proc-macro/subdir/meson.build new file mode 100644 index 000000000000..04842c431e78 --- /dev/null +++ b/test cases/rust/18 proc-macro/subdir/meson.build @@ -0,0 +1 @@ +pm_in_subdir = rust.proc_macro('proc_macro_examples3', '../proc.rs') diff --git a/test cases/rust/18 proc-macro/transitive-proc-macro.rs b/test cases/rust/18 proc-macro/transitive-proc-macro.rs new file mode 100644 index 000000000000..4c804b3b6f4d --- /dev/null +++ b/test cases/rust/18 proc-macro/transitive-proc-macro.rs @@ -0,0 +1,7 @@ +extern crate staticlib; +use staticlib::func; + + +fn main() { + assert_eq!(42, func()); +} diff --git a/test cases/rust/21 transitive dependencies/meson.build b/test cases/rust/21 transitive dependencies/meson.build index 37687fd4db2f..3b1f3d63cd4d 100644 --- a/test cases/rust/21 transitive dependencies/meson.build +++ b/test cases/rust/21 transitive dependencies/meson.build @@ -21,6 +21,7 @@ foo = static_library('foo-rs', 'foo.rs', rust_abi: 'c', link_with: pm, ) +shared_library('shared', 'foo.c', link_with : foo) exe = executable('footest', 'foo.c', link_with: foo, ) From 86f1a2879bb1888e2f7b75d53da36e28cc1ce356 Mon Sep 17 00:00:00 2001 From: RaviRahar Date: Fri, 19 Jul 2024 11:53:56 +0530 Subject: [PATCH 28/72] modules/gnome: gnome.compile_resources() must have 'install_dir' if installing Since they do not implement a default install dir like BuildTargets do. gnome.compile_resources() would result in an unhandled python exception when missing install_dir argument together with providing following arguments: gresource_bundle: true install: true closes: https://github.com/mesonbuild/meson/issues/13447 Signed-off-by: RaviRahar (cherry picked from commit 96f20d5b372b9982c153b114eb3726fbbecb7542) --- mesonbuild/modules/gnome.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index cab7c76a3d86..9d872353ae02 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -478,8 +478,11 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri else: raise MesonException('Compiling GResources into code is only supported in C and C++ projects') - if kwargs['install'] and not gresource: - raise MesonException('The install kwarg only applies to gresource bundles, see install_header') + if kwargs['install']: + if not gresource: + raise MesonException('The install kwarg only applies to gresource bundles, see install_header') + elif not kwargs['install_dir']: + raise MesonException('gnome.compile_resources: "install_dir" keyword argument must be set when "install" is true.') install_header = kwargs['install_header'] if install_header and gresource: From 6565f4c958eae053dd617895462977092034b4e4 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 21 Jul 2024 03:52:07 -0400 Subject: [PATCH 29/72] compilers: fix partial refactor of coredata options Fallout from the OptionStore refactor, and specifically commit 9a6fcd4d9a0c7bb248c5d0587632b741a3301e03. The `std` object was migrated from having an option itself, to having the value fetched and saved directly. In most cases, this also meant avoiding `.value`, but in a couple cases this refactor went overlooked, and crashed at runtime. Only affects Elbrus and Intel C++ compilers, seemingly. Fixes #13401 (cherry picked from commit bc56a2c3469def7fafbdb38da6691cccb171e739) --- mesonbuild/compilers/cpp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 5e8947bcec58..044cd2b378a4 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -618,8 +618,8 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] args: T.List[str] = [] key = self.form_langopt_key('std') std = options.get_value(key) - if std.value != 'none': - args.append(self._find_best_cpp_std(std.value)) + if std != 'none': + args.append(self._find_best_cpp_std(std)) key = self.form_langopt_key('eh') non_msvc_eh_options(options.get_value(key), args) @@ -695,7 +695,7 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] 'c++03': 'c++98', 'gnu++03': 'gnu++98' } - args.append('-std=' + remap_cpp03.get(std.value, std)) + args.append('-std=' + remap_cpp03.get(std, std)) if options.get_value(key.evolve('eh')) == 'none': args.append('-fno-exceptions') if not options.get_value(key.evolve('rtti')): From 19d31addd57abe35e2cebb750c0adfb668f103e4 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 22 Jul 2024 11:56:55 -0400 Subject: [PATCH 30/72] mdist: don't fail on readonly source trees In commit c9aa4aff66ebbbcd3eed3da8fbc3af0e0a8b90a2 we added a refresh call to git to catch cases where checking for uncommitted changes would misfire. Unfortunately, that refresh performs a write operation, which in turn misfires on readonly media. We don't actually care about the return value of the refresh, since its purpose is solely to make the next command more accurate -- so ignore it. Fixes: c9aa4aff66ebbbcd3eed3da8fbc3af0e0a8b90a2 Fixes: #13461 (cherry picked from commit e9037e7b9ff81febbcef860dbfa785464ba3b457) --- mesonbuild/mdist.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index e4606306b6d2..c29020068d9b 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -140,7 +140,9 @@ def git_root(self, dir_: str) -> Path: def have_dirty_index(self) -> bool: '''Check whether there are uncommitted changes in git''' - subprocess.check_call(['git', '-C', self.src_root, 'update-index', '-q', '--refresh']) + # Optimistically call update-index, and disregard its return value. It could be read-only, + # and only the output of diff-index matters. + subprocess.call(['git', '-C', self.src_root, 'update-index', '-q', '--refresh']) ret = subprocess.call(['git', '-C', self.src_root, 'diff-index', '--quiet', 'HEAD']) return ret == 1 From 22a95042e67d8f53597d5607c5eac17125fce5d5 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 22 Jul 2024 08:46:18 +0300 Subject: [PATCH 31/72] Ensure override var exists. Closes #13402. (cherry picked from commit a97de6b527c0109112909af8f29e8d262a87c247) --- mesonbuild/coredata.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 642e33455bd9..90667e8fc6d0 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -12,7 +12,7 @@ from itertools import chain from pathlib import PurePath from collections import OrderedDict, abc -from dataclasses import dataclass +import dataclasses from .mesonlib import ( MesonBugException, @@ -891,7 +891,7 @@ def parse_cmd_line_options(args: SharedCMDOptions) -> None: args.cmd_line_options[key] = value delattr(args, name) -@dataclass +@dataclasses.dataclass class OptionsView(abc.Mapping): '''A view on an options dictionary for a given subproject and with overrides. ''' @@ -900,7 +900,7 @@ class OptionsView(abc.Mapping): # python 3.8 or typing_extensions original_options: T.Union[KeyedOptionDictType, 'dict[OptionKey, UserOption[Any]]'] subproject: T.Optional[str] = None - overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None + overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = dataclasses.field(default_factory=dict) def __getitem__(self, key: OptionKey) -> options.UserOption: # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). From 18ef17e048ea3102fa6c5296fe71f259b243467d Mon Sep 17 00:00:00 2001 From: Monson Shao Date: Sun, 14 Jul 2024 21:58:03 +0800 Subject: [PATCH 32/72] depfixer: deduplicate rpaths on darwin Duplicated -delete_rpath arguments will cause macOS's install_name_tool failed. (cherry picked from commit 93f5ceb9eebfee229c15b31b935d8df6ad642a0b) --- mesonbuild/scripts/depfixer.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index f0166bdc3481..641689f9318d 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -379,11 +379,14 @@ def fix_elf(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Optiona # note: e.get_rpath() and e.get_runpath() may be useful e.fix_rpath(fname, rpath_dirs_to_remove, new_rpath) -def get_darwin_rpaths(fname: str) -> T.List[str]: +def get_darwin_rpaths(fname: str) -> OrderedSet[str]: p, out, _ = Popen_safe(['otool', '-l', fname], stderr=subprocess.DEVNULL) if p.returncode != 0: raise subprocess.CalledProcessError(p.returncode, p.args, out) - result = [] + # Need to deduplicate rpaths, as macOS's install_name_tool + # is *very* allergic to duplicate -delete_rpath arguments + # when calling depfixer on installation. + result = OrderedSet() current_cmd = 'FOOBAR' for line in out.split('\n'): line = line.strip() @@ -394,7 +397,7 @@ def get_darwin_rpaths(fname: str) -> T.List[str]: current_cmd = value if key == 'path' and current_cmd == 'LC_RPATH': rp = value.split('(', 1)[0].strip() - result.append(rp) + result.add(rp) return result def fix_darwin(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: str, final_path: str, install_name_mappings: T.Dict[str, str]) -> None: From b6c98c1c95b5c52dc729589969bf514660b8855c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 23 Jul 2024 14:12:35 -0700 Subject: [PATCH 33/72] depfixer: Add missing annotation that breaks mypy check (cherry picked from commit f76f9ddf28f16704b9d91066f6cc151fc78329e1) --- mesonbuild/scripts/depfixer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 641689f9318d..db9c97d98c6a 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -386,7 +386,7 @@ def get_darwin_rpaths(fname: str) -> OrderedSet[str]: # Need to deduplicate rpaths, as macOS's install_name_tool # is *very* allergic to duplicate -delete_rpath arguments # when calling depfixer on installation. - result = OrderedSet() + result: OrderedSet[str] = OrderedSet() current_cmd = 'FOOBAR' for line in out.split('\n'): line = line.strip() From 813f103493ae1906ac9f6b2efb40f5bc0aee57c4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Jul 2024 09:02:01 -0700 Subject: [PATCH 34/72] backend/ninja: fix off-by-one in cmd length estimate This causes us to not count the spaces between arguments, thereby undercounting the number of elements. This is extra important because we previously double counted all actual characters, covering this issue up. Fixes: cf0fecfce ("backend/ninja: Fix bug in NinjaRule.length_estimate") (cherry picked from commit 4842b8bcb37fe98f48b08e99210e04640380bffb) --- mesonbuild/backend/ninjabackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index eabe75865d2c..b51334a5963e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -291,7 +291,7 @@ def length_estimate(self, infiles: str, outfiles: str, estimate = len(command) for m in re.finditer(r'(\${\w+}|\$\w+)?[^$]*', command): if m.start(1) != -1: - estimate -= m.end(1) - m.start(1) + 1 + estimate -= m.end(1) - m.start(1) chunk = m.group(1) if chunk[1] == '{': chunk = chunk[2:-1] From b1bd200e76cd0d501521b100910f155f7887ec49 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Jul 2024 09:08:01 -0700 Subject: [PATCH 35/72] backend/ninja: use 32k byte limit for command lines on !Windows At an OS level, Unix-like OSes usually have very large or even unlimited sized command line limits. In practice, however, many applications do not handle this (intentionally or otherwise). Notably Wine has the same limits Windows does, 32,768 characters. Because we previously double counted most characters, we papered over most situations that we would need an RSP file on Unix-like OSes with Wine. To fix this issue I have set the command line limit to 32k, this is still a massive command line to pass without an RSP file, and will only cause the use of an RSP file where it is not strictly necessary in a small number of cases, but will fix Wine applications. Projects who wish to not use an RSP file can still set the MESON_RSP_THRESHOLD environment variable to a very large number instead. Fixes: #13414 Fixes: cf0fecfce ("backend/ninja: Fix bug in NinjaRule.length_estimate") (cherry picked from commit a544c750b1d6d6d6cd3e617da6a060f3e5662a6a) --- mesonbuild/backend/ninjabackend.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b51334a5963e..27b9f7bb1d24 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -98,10 +98,11 @@ def get_rsp_threshold() -> int: # and that has a limit of 8k. limit = 8192 else: - # On Linux, ninja always passes the commandline as a single - # big string to /bin/sh, and the kernel limits the size of a - # single argument; see MAX_ARG_STRLEN - limit = 131072 + # Unix-like OSes usualy have very large command line limits, (On Linux, + # for example, this is limited by the kernel's MAX_ARG_STRLEN). However, + # some programs place much lower limits, notably Wine which enforces a + # 32k limit like Windows. Therefore, we limit the command line to 32k. + limit = 32768 # Be conservative limit = limit // 2 return int(os.environ.get('MESON_RSP_THRESHOLD', limit)) From 3ec1fe232657636b0bafbef430169575057560ef Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 25 Jul 2024 16:05:25 +0530 Subject: [PATCH 36/72] wrap: Use OSError instead of URLError for exception handling URLError is a subclass of OSError and intermittent server errors can manifest as OSError while reading instead of a URLError while establishing a connection, which will cause the fallback url to be ignored: ``` Looking for a fallback subproject for the dependency gudev-1.0 Downloading libgudev source from https://gitlab.gnome.org/GNOME/libgudev/-/archive/238/libgudev-238.tar.bz2 HTTP Error 404: Not Found WARNING: failed to download with error: could not get https://gitlab.gnome.org/GNOME/libgudev/-/archive/238/libgudev-238.tar.bz2 is the internet available?. Trying after a delay... HTTP Error 404: Not Found WARNING: failed to download with error: could not get https://gitlab.gnome.org/GNOME/libgudev/-/archive/238/libgudev-238.tar.bz2 is the internet available?. Trying after a delay... HTTP Error 404: Not Found WARNING: failed to download with error: could not get https://gitlab.gnome.org/GNOME/libgudev/-/archive/238/libgudev-238.tar.bz2 is the internet available?. Trying after a delay... WARNING: failed to download with error: The read operation timed out. Trying after a delay... WARNING: failed to download with error: The read operation timed out. Trying after a delay... ERROR: Unhandled python OSError. This is probably not a Meson bug, but an issue with your build environment. ``` (cherry picked from commit 8a202de6ec763284cbb7160b9d43d5e7e0703f19) --- mesonbuild/wrap/wrap.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 4e98c600cf87..3fe40ed9f322 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -76,9 +76,9 @@ def open_wrapdburl(urlstring: str, allow_insecure: bool = False, have_opt: bool if has_ssl: try: return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(url), timeout=REQ_TIMEOUT)) - except urllib.error.URLError as excp: + except OSError as excp: msg = f'WrapDB connection failed to {urlstring} with error {excp}.' - if isinstance(excp.reason, ssl.SSLCertVerificationError): + if isinstance(excp, urllib.error.URLError) and isinstance(excp.reason, ssl.SSLCertVerificationError): if allow_insecure: mlog.warning(f'{msg}\n\n Proceeding without authentication.') else: @@ -95,7 +95,7 @@ def open_wrapdburl(urlstring: str, allow_insecure: bool = False, have_opt: bool nossl_url = url._replace(scheme='http') try: return T.cast('http.client.HTTPResponse', urllib.request.urlopen(urllib.parse.urlunparse(nossl_url), timeout=REQ_TIMEOUT)) - except urllib.error.URLError as excp: + except OSError as excp: raise WrapException(f'WrapDB connection failed to {urlstring} with error {excp}') def get_releases_data(allow_insecure: bool) -> bytes: @@ -704,7 +704,7 @@ def get_data(self, urlstring: str) -> T.Tuple[str, str]: try: req = urllib.request.Request(urlstring, headers=headers) resp = urllib.request.urlopen(req, timeout=REQ_TIMEOUT) - except urllib.error.URLError as e: + except OSError as e: mlog.log(str(e)) raise WrapException(f'could not get {urlstring} is the internet available?') with contextlib.closing(resp) as resp, tmpfile as tmpfile: From 0ee0780e79bd3c8cbbffafdb7c057667835e3f5a Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 13 Jul 2024 14:26:08 +0200 Subject: [PATCH 37/72] tests: try to fix ubuntu bionic tests by forcing an older nodejs (cherry picked from commit 9cc94a16ab837e85c47a818668b98a110fbabc48) --- .github/workflows/os_comp.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/os_comp.yml b/.github/workflows/os_comp.yml index 1d779842e27a..4fa4a87ed15d 100644 --- a/.github/workflows/os_comp.yml +++ b/.github/workflows/os_comp.yml @@ -26,6 +26,12 @@ on: - ".github/workflows/os_comp.yml" - "run*tests.py" +# make GHA actions use node16 which still works with bionic +# See https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/ +# Unclear how long this will work though +env: + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true + permissions: contents: read From d8165a1d1828cccdf15cec674195040b5da85bb8 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 12 Jul 2024 16:12:09 -0700 Subject: [PATCH 38/72] test/rust: Replace gcc -m argument with a -f argument -m arguments aren't portable across architectures. -fipa-pta will hopefully be portable for GCC, but also not implemented by clang. Fixes: #13417 (cherry picked from commit 44323fffead913d0a3c52647ba63a236924c7b78) --- test cases/rust/12 bindgen/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index 09cb02a6d319..57e44a0635c6 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -15,7 +15,7 @@ endif cc_id = meson.get_compiler('c').get_id() compiler_specific_args = [] if cc_id == 'gcc' - compiler_specific_args = ['-mtls-dialect=gnu2'] + compiler_specific_args = ['-fipa-pta'] elif cc_id == 'msvc' compiler_specific_args = ['/fp:fast'] endif From dbc7deee6709fe90f7c13c18ce08b2a16a364ac6 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Mon, 22 Jul 2024 14:32:52 -0400 Subject: [PATCH 39/72] Remove reference to GPL in test files We have permission to use that file. Fixes #13442. (cherry picked from commit fa70974a647db90864df4af6172cf7766f79857b) --- test cases/format/1 default/crazy_comments.meson | 2 +- test cases/format/2 muon/crazy_comments.meson | 2 +- test cases/format/3 editorconfig/crazy_comments.meson | 2 +- test cases/format/4 config/crazy_comments.meson | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test cases/format/1 default/crazy_comments.meson b/test cases/format/1 default/crazy_comments.meson index f391ca28c263..f7ed67101bfd 100644 --- a/test cases/format/1 default/crazy_comments.meson +++ b/test cases/format/1 default/crazy_comments.meson @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Stone Tickle -# SPDX-License-Identifier: GPL-3.0-only +# This file is used from muon sources, with permission project('a') diff --git a/test cases/format/2 muon/crazy_comments.meson b/test cases/format/2 muon/crazy_comments.meson index 5ebda7d63655..fe5ae1402df5 100644 --- a/test cases/format/2 muon/crazy_comments.meson +++ b/test cases/format/2 muon/crazy_comments.meson @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Stone Tickle -# SPDX-License-Identifier: GPL-3.0-only +# This file is used from muon sources, with permission project('a') diff --git a/test cases/format/3 editorconfig/crazy_comments.meson b/test cases/format/3 editorconfig/crazy_comments.meson index 788ea1c88dff..f9fdc8848d54 100644 --- a/test cases/format/3 editorconfig/crazy_comments.meson +++ b/test cases/format/3 editorconfig/crazy_comments.meson @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Stone Tickle -# SPDX-License-Identifier: GPL-3.0-only +# This file is used from muon sources, with permission project('a') diff --git a/test cases/format/4 config/crazy_comments.meson b/test cases/format/4 config/crazy_comments.meson index 557d5d409f65..71ae8f97fdd0 100644 --- a/test cases/format/4 config/crazy_comments.meson +++ b/test cases/format/4 config/crazy_comments.meson @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: Stone Tickle -# SPDX-License-Identifier: GPL-3.0-only +# This file is used from muon sources, with permission project('a') From 2c9f27b459332de2aeceb6b57b470f617b3da7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannik=20Gl=C3=BCckert?= Date: Mon, 22 Jul 2024 00:17:32 +0200 Subject: [PATCH 40/72] coverage: improve llvm-cov detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jannik Glückert (cherry picked from commit 6258f0dc86188570e7d00316557bfb85948ed290) --- mesonbuild/environment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 74c482382264..5bccb903d48e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -148,6 +148,9 @@ def find_coverage_tools(coredata: coredata.CoreData) -> T.Tuple[T.Optional[str], gcovr_exe, gcovr_version = detect_gcovr() llvm_cov_exe = detect_llvm_cov(compute_llvm_suffix(coredata)) + # Some platforms may provide versioned clang but only non-versioned llvm utils + if llvm_cov_exe is None: + llvm_cov_exe = detect_llvm_cov('') lcov_exe, lcov_version, genhtml_exe = detect_lcov_genhtml() From 730ccbc82b1c0fff41925fa6008c327c2c30be73 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 23 Jul 2024 17:42:27 -0400 Subject: [PATCH 41/72] CI: skip LTO tests on cygwin A GCC update broke this and is being investigated Bug: #13465 (cherry picked from commit 0c93149f09bbeedd03c70abc7b6d652b8e9ee9fa) --- unittests/allplatformstests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index e912e943977e..f471f6a95f46 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1336,6 +1336,7 @@ def test_source_generator_program_cause_rebuild(self): self.utime(os.path.join(testdir, 'srcgen.py')) self.assertRebuiltTarget('basic') + @skipIf(is_ci() and is_cygwin(), 'A GCC update on 2024-07-21 has broken LTO and is being investigated') def test_static_library_lto(self): ''' Test that static libraries can be built with LTO and linked to @@ -1352,6 +1353,7 @@ def test_static_library_lto(self): self.build() self.run_tests() + @skipIf(is_ci() and is_cygwin(), 'A GCC update on 2024-07-21 has broken LTO and is being investigated') @skip_if_not_base_option('b_lto_threads') def test_lto_threads(self): testdir = os.path.join(self.common_test_dir, '6 linkshared') From 4df12546c9894bb35c632007173f7c70b3a5ba51 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 11 Jul 2024 10:18:34 -0500 Subject: [PATCH 42/72] Fix failing tests for zlib-ng Fedora, at the very least, now packages zlib-ng as zlib. This means the version reported for the dependency is now X.Y.Z.zlib-ng by pkgconfig whereas the test expected X.Y.Z. Make the version check work for both regular zlib and zlib-ng. (cherry picked from commit b1f4e1495d4f03f4ef68d59535bd954686def3af) --- .../linuxlike/1 pkg-config/prog-checkver.c | 29 ++++++++++++++++++- .../13 cmake dependency/prog-checkver.c | 29 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/test cases/linuxlike/1 pkg-config/prog-checkver.c b/test cases/linuxlike/1 pkg-config/prog-checkver.c index ea1ed32f4ffa..fe705d45da99 100644 --- a/test cases/linuxlike/1 pkg-config/prog-checkver.c +++ b/test cases/linuxlike/1 pkg-config/prog-checkver.c @@ -1,11 +1,38 @@ #include +#include #include #include +static bool check_version(const char *zlib_ver, const char *found_zlib) { +#ifdef ZLIBNG_VERSION + const char *ptr = strstr(zlib_ver, found_zlib); + + // If the needle isn't found or the needle isn't at the start, fail. + if (ptr == NULL || ptr != zlib_ver) + return false; + + /* In zlib-ng, ZLIB_VERSION is of the form X.Y.Z.zlib-ng. This will move the + * pointer to the start of the suffix, .zlib-ng. We know that at this point + * that FOUND_ZLIB is the start of ZLIB_VERSION, so compare the rest. + */ + ptr += strlen(found_zlib); + if (strcmp(ptr, ".zlib-ng") != 0) + return false; +#else + if (strcmp(zlib_ver, found_zlib) != 0) + return false; +#endif + + return true; +} + int main(void) { void * something = deflate; - if(strcmp(ZLIB_VERSION, FOUND_ZLIB) != 0) { + if (!check_version(ZLIB_VERSION, FOUND_ZLIB)) { printf("Meson found '%s' but zlib is '%s'\n", FOUND_ZLIB, ZLIB_VERSION); +#ifdef ZLIBNG_VERSION + puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected\n"); +#endif return 2; } if(something != 0) diff --git a/test cases/linuxlike/13 cmake dependency/prog-checkver.c b/test cases/linuxlike/13 cmake dependency/prog-checkver.c index ea1ed32f4ffa..fe705d45da99 100644 --- a/test cases/linuxlike/13 cmake dependency/prog-checkver.c +++ b/test cases/linuxlike/13 cmake dependency/prog-checkver.c @@ -1,11 +1,38 @@ #include +#include #include #include +static bool check_version(const char *zlib_ver, const char *found_zlib) { +#ifdef ZLIBNG_VERSION + const char *ptr = strstr(zlib_ver, found_zlib); + + // If the needle isn't found or the needle isn't at the start, fail. + if (ptr == NULL || ptr != zlib_ver) + return false; + + /* In zlib-ng, ZLIB_VERSION is of the form X.Y.Z.zlib-ng. This will move the + * pointer to the start of the suffix, .zlib-ng. We know that at this point + * that FOUND_ZLIB is the start of ZLIB_VERSION, so compare the rest. + */ + ptr += strlen(found_zlib); + if (strcmp(ptr, ".zlib-ng") != 0) + return false; +#else + if (strcmp(zlib_ver, found_zlib) != 0) + return false; +#endif + + return true; +} + int main(void) { void * something = deflate; - if(strcmp(ZLIB_VERSION, FOUND_ZLIB) != 0) { + if (!check_version(ZLIB_VERSION, FOUND_ZLIB)) { printf("Meson found '%s' but zlib is '%s'\n", FOUND_ZLIB, ZLIB_VERSION); +#ifdef ZLIBNG_VERSION + puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected\n"); +#endif return 2; } if(something != 0) From 808730a32c0f21200c91be329f58c816c54d0324 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Tue, 16 Jul 2024 10:02:34 -0500 Subject: [PATCH 43/72] Fix the zlib-ng failing tests, for real I failed to properly account for the case in which the two string are completely equal. (cherry picked from commit 4b31974ec5d73afd8deb5b89b35ad917ebef05ba) --- .../linuxlike/1 pkg-config/prog-checkver.c | 17 ++++++++++------- .../13 cmake dependency/prog-checkver.c | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/test cases/linuxlike/1 pkg-config/prog-checkver.c b/test cases/linuxlike/1 pkg-config/prog-checkver.c index fe705d45da99..14d574642923 100644 --- a/test cases/linuxlike/1 pkg-config/prog-checkver.c +++ b/test cases/linuxlike/1 pkg-config/prog-checkver.c @@ -4,6 +4,12 @@ #include static bool check_version(const char *zlib_ver, const char *found_zlib) { + if (zlib_ver == found_zlib) + return true; + + if (strcmp(zlib_ver, found_zlib) == 0) + return true; + #ifdef ZLIBNG_VERSION const char *ptr = strstr(zlib_ver, found_zlib); @@ -16,14 +22,11 @@ static bool check_version(const char *zlib_ver, const char *found_zlib) { * that FOUND_ZLIB is the start of ZLIB_VERSION, so compare the rest. */ ptr += strlen(found_zlib); - if (strcmp(ptr, ".zlib-ng") != 0) - return false; -#else - if (strcmp(zlib_ver, found_zlib) != 0) - return false; + if (strcmp(ptr, ".zlib-ng") == 0) + return true; #endif - return true; + return false; } int main(void) { @@ -31,7 +34,7 @@ int main(void) { if (!check_version(ZLIB_VERSION, FOUND_ZLIB)) { printf("Meson found '%s' but zlib is '%s'\n", FOUND_ZLIB, ZLIB_VERSION); #ifdef ZLIBNG_VERSION - puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected\n"); + puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected"); #endif return 2; } diff --git a/test cases/linuxlike/13 cmake dependency/prog-checkver.c b/test cases/linuxlike/13 cmake dependency/prog-checkver.c index fe705d45da99..14d574642923 100644 --- a/test cases/linuxlike/13 cmake dependency/prog-checkver.c +++ b/test cases/linuxlike/13 cmake dependency/prog-checkver.c @@ -4,6 +4,12 @@ #include static bool check_version(const char *zlib_ver, const char *found_zlib) { + if (zlib_ver == found_zlib) + return true; + + if (strcmp(zlib_ver, found_zlib) == 0) + return true; + #ifdef ZLIBNG_VERSION const char *ptr = strstr(zlib_ver, found_zlib); @@ -16,14 +22,11 @@ static bool check_version(const char *zlib_ver, const char *found_zlib) { * that FOUND_ZLIB is the start of ZLIB_VERSION, so compare the rest. */ ptr += strlen(found_zlib); - if (strcmp(ptr, ".zlib-ng") != 0) - return false; -#else - if (strcmp(zlib_ver, found_zlib) != 0) - return false; + if (strcmp(ptr, ".zlib-ng") == 0) + return true; #endif - return true; + return false; } int main(void) { @@ -31,7 +34,7 @@ int main(void) { if (!check_version(ZLIB_VERSION, FOUND_ZLIB)) { printf("Meson found '%s' but zlib is '%s'\n", FOUND_ZLIB, ZLIB_VERSION); #ifdef ZLIBNG_VERSION - puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected\n"); + puts("Note that in the case of zlib-ng, a version suffix of .zlib-ng is expected"); #endif return 2; } From b6b634ad33e5ca9ad4a9d6139dba4244847cc0e8 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Jul 2024 16:15:33 -0400 Subject: [PATCH 44/72] Bump versions to 1.5.1 for release --- man/meson.1 | 4 ++-- mesonbuild/coredata.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/meson.1 b/man/meson.1 index b6ceb2a27fbe..589bba271246 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "July 2024" "meson 1.5.0" "User Commands" +.TH MESON "1" "July 2024" "meson 1.5.1" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION @@ -410,7 +410,7 @@ Manage the packagefiles overlay .B meson rewrite modifies the project definition. - + .B meson rewrite [ .I options .B ] [ diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 90667e8fc6d0..bbe4af7cfced 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -72,7 +72,7 @@ class SharedCMDOptions(Protocol): # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.5.0' +version = '1.5.1' # The next stable version when we are in dev. This is used to allow projects to # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when From 3f0f62da0b63eda3b1dca33aa9919e83283dc1bb Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 29 Jul 2024 11:00:54 -0400 Subject: [PATCH 45/72] mdist: correctly detect dirty hg repos with non-English locale The command we use to heuristically parse whether it is dirty by interpreting prose descriptions of the repository state, is vulnerable to changes in locale resulting in failing to match the English word that means it is clean. Unfortunately, I am no mercurial expert so I am unaware if mercurial supports scripting, like git does. Perhaps the technology simply does not exist. A quick attempt at searching for the answer turned nothing up. It appears that #4278 had good cause indeed for using this prose parsing command. So, we simply sanitize the environment due to lack of any better idea. Bug: https://bugs.gentoo.org/936670 (cherry picked from commit a05b790d6600586449471d3fe957442896dec2a7) --- mesonbuild/mdist.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index c29020068d9b..26ea7887c314 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -222,7 +222,9 @@ def create_dist(self, archives: T.List[str]) -> T.List[str]: class HgDist(Dist): def have_dirty_index(self) -> bool: '''Check whether there are uncommitted changes in hg''' - out = subprocess.check_output(['hg', '-R', self.src_root, 'summary']) + env = os.environ.copy() + env['LC_ALL'] = 'C' + out = subprocess.check_output(['hg', '-R', self.src_root, 'summary'], env=env) return b'commit: (clean)' not in out def create_dist(self, archives: T.List[str]) -> T.List[str]: From 38f542d881bb4c2883a86db48b997fdd530d95ee Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 29 Jul 2024 21:22:37 -0400 Subject: [PATCH 46/72] tests: nasm: make it easier to debug generator() style build By default, we build with debug info which can be useful for investigating why a test segfaults instead of either passing or failing. The nasm language hooks this up, but using nasm as a generator program does not. Bug: https://bugs.gentoo.org/936911 (cherry picked from commit 03a8f35031c9ae0ded162f8b228c5b3f04643632) --- test cases/nasm/1 configure file/meson.build | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test cases/nasm/1 configure file/meson.build b/test cases/nasm/1 configure file/meson.build index fac46a687331..abe7bb30f98c 100644 --- a/test cases/nasm/1 configure file/meson.build +++ b/test cases/nasm/1 configure file/meson.build @@ -24,10 +24,16 @@ conf = configuration_data() conf.set('HELLO', 0) +debug_nasm = [] +if get_option('debug') + debug_nasm = ['-g'] +endif + asm_gen = generator(nasm, output : '@BASENAME@.o', arguments : [ '-f', asm_format, + debug_nasm, '-i', meson.current_source_dir() + '/', '-i', join_paths(meson.current_source_dir(), ''), '-P', join_paths(meson.current_build_dir(), 'config.asm'), From 2058ad3701400eac461398c0c34531d8f17eb1fb Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 1 Aug 2024 11:44:59 -0400 Subject: [PATCH 47/72] mformat: fix formatting of empty build file Running meson format multiple times on an empty file was adding a new line each time, which is bad for pre-commit checks... (cherry picked from commit fa4f2339465ce3d755e2df802ebd5aa962e2ad27) --- mesonbuild/mformat.py | 2 ++ unittests/platformagnostictests.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 42f562e7f278..606d9d2eccfe 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -396,6 +396,8 @@ def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: if node.lines: self.move_whitespaces(node.lines[-1], node) else: + node.whitespaces.value = node.pre_whitespaces.value + node.whitespaces.value + node.pre_whitespaces.value = '' node.whitespaces.accept(self) if node.condition_level == 0 and self.config.insert_final_newline: diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index fe598a72bb80..d0d2349578bf 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -16,7 +16,7 @@ from .baseplatformtests import BasePlatformTests from .helpers import is_ci from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, MesonException, is_linux, python_command -from mesonbuild.mformat import match_path +from mesonbuild.mformat import Formatter, match_path from mesonbuild.optinterpreter import OptionInterpreter, OptionException from run_tests import Backend @@ -333,7 +333,13 @@ def test_editorconfig_match_path(self): for filename, pattern, expected in cases: self.assertTrue(match_path(filename, pattern) is expected, f'{filename} -> {pattern}') - + + def test_format_empty_file(self) -> None: + formatter = Formatter(None, use_editor_config=False, fetch_subdirs=False) + for code in ('', '\n'): + formatted = formatter.format(code, Path()) + self.assertEqual('\n', formatted) + def test_error_configuring_subdir(self): testdir = os.path.join(self.common_test_dir, '152 index customtarget') out = self.init(os.path.join(testdir, 'subdir'), allow_fail=True) From b0b6e546e062b3a13d416d7552a7a34acb3f3f21 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Sun, 4 Aug 2024 14:55:33 +0200 Subject: [PATCH 48/72] Fix compiling ObjC/ObjC++ on Windows/MinGW Co-Authored-By: L. E. Segovia (cherry picked from commit 81b151f61138357950330f26b601e0b345bf77fa) --- mesonbuild/cmake/toolchain.py | 2 ++ mesonbuild/compilers/detect.py | 4 ++-- mesonbuild/compilers/mixins/clang.py | 2 ++ mesonbuild/compilers/mixins/visualstudio.py | 2 ++ mesonbuild/linkers/linkers.py | 3 +++ test cases/cmake/24 mixing languages/meson.build | 6 ++++++ .../24 mixing languages/subprojects/cmTest/CMakeLists.txt | 2 +- test cases/objc/1 simple/meson.build | 4 ++++ test cases/objc/2 nsstring/meson.build | 4 ++++ test cases/objc/3 objc args/meson.build | 4 ++++ test cases/objc/4 c++ project objc subproject/meson.build | 4 ++++ .../subprojects/foo/meson.build | 4 ++++ test cases/objc/5 objfw/meson.build | 4 ++++ test cases/objcpp/1 simple/meson.build | 4 ++++ test cases/objcpp/2 objc++ args/meson.build | 4 ++++ test cases/objcpp/3 objfw/meson.build | 4 ++++ 16 files changed, 54 insertions(+), 3 deletions(-) diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py index 1aad0bc3b5bc..89d5d84449e0 100644 --- a/mesonbuild/cmake/toolchain.py +++ b/mesonbuild/cmake/toolchain.py @@ -188,6 +188,8 @@ def make_abs(exe: str) -> str: defaults[prefix + 'COMPILER'] = exe_list if comp_obj.get_id() == 'clang-cl': defaults['CMAKE_LINKER'] = comp_obj.get_linker_exelist() + if lang.startswith('objc') and comp_obj.get_id().startswith('clang'): + defaults[f'{prefix}FLAGS'] = ['-D__STDC__=1'] return defaults diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 3a678211c5a1..c8b67f479471 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -46,8 +46,8 @@ # There is currently no pgc++ for Windows, only for Mac and Linux. defaults['cpp'] = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl'] defaults['fortran'] = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95'] - defaults['objc'] = ['clang-cl', 'gcc'] - defaults['objcpp'] = ['clang-cl', 'g++'] + defaults['objc'] = ['clang', 'clang-cl', 'gcc'] + defaults['objcpp'] = ['clang-cl', 'clang-cl', 'g++'] defaults['cs'] = ['csc', 'mcs'] else: if platform.machine().lower() == 'e2k': diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index a799e06a3c8e..d99dc3abf9f9 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -58,6 +58,8 @@ def __init__(self, defines: T.Optional[T.Dict[str, str]]): # linkers don't have base_options. if isinstance(self.linker, AppleDynamicLinker): self.base_options.add(OptionKey('b_bitcode')) + elif isinstance(self.linker, MSVCDynamicLinker): + self.base_options.add(OptionKey('b_vscrt')) # All Clang backends can also do LLVM IR self.can_compile_suffixes.add('ll') diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 907ea07f0c7b..bdf293bd010f 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -381,6 +381,8 @@ def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: # As a last resort, try search in a compiled binary return self._symbols_have_underscore_prefix_searchbin(env) + def get_pie_args(self) -> T.List[str]: + return [] class MSVCCompiler(VisualStudioLikeCompiler): diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index c3750ccc372f..fc9d9cd69af6 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1324,6 +1324,9 @@ def import_library_args(self, implibname: str) -> T.List[str]: def rsp_file_syntax(self) -> RSPFileSyntax: return RSPFileSyntax.MSVC + def get_pie_args(self) -> T.List[str]: + return [] + class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): diff --git a/test cases/cmake/24 mixing languages/meson.build b/test cases/cmake/24 mixing languages/meson.build index 55d7a7d68bc9..a4662fe37c0c 100644 --- a/test cases/cmake/24 mixing languages/meson.build +++ b/test cases/cmake/24 mixing languages/meson.build @@ -7,6 +7,12 @@ if not add_languages('objc', required : false) error('MESON_SKIP_TEST: No ObjC compiler') endif +objc = meson.get_compiler('objc') +c = meson.get_compiler('c') +if c.get_argument_syntax() != objc.get_argument_syntax() + error('MESON_SKIP_TEST: cmake cannot mix compiler types on Windows') +endif + cm = import('cmake') sub_pro = cm.subproject('cmTest') diff --git a/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt b/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt index 80a256f0db1d..a1886115bf5f 100644 --- a/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt +++ b/test cases/cmake/24 mixing languages/subprojects/cmTest/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(cmTest) +project(cmTest LANGUAGES C OBJC) include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/test cases/objc/1 simple/meson.build b/test cases/objc/1 simple/meson.build index f9d5c145025e..bb45839f184f 100644 --- a/test cases/objc/1 simple/meson.build +++ b/test cases/objc/1 simple/meson.build @@ -1,4 +1,8 @@ project('objective c', 'objc', default_options: ['c_std=c99']) +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + exe = executable('prog', 'prog.m') test('objctest', exe) diff --git a/test cases/objc/2 nsstring/meson.build b/test cases/objc/2 nsstring/meson.build index 2c483d50d687..b12710d73f71 100644 --- a/test cases/objc/2 nsstring/meson.build +++ b/test cases/objc/2 nsstring/meson.build @@ -1,5 +1,9 @@ project('nsstring', 'objc') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + if host_machine.system() == 'darwin' dep = dependency('appleframeworks', modules : 'Foundation') elif host_machine.system() == 'cygwin' diff --git a/test cases/objc/3 objc args/meson.build b/test cases/objc/3 objc args/meson.build index 8887d96bc7ac..dd6f50990b31 100644 --- a/test cases/objc/3 objc args/meson.build +++ b/test cases/objc/3 objc args/meson.build @@ -1,4 +1,8 @@ project('objective c args', 'objc') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + exe = executable('prog', 'prog.m', objc_args : ['-DMESON_TEST']) test('objective c args', exe) diff --git a/test cases/objc/4 c++ project objc subproject/meson.build b/test cases/objc/4 c++ project objc subproject/meson.build index 8a77dedce3c4..946af11f603b 100644 --- a/test cases/objc/4 c++ project objc subproject/meson.build +++ b/test cases/objc/4 c++ project objc subproject/meson.build @@ -1,5 +1,9 @@ project('master', ['cpp']) +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + foo = subproject('foo') dep = foo.get_variable('foo_dep') diff --git a/test cases/objc/4 c++ project objc subproject/subprojects/foo/meson.build b/test cases/objc/4 c++ project objc subproject/subprojects/foo/meson.build index 2dbf8ab26764..5f4d9fd836ba 100644 --- a/test cases/objc/4 c++ project objc subproject/subprojects/foo/meson.build +++ b/test cases/objc/4 c++ project objc subproject/subprojects/foo/meson.build @@ -1,5 +1,9 @@ project('foo', ['objc']) +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + l = static_library('foo', 'foo.m') foo_dep = declare_dependency(link_with : l) diff --git a/test cases/objc/5 objfw/meson.build b/test cases/objc/5 objfw/meson.build index 40ddb7968db4..761b49f67e9c 100644 --- a/test cases/objc/5 objfw/meson.build +++ b/test cases/objc/5 objfw/meson.build @@ -1,5 +1,9 @@ project('objfw build tests', 'objc') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objc is not supported by vs backend') +endif + objfw_dep = dependency('objfw', required: false) objfwtest_dep = dependency('objfw', modules: ['ObjFWTest'], required: false) diff --git a/test cases/objcpp/1 simple/meson.build b/test cases/objcpp/1 simple/meson.build index c9a5c8498195..c3acc879ad1e 100644 --- a/test cases/objcpp/1 simple/meson.build +++ b/test cases/objcpp/1 simple/meson.build @@ -1,4 +1,8 @@ project('Objective C++', 'objcpp', default_options: 'cpp_std=c++14') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objcpp is not supported by vs backend') +endif + exe = executable('objcppprog', 'prog.mm') test('objcpp', exe) diff --git a/test cases/objcpp/2 objc++ args/meson.build b/test cases/objcpp/2 objc++ args/meson.build index e0e34b0f1e17..8797b619d3e8 100644 --- a/test cases/objcpp/2 objc++ args/meson.build +++ b/test cases/objcpp/2 objc++ args/meson.build @@ -1,4 +1,8 @@ project('objective c++ args', 'objcpp') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objcpp is not supported by vs backend') +endif + exe = executable('prog', 'prog.mm', objcpp_args : ['-DMESON_OBJCPP_TEST']) test('objective c++ args', exe) diff --git a/test cases/objcpp/3 objfw/meson.build b/test cases/objcpp/3 objfw/meson.build index da14681ebf1a..3fcc84dd554b 100644 --- a/test cases/objcpp/3 objfw/meson.build +++ b/test cases/objcpp/3 objfw/meson.build @@ -1,5 +1,9 @@ project('objfw build tests', 'objcpp') +if get_option('backend').startswith('vs') + error('MESON_SKIP_TEST: objcpp is not supported by vs backend') +endif + objfw_dep = dependency('objfw', required: false) objfwtest_dep = dependency('objfw', modules: ['ObjFWTest'], required: false) From 0a7e91efacb2e7f434da19437a532887694a6605 Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Thu, 15 Aug 2024 19:44:08 +0800 Subject: [PATCH 49/72] compilers: do not strip '-isystem' from C build arguments Meson accidentally strips '-isystem' from C build args like ['-isystem', '/path/to/headers'] if the compiler includes the current working directory in the header search paths. The root cause is that '-isystem'[8:] evaluates to an empty string and os.path.realpath('') returns the absolute path to the current working directory, causing meson to think that '-isystem' specifies a default include path. Different compiler versions varies whether the current working directory is in its search paths. For example, on Ubuntu 21.04: # gcc -xc -v -E - gcc version 10.3.0 (Ubuntu 10.3.0-1ubuntu1) #include "..." search starts here: #include <...> search starts here: . /usr/lib/gcc/x86_64-linux-gnu/10/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include End of search list. While on Ubuntu 24.04: # gcc -xc -v -E - gcc version 13.2.0 (Ubuntu 13.2.0-23ubuntu4) ... #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/13/include /usr/local/include /usr/include/x86_64-linux-gnu /usr/include End of search list. Do not check the '-isystem=' and '-isystem/path/to/header' cases when the option is '-isystem' but the path that follows is not a default search path. Signed-off-by: Junjie Mao (cherry picked from commit 85e92331cba16f038115be241e87634f69f74e78) --- mesonbuild/compilers/mixins/clike.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 1fddb0f95dd1..70613944fcbf 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -98,12 +98,12 @@ def to_native(self, copy: bool = False) -> T.List[str]: continue # Remove the -isystem and the path if the path is a default path - if (each == '-isystem' and - i < (len(new) - 1) and - self._cached_realpath(new[i + 1]) in real_default_dirs): - bad_idx_list += [i, i + 1] - elif each.startswith('-isystem=') and self._cached_realpath(each[9:]) in real_default_dirs: - bad_idx_list += [i] + if each == '-isystem': + if i < (len(new) - 1) and self._cached_realpath(new[i + 1]) in real_default_dirs: + bad_idx_list += [i, i + 1] + elif each.startswith('-isystem='): + if self._cached_realpath(each[9:]) in real_default_dirs: + bad_idx_list += [i] elif self._cached_realpath(each[8:]) in real_default_dirs: bad_idx_list += [i] for i in reversed(bad_idx_list): From 52b6e8a19024a2a4347b10fb8c499815e11be292 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 15 Aug 2024 09:13:20 -0400 Subject: [PATCH 50/72] cargo: Ignore Cargo.lock if toml implementation is missing It is only required if a Cargo subproject is actually configured. (cherry picked from commit 42a4d1aaa0854d376e9d28cf4b6ca93df90c8213) --- mesonbuild/cargo/interpreter.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 33b9d6073e4b..029e5a1b8006 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -54,13 +54,17 @@ toml2json = shutil.which('toml2json') +class TomlImplementationMissing(MesonException): + pass + + def load_toml(filename: str) -> T.Dict[object, object]: if tomllib: with open(filename, 'rb') as f: raw = tomllib.load(f) else: if toml2json is None: - raise MesonException('Could not find an implementation of tomllib, nor toml2json') + raise TomlImplementationMissing('Could not find an implementation of tomllib, nor toml2json') p, out, err = Popen_safe([toml2json, filename]) if p.returncode != 0: @@ -741,7 +745,11 @@ def load_wraps(source_dir: str, subproject_dir: str) -> T.List[PackageDefinition wraps: T.List[PackageDefinition] = [] filename = os.path.join(source_dir, 'Cargo.lock') if os.path.exists(filename): - cargolock = T.cast('manifest.CargoLock', load_toml(filename)) + try: + cargolock = T.cast('manifest.CargoLock', load_toml(filename)) + except TomlImplementationMissing as e: + mlog.warning('Failed to load Cargo.lock:', str(e), fatal=False) + return wraps for package in cargolock['package']: name = package['name'] version = package['version'] From 7e9738133143ec809219bade06e3f88bd93f8f7a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 19 Aug 2024 14:18:04 -0700 Subject: [PATCH 51/72] mformat: correctly handle editorconfig files without the root setting Which happens when a .editorconfig is in a subdirectory, not the root. In this case we need Set the fallback value to `False`, which is what editorconfig expects. Closes: #13568 (cherry picked from commit 18f4a058bf7e4b7eb32553b10fe3a37e1c22aa15) --- mesonbuild/mformat.py | 3 ++- test cases/format/3 editorconfig/meson.build | 1 + test cases/format/3 editorconfig/subdir/.editorconfig | 2 ++ test cases/format/3 editorconfig/subdir/sub.meson | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test cases/format/3 editorconfig/subdir/.editorconfig create mode 100644 test cases/format/3 editorconfig/subdir/sub.meson diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 606d9d2eccfe..f58332b9b3a4 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -823,7 +823,8 @@ def load_editor_config(self, source_file: Path) -> EditorConfig: if value is not None: setattr(config, f.name, value) - if cp.getboolean(cp.default_section, 'root'): + # Root is not required except in the top level .editorconfig. + if cp.getboolean(cp.default_section, 'root', fallback=False): break return config diff --git a/test cases/format/3 editorconfig/meson.build b/test cases/format/3 editorconfig/meson.build index b32974cb9e8e..2468411493c3 100644 --- a/test cases/format/3 editorconfig/meson.build +++ b/test cases/format/3 editorconfig/meson.build @@ -7,6 +7,7 @@ meson_files = { 'self': files('meson.build'), 'comments': files('crazy_comments.meson'), 'indentation': files('indentation.meson'), + 'subdir editorconfig': files('subdir/sub.meson'), } foreach name, f : meson_files diff --git a/test cases/format/3 editorconfig/subdir/.editorconfig b/test cases/format/3 editorconfig/subdir/.editorconfig new file mode 100644 index 000000000000..fac7a92caaba --- /dev/null +++ b/test cases/format/3 editorconfig/subdir/.editorconfig @@ -0,0 +1,2 @@ +[*] +max_line_length = 120 diff --git a/test cases/format/3 editorconfig/subdir/sub.meson b/test cases/format/3 editorconfig/subdir/sub.meson new file mode 100644 index 000000000000..623ca2836a9c --- /dev/null +++ b/test cases/format/3 editorconfig/subdir/sub.meson @@ -0,0 +1,3 @@ +project('line') + +msg = 'this is a very long line, and it should be be wrapped because we have line length limit of 120, not 60' From 4da5bc980497fc5689bd1bffb9d68d1fb4130c77 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 6 Aug 2024 10:15:33 -0400 Subject: [PATCH 52/72] format: fix indentation of comments Fixes #13508 - Fix indentation of comments in arrays - Fix indentation of comments in dicts - Fix indentation of comments in if clauses - Fix indentation of comments in foreach clauses (cherry picked from commit d9ba42217f49c4bd4caeac9050cc475e3453f75e) --- mesonbuild/mformat.py | 31 ++++++++++++++++--- mesonbuild/mparser.py | 1 + test cases/format/1 default/indentation.meson | 17 ++++++++++ unittests/platformagnostictests.py | 15 +++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index f58332b9b3a4..2746eff6924b 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -372,6 +372,8 @@ def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: if node.args.arguments and not node.args.is_multiline and self.config.space_array: self.add_space_after(node.lbracket) self.add_space_after(node.args) + if not node.args.arguments: + self.move_whitespaces(node.lbracket, node.args) def visit_DictNode(self, node: mparser.DictNode) -> None: super().visit_DictNode(node) @@ -388,6 +390,7 @@ def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: self.in_block_comments = False else: node.pre_whitespaces = mparser.WhitespaceNode(mparser.Token('whitespace', node.filename, 0, 0, 0, (0, 0), '')) + node.pre_whitespaces.block_indent = True for i in node.lines: i.accept(self) @@ -398,7 +401,9 @@ def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: else: node.whitespaces.value = node.pre_whitespaces.value + node.whitespaces.value node.pre_whitespaces.value = '' + self.in_block_comments = True node.whitespaces.accept(self) + self.in_block_comments = False if node.condition_level == 0 and self.config.insert_final_newline: self.add_nl_after(node, force=True) @@ -453,6 +458,7 @@ def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self.add_space_after(node.colon) node.block.whitespaces.value += node.condition_level * self.config.indent_by + node.block.whitespaces.block_indent = True self.move_whitespaces(node.endforeach, node) @@ -468,11 +474,19 @@ def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: def visit_IfNode(self, node: mparser.IfNode) -> None: super().visit_IfNode(node) self.add_space_after(node.if_) + self.in_block_comments = True self.move_whitespaces(node.block, node) + self.in_block_comments = False + node.whitespaces.condition_level = node.condition_level + 1 + node.whitespaces.block_indent = True def visit_ElseNode(self, node: mparser.ElseNode) -> None: super().visit_ElseNode(node) + self.in_block_comments = True self.move_whitespaces(node.block, node) + self.in_block_comments = False + node.whitespaces.condition_level = node.condition_level + 1 + node.whitespaces.block_indent = True def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: super().visit_TernaryNode(node) @@ -554,22 +568,28 @@ def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self.enter_node(node) if node.args.is_multiline: self.level += 1 - self.add_nl_after(node.lbracket, indent=self.level) + if node.args.arguments: + self.add_nl_after(node.lbracket, indent=self.level) + node.lbracket.accept(self) self.is_function_arguments = False node.args.accept(self) if node.args.is_multiline: self.level -= 1 + node.rbracket.accept(self) self.exit_node(node) def visit_DictNode(self, node: mparser.DictNode) -> None: self.enter_node(node) if node.args.is_multiline: self.level += 1 - self.add_nl_after(node.lcurl, indent=self.level) + if node.args.kwargs: + self.add_nl_after(node.lcurl, indent=self.level) + node.lcurl.accept(self) self.is_function_arguments = False node.args.accept(self) if node.args.is_multiline: self.level -= 1 + node.rcurl.accept(self) self.exit_node(node) def visit_MethodNode(self, node: mparser.MethodNode) -> None: @@ -599,8 +619,8 @@ def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: lines = node.value.splitlines(keepends=True) if lines: indent = (node.condition_level + self.level) * self.config.indent_by - node.value = lines[0] - for line in lines[1:]: + node.value = '' if node.block_indent else lines.pop(0) + for line in lines: if '#' in line and not line.startswith(indent): node.value += indent node.value += line @@ -650,7 +670,8 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: for comma in node.commas[arg_index:-1]: self.add_nl_after(comma, self.level) - self.add_nl_after(node, self.level - 1) + if node.arguments or node.kwargs: + self.add_nl_after(node, self.level - 1) else: if has_trailing_comma and not (node.commas[-1].whitespaces and node.commas[-1].whitespaces.value): diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 50d720313495..fc37d2a54e2b 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -266,6 +266,7 @@ def __init__(self, token: Token[str]): super().__init__(token.lineno, token.colno, token.filename) self.value = '' self.append(token) + self.block_indent = False def append(self, token: Token[str]) -> None: self.value += token.value diff --git a/test cases/format/1 default/indentation.meson b/test cases/format/1 default/indentation.meson index b1edc3a16a52..fe78847f7667 100644 --- a/test cases/format/1 default/indentation.meson +++ b/test cases/format/1 default/indentation.meson @@ -11,7 +11,10 @@ project( ) a = [ + # comment + # comment 1, + # comment 2, 3, [ @@ -36,8 +39,13 @@ a = [ d = {} if meson.project_version().version_compare('>1.2') + # comment + # comment if meson.version().version_compare('>1.0') + # comment + # comment foreach i : a + # comment e = { 'a': 'a', 'b': 'b', @@ -69,9 +77,18 @@ if meson.project_version().version_compare('>1.2') ], } endforeach + + foreach j : a + # comment + # comment + # comment + endforeach elif 42 in d d += {'foo': 43} else # ensure else is correctly indented (issue #13316) + # comment k = 'k' + # comment + # comment endif endif diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index d0d2349578bf..ebd4ca5210b5 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -339,6 +339,21 @@ def test_format_empty_file(self) -> None: for code in ('', '\n'): formatted = formatter.format(code, Path()) self.assertEqual('\n', formatted) + + def test_format_indent_comment_in_brackets(self) -> None: + """Ensure comments in arrays and dicts are correctly indented""" + formatter = Formatter(None, use_editor_config=False, fetch_subdirs=False) + code = 'a = [\n # comment\n]\n' + formatted = formatter.format(code, Path()) + self.assertEqual(code, formatted) + + code = 'a = [\n # comment\n 1,\n]\n' + formatted = formatter.format(code, Path()) + self.assertEqual(code, formatted) + + code = 'a = {\n # comment\n}\n' + formatted = formatter.format(code, Path()) + self.assertEqual(code, formatted) def test_error_configuring_subdir(self): testdir = os.path.join(self.common_test_dir, '152 index customtarget') From 1a529a26eeef4386ee09c5c43710d0092c0baab2 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 17 Aug 2024 22:47:31 +0200 Subject: [PATCH 53/72] linkers: skip -export_dynamic flag before MacOS 10.7 The flag was only introduced in ld 224.1, as mentioned in the initial PR #13291. Resolves #13543 (cherry picked from commit 7280639cb5967beefa85b561dcbd096bcf05db3d) --- mesonbuild/linkers/linkers.py | 4 +++- unittests/darwintests.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index fc9d9cd69af6..4eec82edd177 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -837,7 +837,9 @@ def get_thinlto_cache_args(self, path: str) -> T.List[str]: return ["-Wl,-cache_path_lto," + path] def export_dynamic_args(self, env: 'Environment') -> T.List[str]: - return self._apply_prefix('-export_dynamic') + if mesonlib.version_compare(self.version, '>=224.1'): + return self._apply_prefix('-export_dynamic') + return [] class LLVMLD64DynamicLinker(AppleDynamicLinker): diff --git a/unittests/darwintests.py b/unittests/darwintests.py index afc663a57ae1..26dd996415af 100644 --- a/unittests/darwintests.py +++ b/unittests/darwintests.py @@ -4,10 +4,11 @@ import subprocess import re import os +import platform import unittest from mesonbuild.mesonlib import ( - MachineChoice, is_osx + MachineChoice, is_osx, version_compare ) from mesonbuild.compilers import ( detect_c_compiler @@ -81,6 +82,7 @@ def test_apple_bitcode_modules(self): self.build() self.run_tests() + @unittest.skipIf(version_compare(platform.mac_ver()[0], '<10.7'), '-export_dynamic was added in 10.7') def test_apple_lto_export_dynamic(self): ''' Tests that -Wl,-export_dynamic is correctly added, when export_dynamic: true is set. From c7031bd82221178cb368048348b4f918f9be20b5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 19 Aug 2024 15:47:58 -0700 Subject: [PATCH 54/72] tests/format: Make the compare script more useful Now it will generate a diff of the expected value and what it actually got (cherry picked from commit ab3cfc2da1c481f52a5525e41150626a2f66de3b) --- test cases/format/5 transform/file_compare.py | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/test cases/format/5 transform/file_compare.py b/test cases/format/5 transform/file_compare.py index 7b0d1b85668f..fd3ce10560a6 100644 --- a/test cases/format/5 transform/file_compare.py +++ b/test cases/format/5 transform/file_compare.py @@ -1,7 +1,31 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2024 Intel Corporation +import argparse import sys +import difflib -with open(sys.argv[1], 'r', encoding='utf-8') as f, open(sys.argv[2], 'r', encoding='utf-8') as g: - if f.read() != g.read(): - sys.exit('contents are not equal') + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument('actual', help='The transformed contents') + parser.add_argument('expected', help='the contents we expected') + args = parser.parse_args() + + with open(args.actual, 'r') as f: + actual = f.readlines() + with open(args.expected, 'r') as f: + expected = f.readlines() + + if actual == expected: + return 0 + + diff = difflib.ndiff(expected, actual) + for line in diff: + print(line, file=sys.stderr, end='') + return 1 + + +if __name__ == "__main__": + sys.exit(main()) From b429aa4e90a6311fb45167dbbd29d8e784ce090d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 19 Aug 2024 15:39:53 -0700 Subject: [PATCH 55/72] mformat: A triple string with a ' in it cannot be simplified The following is valid meson: ```meson a = '''This string can't be simplified''' ``` which cannot be simplified because of the `'` in it, as ```meson a = 'This string can't be simplified' ``` Is invalid. Potentially we could convert that with escapes, but it seems reasonable to me to leave this, since it may be desirable to not have lots of escapes in a string. `'''I can't believe it's her's!'''` is much more readable than `'I can\'t believe it\'s her\'s!'`, for example. Closes: #13564 (cherry picked from commit df706807239095ddbbfd2975b3fe067ad6b5d535) --- mesonbuild/mformat.py | 2 +- test cases/format/5 transform/default.expected.meson | 1 + test cases/format/5 transform/muon.expected.meson | 1 + test cases/format/5 transform/options.expected.meson | 1 + test cases/format/5 transform/source.meson | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 2746eff6924b..67db762c4f18 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -338,7 +338,7 @@ def visit_StringNode(self, node: mparser.StringNode) -> None: self.enter_node(node) if self.config.simplify_string_literals: - if node.is_multiline and '\n' not in node.value: + if node.is_multiline and not any(x in node.value for x in ['\n', "'"]): node.is_multiline = False node.value = node.escape() diff --git a/test cases/format/5 transform/default.expected.meson b/test cases/format/5 transform/default.expected.meson index 4201053e1f18..18af2f8afa79 100644 --- a/test cases/format/5 transform/default.expected.meson +++ b/test cases/format/5 transform/default.expected.meson @@ -47,6 +47,7 @@ d = {'a': 1, 'b': 2, 'c': 3} # string conversion 'This is not a multiline' 'This is not a fstring' +'''This isn't convertible''' # group arg value arguments = [ diff --git a/test cases/format/5 transform/muon.expected.meson b/test cases/format/5 transform/muon.expected.meson index 871ce27d722d..0e6309c7f722 100644 --- a/test cases/format/5 transform/muon.expected.meson +++ b/test cases/format/5 transform/muon.expected.meson @@ -47,6 +47,7 @@ d = {'a': 1, 'b': 2, 'c': 3} # string conversion '''This is not a multiline''' f'This is not a fstring' +'''This isn't convertible''' # group arg value arguments = [ diff --git a/test cases/format/5 transform/options.expected.meson b/test cases/format/5 transform/options.expected.meson index f7f45658d5c3..9ed6ac2be5af 100644 --- a/test cases/format/5 transform/options.expected.meson +++ b/test cases/format/5 transform/options.expected.meson @@ -29,6 +29,7 @@ d = { # string conversion 'This is not a multiline' 'This is not a fstring' +'''This isn't convertible''' # group arg value arguments = [ diff --git a/test cases/format/5 transform/source.meson b/test cases/format/5 transform/source.meson index 7274d4802699..4482884052d6 100644 --- a/test cases/format/5 transform/source.meson +++ b/test cases/format/5 transform/source.meson @@ -29,6 +29,7 @@ d = {'a': 1, 'b': 2, 'c': 3} # string conversion '''This is not a multiline''' f'This is not a fstring' +'''This isn't convertible''' # group arg value arguments = ['a', '--opt_a', 'opt_a_value', 'b', 'c', '--opt_d', '--opt_e', 'opt_e_value', From 9805225debcf8c0177736aa972fb10ed2d24fd66 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 19 Aug 2024 14:29:44 -0700 Subject: [PATCH 56/72] mformat: provide nice error message instead of backtrace for invalid value I ran into this with `option = true;` (note the trailing `;`). Now we provide a nicer message instead of an uncaught Python backtrace. Closes: #13565 (cherry picked from commit 1e6e4c8d571e3bd415f9b8285f6f33170ba81761) --- mesonbuild/mformat.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 67db762c4f18..83c4fad79edf 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -861,7 +861,11 @@ def load_configuration(self, configuration_file: T.Optional[Path]) -> FormatterC for f in fields(config): getter = f.metadata['getter'] - value = getter(cp, cp.default_section, f.name, fallback=None) + try: + value = getter(cp, cp.default_section, f.name, fallback=None) + except ValueError as e: + raise MesonException( + f'Error parsing "{str(configuration_file)}", option "{f.name}", error: "{e!s}"') if value is not None: setattr(config, f.name, value) From 358fe360350646666b90a80fbcd3c51e8f1d2fcd Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 4 Sep 2024 23:06:19 +0300 Subject: [PATCH 57/72] Add support for LLVM 19 in Debian. Originally from here: https: //bugs.debian.org/cgi-bin/bugreport.cgi?bug=1080463 (cherry picked from commit 3bb3d576a1f86fff2afdb345e0283da062b597df) --- mesonbuild/environment.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 5bccb903d48e..484ef45d478d 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -195,6 +195,8 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: # unless it becomes a stable release. suffixes = [ '', # base (no suffix) + '-19.1', '19.1', + '-19', '19', '-18.1', '18.1', '-18', '18', '-17', '17', @@ -216,7 +218,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: '-3.7', '37', '-3.6', '36', '-3.5', '35', - '-19', # Debian development snapshot + '-20', # Debian development snapshot '-devel', # FreeBSD development snapshot ] names: T.List[str] = [] From f182419e47f04389421e040eb1a585f749c22266 Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Tue, 20 Aug 2024 16:07:59 -0700 Subject: [PATCH 58/72] mformat: regenerate long lines even if they're already multiline If kwargs_force_multiline is enabled, an ArgumentNode in a kwarg value can already be marked multiline by the time we notice that the line needs to be broken for length. Ensure we still break the line in this case. Fixes: #13512 (cherry picked from commit 6d92547e6c78ac84dda69ac19b5586795317bac9) --- mesonbuild/mformat.py | 5 ++--- test cases/format/4 config/indentation.meson | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 83c4fad79edf..1454e3119ee2 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -769,9 +769,8 @@ def visit_BreakNode(self, node: mparser.BreakNode) -> None: def split_if_needed(self, node: mparser.ArgumentNode) -> None: if len(node) and not node.is_multiline and self.length > self.config.max_line_length: arg = self.argument_stack[self.level] if len(self.argument_stack) > self.level else node - if not arg.is_multiline: - arg.is_multiline = True - self.need_regenerate = True + arg.is_multiline = True + self.need_regenerate = True def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: self.argument_stack.append(node) diff --git a/test cases/format/4 config/indentation.meson b/test cases/format/4 config/indentation.meson index 816b5f3026a1..96a977e5fb56 100644 --- a/test cases/format/4 config/indentation.meson +++ b/test cases/format/4 config/indentation.meson @@ -71,3 +71,18 @@ if meson.project_version().version_compare('>1.2') endforeach endif endif + +subproject( + '@0@-@1@-@2@-@3@'.format( + meson.project_name(), + meson.project_version(), + meson.project_build_root(), + meson.project_source_root(), + ), + default_options : [ + 'aaaaaaaa=bbbbbbbbbb', + 'cccccccccccc=ddddddddddddd', + 'eeeeeeeeeeeeeee=fffffffffffff', + 'gggggggggggggggggggggg=hhhhhhhhhhhhhhhhhhhh', + ], +) From 7f28d42cc32f616b852df0b97cb3f48c05b81810 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 21 Aug 2024 02:28:26 -0400 Subject: [PATCH 59/72] tests: handle uncommon architecture format for nm The zlib symbols may not be of type 'T' but rather e.g. 'D' -- instead, tell nm to emit the POSIX format and also to only emit defined symbols, not undefined ones. Then we just check if the symbol is listed at all, regardless of type. We already depend on -U elsewhere (e.g symbolextractor). There's no real replacement for it, sadly. It's also buggy in some versions of nm, so we check both its long and short options. Bug: https://bugs.gentoo.org/938259 (cherry picked from commit 83f8de5357f31d6448ae033e1e8ed2b22c8c306a) --- .../14 static dynamic linkage/verify_static.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test cases/linuxlike/14 static dynamic linkage/verify_static.py b/test cases/linuxlike/14 static dynamic linkage/verify_static.py index 8d16d48c989e..25e97f368bb1 100755 --- a/test cases/linuxlike/14 static dynamic linkage/verify_static.py +++ b/test cases/linuxlike/14 static dynamic linkage/verify_static.py @@ -5,8 +5,16 @@ def handle_common(path): """Handle the common case.""" - output = subprocess.check_output(['nm', path]).decode('utf-8') - if 'T zlibVersion' in output: + try: + output = subprocess.check_output(['nm', '--defined-only', '-P', '-A', path]).decode('utf-8') + except subprocess.CalledProcessError: + # some NMs only support -U. Older binutils only supports --defined-only. + output = subprocess.check_output(['nm', '-UPA', path]).decode('utf-8') + # POSIX format. Prints all *defined* symbols, looks like this: + # builddir/main_static: zlibVersion T 1190 39 + # or + # builddir/main_static: zlibVersion D 1fde0 30 + if ': zlibVersion ' in output: return 0 return 1 From 53f5deb13779c14f54a69cd00f785203bafe0876 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 20 Aug 2024 17:09:57 -0400 Subject: [PATCH 60/72] mformat: detect invalid config - detect unknown config keys in format config - add test for detection of invalid config values - detect invalid .editorconfig values Fixes #13569 (cherry picked from commit d3ef02b2e4d312ac604c0045ec97bf35a121bab5) --- mesonbuild/mformat.py | 12 +++++++--- unittests/platformagnostictests.py | 37 ++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index 1454e3119ee2..b4d59dd377d2 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -839,7 +839,10 @@ def load_editor_config(self, source_file: Path) -> EditorConfig: getter = f.metadata['getter'] for section in sections: - value = getter(cp, section, f.name, fallback=None) + try: + value = getter(cp, section, f.name, fallback=None) + except ValueError as e: + raise MesonException(f'Invalid type for key "{f.name}" in "{editorconfig_file}" file:\n{e}') from e if value is not None: setattr(config, f.name, value) @@ -858,6 +861,10 @@ def load_configuration(self, configuration_file: T.Optional[Path]) -> FormatterC except ParsingError as e: raise MesonException(f'Unable to parse configuration file "{configuration_file}":\n{e}') from e + extra_keys = sorted(set(cp.defaults()).difference(f.name for f in fields(config))) + if extra_keys: + raise MesonException(f'Unknown config keys: "{", ".join(extra_keys)}" in configuration file "{configuration_file}"') + for f in fields(config): getter = f.metadata['getter'] try: @@ -992,9 +999,8 @@ def run(options: argparse.Namespace) -> int: # TODO: remove empty newlines when more than N (2...) # TODO: magic comment to prevent formatting -# TODO: handle meson.options ? # TODO: split long lines on binary operators -# TODO: align series of assignements +# TODO: align series of assignments # TODO: align comments # TODO: move comments on long lines diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index ebd4ca5210b5..9468aacdc6d9 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -15,7 +15,7 @@ from .baseplatformtests import BasePlatformTests from .helpers import is_ci -from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, MesonException, is_linux, python_command +from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, MesonException, is_linux, python_command, windows_proof_rmtree from mesonbuild.mformat import Formatter, match_path from mesonbuild.optinterpreter import OptionInterpreter, OptionException from run_tests import Backend @@ -333,7 +333,40 @@ def test_editorconfig_match_path(self): for filename, pattern, expected in cases: self.assertTrue(match_path(filename, pattern) is expected, f'{filename} -> {pattern}') - + + def test_format_invalid_config_key(self) -> None: + fd, fname = tempfile.mkstemp(suffix='.ini', text=True) + self.addCleanup(os.unlink, fname) + + with os.fdopen(fd, 'w', encoding='utf-8') as handle: + handle.write('not_an_option = 42\n') + + with self.assertRaises(MesonException): + Formatter(Path(fname), use_editor_config=False, fetch_subdirs=False) + + def test_format_invalid_config_value(self) -> None: + fd, fname = tempfile.mkstemp(suffix='.ini', text=True) + self.addCleanup(os.unlink, fname) + + with os.fdopen(fd, 'w', encoding='utf-8') as handle: + handle.write('max_line_length = string\n') + + with self.assertRaises(MesonException): + Formatter(Path(fname), use_editor_config=False, fetch_subdirs=False) + + def test_format_invalid_editorconfig_value(self) -> None: + dirpath = tempfile.mkdtemp() + self.addCleanup(windows_proof_rmtree, dirpath) + + editorconfig = Path(dirpath, '.editorconfig') + with open(editorconfig, 'w', encoding='utf-8') as handle: + handle.write('[*]\n') + handle.write('indent_size = string\n') + + formatter = Formatter(None, use_editor_config=True, fetch_subdirs=False) + with self.assertRaises(MesonException): + formatter.load_editor_config(editorconfig) + def test_format_empty_file(self) -> None: formatter = Formatter(None, use_editor_config=False, fetch_subdirs=False) for code in ('', '\n'): From 47c44dc70128ad07a9d37fb0bbc75f6ecbc57105 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 20 Aug 2024 14:52:16 -0400 Subject: [PATCH 61/72] mformat: better handling of continuation lines Fixes #13566. Fixes #13567. (cherry picked from commit 37c5bffbffc6a930522762838012390b80ca833e) --- mesonbuild/mformat.py | 13 ++++++++++++- mesonbuild/mparser.py | 1 + test cases/format/1 default/meson.build | 10 ++++++++++ test cases/format/1 default/meson.options | 1 + 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test cases/format/1 default/meson.options diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py index b4d59dd377d2..7f3dbf01400e 100644 --- a/mesonbuild/mformat.py +++ b/mesonbuild/mformat.py @@ -276,6 +276,7 @@ def exit_node(self, node: mparser.BaseNode) -> None: def move_whitespaces(self, from_node: mparser.BaseNode, to_node: mparser.BaseNode) -> None: to_node.whitespaces.value = from_node.whitespaces.value + to_node.whitespaces.value + to_node.whitespaces.is_continuation = from_node.whitespaces.is_continuation from_node.whitespaces = None to_node.whitespaces.accept(self) @@ -317,7 +318,10 @@ def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: for i, line in enumerate(lines): has_nl = line.endswith('\n') line = line.strip() - if line.startswith('#'): + if line.startswith('\\'): + node.value += ' ' # add space before \ + node.is_continuation = True + elif line.startswith('#'): if not in_block_comments: node.value += self.config.indent_before_comments else: @@ -328,6 +332,8 @@ def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: in_block_comments = True if node.value.endswith('\n'): node.value += self.indent_comments + if node.is_continuation: + node.value += self.config.indent_by def visit_SymbolNode(self, node: mparser.SymbolNode) -> None: super().visit_SymbolNode(node) @@ -595,6 +601,9 @@ def visit_DictNode(self, node: mparser.DictNode) -> None: def visit_MethodNode(self, node: mparser.MethodNode) -> None: self.enter_node(node) node.source_object.accept(self) + is_cont = node.source_object.whitespaces and node.source_object.whitespaces.is_continuation + if is_cont: + self.level += 1 if node.args.is_multiline: self.level += 1 self.add_nl_after(node.lpar, indent=self.level) @@ -602,6 +611,8 @@ def visit_MethodNode(self, node: mparser.MethodNode) -> None: node.args.accept(self) if node.args.is_multiline: self.level -= 1 + if is_cont: + self.level -= 1 self.exit_node(node) def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index fc37d2a54e2b..4e359b3b9f20 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -267,6 +267,7 @@ def __init__(self, token: Token[str]): self.value = '' self.append(token) self.block_indent = False + self.is_continuation = False def append(self, token: Token[str]) -> None: self.value += token.value diff --git a/test cases/format/1 default/meson.build b/test cases/format/1 default/meson.build index 83ae19aa0bde..d3bb153eeb92 100644 --- a/test cases/format/1 default/meson.build +++ b/test cases/format/1 default/meson.build @@ -13,6 +13,16 @@ meson_files = { # Ensure empty function are formatted correctly on long lines a = '@0@@1@@2@@3@@4@'.format('one', 'two', 'three', 'four', 'five').strip().strip() +_opt = get_option('opt') \ + .disable_if( + true, + error_message: 'This is an error message because opt can\'t be enabled', + ) \ + .enable_if( + false, + error_message: 'This is an error message because opt can\'t be disabled', + ) + foreach name, f : meson_files test(name, meson_cmd, args: ['format', '--check-only', f]) endforeach diff --git a/test cases/format/1 default/meson.options b/test cases/format/1 default/meson.options new file mode 100644 index 000000000000..13f5e19c0e68 --- /dev/null +++ b/test cases/format/1 default/meson.options @@ -0,0 +1 @@ +option('opt', type : 'feature', value : 'auto') From 839c5e8675506ad672e37f622e862404960520d5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Feb 2024 11:12:22 +0100 Subject: [PATCH 62/72] compilers: avoid -Wunused-value compiler warning in CLikeCompiler.has_members() Otherwise, `CFLAGS='-Wall -Werror' meson build` can fail detection: void bar(void) { struct stat foo; foo.st_mtim.tv_nsec; } ----------- Command line: `cc ./project/build/meson-private/tmpqz_gi65d/testfile.c -o ./project/build/meson-private/tmpqz_gi65d/output.obj -c -O3 -Werror -Wall -D_FILE_OFFSET_BITS=64 -O0 -std=gnu99` -> 1 stderr: ./project/build/meson-private/tmpqz_gi65d/testfile.c: In function 'bar': ./project/build/meson-private/tmpqz_gi65d/testfile.c:45:24: error: statement with no effect [-Werror=unused-value] 45 | foo.st_mtim.tv_nsec; | ~~~~~~~~~~~^~~~~~~~ cc1: all warnings being treated as errors (cherry picked from commit a22a50a6739160bdf93a5a11f5026112007ccf4e) --- mesonbuild/compilers/mixins/clike.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 70613944fcbf..898a59580610 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -870,11 +870,12 @@ def has_members(self, typename: str, membernames: T.List[str], if extra_args is None: extra_args = [] # Create code that accesses all members - members = ''.join(f'foo.{member};\n' for member in membernames) + members = ''.join(f'(void) ( foo.{member} );\n' for member in membernames) t = f'''{prefix} void bar(void) {{ {typename} foo; {members} + (void) foo; }}''' return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) From b252b34d17de72c24c0df8b27b9f89a000f11dec Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 7 Feb 2024 11:12:22 +0100 Subject: [PATCH 63/72] compilers: avoid -Wunused-value compiler warning in CLikeCompiler.has_type() Otherwise, `CFLAGS='-Wall -Werror' meson build` can fail detection: Running compile: Working directory: ./project/build/meson-private/tmpk86bgc04 Code: #include void bar(void) { sizeof(loff_t); } ----------- Command line: `cc ./project/build/meson-private/tmpk86bgc04/testfile.c -o ./project/build/meson-private/tmpk86bgc04/output.obj -c -Werror -Wall -D_FILE_OFFSET_BITS=64 -O0 -std=gnu99` -> 1 stderr: ./project/build/meson-private/tmpk86bgc04/testfile.c: In function 'bar': ./project/build/meson-private/tmpk86bgc04/testfile.c:3:13: error: statement with no effect [-Werror=unused-value] 3 | sizeof(loff_t); | ^~~~~~ cc1: all warnings being treated as errors ----------- Checking for type "loff_t" : NO (cherry picked from commit fa8bd9306c01a1268d1a4cd7417ad753b1aa09e1) --- mesonbuild/compilers/mixins/clike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 898a59580610..a3c7dc4fc9cd 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -885,7 +885,7 @@ def has_type(self, typename: str, prefix: str, env: 'Environment', dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: t = f'''{prefix} void bar(void) {{ - sizeof({typename}); + (void) sizeof({typename}); }}''' return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies) From c726ca48afeb8453b488fa06f5392ba0c575f77c Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Sat, 7 Sep 2024 13:19:01 +0100 Subject: [PATCH 64/72] Prevent raw exception during project() If a user imports a module and invokes a method on it, a raw Python exception is raised to the user. This commit adds a check to ensure that in this case an appropriate exception is raised instead. A test has been added to ensure that this exception is in fact raised on offending code. Fixes: #11393, #5134 (cherry picked from commit 74dd77ed81c90e3655b3dff5bfe98410a85dd4f0) --- mesonbuild/interpreter/interpreterobjects.py | 6 +++++- .../failing/132 module use inside project decl/meson.build | 6 ++++++ .../failing/132 module use inside project decl/test.json | 7 +++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test cases/failing/132 module use inside project decl/meson.build create mode 100644 test cases/failing/132 module use inside project decl/test.json diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index d5c1efaa8372..79e205d31d0f 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -12,7 +12,7 @@ from .. import build from .. import mlog -from ..modules import ModuleReturnValue, ModuleObject, ModuleState, ExtensionModule +from ..modules import ModuleReturnValue, ModuleObject, ModuleState, ExtensionModule, NewExtensionModule from ..backend.backends import TestProtocol from ..interpreterbase import ( ContainerTypeInfo, KwargInfo, MesonOperator, @@ -844,6 +844,10 @@ def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwa args = flatten(args) if not getattr(method, 'no-second-level-holder-flattening', False): args, kwargs = resolve_second_level_holders(args, kwargs) + if not self.interpreter.active_projectname: + assert isinstance(modobj, (ExtensionModule, NewExtensionModule)), 'for mypy' + full_method_name = f'{modobj.INFO.name}.{method_name}' + raise mesonlib.MesonException(f'Module methods ({full_method_name}) cannot be invoked during project declaration.') state = ModuleState(self.interpreter) # Many modules do for example self.interpreter.find_program_impl(), # so we have to ensure they use the current interpreter and not the one diff --git a/test cases/failing/132 module use inside project decl/meson.build b/test cases/failing/132 module use inside project decl/meson.build new file mode 100644 index 000000000000..8f82a5d3089b --- /dev/null +++ b/test cases/failing/132 module use inside project decl/meson.build @@ -0,0 +1,6 @@ +# GH issue 11393 +project('module use inside project decl', 'c', + version: run_command( + import('python').find_installation('python3') + ) +) diff --git a/test cases/failing/132 module use inside project decl/test.json b/test cases/failing/132 module use inside project decl/test.json new file mode 100644 index 000000000000..33e377b842f3 --- /dev/null +++ b/test cases/failing/132 module use inside project decl/test.json @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/132 module use inside project decl/meson.build:4:21: ERROR: Module methods (python.find_installation) cannot be invoked during project declaration." + } + ] + } From f1b7f52ab76034a4c884250adb256d0918c42afe Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 24 Jan 2024 22:16:49 -0500 Subject: [PATCH 65/72] When configuring fails in Github Actions, print folded logs A common, and challenging, issue in CI runners is debugging issues when you know the information you want to check, but it's in the log file which you don't have because remote CI machines. There are various edge cases where this is especially hard to solve, such as inside of `pip install` where the build directory with the log file is automatically cleaned up. But it's never really *easy* when you don't expect it, and the best case scenario is your iteration time gets cut in half as you hurriedly go add some `cat`s to your CI scripts. Meson can, at least sometimes, detect platforms where text can be emitted inside of "folds", which are auto-collapsed and don't obscure the general output, but when clicked will expand the logfile contents. Hook this up. We start off with a Github Actions implementation. We had some internal code used by our own project tests runner, which can be utilized. Also permit forcing it via an environment variable, in case autodetection fails and you just want to force *something*, especially when meson is called a couple layers deep inside some other tool. (cherry picked from commit 2b80d4cca174916a4b6d0c47c54ad56795741bb6) --- mesonbuild/mesonmain.py | 3 +++ mesonbuild/mlog.py | 31 ++++++++++++++++++++++++++++++- run_project_tests.py | 11 +++-------- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index c486dd846cb9..faa0f426d82a 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -27,6 +27,9 @@ def errorhandler(e: Exception, command: str) -> int: logfile = mlog.shutdown() if logfile is not None: mlog.log("\nA full log can be found at", mlog.bold(logfile)) + contents = mlog.ci_fold_file(logfile, f'CI platform detected, click here for {os.path.basename(logfile)} contents.') + if contents: + print(contents) if os.environ.get('MESON_FORCE_BACKTRACE'): raise e return 1 diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index a8b0185371d1..bc8faeba7d06 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -22,8 +22,9 @@ from pathlib import Path if T.TYPE_CHECKING: - from ._typing import StringProtocol, SizedStringProtocol + from typing_extensions import Literal + from ._typing import StringProtocol, SizedStringProtocol from .mparser import BaseNode TV_Loggable = T.Union[str, 'AnsiDecorator', StringProtocol] @@ -75,6 +76,7 @@ def setup_console() -> None: pass _in_ci = 'CI' in os.environ +_ci_is_github = 'GITHUB_ACTIONS' in os.environ class _Severity(enum.Enum): @@ -540,3 +542,30 @@ def code_line(text: str, line: str, colno: int) -> str: :return: A formatted string of the text, line, and a caret """ return f'{text}\n{line}\n{" " * colno}^' + +@T.overload +def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: Literal[True] = True) -> str: ... + +@T.overload +def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: Literal[False] = False) -> T.Optional[str]: ... + +def ci_fold_file(fname: T.Union[str, os.PathLike], banner: str, force: bool = False) -> T.Optional[str]: + if not _in_ci and not force: + return None + + if _ci_is_github: + header = f'::group::==== {banner} ====' + footer = '::endgroup::' + elif force: + header = banner + footer = '' + elif 'MESON_FORCE_SHOW_LOGS' in os.environ: + header = f'==== Forcing display of logs for {os.path.basename(fname)} ====' + footer = '' + else: + # only github is implemented + return None + + with open(fname, 'r', encoding='utf-8') as f: + data = f.read() + return f'{header}\n{data}\n{footer}\n' diff --git a/run_project_tests.py b/run_project_tests.py index 974273fc790e..c11410486e23 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -305,7 +305,6 @@ def __lt__(self, other: object) -> bool: failing_logs: T.List[str] = [] print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ under_ci = 'CI' in os.environ -ci_is_github = 'GITHUB_ACTIONS' in os.environ raw_ci_jobname = os.environ.get('MESON_CI_JOBNAME', None) ci_jobname = raw_ci_jobname if raw_ci_jobname != 'thirdparty' else None do_debug = under_ci or print_debug @@ -437,16 +436,12 @@ def log_text_file(logfile: T.TextIO, testdir: Path, result: TestResult) -> None: def _run_ci_include(args: T.List[str]) -> str: - header = f'Included file {args[0]}:' - footer = '' - if ci_is_github: - header = f'::group::==== {header} ====' - footer = '::endgroup::' if not args: return 'At least one parameter required' + + header = f'Included file {args[0]}:' try: - data = Path(args[0]).read_text(errors='ignore', encoding='utf-8') - return f'{header}\n{data}\n{footer}\n' + return mlog.ci_fold_file(args[0], header, force=True) except Exception: return 'Failed to open {}\n'.format(args[0]) From 946d52a5f53b64689af35249261ab910a4bbf871 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Jul 2024 12:33:47 -0400 Subject: [PATCH 66/72] CI: mark arch as skipping frameworks/libgcrypt They have recently upgraded to libgcrypt 1.11 and it has inherited the gpg suite migration to pkg-config. (cherry picked from commit 21eda4dd3b0c497daa44cb0afe370520805e4735) --- test cases/frameworks/24 libgcrypt/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/24 libgcrypt/test.json b/test cases/frameworks/24 libgcrypt/test.json index 23af7d93189d..9c282daa86e7 100644 --- a/test cases/frameworks/24 libgcrypt/test.json +++ b/test cases/frameworks/24 libgcrypt/test.json @@ -1,3 +1,3 @@ { - "expect_skip_on_jobname": ["azure", "cygwin", "msys2"] + "expect_skip_on_jobname": ["arch", "azure", "cygwin", "msys2"] } From 54e35c11e696c859cdd71aacc1cdf437cdeea954 Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Tue, 17 Sep 2024 00:28:34 +0100 Subject: [PATCH 67/72] compilers: Pass mode to determine_args, not its string value We always pass the string value of the mode to determine_args, which causes the check on the mode argument inside determine_args to always evaluate to false. Fix this by passing the mode itself, not its value. (cherry picked from commit 9cb9ad88da3e837086753af03813b1f173a6d831) --- mesonbuild/compilers/mixins/clike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index a3c7dc4fc9cd..174104b079ee 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -417,7 +417,7 @@ def build_wrapper_args(self, env: 'Environment', else: # TODO: we want to do this in the caller extra_args = mesonlib.listify(extra_args) - extra_args = mesonlib.listify([e(mode.value) if callable(e) else e for e in extra_args]) + extra_args = mesonlib.listify([e(mode) if callable(e) else e for e in extra_args]) if dependencies is None: dependencies = [] From 72af62b118244cf21eecb804c8d852a0f3bd53b5 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 2 Sep 2024 15:40:28 -0400 Subject: [PATCH 68/72] mdist: detect pathological git repo cases and show a slightly better error When `meson dist` fails with the error: ``` Dist currently only works with Git or Mercurial repos ``` It is sometimes inaccurate, since a git repo may exist but be nonfunctional. Offer some better guidance in that case. Fixes: #10866 (cherry picked from commit 81c50885689488d701ec442d08234b442e975d78) --- mesonbuild/mdist.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 26ea7887c314..87133c504387 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -22,7 +22,7 @@ from glob import glob from pathlib import Path from mesonbuild.environment import Environment, detect_ninja -from mesonbuild.mesonlib import (MesonException, RealPathAction, get_meson_command, quiet_git, +from mesonbuild.mesonlib import (GIT, MesonException, RealPathAction, get_meson_command, quiet_git, windows_proof_rmtree, setup_vsenv, OptionKey) from mesonbuild.msetup import add_arguments as msetup_argparse from mesonbuild.wrap import wrap @@ -79,7 +79,36 @@ def is_git(src_root: str) -> bool: Checks if meson.build file at the root source directory is tracked by git. It could be a subproject part of the parent project git repository. ''' - return quiet_git(['ls-files', '--error-unmatch', 'meson.build'], src_root)[0] + if quiet_git(['ls-files', '--error-unmatch', 'meson.build'], src_root)[0]: + return True + + if os.path.exists(os.path.join(src_root, '.git')): + msg = 'Source tree looks like it may be a git repo, ' + if not GIT: + msg += 'but git is not installed!' + if 'GITLAB_CI' in os.environ: + msg += ' This is a gitlab bug.' + else: + msg += 'but git returned a failure. ' + p, oe = quiet_git(['status'], src_root) + if 'dubious ownership' in oe: + # For a few years now, git has absolved itself of the responsibility to implement + # robust, safe software. Instead of detecting the signs of a problematic scenario, + # they have chosen to consider many legitimate and reasonable use cases as "dangerous", + # and implemented the number one threat to security worldwide: alert fatigue. Having + # done so, they then washed their hands of the matter and permanently tabled the + # notion of adding fine-grained detection. This is not just useless, it is *worse* + # than useless. + # + # In our case, the error is triply meaningless since we are already executing build + # system commands from the same directory. Either way, reject the notion that git is + # well designed or that its error messaging is a valid approach to the problem space. + msg += 'This is a bug in git itself, please set `git config --global safe.directory "*"`' + else: + msg += 'meson.build may not have been committed to git?' + mlog.warning(msg) + return False + def is_hg(src_root: str) -> bool: return os.path.isdir(os.path.join(src_root, '.hg')) From 908f2d11eda8a80758336d7d09d28ddb9588c23b Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Thu, 19 Sep 2024 08:29:59 +0800 Subject: [PATCH 69/72] backend/ninja: Generate sysroot in rust-project.json Rust-analyzer relies on sysroot to discover its proc-macro server [1] which is typically installed at /libexec/rust-analyzer-proc-macro-srv. When used with rust-project.json, rust-analyzer expects the json file to specify sysroot and fails to launch the proc-macro server otherwise. So add sysroot to the meson-generated rust-project.json and point it to the sysroot of the detected rustc compiler. [1] https://github.com/rust-lang/rust-analyzer/blob/2024-09-16/crates/project-model/src/sysroot.rs#L175 Signed-off-by: Junjie Mao (cherry picked from commit e5d03f5e138173b03ad2b0223bbcb8f436cb3bf1) --- mesonbuild/backend/ninjabackend.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 27b9f7bb1d24..9c6932884e4a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -700,10 +700,11 @@ def generate_rust_project_json(self) -> None: return with open(os.path.join(self.environment.get_build_dir(), 'rust-project.json'), 'w', encoding='utf-8') as f: + sysroot = self.environment.coredata.compilers.host['rust'].get_sysroot() json.dump( { - "sysroot_src": os.path.join(self.environment.coredata.compilers.host['rust'].get_sysroot(), - 'lib/rustlib/src/rust/library/'), + "sysroot": sysroot, + "sysroot_src": os.path.join(sysroot, 'lib/rustlib/src/rust/library/'), "crates": [c.to_json() for c in self.rust_crates.values()], }, f, indent=4) From e409a55008935a973d64926beef6302b914d5f47 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 19 Sep 2024 23:46:49 -0400 Subject: [PATCH 70/72] mdist: correctly detect dirty hg repos with non-English locale, redux https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html GNU Gettext defines a feature, whereby for translation purposes, if LC_ALL / LANG are *not* set to C, but rather define an active translation, the LANGUAGE variable can be used to specify fallback languages in a colon-separated list wherein the first option is the primary language and the rest are fallbacks. CPython, instead, checks the LANGUAGE variable first, and the first variable that has a non-null value is treated as the canonical language specification, splitted, and iterated over. LC_ALL=C is therefore totally ignored, which is a major problem, and the variables aren't checked for consistency, which is a less major problem. GNU libc documents the same behavior CPython does -- which is broken as it makes LC_ALL=C useless. POSIX issue 8 standardizes on option 3: do like GNU Gettext, except do not require the primary language in $LANGUAGE to be consistent with LANG / LC_ALL. Thus, we sanitize the environment even harder. What an absolute disaster. Even if this was fixed tomorrow we would need to maintain this hack until 2030. Bug: https://bugs.gentoo.org/936670 (cherry picked from commit 5e6122b2a5804d77ad4cbff398d1193bcae2fd1e) --- mesonbuild/mdist.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 87133c504387..d569f6015739 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -253,6 +253,9 @@ def have_dirty_index(self) -> bool: '''Check whether there are uncommitted changes in hg''' env = os.environ.copy() env['LC_ALL'] = 'C' + # cpython's gettext has a bug and uses LANGUAGE to override LC_ALL, + # contrary to the gettext spec + env.pop('LANGUAGE', None) out = subprocess.check_output(['hg', '-R', self.src_root, 'summary'], env=env) return b'commit: (clean)' not in out From af9658a3669b99bda877f256cd2cf09d49858b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20S=C5=82omi=C5=84ski?= Date: Fri, 20 Sep 2024 19:38:06 +0200 Subject: [PATCH 71/72] nasm: Use different test sources for x86 and x86_64 The x86 test files might not work on x86_64 Linux in certain cases, for example if the kernel is configured without support for x86 executables (which also gets rid of the old system call interface). Bug: https://bugs.gentoo.org/936911 (cherry picked from commit 9501228168086939da1710da634830a70818934b) --- .../{hello.asm => hello-x86.asm} | 0 .../nasm/1 configure file/hello-x86_64.asm | 18 +++++++++++++++ test cases/nasm/1 configure file/meson.build | 2 +- .../{hello.asm => hello-x86.asm} | 0 .../nasm/2 asm language/hello-x86_64.asm | 22 +++++++++++++++++++ test cases/nasm/2 asm language/meson.build | 4 ++-- 6 files changed, 43 insertions(+), 3 deletions(-) rename test cases/nasm/1 configure file/{hello.asm => hello-x86.asm} (100%) create mode 100644 test cases/nasm/1 configure file/hello-x86_64.asm rename test cases/nasm/2 asm language/{hello.asm => hello-x86.asm} (100%) create mode 100644 test cases/nasm/2 asm language/hello-x86_64.asm diff --git a/test cases/nasm/1 configure file/hello.asm b/test cases/nasm/1 configure file/hello-x86.asm similarity index 100% rename from test cases/nasm/1 configure file/hello.asm rename to test cases/nasm/1 configure file/hello-x86.asm diff --git a/test cases/nasm/1 configure file/hello-x86_64.asm b/test cases/nasm/1 configure file/hello-x86_64.asm new file mode 100644 index 000000000000..b6cb776babbd --- /dev/null +++ b/test cases/nasm/1 configure file/hello-x86_64.asm @@ -0,0 +1,18 @@ +%include "config.asm" + + section .data +msg: db "Hello World", 10 +len: equ $ - msg + + section .text + global main +main: + mov eax, 1 ; sys_write + mov edi, 1 ; fd = STDOUT_FILENO + mov rsi, msg ; buf = msg + mov rdx, len ; count = len + syscall + + mov eax, 60 ; sys_exit + mov edi, HELLO ; exit code + syscall diff --git a/test cases/nasm/1 configure file/meson.build b/test cases/nasm/1 configure file/meson.build index abe7bb30f98c..46a704ceb633 100644 --- a/test cases/nasm/1 configure file/meson.build +++ b/test cases/nasm/1 configure file/meson.build @@ -50,7 +50,7 @@ config_file = configure_file( cc = meson.get_compiler('c') link_args = cc.get_supported_link_arguments(['-no-pie']) -exe = executable('hello', asm_gen.process('hello.asm'), +exe = executable('hello', asm_gen.process('hello-' + host_machine.cpu_family() + '.asm'), link_args: link_args, ) diff --git a/test cases/nasm/2 asm language/hello.asm b/test cases/nasm/2 asm language/hello-x86.asm similarity index 100% rename from test cases/nasm/2 asm language/hello.asm rename to test cases/nasm/2 asm language/hello-x86.asm diff --git a/test cases/nasm/2 asm language/hello-x86_64.asm b/test cases/nasm/2 asm language/hello-x86_64.asm new file mode 100644 index 000000000000..7e495f92ab5e --- /dev/null +++ b/test cases/nasm/2 asm language/hello-x86_64.asm @@ -0,0 +1,22 @@ +%include "config.asm" + +%ifdef FOO +%define RETVAL HELLO +%endif + + section .data +msg: db "Hello World", 10 +len: equ $ - msg + + section .text + global main +main: + mov eax, 1 ; sys_write + mov edi, 1 ; fd = STDOUT_FILENO + mov rsi, msg ; buf = msg + mov rdx, len ; count = len + syscall + + mov eax, 60 ; sys_exit + mov edi, RETVAL ; exit code + syscall diff --git a/test cases/nasm/2 asm language/meson.build b/test cases/nasm/2 asm language/meson.build index d5a2ba3eaeb2..594d12dc2496 100644 --- a/test cases/nasm/2 asm language/meson.build +++ b/test cases/nasm/2 asm language/meson.build @@ -46,7 +46,7 @@ config_file = configure_file( cc = meson.get_compiler('c') link_args = cc.get_supported_link_arguments(['-no-pie']) -exe = executable('hello', 'hello.asm', +exe = executable('hello', 'hello-' + host_machine.cpu_family() + '.asm', nasm_args: '-DFOO', link_args: link_args, ) @@ -55,7 +55,7 @@ test('hello', exe) #Test whether pthread dependency gets filtered out threads = dependency('threads') -exe2 = executable('hello_w_threads', 'hello.asm', +exe2 = executable('hello_w_threads', 'hello-' + host_machine.cpu_family() + '.asm', config_file, nasm_args: '-DFOO', link_args: link_args, From 187ef425f96b9ba091edce56e9491373c51b2a34 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 19 Sep 2024 21:46:04 -0400 Subject: [PATCH 72/72] Bump versions to 1.5.2 for release --- man/meson.1 | 2 +- mesonbuild/coredata.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/man/meson.1 b/man/meson.1 index 589bba271246..5c929bc1adf9 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "July 2024" "meson 1.5.1" "User Commands" +.TH MESON "1" "September 2024" "meson 1.5.2" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index bbe4af7cfced..8c27c3ae1fc9 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -72,7 +72,7 @@ class SharedCMDOptions(Protocol): # # Pip requires that RCs are named like this: '0.1.0.rc1' # But the corresponding Git tag needs to be '0.1.0rc1' -version = '1.5.1' +version = '1.5.2' # The next stable version when we are in dev. This is used to allow projects to # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when