From 51d04776a3158ec8a50ea21fde2f19a8d6cdf4ee Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Tue, 20 Jun 2023 15:45:18 -0700 Subject: [PATCH 001/855] tests: add support for c++23/c++26 detection Signed-off-by: Steven Noonan Signed-off-by: Patrick Williams --- unittests/linuxliketests.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index f322b020054f..7c4c6ca680c5 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -517,6 +517,15 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: has_cpp20 = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=10.0.0', None) or compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=10.0.0')) + has_cpp2b = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=12.0.0', None) or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0')) + has_cpp23 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0')) + has_cpp26 = (compiler.get_id() not in {'clang', 'gcc'} or + compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=14.0.0')) has_c18 = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=8.0.0', '>=11.0') or compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=8.0.0')) @@ -533,6 +542,12 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: continue elif '++20' in v and not has_cpp20: continue + elif '++2b' in v and not has_cpp2b: + continue + elif '++23' in v and not has_cpp23: + continue + elif ('++26' in v or '++2c' in v) and not has_cpp26: + continue # now C elif '17' in v and not has_cpp2a_c17: continue From 658b0d10003508d9551378c8b132c2f572b03a19 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Tue, 20 Jun 2023 14:33:50 -0700 Subject: [PATCH 002/855] c++: add fallback mappings for C++23 and C++26 The c++23 mappings apply to current production compilers (GCC, Clang). None of the production c++ compilers support c++26 flags yet, but this mapping will be ready once they do. Signed-off-by: Steven Noonan Signed-off-by: Patrick Williams --- mesonbuild/compilers/cpp.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 0c6892374f7f..14e2638fc203 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -154,6 +154,10 @@ def _find_best_cpp_std(self, cpp_std: str) -> str: 'gnu++17': 'gnu++1z', 'c++20': 'c++2a', 'gnu++20': 'gnu++2a', + 'c++23': 'c++2b', + 'gnu++23': 'gnu++2b', + 'c++26': 'c++2c', + 'gnu++26': 'gnu++2c', } # Currently, remapping is only supported for Clang, Elbrus and GCC From e3c007aefe72d9f896028c6c45906707181d3a07 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Tue, 20 Jun 2023 14:34:47 -0700 Subject: [PATCH 003/855] c++: add support for c++23/c++26 standard and aliases GCC 12.3 and Clang 16 support -std flags for c++23/c++2b. The unreleased GCC 14 and Clang 17 will support -std flags for c++26/c++2c. Signed-off-by: Steven Noonan Signed-off-by: Patrick Williams --- mesonbuild/compilers/cpp.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 14e2638fc203..6eccf259c800 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -226,6 +226,10 @@ def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler): + + _CPP23_VERSION = '>=12.0.0' + _CPP26_VERSION = '>=17.0.0' + def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, @@ -252,11 +256,18 @@ def get_options(self) -> 'MutableKeyedOptionDictType': ), key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), }) - opts[key.evolve('std')].choices = [ + cppstd_choices = [ 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', 'gnu++2a', 'gnu++20', ] + if version_compare(self.version, self._CPP23_VERSION): + cppstd_choices.append('c++23') + cppstd_choices.append('gnu++23') + if version_compare(self.version, self._CPP26_VERSION): + cppstd_choices.append('c++26') + cppstd_choices.append('gnu++26') + opts[key.evolve('std')].choices = cppstd_choices if self.info.is_windows() or self.info.is_cygwin(): opts.update({ key.evolve('winlibs'): coredata.UserArrayOption( @@ -298,7 +309,11 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler): class AppleClangCPPCompiler(ClangCPPCompiler): - pass + + _CPP23_VERSION = '>=13.0.0' + # TODO: We don't know which XCode version will include LLVM 17 yet, so + # use something absurd. + _CPP26_VERSION = '>=99.0.0' class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): @@ -418,6 +433,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': if version_compare(self.version, '>=12.2.0'): cppstd_choices.append('c++23') cppstd_choices.append('gnu++23') + if version_compare(self.version, '>=14.0.0'): + cppstd_choices.append('c++26') + cppstd_choices.append('gnu++26') opts[key].choices = cppstd_choices if self.info.is_windows() or self.info.is_cygwin(): opts.update({ From f9debd3ae24a772056f19aa5f0746661f2259f6b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Jul 2023 09:13:57 +1000 Subject: [PATCH 004/855] docs: fix typos and keyword markdown for the Rust module page Two typos and mark the keyword arguments with backticks so they render nicely. --- docs/markdown/Rust-module.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index d3891bfc3e49..d606629dbd55 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -26,22 +26,22 @@ copying the sources and arguments passed to the original target and adding the `--test` argument to the compilation, then creates a new test target which calls that executable, using the rust test protocol. -This accepts all of the keyword arguments as the +This accepts all of the keyword arguments accepted by the [[test]] function except `protocol`, it will set that automatically. -Additional, test only dependencies may be passed via the dependencies +Additional, test-only dependencies may be passed via the `dependencies` argument. -*(since 1.2.0)* the link_with argument can be used to pass additional build +*(since 1.2.0)* the `link_with` argument can be used to pass additional build targets to link with -*(since 1.2.0)* the `rust_args` keyword argument can be ussed to pass extra +*(since 1.2.0)* the `rust_args` keyword argument can be used to pass extra arguments to the Rust compiler. ### bindgen(*, input: string | BuildTarget | [](string | BuildTarget), output: string, include_directories: [](include_directories | string), c_args: []string, args: []string, dependencies: []Dependency) This function wraps bindgen to simplify creating rust bindings around C -libraries. This has two advantages over hand-rolling ones own with a +libraries. This has two advantages over invoking bindgen with a `generator` or `custom_target`: - It handles `include_directories`, so one doesn't have to manually convert them to `-I...` @@ -51,14 +51,14 @@ libraries. This has two advantages over hand-rolling ones own with a It takes the following keyword arguments -- input — A list of Files, Strings, or CustomTargets. The first element is +- `input` — A list of Files, Strings, or CustomTargets. The first element is the header bindgen will parse, additional elements are dependencies. -- output — the name of the output rust file -- include_directories — A list of `include_directories` or `string` objects, +- `output` — the name of the output rust file +- `include_directories` — A list of `include_directories` or `string` objects, these are passed to clang as `-I` arguments *(string since 1.0.0)* -- c_args — A list of string arguments to pass to clang untouched -- args — A list of string arguments to pass to `bindgen` untouched. -- dependencies — A list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) +- `c_args` — A list of string arguments to pass to clang untouched +- `args` — A list of string arguments to pass to `bindgen` untouched. +- `dependencies` — A list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) ```meson rust = import('unstable-rust') From 1502b90f3a2d3557e0461d27f49b2f29aed46474 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Jul 2023 09:30:06 +1000 Subject: [PATCH 005/855] docs: improve formatting of the Rust module This brings the formatting more in line with other modules, in particular the headers do not include the full function signature for readability, keyword arguments are listed one-by-one, etc. --- docs/markdown/Rust-module.md | 37 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index d606629dbd55..bbc92fc2582c 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -18,7 +18,11 @@ like Meson, rather than Meson work more like rust. ## Functions -### test(name: string, target: library | executable, dependencies: []Dependency, link_with: []targets, rust_args: []string) +### test() + +```meson +rustmod.test(name, target, ...) +``` This function creates a new rust unittest target from an existing rust based target, which may be a library or executable. It does this by @@ -26,19 +30,18 @@ copying the sources and arguments passed to the original target and adding the `--test` argument to the compilation, then creates a new test target which calls that executable, using the rust test protocol. -This accepts all of the keyword arguments accepted by the -[[test]] function except `protocol`, it will set -that automatically. +This function takes two positional arguments, the first is the name of the +test and the second is the library or executable that is the rust based target. +It also takes the following keyword arguments: -Additional, test-only dependencies may be passed via the `dependencies` -argument. +- `dependencies`: a list of test-only Dependencies +- `link_with`: a list of additional build Targets to link with (*since 1.2.0*) +- `rust_args`: a list of extra arguments passed to the Rust compiler (*since 1.2.0*) -*(since 1.2.0)* the `link_with` argument can be used to pass additional build -targets to link with -*(since 1.2.0)* the `rust_args` keyword argument can be used to pass extra -arguments to the Rust compiler. +This function also accepts all of the keyword arguments accepted by the +[[test]] function except `protocol`, it will set that automatically. -### bindgen(*, input: string | BuildTarget | [](string | BuildTarget), output: string, include_directories: [](include_directories | string), c_args: []string, args: []string, dependencies: []Dependency) +### bindgen() This function wraps bindgen to simplify creating rust bindings around C libraries. This has two advantages over invoking bindgen with a @@ -51,14 +54,14 @@ libraries. This has two advantages over invoking bindgen with a It takes the following keyword arguments -- `input` — A list of Files, Strings, or CustomTargets. The first element is +- `input`: a list of Files, Strings, or CustomTargets. The first element is the header bindgen will parse, additional elements are dependencies. -- `output` — the name of the output rust file -- `include_directories` — A list of `include_directories` or `string` objects, +- `output`: the name of the output rust file +- `include_directories`: A list of `include_directories` or `string` objects, these are passed to clang as `-I` arguments *(string since 1.0.0)* -- `c_args` — A list of string arguments to pass to clang untouched -- `args` — A list of string arguments to pass to `bindgen` untouched. -- `dependencies` — A list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) +- `c_args`: a list of string arguments to pass to clang untouched +- `args`: a list of string arguments to pass to `bindgen` untouched. +- `dependencies`: a list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) ```meson rust = import('unstable-rust') From 0a40e591d3b9665a63ef243f78450a6e97304669 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 7 May 2023 20:57:24 -0400 Subject: [PATCH 006/855] tests: mark gpgme test skippable on Ubuntu rolling It has been rebuilt to no longer provide the deprecated gpgme-config tool. --- test cases/frameworks/27 gpgme/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/27 gpgme/test.json b/test cases/frameworks/27 gpgme/test.json index aa7d932dd607..59eb0e24d871 100644 --- a/test cases/frameworks/27 gpgme/test.json +++ b/test cases/frameworks/27 gpgme/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch"] + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch", "ubuntu"] } From a8b9bd2b74030863d61761483dbc3f6db8803c68 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 18 Jul 2023 16:01:29 -0400 Subject: [PATCH 007/855] tests: bump the C++ std for protobuf tests Based on https://opensource.google/documentation/policies/cplusplus-support Google no longer supports C++11, and protobuf spawns an `#error` if you don't have at least 14. So, perform our currently scheduled automatic bump. --- test cases/frameworks/5 protocol buffers/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/5 protocol buffers/meson.build b/test cases/frameworks/5 protocol buffers/meson.build index 046847a89297..9a4154b652f3 100644 --- a/test cases/frameworks/5 protocol buffers/meson.build +++ b/test cases/frameworks/5 protocol buffers/meson.build @@ -1,4 +1,4 @@ -project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++11']) +project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++14']) protoc = find_program('protoc', required : false) dep = dependency('protobuf', required : false) From 46586c79a482a7234f90081d6df9e909a5f93792 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 18 Jul 2023 16:06:24 -0400 Subject: [PATCH 008/855] CI: install a newer java on opensuse They do not appear to have 15 in their repos anymore, and no traces can be found of it in the history, as usual. They do have 11, 17, and 20, so choose one randomly and hope it doesn't keep changing value. --- ci/ciimage/opensuse/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/opensuse/install.sh b/ci/ciimage/opensuse/install.sh index 41cb96192e8f..40c109ce9055 100755 --- a/ci/ciimage/opensuse/install.sh +++ b/ci/ciimage/opensuse/install.sh @@ -9,7 +9,7 @@ pkgs=( ninja make git autoconf automake patch libjpeg-devel elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-obj-c++ vala rust bison flex curl lcov mono-core gtkmm3-devel gtest gmock protobuf-devel wxGTK3-3_2-devel gobject-introspection-devel - itstool gtk3-devel java-15-openjdk-devel gtk-doc llvm-devel clang-devel libSDL2-devel graphviz-devel zlib-devel zlib-devel-static + itstool gtk3-devel java-20-openjdk-devel gtk-doc llvm-devel clang-devel libSDL2-devel graphviz-devel zlib-devel zlib-devel-static #hdf5-devel netcdf-devel libscalapack2-openmpi3-devel libscalapack2-gnu-openmpi3-hpc-devel openmpi3-devel doxygen vulkan-devel vulkan-validationlayers openssh mercurial gtk-sharp3-complete gtk-sharp2-complete libpcap-devel libgpgme-devel libqt5-qtbase-devel libqt5-qttools-devel libqt5-linguist libqt5-qtbase-private-headers-devel From 6894bb5a30a05dbd9d30eb4ce5720f6c2a7df83d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 18 Jul 2023 16:32:36 -0400 Subject: [PATCH 009/855] mtest: avoid meddling with stdout by default The original point of specifying Optional was to default to None... oops. The practical effect of this change is that the testsuite no longer repeatedly logs "No tests defined." in between more meaningful output. --- mesonbuild/mtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index eb56c42be555..88995c0fedeb 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1933,7 +1933,7 @@ def tests_from_args(self, tests: T.List[TestSerialisation]) -> T.Generator[TestS # succeed on an invalid pattern. raise MesonException(f'{arg} test name does not match any test') - def get_tests(self, errorfile: T.Optional[T.IO] = sys.stdout) -> T.List[TestSerialisation]: + def get_tests(self, errorfile: T.Optional[T.IO] = None) -> T.List[TestSerialisation]: if not self.tests: print('No tests defined.', file=errorfile) return [] From d048bbfbe7c3d287e9b1e61c39313862caf9fd52 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 18 Jul 2023 17:29:41 -0400 Subject: [PATCH 010/855] CI: change ubuntu cross exe_wrapper to un-suffixed wine wine64 used to be the way to run a 64-bit wineserver. It was removed due to https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1029536 despite that bug report being about a bug in an unrelated symlink -- apparently there's no recommended solution to starting a specific bitness of wine on demand. The automagic `wine` I believe creates a wineprefix with both, which is... probably not exactly efficient here? But whatever, not worth fighting it. Just get this more or less working again. --- cross/linux-mingw-w64-64bit.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cross/linux-mingw-w64-64bit.txt b/cross/linux-mingw-w64-64bit.txt index f49fb35bfbd3..7403803b4c05 100644 --- a/cross/linux-mingw-w64-64bit.txt +++ b/cross/linux-mingw-w64-64bit.txt @@ -6,7 +6,7 @@ ar = '/usr/bin/x86_64-w64-mingw32-ar' strip = '/usr/bin/x86_64-w64-mingw32-strip' pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' -exe_wrapper = 'wine64' +exe_wrapper = 'wine' cmake = '/usr/bin/cmake' [properties] From 1d84989078026acbfd256f294f5359361d2f1b0d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 18 Jul 2023 18:13:27 -0400 Subject: [PATCH 011/855] CI image builder: log commands a bit --- ci/ciimage/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py index 1e1f23811c3d..01979556dcfb 100755 --- a/ci/ciimage/build.py +++ b/ci/ciimage/build.py @@ -175,7 +175,7 @@ def do_test(self, tty: bool = False) -> None: else: test_cmd = [ self.docker, 'run', '--rm', '-t', 'meson_test_image', - '/bin/bash', '-c', 'source /ci/env_vars.sh; cd meson; ./run_tests.py $CI_ARGS' + '/bin/bash', '-xc', 'source /ci/env_vars.sh; cd meson; ./run_tests.py $CI_ARGS' ] if subprocess.run(test_cmd).returncode != 0 and not tty: From 727b737bc3d94bccc2295b9811dc0c167f1aa5f9 Mon Sep 17 00:00:00 2001 From: kiwixz Date: Sat, 15 Jul 2023 19:41:19 +0200 Subject: [PATCH 012/855] cmake: find dependencies with bare library names on all platforms --- mesonbuild/cmake/tracetargets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py index 338364dbd3f5..bb5faa3959d1 100644 --- a/mesonbuild/cmake/tracetargets.py +++ b/mesonbuild/cmake/tracetargets.py @@ -50,8 +50,8 @@ def resolve_cmake_trace_targets(target_name: str, res.libraries += [curr] elif Path(curr).is_absolute() and Path(curr).exists(): res.libraries += [curr] - elif env.machines.build.is_windows() and reg_is_maybe_bare_lib.match(curr) and clib_compiler: - # On Windows, CMake library dependencies can be passed as bare library names, + elif reg_is_maybe_bare_lib.match(curr) and clib_compiler: + # CMake library dependencies can be passed as bare library names, # CMake brute-forces a combination of prefix/suffix combinations to find the # right library. Assume any bare argument passed which is not also a CMake # target must be a system library we should try to link against. From 4fab71f48144cd6760ceae5c3085e68e93b9016f Mon Sep 17 00:00:00 2001 From: kiwixz Date: Tue, 11 Jul 2023 23:34:55 +0200 Subject: [PATCH 013/855] cmake: fix empty BOOL generator expression evaluating to true --- mesonbuild/cmake/generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py index 7903dd49f530..5b83479196b6 100644 --- a/mesonbuild/cmake/generator.py +++ b/mesonbuild/cmake/generator.py @@ -100,7 +100,7 @@ def target_file(arg: str) -> str: supported = { # Boolean functions - 'BOOL': lambda x: '0' if x.upper() in {'0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'} or x.endswith('-NOTFOUND') else '1', + 'BOOL': lambda x: '0' if x.upper() in {'', '0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'} or x.endswith('-NOTFOUND') else '1', 'AND': lambda x: '1' if all(y == '1' for y in x.split(',')) else '0', 'OR': lambda x: '1' if any(y == '1' for y in x.split(',')) else '0', 'NOT': lambda x: '0' if x == '1' else '1', From 3171fc533812e15bcb5eda607c7c82d37d0aaf42 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 12:25:29 -0400 Subject: [PATCH 014/855] add better comments for mypy suppressions --- mesonbuild/modules/gnome.py | 4 ++-- mesonbuild/modules/pkgconfig.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 7a9acea0009f..755bf240b15a 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1744,7 +1744,7 @@ def mkenums(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnums') - 'identifier_prefix', 'symbol_prefix', 'vhead', 'vprod', 'vtail'] for arg in known_kwargs: - # mypy can't figure this out + # Mypy can't figure out that this TypedDict index is correct, without repeating T.Literal for the entire list if kwargs[arg]: # type: ignore cmd += ['--' + arg.replace('_', '-'), kwargs[arg]] # type: ignore @@ -1966,7 +1966,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh mlog.bold('https://github.com/mesonbuild/meson/pull/2049'), once=True, fatal=False) for k in ['internal', 'nostdinc', 'skip_source', 'stdinc', 'valist_marshallers']: - # Mypy can't figure out that this is correct + # Mypy can't figure out that this TypedDict index is correct, without repeating T.Literal for the entire list if kwargs[k]: # type: ignore cmd.append(f'--{k.replace("_", "-")}') diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 921fb666167b..9f71d952cfec 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -649,6 +649,7 @@ def generate(self, state: ModuleState, if dataonly: default_subdirs = [] blocked_vars = ['libraries', 'libraries_private', 'requires_private', 'extra_cflags', 'subdirs'] + # Mypy can't figure out that this TypedDict index is correct, without repeating T.Literal for the entire list if any(kwargs[k] for k in blocked_vars): # type: ignore raise mesonlib.MesonException(f'Cannot combine dataonly with any of {blocked_vars}') default_install_dir = os.path.join(state.environment.get_datadir(), 'pkgconfig') From ca34c7617036d5af1559767deba36038ecac101d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 12:28:00 -0400 Subject: [PATCH 015/855] linkers: reorganize code so that linker base classes always come first So that we can later reference them. --- mesonbuild/linkers/linkers.py | 399 +++++++++++++++++----------------- 1 file changed, 200 insertions(+), 199 deletions(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 8f413c857901..8fb36565b81d 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -109,6 +109,206 @@ def rsp_file_syntax(self) -> RSPFileSyntax: raise EnvironmentException(f'{self.id} does not implement rsp format, this shouldn\'t be called') +class DynamicLinker(metaclass=abc.ABCMeta): + + """Base class for dynamic linkers.""" + + _BUILDTYPE_ARGS: T.Dict[str, T.List[str]] = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], + 'custom': [], + } + + @abc.abstractproperty + def id(self) -> str: + pass + + def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: + args = [arg] if isinstance(arg, str) else arg + if self.prefix_arg is None: + return args + elif isinstance(self.prefix_arg, str): + return [self.prefix_arg + arg for arg in args] + ret: T.List[str] = [] + for arg in args: + ret += self.prefix_arg + [arg] + return ret + + def __init__(self, exelist: T.List[str], + for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], + always_args: T.List[str], *, version: str = 'unknown version'): + self.exelist = exelist + self.for_machine = for_machine + self.version = version + self.prefix_arg = prefix_arg + self.always_args = always_args + self.machine: T.Optional[str] = None + + def __repr__(self) -> str: + return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist)) + + def get_id(self) -> str: + return self.id + + def get_version_string(self) -> str: + return f'({self.id} {self.version})' + + def get_exelist(self) -> T.List[str]: + return self.exelist.copy() + + def get_accepts_rsp(self) -> bool: + # rsp files are only used when building on Windows because we want to + # avoid issues with quoting and max argument length + return mesonlib.is_windows() + + def rsp_file_syntax(self) -> RSPFileSyntax: + """The format of the RSP file that this compiler supports. + + If `self.can_linker_accept_rsp()` returns True, then this needs to + be implemented + """ + return RSPFileSyntax.GCC + + def get_always_args(self) -> T.List[str]: + return self.always_args.copy() + + def get_lib_prefix(self) -> str: + return '' + + # XXX: is use_ldflags a compiler or a linker attribute? + + def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.') + + def get_debugfile_name(self, targetfile: str) -> T.Optional[str]: + '''Name of debug file written out (see below)''' + return None + + def get_debugfile_args(self, targetfile: str) -> T.List[str]: + """Some compilers (MSVC) write debug into a separate file. + + This method takes the target object path and returns a list of + commands to append to the linker invocation to control where that + file is written. + """ + return [] + + def get_std_shared_lib_args(self) -> T.List[str]: + return [] + + def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return self.get_std_shared_lib_args() + + def get_pie_args(self) -> T.List[str]: + # TODO: this really needs to take a boolean and return the args to + # disable pie, otherwise it only acts to enable pie if pie *isn't* the + # default. + raise EnvironmentException(f'Linker {self.id} does not support position-independent executable') + + def get_lto_args(self) -> T.List[str]: + return [] + + def get_thinlto_cache_args(self, path: str) -> T.List[str]: + return [] + + def sanitizer_args(self, value: str) -> T.List[str]: + return [] + + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + # We can override these in children by just overriding the + # _BUILDTYPE_ARGS value. + return self._BUILDTYPE_ARGS[buildtype] + + def get_asneeded_args(self) -> T.List[str]: + return [] + + def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: + raise EnvironmentException( + f'Linker {self.id} does not support link_whole') + + def get_allow_undefined_args(self) -> T.List[str]: + raise EnvironmentException( + f'Linker {self.id} does not support allow undefined') + + @abc.abstractmethod + def get_output_args(self, outputname: str) -> T.List[str]: + pass + + def get_coverage_args(self) -> T.List[str]: + raise EnvironmentException(f"Linker {self.id} doesn't implement coverage data generation.") + + @abc.abstractmethod + def get_search_args(self, dirname: str) -> T.List[str]: + pass + + def export_dynamic_args(self, env: 'Environment') -> T.List[str]: + return [] + + def import_library_args(self, implibname: str) -> T.List[str]: + """The name of the outputted import library. + + This implementation is used only on Windows by compilers that use GNU ld + """ + return [] + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return [] + + def no_undefined_args(self) -> T.List[str]: + """Arguments to error if there are any undefined symbols at link time. + + This is the inverse of get_allow_undefined_args(). + + TODO: A future cleanup might merge this and + get_allow_undefined_args() into a single method taking a + boolean + """ + return [] + + def fatal_warnings(self) -> T.List[str]: + """Arguments to make all warnings errors.""" + return [] + + def headerpad_args(self) -> T.List[str]: + # Only used by the Apple linker + return [] + + def get_gui_app_args(self, value: bool) -> T.List[str]: + # Only used by VisualStudioLikeLinkers + return [] + + def get_win_subsystem_args(self, value: str) -> T.List[str]: + # Only used if supported by the dynamic linker and + # only when targeting Windows + return [] + + def bitcode_args(self) -> T.List[str]: + raise MesonException('This linker does not support bitcode bundles') + + def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, + rpath_paths: T.Tuple[str, ...], build_rpath: str, + install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: + return ([], set()) + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: + return [] + + def get_archive_name(self, filename: str) -> str: + #Only used by AIX. + return str() + + def get_command_to_archive_shlib(self) -> T.List[str]: + #Only used by AIX. + return [] + + class VisualStudioLikeLinker: always_args = ['/NOLOGO'] @@ -351,205 +551,6 @@ def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str: else: return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) -class DynamicLinker(metaclass=abc.ABCMeta): - - """Base class for dynamic linkers.""" - - _BUILDTYPE_ARGS: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], - } - - @abc.abstractproperty - def id(self) -> str: - pass - - def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: - args = [arg] if isinstance(arg, str) else arg - if self.prefix_arg is None: - return args - elif isinstance(self.prefix_arg, str): - return [self.prefix_arg + arg for arg in args] - ret: T.List[str] = [] - for arg in args: - ret += self.prefix_arg + [arg] - return ret - - def __init__(self, exelist: T.List[str], - for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], - always_args: T.List[str], *, version: str = 'unknown version'): - self.exelist = exelist - self.for_machine = for_machine - self.version = version - self.prefix_arg = prefix_arg - self.always_args = always_args - self.machine: T.Optional[str] = None - - def __repr__(self) -> str: - return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist)) - - def get_id(self) -> str: - return self.id - - def get_version_string(self) -> str: - return f'({self.id} {self.version})' - - def get_exelist(self) -> T.List[str]: - return self.exelist.copy() - - def get_accepts_rsp(self) -> bool: - # rsp files are only used when building on Windows because we want to - # avoid issues with quoting and max argument length - return mesonlib.is_windows() - - def rsp_file_syntax(self) -> RSPFileSyntax: - """The format of the RSP file that this compiler supports. - - If `self.can_linker_accept_rsp()` returns True, then this needs to - be implemented - """ - return RSPFileSyntax.GCC - - def get_always_args(self) -> T.List[str]: - return self.always_args.copy() - - def get_lib_prefix(self) -> str: - return '' - - # XXX: is use_ldflags a compiler or a linker attribute? - - def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]: - return [] - - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: - raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.') - - def get_debugfile_name(self, targetfile: str) -> T.Optional[str]: - '''Name of debug file written out (see below)''' - return None - - def get_debugfile_args(self, targetfile: str) -> T.List[str]: - """Some compilers (MSVC) write debug into a separate file. - - This method takes the target object path and returns a list of - commands to append to the linker invocation to control where that - file is written. - """ - return [] - - def get_std_shared_lib_args(self) -> T.List[str]: - return [] - - def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: - return self.get_std_shared_lib_args() - - def get_pie_args(self) -> T.List[str]: - # TODO: this really needs to take a boolean and return the args to - # disable pie, otherwise it only acts to enable pie if pie *isn't* the - # default. - raise EnvironmentException(f'Linker {self.id} does not support position-independent executable') - - def get_lto_args(self) -> T.List[str]: - return [] - - def get_thinlto_cache_args(self, path: str) -> T.List[str]: - return [] - - def sanitizer_args(self, value: str) -> T.List[str]: - return [] - - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # We can override these in children by just overriding the - # _BUILDTYPE_ARGS value. - return self._BUILDTYPE_ARGS[buildtype] - - def get_asneeded_args(self) -> T.List[str]: - return [] - - def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: - raise EnvironmentException( - f'Linker {self.id} does not support link_whole') - - def get_allow_undefined_args(self) -> T.List[str]: - raise EnvironmentException( - f'Linker {self.id} does not support allow undefined') - - @abc.abstractmethod - def get_output_args(self, outputname: str) -> T.List[str]: - pass - - def get_coverage_args(self) -> T.List[str]: - raise EnvironmentException(f"Linker {self.id} doesn't implement coverage data generation.") - - @abc.abstractmethod - def get_search_args(self, dirname: str) -> T.List[str]: - pass - - def export_dynamic_args(self, env: 'Environment') -> T.List[str]: - return [] - - def import_library_args(self, implibname: str) -> T.List[str]: - """The name of the outputted import library. - - This implementation is used only on Windows by compilers that use GNU ld - """ - return [] - - def thread_flags(self, env: 'Environment') -> T.List[str]: - return [] - - def no_undefined_args(self) -> T.List[str]: - """Arguments to error if there are any undefined symbols at link time. - - This is the inverse of get_allow_undefined_args(). - - TODO: A future cleanup might merge this and - get_allow_undefined_args() into a single method taking a - boolean - """ - return [] - - def fatal_warnings(self) -> T.List[str]: - """Arguments to make all warnings errors.""" - return [] - - def headerpad_args(self) -> T.List[str]: - # Only used by the Apple linker - return [] - - def get_gui_app_args(self, value: bool) -> T.List[str]: - # Only used by VisualStudioLikeLinkers - return [] - - def get_win_subsystem_args(self, value: str) -> T.List[str]: - # Only used if supported by the dynamic linker and - # only when targeting Windows - return [] - - def bitcode_args(self) -> T.List[str]: - raise MesonException('This linker does not support bitcode bundles') - - def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, - rpath_paths: T.Tuple[str, ...], build_rpath: str, - install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: - return ([], set()) - - def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, - suffix: str, soversion: str, darwin_versions: T.Tuple[str, str]) -> T.List[str]: - return [] - - def get_archive_name(self, filename: str) -> str: - #Only used by AIX. - return str() - - def get_command_to_archive_shlib(self) -> T.List[str]: - #Only used by AIX. - return [] - class PosixDynamicLinkerMixin: From 621264e1d4f1a8623c6f82b774c8c9f099e98b62 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 12:29:12 -0400 Subject: [PATCH 016/855] linkers: fix mypy errors that were ignored due to lack of inheritance A linker mixin has to be able to align with the base linker it will be used for, in order to reference super(). Since they weren't inherited, calls to super() resulted in mypy errors, which we ignored, and casting. Use the same trick we use for compilers, and make the linker inherit from the base linker type when running under mypy, and from object at runtime. --- mesonbuild/linkers/linkers.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 8fb36565b81d..5e76a92eb49d 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -309,6 +309,13 @@ def get_command_to_archive_shlib(self) -> T.List[str]: return [] +if T.TYPE_CHECKING: + StaticLinkerBase = StaticLinker + DynamicLinkerBase = DynamicLinker +else: + StaticLinkerBase = DynamicLinkerBase = object + + class VisualStudioLikeLinker: always_args = ['/NOLOGO'] @@ -1218,7 +1225,7 @@ def get_output_args(self, target: str) -> T.List[str]: NvidiaHPC_StaticLinker = PGIStaticLinker -class VisualStudioLikeLinkerMixin: +class VisualStudioLikeLinkerMixin(DynamicLinkerBase): """Mixin class for dynamic linkers that act like Microsoft's link.exe.""" @@ -1241,7 +1248,7 @@ def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]], always_args: T.List[str], *, version: str = 'unknown version', direct: bool = True, machine: str = 'x86'): # There's no way I can find to make mypy understand what's going on here - super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) # type: ignore + super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) self.machine = machine self.direct = direct @@ -1255,8 +1262,8 @@ def get_output_args(self, outputname: str) -> T.List[str]: return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname]) def get_always_args(self) -> T.List[str]: - parent = super().get_always_args() # type: ignore - return self._apply_prefix('/nologo') + T.cast('T.List[str]', parent) + parent = super().get_always_args() + return self._apply_prefix('/nologo') + parent def get_search_args(self, dirname: str) -> T.List[str]: return self._apply_prefix('/LIBPATH:' + dirname) From cfc3960956f98aff74b118ce3de89a40ef3496c1 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 12:38:15 -0400 Subject: [PATCH 017/855] mypy: add more mixin base classes These don't have new errors or old ignored ones, but add them anyway so we can generally validate their sanity. --- mesonbuild/linkers/linkers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 5e76a92eb49d..89483477d8f6 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -316,7 +316,7 @@ def get_command_to_archive_shlib(self) -> T.List[str]: StaticLinkerBase = DynamicLinkerBase = object -class VisualStudioLikeLinker: +class VisualStudioLikeLinker(StaticLinkerBase): always_args = ['/NOLOGO'] def __init__(self, machine: str): @@ -559,7 +559,7 @@ def evaluate_rpath(p: str, build_dir: str, from_dir: str) -> str: return os.path.relpath(os.path.join(build_dir, p), os.path.join(build_dir, from_dir)) -class PosixDynamicLinkerMixin: +class PosixDynamicLinkerMixin(DynamicLinkerBase): """Mixin class for POSIX-ish linkers. @@ -578,7 +578,7 @@ def get_search_args(self, dirname: str) -> T.List[str]: return ['-L' + dirname] -class GnuLikeDynamicLinkerMixin: +class GnuLikeDynamicLinkerMixin(DynamicLinkerBase): """Mixin class for dynamic linkers that provides gnu-like interface. From 7afc69254d6b7240406cb1112ab57355bd9d32cd Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 25 Apr 2023 14:47:37 -0400 Subject: [PATCH 018/855] fix implicit_reexport issues and enforce them going forward This detects cases where module A imports a function from B, and C imports that same function from A instead of B. It's not part of the API contract of A, and causes innocent refactoring to break things. --- .mypy.ini | 1 + mesonbuild/backend/backends.py | 14 ++++++------- mesonbuild/build.py | 21 ++++++++++--------- mesonbuild/compilers/mixins/clike.py | 3 +-- mesonbuild/compilers/vala.py | 5 ++--- mesonbuild/dependencies/boost.py | 3 ++- mesonbuild/dependencies/coarrays.py | 3 ++- mesonbuild/dependencies/misc.py | 8 +++---- mesonbuild/dependencies/mpi.py | 3 ++- mesonbuild/dependencies/pkgconfig.py | 4 +--- mesonbuild/dependencies/scalapack.py | 3 ++- mesonbuild/interpreter/interpreter.py | 15 +++++++------ mesonbuild/interpreter/interpreterobjects.py | 10 ++++----- mesonbuild/interpreter/kwargs.py | 12 +++++------ mesonbuild/interpreter/mesonmain.py | 13 ++++++------ mesonbuild/interpreterbase/decorators.py | 3 +-- mesonbuild/interpreterbase/interpreterbase.py | 15 +++++++------ mesonbuild/mconf.py | 4 ++-- mesonbuild/mdevenv.py | 4 ++-- mesonbuild/minstall.py | 8 +++---- mesonbuild/mintro.py | 2 +- mesonbuild/modules/__init__.py | 11 +++++----- mesonbuild/modules/external_project.py | 5 +++-- mesonbuild/modules/gnome.py | 8 +++---- mesonbuild/modules/hotdoc.py | 2 +- mesonbuild/modules/pkgconfig.py | 2 +- mesonbuild/modules/python.py | 2 +- mesonbuild/mtest.py | 4 ++-- mesonbuild/programs.py | 3 +-- mesonbuild/utils/posix.py | 2 +- mesonbuild/utils/vsenv.py | 3 ++- mesonbuild/utils/win32.py | 2 +- 32 files changed, 98 insertions(+), 100 deletions(-) diff --git a/.mypy.ini b/.mypy.ini index 2ee1e597301c..70fdcd9f3732 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -3,6 +3,7 @@ strict_optional = False show_error_context = False show_column_numbers = True ignore_missing_imports = True +implicit_reexport = False follow_imports = silent warn_redundant_casts = True diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 73741a4412ee..e18906ccab2a 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -202,7 +202,7 @@ class TestSerialisation: needs_exe_wrapper: bool is_parallel: bool cmd_args: T.List[str] - env: build.EnvironmentVariables + env: mesonlib.EnvironmentVariables should_fail: bool timeout: T.Optional[int] workdir: T.Optional[str] @@ -512,7 +512,7 @@ def get_executable_serialisation( extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, capture: T.Optional[bool] = None, feed: T.Optional[bool] = None, - env: T.Optional[build.EnvironmentVariables] = None, + env: T.Optional[mesonlib.EnvironmentVariables] = None, tag: T.Optional[str] = None, verbose: bool = False, installdir_map: T.Optional[T.Dict[str, str]] = None) -> 'ExecutableSerialisation': @@ -585,7 +585,7 @@ def as_meson_exe_cmdline(self, exe: T.Union[str, mesonlib.File, build.BuildTarge capture: T.Optional[bool] = None, feed: T.Optional[bool] = None, force_serialize: bool = False, - env: T.Optional[build.EnvironmentVariables] = None, + env: T.Optional[mesonlib.EnvironmentVariables] = None, verbose: bool = False) -> T.Tuple[T.Sequence[T.Union[str, File, build.Target, programs.ExternalProgram]], str]: ''' Serialize an executable for running with a generator or a custom target @@ -1588,8 +1588,8 @@ def eval_custom_target_command( cmd = [i.replace('\\', '/') for i in cmd] return inputs, outputs, cmd - def get_run_target_env(self, target: build.RunTarget) -> build.EnvironmentVariables: - env = target.env if target.env else build.EnvironmentVariables() + def get_run_target_env(self, target: build.RunTarget) -> mesonlib.EnvironmentVariables: + env = target.env if target.env else mesonlib.EnvironmentVariables() if target.default_env: introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) env.set('MESON_SOURCE_ROOT', [self.environment.get_source_dir()]) @@ -1959,8 +1959,8 @@ def get_introspection_data(self, target_id: str, target: build.Target) -> T.List return [] - def get_devenv(self) -> build.EnvironmentVariables: - env = build.EnvironmentVariables() + def get_devenv(self) -> mesonlib.EnvironmentVariables: + env = mesonlib.EnvironmentVariables() extra_paths = set() library_paths = set() build_machine = self.environment.machines[MachineChoice.BUILD] diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 0a4160fb1c6b..d588c9db8fb4 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -39,7 +39,7 @@ MesonBugException, EnvironmentVariables, pickle_load, ) from .compilers import ( - is_object, clink_langs, sort_clink, all_languages, + is_header, is_object, is_source, clink_langs, sort_clink, all_languages, is_known_suffix, detect_static_linker ) from .interpreterbase import FeatureNew, FeatureDeprecated @@ -47,12 +47,13 @@ if T.TYPE_CHECKING: from typing_extensions import Literal from ._typing import ImmutableListProtocol - from .backend.backends import Backend, ExecutableSerialisation + from .backend.backends import Backend from .compilers import Compiler - from .interpreter.interpreter import Test, SourceOutputs, Interpreter + from .interpreter.interpreter import SourceOutputs, Interpreter + from .interpreter.interpreterobjects import Test from .interpreterbase import SubProject from .linkers.linkers import StaticLinker - from .mesonlib import FileMode, FileOrString + from .mesonlib import ExecutableSerialisation, FileMode, FileOrString from .modules import ModuleState from .mparser import BaseNode from .wrap import WrapMode @@ -434,7 +435,7 @@ def get_sources(sources: T.Sequence['FileOrString'], generated_sources: T.Sequen sources.append(s) # Filter out headers and all non-source files - return [s for s in sources if environment.is_source(s)] + return [s for s in sources if is_source(s)] def classify_all_sources(self, sources: T.List[FileOrString], generated_sources: T.Sequence['GeneratedTypes']) -> T.Dict['Compiler', T.List['FileOrString']]: sources_ = self.get_sources(sources, generated_sources) @@ -1494,14 +1495,14 @@ def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: return elif len(pchlist) == 1: - if not environment.is_header(pchlist[0]): + if not is_header(pchlist[0]): raise InvalidArguments(f'PCH argument {pchlist[0]} is not a header.') elif len(pchlist) == 2: - if environment.is_header(pchlist[0]): - if not environment.is_source(pchlist[1]): + if is_header(pchlist[0]): + if not is_source(pchlist[1]): raise InvalidArguments('PCH definition must contain one header and at most one source.') - elif environment.is_source(pchlist[0]): - if not environment.is_header(pchlist[1]): + elif is_source(pchlist[0]): + if not is_header(pchlist[1]): raise InvalidArguments('PCH definition must contain one header and at most one source.') pchlist = [pchlist[1], pchlist[0]] else: diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index da361856ca72..251a7bf67bd1 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -36,8 +36,7 @@ from ... import mesonlib from ... import mlog from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker -from ...mesonlib import LibType -from ...coredata import OptionKey +from ...mesonlib import LibType, OptionKey from .. import compilers from ..compilers import CompileCheckMode from .visualstudio import VisualStudioLikeCompiler diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index c6af04a274bd..ded158e8190e 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -17,9 +17,8 @@ import typing as T from .. import mlog -from ..mesonlib import EnvironmentException, version_compare, OptionKey - -from .compilers import CompileCheckMode, Compiler, LibType +from ..mesonlib import EnvironmentException, version_compare, LibType, OptionKey +from .compilers import CompileCheckMode, Compiler if T.TYPE_CHECKING: from ..envconfig import MachineInfo diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 0e4dab9a5570..0a936e65e1cd 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -28,7 +28,8 @@ from .misc import threads_factory if T.TYPE_CHECKING: - from ..environment import Environment, Properties + from ..envconfig import Properties + from ..environment import Environment # On windows 3 directory layouts are supported: # * The default layout (versioned) installed: diff --git a/mesonbuild/dependencies/coarrays.py b/mesonbuild/dependencies/coarrays.py index 5cb855614f73..1c59792e646c 100644 --- a/mesonbuild/dependencies/coarrays.py +++ b/mesonbuild/dependencies/coarrays.py @@ -24,7 +24,8 @@ if T.TYPE_CHECKING: from . factory import DependencyGenerator - from ..environment import Environment, MachineChoice + from ..environment import Environment + from ..mesonlib import MachineChoice @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE, DependencyMethods.SYSTEM}) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index d77566961a3c..1a5502f69e8c 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -30,13 +30,13 @@ from .pkgconfig import PkgConfigDependency if T.TYPE_CHECKING: - from ..environment import Environment, MachineChoice + from ..environment import Environment from .factory import DependencyGenerator @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE}) def netcdf_factory(env: 'Environment', - for_machine: 'MachineChoice', + for_machine: 'mesonlib.MachineChoice', kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: language = kwargs.get('language', 'c') @@ -475,7 +475,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM}) def curses_factory(env: 'Environment', - for_machine: 'MachineChoice', + for_machine: 'mesonlib.MachineChoice', kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: candidates: T.List['DependencyGenerator'] = [] @@ -501,7 +501,7 @@ def curses_factory(env: 'Environment', @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM}) def shaderc_factory(env: 'Environment', - for_machine: 'MachineChoice', + for_machine: 'mesonlib.MachineChoice', kwargs: T.Dict[str, T.Any], methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']: """Custom DependencyFactory for ShaderC. diff --git a/mesonbuild/dependencies/mpi.py b/mesonbuild/dependencies/mpi.py index 910068143312..240e6fd95ce5 100644 --- a/mesonbuild/dependencies/mpi.py +++ b/mesonbuild/dependencies/mpi.py @@ -27,7 +27,8 @@ if T.TYPE_CHECKING: from .factory import DependencyGenerator - from ..environment import Environment, MachineChoice + from ..environment import Environment + from ..mesonlib import MachineChoice @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM}) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 0c40847c9992..37f2ecb1c7e4 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -16,7 +16,7 @@ from pathlib import Path from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName -from ..mesonlib import OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged +from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged from ..programs import find_external_program, ExternalProgram from .. import mlog from pathlib import PurePath @@ -30,7 +30,6 @@ from ..mesonlib import MachineChoice from ..utils.core import EnvironOrDict from .._typing import ImmutableListProtocol - from ..build import EnvironmentVariables class PkgConfigDependency(ExternalDependency): # The class's copy of the pkg-config path. Avoids having to search for it @@ -128,7 +127,6 @@ def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple @staticmethod def get_env(environment: 'Environment', for_machine: MachineChoice, uninstalled: bool = False) -> 'EnvironmentVariables': - from ..build import EnvironmentVariables env = EnvironmentVariables() key = OptionKey('pkg_config_path', machine=for_machine) extra_paths: T.List[str] = environment.coredata.options[key].value[:] diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index 257e4aaaa7b3..2442ede41ee0 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -27,7 +27,8 @@ from .factory import factory_methods if T.TYPE_CHECKING: - from ..environment import Environment, MachineChoice + from ..environment import Environment + from ..mesonlib import MachineChoice from .factory import DependencyGenerator diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 363de547f8a3..efca123ab618 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -23,7 +23,7 @@ from .. import envconfig from ..wrap import wrap, WrapMode from .. import mesonlib -from ..mesonlib import (MesonBugException, MesonException, HoldableObject, +from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject, FileMode, MachineChoice, OptionKey, listify, extract_as_list, has_path_sep, PerMachine) from ..programs import ExternalProgram, NonExistingExternalProgram @@ -36,7 +36,6 @@ from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs, FeatureDeprecatedKwargs from ..interpreterbase import ObjectHolder, ContextManagerObject from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule -from ..backend.backends import ExecutableSerialisation from . import interpreterobjects as OBJ from . import compiler as compilerOBJ @@ -458,7 +457,7 @@ def build_holder_map(self) -> None: build.SymlinkData: OBJ.SymlinkDataHolder, build.InstallDir: OBJ.InstallDirHolder, build.IncludeDirs: OBJ.IncludeDirsHolder, - build.EnvironmentVariables: OBJ.EnvironmentVariablesHolder, + mesonlib.EnvironmentVariables: OBJ.EnvironmentVariablesHolder, build.StructuredSources: OBJ.StructuredSourcesHolder, compilers.RunResult: compilerOBJ.TryRunResultHolder, dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder, @@ -2166,10 +2165,10 @@ def func_test(self, node: mparser.BaseNode, kwargs: 'kwtypes.FuncTest') -> None: self.add_test(node, args, kwargs, True) - def unpack_env_kwarg(self, kwargs: T.Union[build.EnvironmentVariables, T.Dict[str, 'TYPE_var'], T.List['TYPE_var'], str]) -> build.EnvironmentVariables: + def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariables, T.Dict[str, 'TYPE_var'], T.List['TYPE_var'], str]) -> EnvironmentVariables: envlist = kwargs.get('env') if envlist is None: - return build.EnvironmentVariables() + return EnvironmentVariables() msg = ENV_KW.validator(envlist) if msg: raise InvalidArguments(f'"env": {msg}') @@ -2687,7 +2686,7 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], mlog.log('Configuring', mlog.bold(output), 'with command') cmd, *args = _cmd res = self.run_command_impl(node, (cmd, args), - {'capture': True, 'check': True, 'env': build.EnvironmentVariables()}, + {'capture': True, 'check': True, 'env': EnvironmentVariables()}, True) if kwargs['capture']: dst_tmp = ofile_abs + '~' @@ -2967,7 +2966,7 @@ def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.Lis @typed_pos_args('environment', optargs=[(str, list, dict)]) @typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0')) def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[None, str, T.List['TYPE_var'], T.Dict[str, 'TYPE_var']]], - kwargs: 'TYPE_kwargs') -> build.EnvironmentVariables: + kwargs: 'TYPE_kwargs') -> EnvironmentVariables: init = args[0] if init is not None: FeatureNew.single_use('environment positional arguments', '0.52.0', self.subproject, location=node) @@ -2977,7 +2976,7 @@ def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[Non if isinstance(init, dict) and any(i for i in init.values() if isinstance(i, list)): FeatureNew.single_use('List of string in dictionary value', '0.62.0', self.subproject, location=node) return env_convertor_with_method(init, kwargs['method'], kwargs['separator']) - return build.EnvironmentVariables() + return EnvironmentVariables() @typed_pos_args('join_paths', varargs=str, min_varargs=1) @noKwargs diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index fac3b0e55ad4..8648b487fd2f 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -203,7 +203,7 @@ class RunProcess(MesonInterpreterObject): def __init__(self, cmd: ExternalProgram, args: T.List[str], - env: build.EnvironmentVariables, + env: mesonlib.EnvironmentVariables, source_dir: str, build_dir: str, subdir: str, @@ -224,7 +224,7 @@ def __init__(self, def run_command(self, cmd: ExternalProgram, args: T.List[str], - env: build.EnvironmentVariables, + env: mesonlib.EnvironmentVariables, source_dir: str, build_dir: str, subdir: str, @@ -280,9 +280,9 @@ def stdout_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self.stderr -class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], MutableInterpreterObject): +class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], MutableInterpreterObject): - def __init__(self, obj: build.EnvironmentVariables, interpreter: 'Interpreter'): + def __init__(self, obj: mesonlib.EnvironmentVariables, interpreter: 'Interpreter'): super().__init__(obj, interpreter) self.methods.update({'set': self.set_method, 'append': self.append_method, @@ -711,7 +711,7 @@ def __init__(self, name: str, project: str, suite: T.List[str], depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]], is_parallel: bool, cmd_args: T.List[T.Union[str, mesonlib.File, build.Target]], - env: build.EnvironmentVariables, + env: mesonlib.EnvironmentVariables, should_fail: bool, timeout: int, workdir: T.Optional[str], protocol: str, priority: int, verbose: bool): super().__init__() diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index cf476cefbb1a..cc48e7ab174a 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -12,7 +12,7 @@ from .. import build from .. import coredata from ..compilers import Compiler -from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey +from ..mesonlib import EnvironmentVariables, MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram @@ -42,7 +42,7 @@ class BaseTest(TypedDict): workdir: T.Optional[str] depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] priority: int - env: build.EnvironmentVariables + env: EnvironmentVariables suite: T.List[str] @@ -164,7 +164,7 @@ class RunTarget(TypedDict): command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, ExternalProgram, File]] depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] - env: build.EnvironmentVariables + env: EnvironmentVariables class CustomTarget(TypedDict): @@ -179,7 +179,7 @@ class CustomTarget(TypedDict): depend_files: T.List[FileOrString] depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] depfile: T.Optional[str] - env: build.EnvironmentVariables + env: EnvironmentVariables feed: bool input: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, build.ExtractedObjects, build.GeneratedList, ExternalProgram, File]] @@ -196,7 +196,7 @@ class AddTestSetup(TypedDict): timeout_multiplier: int is_default: bool exclude_suites: T.List[str] - env: build.EnvironmentVariables + env: EnvironmentVariables class Project(TypedDict): @@ -240,7 +240,7 @@ class RunCommand(TypedDict): check: bool capture: T.Optional[bool] - env: build.EnvironmentVariables + env: EnvironmentVariables class FeatureOptionRequire(TypedDict): diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 73df5edd19c7..66029a01999c 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -21,14 +21,13 @@ from .type_checking import NATIVE_KW, NoneType if T.TYPE_CHECKING: - from typing_extensions import Literal - from ..backend.backends import ExecutableSerialisation + from typing_extensions import Literal, TypedDict + from ..compilers import Compiler from ..interpreterbase import TYPE_kwargs, TYPE_var + from ..mesonlib import ExecutableSerialisation from .interpreter import Interpreter - from typing_extensions import TypedDict - class FuncOverrideDependency(TypedDict): native: mesonlib.MachineChoice @@ -456,15 +455,15 @@ def has_external_property_method(self, args: T.Tuple[str], kwargs: 'NativeKW') - @FeatureNew('add_devenv', '0.58.0') @typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0')) - @typed_pos_args('add_devenv', (str, list, dict, build.EnvironmentVariables)) - def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, build.EnvironmentVariables]], + @typed_pos_args('add_devenv', (str, list, dict, mesonlib.EnvironmentVariables)) + def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, mesonlib.EnvironmentVariables]], kwargs: 'AddDevenvKW') -> None: env = args[0] msg = ENV_KW.validator(env) if msg: raise build.InvalidArguments(f'"add_devenv": {msg}') converted = env_convertor_with_method(env, kwargs['method'], kwargs['separator']) - assert isinstance(converted, build.EnvironmentVariables) + assert isinstance(converted, mesonlib.EnvironmentVariables) self.build.devenv.append(converted) @noPosargs diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index 64e02c27067c..10683fdbf895 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -29,8 +29,7 @@ from typing_extensions import Protocol from .. import mparser - from .baseobjects import InterpreterObject, TV_func, TYPE_var, TYPE_kwargs - from .interpreterbase import SubProject + from .baseobjects import InterpreterObject, SubProject, TV_func, TYPE_var, TYPE_kwargs from .operator import MesonOperator _TV_IntegerObject = T.TypeVar('_TV_IntegerObject', bound=InterpreterObject, contravariant=True) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 5f854d0fae27..d039f6dfbbc2 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -36,7 +36,6 @@ InterpreterException, InvalidArguments, InvalidCode, - MesonException, SubdirDoneRequest, ) @@ -319,12 +318,12 @@ def evaluate_testcase(self, node: mparser.TestCaseClauseNode) -> T.Optional[Disa def evaluate_comparison(self, node: mparser.ComparisonNode) -> InterpreterObject: val1 = self.evaluate_statement(node.left) if val1 is None: - raise MesonException('Cannot compare a void statement on the left-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the left-hand side') if isinstance(val1, Disabler): return val1 val2 = self.evaluate_statement(node.right) if val2 is None: - raise MesonException('Cannot compare a void statement on the right-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the right-hand side') if isinstance(val2, Disabler): return val2 @@ -350,7 +349,7 @@ def evaluate_comparison(self, node: mparser.ComparisonNode) -> InterpreterObject def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject: l = self.evaluate_statement(cur.left) if l is None: - raise MesonException('Cannot compare a void statement on the left-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the left-hand side') if isinstance(l, Disabler): return l l_bool = l.operator_call(MesonOperator.BOOL, None) @@ -358,7 +357,7 @@ def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject: return self._holderify(l_bool) r = self.evaluate_statement(cur.right) if r is None: - raise MesonException('Cannot compare a void statement on the right-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the right-hand side') if isinstance(r, Disabler): return r return self._holderify(r.operator_call(MesonOperator.BOOL, None)) @@ -366,7 +365,7 @@ def evaluate_andstatement(self, cur: mparser.AndNode) -> InterpreterObject: def evaluate_orstatement(self, cur: mparser.OrNode) -> InterpreterObject: l = self.evaluate_statement(cur.left) if l is None: - raise MesonException('Cannot compare a void statement on the left-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the left-hand side') if isinstance(l, Disabler): return l l_bool = l.operator_call(MesonOperator.BOOL, None) @@ -374,7 +373,7 @@ def evaluate_orstatement(self, cur: mparser.OrNode) -> InterpreterObject: return self._holderify(l_bool) r = self.evaluate_statement(cur.right) if r is None: - raise MesonException('Cannot compare a void statement on the right-hand side') + raise mesonlib.MesonException('Cannot compare a void statement on the right-hand side') if isinstance(r, Disabler): return r return self._holderify(r.operator_call(MesonOperator.BOOL, None)) @@ -413,7 +412,7 @@ def evaluate_ternary(self, node: mparser.TernaryNode) -> T.Optional[InterpreterO assert isinstance(node, mparser.TernaryNode) result = self.evaluate_statement(node.condition) if result is None: - raise MesonException('Cannot use a void statement as condition for ternary operator.') + raise mesonlib.MesonException('Cannot use a void statement as condition for ternary operator.') if isinstance(result, Disabler): return result result.current_node = node diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index ddd2ee2d7ff8..d4ecce8719bf 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -26,7 +26,7 @@ from . import mesonlib from . import mintro from . import mlog -from .ast import AstIDGenerator +from .ast import AstIDGenerator, IntrospectionInterpreter from .mesonlib import MachineChoice, OptionKey if T.TYPE_CHECKING: @@ -81,7 +81,7 @@ def __init__(self, build_dir: str): # Make sure that log entries in other parts of meson don't interfere with the JSON output with mlog.no_logging(): self.source_dir = os.path.abspath(os.path.realpath(self.build_dir)) - intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()]) + intr = IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()]) intr.analyze() self.coredata = intr.coredata self.default_values_only = True diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 9c298478d87d..46b1b605de35 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -8,7 +8,7 @@ from pathlib import Path from . import build, minstall -from .mesonlib import (MesonException, is_windows, setup_vsenv, OptionKey, +from .mesonlib import (EnvironmentVariables, MesonException, is_windows, setup_vsenv, OptionKey, get_wine_shortpath, MachineChoice) from . import mlog @@ -55,7 +55,7 @@ def reduce_winepath(env: T.Dict[str, str]) -> None: mlog.log('Meson detected wine and has set WINEPATH accordingly') def get_env(b: build.Build, dump_fmt: T.Optional[str]) -> T.Tuple[T.Dict[str, str], T.Set[str]]: - extra_env = build.EnvironmentVariables() + extra_env = EnvironmentVariables() extra_env.set('MESON_DEVENV', ['1']) extra_env.set('MESON_PROJECT_NAME', [b.project_name]) diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 49006917e914..a9c561f770a3 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -25,7 +25,7 @@ import typing as T import re -from . import build, coredata, environment +from . import build, environment from .backend.backends import InstallData from .mesonlib import (MesonException, Popen_safe, RealPathAction, is_windows, is_aix, setup_vsenv, pickle_load, is_osx, OptionKey) @@ -40,10 +40,10 @@ if T.TYPE_CHECKING: from .backend.backends import ( - ExecutableSerialisation, InstallDataBase, InstallEmptyDir, + InstallDataBase, InstallEmptyDir, InstallSymlinkData, TargetInstallData ) - from .mesonlib import FileMode, EnvironOrDict + from .mesonlib import FileMode, EnvironOrDict, ExecutableSerialisation try: from typing import Protocol @@ -847,7 +847,7 @@ def run(opts: 'ArgumentType') -> int: b = build.load(opts.wd) need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) setup_vsenv(need_vsenv) - backend = T.cast('str', b.environment.coredata.get_option(coredata.OptionKey('backend'))) + backend = T.cast('str', b.environment.coredata.get_option(OptionKey('backend'))) if not rebuild_all(opts.wd, backend): sys.exit(-1) os.chdir(opts.wd) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index ab303b3f520b..1d1e858ac71e 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -444,7 +444,7 @@ def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict else: fname = t.fname to['cmd'] = fname + t.cmd_args - if isinstance(t.env, build.EnvironmentVariables): + if isinstance(t.env, mesonlib.EnvironmentVariables): to['env'] = t.env.get_env({}) else: to['env'] = t.env diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index daac9edb6dab..b46b3007708c 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -30,7 +30,6 @@ from ..interpreterbase import TYPE_var, TYPE_kwargs from ..programs import OverrideProgram from ..wrap import WrapMode - from ..build import Executable from ..dependencies import Dependency class ModuleState: @@ -87,16 +86,16 @@ def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDi def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]], required: bool = True, - version_func: T.Optional[T.Callable[[T.Union[ExternalProgram, Executable, OverrideProgram]], str]] = None, + version_func: T.Optional[T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str]] = None, wanted: T.Optional[str] = None, silent: bool = False, - for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, Executable, OverrideProgram]: + for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.Executable, OverrideProgram]: if not isinstance(prog, list): prog = [prog] return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted, silent=silent, for_machine=for_machine) def find_tool(self, name: str, depname: str, varname: str, required: bool = True, - wanted: T.Optional[str] = None) -> T.Union['Executable', ExternalProgram, 'OverrideProgram']: + wanted: T.Optional[str] = None) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']: # Look in overrides in case it's built as subproject progobj = self._interpreter.program_from_overrides([name], []) if progobj is not None: @@ -256,10 +255,10 @@ def is_module_library(fname: mesonlib.FileOrString) -> bool: class ModuleReturnValue: def __init__(self, return_value: T.Optional['TYPE_var'], - new_objects: T.Sequence[T.Union['TYPE_var', 'build.ExecutableSerialisation']]) -> None: + new_objects: T.Sequence[T.Union['TYPE_var', 'mesonlib.ExecutableSerialisation']]) -> None: self.return_value = return_value assert isinstance(new_objects, list) - self.new_objects: T.List[T.Union['TYPE_var', 'build.ExecutableSerialisation']] = new_objects + self.new_objects: T.List[T.Union['TYPE_var', 'mesonlib.ExecutableSerialisation']] = new_objects class GResourceTarget(build.CustomTarget): pass diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index a1d851491322..fd7e7c885f05 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -39,6 +39,7 @@ from ..build import BuildTarget, CustomTarget from ..interpreter import Interpreter from ..interpreterbase import TYPE_var + from ..mesonlib import EnvironmentVariables class Dependency(TypedDict): @@ -49,7 +50,7 @@ class AddProject(TypedDict): configure_options: T.List[str] cross_configure_options: T.List[str] verbose: bool - env: build.EnvironmentVariables + env: EnvironmentVariables depends: T.List[T.Union[BuildTarget, CustomTarget]] @@ -62,7 +63,7 @@ def __init__(self, configure_command: str, configure_options: T.List[str], cross_configure_options: T.List[str], - env: build.EnvironmentVariables, + env: EnvironmentVariables, verbose: bool, extra_depends: T.List[T.Union['BuildTarget', 'CustomTarget']]): super().__init__() diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 755bf240b15a..32d53eff7243 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -272,7 +272,7 @@ def __init__(self, interpreter: 'Interpreter') -> None: self.install_gtk_update_icon_cache = False self.install_update_desktop_database = False self.install_update_mime_database = False - self.devenv: T.Optional[build.EnvironmentVariables] = None + self.devenv: T.Optional[mesonlib.EnvironmentVariables] = None self.native_glib_version: T.Optional[str] = None self.methods.update({ 'post_install': self.post_install, @@ -328,7 +328,7 @@ def _print_gdbus_warning() -> None: @noPosargs @FeatureNew('gnome.post_install', '0.57.0') def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'PostInstall') -> ModuleReturnValue: - rv: T.List['build.ExecutableSerialisation'] = [] + rv: T.List['mesonlib.ExecutableSerialisation'] = [] datadir_abs = os.path.join(state.environment.get_prefix(), state.environment.get_datadir()) if kwargs['glib_compile_schemas'] and not self.install_glib_compile_schemas: self.install_glib_compile_schemas = True @@ -769,7 +769,7 @@ def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLi def _devenv_prepend(self, varname: str, value: str) -> None: if self.devenv is None: - self.devenv = build.EnvironmentVariables() + self.devenv = mesonlib.EnvironmentVariables() self.devenv.prepend(varname, [value]) def postconf_hook(self, b: build.Build) -> None: @@ -1522,7 +1522,7 @@ def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: check_args = (targetname + '-check', check_cmd) check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir) state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target]) - res: T.List[T.Union[build.Target, build.ExecutableSerialisation]] = [custom_target, alias_target] + res: T.List[T.Union[build.Target, mesonlib.ExecutableSerialisation]] = [custom_target, alias_target] if kwargs['install']: res.append(state.backend.get_executable_serialisation(command + t_args, tag='doc')) return ModuleReturnValue(custom_target, res) diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index ad5ae3079dba..cf1a2477c3ba 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -20,7 +20,7 @@ from mesonbuild import mesonlib from mesonbuild import mlog, build -from mesonbuild.coredata import MesonException +from mesonbuild.mesonlib import MesonException from . import ModuleReturnValue, ModuleInfo from . import ExtensionModule from ..dependencies import Dependency, InternalDependency diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 9f71d952cfec..c6bc42d095bd 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -381,7 +381,7 @@ class PkgConfigModule(NewExtensionModule): # Track already generated pkg-config files This is stored as a class # variable so that multiple `import()`s share metadata - devenv: T.Optional[build.EnvironmentVariables] = None + devenv: T.Optional[mesonlib.EnvironmentVariables] = None _metadata: T.ClassVar[T.Dict[str, MetaData]] = {} def __init__(self) -> None: diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index ac74e13dc5b7..1f05f08d4488 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -43,7 +43,7 @@ from ..dependencies import Dependency from ..interpreter import Interpreter from ..interpreter.kwargs import ExtractRequired - from ..interpreterbase.interpreterbase import TYPE_var, TYPE_kwargs + from ..interpreterbase.baseobjects import TYPE_var, TYPE_kwargs class PyInstallKw(TypedDict): diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 88995c0fedeb..0e1086c35c78 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -44,9 +44,9 @@ from . import build from . import environment from . import mlog -from .coredata import MesonVersionMismatchException, OptionKey, major_versions_differ +from .coredata import MesonVersionMismatchException, major_versions_differ from .coredata import version as coredata_version -from .mesonlib import (MesonException, OrderedSet, RealPathAction, +from .mesonlib import (MesonException, OptionKey, OrderedSet, RealPathAction, get_wine_shortpath, join_args, split_args, setup_vsenv) from .mintro import get_infodir, load_info_file from .programs import ExternalProgram diff --git a/mesonbuild/programs.py b/mesonbuild/programs.py index 9bf1844c9d85..13b998193e84 100644 --- a/mesonbuild/programs.py +++ b/mesonbuild/programs.py @@ -103,13 +103,12 @@ def description(self) -> str: def get_version(self, interpreter: T.Optional['Interpreter'] = None) -> str: if not self.cached_version: - from . import build raw_cmd = self.get_command() + ['--version'] if interpreter: res = interpreter.run_command_impl(interpreter.current_node, (self, ['--version']), {'capture': True, 'check': True, - 'env': build.EnvironmentVariables()}, + 'env': mesonlib.EnvironmentVariables()}, True) o, e = res.stdout, res.stderr else: diff --git a/mesonbuild/utils/posix.py b/mesonbuild/utils/posix.py index 51c3cd06048a..cd05d2758652 100644 --- a/mesonbuild/utils/posix.py +++ b/mesonbuild/utils/posix.py @@ -20,7 +20,7 @@ import fcntl import typing as T -from .universal import MesonException +from .core import MesonException from .platform import BuildDirLock as BuildDirLockBase __all__ = ['BuildDirLock'] diff --git a/mesonbuild/utils/vsenv.py b/mesonbuild/utils/vsenv.py index 3c2687884de2..550a8cf54526 100644 --- a/mesonbuild/utils/vsenv.py +++ b/mesonbuild/utils/vsenv.py @@ -8,7 +8,8 @@ import tempfile from .. import mlog -from .universal import MesonException, is_windows, windows_detect_native_arch +from .core import MesonException +from .universal import is_windows, windows_detect_native_arch __all__ = [ diff --git a/mesonbuild/utils/win32.py b/mesonbuild/utils/win32.py index 2bd4cba8d0f0..18ee0d04e210 100644 --- a/mesonbuild/utils/win32.py +++ b/mesonbuild/utils/win32.py @@ -20,7 +20,7 @@ import msvcrt import typing as T -from .universal import MesonException +from .core import MesonException from .platform import BuildDirLock as BuildDirLockBase __all__ = ['BuildDirLock'] From cff2fb5950cb37b01df5046cc256826449b3abaa Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 11:11:49 -0400 Subject: [PATCH 019/855] avoid module indirection in name resolution for imported objects We already import a bunch of objects directly from ..build but don't use them nearly as much as we can. This resulted both in longer lines and s minor performance difference since python has to resolve the name binding the long way. There's no reason not to rewrite these names to use the direct imports. Found while investigating the fact that Executable was imported but never used. It's easier to just use it. --- mesonbuild/modules/gnome.py | 112 ++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 32d53eff7243..3249212b9c5d 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -79,7 +79,7 @@ class CompileResources(TypedDict): build_by_default: bool c_name: T.Optional[str] - dependencies: T.List[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]] + dependencies: T.List[T.Union[mesonlib.File, CustomTarget, CustomTargetIndex]] export: bool extra_args: T.List[str] gresource_bundle: bool @@ -221,7 +221,7 @@ class MkEnums(_MkEnumsCommon): INSTALL_DIR_KW, KwargInfo( 'sources', - ContainerTypeInfo(list, (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), + ContainerTypeInfo(list, (str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList)), listify=True, required=True, ), @@ -265,8 +265,8 @@ class GnomeModule(ExtensionModule): def __init__(self, interpreter: 'Interpreter') -> None: super().__init__(interpreter) self.gir_dep: T.Optional[Dependency] = None - self.giscanner: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None - self.gicompiler: T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]] = None + self.giscanner: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None + self.gicompiler: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None self.install_glib_compile_schemas = False self.install_gio_querymodules: T.List[str] = [] self.install_gtk_update_icon_cache = False @@ -348,7 +348,7 @@ def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' if kwargs['gtk_update_icon_cache'] and not self.install_gtk_update_icon_cache: self.install_gtk_update_icon_cache = True prog = state.find_program('gtk4-update-icon-cache', required=False) - found = isinstance(prog, build.Executable) or prog.found() + found = isinstance(prog, Executable) or prog.found() if not found: prog = state.find_program('gtk-update-icon-cache') icondir = os.path.join(datadir_abs, 'icons', 'hicolor') @@ -371,7 +371,7 @@ def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' rv.append(script) return ModuleReturnValue(None, rv) - @typed_pos_args('gnome.compile_resources', str, (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) + @typed_pos_args('gnome.compile_resources', str, (str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList)) @typed_kwargs( 'gnome.compile_resources', _BUILD_BY_DEFAULT, @@ -380,7 +380,7 @@ def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' INSTALL_KW.evolve(name='install_header', since='0.37.0'), INSTALL_DIR_KW, KwargInfo('c_name', (str, NoneType)), - KwargInfo('dependencies', ContainerTypeInfo(list, (mesonlib.File, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo('dependencies', ContainerTypeInfo(list, (mesonlib.File, CustomTarget, CustomTargetIndex)), default=[], listify=True), KwargInfo('export', bool, default=False, since='0.37.0'), KwargInfo('gresource_bundle', bool, default=False, since='0.37.0'), KwargInfo('source_dir', ContainerTypeInfo(list, str), default=[], listify=True), @@ -400,7 +400,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri # Validate dependencies subdirs: T.List[str] = [] - depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = [] + depends: T.List[T.Union[CustomTarget, CustomTargetIndex]] = [] for dep in dependencies: if isinstance(dep, mesonlib.File): subdirs.append(dep.subdir) @@ -427,7 +427,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri else: ifile = os.path.join(input_file.subdir, input_file.fname) - elif isinstance(input_file, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)): + elif isinstance(input_file, (CustomTarget, CustomTargetIndex, GeneratedList)): raise MesonException('Resource xml files generated at build-time cannot be used with ' 'gnome.compile_resources() in the current version of glib-compile-resources ' 'because we need to scan the xml for dependencies due to ' @@ -531,8 +531,8 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri @staticmethod def _get_gresource_dependencies( state: 'ModuleState', input_file: str, source_dirs: T.List[str], - dependencies: T.Sequence[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex]] - ) -> T.Tuple[T.List[mesonlib.FileOrString], T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]], T.List[str]]: + dependencies: T.Sequence[T.Union[mesonlib.File, CustomTarget, CustomTargetIndex]] + ) -> T.Tuple[T.List[mesonlib.FileOrString], T.List[T.Union[CustomTarget, CustomTargetIndex]], T.List[str]]: cmd = ['glib-compile-resources', input_file, @@ -554,7 +554,7 @@ def _get_gresource_dependencies( raw_dep_files: T.List[str] = stdout.split('\n')[:-1] - depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex]] = [] + depends: T.List[T.Union[CustomTarget, CustomTargetIndex]] = [] subdirs: T.List[str] = [] dep_files: T.List[mesonlib.FileOrString] = [] for resfile in raw_dep_files.copy(): @@ -567,7 +567,7 @@ def _get_gresource_dependencies( dep_files.append(dep) subdirs.append(dep.subdir) break - elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): + elif isinstance(dep, (CustomTarget, CustomTargetIndex)): fname = None outputs = {(o, os.path.basename(o)) for o in dep.get_outputs()} for o, baseo in outputs: @@ -633,7 +633,7 @@ def _get_link_args(self, state: 'ModuleState', return link_command, new_depends def _get_dependencies_flags_raw( - self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, CustomTarget, CustomTargetIndex]], state: 'ModuleState', depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], include_rpath: bool, @@ -726,7 +726,7 @@ def fix_ldflags(ldflags: T.Iterable[T.Union[str, T.Tuple[str, str]]]) -> Ordered return cflags, internal_ldflags, external_ldflags, gi_includes, depends def _get_dependencies_flags( - self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, CustomTarget, CustomTargetIndex]], state: 'ModuleState', depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], include_rpath: bool = False, @@ -752,9 +752,9 @@ def _get_dependencies_flags( return cflags, internal_ldflags, external_ldflags, gi_includes, depends - def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState' - ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary]: - if not isinstance(girtarget, (build.Executable, build.SharedLibrary, + def _unwrap_gir_target(self, girtarget: T.Union[Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState' + ) -> T.Union[Executable, build.StaticLibrary, build.SharedLibrary]: + if not isinstance(girtarget, (Executable, build.SharedLibrary, build.StaticLibrary)): raise MesonException(f'Gir target must be an executable or library but is "{girtarget}" of type {type(girtarget).__name__}') @@ -776,8 +776,8 @@ def postconf_hook(self, b: build.Build) -> None: if self.devenv is not None: b.devenv.append(self.devenv) - def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram'], - T.Union[build.Executable, 'ExternalProgram', 'OverrideProgram']]: + def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[Executable, 'ExternalProgram', 'OverrideProgram'], + T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]: if not self.gir_dep: self.gir_dep = state.dependency('gobject-introspection-1.0') self.giscanner = state.find_tool('g-ir-scanner', 'gobject-introspection-1.0', 'g_ir_scanner') @@ -825,11 +825,11 @@ def _scan_langs(state: 'ModuleState', langs: T.Iterable[str]) -> T.List[str]: return ret @staticmethod - def _scan_gir_targets(state: 'ModuleState', girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Union[str, build.Executable]]: - ret: T.List[T.Union[str, build.Executable]] = [] + def _scan_gir_targets(state: 'ModuleState', girtargets: T.Sequence[build.BuildTarget]) -> T.List[T.Union[str, Executable]]: + ret: T.List[T.Union[str, Executable]] = [] for girtarget in girtargets: - if isinstance(girtarget, build.Executable): + if isinstance(girtarget, Executable): ret += ['--program', girtarget] else: # Because of https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/72 @@ -872,8 +872,8 @@ def _get_girtargets_langs_compilers(girtargets: T.Sequence[build.BuildTarget]) - @staticmethod def _get_gir_targets_deps(girtargets: T.Sequence[build.BuildTarget] - ) -> T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]]: - ret: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, Dependency]] = [] + ) -> T.List[T.Union[build.BuildTarget, CustomTarget, CustomTargetIndex, Dependency]]: + ret: T.List[T.Union[build.BuildTarget, CustomTarget, CustomTargetIndex, Dependency]] = [] for girtarget in girtargets: ret += girtarget.get_all_link_deps() ret += girtarget.get_external_deps() @@ -919,8 +919,8 @@ def _get_langs_compilers_flags(state: 'ModuleState', langs_compilers: T.List[T.T def _make_gir_filelist(state: 'ModuleState', srcdir: str, ns: str, nsversion: str, girtargets: T.Sequence[build.BuildTarget], libsources: T.Sequence[T.Union[ - str, mesonlib.File, build.GeneratedList, - build.CustomTarget, build.CustomTargetIndex]] + str, mesonlib.File, GeneratedList, + CustomTarget, CustomTargetIndex]] ) -> str: gir_filelist_dir = state.backend.get_target_private_dir_abs(girtargets[0]) if not os.path.isdir(gir_filelist_dir): @@ -929,14 +929,14 @@ def _make_gir_filelist(state: 'ModuleState', srcdir: str, ns: str, with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist: for s in libsources: - if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): + if isinstance(s, (CustomTarget, CustomTargetIndex)): for custom_output in s.get_outputs(): gir_filelist.write(os.path.join(state.environment.get_build_dir(), state.backend.get_target_dir(s), custom_output) + '\n') elif isinstance(s, mesonlib.File): gir_filelist.write(s.rel_to_builddir(state.build_to_src) + '\n') - elif isinstance(s, build.GeneratedList): + elif isinstance(s, GeneratedList): for gen_src in s.get_outputs(): gir_filelist.write(os.path.join(srcdir, gen_src) + '\n') else: @@ -949,7 +949,7 @@ def _make_gir_target( state: 'ModuleState', girfile: str, scan_command: T.Sequence[T.Union['FileOrString', Executable, ExternalProgram, OverrideProgram]], - generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + generated_files: T.Sequence[T.Union[str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList]], depends: T.Sequence[T.Union['FileOrString', build.BuildTarget, 'build.GeneratedTypes', build.StructuredSources]], kwargs: T.Dict[str, T.Any]) -> GirTarget: install = kwargs['install_gir'] @@ -991,8 +991,8 @@ def _make_gir_target( @staticmethod def _make_typelib_target(state: 'ModuleState', typelib_output: str, - typelib_cmd: T.Sequence[T.Union[str, build.Executable, ExternalProgram, build.CustomTarget]], - generated_files: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + typelib_cmd: T.Sequence[T.Union[str, Executable, ExternalProgram, CustomTarget]], + generated_files: T.Sequence[T.Union[str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList]], kwargs: T.Dict[str, T.Any]) -> TypelibTarget: install = kwargs['install_typelib'] if install is None: @@ -1022,7 +1022,7 @@ def _make_typelib_target(state: 'ModuleState', typelib_output: str, @staticmethod def _gather_typelib_includes_and_update_depends( state: 'ModuleState', - deps: T.Sequence[T.Union[Dependency, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + deps: T.Sequence[T.Union[Dependency, build.BuildTarget, CustomTarget, CustomTargetIndex]], depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]] ) -> T.Tuple[T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: # Need to recursively add deps on GirTarget sources from our @@ -1083,7 +1083,7 @@ def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]: if f.startswith(('-L', '-l', '--extra-library')): yield f - @typed_pos_args('gnome.generate_gir', varargs=(build.Executable, build.SharedLibrary, build.StaticLibrary), min_varargs=1) + @typed_pos_args('gnome.generate_gir', varargs=(Executable, build.SharedLibrary, build.StaticLibrary), min_varargs=1) @typed_kwargs( 'gnome.generate_gir', INSTALL_KW, @@ -1108,13 +1108,13 @@ def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]: KwargInfo('link_with', ContainerTypeInfo(list, (build.SharedLibrary, build.StaticLibrary)), default=[], listify=True), KwargInfo('namespace', str, required=True), KwargInfo('nsversion', str, required=True), - KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo('sources', ContainerTypeInfo(list, (str, mesonlib.File, GeneratedList, CustomTarget, CustomTargetIndex)), default=[], listify=True), KwargInfo('symbol_prefix', ContainerTypeInfo(list, str), default=[], listify=True), ) - def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[build.Executable, build.SharedLibrary, build.StaticLibrary]]], + def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[Executable, build.SharedLibrary, build.StaticLibrary]]], kwargs: 'GenerateGir') -> ModuleReturnValue: girtargets = [self._unwrap_gir_target(arg, state) for arg in args[0]] - if len(girtargets) > 1 and any(isinstance(el, build.Executable) for el in girtargets): + if len(girtargets) > 1 and any(isinstance(el, Executable) for el in girtargets): raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable') gir_dep, giscanner, gicompiler = self._get_gir_dep(state) @@ -1157,7 +1157,7 @@ def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[build. gir_inc_dirs: T.List[str] = [] - scan_command: T.List[T.Union[str, build.Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner] + scan_command: T.List[T.Union[str, Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner] scan_command += ['--quiet'] scan_command += ['--no-libtool'] scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion] @@ -1232,7 +1232,7 @@ def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs targetname = 'gsettings-compile' else: targetname = 'gsettings-compile-' + state.subdir.replace('/', '_') - target_g = build.CustomTarget( + target_g = CustomTarget( targetname, state.subdir, state.subproject, @@ -1346,7 +1346,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y potargets.append(potarget) gmo_file = project_id + '-' + l + '.gmo' - gmotarget = build.CustomTarget( + gmotarget = CustomTarget( f'help-{project_id}-{l}-gmo', l_subdir, state.subproject, @@ -1358,7 +1358,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y ) targets.append(gmotarget) - mergetarget = build.CustomTarget( + mergetarget = CustomTarget( f'help-{project_id}-{l}', l_subdir, state.subproject, @@ -1384,7 +1384,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y 'gnome.gtkdoc', KwargInfo('c_args', ContainerTypeInfo(list, str), since='0.48.0', default=[], listify=True), KwargInfo('check', bool, default=False, since='0.52.0'), - KwargInfo('content_files', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True), + KwargInfo('content_files', ContainerTypeInfo(list, (str, mesonlib.File, GeneratedList, CustomTarget, CustomTargetIndex)), default=[], listify=True), KwargInfo( 'dependencies', ContainerTypeInfo(list, (Dependency, build.SharedLibrary, build.StaticLibrary)), @@ -1475,7 +1475,7 @@ def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: depends: T.List['build.GeneratedTypes'] = [] content_files = [] for s in kwargs['content_files']: - if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): + if isinstance(s, (CustomTarget, CustomTargetIndex)): depends.append(s) for o in s.get_outputs(): content_files.append(os.path.join(state.environment.get_build_dir(), @@ -1484,7 +1484,7 @@ def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: elif isinstance(s, mesonlib.File): content_files.append(s.absolute_path(state.environment.get_source_dir(), state.environment.get_build_dir())) - elif isinstance(s, build.GeneratedList): + elif isinstance(s, GeneratedList): depends.append(s) for gen_src in s.get_outputs(): content_files.append(os.path.join(state.environment.get_source_dir(), @@ -1503,7 +1503,7 @@ def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: kwargs['dependencies'], state, depends) t_args.extend(build_args) new_depends.extend(depends) - custom_target = build.CustomTarget( + custom_target = CustomTarget( targetname, state.subdir, state.subproject, @@ -1566,7 +1566,7 @@ def _get_build_args(self, c_args: T.List[str], inc_dirs: T.List[T.Union[str, bui def gtkdoc_html_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> str: return os.path.join('share/gtk-doc/html', args[0]) - @typed_pos_args('gnome.gdbus_codegen', str, optargs=[(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)]) + @typed_pos_args('gnome.gdbus_codegen', str, optargs=[(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList)]) @typed_kwargs( 'gnome.gdbus_codegen', _BUILD_BY_DEFAULT.evolve(since='0.40.0'), @@ -1647,7 +1647,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un cmd += ['--generate-c-code', '@OUTDIR@/' + namebase, '@INPUT@'] c_cmd = cmd - cfile_custom_target = build.CustomTarget( + cfile_custom_target = CustomTarget( output, state.subdir, state.subproject, @@ -1667,7 +1667,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un hfile_cmd = cmd depends = [cfile_custom_target] - hfile_custom_target = build.CustomTarget( + hfile_custom_target = CustomTarget( output, state.subdir, state.subproject, @@ -1698,7 +1698,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un docbook_cmd = cmd depends = [cfile_custom_target] - docbook_custom_target = build.CustomTarget( + docbook_custom_target = CustomTarget( output, state.subdir, state.subproject, @@ -1902,20 +1902,20 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn @staticmethod def _make_mkenum_impl( state: 'ModuleState', - sources: T.Sequence[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]], + sources: T.Sequence[T.Union[str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList]], output: str, cmd: T.List[str], *, install: bool = False, install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None, depends: T.Optional[T.Sequence[T.Union[CustomTarget, CustomTargetIndex, BuildTarget]]] = None - ) -> build.CustomTarget: + ) -> CustomTarget: real_cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program(['glib-mkenums', 'mkenums'])] real_cmd.extend(cmd) _install_dir = install_dir or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) assert isinstance(_install_dir, str), 'for mypy' - return build.CustomTarget( + return CustomTarget( output, state.subdir, state.subproject, @@ -1983,7 +1983,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh h_cmd = cmd + ['--header', '@INPUT@'] if new_genmarshal: h_cmd += ['--pragma-once'] - header = build.CustomTarget( + header = CustomTarget( output + '_h', state.subdir, state.subproject, @@ -1999,12 +1999,12 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh ) c_cmd = cmd + ['--body', '@INPUT@'] - extra_deps: T.List[build.CustomTarget] = [] + extra_deps: T.List[CustomTarget] = [] if mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.4'): # Silence any warnings about missing prototypes c_cmd += ['--include-header', header_file] extra_deps.append(header) - body = build.CustomTarget( + body = CustomTarget( output + '_c', state.subdir, state.subproject, @@ -2068,7 +2068,7 @@ def _generate_deps(self, state: 'ModuleState', library: str, packages: T.List[st ofile.write(package + '\n') return build.Data([mesonlib.File(True, outdir, fname)], install_dir, install_dir, mesonlib.FileMode(), state.subproject) - def _get_vapi_link_with(self, target: build.CustomTarget) -> T.List[build.LibTypes]: + def _get_vapi_link_with(self, target: CustomTarget) -> T.List[build.LibTypes]: link_with: T.List[build.LibTypes] = [] for dep in target.get_target_dependencies(): if isinstance(dep, build.SharedLibrary): From 0bb1647fd15cc112098daf9961b2e01cb4e9cd23 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 3 Jul 2023 12:41:39 -0400 Subject: [PATCH 020/855] move various bits of type-checking only code to TYPE_CHECKING blocks Mostly detected with flake8-type-checking. Also quote T.cast() first arguments, since those are not affected by future annotations. --- mesonbuild/build.py | 3 ++- mesonbuild/cargo/builder.py | 4 +++- mesonbuild/cargo/interpreter.py | 2 +- mesonbuild/environment.py | 2 +- mesonbuild/interpreterbase/interpreterbase.py | 3 +-- mesonbuild/mintro.py | 2 +- mesonbuild/modules/python.py | 2 +- mesonbuild/modules/rust.py | 6 +++--- mesonbuild/msubprojects.py | 4 +++- 9 files changed, 16 insertions(+), 12 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d588c9db8fb4..6438b836d461 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -26,7 +26,6 @@ import typing as T from . import coredata -from . import environment from . import dependencies from . import mlog from . import programs @@ -46,6 +45,8 @@ if T.TYPE_CHECKING: from typing_extensions import Literal + + from . import environment from ._typing import ImmutableListProtocol from .backend.backends import Backend from .compilers import Compiler diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 49bc65db5e86..fb086d1640ef 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -8,12 +8,14 @@ """ from __future__ import annotations -import builtins import dataclasses import typing as T from .. import mparser +if T.TYPE_CHECKING: + import builtins + def _token(tid: str, filename: str, value: mparser.TV_TokenTypes) -> mparser.Token[mparser.TV_TokenTypes]: """Create a Token object, but with the line numbers stubbed out. diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 59e1a1f068d1..8848a46a8d63 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -21,7 +21,6 @@ from . import builder from . import version -from .. import mparser from .._pathlib import Path from ..mesonlib import MesonException, Popen_safe @@ -29,6 +28,7 @@ from types import ModuleType from . import manifest + from .. import mparser from ..environment import Environment # tomllib is present in python 3.11, before that it is a pypi module called tomli, diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index ce7c9f1e6c02..3ec771315e17 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -33,7 +33,6 @@ ) from . import compilers from .compilers import ( - Compiler, is_assembly, is_header, is_library, @@ -49,6 +48,7 @@ import argparse from configparser import ConfigParser + from .compilers import Compiler from .wrap.wrap import Resolver CompilersDict = T.Dict[str, Compiler] diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index d039f6dfbbc2..9aff5b971feb 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -22,7 +22,6 @@ InterpreterObject, MesonInterpreterObject, MutableInterpreterObject, - InterpreterObjectTypeVar, ObjectHolder, IterableObject, ContextManagerObject, @@ -50,7 +49,7 @@ import textwrap if T.TYPE_CHECKING: - from .baseobjects import SubProject, TYPE_kwargs, TYPE_var + from .baseobjects import InterpreterObjectTypeVar, SubProject, TYPE_kwargs, TYPE_var from ..interpreter import Interpreter HolderMapType = T.Dict[ diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 1d1e858ac71e..063c5cdd6b57 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -429,7 +429,7 @@ def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str d = holder.held_object if isinstance(d, Dependency) and d.found(): if d.name in result: - T.cast(T.List[str], result[d.name]['meson_variables']).append(varname) + T.cast('T.List[str]', result[d.name]['meson_variables']).append(varname) else: result[d.name] = _create_result(d, varname) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 1f05f08d4488..f6c82e0d6f64 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -333,7 +333,7 @@ def should_append(f, isdir: bool = False): for i in self.installations.values(): if isinstance(i, PythonExternalProgram) and i.run_bytecompile[i.info['version']]: - i = T.cast(PythonExternalProgram, i) + i = T.cast('PythonExternalProgram', i) manifest = f'python-{i.info["version"]}-installed.json' manifest_json = [] for name, f in py_files: diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 3514412e65df..4f5494af31e8 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -18,16 +18,16 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, InvalidArguments, Jar, StructuredSources +from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources from ..compilers.compilers import are_asserts_disabled -from ..dependencies import Dependency, ExternalLibrary from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs from ..mesonlib import File if T.TYPE_CHECKING: from . import ModuleState - from ..build import LibTypes + from ..build import IncludeDirs, LibTypes + from ..dependencies import Dependency, ExternalLibrary from ..interpreter import Interpreter from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 3ecfba18fe6b..d1b51f04859e 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -16,12 +16,14 @@ from . import mlog from .ast import IntrospectionInterpreter, AstIDGenerator from .mesonlib import quiet_git, GitException, Popen_safe, MesonException, windows_proof_rmtree -from .wrap.wrap import (Resolver, WrapException, ALL_TYPES, PackageDefinition, +from .wrap.wrap import (Resolver, WrapException, ALL_TYPES, parse_patch_url, update_wrap_file, get_releases) if T.TYPE_CHECKING: from typing_extensions import Protocol + from .wrap.wrap import PackageDefinition + SubParsers = argparse._SubParsersAction[argparse.ArgumentParser] class Arguments(Protocol): From ded2204d2c0c24a6f338b4b71b2e1e0a0f184bf3 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 14 Jul 2023 15:17:33 -0400 Subject: [PATCH 021/855] ci: Add Rust Windows cross toolchain on ubuntu-rolling image --- ci/ciimage/build.py | 6 ++++++ ci/ciimage/ubuntu-rolling/install.sh | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py index 01979556dcfb..559723c0c1cc 100755 --- a/ci/ciimage/build.py +++ b/ci/ciimage/build.py @@ -74,6 +74,12 @@ def gen_bashrc(self) -> None: # Also add /ci to PATH out_data += 'export PATH="/ci:$PATH"\n' + out_data += ''' + if [ -f "$HOME/.cargo/env" ]; then + source "$HOME/.cargo/env" + fi + ''' + out_file.write_text(out_data, encoding='utf-8') # make it executable diff --git a/ci/ciimage/ubuntu-rolling/install.sh b/ci/ciimage/ubuntu-rolling/install.sh index 697ef060b2fb..a02eb8f5d3bb 100755 --- a/ci/ciimage/ubuntu-rolling/install.sh +++ b/ci/ciimage/ubuntu-rolling/install.sh @@ -50,6 +50,13 @@ dub_fetch dubtestproject dub build dubtestproject:test1 --compiler=ldc2 dub build dubtestproject:test2 --compiler=ldc2 +# Remove debian version of Rust and install latest with rustup. +# This is needed to get the cross toolchain as well. +apt-get -y remove rustc || true +wget -O - https://sh.rustup.rs | sh -s -- -y --profile minimal --component clippy +source "$HOME/.cargo/env" +rustup target add x86_64-pc-windows-gnu + # cleanup apt-get -y clean apt-get -y autoclean From 686f6aac31d56cfc73f0ccbae32c57661f602da1 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 12:46:15 -0700 Subject: [PATCH 022/855] intepreter: add kwargs annotations for build_target classes This doesn't do much yet, but with my advanced knowledge of what's coming this lays out most of what we're going to need --- mesonbuild/interpreter/interpreter.py | 19 +++++------ mesonbuild/interpreter/kwargs.py | 45 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index efca123ab618..2534efcec155 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1808,7 +1808,7 @@ def func_disabler(self, node, args, kwargs): @typed_kwargs('executable', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_executable(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.Executable: + kwargs: kwtypes.Executable) -> build.Executable: return self.build_target(node, args, kwargs, build.Executable) @permittedKwargs(build.known_stlib_kwargs) @@ -1816,7 +1816,7 @@ def func_executable(self, node: mparser.BaseNode, @typed_kwargs('static_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.StaticLibrary: + kwargs: kwtypes.StaticLibrary) -> build.StaticLibrary: return self.build_target(node, args, kwargs, build.StaticLibrary) @permittedKwargs(build.known_shlib_kwargs) @@ -1824,7 +1824,7 @@ def func_static_lib(self, node: mparser.BaseNode, @typed_kwargs('shared_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.SharedLibrary: + kwargs: kwtypes.SharedLibrary) -> build.SharedLibrary: holder = self.build_target(node, args, kwargs, build.SharedLibrary) holder.shared_library_only = True return holder @@ -1834,7 +1834,7 @@ def func_shared_lib(self, node: mparser.BaseNode, @typed_kwargs('both_libraries', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.BothLibraries: + kwargs: kwtypes.Library) -> build.BothLibraries: return self.build_both_libraries(node, args, kwargs) @FeatureNew('shared_module', '0.37.0') @@ -1843,7 +1843,7 @@ def func_both_lib(self, node: mparser.BaseNode, @typed_kwargs('shared_module', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.SharedModule: + kwargs: kwtypes.SharedModule) -> build.SharedModule: return self.build_target(node, args, kwargs, build.SharedModule) @permittedKwargs(known_library_kwargs) @@ -1851,7 +1851,7 @@ def func_shared_module(self, node: mparser.BaseNode, @typed_kwargs('library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_library(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> build.Executable: + kwargs: kwtypes.Library) -> build.Executable: return self.build_library(node, args, kwargs) @permittedKwargs(build.known_jar_kwargs) @@ -1859,7 +1859,7 @@ def func_library(self, node: mparser.BaseNode, @typed_kwargs('jar', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], - kwargs) -> build.Jar: + kwargs: kwtypes.Jar) -> build.Jar: return self.build_target(node, args, kwargs, build.Jar) @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @@ -1868,8 +1868,9 @@ def func_jar(self, node: mparser.BaseNode, @typed_kwargs('build_target', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], - kwargs) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, - build.SharedModule, build.BothLibraries, build.Jar]: + kwargs: kwtypes.BuildTarget + ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, + build.SharedModule, build.BothLibraries, build.Jar]: if 'target_type' not in kwargs: raise InterpreterException('Missing target_type keyword argument') target_type = kwargs.pop('target_type') diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index cc48e7ab174a..d46d4e3235ab 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -308,3 +308,48 @@ class DoSubproject(ExtractRequired): version: T.List[str] cmake_options: T.List[str] options: T.Optional[CMakeSubprojectOptions] + + +class _BaseBuildTarget(TypedDict): + + """Arguments used by all BuildTarget like functions. + + This really exists because Jar is so different than all of the other + BuildTarget functions. + """ + + override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] + + +class _BuildTarget(_BaseBuildTarget): + + """Arguments shared by non-JAR functions""" + + +class Executable(_BuildTarget): + pass + + +class StaticLibrary(_BuildTarget): + pass + + +class SharedLibrary(_BuildTarget): + pass + + +class SharedModule(_BuildTarget): + pass + + +class Library(_BuildTarget): + + """For library, both_library, and as a base for build_target""" + + +class BuildTarget(Library): + pass + + +class Jar(_BaseBuildTarget): + pass From 68da3669a41d3423bc5db593b66def8a59d2f625 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 13:04:50 -0700 Subject: [PATCH 023/855] interpreter: use type_checking defined target argument lists This moves to a list of shared objects inside the type_checking module. This is based on my experience of fully typing all of these functions several times, and will make it easier to slowly land all of the changes we want to make. --- mesonbuild/interpreter/interpreter.py | 24 +++++--- mesonbuild/interpreter/type_checking.py | 75 +++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 2534efcec155..853d858b93a2 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -50,12 +50,16 @@ NullSubprojectInterpreter, ) from .type_checking import ( + BUILD_TARGET_KWS, COMMAND_KW, CT_BUILD_ALWAYS, CT_BUILD_ALWAYS_STALE, CT_BUILD_BY_DEFAULT, CT_INPUT_KW, CT_INSTALL_DIR_KW, + EXECUTABLE_KWS, + JAR_KWS, + LIBRARY_KWS, MULTI_OUTPUT_KW, OUTPUT_KW, DEFAULT_OPTIONS, @@ -78,10 +82,12 @@ INSTALL_TAG_KW, LANGUAGE_KW, NATIVE_KW, - OVERRIDE_OPTIONS_KW, PRESERVE_PATH_KW, REQUIRED_KW, + SHARED_LIB_KWS, + SHARED_MOD_KWS, SOURCES_KW, + STATIC_LIB_KWS, VARIABLES_KW, TEST_KWS, NoneType, @@ -1805,7 +1811,7 @@ def func_disabler(self, node, args, kwargs): @FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.") @permittedKwargs(build.known_exe_kwargs) @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('executable', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) def func_executable(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.Executable) -> build.Executable: @@ -1813,7 +1819,7 @@ def func_executable(self, node: mparser.BaseNode, @permittedKwargs(build.known_stlib_kwargs) @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('static_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('static_library', *STATIC_LIB_KWS, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.StaticLibrary) -> build.StaticLibrary: @@ -1821,7 +1827,7 @@ def func_static_lib(self, node: mparser.BaseNode, @permittedKwargs(build.known_shlib_kwargs) @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('shared_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('shared_library', *SHARED_LIB_KWS, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.SharedLibrary) -> build.SharedLibrary: @@ -1831,7 +1837,7 @@ def func_shared_lib(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('both_libraries', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('both_libraries', *LIBRARY_KWS, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.Library) -> build.BothLibraries: @@ -1840,7 +1846,7 @@ def func_both_lib(self, node: mparser.BaseNode, @FeatureNew('shared_module', '0.37.0') @permittedKwargs(build.known_shmod_kwargs) @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('shared_module', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('shared_module', *SHARED_MOD_KWS, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.SharedModule) -> build.SharedModule: @@ -1848,7 +1854,7 @@ def func_shared_module(self, node: mparser.BaseNode, @permittedKwargs(known_library_kwargs) @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('library', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('library', *LIBRARY_KWS, allow_unknown=True) def func_library(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.Library) -> build.Executable: @@ -1856,7 +1862,7 @@ def func_library(self, node: mparser.BaseNode, @permittedKwargs(build.known_jar_kwargs) @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('jar', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('jar', *JAR_KWS, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], kwargs: kwtypes.Jar) -> build.Jar: @@ -1865,7 +1871,7 @@ def func_jar(self, node: mparser.BaseNode, @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @permittedKwargs(known_build_target_kwargs) @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) - @typed_kwargs('build_target', OVERRIDE_OPTIONS_KW, allow_unknown=True) + @typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: kwtypes.BuildTarget diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 8b57d06f15db..f2a74080f2a0 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -479,3 +479,78 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('suite', ContainerTypeInfo(list, str), listify=True, default=['']), # yes, a list of empty string KwargInfo('verbose', bool, default=False, since='0.62.0'), ] + +# Applies to all build_target like classes +_ALL_TARGET_KWS: T.List[KwargInfo] = [ + OVERRIDE_OPTIONS_KW, +] + +# Applies to all build_target classes except jar +_BUILD_TARGET_KWS: T.List[KwargInfo] = [ + *_ALL_TARGET_KWS, +] + +# Arguments exclusive to Executable. These are separated to make integrating +# them into build_target easier +_EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [] + +# The total list of arguments used by Executable +EXECUTABLE_KWS = [ + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_EXECUTABLE_KWS, +] + +# Arguments exclusive to StaticLibrary. These are separated to make integrating +# them into build_target easier +_EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [] + +# The total list of arguments used by StaticLibrary +STATIC_LIB_KWS = [ + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_STATIC_LIB_KWS, +] + +# Arguments exclusive to SharedLibrary. These are separated to make integrating +# them into build_target easier +_EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [] + +# The total list of arguments used by SharedLibrary +SHARED_LIB_KWS = [ + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_SHARED_LIB_KWS, +] + +# Arguments exclusive to SharedModule. These are separated to make integrating +# them into build_target easier +_EXCLUSIVE_SHARED_MOD_KWS: T.List[KwargInfo] = [] + +# The total list of arguments used by SharedModule +SHARED_MOD_KWS = [ + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_SHARED_MOD_KWS, +] + +# Arguments exclusive to JAR. These are separated to make integrating +# them into build_target easier +_EXCLUSIVE_JAR_KWS: T.List[KwargInfo] = [] + +# The total list of arguments used by JAR +JAR_KWS = [ + *_ALL_TARGET_KWS, + *_EXCLUSIVE_JAR_KWS, +] + +# Arguments used by both_library and library +LIBRARY_KWS = [ + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_SHARED_LIB_KWS, + *_EXCLUSIVE_SHARED_MOD_KWS, + *_EXCLUSIVE_STATIC_LIB_KWS, +] + +# Arguments used by build_Target +BUILD_TARGET_KWS = [ + *LIBRARY_KWS, + *_EXCLUSIVE_EXECUTABLE_KWS, + *_EXCLUSIVE_JAR_KWS, +] From 01b5581a100bbb5c608cd054dfccbec721285be9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 13:26:27 -0700 Subject: [PATCH 024/855] build|interpreter: move main_class to typed_kwargs Also move it into the Jar class. This is an exclusive Jar keyword argument, and is only used inside java paths, so there's no reason to have this in all build targets. --- mesonbuild/build.py | 5 +---- mesonbuild/interpreter/kwargs.py | 3 ++- mesonbuild/interpreter/type_checking.py | 4 +++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 6438b836d461..c303ffe0f416 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1150,10 +1150,6 @@ def process_kwargs(self, kwargs): (str, bool)) self.install_mode = kwargs.get('install_mode', None) self.install_tag = stringlistify(kwargs.get('install_tag', [None])) - main_class = kwargs.get('main_class', '') - if not isinstance(main_class, str): - raise InvalidArguments('Main class must be a string') - self.main_class = main_class if isinstance(self, Executable): # This kwarg is deprecated. The value of "none" means that the kwarg # was not specified and win_subsystem should be used instead. @@ -2913,6 +2909,7 @@ def __init__(self, name: str, subdir: str, subproject: str, for_machine: Machine self.filename = self.name + '.jar' self.outputs = [self.filename] self.java_args = kwargs.get('java_args', []) + self.main_class = kwargs.get('main_class', '') self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None) def get_main_class(self): diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index d46d4e3235ab..95bf9bcf1d86 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -352,4 +352,5 @@ class BuildTarget(Library): class Jar(_BaseBuildTarget): - pass + + main_class: str diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index f2a74080f2a0..cc1f944a761f 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -532,7 +532,9 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Arguments exclusive to JAR. These are separated to make integrating # them into build_target easier -_EXCLUSIVE_JAR_KWS: T.List[KwargInfo] = [] +_EXCLUSIVE_JAR_KWS: T.List[KwargInfo] = [ + KwargInfo('main_class', str, default=''), +] # The total list of arguments used by JAR JAR_KWS = [ From 096869ad63157f666773bd93bd14bdd6bd0602aa Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 13:28:51 -0700 Subject: [PATCH 025/855] interpreter: use typed_kwargs for jar(java_resources) With the added bonus of adding the correct `since` checking values! --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 95bf9bcf1d86..4254c304320a 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -354,3 +354,4 @@ class BuildTarget(Library): class Jar(_BaseBuildTarget): main_class: str + java_resources: T.Optional[build.StructuredSources] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index cc1f944a761f..38e42573471c 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -10,7 +10,7 @@ from .. import compilers from ..build import (CustomTarget, BuildTarget, CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs, - BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable) + BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable, StructuredSources) from ..coredata import UserFeatureOption from ..dependencies import Dependency, InternalDependency from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo @@ -534,6 +534,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # them into build_target easier _EXCLUSIVE_JAR_KWS: T.List[KwargInfo] = [ KwargInfo('main_class', str, default=''), + KwargInfo('java_resources', (StructuredSources, NoneType), since='0.62.0'), ] # The total list of arguments used by JAR From a62a42b272923f95b7aeb30f0196cfdf3b251264 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 13:12:30 -0700 Subject: [PATCH 026/855] interpreter: use kwarginfo for build_target(target_type) Which lets us remove a bunch of validation code --- mesonbuild/interpreter/interpreter.py | 12 ++---------- mesonbuild/interpreter/kwargs.py | 4 +++- mesonbuild/interpreter/type_checking.py | 12 ++++++++++++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 853d858b93a2..235f0487512d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1877,17 +1877,12 @@ def func_build_target(self, node: mparser.BaseNode, kwargs: kwtypes.BuildTarget ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, build.SharedModule, build.BothLibraries, build.Jar]: - if 'target_type' not in kwargs: - raise InterpreterException('Missing target_type keyword argument') - target_type = kwargs.pop('target_type') + target_type = kwargs['target_type'] if target_type == 'executable': return self.build_target(node, args, kwargs, build.Executable) elif target_type == 'shared_library': return self.build_target(node, args, kwargs, build.SharedLibrary) elif target_type == 'shared_module': - FeatureNew.single_use( - 'build_target(target_type: \'shared_module\')', - '0.51.0', self.subproject, location=node) return self.build_target(node, args, kwargs, build.SharedModule) elif target_type == 'static_library': return self.build_target(node, args, kwargs, build.StaticLibrary) @@ -1895,10 +1890,7 @@ def func_build_target(self, node: mparser.BaseNode, return self.build_both_libraries(node, args, kwargs) elif target_type == 'library': return self.build_library(node, args, kwargs) - elif target_type == 'jar': - return self.build_target(node, args, kwargs, build.Jar) - else: - raise InterpreterException('Unknown target_type.') + return self.build_target(node, args, kwargs, build.Jar) @noPosargs @typed_kwargs( diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 4254c304320a..31c96e28ec97 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -348,7 +348,9 @@ class Library(_BuildTarget): class BuildTarget(Library): - pass + + target_type: Literal['executable', 'shared_library', 'static_library', + 'shared_module', 'both_libraries', 'library', 'jar'] class Jar(_BaseBuildTarget): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 38e42573471c..7c615c2c8ade 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -556,4 +556,16 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus *LIBRARY_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, *_EXCLUSIVE_JAR_KWS, + KwargInfo( + 'target_type', + str, + required=True, + validator=in_set_validator({ + 'executable', 'shared_library', 'static_library', 'shared_module', + 'both_libraries', 'library', 'jar' + }), + since_values={ + 'shared_module': '0.51.0', + } + ) ] From d7acccd36dcf1b62f144eb7389a5e221fe824be4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 13:22:20 -0700 Subject: [PATCH 027/855] interpreter: deprecate 'jar' value of build_target(target_type) Jar has a very low set of overlap with other target types, including that jar sources *must* be .java, and no other target allows .java sources. As such, the difficulty in crafting a useful `build_target` invocation that allows both `jar` and anything else is high, and the usefulness is dubious. Just use `jar()` directly instead. This depends on the changes to make all of the jar() specific keyword arguments be handled by typed_kwargs so that the deprecation messages are correct and consistent. --- docs/markdown/snippets/deprecate_build_target_jar.md | 8 ++++++++ docs/yaml/functions/build_target.yaml | 7 +++++-- mesonbuild/interpreter/type_checking.py | 6 +++++- 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 docs/markdown/snippets/deprecate_build_target_jar.md diff --git a/docs/markdown/snippets/deprecate_build_target_jar.md b/docs/markdown/snippets/deprecate_build_target_jar.md new file mode 100644 index 000000000000..992903e53821 --- /dev/null +++ b/docs/markdown/snippets/deprecate_build_target_jar.md @@ -0,0 +1,8 @@ +## Deprecate 'jar' as a build_target type + +The point of `build_target()` is that what is produced can be conditionally +changed. However, `jar()` has a significant number of non-overlapping arguments +from other build_targets, including the kinds of sources it can include. Because +of this crafting a `build_target` that can be used as a Jar and as something +else is incredibly hard to do. As such, it has been deprecated, and using +`jar()` directly is recomended. diff --git a/docs/yaml/functions/build_target.yaml b/docs/yaml/functions/build_target.yaml index 48385f252580..74d45f0070de 100644 --- a/docs/yaml/functions/build_target.yaml +++ b/docs/yaml/functions/build_target.yaml @@ -12,7 +12,7 @@ description: | - `static_library` (see [[static_library]]) - `both_libraries` (see [[both_libraries]]) - `library` (see [[library]]) - - `jar` (see [[jar]]) + - `jar` (see [[jar]])* This declaration: @@ -32,6 +32,9 @@ description: | The returned object also has methods that are documented in [[@build_tgt]]. + *"jar" is deprecated because it is fundementally a different thing than the + other build_target types. + posargs_inherit: _build_target_base varargs_inherit: _build_target_base kwargs_inherit: @@ -42,4 +45,4 @@ kwargs_inherit: kwargs: target_type: type: str - description: The actual target to build + description: The actual target type to build diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 7c615c2c8ade..206a2e6f532f 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -555,7 +555,8 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus BUILD_TARGET_KWS = [ *LIBRARY_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, - *_EXCLUSIVE_JAR_KWS, + *[a.evolve(deprecated='1.3.0', deprecated_message='The use of "jar" in "build_target()" is deprecated, and this argument is only used by jar()') + for a in _EXCLUSIVE_JAR_KWS], KwargInfo( 'target_type', str, @@ -566,6 +567,9 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus }), since_values={ 'shared_module': '0.51.0', + }, + deprecated_values={ + 'jar': ('1.3.0', 'use the "jar()" function directly'), } ) ] From 1bca73cc376b275e79f01416e7963f359534dffb Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 20 Jul 2023 14:45:30 -0400 Subject: [PATCH 028/855] docs: fix typo in previous commit --- docs/markdown/snippets/deprecate_build_target_jar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/snippets/deprecate_build_target_jar.md b/docs/markdown/snippets/deprecate_build_target_jar.md index 992903e53821..1aa5a81dd2cb 100644 --- a/docs/markdown/snippets/deprecate_build_target_jar.md +++ b/docs/markdown/snippets/deprecate_build_target_jar.md @@ -5,4 +5,4 @@ changed. However, `jar()` has a significant number of non-overlapping arguments from other build_targets, including the kinds of sources it can include. Because of this crafting a `build_target` that can be used as a Jar and as something else is incredibly hard to do. As such, it has been deprecated, and using -`jar()` directly is recomended. +`jar()` directly is recommended. From 047c2d644cdb006d01ce35f2fef76247ccb15335 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 21 Jul 2023 08:43:15 -0400 Subject: [PATCH 029/855] Display more timestamps when profiling ninja When running setup with `--profile-self` option, there are currently no logs after "Found ninja...". However, there are still some lengthy processes for generating targets and ninja.build. This add more log entries, when profiling, only for the purpose of displaying the timestamps of the different steps in ninja generation. --- mesonbuild/backend/ninjabackend.py | 7 +++++++ mesonbuild/mlog.py | 5 +++++ mesonbuild/msetup.py | 2 ++ 3 files changed, 14 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1786fef893f3..9c347d7833f8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -628,11 +628,15 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional for t in ProgressBar(self.build.get_targets().values(), desc='Generating targets'): self.generate_target(t) + mlog.log_timestamp("Targets generated") self.add_build_comment(NinjaComment('Test rules')) self.generate_tests() + mlog.log_timestamp("Tests generated") self.add_build_comment(NinjaComment('Install rules')) self.generate_install() + mlog.log_timestamp("Install generated") self.generate_dist() + mlog.log_timestamp("Dist generated") key = OptionKey('b_coverage') if (key in self.environment.coredata.options and self.environment.coredata.options[key].value): @@ -640,12 +644,14 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional if gcovr_exe or (lcov_exe and genhtml_exe): self.add_build_comment(NinjaComment('Coverage rules')) self.generate_coverage_rules(gcovr_exe, gcovr_version) + mlog.log_timestamp("Coverage rules generated") else: # FIXME: since we explicitly opted in, should this be an error? # The docs just say these targets will be created "if possible". mlog.warning('Need gcovr or lcov/genhtml to generate any coverage reports') self.add_build_comment(NinjaComment('Suffix')) self.generate_utils() + mlog.log_timestamp("Utils generated") self.generate_ending() self.write_rules(outfile) @@ -1363,6 +1369,7 @@ def write_rules(self, outfile): def write_builds(self, outfile): for b in ProgressBar(self.build_elements, desc='Writing build.ninja'): b.write(outfile) + mlog.log_timestamp("build.ninja generated") def generate_phony(self): self.add_build_comment(NinjaComment('Phony build target, always out of date')) diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index 3c95ee84abca..b4314280d175 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -276,6 +276,10 @@ def log(self, *args: TV_Loggable, is_error: bool = False, else: self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + def log_timestamp(self, *args: TV_Loggable) -> None: + if self.log_timestamp_start: + self.log(*args) + def _log_once(self, *args: TV_Loggable, is_error: bool = False, nested: bool = True, sep: T.Optional[str] = None, end: T.Optional[str] = None) -> None: @@ -419,6 +423,7 @@ def get_warning_count(self) -> int: get_warning_count = _logger.get_warning_count initialize = _logger.initialize log = _logger.log +log_timestamp = _logger.log_timestamp nested = _logger.nested nested_warnings = _logger.nested_warnings no_logging = _logger.no_logging diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 61d66f2492e6..e6c122092ec8 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -293,6 +293,8 @@ def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: dic with open(fname, 'w', encoding='utf-8') as f: json.dump(data, f) + mlog.log("meson setup completed") # Display timestamp + except Exception as e: mintro.write_meson_info_file(b, [e]) if cdf is not None: From a84a082b1a1966cb448bc9bbe9cabfa4d967a657 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 21 Jul 2023 09:06:29 -0400 Subject: [PATCH 030/855] Prevent summary displaying timestamp twice Before: [117.000] Subprojects [117.000] OptelMessagingApi : [117.000] YES [117.000] Python27 : [117.000] YES [117.000] op300rtos : [117.000] YES [117.000] optel-common-protos: [117.000] YES After: [38.938] Subprojects [38.938] OptelMessagingApi : YES [38.938] Python27 : YES [38.938] op300rtos : YES [38.938] optel-common-protos: YES --- mesonbuild/interpreter/interpreter.py | 4 ++-- mesonbuild/mlog.py | 25 +++++++++++++------------ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 235f0487512d..6aa0a3751b13 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -204,7 +204,7 @@ def dump(self): def dump_value(self, arr, list_sep, indent): lines_sep = '\n' + ' ' * indent if list_sep is None: - mlog.log(*arr, sep=lines_sep) + mlog.log(*arr, sep=lines_sep, display_timestamp=False) return max_len = shutil.get_terminal_size().columns line = [] @@ -218,7 +218,7 @@ def dump_value(self, arr, list_sep, indent): line = [] line.append(v) line_len += v_len - mlog.log(*line, sep=list_sep) + mlog.log(*line, sep=list_sep, display_timestamp=False) known_library_kwargs = ( build.known_shlib_kwargs | diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index b4314280d175..e51399b4f5c6 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -200,9 +200,9 @@ def initialize(self, logdir: str, fatal_warnings: bool = False) -> None: self.log_file = open(os.path.join(logdir, self._LOG_FNAME), 'w', encoding='utf-8') self.log_fatal_warnings = fatal_warnings - def process_markup(self, args: T.Sequence[TV_Loggable], keep: bool) -> T.List[str]: + def process_markup(self, args: T.Sequence[TV_Loggable], keep: bool, display_timestamp: bool = True) -> T.List[str]: arr = [] # type: T.List[str] - if self.log_timestamp_start is not None: + if self.log_timestamp_start is not None and display_timestamp: arr = ['[{:.3f}]'.format(time.monotonic() - self.log_timestamp_start)] for arg in args: if arg is None: @@ -240,21 +240,21 @@ def force_print(self, *args: str, nested: bool, sep: T.Optional[str] = None, print(cleaned, end='') def debug(self, *args: TV_Loggable, sep: T.Optional[str] = None, - end: T.Optional[str] = None) -> None: - arr = process_markup(args, False) + end: T.Optional[str] = None, display_timestamp: bool = True) -> None: + arr = process_markup(args, False, display_timestamp) if self.log_file is not None: print(*arr, file=self.log_file, sep=sep, end=end) self.log_file.flush() def _log(self, *args: TV_Loggable, is_error: bool = False, nested: bool = True, sep: T.Optional[str] = None, - end: T.Optional[str] = None) -> None: - arr = process_markup(args, False) + end: T.Optional[str] = None, display_timestamp: bool = True) -> None: + arr = process_markup(args, False, display_timestamp) if self.log_file is not None: print(*arr, file=self.log_file, sep=sep, end=end) self.log_file.flush() if colorize_console(): - arr = process_markup(args, True) + arr = process_markup(args, True, display_timestamp) if not self.log_errors_only or is_error: force_print(*arr, nested=nested, sep=sep, end=end) @@ -270,11 +270,12 @@ def cmd_ci_include(self, file: str) -> None: def log(self, *args: TV_Loggable, is_error: bool = False, once: bool = False, nested: bool = True, sep: T.Optional[str] = None, - end: T.Optional[str] = None) -> None: + end: T.Optional[str] = None, + display_timestamp: bool = True) -> None: if once: - self._log_once(*args, is_error=is_error, nested=nested, sep=sep, end=end) + self._log_once(*args, is_error=is_error, nested=nested, sep=sep, end=end, display_timestamp=display_timestamp) else: - self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end, display_timestamp=display_timestamp) def log_timestamp(self, *args: TV_Loggable) -> None: if self.log_timestamp_start: @@ -282,7 +283,7 @@ def log_timestamp(self, *args: TV_Loggable) -> None: def _log_once(self, *args: TV_Loggable, is_error: bool = False, nested: bool = True, sep: T.Optional[str] = None, - end: T.Optional[str] = None) -> None: + end: T.Optional[str] = None, display_timestamp: bool = True) -> None: """Log variant that only prints a given message one time per meson invocation. This considers ansi decorated values by the values they wrap without @@ -298,7 +299,7 @@ def to_str(x: TV_Loggable) -> str: if t in self.logged_once: return self.logged_once.add(t) - self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end) + self._log(*args, is_error=is_error, nested=nested, sep=sep, end=end, display_timestamp=display_timestamp) def _log_error(self, severity: _Severity, *rargs: TV_Loggable, once: bool = False, fatal: bool = True, From 76dd44d6cb699096e656487e77aef1c92ddf79c1 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 22 Jul 2023 13:51:34 -0500 Subject: [PATCH 031/855] backend: fix checking dep instance for xcode --- mesonbuild/backend/xcodebackend.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index bc4ba0bc21d6..a2020e16c165 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -456,7 +456,7 @@ def generate_native_frameworks_map(self) -> None: self.native_frameworks_fileref = {} for t in self.build_targets.values(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.AppleFrameworks): + if isinstance(dep, dependencies.platform.AppleFrameworks): for f in dep.frameworks: self.native_frameworks[f] = self.gen_id() self.native_frameworks_fileref[f] = self.gen_id() @@ -598,7 +598,7 @@ def generate_pbx_aggregate_target(self, objects_dict): def generate_pbx_build_file(self, objects_dict): for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.AppleFrameworks): + if isinstance(dep, dependencies.platform.AppleFrameworks): for f in dep.frameworks: fw_dict = PbxDict() fwkey = self.native_frameworks[f] @@ -708,7 +708,7 @@ def generate_pbx_container_item_proxy(self, objects_dict): def generate_pbx_file_reference(self, objects_dict): for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.AppleFrameworks): + if isinstance(dep, dependencies.platform.AppleFrameworks): for f in dep.frameworks: fw_dict = PbxDict() framework_fileref = self.native_frameworks_fileref[f] @@ -868,7 +868,7 @@ def generate_pbx_frameworks_buildphase(self, objects_dict): file_list = PbxArray() bt_dict.add_item('files', file_list) for dep in t.get_external_deps(): - if isinstance(dep, dependencies.AppleFrameworks): + if isinstance(dep, dependencies.platform.AppleFrameworks): for f in dep.frameworks: file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks') bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0) @@ -916,7 +916,7 @@ def generate_pbx_group(self, objects_dict): for t in self.build_targets.values(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.AppleFrameworks): + if isinstance(dep, dependencies.platform.AppleFrameworks): for f in dep.frameworks: frameworks_children.add_item(self.native_frameworks_fileref[f], f) From b6e306ea5ba16c1668f613267f1627cd6aa6476c Mon Sep 17 00:00:00 2001 From: George Sedov Date: Mon, 17 Jul 2023 17:38:13 +0200 Subject: [PATCH 032/855] hdf5: fix wrong env values for config tool --- mesonbuild/dependencies/hdf5.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index 392bb0964466..b0ce2be277b1 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -98,12 +98,15 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. if language == 'c': cenv = 'CC' + lenv = 'C' tools = ['h5cc', 'h5pcc'] elif language == 'cpp': cenv = 'CXX' + lenv = 'CXX' tools = ['h5c++', 'h5pc++'] elif language == 'fortran': cenv = 'FC' + lenv = 'F' tools = ['h5fc', 'h5pfc'] else: raise DependencyException('How did you get here?') @@ -120,11 +123,11 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. compiler = environment.coredata.compilers[for_machine][language] try: os.environ[f'HDF5_{cenv}'] = join_args(compiler.get_exelist()) - os.environ[f'HDF5_{cenv}LINKER'] = join_args(compiler.get_linker_exelist()) + os.environ[f'HDF5_{lenv}LINKER'] = join_args(compiler.get_linker_exelist()) super().__init__(name, environment, nkwargs, language) finally: del os.environ[f'HDF5_{cenv}'] - del os.environ[f'HDF5_{cenv}LINKER'] + del os.environ[f'HDF5_{lenv}LINKER'] if not self.is_found: return From 0c2b61618322cc5fa6c0658b9dac75613221839e Mon Sep 17 00:00:00 2001 From: George Sedov Date: Mon, 17 Jul 2023 17:39:00 +0200 Subject: [PATCH 033/855] hdf5: remove C sub-dependency for config tool the config tool provided by HDF5 correctly links to the C libraries without explicit sub-dependancy --- mesonbuild/dependencies/hdf5.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index b0ce2be277b1..84f28126f5dd 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -143,13 +143,6 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. elif Path(arg).is_file(): self.link_args.append(arg) - # If the language is not C we need to add C as a subdependency - if language != 'c': - nkwargs = kwargs.copy() - nkwargs['language'] = 'c' - # I'm being too clever for mypy and pylint - self.is_found = self._add_sub_dependency(hdf5_factory(environment, for_machine, nkwargs)) # pylint: disable=no-value-for-parameter - def _sanitize_version(self, ver: str) -> str: v = re.search(r'\s*HDF5 Version: (\d+\.\d+\.\d+)', ver) return v.group(1) From c2ed846b64f02653d1460855c0aadef20308fc1f Mon Sep 17 00:00:00 2001 From: George Sedov Date: Mon, 17 Jul 2023 17:41:11 +0200 Subject: [PATCH 034/855] hdf5 tests: make cpp test actually use cpp HDF5 the previous version didn't even link to libhdf5_cpp.so --- test cases/frameworks/25 hdf5/main.cpp | 28 +++++++++----------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/test cases/frameworks/25 hdf5/main.cpp b/test cases/frameworks/25 hdf5/main.cpp index 477e76b6663a..9c7f7bfb68e9 100644 --- a/test cases/frameworks/25 hdf5/main.cpp +++ b/test cases/frameworks/25 hdf5/main.cpp @@ -1,29 +1,19 @@ #include -#include "hdf5.h" +#include "H5Cpp.h" int main(void) { -herr_t ier; unsigned maj, min, rel; -ier = H5open(); -if (ier) { - std::cerr << "Unable to initialize HDF5: " << ier << std::endl; +try { + H5::H5Library::open(); + H5::H5Library::getLibVersion(maj, min, rel); + std::cout << "C++ HDF5 version " << maj << "." << min << "." << rel << std::endl; + H5::H5Library::close(); + return EXIT_SUCCESS; +} catch (H5::LibraryIException &e) { + std::cerr << "Exception caught from HDF5: " << e.getDetailMsg() << std::endl; return EXIT_FAILURE; } - -ier = H5get_libversion(&maj, &min, &rel); -if (ier) { - std::cerr << "HDF5 did not initialize!" << std::endl; - return EXIT_FAILURE; -} -std::cout << "C++ HDF5 version " << maj << "." << min << "." << rel << std::endl; - -ier = H5close(); -if (ier) { - std::cerr << "Unable to close HDF5: " << ier << std::endl; - return EXIT_FAILURE; -} -return EXIT_SUCCESS; } From c8241d79e46bec7e08b44f2cb0d1882dc4c4b0a6 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 21 Jul 2023 16:01:49 -0700 Subject: [PATCH 035/855] build: remove BuildTarget.need_install This would be either the value `kwargs['install']`, or `False`. There isn't any case that `BuildTarget.need_install` handles that `BuildTarget.install` doesn't handle, if we just initialized it correctly. So, just set Target.install correctly in the super initializer, and do away with need_install. --- mesonbuild/build.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c303ffe0f416..8e8ea779e840 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -721,7 +721,7 @@ def __init__( environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], kwargs): - super().__init__(name, subdir, subproject, True, for_machine, environment) + super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False)) self.all_compilers = compilers self.compilers = OrderedDict() # type: OrderedDict[str, Compiler] self.objects: T.List[ObjectTypes] = [] @@ -739,7 +739,6 @@ def __init__( # The list of all files outputted by this target. Useful in cases such # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] - self.need_install = False self.pch: T.Dict[str, T.List[str]] = {} self.extra_args: T.Dict[str, T.List['FileOrString']] = {} self.sources: T.List[File] = [] @@ -805,7 +804,7 @@ def is_unity(self) -> bool: return unity_opt == 'on' or (unity_opt == 'subprojects' and self.subproject != '') def validate_install(self): - if self.for_machine is MachineChoice.BUILD and self.need_install: + if self.for_machine is MachineChoice.BUILD and self.install: if self.environment.is_cross_build(): raise InvalidArguments('Tried to install a target for the build machine in a cross build.') else: @@ -1092,7 +1091,6 @@ def process_kwargs(self, kwargs): self.process_kwargs_base(kwargs) self.original_kwargs = kwargs kwargs.get('modules', []) - self.need_install = kwargs.get('install', self.need_install) for lang in all_languages: lang_args = extract_as_list(kwargs, f'{lang}_args') @@ -1323,7 +1321,7 @@ def get_generated_sources(self) -> T.List['GeneratedTypes']: return self.generated def should_install(self) -> bool: - return self.need_install + return self.install def has_pch(self) -> bool: return bool(self.pch) @@ -1398,7 +1396,7 @@ def is_internal(self) -> bool: def link(self, targets): for t in targets: - if isinstance(self, StaticLibrary) and self.need_install: + if isinstance(self, StaticLibrary) and self.install: if isinstance(t, (CustomTarget, CustomTargetIndex)): if not t.should_install(): mlog.warning(f'Try to link an installed static library target {self.name} with a' @@ -1468,7 +1466,7 @@ def link_whole(self, targets): self.objects += [t.extract_all_objects()] # If we install this static library we also need to include objects # from all uninstalled static libraries it depends on. - if self.need_install: + if self.install: for lib in t.get_internal_static_libraries(): self.objects += [lib.extract_all_objects()] self.link_whole_targets.append(t) @@ -2133,7 +2131,7 @@ def is_linkable_target(self): return True def is_internal(self) -> bool: - return not self.need_install + return not self.install class SharedLibrary(BuildTarget): known_kwargs = known_shlib_kwargs From 9faf91d14f8ff049140ca24832c7da2ba7f7a028 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 21 Jul 2023 16:03:42 -0700 Subject: [PATCH 036/855] build: remove useless method call This does nothing, so just delete it. --- mesonbuild/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8e8ea779e840..f888ab12ee6d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1090,7 +1090,6 @@ def get_custom_install_mode(self) -> T.Optional['FileMode']: def process_kwargs(self, kwargs): self.process_kwargs_base(kwargs) self.original_kwargs = kwargs - kwargs.get('modules', []) for lang in all_languages: lang_args = extract_as_list(kwargs, f'{lang}_args') From 3a4b874ec0379c688d127f929b8f3f75f6530a72 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 24 Jul 2023 09:45:17 -0700 Subject: [PATCH 037/855] interpreter: stop setting member out of initializer that isn't even used --- mesonbuild/interpreter/interpreter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 6aa0a3751b13..5c3ef827246d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3282,7 +3282,6 @@ def build_target_decorator_caller(self, node, args, kwargs): kwargs['include_directories'] = self.extract_incdirs(kwargs) target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, self.environment, self.compilers[for_machine], kwargs) - target.project_version = self.project_version self.add_target(name, target) self.project_args_frozen = True From a7a3563c0d9d5a0e56174634032df380ef664016 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 23 Jul 2023 12:47:59 -0400 Subject: [PATCH 038/855] fix a few miscellaneous implicit-optional typing issues --- mesonbuild/mintro.py | 2 +- mesonbuild/msetup.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 063c5cdd6b57..9657da7c6b8c 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -503,7 +503,7 @@ def list_projinfo_from_source(intr: IntrospectionInterpreter) -> T.Dict[str, T.U intr.project_data['subproject_dir'] = intr.subproject_dir return intr.project_data -def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: int) -> int: +def print_results(options: argparse.Namespace, results: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], indent: T.Optional[int]) -> int: if not results and not options.force_dict: print('No command specified') return 1 diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index e6c122092ec8..73c9fb3cc25b 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -102,7 +102,7 @@ def has_build_file(self, dirname: str) -> bool: fname = os.path.join(dirname, environment.build_filename) return os.path.exists(fname) - def validate_core_dirs(self, dir1: str, dir2: str) -> T.Tuple[str, str]: + def validate_core_dirs(self, dir1: T.Optional[str], dir2: T.Optional[str]) -> T.Tuple[str, str]: invalid_msg_prefix = f'Neither source directory {dir1!r} nor build directory {dir2!r}' if dir1 is None: if dir2 is None: @@ -144,7 +144,7 @@ def add_vcs_ignore_files(self, build_dir: str) -> None: with open(os.path.join(build_dir, '.hgignore'), 'w', encoding='utf-8') as ofile: ofile.write(hg_ignore_file) - def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> T.Tuple[str, str]: + def validate_dirs(self, dir1: T.Optional[str], dir2: T.Optional[str], reconfigure: bool, wipe: bool) -> T.Tuple[str, str]: (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2) if Path(build_dir) in Path(src_dir).parents: raise MesonException(f'Build directory {build_dir} cannot be a parent of source directory {src_dir}') @@ -174,7 +174,7 @@ def validate_dirs(self, dir1: str, dir2: str, reconfigure: bool, wipe: bool) -> return src_dir, build_dir # See class Backend's 'generate' for comments on capture args and returned dictionary. - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + def generate(self, capture: bool = False, vslite_ctx: T.Optional[dict] = None) -> T.Optional[dict]: env = environment.Environment(self.source_dir, self.build_dir, self.options) mlog.initialize(env.get_log_dir(), self.options.fatal_warnings) if self.options.profile: @@ -182,7 +182,7 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional with mesonlib.BuildDirLock(self.build_dir): return self._generate(env, capture, vslite_ctx) - def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: dict) -> T.Optional[dict]: + def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: T.Optional[dict]) -> T.Optional[dict]: # Get all user defined options, including options that have been defined # during a previous invocation or using meson configure. user_defined_options = argparse.Namespace(**vars(self.options)) From db0d579c7962ce026dc256cdf39eefbf6bfb6c1e Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 23 Jul 2023 12:49:29 -0400 Subject: [PATCH 039/855] interpreter: fix typing for adding tests We know exactly what type we need, since the interpreter function is correctly typed and thinly wraps over this. But we didn't even get the container type correct. :( --- mesonbuild/interpreter/interpreter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 5c3ef827246d..f12a059e7c56 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2216,7 +2216,9 @@ def make_test(self, node: mparser.BaseNode, kwargs['priority'], kwargs['verbose']) - def add_test(self, node: mparser.BaseNode, args: T.List, kwargs: T.Dict[str, T.Any], is_base_test: bool): + def add_test(self, node: mparser.BaseNode, + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + kwargs: T.Dict[str, T.Any], is_base_test: bool): t = self.make_test(node, args, kwargs) if is_base_test: self.build.tests.append(t) From 59af1d902616563383fe06a6ddb50bddb4de54bc Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 23 Jul 2023 12:57:06 -0400 Subject: [PATCH 040/855] force interpreter functions to actually receive tuple from typed posargs We always expect the args parameter in the wrapped function to eventually receive a tuple due to reasons. But in one specific optargs condition we passed it along without any fixup at all. --- mesonbuild/interpreterbase/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index 10683fdbf895..cecdbfdfd392 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -270,7 +270,7 @@ def wrapper(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any: diff = num_types + len(optargs) - num_args nargs[i] = tuple(list(args) + [None] * diff) else: - nargs[i] = args + nargs[i] = tuple(args) else: nargs[i] = tuple(args) return f(*nargs, **wrapped_kwargs) From 22d842a97da45740a19f210d694ce23272a45cf9 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 23 Jul 2023 13:27:24 -0400 Subject: [PATCH 041/855] ninjabackend: remove useless and unused API bits in phony targets I originally refactored this wrapper function in commit dd2f1c4c57874a0efcd9f6d331985c408101c30d and at the time I made it take the following call pattern: ``` self.create_phony_target(self.all_outputs, ..., implicit_outs=None) ``` I am not sure *why*. There are a couple problems here: - When creating a phony target, there are never implicit outs and we never try to create them. - It's invalid to call it without self.all_outputs as the first argument, so really we should just use that directly. This made the function signature pointlessly longer and more complicated. --- mesonbuild/backend/ninjabackend.py | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9c347d7833f8..22d5983a1985 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -491,7 +491,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.rust_crates: T.Dict[str, RustCrate] = {} self.implicit_meson_outs = [] - def create_phony_target(self, all_outputs, dummy_outfile, rulename, phony_infilename, implicit_outs=None): + def create_phony_target(self, dummy_outfile, rulename, phony_infilename): ''' We need to use aliases for targets that might be used as directory names to workaround a Ninja bug that breaks `ninja -t clean`. @@ -503,10 +503,10 @@ def create_phony_target(self, all_outputs, dummy_outfile, rulename, phony_infile raise AssertionError(f'Invalid usage of create_phony_target with {dummy_outfile!r}') to_name = f'meson-internal__{dummy_outfile}' - elem = NinjaBuildElement(all_outputs, dummy_outfile, 'phony', to_name) + elem = NinjaBuildElement(self.all_outputs, dummy_outfile, 'phony', to_name) self.add_build(elem) - return NinjaBuildElement(all_outputs, to_name, rulename, phony_infilename, implicit_outs) + return NinjaBuildElement(self.all_outputs, to_name, rulename, phony_infilename) def detect_vs_dep_prefix(self, tempfilename): '''VS writes its dependency in a locale dependent format. @@ -1209,7 +1209,7 @@ def generate_run_target(self, target: build.RunTarget): env=target_env, verbose=True) cmd_type = f' (wrapped by meson {reason})' if reason else '' - elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', []) + elem = self.create_phony_target(target_name, 'CUSTOM_COMMAND', []) elem.add_item('COMMAND', meson_exe_cmd) elem.add_item('description', f'Running external command {target.name}{cmd_type}') elem.add_item('pool', 'console') @@ -1240,38 +1240,38 @@ def generate_coverage_command(self, elem, outputs): (['--use_llvm_cov'] if use_llvm_cov else [])) def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): - e = self.create_phony_target(self.all_outputs, 'coverage', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('coverage', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, []) e.add_item('description', 'Generates coverage reports') self.add_build(e) self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version) def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): - e = self.create_phony_target(self.all_outputs, 'coverage-html', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('coverage-html', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--html']) e.add_item('description', 'Generates HTML coverage report') self.add_build(e) if gcovr_exe: - e = self.create_phony_target(self.all_outputs, 'coverage-xml', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('coverage-xml', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--xml']) e.add_item('description', 'Generates XML coverage report') self.add_build(e) - e = self.create_phony_target(self.all_outputs, 'coverage-text', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('coverage-text', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--text']) e.add_item('description', 'Generates text coverage report') self.add_build(e) if mesonlib.version_compare(gcovr_version, '>=4.2'): - e = self.create_phony_target(self.all_outputs, 'coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--sonarqube']) e.add_item('description', 'Generates Sonarqube XML coverage report') self.add_build(e) def generate_install(self): self.create_install_data_files() - elem = self.create_phony_target(self.all_outputs, 'install', 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target('install', 'CUSTOM_COMMAND', 'PHONY') elem.add_dep('all') elem.add_item('DESC', 'Installing files.') elem.add_item('COMMAND', self.environment.get_build_command() + ['install', '--no-rebuild']) @@ -1285,7 +1285,7 @@ def generate_tests(self): cmd += ['--no-stdsplit'] if self.environment.coredata.get_option(OptionKey('errorlogs')): cmd += ['--print-errorlogs'] - elem = self.create_phony_target(self.all_outputs, 'test', 'CUSTOM_COMMAND', ['all', 'PHONY']) + elem = self.create_phony_target('test', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running all tests.') elem.add_item('pool', 'console') @@ -1295,7 +1295,7 @@ def generate_tests(self): cmd = self.environment.get_build_command(True) + [ 'test', '--benchmark', '--logbase', 'benchmarklog', '--num-processes=1', '--no-rebuild'] - elem = self.create_phony_target(self.all_outputs, 'benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY']) + elem = self.create_phony_target('benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY']) elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running benchmark suite.') elem.add_item('pool', 'console') @@ -3582,7 +3582,7 @@ def generate_shlib_aliases(self, target, outdir): self.implicit_meson_outs.append(aliasfile) def generate_custom_target_clean(self, trees: T.List[str]) -> str: - e = self.create_phony_target(self.all_outputs, 'clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') + e = self.create_phony_target('clean-ctlist', 'CUSTOM_COMMAND', 'PHONY') d = CleanTrees(self.environment.get_build_dir(), trees) d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat') e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'cleantrees', d_file]) @@ -3594,12 +3594,12 @@ def generate_custom_target_clean(self, trees: T.List[str]) -> str: return 'clean-ctlist' def generate_gcov_clean(self): - gcno_elem = self.create_phony_target(self.all_outputs, 'clean-gcno', 'CUSTOM_COMMAND', 'PHONY') + gcno_elem = self.create_phony_target('clean-gcno', 'CUSTOM_COMMAND', 'PHONY') gcno_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files') self.add_build(gcno_elem) - gcda_elem = self.create_phony_target(self.all_outputs, 'clean-gcda', 'CUSTOM_COMMAND', 'PHONY') + gcda_elem = self.create_phony_target('clean-gcda', 'CUSTOM_COMMAND', 'PHONY') gcda_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcda']) gcda_elem.add_item('description', 'Deleting gcda files') self.add_build(gcda_elem) @@ -3615,7 +3615,7 @@ def get_user_option_args(self): return sorted(cmds) def generate_dist(self): - elem = self.create_phony_target(self.all_outputs, 'dist', 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target('dist', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('DESC', 'Creating source packages') elem.add_item('COMMAND', self.environment.get_build_command() + ['dist']) elem.add_item('pool', 'console') @@ -3629,7 +3629,7 @@ def generate_scanbuild(self): cmd = self.environment.get_build_command() + \ ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \ self.environment.get_build_command() + self.get_user_option_args() - elem = self.create_phony_target(self.all_outputs, 'scan-build', 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target('scan-build', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') self.add_build(elem) @@ -3648,7 +3648,7 @@ def generate_clangtool(self, name, extra_arg=None): cmd = self.environment.get_build_command() + \ ['--internal', 'clang' + name, self.environment.source_dir, self.environment.build_dir] + \ extra_args - elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target(target_name, 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') self.add_build(elem) @@ -3673,7 +3673,7 @@ def generate_tags(self, tool, target_name): return cmd = self.environment.get_build_command() + \ ['--internal', 'tags', tool, self.environment.source_dir] - elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target(target_name, 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') self.add_build(elem) @@ -3687,7 +3687,7 @@ def generate_utils(self): self.generate_tags('ctags', 'ctags') self.generate_tags('cscope', 'cscope') cmd = self.environment.get_build_command() + ['--internal', 'uninstall'] - elem = self.create_phony_target(self.all_outputs, 'uninstall', 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target('uninstall', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') self.add_build(elem) @@ -3715,7 +3715,7 @@ def generate_ending(self): elem = NinjaBuildElement(self.all_outputs, targ, 'phony', targetlist) self.add_build(elem) - elem = self.create_phony_target(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY') + elem = self.create_phony_target('clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', self.ninja_command + ['-t', 'clean']) elem.add_item('description', 'Cleaning') From 4d3432daa3e4291f88056d5a02d214c7d9f77191 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 24 Jul 2023 15:17:27 -0400 Subject: [PATCH 042/855] ninjabackend: track all outputs using a set We need to verify that we don't produce multiple rules for the same file. This uniqueness check is easy to do with a set, but the original old implementation used a dict with True as the value. This isn't a terrible way to implement a set -- we do it for our own internal OrderedSet implementation, even, and back in prehistory (python 2.3) the standard library's set type was one. But it was deleted and replaced with a fast native implementation, and we should too. --- mesonbuild/backend/ninjabackend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 22d5983a1985..5cac121b6fd6 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -299,7 +299,7 @@ def length_estimate(self, infiles, outfiles, elems): return estimate class NinjaBuildElement: - def __init__(self, all_outputs, outfilenames, rulename, infilenames, implicit_outs=None): + def __init__(self, all_outputs: T.Set[str], outfilenames, rulename, infilenames, implicit_outs=None): self.implicit_outfilenames = implicit_outs or [] if isinstance(outfilenames, str): self.outfilenames = [outfilenames] @@ -426,7 +426,7 @@ def check_outputs(self): for n in self.outfilenames: if n in self.all_outputs: self.output_errors = f'Multiple producers for Ninja target "{n}". Please rename your targets.' - self.all_outputs[n] = True + self.all_outputs.add(n) @dataclass class RustDep: @@ -485,7 +485,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.name = 'ninja' self.ninja_filename = 'build.ninja' self.fortran_deps = {} - self.all_outputs = {} + self.all_outputs: T.Set[str] = set() self.introspection_data = {} self.created_llvm_ir_rule = PerMachine(False, False) self.rust_crates: T.Dict[str, RustCrate] = {} From dd578decdb473a9e46c266567077ba114ec36272 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 23 Jul 2023 13:40:57 -0400 Subject: [PATCH 043/855] ninjabackend: add or correct various bits of typing Down from 607 mypy errors to 379. --- mesonbuild/backend/ninjabackend.py | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 5cac121b6fd6..8776796256ca 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -167,7 +167,7 @@ def __str__(self) -> str: return self.s @staticmethod - def list(l: str, q: Quoting) -> T.List[NinjaCommandArg]: + def list(l: T.List[str], q: Quoting) -> T.List[NinjaCommandArg]: return [NinjaCommandArg(i, q) for i in l] @dataclass @@ -317,7 +317,7 @@ def __init__(self, all_outputs: T.Set[str], outfilenames, rulename, infilenames, self.all_outputs = all_outputs self.output_errors = '' - def add_dep(self, dep): + def add_dep(self, dep: T.Union[str, T.List[str]]) -> None: if isinstance(dep, list): self.deps.update(dep) else: @@ -329,7 +329,7 @@ def add_orderdep(self, dep): else: self.orderdeps.add(dep) - def add_item(self, name, elems): + def add_item(self, name: str, elems: T.Union[str, T.List[str, CompilerArgs]]) -> None: # Always convert from GCC-style argument naming to the naming used by the # current compiler. Also filter system include paths, deduplicate, etc. if isinstance(elems, CompilerArgs): @@ -491,7 +491,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.rust_crates: T.Dict[str, RustCrate] = {} self.implicit_meson_outs = [] - def create_phony_target(self, dummy_outfile, rulename, phony_infilename): + def create_phony_target(self, dummy_outfile: str, rulename: str, phony_infilename: str) -> NinjaBuildElement: ''' We need to use aliases for targets that might be used as directory names to workaround a Ninja bug that breaks `ninja -t clean`. @@ -1083,7 +1083,7 @@ def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: return False return True - def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], + def generate_dependency_scan_target(self, target: build.BuildTarget, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], object_deps: T.List['mesonlib.FileOrString']) -> None: if not self.should_use_dyndeps_for_target(target): return @@ -1335,19 +1335,19 @@ def generate_rules(self): 'Regenerating build files.', extra='generator = 1')) - def add_rule_comment(self, comment): + def add_rule_comment(self, comment: NinjaComment) -> None: self.rules.append(comment) - def add_build_comment(self, comment): + def add_build_comment(self, comment: NinjaComment) -> None: self.build_elements.append(comment) - def add_rule(self, rule): + def add_rule(self, rule: NinjaRule) -> None: if rule.name in self.ruledict: raise MesonException(f'Tried to add rule {rule.name} twice.') self.rules.append(rule) self.ruledict[rule.name] = rule - def add_build(self, build): + def add_build(self, build: NinjaBuildElement) -> None: build.check_outputs() self.build_elements.append(build) @@ -1358,7 +1358,7 @@ def add_build(self, build): else: mlog.warning(f"build statement for {build.outfilenames} references nonexistent rule {build.rulename}") - def write_rules(self, outfile): + def write_rules(self, outfile: T.TextIO) -> None: for b in self.build_elements: if isinstance(b, NinjaBuildElement): b.count_rule_references() @@ -1366,12 +1366,12 @@ def write_rules(self, outfile): for r in self.rules: r.write(outfile) - def write_builds(self, outfile): + def write_builds(self, outfile: T.TextIO) -> None: for b in ProgressBar(self.build_elements, desc='Writing build.ninja'): b.write(outfile) mlog.log_timestamp("build.ninja generated") - def generate_phony(self): + def generate_phony(self) -> None: self.add_build_comment(NinjaComment('Phony build target, always out of date')) elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '') self.add_build(elem) @@ -3095,7 +3095,7 @@ def generate_single_compile(self, target: build.BuildTarget, src, assert isinstance(rel_src, str) return (rel_obj, rel_src.replace('\\', '/')) - def add_dependency_scanner_entries_to_element(self, target, compiler, element, src): + def add_dependency_scanner_entries_to_element(self, target: build.BuildTarget, compiler, element, src): if not self.should_use_dyndeps_for_target(target): return if isinstance(target, build.CompileTarget): @@ -3109,7 +3109,7 @@ def add_dependency_scanner_entries_to_element(self, target, compiler, element, s element.add_item('dyndep', dep_scan_file) element.add_orderdep(dep_scan_file) - def get_dep_scan_file_for(self, target): + def get_dep_scan_file_for(self, target: build.BuildTarget) -> str: return os.path.join(self.get_target_private_dir(target), 'depscan.dd') def add_header_deps(self, target, ninja_element, header_deps): @@ -3120,7 +3120,7 @@ def add_header_deps(self, target, ninja_element, header_deps): d = os.path.join(self.get_target_private_dir(target), d) ninja_element.add_dep(d) - def has_dir_part(self, fname): + def has_dir_part(self, fname: mesonlib.FileOrString) -> bool: # FIXME FIXME: The usage of this is a terrible and unreliable hack if isinstance(fname, File): return fname.subdir != '' @@ -3593,7 +3593,7 @@ def generate_custom_target_clean(self, trees: T.List[str]) -> str: pickle.dump(d, ofile) return 'clean-ctlist' - def generate_gcov_clean(self): + def generate_gcov_clean(self) -> None: gcno_elem = self.create_phony_target('clean-gcno', 'CUSTOM_COMMAND', 'PHONY') gcno_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files') @@ -3614,14 +3614,14 @@ def get_user_option_args(self): # affect behavior in any other way. return sorted(cmds) - def generate_dist(self): + def generate_dist(self) -> None: elem = self.create_phony_target('dist', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('DESC', 'Creating source packages') elem.add_item('COMMAND', self.environment.get_build_command() + ['dist']) elem.add_item('pool', 'console') self.add_build(elem) - def generate_scanbuild(self): + def generate_scanbuild(self) -> None: if not environment.detect_scanbuild(): return if 'scan-build' in self.all_outputs: @@ -3634,7 +3634,7 @@ def generate_scanbuild(self): elem.add_item('pool', 'console') self.add_build(elem) - def generate_clangtool(self, name, extra_arg=None): + def generate_clangtool(self, name: str, extra_arg: T.Optional[str] = None) -> None: target_name = 'clang-' + name extra_args = [] if extra_arg: @@ -3653,19 +3653,19 @@ def generate_clangtool(self, name, extra_arg=None): elem.add_item('pool', 'console') self.add_build(elem) - def generate_clangformat(self): + def generate_clangformat(self) -> None: if not environment.detect_clangformat(): return self.generate_clangtool('format') self.generate_clangtool('format', 'check') - def generate_clangtidy(self): + def generate_clangtidy(self) -> None: import shutil if not shutil.which('clang-tidy'): return self.generate_clangtool('tidy') - def generate_tags(self, tool, target_name): + def generate_tags(self, tool: str, target_name: str) -> None: import shutil if not shutil.which(tool): return @@ -3679,7 +3679,7 @@ def generate_tags(self, tool, target_name): self.add_build(elem) # For things like scan-build and other helper tools we might have. - def generate_utils(self): + def generate_utils(self) -> None: self.generate_scanbuild() self.generate_clangformat() self.generate_clangtidy() @@ -3692,7 +3692,7 @@ def generate_utils(self): elem.add_item('pool', 'console') self.add_build(elem) - def generate_ending(self): + def generate_ending(self) -> None: for targ, deps in [ ('all', self.get_build_by_default_targets()), ('meson-test-prereq', self.get_testlike_targets()), From 020610cfbe55870e9ca3c8206328112b95e0ec4e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 24 Jul 2023 19:34:19 -0700 Subject: [PATCH 044/855] modules/pkgconfig: Don't insert None into devenv list When the pkgconfig module is imported, but not used, it will insert None on the end of the devenv list. This list is not expected to contain None, and causes Meson to crash. This can happen in complex build setups (reported from mesa), where pkgconfig is only used in some configurations Fixes: #12032 --- mesonbuild/modules/pkgconfig.py | 3 ++- test cases/unit/90 devenv/meson.build | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index c6bc42d095bd..dd2efad73116 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -391,7 +391,8 @@ def __init__(self) -> None: }) def postconf_hook(self, b: build.Build) -> None: - b.devenv.append(self.devenv) + if self.devenv is not None: + b.devenv.append(self.devenv) def _get_lname(self, l: T.Union[build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex], msg: str, pcfile: str) -> str: diff --git a/test cases/unit/90 devenv/meson.build b/test cases/unit/90 devenv/meson.build index 72d8fdc33ca8..316b20c62a39 100644 --- a/test cases/unit/90 devenv/meson.build +++ b/test cases/unit/90 devenv/meson.build @@ -20,3 +20,6 @@ env = environment({'TEST_C': ['/prefix']}, method: 'prepend') meson.add_devenv(env) env = environment({'TEST_C': ['/suffix']}, method: 'append') meson.add_devenv(env) + +# Reproducer for https://github.com/mesonbuild/meson/issues/12032 +pkgconf = import('pkgconfig') From 67035a181e90f3bdea14a06cd336f95d10a90b4f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 14:18:55 -0700 Subject: [PATCH 045/855] interpreter: use typed_kwargs for gui_app --- mesonbuild/build.py | 4 +--- mesonbuild/interpreter/interpreter.py | 3 +-- mesonbuild/interpreter/kwargs.py | 3 ++- mesonbuild/interpreter/type_checking.py | 4 +++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index f888ab12ee6d..9c2cb1ae76c4 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1151,12 +1151,10 @@ def process_kwargs(self, kwargs): # This kwarg is deprecated. The value of "none" means that the kwarg # was not specified and win_subsystem should be used instead. self.gui_app = None - if 'gui_app' in kwargs: + if kwargs.get('gui_app') is not None: if 'win_subsystem' in kwargs: raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.') self.gui_app = kwargs['gui_app'] - if not isinstance(self.gui_app, bool): - raise InvalidArguments('Argument gui_app must be boolean.') self.win_subsystem = self.validate_win_subsystem(kwargs.get('win_subsystem', 'console')) elif 'gui_app' in kwargs: raise InvalidArguments('Argument gui_app can only be used on executables.') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f12a059e7c56..69a48faf4252 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -33,7 +33,7 @@ from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest from ..interpreterbase import Disabler, disablerIfNotFound -from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs, FeatureDeprecatedKwargs +from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs from ..interpreterbase import ObjectHolder, ContextManagerObject from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule @@ -1808,7 +1808,6 @@ def func_disabler(self, node, args, kwargs): @FeatureNewKwargs('executable', '0.42.0', ['implib']) @FeatureNewKwargs('executable', '0.56.0', ['win_subsystem']) - @FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.") @permittedKwargs(build.known_exe_kwargs) @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 31c96e28ec97..07b6165f7b38 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -327,7 +327,8 @@ class _BuildTarget(_BaseBuildTarget): class Executable(_BuildTarget): - pass + + gui_app: T.Optional[bool] class StaticLibrary(_BuildTarget): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 206a2e6f532f..2b78eb6c8990 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -492,7 +492,9 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Arguments exclusive to Executable. These are separated to make integrating # them into build_target easier -_EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [] +_EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ + KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead") +] # The total list of arguments used by Executable EXECUTABLE_KWS = [ From 1cfbe5279db3e5195b3f71c33960daf5afbd0425 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 14:25:57 -0700 Subject: [PATCH 046/855] interpreter: use typed_kwargs for Executable(win_subsystem) --- mesonbuild/build.py | 10 ++-------- mesonbuild/interpreter/interpreter.py | 1 - mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 15 ++++++++++++++- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 9c2cb1ae76c4..025af1505249 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1152,10 +1152,10 @@ def process_kwargs(self, kwargs): # was not specified and win_subsystem should be used instead. self.gui_app = None if kwargs.get('gui_app') is not None: - if 'win_subsystem' in kwargs: + if kwargs.get('win_subsystem') is not None: raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.') self.gui_app = kwargs['gui_app'] - self.win_subsystem = self.validate_win_subsystem(kwargs.get('win_subsystem', 'console')) + self.win_subsystem = kwargs.get('win_subsystem', 'console') elif 'gui_app' in kwargs: raise InvalidArguments('Argument gui_app can only be used on executables.') elif 'win_subsystem' in kwargs: @@ -1240,12 +1240,6 @@ def process_kwargs(self, kwargs): raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary with string values.') self.rust_dependency_map = rust_dependency_map - def validate_win_subsystem(self, value: str) -> str: - value = value.lower() - if re.fullmatch(r'(boot_application|console|efi_application|efi_boot_service_driver|efi_rom|efi_runtime_driver|native|posix|windows)(,\d+(\.\d+)?)?', value) is None: - raise InvalidArguments(f'Invalid value for win_subsystem: {value}.') - return value - def _extract_pic_pie(self, kwargs, arg: str, option: str): # Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags all_flags = self.extra_args['c'] + self.extra_args['cpp'] diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 69a48faf4252..125562fe3ae8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1807,7 +1807,6 @@ def func_disabler(self, node, args, kwargs): return Disabler() @FeatureNewKwargs('executable', '0.42.0', ['implib']) - @FeatureNewKwargs('executable', '0.56.0', ['win_subsystem']) @permittedKwargs(build.known_exe_kwargs) @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 07b6165f7b38..13b7430b39b9 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -329,6 +329,7 @@ class _BuildTarget(_BaseBuildTarget): class Executable(_BuildTarget): gui_app: T.Optional[bool] + win_subsystem: T.Optional[str] class StaticLibrary(_BuildTarget): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 2b78eb6c8990..b919d6a54903 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -5,6 +5,7 @@ from __future__ import annotations import os +import re import typing as T from .. import compilers @@ -490,10 +491,22 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus *_ALL_TARGET_KWS, ] +def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: + if value is not None: + if re.fullmatch(r'(boot_application|console|efi_application|efi_boot_service_driver|efi_rom|efi_runtime_driver|native|posix|windows)(,\d+(\.\d+)?)?', value) is None: + return f'Invalid value for win_subsystem: {value}.' + return None + # Arguments exclusive to Executable. These are separated to make integrating # them into build_target easier _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ - KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead") + KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead"), + KwargInfo( + 'win_subsystem', + (str, NoneType), + convertor=lambda x: x.lower() if isinstance(x, str) else None, + validator=_validate_win_subsystem, + ), ] # The total list of arguments used by Executable From 1a182ab59919d4838613f9d1962623447636663e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 19 Jul 2023 14:37:03 -0700 Subject: [PATCH 047/855] make 'gui_app' an interpreter only concept Since it's deprecated anyway, we don't really want to plumb it all the way down into the build and backend layers. Instead, we can just turn it into a `win_subsystem` value in the interpreter if `win_subsystem` isn't already set. --- mesonbuild/backend/ninjabackend.py | 7 ++----- mesonbuild/backend/vs2010backend.py | 10 +++------- mesonbuild/build.py | 18 ++++++------------ mesonbuild/compilers/compilers.py | 4 ---- mesonbuild/compilers/mixins/gnu.py | 3 --- mesonbuild/interpreter/interpreter.py | 12 ++++++++++++ mesonbuild/linkers/linkers.py | 13 ------------- 7 files changed, 23 insertions(+), 44 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8776796256ca..3ddc197aece7 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3277,16 +3277,13 @@ def get_target_type_link_args(self, target, linker): def get_target_type_link_args_post_dependencies(self, target, linker): commands = [] if isinstance(target, build.Executable): - # If gui_app is significant on this platform, add the appropriate linker arguments. + # If win_subsystem is significant on this platform, add the appropriate linker arguments. # Unfortunately this can't be done in get_target_type_link_args, because some misguided # libraries (such as SDL2) add -mwindows to their link flags. m = self.environment.machines[target.for_machine] if m.is_windows() or m.is_cygwin(): - if target.gui_app is not None: - commands += linker.get_gui_app_args(target.gui_app) - else: - commands += linker.get_win_subsystem_args(target.win_subsystem) + commands += linker.get_win_subsystem_args(target.win_subsystem) return commands def get_link_whole_args(self, linker, target): diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 340c1a5478bf..0a382be22551 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1645,13 +1645,9 @@ def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ conftype = 'Makefile' elif isinstance(target, build.Executable): conftype = 'Application' - if target.gui_app is not None: - if not target.gui_app: - subsystem = 'Console' - else: - # If someone knows how to set the version properly, - # please send a patch. - subsystem = target.win_subsystem.split(',')[0] + # If someone knows how to set the version properly, + # please send a patch. + subsystem = target.win_subsystem.split(',')[0] elif isinstance(target, build.StaticLibrary): conftype = 'StaticLibrary' elif isinstance(target, build.SharedLibrary): diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 025af1505249..cfb3a5418f66 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1147,19 +1147,12 @@ def process_kwargs(self, kwargs): (str, bool)) self.install_mode = kwargs.get('install_mode', None) self.install_tag = stringlistify(kwargs.get('install_tag', [None])) - if isinstance(self, Executable): - # This kwarg is deprecated. The value of "none" means that the kwarg - # was not specified and win_subsystem should be used instead. - self.gui_app = None + if not isinstance(self, Executable): + # build_target will always populate these as `None`, which is fine if kwargs.get('gui_app') is not None: - if kwargs.get('win_subsystem') is not None: - raise InvalidArguments('Can specify only gui_app or win_subsystem for a target, not both.') - self.gui_app = kwargs['gui_app'] - self.win_subsystem = kwargs.get('win_subsystem', 'console') - elif 'gui_app' in kwargs: - raise InvalidArguments('Argument gui_app can only be used on executables.') - elif 'win_subsystem' in kwargs: - raise InvalidArguments('Argument win_subsystem can only be used on executables.') + raise InvalidArguments('Argument gui_app can only be used on executables.') + if kwargs.get('win_subsystem') is not None: + raise InvalidArguments('Argument win_subsystem can only be used on executables.') extra_files = extract_as_list(kwargs, 'extra_files') for i in extra_files: assert isinstance(i, File) @@ -1901,6 +1894,7 @@ def __init__( kwargs['pie'] = environment.coredata.options[key].value super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, environment, compilers, kwargs) + self.win_subsystem = kwargs.get('win_subsystem') or 'console' # Check for export_dynamic self.export_dynamic = kwargs.get('export_dynamic', False) if not isinstance(self.export_dynamic, bool): diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index cb8eae56ac4e..7a8ae7247cfa 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -980,10 +980,6 @@ def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]: return [] - def get_gui_app_args(self, value: bool) -> T.List[str]: - # Only used on Windows - return self.linker.get_gui_app_args(value) - def get_win_subsystem_args(self, value: str) -> T.List[str]: # By default the dynamic linker is going to return an empty # array in case it either doesn't support Windows subsystems diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 2b187327b8d7..b62435b1931b 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -451,9 +451,6 @@ def get_profile_generate_args(self) -> T.List[str]: def get_profile_use_args(self) -> T.List[str]: return ['-fprofile-use'] - def get_gui_app_args(self, value: bool) -> T.List[str]: - return ['-mwindows' if value else '-mconsole'] - def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): if i[:2] == '-I' or i[:2] == '-L': diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 125562fe3ae8..67203bdc4c1b 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3280,6 +3280,18 @@ def build_target_decorator_caller(self, node, args, kwargs): outputs.update(o) kwargs['include_directories'] = self.extract_incdirs(kwargs) + + if targetclass is build.Executable: + if kwargs['gui_app'] is not None: + if kwargs['win_subsystem'] is not None: + raise InvalidArguments.from_node( + 'Executable got both "gui_app", and "win_subsystem" arguments, which are mutually exclusive', + node=node) + if kwargs['gui_app']: + kwargs['win_subsystem'] = 'windows' + if kwargs['win_subsystem'] is None: + kwargs['win_subsystem'] = 'console' + target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, self.environment, self.compilers[for_machine], kwargs) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 89483477d8f6..9176090404a4 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -279,10 +279,6 @@ def headerpad_args(self) -> T.List[str]: # Only used by the Apple linker return [] - def get_gui_app_args(self, value: bool) -> T.List[str]: - # Only used by VisualStudioLikeLinkers - return [] - def get_win_subsystem_args(self, value: str) -> T.List[str]: # Only used if supported by the dynamic linker and # only when targeting Windows @@ -1318,9 +1314,6 @@ def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str] def get_always_args(self) -> T.List[str]: return self._apply_prefix(['/nologo', '/release']) + super().get_always_args() - def get_gui_app_args(self, value: bool) -> T.List[str]: - return self.get_win_subsystem_args("windows" if value else "console") - def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) @@ -1347,9 +1340,6 @@ def get_output_args(self, outputname: str) -> T.List[str]: return super().get_output_args(outputname) - def get_gui_app_args(self, value: bool) -> T.List[str]: - return self.get_win_subsystem_args("windows" if value else "console") - def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) @@ -1370,9 +1360,6 @@ def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str] direct: bool = True): super().__init__(['xilink.exe'], for_machine, '', always_args, version=version) - def get_gui_app_args(self, value: bool) -> T.List[str]: - return self.get_win_subsystem_args("windows" if value else "console") - def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) From 6aceb7e2d6053a80af88280c7006baec1d25be55 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 25 Jul 2023 13:28:34 -0400 Subject: [PATCH 048/855] packaging: fix regression that prevented pyinstaller from getting custom deps mesonbuild.dependencies.* is now lazy-imported and not automatically detected. Add them as hidden imports. Fixes #12036 --- packaging/hook-mesonbuild.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packaging/hook-mesonbuild.py b/packaging/hook-mesonbuild.py index 86e74639f03b..d6b06cd26213 100644 --- a/packaging/hook-mesonbuild.py +++ b/packaging/hook-mesonbuild.py @@ -25,7 +25,11 @@ def get_all_modules_from_dir(dirname): datas += collect_data_files('mesonbuild.cmake.data') datas += collect_data_files('mesonbuild.dependencies.data') +# lazy-loaded +hiddenimports += get_all_modules_from_dir('mesonbuild/dependencies') +# imported by meson.build files hiddenimports += get_all_modules_from_dir('mesonbuild/modules') +# executed when named on CLI hiddenimports += get_all_modules_from_dir('mesonbuild/scripts') # Python packagers want to be minimal and only copy the things From 54295560ea4a5c2e1935f1cc72526bb2b5171440 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 10:54:02 -0700 Subject: [PATCH 049/855] minit: fix docstring Which must come before `from __future__` --- mesonbuild/minit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 7cca9cfc1fe9..8fc1811943cc 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -11,10 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import annotations """Code that creates simple startup projects.""" +from __future__ import annotations + from pathlib import Path from enum import Enum import subprocess From b082f0025032724216858bc0e2a78ae959287a56 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 10:54:56 -0700 Subject: [PATCH 050/855] minit: put imports together --- mesonbuild/minit.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 8fc1811943cc..2d8786f6d4fe 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -27,16 +27,13 @@ from mesonbuild import build, mesonlib, mlog from mesonbuild.coredata import FORBIDDEN_TARGET_NAMES from mesonbuild.environment import detect_ninja +from mesonbuild.templates.mesontemplates import create_meson_build from mesonbuild.templates.samplefactory import sameple_generator import typing as T if T.TYPE_CHECKING: import argparse -''' -we currently have one meson template at this time. -''' -from mesonbuild.templates.mesontemplates import create_meson_build FORTRAN_SUFFIXES = {'.f', '.for', '.F', '.f90', '.F90'} LANG_SUFFIXES = {'.c', '.cc', '.cpp', '.cs', '.cu', '.d', '.m', '.mm', '.rs', '.java', '.vala'} | FORTRAN_SUFFIXES From b0cd88ceae930b3ddc8165d43513141fa9486587 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 10:55:29 -0700 Subject: [PATCH 051/855] minit: use a Protocol for arguments Which gives better type hinting. It also points out that we're changing the type of sourcefiles. That's now fixed --- mesonbuild/minit.py | 30 ++++++++++++++++++++------ mesonbuild/templates/mesontemplates.py | 7 ++++-- mesonbuild/templates/samplefactory.py | 8 +++++-- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 2d8786f6d4fe..8f64f9becc90 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -24,16 +24,33 @@ import os import re from glob import glob +import typing as T + from mesonbuild import build, mesonlib, mlog from mesonbuild.coredata import FORBIDDEN_TARGET_NAMES from mesonbuild.environment import detect_ninja from mesonbuild.templates.mesontemplates import create_meson_build from mesonbuild.templates.samplefactory import sameple_generator -import typing as T if T.TYPE_CHECKING: import argparse + from typing_extensions import Protocol, Literal + + class Arguments(Protocol): + + srcfiles: T.List[Path] + wd: str + name: str + executable: str + deps: str + language: Literal['c', 'cpp', 'cs', 'cuda', 'd', 'fortran', 'java', 'rust', 'objc', 'objcpp', 'vala'] + build: bool + builddir: str + force: bool + type: Literal['executable', 'library'] + version: str + FORTRAN_SUFFIXES = {'.f', '.for', '.F', '.f90', '.F90'} LANG_SUFFIXES = {'.c', '.cc', '.cpp', '.cs', '.cu', '.d', '.m', '.mm', '.rs', '.java', '.vala'} | FORTRAN_SUFFIXES @@ -53,7 +70,7 @@ class DEFAULT_TYPES(Enum): ''' -def create_sample(options: 'argparse.Namespace') -> None: +def create_sample(options: Arguments) -> None: ''' Based on what arguments are passed we check for a match in language then check for project type and create new Meson samples project. @@ -67,7 +84,7 @@ def create_sample(options: 'argparse.Namespace') -> None: raise RuntimeError('Unreachable code') print(INFO_MESSAGE) -def autodetect_options(options: 'argparse.Namespace', sample: bool = False) -> None: +def autodetect_options(options: Arguments, sample: bool = False) -> None: ''' Here we autodetect options for args not passed in so don't have to think about it. @@ -88,7 +105,7 @@ def autodetect_options(options: 'argparse.Namespace', sample: bool = False) -> N # The rest of the autodetection is not applicable to generating sample projects. return if not options.srcfiles: - srcfiles = [] + srcfiles: T.List[Path] = [] for f in (f for f in Path().iterdir() if f.is_file()): if f.suffix in LANG_SUFFIXES: srcfiles.append(f) @@ -97,7 +114,6 @@ def autodetect_options(options: 'argparse.Namespace', sample: bool = False) -> N 'Run meson init in an empty directory to create a sample project.') options.srcfiles = srcfiles print("Detected source files: " + ' '.join(str(s) for s in srcfiles)) - options.srcfiles = [Path(f) for f in options.srcfiles] if not options.language: for f in options.srcfiles: if f.suffix == '.c': @@ -142,7 +158,7 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None: Here we add args for that the user can passed when making a new Meson project. ''' - parser.add_argument("srcfiles", metavar="sourcefile", nargs="*", help="source files. default: all recognized files in current directory") + parser.add_argument("srcfiles", metavar="sourcefile", nargs="*", type=Path, help="source files. default: all recognized files in current directory") parser.add_argument('-C', dest='wd', action=mesonlib.RealPathAction, help='directory to cd into before running') parser.add_argument("-n", "--name", help="project name. default: name of current directory") @@ -155,7 +171,7 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None: parser.add_argument('--type', default=DEFAULT_PROJECT, choices=('executable', 'library'), help=f"project type. default: {DEFAULT_PROJECT} based project") parser.add_argument('--version', default=DEFAULT_VERSION, help=f"project version. default: {DEFAULT_VERSION}") -def run(options: 'argparse.Namespace') -> int: +def run(options: Arguments) -> int: ''' Here we generate the new Meson sample project. ''' diff --git a/mesonbuild/templates/mesontemplates.py b/mesonbuild/templates/mesontemplates.py index 2868f7b53ec0..bc059fa08cc2 100644 --- a/mesonbuild/templates/mesontemplates.py +++ b/mesonbuild/templates/mesontemplates.py @@ -13,7 +13,10 @@ # limitations under the License. from __future__ import annotations -import argparse +import typing as T + +if T.TYPE_CHECKING: + from ..minit import Arguments meson_executable_template = '''project('{project_name}', {language}, version : '{version}', @@ -36,7 +39,7 @@ ''' -def create_meson_build(options: argparse.Namespace) -> None: +def create_meson_build(options: Arguments) -> None: if options.type != 'executable': raise SystemExit('\nGenerating a meson.build file from existing sources is\n' 'supported only for project type "executable".\n' diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 195083764f91..5c91023c5eab 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -13,6 +13,8 @@ # limitations under the License. from __future__ import annotations +import typing as T + from mesonbuild.templates.valatemplates import ValaProject from mesonbuild.templates.fortrantemplates import FortranProject from mesonbuild.templates.objcpptemplates import ObjCppProject @@ -26,9 +28,11 @@ from mesonbuild.templates.ctemplates import CProject from mesonbuild.templates.sampleimpl import SampleImpl -import argparse +if T.TYPE_CHECKING: + from ..minit import Arguments + -def sameple_generator(options: argparse.Namespace) -> SampleImpl: +def sameple_generator(options: Arguments) -> SampleImpl: return { 'c': CProject, 'cpp': CppProject, From 3fdc877e8a971b3849784797dcc87045aefcd42a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 11:18:27 -0700 Subject: [PATCH 052/855] templates/samplefactory: move type checking only import to special block Don't import things we don't actually need at runtime --- mesonbuild/templates/samplefactory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 5c91023c5eab..9c0c13ed5bbf 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -26,10 +26,10 @@ from mesonbuild.templates.cpptemplates import CppProject from mesonbuild.templates.cstemplates import CSharpProject from mesonbuild.templates.ctemplates import CProject -from mesonbuild.templates.sampleimpl import SampleImpl if T.TYPE_CHECKING: from ..minit import Arguments + from .sampleimpl import SampleImpl def sameple_generator(options: Arguments) -> SampleImpl: From d0729bde02a4fd7708fc9fce2dd779e9fb9ab342 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 14:33:43 -0700 Subject: [PATCH 053/855] templates: move initializer to base class Every class implements the exact same initializer, simplify this by putting it in the base class initializer --- mesonbuild/templates/cpptemplates.py | 7 ++----- mesonbuild/templates/cstemplates.py | 7 ++----- mesonbuild/templates/ctemplates.py | 7 ++----- mesonbuild/templates/cudatemplates.py | 7 ++----- mesonbuild/templates/dlangtemplates.py | 7 ++----- mesonbuild/templates/fortrantemplates.py | 7 ++----- mesonbuild/templates/javatemplates.py | 7 ++----- mesonbuild/templates/objcpptemplates.py | 7 ++----- mesonbuild/templates/objctemplates.py | 7 ++----- mesonbuild/templates/rusttemplates.py | 7 ++----- mesonbuild/templates/sampleimpl.py | 10 ++++++++++ mesonbuild/templates/valatemplates.py | 7 ++----- 12 files changed, 32 insertions(+), 55 deletions(-) diff --git a/mesonbuild/templates/cpptemplates.py b/mesonbuild/templates/cpptemplates.py index 6e9776180597..75a5ee2568bb 100644 --- a/mesonbuild/templates/cpptemplates.py +++ b/mesonbuild/templates/cpptemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_cpp_template = '''#include @@ -143,10 +144,6 @@ class {utoken}_PUBLIC {class_name} {{ class CppProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/cstemplates.py b/mesonbuild/templates/cstemplates.py index df09f61fd305..39653d48acec 100644 --- a/mesonbuild/templates/cstemplates.py +++ b/mesonbuild/templates/cstemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_cs_template = '''using System; @@ -92,10 +93,6 @@ class CSharpProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/ctemplates.py b/mesonbuild/templates/ctemplates.py index 0c7141a626f3..16e6c44478c8 100644 --- a/mesonbuild/templates/ctemplates.py +++ b/mesonbuild/templates/ctemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + lib_h_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ @@ -126,10 +127,6 @@ class CProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/cudatemplates.py b/mesonbuild/templates/cudatemplates.py index 63abd2be8751..ce775040caec 100644 --- a/mesonbuild/templates/cudatemplates.py +++ b/mesonbuild/templates/cudatemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_cuda_template = '''#include @@ -143,10 +144,6 @@ class {utoken}_PUBLIC {class_name} {{ class CudaProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/dlangtemplates.py b/mesonbuild/templates/dlangtemplates.py index 81840fe111a0..d5adf926914a 100644 --- a/mesonbuild/templates/dlangtemplates.py +++ b/mesonbuild/templates/dlangtemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_d_template = '''module main; import std.stdio; @@ -104,10 +105,6 @@ class DlangProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/fortrantemplates.py b/mesonbuild/templates/fortrantemplates.py index 00cd509702e9..6c21cad68396 100644 --- a/mesonbuild/templates/fortrantemplates.py +++ b/mesonbuild/templates/fortrantemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + lib_fortran_template = ''' ! This procedure will not be exported and is not ! directly callable by users of this library. @@ -103,10 +104,6 @@ class FortranProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/javatemplates.py b/mesonbuild/templates/javatemplates.py index 58d48bac1d20..4b9c7469580f 100644 --- a/mesonbuild/templates/javatemplates.py +++ b/mesonbuild/templates/javatemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_java_template = ''' @@ -96,10 +97,6 @@ class JavaProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/objcpptemplates.py b/mesonbuild/templates/objcpptemplates.py index 450f2b03035c..4ec785c185e8 100644 --- a/mesonbuild/templates/objcpptemplates.py +++ b/mesonbuild/templates/objcpptemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + lib_h_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ @@ -126,10 +127,6 @@ class ObjCppProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/objctemplates.py b/mesonbuild/templates/objctemplates.py index 2e035269f65c..331b76cc0f87 100644 --- a/mesonbuild/templates/objctemplates.py +++ b/mesonbuild/templates/objctemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + lib_h_template = '''#pragma once #if defined _WIN32 || defined __CYGWIN__ @@ -126,10 +127,6 @@ class ObjCProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/rusttemplates.py b/mesonbuild/templates/rusttemplates.py index 0dde5474ce99..840835987e34 100644 --- a/mesonbuild/templates/rusttemplates.py +++ b/mesonbuild/templates/rusttemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + lib_rust_template = '''#![crate_name = "{crate_file}"] @@ -74,10 +75,6 @@ class RustProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) diff --git a/mesonbuild/templates/sampleimpl.py b/mesonbuild/templates/sampleimpl.py index 9702ae884b8e..4d586b1fe1e4 100644 --- a/mesonbuild/templates/sampleimpl.py +++ b/mesonbuild/templates/sampleimpl.py @@ -13,8 +13,18 @@ # limitations under the License. from __future__ import annotations +import typing as T + +if T.TYPE_CHECKING: + from ..minit import Arguments + class SampleImpl: + + def __init__(self, args: Arguments): + self.name = args.name + self.version = args.version + def create_executable(self) -> None: raise NotImplementedError('Sample implementation for "executable" not implemented!') diff --git a/mesonbuild/templates/valatemplates.py b/mesonbuild/templates/valatemplates.py index ef9794dc2b17..b6a461417809 100644 --- a/mesonbuild/templates/valatemplates.py +++ b/mesonbuild/templates/valatemplates.py @@ -13,9 +13,10 @@ # limitations under the License. from __future__ import annotations -from mesonbuild.templates.sampleimpl import SampleImpl import re +from mesonbuild.templates.sampleimpl import SampleImpl + hello_vala_template = '''void main (string[] args) {{ stdout.printf ("Hello {project_name}!\\n"); @@ -84,10 +85,6 @@ class ValaProject(SampleImpl): - def __init__(self, options): - super().__init__() - self.name = options.name - self.version = options.version def create_executable(self) -> None: lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) From 65a0cd127e1b180965a1aa5d139c0aac68557c03 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 09:13:25 -0700 Subject: [PATCH 054/855] templates: fix typo in function name `sameple` -> `sample` --- mesonbuild/minit.py | 4 ++-- mesonbuild/templates/samplefactory.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 8f64f9becc90..abe8104d022d 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -30,7 +30,7 @@ from mesonbuild.coredata import FORBIDDEN_TARGET_NAMES from mesonbuild.environment import detect_ninja from mesonbuild.templates.mesontemplates import create_meson_build -from mesonbuild.templates.samplefactory import sameple_generator +from mesonbuild.templates.samplefactory import sample_generator if T.TYPE_CHECKING: import argparse @@ -75,7 +75,7 @@ def create_sample(options: Arguments) -> None: Based on what arguments are passed we check for a match in language then check for project type and create new Meson samples project. ''' - sample_gen = sameple_generator(options) + sample_gen = sample_generator(options) if options.type == DEFAULT_TYPES['EXE'].value: sample_gen.create_executable() elif options.type == DEFAULT_TYPES['LIB'].value: diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 9c0c13ed5bbf..89c3c4c76aa4 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -32,7 +32,7 @@ from .sampleimpl import SampleImpl -def sameple_generator(options: Arguments) -> SampleImpl: +def sample_generator(options: Arguments) -> SampleImpl: return { 'c': CProject, 'cpp': CppProject, From 9ae6e38e90d9a0ddcc1bb8a85eb04220f4976841 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 10:40:11 -0700 Subject: [PATCH 055/855] mypy: add templates to checked modules --- run_mypy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_mypy.py b/run_mypy.py index 3be79bca4c0c..15dd5a628195 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -20,6 +20,7 @@ 'mesonbuild/interpreterbase/', 'mesonbuild/linkers/', 'mesonbuild/scripts/', + 'mesonbuild/templates/', 'mesonbuild/wrap/', # specific files From c30cdfc4b056c2638779bf126b70fd5f6bbaac29 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 14:55:45 -0700 Subject: [PATCH 056/855] unittests: use subtests for template tests Which gives more exact errors --- unittests/allplatformstests.py | 51 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index b4bf3714a4e8..4b20529d02ba 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2231,31 +2231,32 @@ def test_templates(self): for lang in langs: for target_type in ('executable', 'library'): - if is_windows() and lang == 'fortran' and target_type == 'library': - # non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way - # see "test cases/fortran/6 dynamic" - fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True) - if fc.get_id() in {'intel-cl', 'pgi'}: - continue - # test empty directory - with tempfile.TemporaryDirectory() as tmpdir: - self._run(self.meson_command + ['init', '--language', lang, '--type', target_type], - workdir=tmpdir) - self._run(self.setup_command + ['--backend=ninja', 'builddir'], - workdir=tmpdir) - self._run(ninja, - workdir=os.path.join(tmpdir, 'builddir')) - # test directory with existing code file - if lang in {'c', 'cpp', 'd'}: - with tempfile.TemporaryDirectory() as tmpdir: - with open(os.path.join(tmpdir, 'foo.' + lang), 'w', encoding='utf-8') as f: - f.write('int main(void) {}') - self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) - elif lang in {'java'}: - with tempfile.TemporaryDirectory() as tmpdir: - with open(os.path.join(tmpdir, 'Foo.' + lang), 'w', encoding='utf-8') as f: - f.write('public class Foo { public static void main() {} }') - self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + with self.subTest(f'Language: {lang}; type: {target_type}'): + if is_windows() and lang == 'fortran' and target_type == 'library': + # non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way + # see "test cases/fortran/6 dynamic" + fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True) + if fc.get_id() in {'intel-cl', 'pgi'}: + continue + # test empty directory + with tempfile.TemporaryDirectory() as tmpdir: + self._run(self.meson_command + ['init', '--language', lang, '--type', target_type], + workdir=tmpdir) + self._run(self.setup_command + ['--backend=ninja', 'builddir'], + workdir=tmpdir) + self._run(ninja, + workdir=os.path.join(tmpdir, 'builddir')) + # test directory with existing code file + if lang in {'c', 'cpp', 'd'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'foo.' + lang), 'w', encoding='utf-8') as f: + f.write('int main(void) {}') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) + elif lang in {'java'}: + with tempfile.TemporaryDirectory() as tmpdir: + with open(os.path.join(tmpdir, 'Foo.' + lang), 'w', encoding='utf-8') as f: + f.write('public class Foo { public static void main() {} }') + self._run(self.meson_command + ['init', '-b'], workdir=tmpdir) def test_compiler_run_command(self): ''' From bbe649a5fc7bb0b955b2688c4d797b71830c8aeb Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 16:40:09 -0700 Subject: [PATCH 057/855] unittests: test the vala template --- unittests/allplatformstests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 4b20529d02ba..baf5875fc4e2 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2215,7 +2215,7 @@ def test_templates(self): langs = ['c'] env = get_fake_env() - for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust']: + for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust', 'vala']: try: comp = detect_compiler_for(env, l, MachineChoice.HOST, True) with tempfile.TemporaryDirectory() as d: From 5449d10f01bc765e33e041a15f7c90e752ba7539 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 14:58:30 -0700 Subject: [PATCH 058/855] templates: use a common template for C# and Java The only real differences between these generators is the file extension and the templates themselves. We can uses a shared abstract class with a few abstract properties to provide all of this to the same base class. This results in less code duplication and easier maintanence. I've made a few cleanups to the shared template: - use `str.capitalize()` instead of `str.upper()[0] + str[1:]` - use `open` as a context manager - use f-strings - put some duplicate calculations in the initializer --- mesonbuild/templates/cstemplates.py | 51 ++++-------------- mesonbuild/templates/javatemplates.py | 49 ++++------------- mesonbuild/templates/samplefactory.py | 31 ++++++----- mesonbuild/templates/sampleimpl.py | 78 +++++++++++++++++++++++++-- 4 files changed, 110 insertions(+), 99 deletions(-) diff --git a/mesonbuild/templates/cstemplates.py b/mesonbuild/templates/cstemplates.py index 39653d48acec..d2d5ec9f34b3 100644 --- a/mesonbuild/templates/cstemplates.py +++ b/mesonbuild/templates/cstemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import ClassImpl hello_cs_template = '''using System; @@ -92,42 +90,11 @@ ''' -class CSharpProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - source_name = uppercase_token[0] + lowercase_token[1:] + '.cs' - open(source_name, 'w', encoding='utf-8').write( - hello_cs_template.format(project_name=self.name, - class_name=class_name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_cs_meson_template.format(project_name=self.name, - exe_name=self.name, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - class_test = uppercase_token[0] + lowercase_token[1:] + '_test' - project_test = lowercase_token + '_test' - lib_cs_name = uppercase_token[0] + lowercase_token[1:] + '.cs' - test_cs_name = uppercase_token[0] + lowercase_token[1:] + '_test.cs' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'class_test': class_test, - 'class_name': class_name, - 'source_file': lib_cs_name, - 'test_source_file': test_cs_name, - 'test_exe_name': project_test, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_cs_name, 'w', encoding='utf-8').write(lib_cs_template.format(**kwargs)) - open(test_cs_name, 'w', encoding='utf-8').write(lib_cs_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_cs_meson_template.format(**kwargs)) +class CSharpProject(ClassImpl): + + source_ext = 'cs' + exe_template = hello_cs_template + exe_meson_template = hello_cs_meson_template + lib_template = lib_cs_template + lib_test_template = lib_cs_test_template + lib_meson_template = lib_cs_meson_template diff --git a/mesonbuild/templates/javatemplates.py b/mesonbuild/templates/javatemplates.py index 4b9c7469580f..4163ffd32b0d 100644 --- a/mesonbuild/templates/javatemplates.py +++ b/mesonbuild/templates/javatemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import ClassImpl hello_java_template = ''' @@ -96,40 +94,11 @@ ''' -class JavaProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - source_name = uppercase_token[0] + lowercase_token[1:] + '.java' - open(source_name, 'w', encoding='utf-8').write( - hello_java_template.format(project_name=self.name, - class_name=class_name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_java_meson_template.format(project_name=self.name, - exe_name=class_name, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - class_test = uppercase_token[0] + lowercase_token[1:] + '_test' - lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java' - test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'class_test': class_test, - 'class_name': class_name, - 'source_file': lib_java_name, - 'test_source_file': test_java_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs)) - open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs)) +class JavaProject(ClassImpl): + + source_ext = 'java' + exe_template = hello_java_template + exe_meson_template = hello_java_meson_template + lib_template = lib_java_template + lib_test_template = lib_java_test_template + lib_meson_template = lib_java_meson_template diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 89c3c4c76aa4..e3c855103430 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -29,20 +29,23 @@ if T.TYPE_CHECKING: from ..minit import Arguments - from .sampleimpl import SampleImpl + from .sampleimpl import ClassImpl, SampleImpl + + +_IMPL: T.Mapping[str, T.Union[T.Type[ClassImpl], T.Type[SampleImpl]]] = { + 'c': CProject, + 'cpp': CppProject, + 'cs': CSharpProject, + 'cuda': CudaProject, + 'objc': ObjCProject, + 'objcpp': ObjCppProject, + 'java': JavaProject, + 'd': DlangProject, + 'rust': RustProject, + 'fortran': FortranProject, + 'vala': ValaProject, +} def sample_generator(options: Arguments) -> SampleImpl: - return { - 'c': CProject, - 'cpp': CppProject, - 'cs': CSharpProject, - 'cuda': CudaProject, - 'objc': ObjCProject, - 'objcpp': ObjCppProject, - 'java': JavaProject, - 'd': DlangProject, - 'rust': RustProject, - 'fortran': FortranProject, - 'vala': ValaProject - }[options.language](options) + return _IMPL[options.language](options) diff --git a/mesonbuild/templates/sampleimpl.py b/mesonbuild/templates/sampleimpl.py index 4d586b1fe1e4..0d31aa447de9 100644 --- a/mesonbuild/templates/sampleimpl.py +++ b/mesonbuild/templates/sampleimpl.py @@ -13,20 +13,92 @@ # limitations under the License. from __future__ import annotations +import abc +import re import typing as T if T.TYPE_CHECKING: from ..minit import Arguments -class SampleImpl: +class SampleImpl(metaclass=abc.ABCMeta): def __init__(self, args: Arguments): self.name = args.name self.version = args.version + @abc.abstractmethod def create_executable(self) -> None: - raise NotImplementedError('Sample implementation for "executable" not implemented!') + pass + @abc.abstractmethod def create_library(self) -> None: - raise NotImplementedError('Sample implementation for "library" not implemented!') + pass + + +class ClassImpl(SampleImpl): + + """For Class based languages, like Java and C#""" + + def __init__(self, args: Arguments): + super().__init__(args) + self.lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + self.uppercase_token = self.lowercase_token.upper() + self.capitalized_token = self.lowercase_token.capitalize() + + @abc.abstractproperty + def exe_template(self) -> str: + pass + + @abc.abstractproperty + def exe_meson_template(self) -> str: + pass + + @abc.abstractproperty + def lib_template(self) -> str: + pass + + @abc.abstractproperty + def lib_test_template(self) -> str: + pass + + @abc.abstractproperty + def lib_meson_template(self) -> str: + pass + + @abc.abstractproperty + def source_ext(self) -> str: + pass + + def create_executable(self) -> None: + source_name = f'{self.capitalized_token}.{self.source_ext}' + with open(source_name, 'w', encoding='utf-8') as f: + f.write(self.exe_template.format(project_name=self.name, + class_name=self.capitalized_token)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.exe_meson_template.format(project_name=self.name, + exe_name=self.name, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lib_name = f'{self.capitalized_token}.{self.source_ext}' + test_name = f'{self.capitalized_token}_test.{self.source_ext}' + kwargs = {'utoken': self.uppercase_token, + 'ltoken': self.lowercase_token, + 'class_test': f'{self.capitalized_token}_test', + 'class_name': self.capitalized_token, + 'source_file': lib_name, + 'test_source_file': test_name, + 'test_exe_name': f'{self.lowercase_token}_test', + 'project_name': self.name, + 'lib_name': self.lowercase_token, + 'test_name': self.lowercase_token, + 'version': self.version, + } + with open(lib_name, 'w', encoding='utf-8') as f: + f.write(self.lib_template.format(**kwargs)) + with open(test_name, 'w', encoding='utf-8') as f: + f.write(self.lib_test_template.format(**kwargs)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.lib_meson_template.format(**kwargs)) From 492d8e90ad0fca985c4c09e518157230efaa5618 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 30 Jun 2023 15:53:56 -0700 Subject: [PATCH 059/855] templates: use common classes for remaining languages These all break down into either a single file or a file + header. This means a little more customization per class, but not too much. --- mesonbuild/templates/cpptemplates.py | 53 +++----------- mesonbuild/templates/ctemplates.py | 51 +++----------- mesonbuild/templates/cudatemplates.py | 53 +++----------- mesonbuild/templates/dlangtemplates.py | 53 ++++---------- mesonbuild/templates/fortrantemplates.py | 46 +++---------- mesonbuild/templates/objcpptemplates.py | 51 +++----------- mesonbuild/templates/objctemplates.py | 51 +++----------- mesonbuild/templates/rusttemplates.py | 53 ++++---------- mesonbuild/templates/samplefactory.py | 4 +- mesonbuild/templates/sampleimpl.py | 88 +++++++++++++++++++++--- mesonbuild/templates/valatemplates.py | 48 +++---------- 11 files changed, 182 insertions(+), 369 deletions(-) diff --git a/mesonbuild/templates/cpptemplates.py b/mesonbuild/templates/cpptemplates.py index 75a5ee2568bb..d3d29d3cbc59 100644 --- a/mesonbuild/templates/cpptemplates.py +++ b/mesonbuild/templates/cpptemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileHeaderImpl hello_cpp_template = '''#include @@ -143,42 +141,13 @@ class {utoken}_PUBLIC {class_name} {{ ''' -class CppProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.cpp' - open(source_name, 'w', encoding='utf-8').write(hello_cpp_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_cpp_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - test_exe_name = lowercase_token + '_test' - namespace = lowercase_token - lib_hpp_name = lowercase_token + '.hpp' - lib_cpp_name = lowercase_token + '.cpp' - test_cpp_name = lowercase_token + '_test.cpp' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'class_name': class_name, - 'namespace': namespace, - 'header_file': lib_hpp_name, - 'source_file': lib_cpp_name, - 'test_source_file': test_cpp_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_hpp_name, 'w', encoding='utf-8').write(lib_hpp_template.format(**kwargs)) - open(lib_cpp_name, 'w', encoding='utf-8').write(lib_cpp_template.format(**kwargs)) - open(test_cpp_name, 'w', encoding='utf-8').write(lib_cpp_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_cpp_meson_template.format(**kwargs)) +class CppProject(FileHeaderImpl): + + source_ext = 'cpp' + header_ext = 'hpp' + exe_template = hello_cpp_template + exe_meson_template = hello_cpp_meson_template + lib_template = lib_cpp_template + lib_header_template = lib_hpp_template + lib_test_template = lib_cpp_test_template + lib_meson_template = lib_cpp_meson_template diff --git a/mesonbuild/templates/ctemplates.py b/mesonbuild/templates/ctemplates.py index 16e6c44478c8..14eeaf789b7c 100644 --- a/mesonbuild/templates/ctemplates.py +++ b/mesonbuild/templates/ctemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileHeaderImpl lib_h_template = '''#pragma once @@ -126,40 +124,13 @@ ''' -class CProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.c' - open(source_name, 'w', encoding='utf-8').write(hello_c_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_c_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_h_name = lowercase_token + '.h' - lib_c_name = lowercase_token + '.c' - test_c_name = lowercase_token + '_test.c' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'header_file': lib_h_name, - 'source_file': lib_c_name, - 'test_source_file': test_c_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) - open(lib_c_name, 'w', encoding='utf-8').write(lib_c_template.format(**kwargs)) - open(test_c_name, 'w', encoding='utf-8').write(lib_c_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_c_meson_template.format(**kwargs)) +class CProject(FileHeaderImpl): + + source_ext = 'c' + header_ext = 'h' + exe_template = hello_c_template + exe_meson_template = hello_c_meson_template + lib_template = lib_c_template + lib_header_template = lib_h_template + lib_test_template = lib_c_test_template + lib_meson_template = lib_c_meson_template diff --git a/mesonbuild/templates/cudatemplates.py b/mesonbuild/templates/cudatemplates.py index ce775040caec..f59d79aeb632 100644 --- a/mesonbuild/templates/cudatemplates.py +++ b/mesonbuild/templates/cudatemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileHeaderImpl hello_cuda_template = '''#include @@ -143,42 +141,13 @@ class {utoken}_PUBLIC {class_name} {{ ''' -class CudaProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.cu' - open(source_name, 'w', encoding='utf-8').write(hello_cuda_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_cuda_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - test_exe_name = lowercase_token + '_test' - namespace = lowercase_token - lib_h_name = lowercase_token + '.h' - lib_cuda_name = lowercase_token + '.cu' - test_cuda_name = lowercase_token + '_test.cu' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'class_name': class_name, - 'namespace': namespace, - 'header_file': lib_h_name, - 'source_file': lib_cuda_name, - 'test_source_file': test_cuda_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) - open(lib_cuda_name, 'w', encoding='utf-8').write(lib_cuda_template.format(**kwargs)) - open(test_cuda_name, 'w', encoding='utf-8').write(lib_cuda_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_cuda_meson_template.format(**kwargs)) +class CudaProject(FileHeaderImpl): + + source_ext = 'cu' + header_ext = 'h' + exe_template = hello_cuda_template + exe_meson_template = hello_cuda_meson_template + lib_template = lib_cuda_template + lib_header_template = lib_h_template + lib_test_template = lib_cuda_test_template + lib_meson_template = lib_cuda_meson_template diff --git a/mesonbuild/templates/dlangtemplates.py b/mesonbuild/templates/dlangtemplates.py index d5adf926914a..6a8a0710cda5 100644 --- a/mesonbuild/templates/dlangtemplates.py +++ b/mesonbuild/templates/dlangtemplates.py @@ -13,9 +13,9 @@ # limitations under the License. from __future__ import annotations -import re +from mesonbuild.templates.sampleimpl import FileImpl -from mesonbuild.templates.sampleimpl import SampleImpl +import typing as T hello_d_template = '''module main; @@ -104,39 +104,16 @@ ''' -class DlangProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.d' - open(source_name, 'w', encoding='utf-8').write(hello_d_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_d_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_m_name = lowercase_token - lib_d_name = lowercase_token + '.d' - test_d_name = lowercase_token + '_test.d' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'module_file': lib_m_name, - 'source_file': lib_d_name, - 'test_source_file': test_d_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_d_name, 'w', encoding='utf-8').write(lib_d_template.format(**kwargs)) - open(test_d_name, 'w', encoding='utf-8').write(lib_d_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_d_meson_template.format(**kwargs)) +class DlangProject(FileImpl): + + source_ext = 'd' + exe_template = hello_d_template + exe_meson_template = hello_d_meson_template + lib_template = lib_d_template + lib_test_template = lib_d_test_template + lib_meson_template = lib_d_meson_template + + def lib_kwargs(self) -> T.Dict[str, str]: + kwargs = super().lib_kwargs() + kwargs['module_file'] = self.lowercase_token + return kwargs diff --git a/mesonbuild/templates/fortrantemplates.py b/mesonbuild/templates/fortrantemplates.py index 6c21cad68396..8895e321e64b 100644 --- a/mesonbuild/templates/fortrantemplates.py +++ b/mesonbuild/templates/fortrantemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileImpl lib_fortran_template = ''' ! This procedure will not be exported and is not @@ -103,37 +101,11 @@ ''' -class FortranProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.f90' - open(source_name, 'w', encoding='utf-8').write(hello_fortran_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_fortran_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_fortran_name = lowercase_token + '.f90' - test_fortran_name = lowercase_token + '_test.f90' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'source_file': lib_fortran_name, - 'test_source_file': test_fortran_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_fortran_name, 'w', encoding='utf-8').write(lib_fortran_template.format(**kwargs)) - open(test_fortran_name, 'w', encoding='utf-8').write(lib_fortran_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_fortran_meson_template.format(**kwargs)) +class FortranProject(FileImpl): + + source_ext = 'f90' + exe_template = hello_fortran_template + exe_meson_template = hello_fortran_meson_template + lib_template = lib_fortran_template + lib_meson_template = lib_fortran_meson_template + lib_test_template = lib_fortran_test_template diff --git a/mesonbuild/templates/objcpptemplates.py b/mesonbuild/templates/objcpptemplates.py index 4ec785c185e8..a1021656c9c6 100644 --- a/mesonbuild/templates/objcpptemplates.py +++ b/mesonbuild/templates/objcpptemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileHeaderImpl lib_h_template = '''#pragma once @@ -126,40 +124,13 @@ ''' -class ObjCppProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.mm' - open(source_name, 'w', encoding='utf-8').write(hello_objcpp_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_objcpp_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_h_name = lowercase_token + '.h' - lib_objcpp_name = lowercase_token + '.mm' - test_objcpp_name = lowercase_token + '_test.mm' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'header_file': lib_h_name, - 'source_file': lib_objcpp_name, - 'test_source_file': test_objcpp_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) - open(lib_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_template.format(**kwargs)) - open(test_objcpp_name, 'w', encoding='utf-8').write(lib_objcpp_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_objcpp_meson_template.format(**kwargs)) +class ObjCppProject(FileHeaderImpl): + + source_ext = 'mm' + header_ext = 'h' + exe_template = hello_objcpp_template + exe_meson_template = hello_objcpp_meson_template + lib_template = lib_objcpp_template + lib_header_template = lib_h_template + lib_test_template = lib_objcpp_test_template + lib_meson_template = lib_objcpp_meson_template diff --git a/mesonbuild/templates/objctemplates.py b/mesonbuild/templates/objctemplates.py index 331b76cc0f87..4e31beb8d26f 100644 --- a/mesonbuild/templates/objctemplates.py +++ b/mesonbuild/templates/objctemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileHeaderImpl lib_h_template = '''#pragma once @@ -126,40 +124,13 @@ ''' -class ObjCProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.m' - open(source_name, 'w', encoding='utf-8').write(hello_objc_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_objc_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_h_name = lowercase_token + '.h' - lib_objc_name = lowercase_token + '.m' - test_objc_name = lowercase_token + '_test.m' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'header_file': lib_h_name, - 'source_file': lib_objc_name, - 'test_source_file': test_objc_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_h_name, 'w', encoding='utf-8').write(lib_h_template.format(**kwargs)) - open(lib_objc_name, 'w', encoding='utf-8').write(lib_objc_template.format(**kwargs)) - open(test_objc_name, 'w', encoding='utf-8').write(lib_objc_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_objc_meson_template.format(**kwargs)) +class ObjCProject(FileHeaderImpl): + + source_ext = 'm' + header_ext = 'h' + exe_template = hello_objc_template + exe_meson_template = hello_objc_meson_template + lib_template = lib_objc_template + lib_header_template = lib_h_template + lib_test_template = lib_objc_test_template + lib_meson_template = lib_objc_meson_template diff --git a/mesonbuild/templates/rusttemplates.py b/mesonbuild/templates/rusttemplates.py index 840835987e34..26548b837483 100644 --- a/mesonbuild/templates/rusttemplates.py +++ b/mesonbuild/templates/rusttemplates.py @@ -13,9 +13,9 @@ # limitations under the License. from __future__ import annotations -import re +import typing as T -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileImpl lib_rust_template = '''#![crate_name = "{crate_file}"] @@ -74,39 +74,16 @@ ''' -class RustProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.rs' - open(source_name, 'w', encoding='utf-8').write(hello_rust_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_rust_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - function_name = lowercase_token[0:3] + '_func' - test_exe_name = lowercase_token + '_test' - lib_crate_name = lowercase_token - lib_rs_name = lowercase_token + '.rs' - test_rs_name = lowercase_token + '_test.rs' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'function_name': function_name, - 'crate_file': lib_crate_name, - 'source_file': lib_rs_name, - 'test_source_file': test_rs_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_rs_name, 'w', encoding='utf-8').write(lib_rust_template.format(**kwargs)) - open(test_rs_name, 'w', encoding='utf-8').write(lib_rust_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_rust_meson_template.format(**kwargs)) +class RustProject(FileImpl): + + source_ext = 'rs' + exe_template = hello_rust_template + exe_meson_template = hello_rust_meson_template + lib_template = lib_rust_template + lib_test_template = lib_rust_test_template + lib_meson_template = lib_rust_meson_template + + def lib_kwargs(self) -> T.Dict[str, str]: + kwargs = super().lib_kwargs() + kwargs['crate_file'] = self.lowercase_token + return kwargs diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index e3c855103430..8e200e200572 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -29,10 +29,10 @@ if T.TYPE_CHECKING: from ..minit import Arguments - from .sampleimpl import ClassImpl, SampleImpl + from .sampleimpl import ClassImpl, FileHeaderImpl, FileImpl, SampleImpl -_IMPL: T.Mapping[str, T.Union[T.Type[ClassImpl], T.Type[SampleImpl]]] = { +_IMPL: T.Mapping[str, T.Union[T.Type[ClassImpl], T.Type[FileHeaderImpl], T.Type[FileImpl]]] = { 'c': CProject, 'cpp': CppProject, 'cs': CSharpProject, diff --git a/mesonbuild/templates/sampleimpl.py b/mesonbuild/templates/sampleimpl.py index 0d31aa447de9..e34cad7718af 100644 --- a/mesonbuild/templates/sampleimpl.py +++ b/mesonbuild/templates/sampleimpl.py @@ -26,6 +26,9 @@ class SampleImpl(metaclass=abc.ABCMeta): def __init__(self, args: Arguments): self.name = args.name self.version = args.version + self.lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + self.uppercase_token = self.lowercase_token.upper() + self.capitalized_token = self.lowercase_token.capitalize() @abc.abstractmethod def create_executable(self) -> None: @@ -35,17 +38,6 @@ def create_executable(self) -> None: def create_library(self) -> None: pass - -class ClassImpl(SampleImpl): - - """For Class based languages, like Java and C#""" - - def __init__(self, args: Arguments): - super().__init__(args) - self.lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - self.uppercase_token = self.lowercase_token.upper() - self.capitalized_token = self.lowercase_token.capitalize() - @abc.abstractproperty def exe_template(self) -> str: pass @@ -70,6 +62,11 @@ def lib_meson_template(self) -> str: def source_ext(self) -> str: pass + +class ClassImpl(SampleImpl): + + """For Class based languages, like Java and C#""" + def create_executable(self) -> None: source_name = f'{self.capitalized_token}.{self.source_ext}' with open(source_name, 'w', encoding='utf-8') as f: @@ -102,3 +99,72 @@ def create_library(self) -> None: f.write(self.lib_test_template.format(**kwargs)) with open('meson.build', 'w', encoding='utf-8') as f: f.write(self.lib_meson_template.format(**kwargs)) + + +class FileImpl(SampleImpl): + + """File based languages without headers""" + + def create_executable(self) -> None: + source_name = f'{self.lowercase_token}.{self.source_ext}' + with open(source_name, 'w', encoding='utf-8') as f: + f.write(self.exe_template.format(project_name=self.name)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.exe_meson_template.format(project_name=self.name, + exe_name=self.name, + source_name=source_name, + version=self.version)) + + def lib_kwargs(self) -> T.Dict[str, str]: + """Get Language specific keyword arguments + + :return: A dictionary of key: values to fill in the templates + """ + return { + 'utoken': self.uppercase_token, + 'ltoken': self.lowercase_token, + 'header_dir': self.lowercase_token, + 'class_name': self.capitalized_token, + 'function_name': f'{self.lowercase_token[0:3]}_func', + 'namespace': self.lowercase_token, + 'source_file': f'{self.lowercase_token}.{self.source_ext}', + 'test_source_file': f'{self.lowercase_token}_test.{self.source_ext}', + 'test_exe_name': f'{self.lowercase_token}_test', + 'project_name': self.name, + 'lib_name': self.lowercase_token, + 'test_name': self.lowercase_token, + 'version': self.version, + } + + def create_library(self) -> None: + lib_name = f'{self.lowercase_token}.{self.source_ext}' + test_name = f'{self.lowercase_token}_test.{self.source_ext}' + kwargs = self.lib_kwargs() + with open(lib_name, 'w', encoding='utf-8') as f: + f.write(self.lib_template.format(**kwargs)) + with open(test_name, 'w', encoding='utf-8') as f: + f.write(self.lib_test_template.format(**kwargs)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.lib_meson_template.format(**kwargs)) + + +class FileHeaderImpl(FileImpl): + + @abc.abstractproperty + def header_ext(self) -> str: + pass + + @abc.abstractproperty + def lib_header_template(self) -> str: + pass + + def lib_kwargs(self) -> T.Dict[str, str]: + kwargs = super().lib_kwargs() + kwargs['header_file'] = f'{self.lowercase_token}.{self.header_ext}' + return kwargs + + def create_library(self) -> None: + super().create_library() + kwargs = self.lib_kwargs() + with open(kwargs['header_file'], 'w', encoding='utf-8') as f: + f.write(self.lib_header_template.format_map(kwargs)) diff --git a/mesonbuild/templates/valatemplates.py b/mesonbuild/templates/valatemplates.py index b6a461417809..aa82de73fbd8 100644 --- a/mesonbuild/templates/valatemplates.py +++ b/mesonbuild/templates/valatemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import FileImpl hello_vala_template = '''void main (string[] args) {{ @@ -84,39 +82,11 @@ ''' -class ValaProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - source_name = lowercase_token + '.vala' - open(source_name, 'w', encoding='utf-8').write(hello_vala_template.format(project_name=self.name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_vala_meson_template.format(project_name=self.name, - exe_name=lowercase_token, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - test_exe_name = lowercase_token + '_test' - namespace = lowercase_token - lib_vala_name = lowercase_token + '.vala' - test_vala_name = lowercase_token + '_test.vala' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'header_dir': lowercase_token, - 'class_name': class_name, - 'namespace': namespace, - 'source_file': lib_vala_name, - 'test_source_file': test_vala_name, - 'test_exe_name': test_exe_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_vala_name, 'w', encoding='utf-8').write(lib_vala_template.format(**kwargs)) - open(test_vala_name, 'w', encoding='utf-8').write(lib_vala_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_vala_meson_template.format(**kwargs)) +class ValaProject(FileImpl): + + source_ext = 'vala' + exe_template = hello_vala_template + exe_meson_template = hello_vala_meson_template + lib_template = lib_vala_template + lib_test_template = lib_vala_test_template + lib_meson_template = lib_vala_meson_template From a0f165b2fa57653a44c97398c00c453ec28e6dcc Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 15 Jul 2023 22:46:41 +0200 Subject: [PATCH 060/855] interpreter: Remove redundant comment The function name adheres to the pattern used by many other Meson DSL implementation methods, thus stating that this is the implementation of the functionality without argument validation is not very useful. The docstring is separated from the function declaration by a blank line. Removing the docstring avoids having to decide if the blank line should be there or not. --- mesonbuild/interpreter/interpreter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 67203bdc4c1b..d891fa6578ee 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2477,7 +2477,6 @@ def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optio install_data_type: T.Optional[str] = None, preserve_path: bool = False) -> build.Data: - """Just the implementation with no validation.""" idir = install_dir or '' idir_name = install_dir_name or idir or '{datadir}' if isinstance(idir_name, P_OBJ.OptionString): From 9eb7fe332f6a6a8babd040b76ad2a6808faf0423 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Mon, 26 Jun 2023 16:24:53 +0200 Subject: [PATCH 061/855] Fix install_data() default install path This fixes two issues in constructing the default installation path when install_dir is not specified: - inside a subproject, install_data() would construct the destination path using the parent project name instead than the current project name, - when specifying preserve_path, install_data() would construct the destination path omitting the project name. Fixes #11910. --- docs/yaml/functions/install_data.yaml | 2 ++ mesonbuild/backend/backends.py | 3 -- mesonbuild/interpreter/interpreter.py | 28 ++++++++++++------- mesonbuild/modules/python.py | 1 - test cases/common/12 data/meson.build | 4 +++ test cases/common/12 data/subdir/data.txt | 0 .../12 data/subprojects/moredata/data.txt | 1 + .../12 data/subprojects/moredata/meson.build | 3 ++ test cases/common/12 data/test.json | 4 ++- unittests/allplatformstests.py | 13 +++++---- 10 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 test cases/common/12 data/subdir/data.txt create mode 100644 test cases/common/12 data/subprojects/moredata/data.txt create mode 100644 test cases/common/12 data/subprojects/moredata/meson.build diff --git a/docs/yaml/functions/install_data.yaml b/docs/yaml/functions/install_data.yaml index b0834791e907..5ecc318a9bbf 100644 --- a/docs/yaml/functions/install_data.yaml +++ b/docs/yaml/functions/install_data.yaml @@ -12,6 +12,8 @@ varargs: warnings: - the `install_mode` kwarg ignored integer values between 0.59.0 -- 1.1.0. + - an omitted `install_dir` kwarg did not work correctly inside of a subproject until 1.3.0. + - an omitted `install_dir` kwarg did not work correctly when combined with the `preserve_path` kwarg untill 1.3.0. kwargs: install_dir: diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index e18906ccab2a..3e6d65210ff9 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1866,9 +1866,6 @@ def generate_data_install(self, d: InstallData) -> None: assert isinstance(de, build.Data) subdir = de.install_dir subdir_name = de.install_dir_name - if not subdir: - subdir = os.path.join(self.environment.get_datadir(), self.interpreter.build.project_name) - subdir_name = os.path.join('{datadir}', self.interpreter.build.project_name) for src_file, dst_name in zip(de.sources, de.rename): assert isinstance(src_file, mesonlib.File) dst_abs = os.path.join(subdir, dst_name) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d891fa6578ee..dc2431267f1a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2465,24 +2465,31 @@ def func_install_data(self, node: mparser.BaseNode, '"rename" and "sources" argument lists must be the same length if "rename" is given. ' f'Rename has {len(rename)} elements and sources has {len(sources)}.') + install_dir = kwargs['install_dir'] + if not install_dir: + subdir = self.active_projectname + install_dir = P_OBJ.OptionString(os.path.join(self.environment.get_datadir(), subdir), os.path.join('{datadir}', subdir)) + if self.is_subproject(): + FeatureNew.single_use('install_data() without install_dir inside of a subproject', '1.3.0', self.subproject, + 'This was broken and would install to the project name of the parent project instead', + node) + if kwargs['preserve_path']: + FeatureNew.single_use('install_data() with preserve_path and without install_dir', '1.3.0', self.subproject, + 'This was broken and would not add the project name to the install path', + node) + install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) - return self.install_data_impl(sources, kwargs['install_dir'], install_mode, - rename, kwargs['install_tag'], + return self.install_data_impl(sources, install_dir, install_mode, rename, kwargs['install_tag'], preserve_path=kwargs['preserve_path']) - def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optional[str], + def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str, install_mode: FileMode, rename: T.Optional[str], tag: T.Optional[str], - install_dir_name: T.Optional[str] = None, install_data_type: T.Optional[str] = None, preserve_path: bool = False) -> build.Data: + install_dir_name = install_dir.optname if isinstance(install_dir, P_OBJ.OptionString) else install_dir - idir = install_dir or '' - idir_name = install_dir_name or idir or '{datadir}' - if isinstance(idir_name, P_OBJ.OptionString): - idir_name = idir_name.optname dirs = collections.defaultdict(list) - ret_data = [] if preserve_path: for file in sources: dirname = os.path.dirname(file.fname) @@ -2490,8 +2497,9 @@ def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optio else: dirs[''].extend(sources) + ret_data = [] for childdir, files in dirs.items(): - d = build.Data(files, os.path.join(idir, childdir), os.path.join(idir_name, childdir), + d = build.Data(files, os.path.join(install_dir, childdir), os.path.join(install_dir_name, childdir), install_mode, self.subproject, rename, tag, install_data_type) ret_data.append(d) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index f6c82e0d6f64..75b291f02d77 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -224,7 +224,6 @@ def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File self.interpreter.source_strings_to_files(args[0]), install_dir, mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python', - install_dir_name=install_dir.optname, preserve_path=kwargs['preserve_path']) @noPosargs diff --git a/test cases/common/12 data/meson.build b/test cases/common/12 data/meson.build index d318633b30c7..aa021317831e 100644 --- a/test cases/common/12 data/meson.build +++ b/test cases/common/12 data/meson.build @@ -22,3 +22,7 @@ install_data(sources : ['vanishing/to_be_renamed_2.txt', 'to_be_renamed_3.txt'], install_dir : 'share/renamed', rename : ['renamed 2.txt', 'renamed 3.txt']) install_data(sources : 'to_be_renamed_4.txt', rename : 'some/nested/path.txt') + +install_data('subdir/data.txt', preserve_path : true) + +subproject('moredata') diff --git a/test cases/common/12 data/subdir/data.txt b/test cases/common/12 data/subdir/data.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/common/12 data/subprojects/moredata/data.txt b/test cases/common/12 data/subprojects/moredata/data.txt new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/test cases/common/12 data/subprojects/moredata/data.txt @@ -0,0 +1 @@ + diff --git a/test cases/common/12 data/subprojects/moredata/meson.build b/test cases/common/12 data/subprojects/moredata/meson.build new file mode 100644 index 000000000000..6234e261ce53 --- /dev/null +++ b/test cases/common/12 data/subprojects/moredata/meson.build @@ -0,0 +1,3 @@ +project('moredata') + +install_data('data.txt') diff --git a/test cases/common/12 data/test.json b/test cases/common/12 data/test.json index f392e9a03abb..c5fef010c055 100644 --- a/test cases/common/12 data/test.json +++ b/test cases/common/12 data/test.json @@ -10,6 +10,8 @@ {"type": "file", "file": "usr/share/renamed/renamed 2.txt"}, {"type": "file", "file": "usr/share/renamed/renamed 3.txt"}, {"type": "file", "file": "etc/etcfile.dat"}, - {"type": "file", "file": "usr/bin/runscript.sh"} + {"type": "file", "file": "usr/bin/runscript.sh"}, + {"type": "file", "file": "usr/share/moredata/data.txt"}, + {"type": "file", "file": "usr/share/data install test/subdir/data.txt"} ] } diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index baf5875fc4e2..5a6e88b1f3c3 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -4130,7 +4130,8 @@ def test_install_skip_subprojects(self): ] bar_expected = [ 'bar', - 'share/foo/bar.dat', + 'share/bar', + 'share/bar/bar.dat', 'include/bar.h', 'bin/bar' + exe_suffix, 'bar/barfile' @@ -4410,9 +4411,9 @@ def exe_name(name): Path(installpath, 'usr/share/foo2.h'), Path(installpath, 'usr/share/out1.txt'), Path(installpath, 'usr/share/out2.txt'), - Path(installpath, 'usr/share/install tag'), - Path(installpath, 'usr/share/install tag/aaa.txt'), - Path(installpath, 'usr/share/install tag/bbb.txt'), + Path(installpath, 'usr/share/subproject'), + Path(installpath, 'usr/share/subproject/aaa.txt'), + Path(installpath, 'usr/share/subproject/bbb.txt'), } def do_install(tags, expected_files, expected_scripts): @@ -4613,12 +4614,12 @@ def output_name(name, type_): 'subproject': None, }, f'{testdir}/subprojects/subproject/aaa.txt': { - 'destination': '{datadir}/install tag/aaa.txt', + 'destination': '{datadir}/subproject/aaa.txt', 'tag': None, 'subproject': 'subproject', }, f'{testdir}/subprojects/subproject/bbb.txt': { - 'destination': '{datadir}/install tag/bbb.txt', + 'destination': '{datadir}/subproject/bbb.txt', 'tag': 'data', 'subproject': 'subproject', }, From 1b8dcbcc5782a7809d23d5bff1baeb5fee74068e Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 28 Jul 2023 12:11:42 -0400 Subject: [PATCH 062/855] docs: clarify what str.split does The wording was a bit confusing and misled at least one person into thinking it behaved like `str.replace('c', '')` operating on the entire line. Tweak the wording to be more precise and avoid this confusion. --- docs/markdown/Syntax.md | 4 ++-- docs/yaml/elementary/str.yml | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index f63125e42c4b..9958db5429eb 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -252,13 +252,13 @@ s = s.replace('as', 'are') #### .strip() ```meson -# Similar to the Python str.strip(). Removes leading/ending spaces and newlines +# Similar to the Python str.strip(). Removes leading/ending spaces and newlines. define = ' -Dsomedefine ' stripped_define = define.strip() # 'stripped_define' now has the value '-Dsomedefine' # You may also pass a string to strip, which specifies the set of characters to -# be removed. +# be removed instead of the default whitespace. string = 'xyxHelloxyx'.strip('xy') # 'string' now has the value 'Hello' ``` diff --git a/docs/yaml/elementary/str.yml b/docs/yaml/elementary/str.yml index dca6382a2fe5..7c48c5d23806 100644 --- a/docs/yaml/elementary/str.yml +++ b/docs/yaml/elementary/str.yml @@ -61,7 +61,10 @@ methods: # str.strip() - name: strip - description: Removes leading/ending spaces and newlines from the string. + description: | + Removes leading/ending characters from the string. + + By default the characters to remove are spaces and newlines. returns: str example: | ```meson @@ -75,7 +78,8 @@ methods: strip_chars: type: str since: 0.43.0 - description: All characters in this string will be stripped. + description: + description: Instead of whitespace, strip all the characters in this string. # str.to_lower() - name: to_lower From 01902d722731ea4ede3ac2732b892a0b113b055e Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 28 Jul 2023 12:17:47 -0400 Subject: [PATCH 063/855] ugh, fix typo in previous commit --- docs/yaml/elementary/str.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/yaml/elementary/str.yml b/docs/yaml/elementary/str.yml index 7c48c5d23806..774812100ffa 100644 --- a/docs/yaml/elementary/str.yml +++ b/docs/yaml/elementary/str.yml @@ -78,7 +78,6 @@ methods: strip_chars: type: str since: 0.43.0 - description: description: Instead of whitespace, strip all the characters in this string. # str.to_lower() From a8cba0768700916c4fc73aaa9b003cc9f1c713df Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 09:37:59 -0700 Subject: [PATCH 064/855] modules/python: use the SHARED_MOD_KWS for extension method --- mesonbuild/modules/python.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 75b291f02d77..3ac4c87e0e4b 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -26,7 +26,7 @@ from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs from ..interpreter import primitives as P_OBJ -from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW +from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW, SHARED_MOD_KWS from ..interpreterbase import ( noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo, @@ -42,7 +42,7 @@ from ..build import Build, SharedModule, Data from ..dependencies import Dependency from ..interpreter import Interpreter - from ..interpreter.kwargs import ExtractRequired + from ..interpreter.kwargs import ExtractRequired, SharedModule as SharedModuleKw from ..interpreterbase.baseobjects import TYPE_var, TYPE_kwargs class PyInstallKw(TypedDict): @@ -57,11 +57,17 @@ class FindInstallationKw(ExtractRequired): modules: T.List[str] pure: T.Optional[bool] + class ExtensionModuleKw(SharedModuleKw): + + pass + mod_kwargs = {'subdir'} mod_kwargs.update(known_shmod_kwargs) mod_kwargs -= {'name_prefix', 'name_suffix'} +_MOD_KWARGS = [k for k in SHARED_MOD_KWS if k.name not in {'name_prefix', 'name_suffix'}] + class PythonExternalProgram(BasicPythonExternalProgram): @@ -138,7 +144,8 @@ def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): }) @permittedKwargs(mod_kwargs) - def extension_module_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'SharedModule': + @typed_kwargs('python.extension_module', *_MOD_KWARGS, allow_unknown=True) + def extension_module_method(self, args: T.List['TYPE_var'], kwargs: ExtensionModuleKw) -> 'SharedModule': if 'install_dir' in kwargs: if 'subdir' in kwargs: raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive') From 848614ababa9d10a3285029acf6635aeaad8567a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 09:41:53 -0700 Subject: [PATCH 065/855] modules/python: typed_kwargs for subdir We cannot re-use the existing KwargInfo, since we need to know if the keyword was set explicitly or not, since it conflicts with `install_dir` --- mesonbuild/modules/python.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 3ac4c87e0e4b..cec98948c3a1 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -36,7 +36,7 @@ from ..programs import ExternalProgram, NonExistingExternalProgram if T.TYPE_CHECKING: - from typing_extensions import TypedDict + from typing_extensions import TypedDict, NotRequired from . import ModuleState from ..build import Build, SharedModule, Data @@ -59,7 +59,7 @@ class FindInstallationKw(ExtractRequired): class ExtensionModuleKw(SharedModuleKw): - pass + subdir: NotRequired[T.Optional[str]] mod_kwargs = {'subdir'} @@ -111,7 +111,7 @@ def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None: _PURE_KW = KwargInfo('pure', (bool, NoneType)) _SUBDIR_KW = KwargInfo('subdir', str, default='') - +_DEFAULTABLE_SUBDIR_KW = KwargInfo('subdir', (str, NoneType)) class PythonInstallation(ExternalProgramHolder): def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): @@ -144,15 +144,16 @@ def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): }) @permittedKwargs(mod_kwargs) - @typed_kwargs('python.extension_module', *_MOD_KWARGS, allow_unknown=True) + @typed_kwargs('python.extension_module', *_MOD_KWARGS, _DEFAULTABLE_SUBDIR_KW, allow_unknown=True) def extension_module_method(self, args: T.List['TYPE_var'], kwargs: ExtensionModuleKw) -> 'SharedModule': if 'install_dir' in kwargs: - if 'subdir' in kwargs: + if kwargs['subdir'] is not None: raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive') else: - subdir = kwargs.pop('subdir', '') - if not isinstance(subdir, str): - raise InvalidArguments('"subdir" argument must be a string.') + # We want to remove 'subdir', but it may be None and we want to replace it with '' + # It must be done this way since we don't allow both `install_dir` + # and `subdir` to be set at the same time + subdir = kwargs.pop('subdir') or '' kwargs['install_dir'] = self._get_install_dir_impl(False, subdir) From fdbce211b2e34e753308499d3e065ffd6d856c83 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 09:46:55 -0700 Subject: [PATCH 066/855] modules/python: use typed_pos_args for extension_module --- mesonbuild/modules/python.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index cec98948c3a1..879c5487c729 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -20,7 +20,7 @@ from .. import mesonlib from .. import mlog from ..coredata import UserFeatureOption -from ..build import known_shmod_kwargs +from ..build import known_shmod_kwargs, CustomTarget, CustomTargetIndex, BuildTarget, GeneratedList, StructuredSources, ExtractedObjects, SharedModule from ..dependencies import NotFoundDependency from ..dependencies.detect import get_dep_identifier, find_external_dependency from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase @@ -39,9 +39,10 @@ from typing_extensions import TypedDict, NotRequired from . import ModuleState - from ..build import Build, SharedModule, Data + from ..build import Build, Data from ..dependencies import Dependency from ..interpreter import Interpreter + from ..interpreter.interpreter import BuildTargetSource from ..interpreter.kwargs import ExtractRequired, SharedModule as SharedModuleKw from ..interpreterbase.baseobjects import TYPE_var, TYPE_kwargs @@ -144,8 +145,9 @@ def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): }) @permittedKwargs(mod_kwargs) + @typed_pos_args('python.extension_module', str, varargs=(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget)) @typed_kwargs('python.extension_module', *_MOD_KWARGS, _DEFAULTABLE_SUBDIR_KW, allow_unknown=True) - def extension_module_method(self, args: T.List['TYPE_var'], kwargs: ExtensionModuleKw) -> 'SharedModule': + def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: ExtensionModuleKw) -> 'SharedModule': if 'install_dir' in kwargs: if kwargs['subdir'] is not None: raise InvalidArguments('"subdir" and "install_dir" are mutually exclusive') @@ -172,7 +174,7 @@ def extension_module_method(self, args: T.List['TYPE_var'], kwargs: ExtensionMod # msys2's python3 has "-cpython-36m.dll", we have to be clever # FIXME: explain what the specific cleverness is here split, suffix = self.suffix.rsplit('.', 1) - args[0] += split + args = (args[0] + split, args[1]) kwargs['name_prefix'] = '' kwargs['name_suffix'] = suffix @@ -181,7 +183,7 @@ def extension_module_method(self, args: T.List['TYPE_var'], kwargs: ExtensionMod (self.is_pypy or mesonlib.version_compare(self.version, '>=3.9')): kwargs['gnu_symbol_visibility'] = 'inlineshidden' - return self.interpreter.func_shared_module(None, args, kwargs) + return self.interpreter.build_target(self.current_node, args, kwargs, SharedModule) def _dependency_method_impl(self, kwargs: TYPE_kwargs) -> Dependency: for_machine = self.interpreter.machine_from_native_kwarg(kwargs) From 36301eaf8a043fe8cd862f86fd4e8e70e59d9f30 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 10:04:08 -0700 Subject: [PATCH 067/855] modules/python3: use typed_kwargs for extension_module Just like python, but for the python3 module --- mesonbuild/modules/python3.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index 065e8d7a2318..9d160980c6dd 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -14,13 +14,21 @@ from __future__ import annotations import sysconfig -from .. import mesonlib +import typing as T +from .. import mesonlib from . import ExtensionModule, ModuleInfo -from ..interpreterbase import typed_pos_args, noPosargs, noKwargs, permittedKwargs +from ..interpreter.type_checking import SHARED_MOD_KWS +from ..interpreterbase import typed_kwargs, typed_pos_args, noPosargs, noKwargs, permittedKwargs from ..build import known_shmod_kwargs from ..programs import ExternalProgram +if T.TYPE_CHECKING: + from ..interpreter.kwargs import SharedModule as SharedModuleKW + + +_MOD_KWARGS = [k for k in SHARED_MOD_KWS if k.name not in {'name_prefix', 'name_suffix'}] + class Python3Module(ExtensionModule): @@ -36,7 +44,8 @@ def __init__(self, *args, **kwargs): }) @permittedKwargs(known_shmod_kwargs) - def extension_module(self, state, args, kwargs): + @typed_kwargs('python3.extension_module', *_MOD_KWARGS, allow_unknown=True) + def extension_module(self, state, args, kwargs: SharedModuleKW): if 'name_prefix' in kwargs: raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.') if 'name_suffix' in kwargs: From 10a94d3e751ddff0121de41c17f16b4d24f8f3b3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 10:08:45 -0700 Subject: [PATCH 068/855] modules/python3: use typed_pos_args for extension_module --- mesonbuild/modules/python3.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index 9d160980c6dd..90ee9529f27f 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -17,13 +17,17 @@ import typing as T from .. import mesonlib -from . import ExtensionModule, ModuleInfo +from . import ExtensionModule, ModuleInfo, ModuleState +from ..build import ( + BuildTarget, CustomTarget, CustomTargetIndex, ExtractedObjects, + GeneratedList, SharedModule, StructuredSources, known_shmod_kwargs +) from ..interpreter.type_checking import SHARED_MOD_KWS from ..interpreterbase import typed_kwargs, typed_pos_args, noPosargs, noKwargs, permittedKwargs -from ..build import known_shmod_kwargs from ..programs import ExternalProgram if T.TYPE_CHECKING: + from ..interpreter.interpreter import BuildTargetSource from ..interpreter.kwargs import SharedModule as SharedModuleKW @@ -44,8 +48,9 @@ def __init__(self, *args, **kwargs): }) @permittedKwargs(known_shmod_kwargs) + @typed_pos_args('python3.extension_module', str, varargs=(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget)) @typed_kwargs('python3.extension_module', *_MOD_KWARGS, allow_unknown=True) - def extension_module(self, state, args, kwargs: SharedModuleKW): + def extension_module(self, state: ModuleState, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: SharedModuleKW): if 'name_prefix' in kwargs: raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.') if 'name_suffix' in kwargs: @@ -61,7 +66,7 @@ def extension_module(self, state, args, kwargs: SharedModuleKW): suffix = [] kwargs['name_prefix'] = '' kwargs['name_suffix'] = suffix - return self.interpreter.func_shared_module(None, args, kwargs) + return self.interpreter.build_target(state.current_node, args, kwargs, SharedModule) @noPosargs @noKwargs From d9870ed54b27f853d43b4aaaf4daec86e92bd20e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Jul 2023 11:25:58 -0700 Subject: [PATCH 069/855] modules/python3: exclude name_prefix and name_suffix We can remove these from `permittedKwargs` (like we've already done for `typed_kwargs`) and then remove the in body checks. --- mesonbuild/modules/python3.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index 90ee9529f27f..bc4d9af3ab90 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -47,14 +47,10 @@ def __init__(self, *args, **kwargs): 'sysconfig_path': self.sysconfig_path, }) - @permittedKwargs(known_shmod_kwargs) + @permittedKwargs(known_shmod_kwargs - {'name_prefix', 'name_suffix'}) @typed_pos_args('python3.extension_module', str, varargs=(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget)) @typed_kwargs('python3.extension_module', *_MOD_KWARGS, allow_unknown=True) def extension_module(self, state: ModuleState, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: SharedModuleKW): - if 'name_prefix' in kwargs: - raise mesonlib.MesonException('Name_prefix is set automatically, specifying it is forbidden.') - if 'name_suffix' in kwargs: - raise mesonlib.MesonException('Name_suffix is set automatically, specifying it is forbidden.') host_system = state.host_machine.system if host_system == 'darwin': # Default suffix is 'dylib' but Python does not use it for extensions. From 68dce66bf9a2bcb3d23c291beb2354225a74b954 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 28 Jul 2023 17:43:50 +0200 Subject: [PATCH 070/855] tests: skip a test that fails with new Python 3.11 from MSYS2 For some (atm unknown) reason mingw Python fails to load some modules when MSYS2 is removed from PATH, like in this test. Skip for now to make the test suite pass again. Once https://github.com/msys2-contrib/cpython-mingw/issues/141 is fixed this can be reverted. --- unittests/windowstests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unittests/windowstests.py b/unittests/windowstests.py index 37e92996d97a..c201953276cc 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -462,6 +462,9 @@ def test_non_utf8_fails(self): @unittest.skipIf(is_cygwin(), "Needs visual studio") def test_vsenv_option(self): + if mesonbuild.environment.detect_msys2_arch(): + # https://github.com/msys2-contrib/cpython-mingw/issues/141 + raise SkipTest('mingw python fails with /bin being removed from PATH') if self.backend is not Backend.ninja: raise SkipTest('Only ninja backend is valid for test') env = os.environ.copy() From 3752041c8d56c7667bc0fe644fda6c2834d6aaf8 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 29 Jul 2023 20:53:31 +0200 Subject: [PATCH 071/855] Revert "CI: add potential workaround for python crashes in MSYS2" This reverts commit e945f35cd72402d0d204ff10870e2a95c59b6192. With MSYS2 udpating to Python 3.11, this should no longer be needed. See https://github.com/msys2/MINGW-packages/issues/17415#issuecomment-1606085553 --- .github/workflows/msys2.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 8f1823d70633..2bdcdd30e6f4 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -51,9 +51,6 @@ jobs: TOOLCHAIN: clang env: MESON_CI_JOBNAME: msys2-${{ matrix.NAME }} - # XXX: For some reason enabling jit debugging "fixes" random python crashes - # see https://github.com/msys2/MINGW-packages/issues/11864 - MSYS: "winjitdebug" defaults: run: From 404312c6ddc44b1e8f09a95a5c889184a25a384b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 21 Jul 2023 01:00:44 -0400 Subject: [PATCH 072/855] do better sanity check for vs_module_defs input We allow custom_target() but check for it based on hasattr, ever since the initial implementation way back in the day, in commit 66a6ea984bc43d9ac144e22cf411c16e9f911bb3. This is a bit broken because various objects might support that but still aren't supposed to work. We can actually just use isintance checks like we do immediately above, which are more accurate and avoid crashes on things that aren't even targets at all, like run_target(). Although custom_target indexes are actually targets those didn't work either. Fixes #9648 --- mesonbuild/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index cfb3a5418f66..16bf4121fdab 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2383,7 +2383,7 @@ def process_kwargs(self, kwargs): elif isinstance(path, File): # When passing a generated file. self.vs_module_defs = path - elif hasattr(path, 'get_filename'): + elif isinstance(path, CustomTarget): # When passing output of a Custom Target self.vs_module_defs = File.from_built_file(path.subdir, path.get_filename()) else: From d4615369ffbfc0f9a769ca1fd3566056cfa5ef81 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 30 Jul 2023 20:28:59 -0400 Subject: [PATCH 073/855] fix lint errors revealed by pycodestyle 2.11 When performing isinstance checks, an identity comparison is automatically done, but we don't use isinstance here because we need strict identity equality *without allowing subtypes*. Comparing type() == type() is a value comparison, but could produce effectively the same results as an identity comparison, usually, despite being semantically off. pycodestyle learned to detect this and warn you to do strict identity comparison. --- mesonbuild/coredata.py | 2 +- mesonbuild/interpreterbase/baseobjects.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a6178f04dc26..54d9b1d02d72 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -807,7 +807,7 @@ def update_project_options(self, options: 'MutableKeyedOptionDictType') -> None: continue oldval = self.options[key] - if type(oldval) != type(value): + if type(oldval) is not type(value): self.options[key] = value elif oldval.choices != value.choices: # If the choices have changed, use the new value, but attempt diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py index d5b8c947624c..4966978a0c2b 100644 --- a/mesonbuild/interpreterbase/baseobjects.py +++ b/mesonbuild/interpreterbase/baseobjects.py @@ -119,12 +119,12 @@ def op_equals(self, other: TYPE_var) -> bool: # We use `type(...) == type(...)` here to enforce an *exact* match for comparison. We # don't want comparisons to be possible where `isinstance(derived_obj, type(base_obj))` # would pass because this comparison must never be true: `derived_obj == base_obj` - if type(self) != type(other): + if type(self) is not type(other): self._throw_comp_exception(other, '==') return self == other def op_not_equals(self, other: TYPE_var) -> bool: - if type(self) != type(other): + if type(self) is not type(other): self._throw_comp_exception(other, '!=') return self != other @@ -157,12 +157,12 @@ def display_name(self) -> str: # Override default comparison operators for the held object def op_equals(self, other: TYPE_var) -> bool: # See the comment from InterpreterObject why we are using `type()` here. - if type(self.held_object) != type(other): + if type(self.held_object) is not type(other): self._throw_comp_exception(other, '==') return self.held_object == other def op_not_equals(self, other: TYPE_var) -> bool: - if type(self.held_object) != type(other): + if type(self.held_object) is not type(other): self._throw_comp_exception(other, '!=') return self.held_object != other From 7c955618dd46c3ea7dc221bdf60354871f17f39d Mon Sep 17 00:00:00 2001 From: Dan Hawson <18214721+GertyP@users.noreply.github.com> Date: Sat, 29 Jul 2023 14:47:08 +0100 Subject: [PATCH 074/855] Rename variables that clash with pdb commands By default, pdb assumes that any command run is python code to be evaluated, but only if that code isn't a builtin pdb command. You can force it to be evaluated as python code by prefixing it with `!`. It's handy to simply name a python variable and have its variable be printed. But single letter variables like 's' and 'p' make debugging with pdb commands (i.e. 's'tep, and 'p'rint evaluated expressions) less convenient, and potentially confusing. --- unittests/allplatformstests.py | 4 ++-- unittests/baseplatformtests.py | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 5a6e88b1f3c3..12eafd59598f 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1369,8 +1369,8 @@ def test_lto_mode(self): targets = self.introspect('--targets') # This assumes all of the targets support lto for t in targets: - for s in t['target_sources']: - self.assertTrue(expected.issubset(set(s['parameters'])), f'Incorrect values for {t["name"]}') + for src in t['target_sources']: + self.assertTrue(expected.issubset(set(src['parameters'])), f'Incorrect values for {t["name"]}') def test_dist_git(self): if not shutil.which('git'): diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 4b16e7d8253b..3008eb731850 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -171,22 +171,22 @@ def _run(self, command, *, workdir=None, override_envvars: T.Optional[T.Mapping[ env = os.environ.copy() env.update(override_envvars) - p = subprocess.run(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT if stderr else subprocess.PIPE, - env=env, - encoding='utf-8', - text=True, cwd=workdir, timeout=60 * 5) + proc = subprocess.run(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if stderr else subprocess.PIPE, + env=env, + encoding='utf-8', + text=True, cwd=workdir, timeout=60 * 5) print('$', join_args(command)) print('stdout:') - print(p.stdout) + print(proc.stdout) if not stderr: print('stderr:') - print(p.stderr) - if p.returncode != 0: - if 'MESON_SKIP_TEST' in p.stdout: + print(proc.stderr) + if proc.returncode != 0: + if 'MESON_SKIP_TEST' in proc.stdout: raise SkipTest('Project requested skipping.') - raise subprocess.CalledProcessError(p.returncode, command, output=p.stdout) - return p.stdout + raise subprocess.CalledProcessError(proc.returncode, command, output=proc.stdout) + return proc.stdout def init(self, srcdir, *, extra_args=None, From b4c9269daba363f2326cb3d22cc3511ac08cb28b Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 31 Jul 2023 17:31:11 +0300 Subject: [PATCH 075/855] Upgrade MSI builder from WiX3 to WiX 4. --- packaging/createmsi.py | 98 +++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/packaging/createmsi.py b/packaging/createmsi.py index 4febc393dda6..6f198f3088b6 100755 --- a/packaging/createmsi.py +++ b/packaging/createmsi.py @@ -31,7 +31,7 @@ from mesonbuild import coredata # Elementtree does not support CDATA. So hack it. -WINVER_CHECK = ' 602)]]>' +WINVER_CHECK = 'Installed OR (VersionNT64 > 602)>' def gen_guid(): ''' @@ -102,7 +102,7 @@ def __init__(self): 'Title': 'Meson', 'Description': 'Meson executables', 'Level': '1', - 'Absent': 'disallow', + 'AllowAbsent': 'no', }, self.staging_dirs[1]: { 'Id': 'NinjaProgram', @@ -160,49 +160,44 @@ def generate_files(self): ''' Generate package files for MSI installer package ''' - self.root = ET.Element('Wix', {'xmlns': 'http://schemas.microsoft.com/wix/2006/wi'}) - product = ET.SubElement(self.root, 'Product', { + self.root = ET.Element('Wix', { + 'xmlns': 'http://wixtoolset.org/schemas/v4/wxs', + 'xmlns:ui': 'http://wixtoolset.org/schemas/v4/wxs/ui' + }) + + package = ET.SubElement(self.root, 'Package', { 'Name': self.product_name, 'Manufacturer': 'The Meson Development Team', - 'Id': self.guid, 'UpgradeCode': self.update_guid, 'Language': '1033', 'Codepage': '1252', 'Version': self.version, }) - package = ET.SubElement(product, 'Package', { - 'Id': '*', + ET.SubElement(package, 'SummaryInformation', { 'Keywords': 'Installer', 'Description': f'Meson {self.version} installer', - 'Comments': 'Meson is a high performance build system', 'Manufacturer': 'The Meson Development Team', - 'InstallerVersion': '500', - 'Languages': '1033', - 'Compressed': 'yes', - 'SummaryCodepage': '1252', }) - condition = ET.SubElement(product, 'Condition', {'Message': 'This application is only supported on Windows 10 or higher.'}) + ET.SubElement(package, + 'Launch', + {'Message': 'This application is only supported on Windows 10 or higher.', + 'Condition': 'X'*len(WINVER_CHECK)}) - condition.text = 'X'*len(WINVER_CHECK) - ET.SubElement(product, 'MajorUpgrade', - {'DowngradeErrorMessage': 'A newer version of Meson is already installed.'}) + ET.SubElement(package, 'MajorUpgrade', + {'DowngradeErrorMessage': + 'A newer version of Meson is already installed.'}) - package.set('Platform', 'x64') - ET.SubElement(product, 'Media', { + ET.SubElement(package, 'Media', { 'Id': '1', 'Cabinet': 'meson.cab', 'EmbedCab': 'yes', }) - targetdir = ET.SubElement(product, 'Directory', { - 'Id': 'TARGETDIR', - 'Name': 'SourceDir', + targetdir = ET.SubElement(package, 'StandardDirectory', { + 'Id': 'ProgramFiles64Folder', }) - progfiledir = ET.SubElement(targetdir, 'Directory', { - 'Id': self.progfile_dir, - }) - installdir = ET.SubElement(progfiledir, 'Directory', { + installdir = ET.SubElement(targetdir, 'Directory', { 'Id': 'INSTALLDIR', 'Name': 'Meson', }) @@ -213,16 +208,12 @@ def generate_files(self): 'Language': '0', }) - ET.SubElement(product, 'Property', { - 'Id': 'WIXUI_INSTALLDIR', - 'Value': 'INSTALLDIR', - }) - ET.SubElement(product, 'UIRef', { + ET.SubElement(package, 'ui:WixUI', { 'Id': 'WixUI_FeatureTree', }) for s_d in self.staging_dirs: assert os.path.isdir(s_d) - top_feature = ET.SubElement(product, 'Feature', { + top_feature = ET.SubElement(package, 'Feature', { 'Id': 'Complete', 'Title': 'Meson ' + self.version, 'Description': 'The complete package', @@ -277,10 +268,10 @@ def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir): component_id = f'ApplicationFiles{self.component_num}' comp_xml_node = ET.SubElement(parent_xml_node, 'Component', { 'Id': component_id, + 'Bitness': 'always64', 'Guid': gen_guid(), }) self.feature_components[staging_dir].append(component_id) - comp_xml_node.set('Win64', 'yes') if self.component_num == 0: ET.SubElement(comp_xml_node, 'Environment', { 'Id': 'Environment', @@ -311,23 +302,40 @@ def build_package(self): ''' Generate the Meson build MSI package. ''' - wixdir = 'c:\\Program Files\\Wix Toolset v3.11\\bin' - if not os.path.isdir(wixdir): - wixdir = 'c:\\Program Files (x86)\\Wix Toolset v3.11\\bin' - if not os.path.isdir(wixdir): - print("ERROR: This script requires WIX") - sys.exit(1) - subprocess.check_call([os.path.join(wixdir, 'candle'), self.main_xml]) - subprocess.check_call([os.path.join(wixdir, 'light'), - '-ext', 'WixUIExtension', - '-cultures:en-us', - '-dWixUILicenseRtf=packaging\\License.rtf', - '-out', self.final_output, - self.main_o]) + subprocess.check_call(['wix', + 'build', + '-bindvariable', 'WixUILicenseRtf=packaging\\License.rtf', + '-ext', 'WixToolset.UI.wixext', + '-culture', 'en-us', + '-arch', 'x64', + '-o', + self.final_output, + self.main_xml, + ]) + + +def install_wix(): + subprocess.check_call(['dotnet', + 'nuget', + 'add', + 'source', + 'https://api.nuget.org/v3/index.json']) + subprocess.check_call(['dotnet', + 'tool', + 'install', + '--global', + 'wix']) + subprocess.check_call(['wix', + 'extension', + 'add', + 'WixToolset.UI.wixext', + ]) if __name__ == '__main__': if not os.path.exists('meson.py'): sys.exit(print('Run me in the top level source dir.')) + if not shutil.which('wix'): + install_wix() subprocess.check_call(['pip', 'install', '--upgrade', 'pyinstaller']) p = PackageGenerator() From ce5f2982e46fac866034a45558a82c337279fd6a Mon Sep 17 00:00:00 2001 From: Alex Rao Date: Tue, 1 Aug 2023 15:00:45 -0400 Subject: [PATCH 076/855] Fix typo in Cross-compilation.md --- docs/markdown/Cross-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md index 1d0e46332b51..e1ad837173cd 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -338,7 +338,7 @@ scratch. ## Custom data You can store arbitrary data in `properties` and access them from your -Meson files. As an example if you cross file has this: +Meson files. As an example if your cross file has this: ```ini [properties] From 947e0f819b942951dfc251da37ef4ae83b3ea9b7 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 28 Jul 2023 10:03:58 -0400 Subject: [PATCH 077/855] Optimize extract_dll_paths in ninja backend On my project, this function was a bottleneck in setup time. By properly caching it, the cumtime for this function went from 26s to 4.3s when I profiled it. --- mesonbuild/backend/backends.py | 53 +++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 3e6d65210ff9..26819243257b 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1098,6 +1098,34 @@ def get_mingw_extra_paths(self, target: build.BuildTarget) -> T.List[str]: paths.update(cc.get_library_dirs(self.environment)) return list(paths) + @staticmethod + @lru_cache(maxsize=None) + def search_dll_path(link_arg: str) -> T.Optional[str]: + if link_arg.startswith(('-l', '-L')): + link_arg = link_arg[2:] + + p = Path(link_arg) + if not p.is_absolute(): + return None + + try: + p = p.resolve(strict=True) + except FileNotFoundError: + return None + + for f in p.parent.glob('*.dll'): + # path contains dlls + return str(p.parent) + + if p.is_file(): + p = p.parent + # Heuristic: replace *last* occurence of '/lib' + binpath = Path('/bin'.join(p.as_posix().rsplit('/lib', maxsplit=1))) + for _ in binpath.glob('*.dll'): + return str(binpath) + + return None + @classmethod @lru_cache(maxsize=None) def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: @@ -1116,32 +1144,9 @@ def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: bindir = dep.get_pkgconfig_variable('bindir', [], default='') if bindir: results.add(bindir) - - for link_arg in dep.link_args: - if link_arg.startswith(('-l', '-L')): - link_arg = link_arg[2:] - p = Path(link_arg) - if not p.is_absolute(): - continue - - try: - p = p.resolve(strict=True) - except FileNotFoundError: continue - for _ in p.parent.glob('*.dll'): - # path contains dlls - results.add(str(p.parent)) - break - - else: - if p.is_file(): - p = p.parent - # Heuristic: replace *last* occurence of '/lib' - binpath = Path('/bin'.join(p.as_posix().rsplit('/lib', maxsplit=1))) - for _ in binpath.glob('*.dll'): - results.add(str(binpath)) - break + results.update(filter(None, map(cls.search_dll_path, dep.link_args))) # pylint: disable=bad-builtin for i in chain(target.link_targets, target.link_whole_targets): if isinstance(i, build.BuildTarget): From 13f8eba9b63fe5185ba34c2690dffac651d91593 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 1 Aug 2023 14:23:57 -0400 Subject: [PATCH 078/855] treewide: internally avoid deprecated machine file uses of "pkgconfig" We support this in a machine file: ``` [binaries] pkgconfig = 'pkg-config' pkg-config = 'pkg-config' ``` and you can use either one, because internally we look up both. If you only set *one* of them, this plays awkwardly with setting $PKG_CONFIG, since we don't know which one you set in the machine file and the *other* one will be initialized from the environment instead. In commit 22df45a31981874310a78dde0df59a6a7c5ebb29 we changed program lookup of config-tool style dependencies to use the regular tool names and only fall back on the strange internal names. This affected the pkg-config class too. The result is that instead of preferring `pkgconfig =` followed by $PKG_CONFIG followed by `pkg-config =`, we inverted the lookup order. This is a good idea anyway, because now it behaves consistently with `find_program('pkg-config')`. Unfortunately, we documented the wrong name in a bunch of places, and also used the wrong name in various testsuite bits, which meant that if you set $PKG_CONFIG and then ran the testsuite, it would fail. Correct these references, because they are buggy. One test case expected to find_program() a native copy for convenience of testing against natively installed glib. Force it to resolve a native copy. --- cross/armclang-linux.txt | 2 +- cross/linux-mingw-w64-32bit.txt | 2 +- cross/linux-mingw-w64-64bit.txt | 2 +- cross/none.txt | 2 +- cross/ubuntu-armhf.txt | 2 +- docs/markdown/Machine-files.md | 6 +++--- mesonbuild/scripts/env2mfile.py | 2 +- test cases/common/44 pkgconfig-gen/meson.build | 2 +- .../ubuntu-armhf-overrides.txt | 2 +- test cases/unit/36 exe_wrapper behaviour/broken-cross.txt | 2 +- unittests/allplatformstests.py | 4 ++-- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cross/armclang-linux.txt b/cross/armclang-linux.txt index 863b355c345f..36927b882b5b 100644 --- a/cross/armclang-linux.txt +++ b/cross/armclang-linux.txt @@ -22,7 +22,7 @@ c = ['/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armclang', '--tar #cpp = '/usr/bin/arm-linux-gnueabihf-g++' ar = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armar' #strip = '/usr/arm-linux-gnueabihf/bin/strip' -#pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +#pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' [host_machine] system = 'baremetal' diff --git a/cross/linux-mingw-w64-32bit.txt b/cross/linux-mingw-w64-32bit.txt index caf1da1a045f..91ad9c5029a4 100644 --- a/cross/linux-mingw-w64-32bit.txt +++ b/cross/linux-mingw-w64-32bit.txt @@ -4,7 +4,7 @@ cpp = '/usr/bin/i686-w64-mingw32-g++' objc = '/usr/bin/i686-w64-mingw32-gcc' ar = '/usr/bin/i686-w64-mingw32-ar' strip = '/usr/bin/i686-w64-mingw32-strip' -pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config' +pkg-config = '/usr/bin/i686-w64-mingw32-pkg-config' windres = '/usr/bin/i686-w64-mingw32-windres' exe_wrapper = 'wine' ld = '/usr/bin/i686-w64-mingw32-ld' diff --git a/cross/linux-mingw-w64-64bit.txt b/cross/linux-mingw-w64-64bit.txt index 7403803b4c05..08fa70410430 100644 --- a/cross/linux-mingw-w64-64bit.txt +++ b/cross/linux-mingw-w64-64bit.txt @@ -4,7 +4,7 @@ cpp = '/usr/bin/x86_64-w64-mingw32-g++' objc = '/usr/bin/x86_64-w64-mingw32-gcc' ar = '/usr/bin/x86_64-w64-mingw32-ar' strip = '/usr/bin/x86_64-w64-mingw32-strip' -pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' +pkg-config = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' exe_wrapper = 'wine' cmake = '/usr/bin/cmake' diff --git a/cross/none.txt b/cross/none.txt index 1fbe4713ac09..9eadf974c321 100644 --- a/cross/none.txt +++ b/cross/none.txt @@ -15,5 +15,5 @@ fc = ['false'] objc = ['false'] objcpp = ['false'] ar = ['false'] -pkgconfig = ['false'] +pkg-config = ['false'] cmake = ['false'] diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt index 408c2ceaecba..6409e396b577 100644 --- a/cross/ubuntu-armhf.txt +++ b/cross/ubuntu-armhf.txt @@ -6,7 +6,7 @@ cpp = ['/usr/bin/arm-linux-gnueabihf-g++'] rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7'] ar = '/usr/arm-linux-gnueabihf/bin/ar' strip = '/usr/arm-linux-gnueabihf/bin/strip' -pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' [built-in options] diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index 9e4b0c2a5f4e..c30076919f5e 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -90,7 +90,7 @@ arch = 'aarch64-linux-gnu' c = arch + '-gcc' cpp = arch + '-g++' strip = arch + '-strip' -pkgconfig = arch + '-pkg-config' +pkg-config = arch + '-pkg-config' ... ``` @@ -165,7 +165,7 @@ c_ld = 'gold' cpp_ld = 'gold' ar = '/usr/i586-mingw32msvc/bin/ar' strip = '/usr/i586-mingw32msvc/bin/strip' -pkgconfig = '/usr/bin/i586-mingw32msvc-pkg-config' +pkg-config = '/usr/bin/i586-mingw32msvc-pkg-config' ``` An incomplete list of internally used programs that can be overridden @@ -179,7 +179,7 @@ here is: - libwmf-config - llvm-config - pcap-config -- pkgconfig +- pkg-config - sdl2-config - wx-config (or wx-3.0-config or wx-config-gtk) diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index 27a7dd969841..df93730424de 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -213,7 +213,7 @@ def detect_cross_debianlike(options: T.Any) -> MachineInfo: except ValueError: pass try: - infos.binaries['pkgconfig'] = locate_path("%s-pkg-config" % host_arch) + infos.binaries['pkg-config'] = locate_path("%s-pkg-config" % host_arch) except ValueError: pass # pkg-config is optional try: diff --git a/test cases/common/44 pkgconfig-gen/meson.build b/test cases/common/44 pkgconfig-gen/meson.build index adf3e2765e81..fd6371ef4b92 100644 --- a/test cases/common/44 pkgconfig-gen/meson.build +++ b/test cases/common/44 pkgconfig-gen/meson.build @@ -8,7 +8,7 @@ if not cc.find_library('z', required: false).found() endif # First check we have pkg-config >= 0.29 -pkgconfig = find_program('pkg-config', required: false) +pkgconfig = find_program('pkg-config', native: true, required: false) if not pkgconfig.found() error('MESON_SKIP_TEST: pkg-config not found') endif diff --git a/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt b/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt index a00a7d1366c7..d687b29817a7 100644 --- a/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt +++ b/test cases/unit/33 cross file overrides always args/ubuntu-armhf-overrides.txt @@ -6,7 +6,7 @@ cpp = '/usr/bin/arm-linux-gnueabihf-g++' rust = ['rustc', '--target', 'arm-unknown-linux-gnueabihf', '-C', 'linker=/usr/bin/arm-linux-gnueabihf-gcc-7'] ar = '/usr/arm-linux-gnueabihf/bin/ar' strip = '/usr/arm-linux-gnueabihf/bin/strip' -pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' +pkg-config = '/usr/bin/arm-linux-gnueabihf-pkg-config' [properties] root = '/usr/arm-linux-gnueabihf' diff --git a/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt b/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt index a5a39318d2c8..3615f92f763d 100644 --- a/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt +++ b/test cases/unit/36 exe_wrapper behaviour/broken-cross.txt @@ -3,7 +3,7 @@ c = '/usr/bin/x86_64-w64-mingw32-gcc' cpp = '/usr/bin/x86_64-w64-mingw32-g++' ar = '/usr/bin/x86_64-w64-mingw32-ar' strip = '/usr/bin/x86_64-w64-mingw32-strip' -pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' +pkg-config = '/usr/bin/x86_64-w64-mingw32-pkg-config' windres = '/usr/bin/x86_64-w64-mingw32-windres' exe_wrapper = 'broken' diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 12eafd59598f..4327d99fcd03 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2722,7 +2722,7 @@ def test_native_dep_pkgconfig(self): with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: crossfile.write(textwrap.dedent( '''[binaries] - pkgconfig = '{}' + pkg-config = '{}' [properties] @@ -2749,7 +2749,7 @@ def test_pkg_config_libdir(self): with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as crossfile: crossfile.write(textwrap.dedent( '''[binaries] - pkgconfig = 'pkg-config' + pkg-config = 'pkg-config' [properties] pkg_config_libdir = ['{}'] From 465ad6d261e2733c60c3a066eebabee72f14346a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20Wei=C3=9Fmann?= Date: Wed, 2 Aug 2023 17:28:03 +0200 Subject: [PATCH 079/855] Fix syntax mistakes in two examples --- docs/markdown/CMake-module.md | 2 +- docs/markdown/Release-notes-for-0.51.0.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/CMake-module.md b/docs/markdown/CMake-module.md index ceaee0b1c1a0..f8275c981733 100644 --- a/docs/markdown/CMake-module.md +++ b/docs/markdown/CMake-module.md @@ -41,7 +41,7 @@ sub_proj = cmake.subproject('libsimple_cmake') # Fetch the dependency object cm_lib = sub_proj.dependency('cm_lib') -executable(exe1, ['sources'], dependencies: [cm_lib]) +executable('exe1', ['sources'], dependencies: [cm_lib]) ``` The `subproject` method is almost identical to the normal Meson diff --git a/docs/markdown/Release-notes-for-0.51.0.md b/docs/markdown/Release-notes-for-0.51.0.md index da80db2f23a5..635fbbdda773 100644 --- a/docs/markdown/Release-notes-for-0.51.0.md +++ b/docs/markdown/Release-notes-for-0.51.0.md @@ -325,7 +325,7 @@ sub_proj = cmake.subproject('libsimple_cmake') # Fetch the dependency object cm_lib = sub_proj.dependency('cm_lib') -executable(exe1, ['sources'], dependencies: [cm_lib]) +executable('exe1', ['sources'], dependencies: [cm_lib]) ``` It should be noted that not all projects are guaranteed to work. The From cec3edc08a6cd6a89761c49292ba6a3bace8b3c1 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 30 May 2023 09:27:42 -0400 Subject: [PATCH 080/855] Unify message(), format() and fstring formatting Share a common function to convert objects to display strings for consistency. While at it, also add support for formatting user options. --- docs/markdown/snippets/string_format.md | 10 +++++++ docs/yaml/elementary/str.yml | 4 +++ mesonbuild/interpreter/interpreter.py | 29 +++++++------------ mesonbuild/interpreter/primitives/string.py | 13 +++++---- mesonbuild/interpreterbase/__init__.py | 8 ++++- mesonbuild/interpreterbase/helpers.py | 25 ++++++++++++++-- mesonbuild/interpreterbase/interpreterbase.py | 13 +++++---- .../common/264 format string/meson.build | 20 +++++++++++++ .../264 format string/meson_options.txt | 1 + test cases/common/264 format string/test.json | 28 ++++++++++++++++++ 10 files changed, 119 insertions(+), 32 deletions(-) create mode 100644 docs/markdown/snippets/string_format.md create mode 100644 test cases/common/264 format string/meson.build create mode 100644 test cases/common/264 format string/meson_options.txt create mode 100644 test cases/common/264 format string/test.json diff --git a/docs/markdown/snippets/string_format.md b/docs/markdown/snippets/string_format.md new file mode 100644 index 000000000000..fa3361750e8e --- /dev/null +++ b/docs/markdown/snippets/string_format.md @@ -0,0 +1,10 @@ +## Unified message(), str.format() and f-string formatting + +They now all support the same set of values: strings, integers, bools, options, +dictionaries and lists thereof. + +- Feature options (i.e. enabled, disabled, auto) were not previously supported + by any of those functions. +- Lists and dictionaries were not previously supported by f-string. +- str.format() allowed any type and often resulted in printing the internal + representation which is now deprecated. diff --git a/docs/yaml/elementary/str.yml b/docs/yaml/elementary/str.yml index 774812100ffa..83ab3dd64478 100644 --- a/docs/yaml/elementary/str.yml +++ b/docs/yaml/elementary/str.yml @@ -14,6 +14,10 @@ methods: See [the Meson syntax entry](Syntax.md#string-formatting) for more information. + + *Since 1.3.0* values other than strings, integers, bools, options, + dictionaries and lists thereof are deprecated. They were previously printing + the internal representation of the raw Python object. example: | ```meson template = 'string: @0@, number: @1@, bool: @2@' diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index dc2431267f1a..ff9b9ee664c1 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -35,6 +35,7 @@ from ..interpreterbase import Disabler, disablerIfNotFound from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs from ..interpreterbase import ObjectHolder, ContextManagerObject +from ..interpreterbase import stringifyUserArguments from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule from . import interpreterobjects as OBJ @@ -139,20 +140,6 @@ def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) return 'when passed as array must contain a File' return None - -def stringifyUserArguments(args: T.List[T.Any], quote: bool = False) -> str: - if isinstance(args, list): - return '[%s]' % ', '.join([stringifyUserArguments(x, True) for x in args]) - elif isinstance(args, dict): - return '{%s}' % ', '.join(['{} : {}'.format(stringifyUserArguments(k, True), stringifyUserArguments(v, True)) for k, v in args.items()]) - elif isinstance(args, bool): - return 'true' if args else 'false' - elif isinstance(args, int): - return str(args) - elif isinstance(args, str): - return f"'{args}'" if quote else args - raise InvalidArguments('Function accepts only strings, integers, bools, lists, dictionaries and lists thereof.') - class Summary: def __init__(self, project_name: str, project_version: str): self.project_name = project_name @@ -1343,12 +1330,18 @@ def func_add_languages(self, node: mparser.FunctionNode, args: T.Tuple[T.List[st success &= self.add_languages(langs, required, MachineChoice.HOST) return success + def _stringify_user_arguments(self, args: T.List[TYPE_var], func_name: str) -> T.List[str]: + try: + return [stringifyUserArguments(i, self.subproject) for i in args] + except InvalidArguments as e: + raise InvalidArguments(f'{func_name}(): {str(e)}') + @noArgsFlattening @noKwargs def func_message(self, node: mparser.BaseNode, args, kwargs): if len(args) > 1: FeatureNew.single_use('message with more than one argument', '0.54.0', self.subproject, location=node) - args_str = [stringifyUserArguments(i) for i in args] + args_str = self._stringify_user_arguments(args, 'message') self.message_impl(args_str) def message_impl(self, args): @@ -1427,7 +1420,7 @@ def _print_summary(self) -> None: def func_warning(self, node, args, kwargs): if len(args) > 1: FeatureNew.single_use('warning with more than one argument', '0.54.0', self.subproject, location=node) - args_str = [stringifyUserArguments(i) for i in args] + args_str = self._stringify_user_arguments(args, 'warning') mlog.warning(*args_str, location=node) @noArgsFlattening @@ -1435,14 +1428,14 @@ def func_warning(self, node, args, kwargs): def func_error(self, node, args, kwargs): if len(args) > 1: FeatureNew.single_use('error with more than one argument', '0.58.0', self.subproject, location=node) - args_str = [stringifyUserArguments(i) for i in args] + args_str = self._stringify_user_arguments(args, 'error') raise InterpreterException('Problem encountered: ' + ' '.join(args_str)) @noArgsFlattening @FeatureNew('debug', '0.63.0') @noKwargs def func_debug(self, node, args, kwargs): - args_str = [stringifyUserArguments(i) for i in args] + args_str = self._stringify_user_arguments(args, 'debug') mlog.debug('Debug:', *args_str) @noKwargs diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py index b825128e5809..bc98934dc00f 100644 --- a/mesonbuild/interpreter/primitives/string.py +++ b/mesonbuild/interpreter/primitives/string.py @@ -17,8 +17,9 @@ noKwargs, noPosargs, typed_pos_args, - InvalidArguments, + FeatureBroken, + stringifyUserArguments, ) @@ -90,12 +91,14 @@ def endswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool: @noArgsFlattening @noKwargs @typed_pos_args('str.format', varargs=object) - def format_method(self, args: T.Tuple[T.List[object]], kwargs: TYPE_kwargs) -> str: + def format_method(self, args: T.Tuple[T.List[TYPE_var]], kwargs: TYPE_kwargs) -> str: arg_strings: T.List[str] = [] for arg in args[0]: - if isinstance(arg, bool): # Python boolean is upper case. - arg = str(arg).lower() - arg_strings.append(str(arg)) + try: + arg_strings.append(stringifyUserArguments(arg, self.subproject)) + except InvalidArguments as e: + FeatureBroken.single_use(f'str.format: {str(e)}', '1.3.0', self.subproject, location=self.current_node) + arg_strings.append(str(arg)) def arg_replace(match: T.Match[str]) -> str: idx = int(match.group(1)) diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py index f0c2002cd3ed..3cb95303fbcd 100644 --- a/mesonbuild/interpreterbase/__init__.py +++ b/mesonbuild/interpreterbase/__init__.py @@ -35,6 +35,7 @@ 'default_resolve_key', 'flatten', 'resolve_second_level_holders', + 'stringifyUserArguments', 'noPosargs', 'noKwargs', @@ -134,6 +135,11 @@ ) from .disabler import Disabler, is_disabled -from .helpers import default_resolve_key, flatten, resolve_second_level_holders +from .helpers import ( + default_resolve_key, + flatten, + resolve_second_level_holders, + stringifyUserArguments, +) from .interpreterbase import InterpreterBase from .operator import MesonOperator diff --git a/mesonbuild/interpreterbase/helpers.py b/mesonbuild/interpreterbase/helpers.py index 2196b4e738ee..f2ee1b1a9f2f 100644 --- a/mesonbuild/interpreterbase/helpers.py +++ b/mesonbuild/interpreterbase/helpers.py @@ -14,13 +14,15 @@ from __future__ import annotations from .. import mesonlib, mparser -from .exceptions import InterpreterException +from .exceptions import InterpreterException, InvalidArguments +from ..coredata import UserOption + import collections.abc import typing as T if T.TYPE_CHECKING: - from .baseobjects import TYPE_var, TYPE_kwargs + from .baseobjects import TYPE_var, TYPE_kwargs, SubProject def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var']: if isinstance(args, mparser.StringNode): @@ -54,3 +56,22 @@ def default_resolve_key(key: mparser.BaseNode) -> str: if not isinstance(key, mparser.IdNode): raise InterpreterException('Invalid kwargs format.') return key.value + +def stringifyUserArguments(args: TYPE_var, subproject: SubProject, quote: bool = False) -> str: + if isinstance(args, str): + return f"'{args}'" if quote else args + elif isinstance(args, bool): + return 'true' if args else 'false' + elif isinstance(args, int): + return str(args) + elif isinstance(args, list): + return '[%s]' % ', '.join([stringifyUserArguments(x, subproject, True) for x in args]) + elif isinstance(args, dict): + l = ['{} : {}'.format(stringifyUserArguments(k, subproject, True), + stringifyUserArguments(v, subproject, True)) for k, v in args.items()] + return '{%s}' % ', '.join(l) + elif isinstance(args, UserOption): + from .decorators import FeatureNew + FeatureNew.single_use('User option in string format', '1.3.0', subproject) + return stringifyUserArguments(args.printable_value(), subproject) + raise InvalidArguments('Value other than strings, integers, bools, options, dictionaries and lists thereof.') diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 9aff5b971feb..d23a23d1f483 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -40,7 +40,7 @@ from .decorators import FeatureNew from .disabler import Disabler, is_disabled -from .helpers import default_resolve_key, flatten, resolve_second_level_holders +from .helpers import default_resolve_key, flatten, resolve_second_level_holders, stringifyUserArguments from .operator import MesonOperator from ._unholder import _unholder @@ -433,11 +433,12 @@ def replace(match: T.Match[str]) -> str: var = str(match.group(1)) try: val = _unholder(self.variables[var]) - if not isinstance(val, (str, int, float, bool)): - raise InvalidCode(f'Identifier "{var}" does not name a formattable variable ' + - '(has to be an integer, a string, a floating point number or a boolean).') - - return str(val) + if isinstance(val, (list, dict)): + FeatureNew.single_use('List or dictionary in f-string', '1.3.0', self.subproject, location=self.current_node) + try: + return stringifyUserArguments(val, self.subproject) + except InvalidArguments as e: + raise InvalidArguments(f'f-string: {str(e)}') except KeyError: raise InvalidCode(f'Identifier "{var}" does not name a variable.') diff --git a/test cases/common/264 format string/meson.build b/test cases/common/264 format string/meson.build new file mode 100644 index 000000000000..200cfac40e76 --- /dev/null +++ b/test cases/common/264 format string/meson.build @@ -0,0 +1,20 @@ +project('test format string') + +# Test all supported types in message(), format(), f-string. +foreach t : [get_option('opt'), 42, true, false, 'str', ['list'], {'dict': 'value'}] + message(t, '@0@'.format(t), f'@t@', [t], {'key': t}) +endforeach + +# Deprecated but should work with str.format(). +env = environment() +message('@0@'.format(env)) + +# Should fail with f-string and message() +error_msg = 'Value other than strings, integers, bools, options, dictionaries and lists thereof.' +testcase expect_error('message(): ' + error_msg) + message(env) +endtestcase + +testcase expect_error('f-string: ' + error_msg) + message(f'@env@') +endtestcase diff --git a/test cases/common/264 format string/meson_options.txt b/test cases/common/264 format string/meson_options.txt new file mode 100644 index 000000000000..2e39176176ca --- /dev/null +++ b/test cases/common/264 format string/meson_options.txt @@ -0,0 +1 @@ +option('opt', type: 'feature') diff --git a/test cases/common/264 format string/test.json b/test cases/common/264 format string/test.json new file mode 100644 index 000000000000..2369864b2658 --- /dev/null +++ b/test cases/common/264 format string/test.json @@ -0,0 +1,28 @@ +{ + "stdout": [ + { + "line": "Message: auto auto auto [auto] {'key' : auto}" + }, + { + "line": "Message: 42 42 42 [42] {'key' : 42}" + }, + { + "line": "Message: true true true [true] {'key' : true}" + }, + { + "line": "Message: false false false [false] {'key' : false}" + }, + { + "line": "Message: str str str ['str'] {'key' : 'str'}" + }, + { + "line": "Message: ['list'] ['list'] ['list'] [['list']] {'key' : ['list']}" + }, + { + "line": "Message: {'dict' : 'value'} {'dict' : 'value'} {'dict' : 'value'} [{'dict' : 'value'}] {'key' : {'dict' : 'value'}}" + }, + { + "line": "Message: " + } + ] + } From cdef6741698d98453142cb2a0b65c72676dbb259 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 26 Jul 2023 10:50:17 -0400 Subject: [PATCH 081/855] convert booleans in summary function to correct representation str() is going to return titlecased "True" which is not how meson works. This is misleading, so use the meson-specific format instead. --- mesonbuild/interpreter/interpreter.py | 9 ++++++--- unittests/allplatformstests.py | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index ff9b9ee664c1..4df8a1249a5e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -154,9 +154,12 @@ def add_section(self, section: str, values: T.Dict[str, T.Any], bool_yn: bool, raise InterpreterException(f'Summary section {section!r} already have key {k!r}') formatted_values = [] for i in listify(v): - if isinstance(i, bool) and bool_yn: - formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) - elif isinstance(i, (str, int, bool)): + if isinstance(i, bool): + if bool_yn: + formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) + else: + formatted_values.append('true' if i else 'false') + elif isinstance(i, (str, int)): formatted_values.append(str(i)) elif isinstance(i, (ExternalProgram, Dependency)): FeatureNew.single_use('dependency or external program in summary', '0.57.0', subproject) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 4327d99fcd03..7f38d4b09904 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -3530,7 +3530,7 @@ def test_summary(self): string : bar integer: 1 - boolean: True + boolean: true subsub undefined @@ -3539,12 +3539,12 @@ def test_summary(self): My Project 1.0 Configuration - Some boolean : False - Another boolean: True + Some boolean : false + Another boolean: true Some string : Hello World A list : string 1 - True + true empty list : enabled_opt : enabled A number : 1 From 28e6d2be9621dcd1056d6e386576510fd9cd8860 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 2 Aug 2023 17:05:49 -0400 Subject: [PATCH 082/855] ExecutableSerialisation: capture and feed are optional strings capture is the optional filename stdout is redirected to. feed is the optional filename stdin reads from. --- mesonbuild/backend/backends.py | 12 ++++++------ mesonbuild/utils/core.py | 6 ++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 26819243257b..62cf16296a0f 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -510,8 +510,8 @@ def get_executable_serialisation( self, cmd: T.Sequence[T.Union[programs.ExternalProgram, build.BuildTarget, build.CustomTarget, File, str]], workdir: T.Optional[str] = None, extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, - capture: T.Optional[bool] = None, - feed: T.Optional[bool] = None, + capture: T.Optional[str] = None, + feed: T.Optional[str] = None, env: T.Optional[mesonlib.EnvironmentVariables] = None, tag: T.Optional[str] = None, verbose: bool = False, @@ -582,8 +582,8 @@ def as_meson_exe_cmdline(self, exe: T.Union[str, mesonlib.File, build.BuildTarge cmd_args: T.Sequence[T.Union[str, mesonlib.File, build.BuildTarget, build.CustomTarget, programs.ExternalProgram]], workdir: T.Optional[str] = None, extra_bdeps: T.Optional[T.List[build.BuildTarget]] = None, - capture: T.Optional[bool] = None, - feed: T.Optional[bool] = None, + capture: T.Optional[str] = None, + feed: T.Optional[str] = None, force_serialize: bool = False, env: T.Optional[mesonlib.EnvironmentVariables] = None, verbose: bool = False) -> T.Tuple[T.Sequence[T.Union[str, File, build.Target, programs.ExternalProgram]], str]: @@ -638,9 +638,9 @@ def as_meson_exe_cmdline(self, exe: T.Union[str, mesonlib.File, build.BuildTarge return es.cmd_args, '' args: T.List[str] = [] if capture: - args += ['--capture', str(capture)] + args += ['--capture', capture] if feed: - args += ['--feed', str(feed)] + args += ['--feed', feed] return ( self.environment.get_build_command() + ['--internal', 'exe'] + args + ['--'] + es.cmd_args, diff --git a/mesonbuild/utils/core.py b/mesonbuild/utils/core.py index eee88b94d9aa..6e2ec6ac225c 100644 --- a/mesonbuild/utils/core.py +++ b/mesonbuild/utils/core.py @@ -141,15 +141,13 @@ def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) @dataclass(eq=False) class ExecutableSerialisation: - # XXX: should capture and feed default to False, instead of None? - cmd_args: T.List[str] env: T.Optional[EnvironmentVariables] = None exe_wrapper: T.Optional['programs.ExternalProgram'] = None workdir: T.Optional[str] = None extra_paths: T.Optional[T.List] = None - capture: T.Optional[bool] = None - feed: T.Optional[bool] = None + capture: T.Optional[str] = None + feed: T.Optional[str] = None tag: T.Optional[str] = None verbose: bool = False installdir_map: T.Optional[T.Dict[str, str]] = None From 6d7562a02cc6b6e45f2a43c7a29223e75e88c3df Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 2 Aug 2023 17:20:59 -0400 Subject: [PATCH 083/855] run_command: Remove useless node argument There is no need to pass it, we already have self.current_node. --- mesonbuild/interpreter/interpreter.py | 7 +++---- mesonbuild/programs.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 4df8a1249a5e..4ef78e878c3d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -770,10 +770,9 @@ def func_run_command(self, node: mparser.BaseNode, args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], kwargs: 'kwtypes.RunCommand') -> RunProcess: - return self.run_command_impl(node, args, kwargs) + return self.run_command_impl(args, kwargs) def run_command_impl(self, - node: mparser.BaseNode, args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], kwargs: 'kwtypes.RunCommand', @@ -829,7 +828,7 @@ def run_command_impl(self, elif isinstance(a, ExternalProgram): expanded_args.append(a.get_path()) elif isinstance(a, compilers.Compiler): - FeatureNew.single_use('Compiler object as a variadic argument to `run_command`', '0.61.0', self.subproject, location=node) + FeatureNew.single_use('Compiler object as a variadic argument to `run_command`', '0.61.0', self.subproject, location=self.current_node) prog = ExternalProgram(a.exelist[0], silent=True) if not prog.found(): raise InterpreterException(f'Program {cmd!r} not found or not executable') @@ -2687,7 +2686,7 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], _cmd = mesonlib.substitute_values(kwargs['command'], values) mlog.log('Configuring', mlog.bold(output), 'with command') cmd, *args = _cmd - res = self.run_command_impl(node, (cmd, args), + res = self.run_command_impl((cmd, args), {'capture': True, 'check': True, 'env': EnvironmentVariables()}, True) if kwargs['capture']: diff --git a/mesonbuild/programs.py b/mesonbuild/programs.py index 13b998193e84..beb5bc566f74 100644 --- a/mesonbuild/programs.py +++ b/mesonbuild/programs.py @@ -105,7 +105,7 @@ def get_version(self, interpreter: T.Optional['Interpreter'] = None) -> str: if not self.cached_version: raw_cmd = self.get_command() + ['--version'] if interpreter: - res = interpreter.run_command_impl(interpreter.current_node, (self, ['--version']), + res = interpreter.run_command_impl((self, ['--version']), {'capture': True, 'check': True, 'env': mesonlib.EnvironmentVariables()}, From f077cb2ee3fba55fc0e1be327ad791c19f3c3b5e Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 2 Aug 2023 13:33:02 -0400 Subject: [PATCH 084/855] MachineChoice: Implement __str__ for easier debug --- mesonbuild/utils/universal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index d78fadd438c6..5b7750c99241 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -487,6 +487,9 @@ class MachineChoice(enum.IntEnum): BUILD = 0 HOST = 1 + def __str__(self) -> str: + return f'{self.get_lower_case_name()} machine' + def get_lower_case_name(self) -> str: return PerMachine('build', 'host')[self] From 183e4b8e903c6c4c057d09549e669d6292478a4e Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 6 Jun 2023 12:10:35 -0400 Subject: [PATCH 085/855] PkgConfigDependency: Move CLI handling into its own abstraction This makes the code cleaner and will allow to have other implementations in the future. --- mesonbuild/dependencies/hdf5.py | 25 +- mesonbuild/dependencies/pkgconfig.py | 347 +++++++++++++++---------- mesonbuild/dependencies/scalapack.py | 16 +- mesonbuild/modules/external_project.py | 6 +- mesonbuild/modules/gnome.py | 4 +- mesonbuild/modules/pkgconfig.py | 4 +- run_tests.py | 6 +- unittests/internaltests.py | 38 +-- unittests/linuxliketests.py | 7 +- 9 files changed, 254 insertions(+), 199 deletions(-) diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index 84f28126f5dd..501e89d1b9ef 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -18,15 +18,13 @@ import functools import os import re -import subprocess from pathlib import Path -from ..mesonlib import Popen_safe, OrderedSet, join_args -from ..programs import ExternalProgram +from ..mesonlib import OrderedSet, join_args from .base import DependencyException, DependencyMethods from .configtool import ConfigToolDependency from .detect import packages -from .pkgconfig import PkgConfigDependency +from .pkgconfig import PkgConfigDependency, PkgConfigInterface from .factory import factory_methods import typing as T @@ -157,19 +155,14 @@ def hdf5_factory(env: 'Environment', for_machine: 'MachineChoice', if DependencyMethods.PKGCONFIG in methods: # Use an ordered set so that these remain the first tried pkg-config files pkgconfig_files = OrderedSet(['hdf5', 'hdf5-serial']) - PCEXE = PkgConfigDependency._detect_pkgbin(False, env, for_machine) - pcenv = PkgConfigDependency.setup_env(os.environ, env, for_machine) - if PCEXE: - assert isinstance(PCEXE, ExternalProgram) + pkg = PkgConfigInterface.instance(env, for_machine, silent=False) + if pkg: # some distros put hdf5-1.2.3.pc with version number in .pc filename. - ret, stdout, _ = Popen_safe(PCEXE.get_command() + ['--list-all'], stderr=subprocess.DEVNULL, env=pcenv) - if ret.returncode == 0: - for pkg in stdout.split('\n'): - if pkg.startswith('hdf5'): - pkgconfig_files.add(pkg.split(' ', 1)[0]) - - for pkg in pkgconfig_files: - candidates.append(functools.partial(HDF5PkgConfigDependency, pkg, env, kwargs, language)) + for mod in pkg.list_all(): + if mod.startswith('hdf5'): + pkgconfig_files.add(mod) + for mod in pkgconfig_files: + candidates.append(functools.partial(HDF5PkgConfigDependency, mod, env, kwargs, language)) if DependencyMethods.CONFIG_TOOL in methods: candidates.append(functools.partial(HDF5ConfigToolDependency, 'hdf5', env, kwargs, language)) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 37f2ecb1c7e4..cfe9cbb7c9c1 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -31,64 +31,142 @@ from ..utils.core import EnvironOrDict from .._typing import ImmutableListProtocol -class PkgConfigDependency(ExternalDependency): +class PkgConfigInterface: + '''Base class wrapping a pkg-config implementation''' + + @staticmethod + def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[PkgConfigInterface]: + impl = PkgConfigCLI(env, for_machine, silent) + if not impl.found(): + return None + return impl + + def found(self) -> bool: + '''Return whether pkg-config is supported''' + raise NotImplementedError + + def version(self, name: str) -> T.Optional[str]: + '''Return module version or None if not found''' + raise NotImplementedError + + def cflags(self, name: str, allow_system: bool = False, + define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + '''Return module cflags + @allow_system: If False, remove default system include paths + ''' + raise NotImplementedError + + def libs(self, name: str, static: bool = False, allow_system: bool = False, + define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + '''Return module libs + @static: If True, also include private libraries + @allow_system: If False, remove default system libraries search paths + ''' + raise NotImplementedError + + def variable(self, name: str, variable_name: str, + define_variable: ImmutableListProtocol[str]) -> T.Optional[str]: + '''Return module variable or None if variable is not defined''' + raise NotImplementedError + + def list_all(self) -> T.List[str]: + '''Return all available pkg-config modules''' + raise NotImplementedError + +class PkgConfigCLI(PkgConfigInterface): + '''pkg-config CLI implementation''' + # The class's copy of the pkg-config path. Avoids having to search for it # multiple times in the same Meson invocation. - class_pkgbin: PerMachine[T.Union[None, bool, ExternalProgram]] = PerMachine(None, None) + class_pkgbin: PerMachine[T.Union[None, T.Literal[False], ExternalProgram]] = PerMachine(None, None) # We cache all pkg-config subprocess invocations to avoid redundant calls pkgbin_cache: T.Dict[ T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]], T.Tuple[int, str, str] ] = {} - def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: - super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language) - self.name = name - self.is_libtool = False + def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None: + self.env = env + self.for_machine = for_machine # Store a copy of the pkg-config path on the object itself so it is # stored in the pickled coredata and recovered. - self.pkgbin = self._detect_pkgbin(self.silent, self.env, self.for_machine) - if self.pkgbin is False: - self.pkgbin = None - msg = f'Pkg-config binary for machine {self.for_machine} not found. Giving up.' - if self.required: - raise DependencyException(msg) - else: - mlog.debug(msg) - return + self.pkgbin = self._detect_pkgbin(env, for_machine, silent) - assert isinstance(self.pkgbin, ExternalProgram) - mlog.debug('Determining dependency {!r} with pkg-config executable ' - '{!r}'.format(name, self.pkgbin.get_path())) - ret, self.version, _ = self._call_pkgbin(['--modversion', name]) + def found(self) -> bool: + return bool(self.pkgbin) + + def version(self, name: str) -> T.Optional[str]: + mlog.debug(f'Determining dependency {name!r} with pkg-config executable {self.pkgbin.get_path()!r}') + ret, version, _ = self._call_pkgbin(['--modversion', name]) + return version if ret == 0 else None + + @staticmethod + def _define_variable_args(define_variable: T.Optional[ImmutableListProtocol[str]]) -> T.List[str]: + if define_variable: + return ['--define-variable=' + '='.join(define_variable)] + return [] + + def cflags(self, name: str, allow_system: bool = False, + define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + env = None + if allow_system: + env = os.environ.copy() + env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1' + args: T.List[str] = [] + args += self._define_variable_args(define_variable) + args += ['--cflags', name] + ret, out, err = self._call_pkgbin(args, env=env) if ret != 0: - return + raise DependencyException(f'Could not generate cflags for {name}:\n{err}\n') + return self._split_args(out) - self.is_found = True + def libs(self, name: str, static: bool = False, allow_system: bool = False, + define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + env = None + if allow_system: + env = os.environ.copy() + env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1' + args: T.List[str] = [] + args += self._define_variable_args(define_variable) + if static: + args.append('--static') + args += ['--libs', name] + ret, out, err = self._call_pkgbin(args, env=env) + if ret != 0: + raise DependencyException(f'Could not generate libs for {name}:\n{err}\n') + return self._split_args(out) + + def variable(self, name: str, variable_name: str, + define_variable: ImmutableListProtocol[str]) -> T.Optional[str]: + args: T.List[str] = [] + args += self._define_variable_args(define_variable) + args += ['--variable=' + variable_name, name] + ret, out, err = self._call_pkgbin(args) + if ret != 0: + raise DependencyException(f'Could not get variable for {name}:\n{err}\n') + variable = out.strip() + # pkg-config doesn't distinguish between empty and nonexistent variables + # use the variable list to check for variable existence + if not variable: + ret, out, _ = self._call_pkgbin(['--print-variables', name]) + if not re.search(rf'^{variable_name}$', out, re.MULTILINE): + return None + mlog.debug(f'Got pkg-config variable {variable_name} : {variable}') + return variable - try: - # Fetch cargs to be used while using this dependency - self._set_cargs() - # Fetch the libraries and library paths needed for using this - self._set_libs() - except DependencyException as e: - mlog.debug(f"pkg-config error with '{name}': {e}") - if self.required: - raise - else: - self.compile_args = [] - self.link_args = [] - self.is_found = False - self.reason = e + def list_all(self) -> T.List[str]: + ret, out, err = self._call_pkgbin(['--list-all']) + if ret != 0: + raise DependencyException(f'could not list modules:\n{err}\n') + return [i.split(' ', 1)[0] for i in out.splitlines()] - def __repr__(self) -> str: - s = '<{0} {1}: {2} {3}>' - return s.format(self.__class__.__name__, self.name, self.is_found, - self.version_reqs) + def _split_args(self, cmd: str) -> T.List[str]: + # pkg-config paths follow Unix conventions, even on Windows; split the + # output using shlex.split rather than mesonlib.split_args + return shlex.split(cmd) @classmethod - def _detect_pkgbin(cls, silent: bool, env: Environment, - for_machine: MachineChoice) -> T.Union[None, bool, ExternalProgram]: + def _detect_pkgbin(cls, env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[ExternalProgram]: # Only search for pkg-config for each machine the first time and store # the result in the class definition if cls.class_pkgbin[for_machine] is False: @@ -111,12 +189,12 @@ def _detect_pkgbin(cls, silent: bool, env: Environment, break else: if not silent: - mlog.log('Found Pkg-config:', mlog.red('NO')) + mlog.log('Found pkg-config:', mlog.red('NO')) # Set to False instead of None to signify that we've already # searched for it and not found it cls.class_pkgbin[for_machine] = False - return cls.class_pkgbin[for_machine] + return cls.class_pkgbin[for_machine] or None def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]: assert isinstance(self.pkgbin, ExternalProgram) @@ -125,8 +203,34 @@ def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple return p.returncode, out.strip(), err.strip() @staticmethod - def get_env(environment: 'Environment', for_machine: MachineChoice, - uninstalled: bool = False) -> 'EnvironmentVariables': + def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str]: + if not pkgbin.found(): + mlog.log(f'Did not find pkg-config by name {pkgbin.name!r}') + return None + command_as_string = ' '.join(pkgbin.get_command()) + try: + helptext = Popen_safe(pkgbin.get_command() + ['--help'])[1] + if 'Pure-Perl' in helptext: + mlog.log(f'Found pkg-config {command_as_string!r} but it is Strawberry Perl and thus broken. Ignoring...') + return None + p, out = Popen_safe(pkgbin.get_command() + ['--version'])[0:2] + if p.returncode != 0: + mlog.warning(f'Found pkg-config {command_as_string!r} but it failed when ran') + return None + except FileNotFoundError: + mlog.warning(f'We thought we found pkg-config {command_as_string!r} but now it\'s not there. How odd!') + return None + except PermissionError: + msg = f'Found pkg-config {command_as_string!r} but didn\'t have permissions to run it.' + if not env.machines.build.is_windows(): + msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.' + mlog.warning(msg) + return None + return out.strip() + + @staticmethod + def get_env(environment: Environment, for_machine: MachineChoice, + uninstalled: bool = False) -> EnvironmentVariables: env = EnvironmentVariables() key = OptionKey('pkg_config_path', machine=for_machine) extra_paths: T.List[str] = environment.coredata.options[key].value[:] @@ -144,9 +248,9 @@ def get_env(environment: 'Environment', for_machine: MachineChoice, return env @staticmethod - def setup_env(env: EnvironOrDict, environment: 'Environment', for_machine: MachineChoice, + def setup_env(env: EnvironOrDict, environment: Environment, for_machine: MachineChoice, uninstalled: bool = False) -> T.Dict[str, str]: - envvars = PkgConfigDependency.get_env(environment, for_machine, uninstalled) + envvars = PkgConfigCLI.get_env(environment, for_machine, uninstalled) env = envvars.get_env(env) # Dump all PKG_CONFIG environment variables for key, value in env.items(): @@ -157,15 +261,57 @@ def setup_env(env: EnvironOrDict, environment: 'Environment', for_machine: Machi def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) -> T.Tuple[int, str, str]: assert isinstance(self.pkgbin, ExternalProgram) env = env or os.environ - env = PkgConfigDependency.setup_env(env, self.env, self.for_machine) + env = self.setup_env(env, self.env, self.for_machine) fenv = frozenset(env.items()) targs = tuple(args) - cache = PkgConfigDependency.pkgbin_cache + cache = self.pkgbin_cache if (self.pkgbin, targs, fenv) not in cache: cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env) return cache[(self.pkgbin, targs, fenv)] + +class PkgConfigDependency(ExternalDependency): + + def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None: + super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language) + self.name = name + self.is_libtool = False + self.pkgconfig = PkgConfigInterface.instance(self.env, self.for_machine, self.silent) + if not self.pkgconfig: + msg = f'Pkg-config for machine {self.for_machine} not found. Giving up.' + if self.required: + raise DependencyException(msg) + mlog.debug(msg) + return + + version = self.pkgconfig.version(name) + if version is None: + return + + self.version = version + self.is_found = True + + try: + # Fetch cargs to be used while using this dependency + self._set_cargs() + # Fetch the libraries and library paths needed for using this + self._set_libs() + except DependencyException as e: + mlog.debug(f"Pkg-config error with '{name}': {e}") + if self.required: + raise + else: + self.compile_args = [] + self.link_args = [] + self.is_found = False + self.reason = e + + def __repr__(self) -> str: + s = '<{0} {1}: {2} {3}>' + return s.format(self.__class__.__name__, self.name, self.is_found, + self.version_reqs) + def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]: ''' Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo @@ -197,27 +343,19 @@ def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]: converted.append(arg) return converted - def _split_args(self, cmd: str) -> T.List[str]: - # pkg-config paths follow Unix conventions, even on Windows; split the - # output using shlex.split rather than mesonlib.split_args - return shlex.split(cmd) - def _set_cargs(self) -> None: - env = None + allow_system = False if self.language == 'fortran': # gfortran doesn't appear to look in system paths for INCLUDE files, # so don't allow pkg-config to suppress -I flags for system paths - env = os.environ.copy() - env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1' - ret, out, err = self._call_pkgbin(['--cflags', self.name], env=env) - if ret != 0: - raise DependencyException(f'Could not generate cargs for {self.name}:\n{err}\n') - self.compile_args = self._convert_mingw_paths(self._split_args(out)) + allow_system = True + cflags = self.pkgconfig.cflags(self.name, allow_system) + self.compile_args = self._convert_mingw_paths(cflags) - def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[str]]: + def _search_libs(self, libs_in: T.List[str], raw_libs_in: T.List[str]) -> T.Tuple[T.List[str], T.List[str]]: ''' - @out: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs - @out_raw: pkg-config --libs + @libs_in: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs + @raw_libs_in: pkg-config --libs We always look for the file ourselves instead of depending on the compiler to find it with -lfoo or foo.lib (if possible) because: @@ -241,7 +379,7 @@ def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[st # always searched first. prefix_libpaths: OrderedSet[str] = OrderedSet() # We also store this raw_link_args on the object later - raw_link_args = self._convert_mingw_paths(self._split_args(out_raw)) + raw_link_args = self._convert_mingw_paths(raw_libs_in) for arg in raw_link_args: if arg.startswith('-L') and not arg.startswith(('-L-l', '-L-L')): path = arg[2:] @@ -262,7 +400,7 @@ def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[st pkg_config_path = self._convert_mingw_paths(pkg_config_path) prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path)) system_libpaths: OrderedSet[str] = OrderedSet() - full_args = self._convert_mingw_paths(self._split_args(out)) + full_args = self._convert_mingw_paths(libs_in) for arg in full_args: if arg.startswith(('-L-l', '-L-L')): # These are D language arguments, not library paths @@ -367,84 +505,25 @@ def _search_libs(self, out: str, out_raw: str) -> T.Tuple[T.List[str], T.List[st return link_args, raw_link_args def _set_libs(self) -> None: - env = None - libcmd = ['--libs'] - - if self.static: - libcmd.append('--static') - - libcmd.append(self.name) - # Force pkg-config to output -L fields even if they are system # paths so we can do manual searching with cc.find_library() later. - env = os.environ.copy() - env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1' - ret, out, err = self._call_pkgbin(libcmd, env=env) - if ret != 0: - raise DependencyException(f'Could not generate libs for {self.name}:\n{err}\n') + libs = self.pkgconfig.libs(self.name, self.static, allow_system=True) # Also get the 'raw' output without -Lfoo system paths for adding -L # args with -lfoo when a library can't be found, and also in # gnome.generate_gir + gnome.gtkdoc which need -L -l arguments. - ret, out_raw, err_raw = self._call_pkgbin(libcmd) - if ret != 0: - raise DependencyException(f'Could not generate libs for {self.name}:\n\n{out_raw}') - self.link_args, self.raw_link_args = self._search_libs(out, out_raw) + raw_libs = self.pkgconfig.libs(self.name, self.static, allow_system=False) + self.link_args, self.raw_link_args = self._search_libs(libs, raw_libs) def get_pkgconfig_variable(self, variable_name: str, - define_variable: 'ImmutableListProtocol[str]', + define_variable: ImmutableListProtocol[str], default: T.Optional[str]) -> str: - options = ['--variable=' + variable_name, self.name] - - if define_variable: - options = ['--define-variable=' + '='.join(define_variable)] + options - - ret, out, err = self._call_pkgbin(options) - variable = '' - if ret != 0: - if self.required: - raise DependencyException(f'dependency {self.name} not found:\n{err}\n') - else: - variable = out.strip() - - # pkg-config doesn't distinguish between empty and nonexistent variables - # use the variable list to check for variable existence - if not variable: - ret, out, _ = self._call_pkgbin(['--print-variables', self.name]) - if not re.search(r'^' + variable_name + r'$', out, re.MULTILINE): - if default is not None: - variable = default - else: - mlog.warning(f"pkgconfig variable '{variable_name}' not defined for dependency {self.name}.") - - mlog.debug(f'Got pkgconfig variable {variable_name} : {variable}') + variable = self.pkgconfig.variable(self.name, variable_name, define_variable) + if variable is None: + if default is None: + mlog.warning(f'Pkg-config variable {variable_name!r} not defined for dependency {self.name}.') + variable = default or '' return variable - @staticmethod - def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str]: - if not pkgbin.found(): - mlog.log(f'Did not find pkg-config by name {pkgbin.name!r}') - return None - command_as_string = ' '.join(pkgbin.get_command()) - try: - helptext = Popen_safe(pkgbin.get_command() + ['--help'])[1] - if 'Pure-Perl' in helptext: - mlog.log(f'found pkg-config {command_as_string!r} but it is Strawberry Perl and thus broken. Ignoring...') - return None - p, out = Popen_safe(pkgbin.get_command() + ['--version'])[0:2] - if p.returncode != 0: - mlog.warning(f'Found pkg-config {command_as_string!r} but it failed when run') - return None - except FileNotFoundError: - mlog.warning(f'We thought we found pkg-config {command_as_string!r} but now it\'s not there. How odd!') - return None - except PermissionError: - msg = f'Found pkg-config {command_as_string!r} but didn\'t have permissions to run it.' - if not env.machines.build.is_windows(): - msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.' - mlog.warning(msg) - return None - return out.strip() - def extract_field(self, la_file: str, fieldname: str) -> T.Optional[str]: with open(la_file, encoding='utf-8') as f: for line in f: diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index 2442ede41ee0..fc2f7206423e 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -20,7 +20,6 @@ from ..mesonlib import OptionKey from .base import DependencyMethods -from .base import DependencyException from .cmake import CMakeDependency from .detect import packages from .pkgconfig import PkgConfigDependency @@ -144,17 +143,10 @@ def _set_libs(self) -> None: self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64') def _set_cargs(self) -> None: - env = None + allow_system = False if self.language == 'fortran': # gfortran doesn't appear to look in system paths for INCLUDE files, # so don't allow pkg-config to suppress -I flags for system paths - env = os.environ.copy() - env['PKG_CONFIG_ALLOW_SYSTEM_CFLAGS'] = '1' - ret, out, err = self._call_pkgbin([ - '--cflags', self.name, - '--define-variable=prefix=' + self.__mklroot.as_posix()], - env=env) - if ret != 0: - raise DependencyException('Could not generate cargs for %s:\n%s\n' % - (self.name, err)) - self.compile_args = self._convert_mingw_paths(self._split_args(out)) + allow_system = True + cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=['prefix', self.__mklroot.as_posix()]) + self.compile_args = self._convert_mingw_paths(cflags) diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index fd7e7c885f05..f7a72bcedafb 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -24,7 +24,7 @@ from ..compilers.compilers import CFLAGS_MAPPING from ..envconfig import ENV_VAR_PROG_MAP from ..dependencies import InternalDependency -from ..dependencies.pkgconfig import PkgConfigDependency +from ..dependencies.pkgconfig import PkgConfigCLI from ..interpreterbase import FeatureNew from ..interpreter.type_checking import ENV_KW, DEPENDS_KW from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -165,8 +165,8 @@ def _configure(self, state: 'ModuleState') -> None: self.run_env['LDFLAGS'] = self._quote_and_join(link_args) self.run_env = self.user_env.get_env(self.run_env) - self.run_env = PkgConfigDependency.setup_env(self.run_env, self.env, MachineChoice.HOST, - uninstalled=True) + self.run_env = PkgConfigCLI.setup_env(self.run_env, self.env, MachineChoice.HOST, + uninstalled=True) self.build_dir.mkdir(parents=True, exist_ok=True) self._run('configure', configure_cmd, workdir) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 3249212b9c5d..18862e72c96b 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -34,7 +34,7 @@ from .. import mlog from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments from ..dependencies import Dependency, InternalDependency -from ..dependencies.pkgconfig import PkgConfigDependency +from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, in_set_validator from ..interpreterbase import noPosargs, noKwargs, FeatureNew, FeatureDeprecated from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo @@ -967,7 +967,7 @@ def _make_gir_target( # -uninstalled.pc files Meson generated. It also must respect pkgconfig # settings user could have set in machine file, like PKG_CONFIG_LIBDIR, # SYSROOT, etc. - run_env = PkgConfigDependency.get_env(state.environment, MachineChoice.HOST, uninstalled=True) + run_env = PkgConfigCLI.get_env(state.environment, MachineChoice.HOST, uninstalled=True) # g-ir-scanner uses Python's distutils to find the compiler, which uses 'CC' cc_exelist = state.environment.coredata.compilers.host['c'].get_exelist() run_env.set('CC', [quote_arg(x) for x in cc_exelist], ' ') diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index dd2efad73116..44182d785feb 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -26,7 +26,7 @@ from .. import mesonlib from .. import mlog from ..coredata import BUILTIN_DIR_OPTIONS -from ..dependencies.pkgconfig import PkgConfigDependency +from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI from ..interpreter.type_checking import D_MODULE_VERSIONS_KW, INSTALL_DIR_KW, VARIABLES_KW, NoneType from ..interpreterbase import FeatureNew, FeatureDeprecated from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -741,7 +741,7 @@ def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]: self._metadata[lib.get_id()] = MetaData( filebase, name, state.current_node) if self.devenv is None: - self.devenv = PkgConfigDependency.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) + self.devenv = PkgConfigCLI.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) return ModuleReturnValue(res, [res]) diff --git a/run_tests.py b/run_tests.py index 66341e465a57..cf0633783303 100755 --- a/run_tests.py +++ b/run_tests.py @@ -36,7 +36,7 @@ from mesonbuild.compilers.c import CCompiler from mesonbuild.compilers.detect import detect_c_compiler -from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigCLI from mesonbuild import mesonlib from mesonbuild import mesonmain from mesonbuild import mtest @@ -302,8 +302,8 @@ def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: def clear_meson_configure_class_caches() -> None: CCompiler.find_library_cache = {} CCompiler.find_framework_cache = {} - PkgConfigDependency.pkgbin_cache = {} - PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None) + PkgConfigCLI.pkgbin_cache = {} + PkgConfigCLI.class_pkgbin = mesonlib.PerMachine(None, None) mesonlib.project_meson_versions = collections.defaultdict(str) def run_configure_inprocess(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 672a5a069bc6..86a30f8abeae 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -47,7 +47,7 @@ OptionType ) from mesonbuild.interpreter.type_checking import in_set_validator, NoneType -from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface, PkgConfigCLI from mesonbuild.programs import ExternalProgram import mesonbuild.modules.pkgconfig @@ -640,22 +640,19 @@ def create_static_lib(name): create_static_lib(p1 / 'libdl.a') create_static_lib(p1 / 'librt.a') - def fake_call_pkgbin(self, args, env=None): - if '--libs' not in args: - return 0, '', '' - if args[-1] == 'foo': - return 0, f'-L{p2.as_posix()} -lfoo -L{p1.as_posix()} -lbar', '' - if args[-1] == 'bar': - return 0, f'-L{p2.as_posix()} -lbar', '' - if args[-1] == 'internal': - return 0, f'-L{p1.as_posix()} -lpthread -lm -lc -lrt -ldl', '' - - old_call = PkgConfigDependency._call_pkgbin - old_check = PkgConfigDependency.check_pkgconfig - PkgConfigDependency._call_pkgbin = fake_call_pkgbin - PkgConfigDependency.check_pkgconfig = lambda x, _: pkgbin - # Test begins - try: + class FakeInstance(PkgConfigCLI): + def _call_pkgbin(self, args, env=None): + if '--libs' not in args: + return 0, '', '' + if args[-1] == 'foo': + return 0, f'-L{p2.as_posix()} -lfoo -L{p1.as_posix()} -lbar', '' + if args[-1] == 'bar': + return 0, f'-L{p2.as_posix()} -lbar', '' + if args[-1] == 'internal': + return 0, f'-L{p1.as_posix()} -lpthread -lm -lc -lrt -ldl', '' + + with mock.patch.object(PkgConfigInterface, 'instance') as instance_method: + instance_method.return_value = FakeInstance(env, MachineChoice.HOST, silent=True) kwargs = {'required': True, 'silent': True} foo_dep = PkgConfigDependency('foo', env, kwargs) self.assertEqual(foo_dep.get_link_args(), @@ -670,13 +667,6 @@ def fake_call_pkgbin(self, args, env=None): for link_arg in link_args: for lib in ('pthread', 'm', 'c', 'dl', 'rt'): self.assertNotIn(f'lib{lib}.a', link_arg, msg=link_args) - finally: - # Test ends - PkgConfigDependency._call_pkgbin = old_call - PkgConfigDependency.check_pkgconfig = old_check - # Reset dependency class to ensure that in-process configure doesn't mess up - PkgConfigDependency.pkgbin_cache = {} - PkgConfigDependency.class_pkgbin = PerMachine(None, None) def test_version_compare(self): comparefunc = mesonbuild.mesonlib.version_compare_many diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 7ebb575a79df..bd73857e960f 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -45,7 +45,7 @@ from mesonbuild.compilers.cpp import AppleClangCPPCompiler from mesonbuild.compilers.objc import AppleClangObjCCompiler from mesonbuild.compilers.objcpp import AppleClangObjCPPCompiler -from mesonbuild.dependencies.pkgconfig import PkgConfigDependency +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI import mesonbuild.modules.pkgconfig PKG_CONFIG = os.environ.get('PKG_CONFIG', 'pkg-config') @@ -173,7 +173,8 @@ def test_pkgconfig_gen(self): self.assertEqual(libhello_nolib.get_compile_args(), []) self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', [], None), 'bar') self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', [], None), self.prefix) - if version_compare(PkgConfigDependency.check_pkgconfig(env, libhello_nolib.pkgbin),">=0.29.1"): + impl = libhello_nolib.pkgconfig + if not isinstance(impl, PkgConfigCLI) or version_compare(PkgConfigCLI.check_pkgconfig(env, impl.pkgbin),">=0.29.1"): self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', [], None), r'hello\ world') self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', [], None), 'hello world') @@ -1168,7 +1169,7 @@ def test_pkgconfig_duplicate_path_entries(self): # Regression test: This used to modify the value of `pkg_config_path` # option, adding the meson-uninstalled directory to it. - PkgConfigDependency.setup_env({}, env, MachineChoice.HOST, uninstalled=True) + PkgConfigCLI.setup_env({}, env, MachineChoice.HOST, uninstalled=True) pkg_config_path = env.coredata.options[OptionKey('pkg_config_path')].value self.assertEqual(pkg_config_path, [pkg_dir]) From 50baf3c626267252a2d943a49d8e7c0402e23218 Mon Sep 17 00:00:00 2001 From: Nomura Date: Wed, 2 Aug 2023 22:34:39 +0200 Subject: [PATCH 086/855] Add default_options argument to find_program() --- .../snippets/find_program_default_options.md | 4 ++++ docs/yaml/functions/find_program.yaml | 10 ++++++++++ mesonbuild/interpreter/interpreter.py | 15 ++++++++++----- mesonbuild/interpreter/kwargs.py | 1 + .../meson.build | 5 +++++ .../subprojects/dummy.wrap | 5 +++++ .../subprojects/dummy/dummy.c | 3 +++ .../subprojects/dummy/meson.build | 6 ++++++ .../subprojects/dummy/meson_options.txt | 1 + 9 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/find_program_default_options.md create mode 100644 test cases/common/265 default_options in find_program/meson.build create mode 100644 test cases/common/265 default_options in find_program/subprojects/dummy.wrap create mode 100644 test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c create mode 100644 test cases/common/265 default_options in find_program/subprojects/dummy/meson.build create mode 100644 test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt diff --git a/docs/markdown/snippets/find_program_default_options.md b/docs/markdown/snippets/find_program_default_options.md new file mode 100644 index 000000000000..2cf9822d2f87 --- /dev/null +++ b/docs/markdown/snippets/find_program_default_options.md @@ -0,0 +1,4 @@ +## find_program() now supports the 'default_options' argument + +In a similar fashion as dependency(), find_program() now also allows you to set default +options for the subproject that gets built in case of a fallback. diff --git a/docs/yaml/functions/find_program.yaml b/docs/yaml/functions/find_program.yaml index 537bbc59c52c..3153bd32786a 100644 --- a/docs/yaml/functions/find_program.yaml +++ b/docs/yaml/functions/find_program.yaml @@ -113,3 +113,13 @@ kwargs: type: list[str] since: 0.53.0 description: extra list of absolute paths where to look for program names. + + default_options: + type: list[str] | dict[str | bool | int | list[str]] + since: 1.3.0 + description: | + An array of default option values + that override those set in the subproject's `meson.options` + (like `default_options` in [[project]], they only have + effect when Meson is run for the first time, and command line + arguments override any default options in build files) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 4ef78e878c3d..95a6e1d8004b 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1619,6 +1619,7 @@ def notfound_program(self, args: T.List[mesonlib.FileOrString]) -> ExternalProgr # the host machine. def find_program_impl(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice = MachineChoice.HOST, + default_options: T.Optional[T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None, required: bool = True, silent: bool = True, wanted: T.Union[str, T.List[str]] = '', search_dirs: T.Optional[T.List[str]] = None, @@ -1627,7 +1628,7 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString], args = mesonlib.listify(args) extra_info: T.List[mlog.TV_Loggable] = [] - progobj = self.program_lookup(args, for_machine, required, search_dirs, extra_info) + progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, extra_info) if progobj is None: progobj = self.notfound_program(args) @@ -1671,6 +1672,7 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString], return progobj def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice, + default_options: T.Optional[T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]], required: bool, search_dirs: T.List[str], extra_info: T.List[mlog.TV_Loggable] ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: progobj = self.program_from_overrides(args, extra_info) @@ -1686,7 +1688,7 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver: fallback = self.environment.wrap_resolver.find_program_provider(args) if fallback and wrap_mode == WrapMode.forcefallback: - return self.find_program_fallback(fallback, args, required, extra_info) + return self.find_program_fallback(fallback, args, default_options, required, extra_info) progobj = self.program_from_file_for(for_machine, args) if progobj is None: @@ -1695,18 +1697,19 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi prog = ExternalProgram('python3', mesonlib.python_command, silent=True) progobj = prog if prog.found() else None if progobj is None and fallback and required: - progobj = self.find_program_fallback(fallback, args, required, extra_info) + progobj = self.find_program_fallback(fallback, args, default_options, required, extra_info) return progobj def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]], required: bool, extra_info: T.List[mlog.TV_Loggable] ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', mlog.bold(' '.join(args))) sp_kwargs: kwtypes.DoSubproject = { 'required': required, - 'default_options': {}, + 'default_options': default_options or {}, 'version': [], 'cmake_options': [], 'options': None, @@ -1722,6 +1725,7 @@ def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrStrin REQUIRED_KW, KwargInfo('dirs', ContainerTypeInfo(list, str), default=[], listify=True, since='0.53.0'), KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True, since='0.52.0'), + DEFAULT_OPTIONS.evolve(since='1.3.0') ) @disablerIfNotFound def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]], @@ -1733,7 +1737,8 @@ def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonli return self.notfound_program(args[0]) search_dirs = extract_search_dirs(kwargs) - return self.find_program_impl(args[0], kwargs['native'], required=required, + default_options = kwargs['default_options'] + return self.find_program_impl(args[0], kwargs['native'], default_options=default_options, required=required, silent=False, wanted=kwargs['version'], search_dirs=search_dirs) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 13b7430b39b9..2a1cd6173891 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -232,6 +232,7 @@ class Summary(TypedDict): class FindProgram(ExtractRequired, ExtractSearchDirs): + default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] native: MachineChoice version: T.List[str] diff --git a/test cases/common/265 default_options in find_program/meson.build b/test cases/common/265 default_options in find_program/meson.build new file mode 100644 index 000000000000..99d8425927d6 --- /dev/null +++ b/test cases/common/265 default_options in find_program/meson.build @@ -0,0 +1,5 @@ +project('test default_options in find_program') + +dummy_exe = find_program('dummy', default_options: ['subproject_option=true']) + +test('test_dummy', dummy_exe) diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy.wrap b/test cases/common/265 default_options in find_program/subprojects/dummy.wrap new file mode 100644 index 000000000000..0c03eec4418e --- /dev/null +++ b/test cases/common/265 default_options in find_program/subprojects/dummy.wrap @@ -0,0 +1,5 @@ +[wrap-file] +directory = dummy + +[provide] +program_names = dummy \ No newline at end of file diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c b/test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c new file mode 100644 index 000000000000..a51103c3c68e --- /dev/null +++ b/test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} \ No newline at end of file diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/meson.build b/test cases/common/265 default_options in find_program/subprojects/dummy/meson.build new file mode 100644 index 000000000000..b6441307ff0d --- /dev/null +++ b/test cases/common/265 default_options in find_program/subprojects/dummy/meson.build @@ -0,0 +1,6 @@ +project('dummy', 'c') + +if get_option('subproject_option') + dummy_exe = executable('dummy', 'dummy.c') + meson.override_find_program('dummy', dummy_exe) +endif diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt b/test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt new file mode 100644 index 000000000000..c91a24af7c5d --- /dev/null +++ b/test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt @@ -0,0 +1 @@ +option('subproject_option', type: 'boolean', value: false) From e01d53b816c9fba25a068039e62d8ac9e5e2a971 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 2 Mar 2023 11:59:28 -0500 Subject: [PATCH 087/855] compiler: Add required keyword to has_* methods add the "required" keyword to the functions has_function has_type has_member has_members has_argument has_multi_arguments has_link_argument has_multi_link_argument has_function_attribute Co-authored-by: Milan Hauth --- .../required_keyword_for_has_functions.md | 19 +++ docs/yaml/objects/compiler.yaml | 43 +++++- mesonbuild/interpreter/compiler.py | 140 +++++++++++++----- .../meson.build | 67 +++++++++ .../meson_options.txt | 1 + 5 files changed, 222 insertions(+), 48 deletions(-) create mode 100644 docs/markdown/snippets/required_keyword_for_has_functions.md create mode 100644 test cases/common/262 required keyword in has functions/meson.build create mode 100644 test cases/common/262 required keyword in has functions/meson_options.txt diff --git a/docs/markdown/snippets/required_keyword_for_has_functions.md b/docs/markdown/snippets/required_keyword_for_has_functions.md new file mode 100644 index 000000000000..0752ac7fe11b --- /dev/null +++ b/docs/markdown/snippets/required_keyword_for_has_functions.md @@ -0,0 +1,19 @@ +## All compiler `has_*` methods support the `required` keyword + +Now instead of + +```meson +assert(cc.has_function('some_function')) +assert(cc.has_type('some_type')) +assert(cc.has_member('struct some_type', 'x')) +assert(cc.has_members('struct some_type', ['x', 'y'])) +``` + +we can use + +```meson +cc.has_function('some_function', required: true) +cc.has_type('some_type', required: true) +cc.has_member('struct some_type', 'x', required: true) +cc.has_members('struct some_type', ['x', 'y'], required: true) +``` diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index 4bf69c3b17c3..14b61a876c13 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -143,6 +143,19 @@ methods: When set to a [`feature`](Build-options.md#features) option, the feature will control if it is searched and whether to fail if not found. +- name: _required + returns: void + description: You have found a bug if you can see this! + kwargs: + required: + type: bool | feature + default: false + since: 1.1.0 + description: + When set to `true`, Meson will halt if the check fails. + + When set to a [`feature`](Build-options.md#features) option, the feature + will control if it is searched and whether to fail if not found. # Star of the actual functions - name: version @@ -196,7 +209,9 @@ methods: - name: has_member returns: bool description: Returns true if the type has the specified member. - kwargs_inherit: compiler._common + kwargs_inherit: + - compiler._common + - compiler._required posargs: typename: type: str @@ -208,7 +223,9 @@ methods: - name: has_members returns: bool description: Returns `true` if the type has *all* the specified members. - kwargs_inherit: compiler._common + kwargs_inherit: + - compiler._common + - compiler._required posargs: typename: type: str @@ -225,7 +242,9 @@ methods: Returns true if the given function is provided by the standard library or a library passed in with the `args` keyword. - kwargs_inherit: compiler._common + kwargs_inherit: + - compiler._common + - compiler._required posargs: funcname: type: str @@ -234,7 +253,9 @@ methods: - name: has_type returns: bool description: Returns `true` if the specified token is a type. - kwargs_inherit: compiler._common + kwargs_inherit: + - compiler._common + - compiler._required posargs: typename: type: str @@ -457,6 +478,8 @@ methods: argument: type: str description: The argument to check. + kwargs_inherit: + - compiler._required - name: has_multi_arguments since: 0.37.0 @@ -469,6 +492,8 @@ methods: name: arg type: str description: The arguments to check. + kwargs_inherit: + - compiler._required - name: get_supported_arguments returns: list[str] @@ -515,6 +540,8 @@ methods: argument: type: str description: The argument to check. + kwargs_inherit: + - compiler._required - name: has_multi_link_arguments since: 0.46.0 @@ -527,6 +554,8 @@ methods: name: arg type: str description: The link arguments to check. + kwargs_inherit: + - compiler._required - name: get_supported_link_arguments returns: list[str] @@ -556,10 +585,6 @@ methods: Given a list of strings, returns the first argument that passes the [[compiler.has_link_argument]] test or an empty array if none pass. - - - - - name: has_function_attribute returns: bool since: 0.48.0 @@ -573,6 +598,8 @@ methods: name: type: str description: The attribute name to check. + kwargs_inherit: + - compiler._required - name: get_supported_function_attributes returns: list[str] diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 52737c4e0f5b..434587427df4 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -31,6 +31,7 @@ from ..interpreterbase import TYPE_var, TYPE_kwargs from .kwargs import ExtractRequired, ExtractSearchDirs from .interpreter.interpreter import SourceOutputs + from ..mlog import TV_LoggableList from typing_extensions import TypedDict, Literal @@ -69,6 +70,12 @@ class ComputeIntKW(CommonKW): class HeaderKW(CommonKW, ExtractRequired): pass + class HasKW(CommonKW, ExtractRequired): + pass + + class HasArgumentKW(ExtractRequired): + pass + class FindLibraryKW(ExtractRequired, ExtractSearchDirs): disabler: bool @@ -165,6 +172,7 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: _COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW] _HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] +_HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.1.0', default=False) class CompilerHolder(ObjectHolder['Compiler']): preprocess_uid: T.Dict[str, itertools.count] = collections.defaultdict(itertools.count) @@ -325,9 +333,13 @@ def symbols_have_underscore_prefix_method(self, args: T.List['TYPE_var'], kwargs return self.compiler.symbols_have_underscore_prefix(self.environment) @typed_pos_args('compiler.has_member', str, str) - @typed_kwargs('compiler.has_member', *_COMMON_KWS) - def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool: + @typed_kwargs('compiler.has_member', _HAS_REQUIRED_KW, *_COMMON_KWS) + def has_member_method(self, args: T.Tuple[str, str], kwargs: 'HasKW') -> bool: typename, membername = args + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Type', mlog.bold(typename, True), 'has member', mlog.bold(membername, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'], @@ -335,7 +347,9 @@ def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool extra_args=extra_args, dependencies=deps) cached_msg = mlog.blue('(cached)') if cached else '' - if had: + if required and not had: + raise InterpreterException(f'{self.compiler.get_display_language()} member {membername!r} of type {typename!r} not usable') + elif had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') @@ -344,9 +358,14 @@ def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool return had @typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1) - @typed_kwargs('compiler.has_members', *_COMMON_KWS) - def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW') -> bool: + @typed_kwargs('compiler.has_members', _HAS_REQUIRED_KW, *_COMMON_KWS) + def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'HasKW') -> bool: typename, membernames = args + members = mlog.bold(', '.join([f'"{m}"' for m in membernames])) + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Type', mlog.bold(typename, True), 'has members', members, 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'], @@ -354,26 +373,34 @@ def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW' extra_args=extra_args, dependencies=deps) cached_msg = mlog.blue('(cached)') if cached else '' - if had: + if required and not had: + # print members as array: ['member1', 'member2'] + raise InterpreterException(f'{self.compiler.get_display_language()} members {membernames!r} of type {typename!r} not usable') + elif had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') - members = mlog.bold(', '.join([f'"{m}"' for m in membernames])) mlog.log('Checking whether type', mlog.bold(typename, True), 'has members', members, msg, hadtxt, cached_msg) return had @typed_pos_args('compiler.has_function', str) - @typed_kwargs('compiler.has_function', *_COMMON_KWS) - def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: + @typed_kwargs('compiler.has_function', _HAS_REQUIRED_KW, *_COMMON_KWS) + def has_function_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: funcname = args[0] + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Has function', mlog.bold(funcname, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment, extra_args=extra_args, dependencies=deps) cached_msg = mlog.blue('(cached)') if cached else '' - if had: + if required and not had: + raise InterpreterException(f'{self.compiler.get_display_language()} function {funcname!r} not usable') + elif had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') @@ -381,15 +408,21 @@ def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: return had @typed_pos_args('compiler.has_type', str) - @typed_kwargs('compiler.has_type', *_COMMON_KWS) - def has_type_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: + @typed_kwargs('compiler.has_type', _HAS_REQUIRED_KW, *_COMMON_KWS) + def has_type_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: typename = args[0] + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Has type', mlog.bold(typename, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment, extra_args=extra_args, dependencies=deps) cached_msg = mlog.blue('(cached)') if cached else '' - if had: + if required and not had: + raise InterpreterException(f'{self.compiler.get_display_language()} type {typename!r} not usable') + elif had: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') @@ -646,33 +679,46 @@ def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'd return lib def _has_argument_impl(self, arguments: T.Union[str, T.List[str]], - mode: _TestMode = _TestMode.COMPILER) -> bool: + mode: _TestMode = _TestMode.COMPILER, + kwargs: T.Optional['ExtractRequired'] = None) -> bool: """Shared implementation for methods checking compiler and linker arguments.""" # This simplifies the callers if isinstance(arguments, str): arguments = [arguments] - test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments - result, cached = test(arguments, self.environment) - cached_msg = mlog.blue('(cached)') if cached else '' - mlog.log( + logargs: TV_LoggableList = [ 'Compiler for', self.compiler.get_display_language(), 'supports{}'.format(' link' if mode is _TestMode.LINKER else ''), 'arguments {}:'.format(' '.join(arguments)), + ] + kwargs = kwargs or {'required': False} + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + logargs += ['skipped: feature', mlog.bold(feature), 'disabled'] + mlog.log(*logargs) + return False + test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments + result, cached = test(arguments, self.environment) + if required and not result: + logargs += ['not usable'] + raise InterpreterException(*logargs) + logargs += [ mlog.green('YES') if result else mlog.red('NO'), - cached_msg) + mlog.blue('(cached)') if cached else '', + ] + mlog.log(*logargs) return result - @noKwargs @typed_pos_args('compiler.has_argument', str) - def has_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: - return self._has_argument_impl([args[0]]) + @typed_kwargs('compiler.has_argument', _HAS_REQUIRED_KW) + def has_argument_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool: + return self._has_argument_impl([args[0]], kwargs=kwargs) - @noKwargs @typed_pos_args('compiler.has_multi_arguments', varargs=str) + @typed_kwargs('compiler.has_multi_arguments', _HAS_REQUIRED_KW) @FeatureNew('compiler.has_multi_arguments', '0.37.0') - def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool: - return self._has_argument_impl(args[0]) + def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'HasArgumentKW') -> bool: + return self._has_argument_impl(args[0], kwargs=kwargs) @FeatureNew('compiler.get_supported_arguments', '0.43.0') @typed_pos_args('compiler.get_supported_arguments', varargs=str) @@ -707,16 +753,16 @@ def first_supported_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'T return [] @FeatureNew('compiler.has_link_argument', '0.46.0') - @noKwargs @typed_pos_args('compiler.has_link_argument', str) - def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: - return self._has_argument_impl([args[0]], mode=_TestMode.LINKER) + @typed_kwargs('compiler.has_link_argument', _HAS_REQUIRED_KW) + def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool: + return self._has_argument_impl([args[0]], mode=_TestMode.LINKER, kwargs=kwargs) @FeatureNew('compiler.has_multi_link_argument', '0.46.0') - @noKwargs @typed_pos_args('compiler.has_multi_link_argument', varargs=str) - def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool: - return self._has_argument_impl(args[0], mode=_TestMode.LINKER) + @typed_kwargs('compiler.has_multi_link_argument', _HAS_REQUIRED_KW) + def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'HasArgumentKW') -> bool: + return self._has_argument_impl(args[0], mode=_TestMode.LINKER, kwargs=kwargs) @FeatureNew('compiler.get_supported_link_arguments', '0.46.0') @noKwargs @@ -739,19 +785,33 @@ def first_supported_link_argument_method(self, args: T.Tuple[T.List[str]], kwarg mlog.log('First supported link argument:', mlog.red('None')) return [] - def _has_function_attribute_impl(self, attr: str) -> bool: + def _has_function_attribute_impl(self, attr: str, kwargs: T.Optional['ExtractRequired'] = None) -> bool: """Common helper for function attribute testing.""" - result, cached = self.compiler.has_func_attribute(attr, self.environment) - cached_msg = mlog.blue('(cached)') if cached else '' - h = mlog.green('YES') if result else mlog.red('NO') - mlog.log(f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', h, cached_msg) - return result + logargs: TV_LoggableList = [ + f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', + ] + kwargs = kwargs or {'required': False} + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + logargs += ['skipped: feature', mlog.bold(feature), 'disabled'] + mlog.log(*logargs) + return False + had, cached = self.compiler.has_func_attribute(attr, self.environment) + if required and not had: + logargs += ['not usable'] + raise InterpreterException(*logargs) + logargs += [ + mlog.green('YES') if had else mlog.red('NO'), + mlog.blue('(cached)') if cached else '' + ] + mlog.log(*logargs) + return had @FeatureNew('compiler.has_function_attribute', '0.48.0') - @noKwargs @typed_pos_args('compiler.has_function_attribute', str) - def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool: - return self._has_function_attribute_impl(args[0]) + @typed_kwargs('compiler.has_function_attribute', _HAS_REQUIRED_KW) + def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool: + return self._has_function_attribute_impl(args[0], kwargs) @FeatureNew('compiler.get_supported_function_attributes', '0.48.0') @noKwargs diff --git a/test cases/common/262 required keyword in has functions/meson.build b/test cases/common/262 required keyword in has functions/meson.build new file mode 100644 index 000000000000..afd07eab1a50 --- /dev/null +++ b/test cases/common/262 required keyword in has functions/meson.build @@ -0,0 +1,67 @@ +project('required keyword in has functions', 'c') + +cc = meson.get_compiler('c') +opt = get_option('opt') + +cc.has_function('printf', prefix : '#include', required : true) +cc.has_type('time_t', prefix : '#include', required : true) +cc.has_member('struct tm', 'tm_sec', prefix : '#include', required : true) +cc.has_members('struct tm', ['tm_sec', 'tm_min'], prefix : '#include', required : true) +cc.has_header('time.h', required : true) +cc.has_header_symbol('time.h', 'time', required : true) + +assert(not cc.has_function('printf', prefix : '#include', required : opt)) +assert(not cc.has_type('time_t', prefix : '#include', required : opt)) +assert(not cc.has_member('struct tm', 'tm_sec', prefix : '#include', required : opt)) +assert(not cc.has_members('struct tm', ['tm_sec', 'tm_min'], prefix : '#include', required : opt)) +assert(not cc.has_header('time.h', required : opt)) +assert(not cc.has_header_symbol('time.h', 'time', required : opt)) + +# compiler.has_argument +if cc.get_id() == 'msvc' + is_arg = '/O2' +else + is_arg = '-O2' +endif +cc.has_argument(is_arg, required: true) +assert(not cc.has_argument(is_arg, required: opt)) + +# compiler.has_multi_arguments +if cc.get_id() == 'gcc' + pre_arg = '-Wformat' + arg = '-Werror=format-security' + cc.has_multi_arguments([pre_arg, arg], required: true) + assert(not cc.has_multi_arguments(pre_arg, arg, required: opt)) +endif + +# compiler.has_link_argument +if cc.get_argument_syntax() == 'msvc' + is_arg = '/OPT:REF' +else + is_arg = '-Wl,-L/tmp' +endif +cc.has_link_argument(is_arg, required: true) +assert(not cc.has_link_argument(is_arg, required: opt)) + +# compiler.has_function_attribute +if not ['pgi', 'msvc', 'clang-cl', 'intel-cl'].contains(cc.get_id()) + a = 'aligned' + cc.has_function_attribute(a, required: true) + assert(not cc.has_function_attribute(a, required: opt)) +endif + +testcase expect_error('''compiler.has_function keyword argument 'required' was of type str but should have been one of: bool, UserFeatureOption''') + cc.has_function('printf', required : 'not a bool') +endtestcase + +testcase expect_error('''C function 'asdfkawlegsdiovapfjhkr' not usable''') + cc.has_function('asdfkawlegsdiovapfjhkr', required : true) +endtestcase + +testcase expect_error('''C header 'asdfkawlegsdiovapfjhkr.h' not found''') + cc.has_header('asdfkawlegsdiovapfjhkr.h', required : true) +endtestcase + +testcase expect_error('''C symbol time_not_found not found in header time.h''') + cc.has_header_symbol('time.h', 'time_not_found', required : true) +endtestcase diff --git a/test cases/common/262 required keyword in has functions/meson_options.txt b/test cases/common/262 required keyword in has functions/meson_options.txt new file mode 100644 index 000000000000..53175afec478 --- /dev/null +++ b/test cases/common/262 required keyword in has functions/meson_options.txt @@ -0,0 +1 @@ +option('opt', type: 'feature', value: 'disabled') From 78337653fce90d6745d2ce46eaba9d25ab9e18d2 Mon Sep 17 00:00:00 2001 From: Milan Hauth Date: Sat, 5 Aug 2023 09:32:17 +0200 Subject: [PATCH 088/855] fixup: since: 1.1.0 -> 1.3.0 --- docs/yaml/objects/compiler.yaml | 2 +- mesonbuild/interpreter/compiler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index 14b61a876c13..3ba9c44dbcfd 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -150,7 +150,7 @@ methods: required: type: bool | feature default: false - since: 1.1.0 + since: 1.3.0 description: When set to `true`, Meson will halt if the check fails. diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 434587427df4..fe30195d53b8 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -172,7 +172,7 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: _COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW] _HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] -_HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.1.0', default=False) +_HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.3.0', default=False) class CompilerHolder(ObjectHolder['Compiler']): preprocess_uid: T.Dict[str, itertools.count] = collections.defaultdict(itertools.count) From 432317bc6bbfa594bbaf99e13ccb840db3903568 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 5 Aug 2023 11:35:56 +0100 Subject: [PATCH 089/855] tests: Pass a mock C compiler to detect_cpu(), detect_cpu_family() In some cases the desired result can be different if there are no compilers at all. The expectations here are based on there being at least one compiler, so reflect that by providing one; a later test enhancement can cover the case where there are no compilers provided. As a result of the mock any_compiler_has_define(), all that matters will be the distinction between an empty or non-empty dict: the compiler object itself is unused. Signed-off-by: Simon McVittie --- unittests/internaltests.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 86a30f8abeae..89979cd9451e 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1586,16 +1586,18 @@ def mock_trial(value: str) -> T.Iterable[None]: ('aarch64_be', 'aarch64'), ] + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): for test, expected in cases: with self.subTest(test, has_define=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu_family({}) + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) self.assertEqual(actual, expected) with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): - actual = mesonbuild.environment.detect_cpu_family({}) + actual = mesonbuild.environment.detect_cpu_family({'c': cc}) self.assertEqual(actual, expected) def test_detect_cpu(self) -> None: @@ -1623,16 +1625,18 @@ def mock_trial(value: str) -> T.Iterable[None]: ('aarch64_be', 'aarch64'), ] + cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) + with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): for test, expected in cases: with self.subTest(test, has_define=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu({}) + actual = mesonbuild.environment.detect_cpu({'c': cc}) self.assertEqual(actual, expected) with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): - actual = mesonbuild.environment.detect_cpu({}) + actual = mesonbuild.environment.detect_cpu({'c': cc}) self.assertEqual(actual, expected) def test_interpreter_unpicklable(self) -> None: From 2cf79c5062f553382b641f4ac8be897d532902aa Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 5 Aug 2023 11:13:53 +0100 Subject: [PATCH 090/855] environment: Assume that mips64 can run 32-bit mips binaries The relationship between mips64 and mips is similar to the relationship between x86_64 and x86. Representing it here is necessary so that we will not require an exe_wrapper when cross-compiling for 32-bit mips on mips64, or when a complete 32-bit mips user-space runs on a 64-bit kernel without using linux32 to alter uname(2) to pretend to be 32-bit. Signed-off-by: Simon McVittie --- mesonbuild/environment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 3ec771315e17..836963e22c7c 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -469,6 +469,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')) class Environment: From b95ebf80b85fc8ed3ba2cf828d7b96f95894a29b Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 5 Aug 2023 11:34:29 +0100 Subject: [PATCH 091/855] environment: Don't override mips64 to mips if no compilers are available If we have a build- or host-architecture compiler, we can detect mips64 vs. mips by the fact that mips64 compilers define __mips64. However, machine_info_can_run() doesn't provide any compilers, because it is interested in the architecture of the underlying kernel. If we don't return mips64 when running on a mips64 kernel, machine_info_can_run() will wrongly say that we can't run mips64 binaries. If we're running a complete 32-bit mips user-space on a mips64 kernel, it's OK to return mips64 in the absence of any compilers, as a result of the previous commit "environment: Assume that mips64 can run 32-bit mips binaries". Resolves: https://github.com/mesonbuild/meson/issues/12017 Bug-Debian: https://bugs.debian.org/1041499 Fixes: 6def03c7 "detect_cpu: Fix mips32 detection on mips64" Signed-off-by: Simon McVittie --- mesonbuild/environment.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 836963e22c7c..ab6f56ca23a0 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -343,7 +343,7 @@ def detect_cpu_family(compilers: CompilersDict) -> str: # MIPS64 is able to run MIPS32 code natively, so there is a chance that # such mixture mentioned above exists. elif trial == 'mips64': - if not any_compiler_has_define(compilers, '__mips64'): + if compilers and not any_compiler_has_define(compilers, '__mips64'): trial = 'mips' if trial not in known_cpu_families: @@ -383,7 +383,7 @@ def detect_cpu(compilers: CompilersDict) -> str: if '64' not in trial: trial = 'mips' else: - if not any_compiler_has_define(compilers, '__mips64'): + if compilers and not any_compiler_has_define(compilers, '__mips64'): trial = 'mips' else: trial = 'mips64' From 61554ad37b32001f352739382e79f8639dea3c31 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 5 Aug 2023 11:40:04 +0100 Subject: [PATCH 092/855] tests: Assert that mips64 kernel is detected as mips64 with no compilers Reproduces: https://github.com/mesonbuild/meson/issues/12017 Signed-off-by: Simon McVittie --- unittests/internaltests.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 89979cd9451e..56d36117a454 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1600,6 +1600,16 @@ def mock_trial(value: str) -> T.Iterable[None]: actual = mesonbuild.environment.detect_cpu_family({'c': cc}) self.assertEqual(actual, expected) + # machine_info_can_run calls detect_cpu_family with no compilers at all + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu_family({}) + self.assertEqual(actual, expected) + def test_detect_cpu(self) -> None: @contextlib.contextmanager @@ -1639,6 +1649,15 @@ def mock_trial(value: str) -> T.Iterable[None]: actual = mesonbuild.environment.detect_cpu({'c': cc}) self.assertEqual(actual, expected) + with mock.patch( + 'mesonbuild.environment.any_compiler_has_define', + mock.Mock(side_effect=AssertionError('Should not be called')), + ): + for test, expected in [('mips64', 'mips64')]: + with self.subTest(test, has_compiler=False), mock_trial(test): + actual = mesonbuild.environment.detect_cpu({}) + self.assertEqual(actual, expected) + def test_interpreter_unpicklable(self) -> None: build = mock.Mock() build.environment = mock.Mock() From 48c17b7ae651b5819938392502d341377cb4435a Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 3 May 2023 09:39:26 -0400 Subject: [PATCH 093/855] UserArrayOption: Remove user_input argument The only place it can be set to False is from optinterpreter. Better check value there and deprecate string usage. --- mesonbuild/compilers/compilers.py | 4 ++-- mesonbuild/coredata.py | 17 +++++------------ mesonbuild/mcompile.py | 2 +- mesonbuild/optinterpreter.py | 7 ++++++- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 7a8ae7247cfa..c7af1cac6841 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1380,11 +1380,11 @@ def get_global_options(lang: str, cargs = coredata.UserArrayOption( description + ' compiler', - comp_options, split_args=True, user_input=True, allow_dups=True) + comp_options, split_args=True, allow_dups=True) largs = coredata.UserArrayOption( description + ' linker', - link_options, split_args=True, user_input=True, allow_dups=True) + link_options, split_args=True, allow_dups=True) if comp.INVOKES_LINKER and comp_key == envkey: # If the compiler acts as a linker driver, and we're using the diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 54d9b1d02d72..975719e8908c 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -247,23 +247,16 @@ def validate_value(self, value: T.Any) -> str: class UserArrayOption(UserOption[T.List[str]]): def __init__(self, description: str, value: T.Union[str, T.List[str]], - split_args: bool = False, user_input: bool = False, + split_args: bool = False, allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING, choices: T.Optional[T.List[str]] = None, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): super().__init__(description, choices if choices is not None else [], yielding, deprecated) self.split_args = split_args self.allow_dups = allow_dups - self.value = self.validate_value(value, user_input=user_input) - - def listify(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]: - # User input is for options defined on the command line (via -D - # options). Users can put their input in as a comma separated - # string, but for defining options in meson_options.txt the format - # should match that of a combo - if not user_input and isinstance(value, str) and not value.startswith('['): - raise MesonException('Value does not define an array: ' + value) + self.set_value(value) + def listify(self, value: T.Union[str, T.List[str]]) -> T.List[str]: if isinstance(value, str): if value.startswith('['): try: @@ -283,8 +276,8 @@ def listify(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> raise MesonException(f'"{value}" should be a string array, but it is not') return newvalue - def validate_value(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]: - newvalue = self.listify(value, user_input) + def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: + newvalue = self.listify(value) if not self.allow_dups and len(set(newvalue)) != len(newvalue): msg = 'Duplicated values in array option is deprecated. ' \ diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 4e46702f04fd..950b27ca9245 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -35,7 +35,7 @@ import argparse def array_arg(value: str) -> T.List[str]: - return UserArrayOption(None, value, allow_dups=True, user_input=True).value + return UserArrayOption(None, value, allow_dups=True).value def validate_builddir(builddir: Path) -> None: if not (builddir / 'meson-private' / 'coredata.dat').is_file(): diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 8377614fe4dd..2756997f5957 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -20,7 +20,7 @@ from . import mesonlib from . import mparser from . import mlog -from .interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo +from .interpreterbase import FeatureNew, FeatureDeprecated, typed_pos_args, typed_kwargs, ContainerTypeInfo, KwargInfo from .interpreter.type_checking import NoneType, in_set_validator if T.TYPE_CHECKING: @@ -266,6 +266,11 @@ def integer_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS] def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption: choices = kwargs['choices'] value = kwargs['value'] if kwargs['value'] is not None else choices + if isinstance(value, str): + if value.startswith('['): + FeatureDeprecated('String value for array option', '1.2.0').use(self.subproject) + else: + raise mesonlib.MesonException('Value does not define an array: ' + value) return coredata.UserArrayOption(description, value, choices=choices, yielding=args[0], From 7600856e0a1b1e058ef684928ac29a92218b1257 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 3 May 2023 10:20:15 -0400 Subject: [PATCH 094/855] UserArrayOption: Make listify_value() a static method --- mesonbuild/coredata.py | 8 ++++++-- mesonbuild/mcompile.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 975719e8908c..97261d67a1a6 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -256,7 +256,8 @@ def __init__(self, description: str, value: T.Union[str, T.List[str]], self.allow_dups = allow_dups self.set_value(value) - def listify(self, value: T.Union[str, T.List[str]]) -> T.List[str]: + @staticmethod + def listify_value(value: T.Union[str, T.List[str]], shlex_split_args: bool = False) -> T.List[str]: if isinstance(value, str): if value.startswith('['): try: @@ -266,7 +267,7 @@ def listify(self, value: T.Union[str, T.List[str]]) -> T.List[str]: elif value == '': newvalue = [] else: - if self.split_args: + if shlex_split_args: newvalue = split_args(value) else: newvalue = [v.strip() for v in value.split(',')] @@ -276,6 +277,9 @@ def listify(self, value: T.Union[str, T.List[str]]) -> T.List[str]: raise MesonException(f'"{value}" should be a string array, but it is not') return newvalue + def listify(self, value: T.Any) -> T.List[T.Any]: + return self.listify_value(value, self.split_args) + def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: newvalue = self.listify(value) diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 950b27ca9245..b9bd71bd308e 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -35,7 +35,7 @@ import argparse def array_arg(value: str) -> T.List[str]: - return UserArrayOption(None, value, allow_dups=True).value + return UserArrayOption.listify_value(value) def validate_builddir(builddir: Path) -> None: if not (builddir / 'meson-private' / 'coredata.dat').is_file(): From f3b9db9e9d9025d582ecd45107f52acb3bafee8d Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Fri, 4 Aug 2023 17:59:44 +0200 Subject: [PATCH 095/855] build.py: improve BuildTarget error message Improve the error message when a build target is assigned as dependency of another build target, which allows to better pinpoint where the issue lies on. In the example that follow, modules/meson.build:294 is in a for loop creating library targets from an array of dictionary, and doesn't point to the location where interop_sw_plugin is assigned with vlc_opengl: Before: modules/meson.build:294:17: ERROR: Tried to use a build target as a dependency. You probably should put it in link_with instead. After: modules/meson.build:294:17: ERROR: Tried to use a build target vlc_opengl as a dependency of target interop_sw_plugin. You probably should put it in link_with instead. It would probably be best to directly pinpoint where the assignment was made but it's probably harder so start simple by saying what is concerned by the error. --- mesonbuild/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 16bf4121fdab..d6ca8c11ca48 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1346,8 +1346,8 @@ def add_deps(self, deps): self.process_sourcelist(dep.get_sources()) self.add_deps(dep.ext_deps) elif isinstance(dep, BuildTarget): - raise InvalidArguments('''Tried to use a build target as a dependency. -You probably should put it in link_with instead.''') + raise InvalidArguments(f'Tried to use a build target {dep.name} as a dependency of target {self.name}.\n' + 'You probably should put it in link_with instead.') else: # This is a bit of a hack. We do not want Build to know anything # about the interpreter so we can't import it and use isinstance. From 2a731cc021f4699f73fb0fd23bb0b8ce11c4c510 Mon Sep 17 00:00:00 2001 From: Sebastian Crane Date: Mon, 7 Aug 2023 11:04:12 +0100 Subject: [PATCH 096/855] docs: add missing punctuation --- docs/yaml/builtins/meson.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/yaml/builtins/meson.yaml b/docs/yaml/builtins/meson.yaml index 20c8c80150c7..0d4eacf608c0 100644 --- a/docs/yaml/builtins/meson.yaml +++ b/docs/yaml/builtins/meson.yaml @@ -233,7 +233,7 @@ methods: returns: str since: 0.58.0 description: | - Returns a string with the absolute path to the source root directory + Returns a string with the absolute path to the source root directory. This function will return the source root of the main project if called from a subproject, which is usually not what you want. It is usually preferable to use [[meson.current_source_dir]] or [[meson.project_source_root]]. From 9df16279971b48787c1db232c274054f173531df Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 12 May 2022 08:58:46 -0400 Subject: [PATCH 097/855] Compiler: Add werror kwarg to compiles(), links() and run() methods Fixes: #5399 --- docs/markdown/snippets/compile_werror.md | 5 ++ docs/yaml/objects/compiler.yaml | 11 ++++ mesonbuild/interpreter/compiler.py | 56 ++++++++++---------- test cases/common/28 try compile/meson.build | 23 ++++++++ 4 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 docs/markdown/snippets/compile_werror.md diff --git a/docs/markdown/snippets/compile_werror.md b/docs/markdown/snippets/compile_werror.md new file mode 100644 index 000000000000..e81abb8558c9 --- /dev/null +++ b/docs/markdown/snippets/compile_werror.md @@ -0,0 +1,5 @@ +## Treat warnings as error in compiler checks + +Compiler check methods `compiler.compiles()`, `compiler.links()` and `compiler.run()` +now have a new `werror: true` keyword argument to treat compiler warnings as error. +This can be used to check if code compiles without warnings. diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index 3ba9c44dbcfd..d5d7df5696b4 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -127,6 +127,7 @@ methods: - compiler._dependencies - compiler._no_builtin_args - compiler._name + - compiler._werror - name: _header returns: void @@ -157,6 +158,16 @@ methods: When set to a [`feature`](Build-options.md#features) option, the feature will control if it is searched and whether to fail if not found. +- name: _werror + returns: void + description: You have found a bug if you can see this! + kwargs: + werror: + type: bool + default: false + description: When set to `true`, compiler warnings are treated as error. + since: 1.3.0 + # Star of the actual functions - name: version returns: str diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index fe30195d53b8..0e34f6c91da3 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -45,20 +45,20 @@ class AlignmentKw(TypedDict): args: T.List[str] dependencies: T.List[dependencies.Dependency] - class CompileKW(TypedDict): - - name: str + class BaseCompileKW(TypedDict): no_builtin_args: bool include_directories: T.List[build.IncludeDirs] args: T.List[str] + + class CompileKW(BaseCompileKW): + + name: str dependencies: T.List[dependencies.Dependency] + werror: bool - class CommonKW(TypedDict): + class CommonKW(BaseCompileKW): prefix: str - no_builtin_args: bool - include_directories: T.List[build.IncludeDirs] - args: T.List[str] dependencies: T.List[dependencies.Dependency] class ComputeIntKW(CommonKW): @@ -163,13 +163,15 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: _NO_BUILTIN_ARGS_KW = KwargInfo('no_builtin_args', bool, default=False) _NAME_KW = KwargInfo('name', str, default='') +_WERROR_KW = KwargInfo('werror', bool, default=False, since='1.3.0') # Many of the compiler methods take this kwarg signature exactly, this allows # simplifying the `typed_kwargs` calls _COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _PREFIX_KW, _NO_BUILTIN_ARGS_KW] # Common methods of compiles, links, runs, and similar -_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW] +_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW, + _WERROR_KW] _HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] _HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.3.0', default=False) @@ -251,20 +253,20 @@ def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]: return self.compiler.exelist - def _determine_args(self, nobuiltins: bool, - incdirs: T.List[build.IncludeDirs], - extra_args: T.List[str], + def _determine_args(self, kwargs: BaseCompileKW, mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]: args: T.List[str] = [] - for i in incdirs: + for i in kwargs['include_directories']: for idir in i.to_string_list(self.environment.get_source_dir()): args.extend(self.compiler.get_include_args(idir, False)) - if not nobuiltins: + if not kwargs['no_builtin_args']: opts = self.environment.coredata.options args += self.compiler.get_option_compile_args(opts) if mode is CompileCheckMode.LINK: args.extend(self.compiler.get_option_link_args(opts)) - args.extend(extra_args) + if kwargs.get('werror', False): + args.extend(self.compiler.get_werror_args()) + args.extend(kwargs['args']) return args def _determine_dependencies(self, deps: T.List['dependencies.Dependency'], compile_only: bool = False, endl: str = ':') -> T.Tuple[T.List['dependencies.Dependency'], str]: @@ -298,7 +300,7 @@ def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW' code = mesonlib.File.from_absolute_file( code.rel_to_builddir(self.environment.source_dir)) testname = kwargs['name'] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False, endl=None) result = self.compiler.run(code, self.environment, extra_args=extra_args, dependencies=deps) @@ -340,7 +342,7 @@ def has_member_method(self, args: T.Tuple[str, str], kwargs: 'HasKW') -> bool: if disabled: mlog.log('Type', mlog.bold(typename, True), 'has member', mlog.bold(membername, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'], self.environment, @@ -366,7 +368,7 @@ def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'HasKW') - if disabled: mlog.log('Type', mlog.bold(typename, True), 'has members', members, 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'], self.environment, @@ -392,7 +394,7 @@ def has_function_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: if disabled: mlog.log('Has function', mlog.bold(funcname, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = self._determine_args(kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment, extra_args=extra_args, @@ -415,7 +417,7 @@ def has_type_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: if disabled: mlog.log('Has type', mlog.bold(typename, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment, extra_args=extra_args, dependencies=deps) @@ -440,7 +442,7 @@ def has_type_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: ) def compute_int_method(self, args: T.Tuple[str], kwargs: 'ComputeIntKW') -> int: expression = args[0] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) res = self.compiler.compute_int(expression, kwargs['low'], kwargs['high'], kwargs['guess'], kwargs['prefix'], @@ -453,7 +455,7 @@ def compute_int_method(self, args: T.Tuple[str], kwargs: 'ComputeIntKW') -> int: @typed_kwargs('compiler.sizeof', *_COMMON_KWS) def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int: element = args[0] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross) esize, cached = self.compiler.sizeof(element, kwargs['prefix'], self.environment, extra_args=extra_args, dependencies=deps) @@ -467,7 +469,7 @@ def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int: @typed_kwargs('compiler.get_define', *_COMMON_KWS) def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str: element = args[0] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) value, cached = self.compiler.get_define(element, kwargs['prefix'], self.environment, extra_args=extra_args, @@ -488,7 +490,7 @@ def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'Compi code = mesonlib.File.from_absolute_file( code.absolute_path(self.environment.source_dir, self.environment.build_dir)) testname = kwargs['name'] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None) result, cached = self.compiler.compiles(code, self.environment, extra_args=extra_args, @@ -527,7 +529,7 @@ def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileK compiler = clist[SUFFIX_TO_LANG[suffix]] testname = kwargs['name'] - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) result, cached = self.compiler.links(code, self.environment, compiler=compiler, @@ -551,7 +553,7 @@ def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool: if disabled: mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) haz, cached = self.compiler.check_header(hname, kwargs['prefix'], self.environment, extra_args=extra_args, @@ -571,7 +573,7 @@ def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool: if disabled: mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) haz, cached = self.compiler.has_header(hname, kwargs['prefix'], self.environment, extra_args=extra_args, dependencies=deps) @@ -598,7 +600,7 @@ def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') if disabled: mlog.log('Header', mlog.bold(hname, True), 'has symbol', mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled') return False - extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args']) + extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) haz, cached = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment, extra_args=extra_args, diff --git a/test cases/common/28 try compile/meson.build b/test cases/common/28 try compile/meson.build index 3480d1d89555..83cd29e87f89 100644 --- a/test cases/common/28 try compile/meson.build +++ b/test cases/common/28 try compile/meson.build @@ -8,6 +8,10 @@ breakcode = '''#include void func(void) { printf("This won't work.\n"); } ''' +warncode = '''#warning This is a warning +int main(void) { return 0; } +''' + foreach lang : ['c', 'cpp'] compiler = meson.get_compiler(lang) @@ -31,4 +35,23 @@ foreach lang : ['c', 'cpp'] if compiler.compiles(files('invalid.c'), name : 'file should fail') error('Compiler ' + compiler.get_id() + ' returned true on broken code.') endif + + # MSVC does not support #warning instruction + if compiler.get_id() != 'msvc' + # First check that all tests pass without werror, then check they fail with it. + foreach with_werror : [false, true] + expect_success = not with_werror + assert(compiler.compiles(warncode, + name: f'code with warning compiles with werror=@with_werror@', + werror: with_werror) == expect_success) + assert(compiler.links(warncode, + name: f'code with warning links with werror=@with_werror@', + werror: with_werror) == expect_success) + if meson.can_run_host_binaries() + assert((compiler.run(warncode, + name: f'code with warning runs with werror=@with_werror@', + werror: with_werror).returncode() == 0) == expect_success) + endif + endforeach + endif endforeach From 82a8c72187f844713618526ed3890d7b313b2065 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 28 Apr 2022 16:08:24 -0400 Subject: [PATCH 098/855] c_std, cpp_std: Change to a list of desired versions in preference order Projects that prefer GNU C but can fallback to ISO C can now set for example `default_options: 'c_std=gnu11,c11'` and it will use gnu11 when available, fallback to c11 otherwise. It is an error only if none of the values are supported by the current compiler. This allows to deprecate gnuXX values from MSVC compiler, that means that `default_options: 'c_std=gnu11'` will now print warning with MSVC but still fallback to 'c11' value. No warning is printed if at least one of the values is valid, i.e. `default_options: 'c_std=gnu11,c11'`. In the future that deprecation warning will become an hard error because `c_std=gnu11` should mean GNU is required, for projects that cannot be built with MSVC for example. --- docs/markdown/Builtin-options.md | 15 +++ docs/markdown/snippets/cstd.md | 18 ++++ mesonbuild/compilers/c.py | 114 ++++++++++----------- mesonbuild/compilers/cpp.py | 76 +++++++------- mesonbuild/coredata.py | 53 ++++++++++ mesonbuild/optinterpreter.py | 2 +- test cases/unit/114 c cpp stds/meson.build | 6 ++ unittests/allplatformstests.py | 33 ++++++ unittests/baseplatformtests.py | 7 ++ 9 files changed, 229 insertions(+), 95 deletions(-) create mode 100644 docs/markdown/snippets/cstd.md create mode 100644 test cases/unit/114 c cpp stds/meson.build diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index fed893e104c7..cd86e22b71b0 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -296,6 +296,21 @@ is inherited from the main project. This is useful, for example, when the main project requires C++11, but a subproject requires C++14. The `cpp_std` value from the subproject's `default_options` is now respected. +Since *1.3.0* `c_std` and `cpp_std` options now accept a list of values. +Projects that prefer GNU C, but can fallback to ISO C, can now set, for +example, `default_options: 'c_std=gnu11,c11'`, and it will use `gnu11` when +available, but fallback to c11 otherwise. It is an error only if none of the +values are supported by the current compiler. +Likewise, a project that can take benefit of `c++17` but can still build with +`c++11` can set `default_options: 'cpp_std=c++17,c++11'`. +This allows us to deprecate `gnuXX` values from the MSVC compiler. That means +that `default_options: 'c_std=gnu11'` will now print a warning with MSVC +but fallback to `c11`. No warning is printed if at least one +of the values is valid, i.e. `default_options: 'c_std=gnu11,c11'`. +In the future that deprecation warning will become an hard error because +`c_std=gnu11` should mean GNU is required, for projects that cannot be +built with MSVC for example. + ## Specifying options per machine Since *0.51.0*, some options are specified per machine rather than diff --git a/docs/markdown/snippets/cstd.md b/docs/markdown/snippets/cstd.md new file mode 100644 index 000000000000..cc1f08318745 --- /dev/null +++ b/docs/markdown/snippets/cstd.md @@ -0,0 +1,18 @@ +## `c_std` and `cpp_std` options now accepts a list of values + +Projects that prefer GNU C, but can fallback to ISO C, can now set, for +example, `default_options: 'c_std=gnu11,c11'`, and it will use `gnu11` when +available, but fallback to `c11` otherwise. It is an error only if none of the +values are supported by the current compiler. + +Likewise, a project that can take benefit of `c++17` but can still build with +`c++11` can set `default_options: 'cpp_std=c++17,c++11'`. + +This allows us to deprecate `gnuXX` values from the MSVC compiler. That means +that `default_options: 'c_std=gnu11'` will now print a warning with MSVC +but fallback to `c11`. No warning is printed if at least one +of the values is valid, i.e. `default_options: 'c_std=gnu11,c11'`. + +In the future that deprecation warning will become an hard error because +`c_std=gnu11` should mean GNU is required, for projects that cannot be +built with MSVC for example. diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index d514650de71f..7f9e5844c09a 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -56,6 +56,10 @@ else: CompilerMixinBase = object +_ALL_STDS = ['c89', 'c9x', 'c90', 'c99', 'c1x', 'c11', 'c17', 'c18', 'c2x'] +_ALL_STDS += [f'gnu{std[1:]}' for std in _ALL_STDS] +_ALL_STDS += ['iso9899:1990', 'iso9899:199409', 'iso9899:1999', 'iso9899:2011', 'iso9899:2017', 'iso9899:2018'] + class CCompiler(CLikeCompiler, Compiler): def attribute_check_func(self, name: str) -> str: @@ -101,12 +105,9 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str, def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() + key = OptionKey('std', machine=self.for_machine, lang=self.language) opts.update({ - OptionKey('std', machine=self.for_machine, lang=self.language): coredata.UserComboOption( - 'C language standard to use', - ['none'], - 'none', - ) + key: coredata.UserStdOption('C', _ALL_STDS), }) return opts @@ -125,20 +126,18 @@ class _ClangCStds(CompilerMixinBase): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - c_stds = ['c89', 'c99', 'c11'] - g_stds = ['gnu89', 'gnu99', 'gnu11'] + stds = ['c89', 'c99', 'c11'] # https://releases.llvm.org/6.0.0/tools/clang/docs/ReleaseNotes.html # https://en.wikipedia.org/wiki/Xcode#Latest_versions if version_compare(self.version, self._C17_VERSION): - c_stds += ['c17'] - g_stds += ['gnu17'] + stds += ['c17'] if version_compare(self.version, self._C18_VERSION): - c_stds += ['c18'] - g_stds += ['gnu18'] + stds += ['c18'] if version_compare(self.version, self._C2X_VERSION): - c_stds += ['c2x'] - g_stds += ['gnu2x'] - opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds + stds += ['c2x'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(stds, gnu=True) return opts @@ -244,8 +243,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c90', 'c99', 'c11'], gnu=True) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -285,16 +285,15 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - c_stds = ['c89', 'c99', 'c11'] - g_stds = ['gnu89', 'gnu99', 'gnu11'] + stds = ['c89', 'c99', 'c11'] if version_compare(self.version, self._C18_VERSION): - c_stds += ['c17', 'c18'] - g_stds += ['gnu17', 'gnu18'] + stds += ['c17', 'c18'] if version_compare(self.version, self._C2X_VERSION): - c_stds += ['c2x'] - g_stds += ['gnu2x'] + stds += ['c2x'] key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none'] + c_stds + g_stds + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(stds, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): opts.update({ key.evolve('winlibs'): coredata.UserArrayOption( @@ -370,7 +369,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': stds += ['c90', 'c1x', 'gnu90', 'gnu1x', 'iso9899:2011'] if version_compare(self.version, '>=1.26.00'): stds += ['c17', 'c18', 'iso9899:2017', 'iso9899:2018', 'gnu17', 'gnu18'] - opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + stds + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(stds) return opts # Elbrus C compiler does not have lchmod, but there is only linker warning, not compiler error. @@ -404,11 +405,12 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - c_stds = ['c89', 'c99'] - g_stds = ['gnu89', 'gnu99'] + stds = ['c89', 'c99'] if version_compare(self.version, '>=16.0.0'): - c_stds += ['c11'] - opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds + stds += ['c11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(stds, gnu=True) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -465,33 +467,23 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - c_stds = ['c89', 'c99'] - # Need to have these to be compatible with projects - # that set c_std to e.g. gnu99. - # https://github.com/mesonbuild/meson/issues/7611 - g_stds = ['gnu89', 'gnu90', 'gnu9x', 'gnu99'] + stds = ['c89', 'c99'] if version_compare(self.version, self._C11_VERSION): - c_stds += ['c11'] - g_stds += ['gnu1x', 'gnu11'] + stds += ['c11'] if version_compare(self.version, self._C17_VERSION): - c_stds += ['c17', 'c18'] - g_stds += ['gnu17', 'gnu18'] - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none'] + c_stds + g_stds + stds += ['c17', 'c18'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(stds, gnu=True, gnu_deprecated=True) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = [] std = options[OptionKey('std', machine=self.for_machine, lang=self.language)] - if std.value.startswith('gnu'): - mlog.log( - 'cl.exe does not actually support gnu standards, and meson ' - 'will instead demote to the nearest ISO C standard. This ' - 'may cause compilation to fail.', once=True) # As of MVSC 16.8, /std:c11 and /std:c17 are the only valid C standard options. - if std.value in {'c11', 'gnu1x', 'gnu11'}: + if std.value in {'c11'}: args.append('/std:c11') - elif std.value in {'c17', 'c18', 'gnu17', 'gnu18'}: + elif std.value in {'c17', 'c18'}: args.append('/std:c17') return args @@ -531,8 +523,9 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99', 'c11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99', 'c11']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -564,8 +557,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99', 'c11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99', 'c11']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -593,8 +587,9 @@ def get_always_args(self) -> T.List[str]: def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99']) return opts def get_no_stdinc_args(self) -> T.List[str]: @@ -640,8 +635,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99'], gnu=True) return opts def get_no_stdinc_args(self) -> T.List[str]: @@ -685,8 +681,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -722,8 +719,9 @@ def get_always_args(self) -> T.List[str]: def get_options(self) -> 'MutableKeyedOptionDictType': opts = CCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c89', 'c99', 'c11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c89', 'c99', 'c11']) return opts def get_no_stdinc_args(self) -> T.List[str]: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 8c8043763740..3e96682621d1 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -55,6 +55,10 @@ else: CompilerMixinBase = object +_ALL_STDS = ['c++98', 'c++0x', 'c++03', 'c++1y', 'c++1z', 'c++11', 'c++14', 'c++17', 'c++2a', 'c++20', 'c++23'] +_ALL_STDS += [f'gnu{std[1:]}' for std in _ALL_STDS] +_ALL_STDS += ['vc++11', 'vc++14', 'vc++17', 'vc++20', 'vc++latest', 'c++latest'] + def non_msvc_eh_options(eh: str, args: T.List[str]) -> None: if eh == 'none': @@ -178,11 +182,7 @@ def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() key = OptionKey('std', machine=self.for_machine, lang=self.language) opts.update({ - key: coredata.UserComboOption( - 'C++ language standard to use', - ['none'], - 'none', - ), + key: coredata.UserStdOption('C++', _ALL_STDS), }) return opts @@ -257,17 +257,15 @@ def get_options(self) -> 'MutableKeyedOptionDictType': key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), }) cppstd_choices = [ - 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', - 'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z', - 'gnu++2a', 'gnu++20', + 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20', ] if version_compare(self.version, self._CPP23_VERSION): cppstd_choices.append('c++23') - cppstd_choices.append('gnu++23') if version_compare(self.version, self._CPP26_VERSION): cppstd_choices.append('c++26') - cppstd_choices.append('gnu++26') - opts[key.evolve('std')].choices = cppstd_choices + std_opt = opts[key.evolve('std')] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(cppstd_choices, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): opts.update({ key.evolve('winlibs'): coredata.UserArrayOption( @@ -371,10 +369,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': 'default', ), }) - opts[key].choices = [ - 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98', - 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', - ] + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c++98', 'c++03', 'c++11', 'c++14', 'c++17'], gnu=True) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -426,17 +423,16 @@ def get_options(self) -> 'MutableKeyedOptionDictType': ) }) cppstd_choices = [ - 'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', - 'c++2a', 'c++20', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17', - 'gnu++1z', 'gnu++2a', 'gnu++20', + 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', + 'c++2a', 'c++20', ] if version_compare(self.version, '>=12.2.0'): cppstd_choices.append('c++23') - cppstd_choices.append('gnu++23') if version_compare(self.version, '>=14.0.0'): cppstd_choices.append('c++26') - cppstd_choices.append('gnu++26') - opts[key].choices = cppstd_choices + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(cppstd_choices, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): opts.update({ key.evolve('winlibs'): coredata.UserArrayOption( @@ -513,21 +509,21 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) - cpp_stds = ['none', 'c++98', 'gnu++98'] + cpp_stds = ['c++98'] if version_compare(self.version, '>=1.20.00'): - cpp_stds += ['c++03', 'c++0x', 'c++11', 'gnu++03', 'gnu++0x', 'gnu++11'] + cpp_stds += ['c++03', 'c++0x', 'c++11'] if version_compare(self.version, '>=1.21.00') and version_compare(self.version, '<1.22.00'): - cpp_stds += ['c++14', 'gnu++14', 'c++1y', 'gnu++1y'] + cpp_stds += ['c++14', 'c++1y'] if version_compare(self.version, '>=1.22.00'): - cpp_stds += ['c++14', 'gnu++14'] + cpp_stds += ['c++14'] if version_compare(self.version, '>=1.23.00'): - cpp_stds += ['c++1y', 'gnu++1y'] + cpp_stds += ['c++1y'] if version_compare(self.version, '>=1.24.00'): - cpp_stds += ['c++1z', 'c++17', 'gnu++1z', 'gnu++17'] + cpp_stds += ['c++1z', 'c++17'] if version_compare(self.version, '>=1.25.00'): - cpp_stds += ['c++2a', 'gnu++2a'] + cpp_stds += ['c++2a'] if version_compare(self.version, '>=1.26.00'): - cpp_stds += ['c++20', 'gnu++20'] + cpp_stds += ['c++20'] key = OptionKey('std', machine=self.for_machine, lang=self.language) opts.update({ @@ -541,7 +537,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': False, ), }) - opts[key].choices = cpp_stds + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(cpp_stds, gnu=True) return opts # Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error. @@ -615,7 +613,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False), }) - opts[key].choices = ['none'] + c_stds + g_stds + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(c_stds + g_stds) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -682,7 +682,9 @@ def _get_options_impl(self, opts: 'MutableKeyedOptionDictType', cpp_stds: T.List msvc_winlibs, ), }) - opts[key.evolve('std')].choices = cpp_stds + std_opt = opts[key] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(cpp_stds) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -846,8 +848,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c++03', 'c++11'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c++03', 'c++11']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -906,8 +909,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts[key].choices = ['none', 'c++03'] + std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] + assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' + std_opt.set_versions(['c++03']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 97261d67a1a6..11848664ad5e 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -320,6 +320,59 @@ def is_disabled(self) -> bool: def is_auto(self) -> bool: return self.value == 'auto' +class UserStdOption(UserComboOption): + ''' + UserOption specific to c_std and cpp_std options. User can set a list of + STDs in preference order and it selects the first one supported by current + compiler. + + For historical reasons, some compilers (msvc) allowed setting a GNU std and + silently fell back to C std. This is now deprecated. Projects that support + both GNU and MSVC compilers should set e.g. c_std=gnu11,c11. + + This is not using self.deprecated mechanism we already have for project + options because we want to print a warning if ALL values are deprecated, not + if SOME values are deprecated. + ''' + def __init__(self, lang: str, all_stds: T.List[str]) -> None: + self.lang = lang.lower() + self.all_stds = ['none'] + all_stds + # Map a deprecated std to its replacement. e.g. gnu11 -> c11. + self.deprecated_stds: T.Dict[str, str] = {} + super().__init__(f'{lang} language standard to use', ['none'], 'none') + + def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None: + assert all(std in self.all_stds for std in versions) + self.choices += versions + if gnu: + gnu_stds_map = {f'gnu{std[1:]}': std for std in versions} + if gnu_deprecated: + self.deprecated_stds.update(gnu_stds_map) + else: + self.choices += gnu_stds_map.keys() + + def validate_value(self, value: T.Union[str, T.List[str]]) -> str: + candidates = UserArrayOption.listify_value(value) + unknown = [std for std in candidates if std not in self.all_stds] + if unknown: + raise MesonException(f'Unknown {self.lang.upper()} std {unknown}. Possible values are {self.all_stds}.') + # Check first if any of the candidates are not deprecated + for std in candidates: + if std in self.choices: + return std + # Fallback to a deprecated std if any + for std in candidates: + newstd = self.deprecated_stds.get(std) + if newstd is not None: + mlog.deprecation( + f'None of the values {candidates} are supported by the {self.lang} compiler.\n' + + f'However, the deprecated {std} std currently falls back to {newstd}.\n' + + 'This will be an error in the future.\n' + + 'If the project supports both GNU and MSVC compilers, a value such as\n' + + '"c_std=gnu11,c11" specifies that GNU is prefered but it can safely fallback to plain c11.') + return newstd + raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' + + f'Possible values are {self.choices}') class DependencyCacheType(enum.Enum): diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 2756997f5957..8ad84aaa8331 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -268,7 +268,7 @@ def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ value = kwargs['value'] if kwargs['value'] is not None else choices if isinstance(value, str): if value.startswith('['): - FeatureDeprecated('String value for array option', '1.2.0').use(self.subproject) + FeatureDeprecated('String value for array option', '1.3.0').use(self.subproject) else: raise mesonlib.MesonException('Value does not define an array: ' + value) return coredata.UserArrayOption(description, value, diff --git a/test cases/unit/114 c cpp stds/meson.build b/test cases/unit/114 c cpp stds/meson.build new file mode 100644 index 000000000000..0b15efc08d27 --- /dev/null +++ b/test cases/unit/114 c cpp stds/meson.build @@ -0,0 +1,6 @@ +project('c cpp stds', 'c', 'cpp', + default_options: [ + 'c_std=gnu89,c89', + 'cpp_std=gnu++98,vc++11', + ], +) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 7f38d4b09904..1a34f5dd5c91 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -4776,3 +4776,36 @@ def test_configure_same_noop(self): self.assertNotEqual(olddata, newdata) olddata = newdata oldmtime = newmtime + + def test_c_cpp_stds(self): + testdir = os.path.join(self.unit_test_dir, '114 c cpp stds') + self.init(testdir) + # Invalid values should fail whatever compiler we have + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dc_std=invalid') + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dc_std=c89,invalid') + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dc_std=c++11') + env = get_fake_env() + cc = detect_c_compiler(env, MachineChoice.HOST) + if cc.get_id() == 'msvc': + # default_option should have selected those + self.assertEqual(self.getconf('c_std'), 'c89') + self.assertEqual(self.getconf('cpp_std'), 'vc++11') + # This is deprecated but works for C + self.setconf('-Dc_std=gnu99') + self.assertEqual(self.getconf('c_std'), 'c99') + # C++ however never accepted that fallback + with self.assertRaises(subprocess.CalledProcessError): + self.setconf('-Dcpp_std=gnu++11') + # The first supported std should be selected + self.setconf('-Dcpp_std=gnu++11,vc++11,c++11') + self.assertEqual(self.getconf('cpp_std'), 'vc++11') + elif cc.get_id() == 'gcc': + # default_option should have selected those + self.assertEqual(self.getconf('c_std'), 'gnu89') + self.assertEqual(self.getconf('cpp_std'), 'gnu++98') + # The first supported std should be selected + self.setconf('-Dcpp_std=c++11,gnu++11,vc++11') + self.assertEqual(self.getconf('cpp_std'), 'c++11') diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 3008eb731850..b7deda5e01e0 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -303,6 +303,13 @@ def setconf(self, arg, will_build=True): ensure_backend_detects_changes(self.backend) self._run(self.mconf_command + arg + [self.builddir]) + def getconf(self, optname: str): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == optname: + return x.get('value') + self.fail(f'Option {optname} not found') + def wipe(self): windows_proof_rmtree(self.builddir) From 926c3a69195385bd5c16acd269f4dae5322e0c03 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 18 Jul 2023 21:20:32 -0400 Subject: [PATCH 099/855] Error when an installed static library links to internal custom target When an installed static library A links to an internal static library B built using a custom_target(), raise an error instead of a warning. This is because to be usable, A needs to contain B which would require to extract the archive to get its objects files. This used to work, but was printing a warning and was installing a broken static library, because we used to overlink in many cases, and that got fixed in Meson 1.2.0. It now fails at link time with symbols from the custom target not being defined. It's better to turn the warning into a hard error at configure time. While at it, noticed this situation can happen for any internal custom or rust target we link to, recursively. get_internal_static_libraries_recurse() could be called on CustomTarget objects which do not implement it, and even if we did not call that method, it would still fail when trying to call extract_all_objects() on it. Fixes: #12006 --- mesonbuild/build.py | 59 ++++++++++--------- test cases/rust/5 polyglot static/meson.build | 2 +- .../unit/113 complex link cases/meson.build | 51 ++++++++++++++++ unittests/linuxliketests.py | 3 + 4 files changed, 86 insertions(+), 29 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d6ca8c11ca48..a0a38d0ac4a7 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1380,17 +1380,6 @@ def is_internal(self) -> bool: def link(self, targets): for t in targets: - if isinstance(self, StaticLibrary) and self.install: - if isinstance(t, (CustomTarget, CustomTargetIndex)): - if not t.should_install(): - mlog.warning(f'Try to link an installed static library target {self.name} with a' - 'custom target that is not installed, this might cause problems' - 'when you try to use this static library') - elif t.is_internal(): - # When we're a static library and we link_with to an - # internal/convenience library, promote to link_whole. - self.link_whole([t]) - continue if not isinstance(t, (Target, CustomTargetIndex)): if isinstance(t, dependencies.ExternalLibrary): raise MesonException(textwrap.dedent('''\ @@ -1403,6 +1392,11 @@ def link(self, targets): raise InvalidArguments(f'{t!r} is not a target.') if not t.is_linkable_target(): raise InvalidArguments(f"Link target '{t!s}' is not linkable.") + if isinstance(self, StaticLibrary) and self.install and t.is_internal(): + # When we're a static library and we link_with to an + # internal/convenience library, promote to link_whole. + self.link_whole([t], promoted=True) + continue if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic: msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." @@ -1415,7 +1409,7 @@ def link(self, targets): mlog.warning(msg + ' This will fail in cross build.') self.link_targets.append(t) - def link_whole(self, targets): + def link_whole(self, targets, promoted: bool = False): for t in targets: if isinstance(t, (CustomTarget, CustomTargetIndex)): if not t.is_linkable_target(): @@ -1435,40 +1429,49 @@ def link_whole(self, targets): else: mlog.warning(msg + ' This will fail in cross build.') if isinstance(self, StaticLibrary) and not self.uses_rust(): - if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): - # There are cases we cannot do this, however. In Rust, for - # example, this can't be done with Rust ABI libraries, though - # it could be done with C ABI libraries, though there are - # several meson issues that need to be fixed: - # https://github.com/mesonbuild/meson/issues/10722 - # https://github.com/mesonbuild/meson/issues/10723 - # https://github.com/mesonbuild/meson/issues/10724 - # FIXME: We could extract the .a archive to get object files - raise InvalidArguments('Cannot link_whole a custom or Rust target into a static library') # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. + self.check_can_extract_objects(t, origin=self, promoted=promoted) self.objects += [t.extract_all_objects()] # If we install this static library we also need to include objects # from all uninstalled static libraries it depends on. if self.install: - for lib in t.get_internal_static_libraries(): + for lib in t.get_internal_static_libraries(origin=self): self.objects += [lib.extract_all_objects()] self.link_whole_targets.append(t) @lru_cache(maxsize=None) - def get_internal_static_libraries(self) -> OrderedSet[Target]: + def get_internal_static_libraries(self, origin: StaticLibrary) -> OrderedSet[Target]: result: OrderedSet[Target] = OrderedSet() - self.get_internal_static_libraries_recurse(result) + self.get_internal_static_libraries_recurse(result, origin) return result - def get_internal_static_libraries_recurse(self, result: OrderedSet[Target]) -> None: + def get_internal_static_libraries_recurse(self, result: OrderedSet[Target], origin: StaticLibrary) -> None: for t in self.link_targets: if t.is_internal() and t not in result: + self.check_can_extract_objects(t, origin, promoted=True) result.add(t) - t.get_internal_static_libraries_recurse(result) + t.get_internal_static_libraries_recurse(result, origin) for t in self.link_whole_targets: if t.is_internal(): - t.get_internal_static_libraries_recurse(result) + t.get_internal_static_libraries_recurse(result, origin) + + def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origin: StaticLibrary, promoted: bool = False) -> None: + if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): + # To extract objects from a custom target we would have to extract + # the archive, WIP implementation can be found in + # https://github.com/mesonbuild/meson/pull/9218. + # For Rust C ABI we could in theory have access to objects, but there + # are several meson issues that need to be fixed: + # https://github.com/mesonbuild/meson/issues/10722 + # https://github.com/mesonbuild/meson/issues/10723 + # https://github.com/mesonbuild/meson/issues/10724 + m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {origin.name!r}. ' + 'Instead, pass individual object files with the "objects:" keyword argument if possible.') + if promoted: + m += (f' Meson had to promote link to link_whole because {origin.name!r} is installed but not {t.name!r},' + f' and thus has to include objects from {t.name!r} to be usable.') + raise InvalidArguments(m) def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: diff --git a/test cases/rust/5 polyglot static/meson.build b/test cases/rust/5 polyglot static/meson.build index 5d1f02368c20..54f383cd3872 100644 --- a/test cases/rust/5 polyglot static/meson.build +++ b/test cases/rust/5 polyglot static/meson.build @@ -7,7 +7,7 @@ r = static_library('stuff', 'stuff.rs', rust_crate_type : 'staticlib') # as it would do with C libraries, but then cannot extract objects from stuff and # thus should error out. # FIXME: We should support this use-case in the future. -testcase expect_error('Cannot link_whole a custom or Rust target into a static library') +testcase expect_error('Cannot link_whole a custom or Rust target \'stuff\' into a static library \'clib\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'clib\' is installed but not \'stuff\', and thus has to include objects from \'stuff\' to be usable.') l = static_library('clib', 'clib.c', link_with : r, install : true) endtestcase diff --git a/test cases/unit/113 complex link cases/meson.build b/test cases/unit/113 complex link cases/meson.build index 04e6281775d5..3b4b898df748 100644 --- a/test cases/unit/113 complex link cases/meson.build +++ b/test cases/unit/113 complex link cases/meson.build @@ -1,5 +1,7 @@ project('complex link cases', 'c') +cc = meson.get_compiler('c') + # In all tests, e1 uses s3 which uses s2 which uses s1. # Executable links with s3 and s1 but not s2 because it is included in s3. @@ -58,3 +60,52 @@ e = executable('t8-e1', 'main.c', link_with: [s1, s2], dependencies: declare_dependency(link_with: s3), ) + +if cc.get_argument_syntax() == 'gcc' + # s1 is an internal static library, using custom target. + s1_o = custom_target( + input: 's1.c', + output: 's1.c.o', + command: [cc.cmd_array(), '-c', '-o', '@OUTPUT@', '@INPUT@'] + ) + s1 = custom_target( + output: 'libt9-s1.a', + command: ['ar', 'rcs', '@OUTPUT@', s1_o], + ) + + # Executable needs to link with s1, s2 and s3. + s2 = static_library('t9-s2', 's2.c', link_with: s1) + s3 = static_library('t9-s3', 's3.c', link_with: s2) + e = executable('t9-e1', 'main.c', link_with: s3) + + # s2 cannot be installed because s1 is not being installed and Meson cannot + # extract object files from the custom target. + testcase expect_error('Cannot link_whole a custom or Rust target \'libt9-s1.a\' into a static library \'t10-s2\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'t10-s2\' is installed but not \'libt9-s1.a\', and thus has to include objects from \'libt9-s1.a\' to be usable.') + s2 = static_library('t10-s2', 's2.c', link_with: s1, install: true) + endtestcase + + # s3 cannot be installed because s1 is not being installed and Meson cannot + # extract object files from the custom target. + testcase expect_error('Cannot link_whole a custom or Rust target \'libt9-s1.a\' into a static library \'t11-s3\'. Instead, pass individual object files with the "objects:" keyword argument if possible. Meson had to promote link to link_whole because \'t11-s3\' is installed but not \'libt9-s1.a\', and thus has to include objects from \'libt9-s1.a\' to be usable.') + s2 = static_library('t11-s2', 's2.c', link_with: s1) + s3 = static_library('t11-s3', 's3.c', link_with: s2, install: true) + endtestcase + + # s1 is an installed static library, using custom target. + s1 = custom_target( + output: 'libt12-s1.a', + command: ['ar', 'rcs', '@OUTPUT@', s1_o], + install: true, + install_dir: get_option('libdir'), + ) + + # Executable needs to link with s1, s2 and s3. + s2 = static_library('t12-s2', 's2.c', link_with: s1, install: true) + s3 = static_library('t12-s3', 's3.c', link_with: s2) + e = executable('t12-e1', 'main.c', link_with: s3) + + # Executable links with s3 and s1 but not s2 because it is included in s3. + s2 = static_library('t13-s2', 's2.c', link_with: s1) + s3 = static_library('t13-s3', 's3.c', link_with: s2, install: true) + e = executable('t13-e1', 'main.c', link_with: s3) +endif diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index bd73857e960f..2de4dbcf0d25 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -1863,3 +1863,6 @@ def test_complex_link_cases(self): self.assertIn('build t6-e1: c_LINKER t6-e1.p/main.c.o | libt6-s2.a libt6-s3.a\n', content) self.assertIn('build t7-e1: c_LINKER t7-e1.p/main.c.o | libt7-s3.a\n', content) self.assertIn('build t8-e1: c_LINKER t8-e1.p/main.c.o | libt8-s1.a libt8-s2.a libt8-s3.a\n', content) + self.assertIn('build t9-e1: c_LINKER t9-e1.p/main.c.o | libt9-s1.a libt9-s2.a libt9-s3.a\n', content) + self.assertIn('build t12-e1: c_LINKER t12-e1.p/main.c.o | libt12-s1.a libt12-s2.a libt12-s3.a\n', content) + self.assertIn('build t13-e1: c_LINKER t13-e1.p/main.c.o | libt12-s1.a libt13-s3.a\n', content) From 142dd17f5b7fbc4b2cd94f2af5bde1edfdb135be Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 6 Aug 2023 13:15:12 -0400 Subject: [PATCH 100/855] machine file: Fix crash on empty value Fixes: #12025 --- mesonbuild/coredata.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 54d9b1d02d72..e930dfff5586 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -992,9 +992,11 @@ def _parse_section(self, s: str) -> T.Dict[str, T.Union[str, bool, int, T.List[s value = value.replace('\\', '\\\\') try: ast = mparser.Parser(value, 'machinefile').parse() + if not ast.lines: + raise EnvironmentException('value cannot be empty') res = self._evaluate_statement(ast.lines[0]) - except MesonException: - raise EnvironmentException(f'Malformed value in machine file variable {entry!r}.') + except MesonException as e: + raise EnvironmentException(f'Malformed value in machine file variable {entry!r}: {str(e)}.') except KeyError as e: raise EnvironmentException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.') section[entry] = res From a151b10988644b24dd45d0a912d5994edccbb6e0 Mon Sep 17 00:00:00 2001 From: Lucas Alber Date: Tue, 8 Aug 2023 10:16:49 +0200 Subject: [PATCH 101/855] Detect version for Vulkan system dependency --- mesonbuild/dependencies/ui.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 1dffa1f6b9e0..6de55348bf24 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -17,11 +17,13 @@ from __future__ import annotations import os +import re import subprocess import typing as T from .. import mlog from .. import mesonlib +from ..compilers.compilers import CrossNoRunException from ..mesonlib import ( Popen_safe, extract_as_list, version_compare_many ) @@ -235,10 +237,6 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. self.compile_args.append('-I' + inc_path) self.link_args.append('-L' + lib_path) self.link_args.append('-l' + lib_name) - - # TODO: find a way to retrieve the version from the sdk? - # Usually it is a part of the path to it (but does not have to be) - return else: # simply try to guess it, usually works on linux libs = self.clib_compiler.find_library('vulkan', environment, []) @@ -246,7 +244,33 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. self.is_found = True for lib in libs: self.link_args.append(lib) - return + + if self.is_found: + get_version = '''\ +#include +#include + +int main() { + printf("%i.%i.%i", VK_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE), + VK_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE), + VK_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE)); + return 0; +} +''' + try: + run = self.clib_compiler.run(get_version, environment, extra_args=self.compile_args) + except CrossNoRunException: + run = None + if run and run.compiled and run.returncode == 0: + self.version = run.stdout + elif self.vulkan_sdk: + # fall back to heuristics: detect version number in path + # matches the default install path on Windows + match = re.search(rf'VulkanSDK{re.escape(os.path.sep)}([0-9]+(?:\.[0-9]+)+)', self.vulkan_sdk) + if match: + self.version = match.group(1) + else: + mlog.warning(f'Environment variable VULKAN_SDK={self.vulkan_sdk} is present, but Vulkan version could not be extracted.') packages['gl'] = gl_factory = DependencyFactory( 'gl', From 7abd4d39c179f9cf4b8830d44d070b910db8a2d4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 17 Jun 2022 14:05:25 -0700 Subject: [PATCH 102/855] interpreter: add type annotations to func_declare_dependency --- mesonbuild/interpreter/interpreter.py | 7 ++++--- mesonbuild/interpreter/kwargs.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 95a6e1d8004b..61c0b253ee4b 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -691,7 +691,8 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa KwargInfo('version', (str, NoneType)), KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'), ) - def func_declare_dependency(self, node, args, kwargs): + def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var], + kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency: deps = kwargs['dependencies'] incs = self.extract_incdirs(kwargs) libs = kwargs['link_with'] @@ -2738,7 +2739,7 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], install_tag=install_tag, data_type='configure')) return mesonlib.File.from_built_file(self.subdir, output) - def extract_incdirs(self, kwargs, key: str = 'include_directories'): + def extract_incdirs(self, kwargs, key: str = 'include_directories') -> T.List[build.IncludeDirs]: prospectives = extract_as_list(kwargs, key) if key == 'include_directories': for i in prospectives: @@ -2747,7 +2748,7 @@ def extract_incdirs(self, kwargs, key: str = 'include_directories'): f'Use include_directories({i!r}) instead', location=self.current_node) break - result = [] + result: T.List[build.IncludeDirs] = [] for p in prospectives: if isinstance(p, build.IncludeDirs): result.append(p) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 2a1cd6173891..48e483efc7be 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -12,6 +12,7 @@ from .. import build from .. import coredata from ..compilers import Compiler +from ..dependencies.base import Dependency from ..mesonlib import EnvironmentVariables, MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram @@ -360,3 +361,20 @@ class Jar(_BaseBuildTarget): main_class: str java_resources: T.Optional[build.StructuredSources] + + +class FuncDeclareDependency(TypedDict): + + compile_args: T.List[str] + d_import_dirs: T.List[T.Union[build.IncludeDirs, str]] + d_module_versions: T.List[T.Union[str, int]] + dependencies: T.List[Dependency] + extra_files: T.List[FileOrString] + include_directories: T.List[T.Union[build.IncludeDirs, str]] + link_args: T.List[str] + link_whole: T.List[T.Union[build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]] + link_with: T.List[build.LibTypes] + objects: T.List[build.ExtractedObjects] + sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] + variables: T.Dict[str, str] + version: T.Optional[str] From bf036f37cdbd316719aa59f2ea811532a23d83b1 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 17 Jun 2022 14:10:32 -0700 Subject: [PATCH 103/855] interpreter: delete dead code in func_declare_dependency --- mesonbuild/interpreter/interpreter.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 61c0b253ee4b..e54f2a661d37 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -720,9 +720,6 @@ def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var] continue if p.is_absolute() and p.is_dir() and srcdir / self.root_subdir in [p] + list(Path(os.path.abspath(p)).parents): variables[k] = P_OBJ.DependencyVariableString(v) - for d in deps: - if not isinstance(d, dependencies.Dependency): - raise InterpreterException('Invalid dependency') dep = dependencies.InternalDependency(version, incs, compile_args, link_args, libs, libs_whole, sources, extra_files, From 94a97b2f8d11772ee96740026119414164f1617a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 17 Jun 2022 14:17:13 -0700 Subject: [PATCH 104/855] interpreter|dependencies: Fix issues spotted by mypy Which is mostly that other annotations are wrong. --- mesonbuild/dependencies/base.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index ce206b6dd8b1..72e9f44d99ac 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -36,9 +36,8 @@ from ..interpreterbase import FeatureCheckBase from ..build import ( CustomTarget, IncludeDirs, CustomTargetIndex, LibTypes, - StaticLibrary, StructuredSources, ExtractedObjects + StaticLibrary, StructuredSources, ExtractedObjects, GeneratedTypes ) - from ..mesonlib import FileOrString class DependencyException(MesonException): @@ -109,7 +108,7 @@ def __init__(self, type_name: DependencyTypeName, kwargs: T.Dict[str, T.Any]) -> # Raw -L and -l arguments without manual library searching # If None, self.link_args will be used self.raw_link_args: T.Optional[T.List[str]] = None - self.sources: T.List[T.Union['FileOrString', 'CustomTarget', 'StructuredSources']] = [] + self.sources: T.List[T.Union[mesonlib.File, GeneratedTypes, 'StructuredSources']] = [] self.extra_files: T.List[mesonlib.File] = [] self.include_type = self._process_include_type_kw(kwargs) self.ext_deps: T.List[Dependency] = [] @@ -167,7 +166,7 @@ def get_all_link_args(self) -> T.List[str]: def found(self) -> bool: return self.is_found - def get_sources(self) -> T.List[T.Union['FileOrString', 'CustomTarget', 'StructuredSources']]: + def get_sources(self) -> T.List[T.Union[mesonlib.File, GeneratedTypes, 'StructuredSources']]: """Source files that need to be added to the target. As an example, gtest-all.cc when using GTest.""" return self.sources @@ -254,7 +253,7 @@ def __init__(self, version: str, incdirs: T.List['IncludeDirs'], compile_args: T link_args: T.List[str], libraries: T.List[LibTypes], whole_libraries: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]], - sources: T.Sequence[T.Union[FileOrString, CustomTarget, StructuredSources]], + sources: T.Sequence[T.Union[mesonlib.File, GeneratedTypes, StructuredSources]], extra_files: T.Sequence[mesonlib.File], ext_deps: T.List[Dependency], variables: T.Dict[str, str], d_module_versions: T.List[T.Union[str, int]], d_import_dirs: T.List['IncludeDirs'], From ec1081666578fe33a75f2c03b6ee9582806d012f Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 8 Aug 2023 08:41:01 +0200 Subject: [PATCH 105/855] tests: fix test_vsenv_option with Python 3.11+ on Windows meson tests enable PYTHONWARNDEFAULTENCODING by default and make EncodingWarning fatal too. Starting with Python 3.11 CPython not only warns if no encoding is passed to open() but also to things like subprocess.check_output(). This made the call in vsenv.py fail and in turn made test_vsenv_option fail. check_output() here calls a .bat file which in turn calls vcvars. I don't know what the encoding is supposed to be used there, so just be explicit with the locale encoding to silence the warning. --- mesonbuild/utils/vsenv.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/utils/vsenv.py b/mesonbuild/utils/vsenv.py index 550a8cf54526..5a023794b3e6 100644 --- a/mesonbuild/utils/vsenv.py +++ b/mesonbuild/utils/vsenv.py @@ -6,6 +6,7 @@ import pathlib import shutil import tempfile +import locale from .. import mlog from .core import MesonException @@ -93,7 +94,8 @@ def _setup_vsenv(force: bool) -> bool: bat_file.write(bat_contents) bat_file.flush() bat_file.close() - bat_output = subprocess.check_output(bat_file.name, universal_newlines=True) + bat_output = subprocess.check_output(bat_file.name, universal_newlines=True, + encoding=locale.getpreferredencoding(False)) os.unlink(bat_file.name) bat_lines = bat_output.split('\n') bat_separator_seen = False From 6671b7359fd042f576f5b944b67f73ced89fe5a6 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 8 Aug 2023 09:26:33 +0200 Subject: [PATCH 106/855] tests: fix "4 custom target depends extmodule" with Python 3.8+ on Windows Since CPython 3.8 .pyd files no longer look in PATH for loading libraries, but require the DLL directory to be explicitely added via os.add_dll_directory(). This resulted in those tests failing with 3.8+ on Windows. Add the DLL build directory with os.add_dll_directory() to fix them. This was never noticed in CI because it only uses Python 3.7 and the MSYS2 CPython still used the old behaviour until now. --- test cases/python/4 custom target depends extmodule/blaster.py | 3 +++ .../python3/4 custom target depends extmodule/blaster.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test cases/python/4 custom target depends extmodule/blaster.py b/test cases/python/4 custom target depends extmodule/blaster.py index 61b11f922977..65b6493df890 100644 --- a/test cases/python/4 custom target depends extmodule/blaster.py +++ b/test cases/python/4 custom target depends extmodule/blaster.py @@ -10,6 +10,9 @@ if list(filedir.glob('ext/*tachyon*')): sys.path.insert(0, (filedir / 'ext').as_posix()) +if hasattr(os, 'add_dll_directory'): + os.add_dll_directory(filedir / 'ext' / 'lib') + import tachyon parser = argparse.ArgumentParser() diff --git a/test cases/python3/4 custom target depends extmodule/blaster.py b/test cases/python3/4 custom target depends extmodule/blaster.py index d2c93ad038fa..9cce64505e5d 100644 --- a/test cases/python3/4 custom target depends extmodule/blaster.py +++ b/test cases/python3/4 custom target depends extmodule/blaster.py @@ -10,6 +10,9 @@ if list(filedir.glob('ext/*tachyon.*')): sys.path.insert(0, (filedir / 'ext').as_posix()) +if hasattr(os, 'add_dll_directory'): + os.add_dll_directory(filedir / 'ext' / 'lib') + import tachyon parser = argparse.ArgumentParser() From 3de0f6d4e94036646321859b9287faba6e99f050 Mon Sep 17 00:00:00 2001 From: kiwixz Date: Mon, 7 Aug 2023 23:53:30 +0200 Subject: [PATCH 107/855] clang: use gcc syntax to enable diagnostics color clang has supported gcc syntax since version 3.3.0 from 10 years ago. It's better than its own version because it takes a "when" verb which allows us to explicitely ask for "auto". This is useful when overriding flags that came from elsewhere. Before this patch, meson was just treating b_colorout="auto" as "always". --- mesonbuild/compilers/mixins/clang.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index 24f24a8df0db..6a9c79bc77c5 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -31,9 +31,9 @@ from ...dependencies import Dependency # noqa: F401 clang_color_args: T.Dict[str, T.List[str]] = { - 'auto': ['-fcolor-diagnostics'], - 'always': ['-fcolor-diagnostics'], - 'never': ['-fno-color-diagnostics'], + 'auto': ['-fdiagnostics-color=auto'], + 'always': ['-fdiagnostics-color=always'], + 'never': ['-fdiagnostics-color=never'], } clang_optimization_args: T.Dict[str, T.List[str]] = { From b91244c3b7f77578d601502628bceb9e92183387 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Mon, 23 Jan 2023 21:41:43 +0100 Subject: [PATCH 108/855] correct cmakedefine behavior - allow defines with leading whitespace - always do replacement for cmakedefine - output boolean value for cmakedefine01 - correct unittests for cmakedefine - add cmakedefine specific unittests --- mesonbuild/utils/universal.py | 38 +++++++++++++++++++++++++--------- unittests/allplatformstests.py | 38 +++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 5b7750c99241..ac239ed55558 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1207,6 +1207,8 @@ def variable_replace(match: T.Match[str]) -> str: var, _ = confdata.get(varname) if isinstance(var, str): var_str = var + elif isinstance(var, bool): + var_str = str(int(var)) elif isinstance(var, int): var_str = str(var) else: @@ -1220,8 +1222,17 @@ def variable_replace(match: T.Match[str]) -> str: def do_define(regex: T.Pattern[str], line: str, confdata: 'ConfigurationData', variable_format: Literal['meson', 'cmake', 'cmake@'], subproject: T.Optional[SubProject] = None) -> str: + cmake_bool_define = False + if variable_format != "meson": + cmake_bool_define = "cmakedefine01" in line + def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str: arr = line.split() + + if cmake_bool_define: + (v, desc) = confdata.get(arr[1]) + return str(int(bool(v))) + define_value: T.List[str] = [] for token in arr[2:]: try: @@ -1243,22 +1254,29 @@ def get_cmake_define(line: str, confdata: 'ConfigurationData') -> str: try: v, _ = confdata.get(varname) except KeyError: - return '/* #undef %s */\n' % varname - if isinstance(v, bool): - if v: - return '#define %s\n' % varname + if cmake_bool_define: + return '#define %s 0\n' % varname else: - return '#undef %s\n' % varname - elif isinstance(v, int): - return '#define %s %d\n' % (varname, v) - elif isinstance(v, str): + return '/* #undef %s */\n' % varname + + if isinstance(v, str) or variable_format != "meson": if variable_format == 'meson': result = v else: + if not cmake_bool_define and not v: + return '/* #undef %s */\n' % varname + result = get_cmake_define(line, confdata) - result = f'#define {varname} {result}\n' + result = f'#define {varname} {result}'.strip() + '\n' result, _ = do_replacement(regex, result, variable_format, confdata) return result + elif isinstance(v, bool): + if v: + return '#define %s\n' % varname + else: + return '#undef %s\n' % varname + elif isinstance(v, int): + return '#define %s %d\n' % (varname, v) else: raise MesonException('#mesondefine argument "%s" is of unknown type.' % varname) @@ -1295,7 +1313,7 @@ def line_is_valid(line: str, variable_format: str) -> bool: # during substitution so we can warn the user to use the `copy:` kwarg. confdata_useless = not confdata.keys() for line in data: - if line.startswith(search_token): + if line.lstrip().startswith(search_token): confdata_useless = False line = do_define(regex, line, confdata, variable_format, subproject) else: diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 7f38d4b09904..f7fb1b0c5f00 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -153,20 +153,33 @@ def conf_str(in_data, confdata, vformat): (result, missing_variables, confdata_useless) = do_conf_str('configuration_file', in_data, confdata, variable_format = vformat) return '\n'.join(result) - def check_formats(confdata, result): + def check_meson_format(confdata, result): self.assertEqual(conf_str(['#mesondefine VAR'], confdata, 'meson'), result) + + def check_cmake_format_simple(confdata, result): + self.assertEqual(conf_str(['#cmakedefine VAR'], confdata, 'cmake'), result) + + def check_cmake_formats_full(confdata, result): self.assertEqual(conf_str(['#cmakedefine VAR ${VAR}'], confdata, 'cmake'), result) self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'), result) + def check_formats(confdata, result): + check_meson_format(confdata, result) + check_cmake_formats_full(confdata, result) + confdata = ConfigurationData() # Key error as they do not exists check_formats(confdata, '/* #undef VAR */\n') # Check boolean confdata.values = {'VAR': (False, 'description')} - check_formats(confdata, '#undef VAR\n') + check_meson_format(confdata, '#undef VAR\n') + check_cmake_formats_full(confdata, '/* #undef VAR */\n') + confdata.values = {'VAR': (True, 'description')} - check_formats(confdata, '#define VAR\n') + check_meson_format(confdata, '#define VAR\n') + check_cmake_format_simple(confdata, '#define VAR\n') + check_cmake_formats_full(confdata, '#define VAR 1\n') # Check string confdata.values = {'VAR': ('value', 'description')} @@ -176,6 +189,25 @@ def check_formats(confdata, result): confdata.values = {'VAR': (10, 'description')} check_formats(confdata, '#define VAR 10\n') + # Checking if cmakedefine behaves as it does with cmake + confdata.values = {'VAR': ("var", 'description')} + self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'), '#define VAR var\n') + + confdata.values = {'VAR': (True, 'description')} + self.assertEqual(conf_str(['#cmakedefine01 VAR'], confdata, 'cmake'), '#define VAR 1\n') + + confdata.values = {'VAR': (0, 'description')} + self.assertEqual(conf_str(['#cmakedefine01 VAR'], confdata, 'cmake'), '#define VAR 0\n') + confdata.values = {'VAR': (False, 'description')} + self.assertEqual(conf_str(['#cmakedefine01 VAR'], confdata, 'cmake'), '#define VAR 0\n') + + confdata.values = {} + self.assertEqual(conf_str(['#cmakedefine01 VAR'], confdata, 'cmake'), '#define VAR 0\n') + self.assertEqual(conf_str(['#cmakedefine VAR @VAR@'], confdata, 'cmake@'), '/* #undef VAR */\n') + + confdata.values = {'VAR': (5, 'description')} + self.assertEqual(conf_str(['#cmakedefine VAR'], confdata, 'cmake'), '#define VAR\n') + # Check multiple string with cmake formats confdata.values = {'VAR': ('value', 'description')} self.assertEqual(conf_str(['#cmakedefine VAR xxx @VAR@ yyy @VAR@'], confdata, 'cmake@'), '#define VAR xxx value yyy value\n') From 711e4e3b069313df7e0c9912d316fecd197b2ce0 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 9 Aug 2023 08:40:20 -0400 Subject: [PATCH 109/855] Optimize CLikeCompiler._get_file_from_list() Simplify and optimize the function. When not on Mac OS, it was iterating two times the list when there were no files in it. --- mesonbuild/compilers/mixins/clike.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 251a7bf67bd1..f333357e2312 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1090,27 +1090,25 @@ def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> return [f] @staticmethod - def _get_file_from_list(env: 'Environment', paths: T.List[Path]) -> Path: + def _get_file_from_list(env: Environment, paths: T.List[Path]) -> T.Optional[Path]: ''' We just check whether the library exists. We can't do a link check because the library might have unresolved symbols that require other libraries. On macOS we check if the library matches our target architecture. ''' - # If not building on macOS for Darwin, do a simple file check - if not env.machines.host.is_darwin() or not env.machines.build.is_darwin(): - for p in paths: - if p.is_file(): - return p - # Run `lipo` and check if the library supports the arch we want for p in paths: - if not p.is_file(): - continue - archs = mesonlib.darwin_get_object_archs(str(p)) - if archs and env.machines.host.cpu_family in archs: + if p.is_file(): + + if env.machines.host.is_darwin() and env.machines.build.is_darwin(): + # Run `lipo` and check if the library supports the arch we want + archs = mesonlib.darwin_get_object_archs(str(p)) + if not archs or env.machines.host.cpu_family not in archs: + mlog.debug(f'Rejected {p}, supports {archs} but need {env.machines.host.cpu_family}') + continue + return p - else: - mlog.debug(f'Rejected {p}, supports {archs} but need {env.machines.host.cpu_family}') + return None @functools.lru_cache() From 13b626b67be41635886d0a95e492cd13dfee0b1a Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 9 Aug 2023 14:33:08 -0400 Subject: [PATCH 110/855] Popen_safe_logged: Also log exceptions Popen can raise OSError when program is not found, or PermissionError if not executable, etc. --- mesonbuild/utils/universal.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index ac239ed55558..c1125fbe8b12 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1547,7 +1547,13 @@ def Popen_safe_logged(args: T.List[str], msg: str = 'Called', **kwargs: T.Any) - ''' Wrapper around Popen_safe that assumes standard piped o/e and logs this to the meson log. ''' - p, o, e = Popen_safe(args, **kwargs) + try: + p, o, e = Popen_safe(args, **kwargs) + except Exception as excp: + mlog.debug('-----------') + mlog.debug(f'{msg}: `{join_args(args)}` -> {excp}') + raise + rc, out, err = p.returncode, o.strip(), e.strip() mlog.debug('-----------') mlog.debug(f'{msg}: `{join_args(args)}` -> {rc}') From 277151450a8eaf48f7038b21fdbf39b85f339e8b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 2 Aug 2023 21:51:50 -0400 Subject: [PATCH 111/855] allow some ObjectHolder subclasses to continue to be generic ExternalProgram and CustomTarget have some use cases for producing subclassed interpreter holders with more specific types and methods. In order for those subclasses to properly refer to their held_object, we need a shared base class that is still generic, though bound. For the derived held objects, inherit from the base class and specify the final types as the module-specific type. --- mesonbuild/interpreter/interpreterobjects.py | 18 ++++++++++++++---- mesonbuild/modules/hotdoc.py | 6 +++--- mesonbuild/modules/python.py | 8 ++++---- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 8648b487fd2f..f1f8ea8fbc23 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -559,8 +559,10 @@ def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> D new_dep = self.held_object.generate_link_whole_dependency() return new_dep -class ExternalProgramHolder(ObjectHolder[ExternalProgram]): - def __init__(self, ep: ExternalProgram, interpreter: 'Interpreter') -> None: +_EXTPROG = T.TypeVar('_EXTPROG', bound=ExternalProgram) + +class _ExternalProgramHolder(ObjectHolder[_EXTPROG]): + def __init__(self, ep: _EXTPROG, interpreter: 'Interpreter') -> None: super().__init__(ep, interpreter) self.methods.update({'found': self.found_method, 'path': self.path_method, @@ -606,6 +608,9 @@ def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: def found(self) -> bool: return self.held_object.found() +class ExternalProgramHolder(_ExternalProgramHolder[ExternalProgram]): + pass + class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]): def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'): super().__init__(el, interpreter) @@ -969,8 +974,10 @@ def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: assert self.interpreter.backend is not None return self.interpreter.backend.get_target_filename_abs(self.held_object) -class CustomTargetHolder(ObjectHolder[build.CustomTarget]): - def __init__(self, target: 'build.CustomTarget', interp: 'Interpreter'): +_CT = T.TypeVar('_CT', bound=build.CustomTarget) + +class _CustomTargetHolder(ObjectHolder[_CT]): + def __init__(self, target: _CT, interp: 'Interpreter'): super().__init__(target, interp) self.methods.update({'full_path': self.full_path_method, 'to_list': self.to_list_method, @@ -1007,6 +1014,9 @@ def op_index(self, other: int) -> build.CustomTargetIndex: except IndexError: raise InvalidArguments(f'Index {other} out of bounds of custom target {self.held_object.name} output of size {len(self.held_object)}.') +class CustomTargetHolder(_CustomTargetHolder[build.CustomTarget]): + pass + class RunTargetHolder(ObjectHolder[build.RunTarget]): pass diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index cf1a2477c3ba..f5916ebe8154 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -28,7 +28,7 @@ InvalidArguments, noPosargs, noKwargs, typed_kwargs, FeatureDeprecated, ContainerTypeInfo, KwargInfo, typed_pos_args ) -from ..interpreter import CustomTargetHolder +from ..interpreter.interpreterobjects import _CustomTargetHolder from ..interpreter.type_checking import NoneType from ..programs import ExternalProgram @@ -364,8 +364,8 @@ def make_targets(self): return (target, install_script) -class HotdocTargetHolder(CustomTargetHolder): - def __init__(self, target, interp): +class HotdocTargetHolder(_CustomTargetHolder['HotdocTarget']): + def __init__(self, target: HotdocTarget, interp): super().__init__(target, interp) self.methods.update({'config_path': self.config_path_method}) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 879c5487c729..470f7b33bd98 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -24,8 +24,8 @@ from ..dependencies import NotFoundDependency from ..dependencies.detect import get_dep_identifier, find_external_dependency from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase -from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs -from ..interpreter import primitives as P_OBJ +from ..interpreter import extract_required_kwarg, permitted_dependency_kwargs, primitives as P_OBJ +from ..interpreter.interpreterobjects import _ExternalProgramHolder from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW, SHARED_MOD_KWS from ..interpreterbase import ( noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, @@ -114,9 +114,9 @@ def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None: _SUBDIR_KW = KwargInfo('subdir', str, default='') _DEFAULTABLE_SUBDIR_KW = KwargInfo('subdir', (str, NoneType)) -class PythonInstallation(ExternalProgramHolder): +class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']): def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): - ExternalProgramHolder.__init__(self, python, interpreter) + _ExternalProgramHolder.__init__(self, python, interpreter) info = python.info prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix')) assert isinstance(prefix, str), 'for mypy' From 169cd7e61934a9c852d109d65226b10b332283a0 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 12 Mar 2023 23:14:01 -0400 Subject: [PATCH 112/855] python module: add a few more type annotations --- mesonbuild/modules/python.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 470f7b33bd98..d0067db5ae42 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -62,6 +62,8 @@ class ExtensionModuleKw(SharedModuleKw): subdir: NotRequired[T.Optional[str]] + MaybePythonProg = T.Union[NonExistingExternalProgram, 'PythonExternalProgram'] + mod_kwargs = {'subdir'} mod_kwargs.update(known_shmod_kwargs) @@ -84,12 +86,12 @@ def sanity(self, state: T.Optional['ModuleState'] = None) -> bool: self.purelib = self._get_path(state, 'purelib') return ret - def _get_path(self, state: T.Optional['ModuleState'], key: str) -> None: + def _get_path(self, state: T.Optional['ModuleState'], key: str) -> str: rel_path = self.info['install_paths'][key][1:] if not state: # This happens only from run_project_tests.py return rel_path - value = state.get_option(f'{key}dir', module='python') + value = T.cast('str', state.get_option(f'{key}dir', module='python')) if value: if state.is_user_defined_option('install_env', module='python'): raise mesonlib.MesonException(f'python.{key}dir and python.install_env are mutually exclusive') @@ -303,7 +305,7 @@ class PythonModule(ExtensionModule): def __init__(self, interpreter: 'Interpreter') -> None: super().__init__(interpreter) - self.installations: T.Dict[str, ExternalProgram] = {} + self.installations: T.Dict[str, MaybePythonProg] = {} self.methods.update({ 'find_installation': self.find_installation, }) @@ -377,7 +379,7 @@ def _get_win_pythonpath(name_or_path: str) -> T.Optional[str]: else: return None - def _find_installation_impl(self, state: 'ModuleState', display_name: str, name_or_path: str, required: bool) -> ExternalProgram: + def _find_installation_impl(self, state: 'ModuleState', display_name: str, name_or_path: str, required: bool) -> MaybePythonProg: if not name_or_path: python = PythonExternalProgram('python3', mesonlib.python_command) else: @@ -420,7 +422,7 @@ def _find_installation_impl(self, state: 'ModuleState', display_name: str, name_ _PURE_KW.evolve(default=True, since='0.64.0'), ) def find_installation(self, state: 'ModuleState', args: T.Tuple[T.Optional[str]], - kwargs: 'FindInstallationKw') -> ExternalProgram: + kwargs: 'FindInstallationKw') -> MaybePythonProg: feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0') disabled, required, feature = extract_required_kwarg(kwargs, state.subproject, feature_check) @@ -482,6 +484,7 @@ def find_installation(self, state: 'ModuleState', args: T.Tuple[T.Optional[str]] raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules))) return NonExistingExternalProgram(python.name) else: + assert isinstance(python, PythonExternalProgram), 'for mypy' python = copy.copy(python) python.pure = kwargs['pure'] python.run_bytecompile.setdefault(python.info['version'], False) From bf0494fcc00e816c2972112a1ae2e0580053cbb8 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 2 Aug 2023 23:05:08 -0400 Subject: [PATCH 113/855] hotdoc module: avoid monkeypatch crime by properly subclassing ExternalProgram --- mesonbuild/modules/hotdoc.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index f5916ebe8154..a272b683d559 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -15,8 +15,8 @@ '''This module provides helper functions for generating documentation using hotdoc''' -import os -import subprocess +import os, subprocess +import typing as T from mesonbuild import mesonlib from mesonbuild import mlog, build @@ -44,6 +44,11 @@ def ensure_list(value): file_types = (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex) +class HotdocExternalProgram(ExternalProgram): + def run_hotdoc(self, cmd: T.List[str]) -> int: + return subprocess.run(self.get_command() + cmd, stdout=subprocess.DEVNULL).returncode + + class HotdocTargetBuilder: def __init__(self, name, state, hotdoc, interpreter, kwargs): @@ -400,17 +405,13 @@ class HotDocModule(ExtensionModule): def __init__(self, interpreter): super().__init__(interpreter) - self.hotdoc = ExternalProgram('hotdoc') + self.hotdoc = HotdocExternalProgram('hotdoc') if not self.hotdoc.found(): raise MesonException('hotdoc executable not found') version = self.hotdoc.get_version(interpreter) if not mesonlib.version_compare(version, f'>={MIN_HOTDOC_VERSION}'): raise MesonException(f'hotdoc {MIN_HOTDOC_VERSION} required but not found.)') - def run_hotdoc(cmd): - return subprocess.run(self.hotdoc.get_command() + cmd, stdout=subprocess.DEVNULL).returncode - - self.hotdoc.run_hotdoc = run_hotdoc self.methods.update({ 'has_extensions': self.has_extensions, 'generate_doc': self.generate_doc, From 32e7ebc821a2078722947c5bd412b6c0a244b30d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 3 Aug 2023 15:41:06 -0400 Subject: [PATCH 114/855] hotdoc module: add a bunch more type annotations --- mesonbuild/modules/hotdoc.py | 125 +++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index a272b683d559..f11354900dd0 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -18,11 +18,9 @@ import os, subprocess import typing as T -from mesonbuild import mesonlib -from mesonbuild import mlog, build -from mesonbuild.mesonlib import MesonException -from . import ModuleReturnValue, ModuleInfo -from . import ExtensionModule +from . import ExtensionModule, ModuleReturnValue, ModuleInfo +from .. import build, mesonlib, mlog +from ..build import CustomTarget, CustomTargetIndex from ..dependencies import Dependency, InternalDependency from ..interpreterbase import ( InvalidArguments, noPosargs, noKwargs, typed_kwargs, FeatureDeprecated, @@ -30,10 +28,34 @@ ) from ..interpreter.interpreterobjects import _CustomTargetHolder from ..interpreter.type_checking import NoneType +from ..mesonlib import File, MesonException from ..programs import ExternalProgram - -def ensure_list(value): +if T.TYPE_CHECKING: + from typing_extensions import TypedDict + + from . import ModuleState + from ..environment import Environment + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_kwargs, TYPE_var + + _T = T.TypeVar('_T') + + class GenerateDocKwargs(TypedDict): + sitemap: T.Union[str, File, CustomTarget, CustomTargetIndex] + index: T.Union[str, File, CustomTarget, CustomTargetIndex] + project_version: str + html_extra_theme: T.Optional[str] + include_paths: T.List[str] + dependencies: T.List[T.Union[Dependency, build.StaticLibrary, build.SharedLibrary, CustomTarget, CustomTargetIndex]] + depends: T.List[T.Union[CustomTarget, CustomTargetIndex]] + gi_c_source_roots: T.List[str] + extra_assets: T.List[str] + extra_extension_paths: T.List[str] + subprojects: T.List['HotdocTarget'] + install: bool + +def ensure_list(value: T.Union[_T, T.List[_T]]) -> T.List[_T]: if not isinstance(value, list): return [value] return value @@ -41,7 +63,7 @@ def ensure_list(value): MIN_HOTDOC_VERSION = '0.8.100' -file_types = (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex) +file_types = (str, File, CustomTarget, CustomTargetIndex) class HotdocExternalProgram(ExternalProgram): @@ -51,29 +73,29 @@ def run_hotdoc(self, cmd: T.List[str]) -> int: class HotdocTargetBuilder: - def __init__(self, name, state, hotdoc, interpreter, kwargs): + def __init__(self, name: str, state: ModuleState, hotdoc: HotdocExternalProgram, interpreter: Interpreter, kwargs): self.hotdoc = hotdoc self.build_by_default = kwargs.pop('build_by_default', False) self.kwargs = kwargs self.name = name self.state = state self.interpreter = interpreter - self.include_paths = mesonlib.OrderedSet() + self.include_paths: mesonlib.OrderedSet[str] = mesonlib.OrderedSet() self.builddir = state.environment.get_build_dir() self.sourcedir = state.environment.get_source_dir() self.subdir = state.subdir self.build_command = state.environment.get_build_command() - self.cmd = ['conf', '--project-name', name, "--disable-incremental-build", - '--output', os.path.join(self.builddir, self.subdir, self.name + '-doc')] + self.cmd: T.List[TYPE_var] = ['conf', '--project-name', name, "--disable-incremental-build", + '--output', os.path.join(self.builddir, self.subdir, self.name + '-doc')] self._extra_extension_paths = set() self.extra_assets = set() self.extra_depends = [] self._subprojects = [] - def process_known_arg(self, option, argname=None, value_processor=None): + def process_known_arg(self, option: str, argname: T.Optional[str] = None, value_processor: T.Optional[T.Callable] = None) -> None: if not argname: argname = option.strip("-").replace("-", "_") @@ -83,7 +105,7 @@ def process_known_arg(self, option, argname=None, value_processor=None): self.set_arg_value(option, value) - def set_arg_value(self, option, value): + def set_arg_value(self, option: str, value: TYPE_var) -> None: if value is None: return @@ -116,18 +138,18 @@ def set_arg_value(self, option, value): else: self.cmd.extend([option, value]) - def check_extra_arg_type(self, arg, value): + def check_extra_arg_type(self, arg: str, value: TYPE_var) -> None: if isinstance(value, list): for v in value: self.check_extra_arg_type(arg, v) return - valid_types = (str, bool, mesonlib.File, build.IncludeDirs, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget) + valid_types = (str, bool, File, build.IncludeDirs, CustomTarget, CustomTargetIndex, build.BuildTarget) if not isinstance(value, valid_types): raise InvalidArguments('Argument "{}={}" should be of type: {}.'.format( arg, value, [t.__name__ for t in valid_types])) - def process_extra_args(self): + def process_extra_args(self) -> None: for arg, value in self.kwargs.items(): option = "--" + arg.replace("_", "-") self.check_extra_arg_type(arg, value) @@ -158,7 +180,7 @@ def get_value(self, types, argname, default=None, value_processor=None, return None, None - def add_extension_paths(self, paths): + def add_extension_paths(self, paths: T.Union[T.List[str], T.Set[str]]) -> None: for path in paths: if path in self._extra_extension_paths: continue @@ -166,10 +188,10 @@ def add_extension_paths(self, paths): self._extra_extension_paths.add(path) self.cmd.extend(["--extra-extension-path", path]) - def replace_dirs_in_string(self, string): + def replace_dirs_in_string(self, string: str) -> str: return string.replace("@SOURCE_ROOT@", self.sourcedir).replace("@BUILD_ROOT@", self.builddir) - def process_gi_c_source_roots(self): + def process_gi_c_source_roots(self) -> None: if self.hotdoc.run_hotdoc(['--has-extension=gi-extension']) != 0: return @@ -181,7 +203,7 @@ def process_gi_c_source_roots(self): self.cmd += ['--gi-c-source-roots'] + value - def process_dependencies(self, deps): + def process_dependencies(self, deps: T.List[T.Union[Dependency, build.StaticLibrary, build.SharedLibrary, CustomTarget, CustomTargetIndex]]) -> T.List[str]: cflags = set() for dep in mesonlib.listify(ensure_list(deps)): if isinstance(dep, InternalDependency): @@ -205,29 +227,29 @@ def process_dependencies(self, deps): self.include_paths.add(os.path.join(self.builddir, dep.hotdoc_conf.subdir)) self.cmd += ['--extra-assets=' + p for p in dep.extra_assets] self.add_extension_paths(dep.extra_extension_paths) - elif isinstance(dep, (build.CustomTarget, build.BuildTarget)): + elif isinstance(dep, (CustomTarget, build.BuildTarget)): self.extra_depends.append(dep) - elif isinstance(dep, build.CustomTargetIndex): + elif isinstance(dep, CustomTargetIndex): self.extra_depends.append(dep.target) return [f.strip('-I') for f in cflags] - def process_extra_assets(self): + def process_extra_assets(self) -> None: self._extra_assets = self.kwargs.pop('extra_assets') for assets_path in self._extra_assets: self.cmd.extend(["--extra-assets", assets_path]) - def process_subprojects(self): + def process_subprojects(self) -> None: value = self.kwargs.pop('subprojects') self.process_dependencies(value) self._subprojects.extend(value) - def flatten_config_command(self): + def flatten_config_command(self) -> T.List[str]: cmd = [] for arg in mesonlib.listify(self.cmd, flatten=True): - if isinstance(arg, mesonlib.File): + if isinstance(arg, File): arg = arg.absolute_path(self.state.environment.get_source_dir(), self.state.environment.get_build_dir()) elif isinstance(arg, build.IncludeDirs): @@ -236,10 +258,10 @@ def flatten_config_command(self): cmd.append(os.path.join(self.builddir, arg.get_curdir(), inc_dir)) continue - elif isinstance(arg, (build.BuildTarget, build.CustomTarget)): + elif isinstance(arg, (build.BuildTarget, CustomTarget)): self.extra_depends.append(arg) arg = self.interpreter.backend.get_target_filename_abs(arg) - elif isinstance(arg, build.CustomTargetIndex): + elif isinstance(arg, CustomTargetIndex): self.extra_depends.append(arg.target) arg = self.interpreter.backend.get_target_filename_abs(arg) @@ -247,7 +269,7 @@ def flatten_config_command(self): return cmd - def generate_hotdoc_config(self): + def generate_hotdoc_config(self) -> None: cwd = os.path.abspath(os.curdir) ncwd = os.path.join(self.sourcedir, self.subdir) mlog.log('Generating Hotdoc configuration for: ', mlog.bold(self.name)) @@ -256,7 +278,7 @@ def generate_hotdoc_config(self): raise MesonException('hotdoc failed to configure') os.chdir(cwd) - def ensure_file(self, value): + def ensure_file(self, value: T.Union[str, File, CustomTarget, CustomTargetIndex]) -> T.Union[File, CustomTarget, CustomTargetIndex]: if isinstance(value, list): res = [] for val in value: @@ -264,11 +286,11 @@ def ensure_file(self, value): return res if isinstance(value, str): - return mesonlib.File.from_source_file(self.sourcedir, self.subdir, value) + return File.from_source_file(self.sourcedir, self.subdir, value) return value - def ensure_dir(self, value): + def ensure_dir(self, value: str) -> str: if os.path.isabs(value): _dir = value else: @@ -279,12 +301,12 @@ def ensure_dir(self, value): return os.path.relpath(_dir, os.path.join(self.builddir, self.subdir)) - def check_forbidden_args(self): + def check_forbidden_args(self) -> None: for arg in ['conf_file']: if arg in self.kwargs: raise InvalidArguments(f'Argument "{arg}" is forbidden.') - def make_targets(self): + def make_targets(self) -> T.Tuple[HotdocTarget, mesonlib.ExecutableSerialisation]: self.check_forbidden_args() self.process_known_arg("--index", value_processor=self.ensure_file) self.process_known_arg("--project-version") @@ -330,7 +352,7 @@ def make_targets(self): subdir=self.subdir, subproject=self.state.subproject, environment=self.state.environment, - hotdoc_conf=mesonlib.File.from_built_file( + hotdoc_conf=File.from_built_file( self.subdir, hotdoc_config_name), extra_extension_paths=self._extra_extension_paths, extra_assets=self._extra_assets, @@ -370,28 +392,29 @@ def make_targets(self): class HotdocTargetHolder(_CustomTargetHolder['HotdocTarget']): - def __init__(self, target: HotdocTarget, interp): + def __init__(self, target: HotdocTarget, interp: Interpreter): super().__init__(target, interp) self.methods.update({'config_path': self.config_path_method}) @noPosargs @noKwargs - def config_path_method(self, *args, **kwargs): + def config_path_method(self, *args: T.Any, **kwargs: T.Any) -> str: conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir) return conf -class HotdocTarget(build.CustomTarget): - def __init__(self, name, subdir, subproject, hotdoc_conf, extra_extension_paths, extra_assets, - subprojects, environment, **kwargs): +class HotdocTarget(CustomTarget): + def __init__(self, name: str, subdir: str, subproject: str, hotdoc_conf: File, + extra_extension_paths: T.Set[str], extra_assets: T.List[str], + subprojects: T.List['HotdocTarget'], environment: Environment, **kwargs: T.Any): super().__init__(name, subdir, subproject, environment, **kwargs, absolute_paths=True) self.hotdoc_conf = hotdoc_conf self.extra_extension_paths = extra_extension_paths self.extra_assets = extra_assets self.subprojects = subprojects - def __getstate__(self): + def __getstate__(self) -> dict: # Make sure we do not try to pickle subprojects res = self.__dict__.copy() res['subprojects'] = [] @@ -403,7 +426,7 @@ class HotDocModule(ExtensionModule): INFO = ModuleInfo('hotdoc', '0.48.0') - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter): super().__init__(interpreter) self.hotdoc = HotdocExternalProgram('hotdoc') if not self.hotdoc.found(): @@ -419,7 +442,7 @@ def __init__(self, interpreter): @noKwargs @typed_pos_args('hotdoc.has_extensions', varargs=str, min_varargs=1) - def has_extensions(self, state, args, kwargs): + def has_extensions(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> bool: return self.hotdoc.run_hotdoc([f'--has-extension={extension}' for extension in args[0]]) == 0 @typed_pos_args('hotdoc.generate_doc', str) @@ -434,13 +457,13 @@ def has_extensions(self, state, args, kwargs): KwargInfo( 'dependencies', ContainerTypeInfo(list, (Dependency, build.StaticLibrary, build.SharedLibrary, - build.CustomTarget, build.CustomTargetIndex)), + CustomTarget, CustomTargetIndex)), listify=True, default=[], ), KwargInfo( 'depends', - ContainerTypeInfo(list, (build.CustomTarget, build.CustomTargetIndex)), + ContainerTypeInfo(list, (CustomTarget, CustomTargetIndex)), listify=True, default=[], since='0.64.1', @@ -452,21 +475,21 @@ def has_extensions(self, state, args, kwargs): KwargInfo('install', bool, default=False), allow_unknown=True ) - def generate_doc(self, state, args, kwargs): + def generate_doc(self, state: ModuleState, args: T.Tuple[str], kwargs: GenerateDocKwargs) -> ModuleReturnValue: project_name = args[0] - if any(isinstance(x, (build.CustomTarget, build.CustomTargetIndex)) for x in kwargs['dependencies']): + if any(isinstance(x, (CustomTarget, CustomTargetIndex)) for x in kwargs['dependencies']): FeatureDeprecated.single_use('hotdoc.generate_doc dependencies argument with custom_target', '0.64.1', state.subproject, 'use `depends`', state.current_node) builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs) target, install_script = builder.make_targets() - targets = [target] + targets: T.List[T.Union[HotdocTarget, mesonlib.ExecutableSerialisation]] = [target] if install_script: targets.append(install_script) - return ModuleReturnValue(targets[0], targets) + return ModuleReturnValue(target, targets) -def initialize(interpreter): +def initialize(interpreter: Interpreter) -> HotDocModule: mod = HotDocModule(interpreter) mod.interpreter.append_holder_map(HotdocTarget, HotdocTargetHolder) return mod From 03a2a3a6773785e087b296e9e6ff6791c6068f60 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Fri, 11 Aug 2023 12:26:27 +0200 Subject: [PATCH 115/855] docs: Add more feature truth tables These are much easier to understand at a glance than free-form text. --- docs/yaml/objects/feature.yaml | 38 +++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/yaml/objects/feature.yaml b/docs/yaml/objects/feature.yaml index 3e37644f42de..26b677f7ac80 100644 --- a/docs/yaml/objects/feature.yaml +++ b/docs/yaml/objects/feature.yaml @@ -27,11 +27,11 @@ methods: description: | Returns the feature, with `'auto'` converted to `'disabled'` if value is true. - | Feature / Condition | `value = true` | `value = false` | - | ------------------- | -------------- | --------------- | - | Enabled | Enabled | Enabled | - | Disabled | Disabled | Disabled | - | Auto | Disabled | Auto | + | Feature | `value = true` | `value = false` | + | -------- | -------------- | --------------- | + | Auto | Disabled | Auto | + | Enabled | Enabled | Enabled | + | Disabled | Disabled | Disabled | posargs: value: @@ -44,11 +44,11 @@ methods: description: | Returns the feature, with `'auto'` converted to `'enabled'` if value is true. - | Feature / Condition | `value = true` | `value = false` | - | ------------------- | -------------- | --------------- | - | Enabled | Enabled | Enabled | - | Disabled | Disabled | Disabled | - | Auto | Enabled | Auto | + | Feature | `value = true` | `value = false` | + | -------- | -------------- | --------------- | + | Auto | Enabled | Auto | + | Enabled | Enabled | Enabled | + | Disabled | Disabled | Disabled | posargs: value: @@ -63,6 +63,12 @@ methods: `'enabled'` and the value is false; a disabled feature if the object is `'auto'` or `'disabled'` and the value is false. + | Feature | `value = true` | `value = false` | + | -------- | -------------- | --------------- | + | Auto | Auto | Disabled | + | Enabled | Enabled | Error | + | Disabled | Disabled | Disabled | + example: | `require` is useful to restrict the applicability of `'auto'` features, for example based on other features or on properties of the host machine: @@ -94,6 +100,12 @@ methods: `'disabled'` and the value is true; an enabled feature if the object is `'auto'` or `'enabled'` and the value is true. + | Feature | `value = true` | `value = false` | + | -------- | -------------- | --------------- | + | Auto | Enabled | Auto | + | Enabled | Enabled | Enabled | + | Disabled | Error | Disabled | + example: | `enable_if` is useful to restrict the applicability of `'auto'` features, particularly when passing them to [[dependency]]: @@ -122,6 +134,12 @@ methods: `'enabled'` and the value is true; a disabled feature if the object is `'auto'` or `'disabled'` and the value is true. + | Feature | `value = true` | `value = false` | + | -------- | -------------- | --------------- | + | Auto | Disabled | Auto | + | Enabled | Error | Enabled | + | Disabled | Disabled | Disabled | + This is equivalent to `feature_opt.require(not condition)`, but may make code easier to reason about, especially when mixed with `enable_if` From a01418db0a37908cc2504adbb0cf56d333348f9a Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 10 Aug 2023 20:51:45 -0400 Subject: [PATCH 116/855] remove useless type annotations These annotations all had a default initializer of the correct type, or a parent class annotation. --- mesonbuild/arglist.py | 6 +++--- mesonbuild/ast/introspection.py | 2 +- mesonbuild/backend/ninjabackend.py | 4 ++-- mesonbuild/cmake/common.py | 24 ++++++++++++------------ mesonbuild/cmake/generator.py | 12 ++++++------ mesonbuild/cmake/traceparser.py | 6 +++--- mesonbuild/compilers/mixins/arm.py | 2 +- mesonbuild/compilers/mixins/xc16.py | 2 +- mesonbuild/dependencies/boost.py | 2 +- mesonbuild/dependencies/cuda.py | 4 ++-- mesonbuild/envconfig.py | 2 +- mesonbuild/interpreterbase/decorators.py | 6 +++--- mesonbuild/mcompile.py | 2 +- mesonbuild/mparser.py | 6 +++--- mesonbuild/mtest.py | 6 +++--- 15 files changed, 43 insertions(+), 43 deletions(-) diff --git a/mesonbuild/arglist.py b/mesonbuild/arglist.py index c44728ab762b..dfb3dcd414c7 100644 --- a/mesonbuild/arglist.py +++ b/mesonbuild/arglist.py @@ -26,7 +26,7 @@ from .compilers import Compiler # execinfo is a compiler lib on BSD -UNIXY_COMPILER_INTERNAL_LIBS = ['m', 'c', 'pthread', 'dl', 'rt', 'execinfo'] # type: T.List[str] +UNIXY_COMPILER_INTERNAL_LIBS = ['m', 'c', 'pthread', 'dl', 'rt', 'execinfo'] class Dedup(enum.Enum): @@ -94,7 +94,7 @@ class CompilerArgs(T.MutableSequence[str]): # NOTE: not thorough. A list of potential corner cases can be found in # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 dedup1_prefixes = () # type: T.Tuple[str, ...] - dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # type: T.Tuple[str, ...] + dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # Match a .so of the form path/to/libfoo.so.0.1.0 # Only UNIX shared libraries require this. Others have a fixed extension. dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') @@ -102,7 +102,7 @@ class CompilerArgs(T.MutableSequence[str]): # In generate_link() we add external libs without de-dup, but we must # *always* de-dup these because they're special arguments to the linker # TODO: these should probably move too - always_dedup_args = tuple('-l' + lib for lib in UNIXY_COMPILER_INTERNAL_LIBS) # type : T.Tuple[str, ...] + always_dedup_args = tuple('-l' + lib for lib in UNIXY_COMPILER_INTERNAL_LIBS) def __init__(self, compiler: T.Union['Compiler', 'StaticLinker'], iterable: T.Optional[T.Iterable[str]] = None): diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index d66e73f3e320..d31b29fa79d6 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -46,7 +46,7 @@ class IntrospectionHelper(argparse.Namespace): # mimic an argparse namespace def __init__(self, cross_file: str): super().__init__() - self.cross_file = cross_file # type: str + self.cross_file = cross_file self.native_file = None # type: str self.cmd_line_options = {} # type: T.Dict[str, str] diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3ddc197aece7..72c826517ba9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3815,7 +3815,7 @@ def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compi # a common occurrence, which would lead to lots of # distracting noise. continue - srcfile = srcdir / tdeps[usename].fname # type: Path + srcfile = srcdir / tdeps[usename].fname if not srcfile.is_file(): if srcfile.name != src.name: # generated source file pass @@ -3837,7 +3837,7 @@ def _scan_fortran_file_deps(src: Path, srcdir: Path, dirname: Path, tdeps, compi ancestor_child = '_'.join(parents) if ancestor_child not in tdeps: raise MesonException("submodule {} relies on ancestor module {} that was not found.".format(submodmatch.group(2).lower(), ancestor_child.split('_', maxsplit=1)[0])) - submodsrcfile = srcdir / tdeps[ancestor_child].fname # type: Path + submodsrcfile = srcdir / tdeps[ancestor_child].fname if not submodsrcfile.is_file(): if submodsrcfile.name != src.name: # generated source file pass diff --git a/mesonbuild/cmake/common.py b/mesonbuild/cmake/common.py index 3de6c16ace3c..002cda713e60 100644 --- a/mesonbuild/cmake/common.py +++ b/mesonbuild/cmake/common.py @@ -167,10 +167,10 @@ def __repr__(self) -> str: class CMakeFileGroup: def __init__(self, data: T.Dict[str, T.Any]) -> None: self.defines = data.get('defines', '') # type: str - self.flags = _flags_to_list(data.get('compileFlags', '')) # type: T.List[str] + self.flags = _flags_to_list(data.get('compileFlags', '')) self.is_generated = data.get('isGenerated', False) # type: bool self.language = data.get('language', 'C') # type: str - self.sources = [Path(x) for x in data.get('sources', [])] # type: T.List[Path] + self.sources = [Path(x) for x in data.get('sources', [])] # Fix the include directories self.includes = [] # type: T.List[CMakeInclude] @@ -196,18 +196,18 @@ def log(self) -> None: class CMakeTarget: def __init__(self, data: T.Dict[str, T.Any]) -> None: - self.artifacts = [Path(x) for x in data.get('artifacts', [])] # type: T.List[Path] - self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path - self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.artifacts = [Path(x) for x in data.get('artifacts', [])] + self.src_dir = Path(data.get('sourceDirectory', '')) + self.build_dir = Path(data.get('buildDirectory', '')) self.name = data.get('name', '') # type: str self.full_name = data.get('fullName', '') # type: str self.install = data.get('hasInstallRule', False) # type: bool - self.install_paths = [Path(x) for x in set(data.get('installPaths', []))] # type: T.List[Path] + self.install_paths = [Path(x) for x in set(data.get('installPaths', []))] self.link_lang = data.get('linkerLanguage', '') # type: str - self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) # type: T.List[str] - self.link_flags = _flags_to_list(data.get('linkFlags', '')) # type: T.List[str] - self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) # type: T.List[str] - # self.link_path = Path(data.get('linkPath', '')) # type: Path + self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) + self.link_flags = _flags_to_list(data.get('linkFlags', '')) + self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) + # self.link_path = Path(data.get('linkPath', '')) self.type = data.get('type', 'EXECUTABLE') # type: str # self.is_generator_provided = data.get('isGeneratorProvided', False) # type: bool self.files = [] # type: T.List[CMakeFileGroup] @@ -237,8 +237,8 @@ def log(self) -> None: class CMakeProject: def __init__(self, data: T.Dict[str, T.Any]) -> None: - self.src_dir = Path(data.get('sourceDirectory', '')) # type: Path - self.build_dir = Path(data.get('buildDirectory', '')) # type: Path + self.src_dir = Path(data.get('sourceDirectory', '')) + self.build_dir = Path(data.get('buildDirectory', '')) self.name = data.get('name', '') # type: str self.targets = [] # type: T.List[CMakeTarget] diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py index 5b83479196b6..f47625c83fa6 100644 --- a/mesonbuild/cmake/generator.py +++ b/mesonbuild/cmake/generator.py @@ -38,8 +38,8 @@ def parse_generator_expressions( if '$<' not in raw: return raw - out = '' # type: str - i = 0 # type: int + out = '' + i = 0 def equal(arg: str) -> str: col_pos = arg.find(',') @@ -147,10 +147,10 @@ def eval_generator_expressions() -> str: nonlocal i i += 2 - func = '' # type: str - args = '' # type: str - res = '' # type: str - exp = '' # type: str + func = '' + args = '' + res = '' + exp = '' # Determine the body of the expression while i < len(raw): diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py index 7f31f137f80b..92ff7803bb3c 100644 --- a/mesonbuild/cmake/traceparser.py +++ b/mesonbuild/cmake/traceparser.py @@ -107,8 +107,8 @@ def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', perm self.custom_targets = [] # type: T.List[CMakeGeneratorTarget] self.env = env - self.permissive = permissive # type: bool - self.cmake_version = cmake_version # type: str + self.permissive = permissive + self.cmake_version = cmake_version self.trace_file = 'cmake_trace.txt' self.trace_file_path = build_dir / self.trace_file self.trace_format = 'json-v1' if version_compare(cmake_version, '>=3.17') else 'human' @@ -785,7 +785,7 @@ def _guess_files(self, broken_list: T.List[str]) -> T.List[str]: fixed_list = [] # type: T.List[str] curr_str = None # type: T.Optional[str] - path_found = False # type: bool + path_found = False for i in broken_list: if curr_str is None: diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index 7c533273923c..22595a8c87c2 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -87,7 +87,7 @@ def __init__(self) -> None: '1': default_warn_args, '2': default_warn_args + [], '3': default_warn_args + [], - 'everything': default_warn_args + []} # type: T.Dict[str, T.List[str]] + 'everything': default_warn_args + []} # Assembly self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('sx') diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py index 36c2c10ab9bd..8957dd960e76 100644 --- a/mesonbuild/compilers/mixins/xc16.py +++ b/mesonbuild/compilers/mixins/xc16.py @@ -71,7 +71,7 @@ def __init__(self) -> None: '1': default_warn_args, '2': default_warn_args + [], '3': default_warn_args + [], - 'everything': default_warn_args + []} # type: T.Dict[str, T.List[str]] + 'everything': default_warn_args + []} def get_always_args(self) -> T.List[str]: return [] diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 0a936e65e1cd..648c8d2e1a57 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -333,7 +333,7 @@ def vscrt_matches(self, vscrt: str) -> bool: def get_compiler_args(self) -> T.List[str]: args = [] # type: T.List[str] if self.mod_name in boost_libraries: - libdef = boost_libraries[self.mod_name] # type: BoostLibrary + libdef = boost_libraries[self.mod_name] if self.static: args += libdef.static else: diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index af0ae4b1f569..e16808b6a5c8 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -195,8 +195,8 @@ def _read_cuda_runtime_api_version(self, path_str: str) -> T.Optional[str]: except ValueError: continue # use // for floor instead of / which produces a float - major = vers_int // 1000 # type: int - minor = (vers_int - major * 1000) // 10 # type: int + major = vers_int // 1000 + minor = (vers_int - major * 1000) // 10 return f'{major}.{minor}' return None diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 7e0c56703121..56dee650d8c8 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -161,7 +161,7 @@ def __init__( self, properties: T.Optional[T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]]] = None, ): - self.properties = properties or {} # type: T.Dict[str, T.Optional[T.Union[str, bool, int, T.List[str]]]] + self.properties = properties or {} def has_stdlib(self, language: str) -> bool: return language + '_stdlib' in self.properties diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index cecdbfdfd392..5bb8306a563b 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -606,9 +606,9 @@ class FeatureCheckBase(metaclass=abc.ABCMeta): unconditional = False def __init__(self, feature_name: str, feature_version: str, extra_message: str = ''): - self.feature_name = feature_name # type: str - self.feature_version = feature_version # type: str - self.extra_message = extra_message # type: str + self.feature_name = feature_name + self.feature_version = feature_version + self.extra_message = extra_message @staticmethod def get_target_version(subproject: str) -> str: diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 4e46702f04fd..7ae7175e8b03 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -174,7 +174,7 @@ def generate_target_name_vs(target: ParsedTargetName, builddir: Path, introspect # Normalize project name # Source: https://docs.microsoft.com/en-us/visualstudio/msbuild/how-to-build-specific-targets-in-solutions-by-using-msbuild-exe - target_name = re.sub(r"[\%\$\@\;\.\(\)']", '_', intro_target['id']) # type: str + target_name = re.sub(r"[\%\$\@\;\.\(\)']", '_', intro_target['id']) rel_path = Path(intro_target['filename'][0]).relative_to(builddir.resolve()).parent if rel_path != Path('.'): target_name = str(rel_path / target_name) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 85f1ef33afe1..d4ddff929cb5 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -811,7 +811,7 @@ def e9(self) -> BaseNode: return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) def key_values(self) -> ArgumentNode: - s = self.statement() # type: BaseNode + s = self.statement() a = ArgumentNode(self.current) while not isinstance(s, EmptyNode): @@ -828,7 +828,7 @@ def key_values(self) -> ArgumentNode: return a def args(self) -> ArgumentNode: - s = self.statement() # type: BaseNode + s = self.statement() a = ArgumentNode(self.current) while not isinstance(s, EmptyNode): @@ -875,7 +875,7 @@ def foreachblock(self) -> ForeachClauseNode: self.expect('id') assert isinstance(t.value, str) varname = t - varnames = [t.value] # type: T.List[str] + varnames = [t.value] if self.accept('comma'): t = self.current diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 0e1086c35c78..2ee337c8b4ed 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -524,7 +524,7 @@ def __init__(self) -> None: self.running_tests = OrderedSet() # type: OrderedSet['TestRun'] self.progress_test = None # type: T.Optional['TestRun'] self.progress_task = None # type: T.Optional[asyncio.Future] - self.max_left_width = 0 # type: int + self.max_left_width = 0 self.stop = False # TODO: before 3.10 this cannot be created immediately, because # it will create a new event loop @@ -933,7 +933,7 @@ def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str], self.stde = '' self.additional_error = '' self.cmd = None # type: T.Optional[T.List[str]] - self.env = test_env # type: T.Dict[str, str] + self.env = test_env self.should_fail = test.should_fail self.project = test.project_name self.junit = None # type: T.Optional[et.ElementTree] @@ -1285,7 +1285,7 @@ def __init__(self, p: asyncio.subprocess.Process, self.stderr = stderr self.stdo_task: T.Optional[asyncio.Task[None]] = None self.stde_task: T.Optional[asyncio.Task[None]] = None - self.postwait_fn = postwait_fn # type: T.Callable[[], None] + self.postwait_fn = postwait_fn self.all_futures = [] # type: T.List[asyncio.Future] self.queue = None # type: T.Optional[asyncio.Queue[T.Optional[str]]] From de1cc0b02bcb1bab6977f0ab8bb3fef0cd0646dd Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 11 Aug 2023 12:57:16 -0400 Subject: [PATCH 117/855] rewrite a couple comment-style type annotations for oddly indented dicts Make them into real type annotations. These are the only ones that if automatically rewritten, would cause flake8 to error out with the message: "E128 continuation line under-indented for visual indent". --- mesonbuild/mintro.py | 16 ++++++++++------ mesonbuild/mtest.py | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 9657da7c6b8c..14f8d86b6d21 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -477,14 +477,18 @@ def list_machines(builddata: build.Build) -> T.Dict[str, T.Dict[str, T.Union[str return machines def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]: - result = {'version': builddata.project_version, - 'descriptive_name': builddata.project_name, - 'subproject_dir': builddata.subproject_dir} # type: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]] + result: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]] = { + 'version': builddata.project_version, + 'descriptive_name': builddata.project_name, + 'subproject_dir': builddata.subproject_dir, + } subprojects = [] for k, v in builddata.subprojects.items(): - c = {'name': k, - 'version': v, - 'descriptive_name': builddata.projects.get(k)} # type: T.Dict[str, str] + c: T.Dict[str, str] = { + 'name': k, + 'version': v, + 'descriptive_name': builddata.projects.get(k), + } subprojects.append(c) result['subprojects'] = subprojects return result diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 2ee337c8b4ed..36afd6128b11 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -770,14 +770,16 @@ async def finish(self, harness: 'TestHarness') -> None: class JsonLogfileBuilder(TestFileLogger): def log(self, harness: 'TestHarness', result: 'TestRun') -> None: - jresult = {'name': result.name, - 'stdout': result.stdo, - 'result': result.res.value, - 'starttime': result.starttime, - 'duration': result.duration, - 'returncode': result.returncode, - 'env': result.env, - 'command': result.cmd} # type: T.Dict[str, T.Any] + jresult: T.Dict[str, T.Any] = { + 'name': result.name, + 'stdout': result.stdo, + 'result': result.res.value, + 'starttime': result.starttime, + 'duration': result.duration, + 'returncode': result.returncode, + 'env': result.env, + 'command': result.cmd, + } if result.stde: jresult['stderr'] = result.stde self.file.write(json.dumps(jresult) + '\n') From 90ce0841441506e3f409ab59ded1df8f2e6e7363 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 10 Aug 2023 21:19:29 -0400 Subject: [PATCH 118/855] treewide: automatic rewriting of all comment-style type annotations Performed using https://github.com/ilevkivskyi/com2ann This has no actual effect on the codebase as type checkers (still) support both and negligible effect on runtime performance since __future__ annotations ameliorates that. Technically, the bytecode would be bigger for non function-local annotations, of which we have many either way. So if it doesn't really matter, why do a large-scale refactor? Simple: because people keep wanting to, but it's getting nickle-and-dimed. If we're going to do this we might as well do it consistently in one shot, using tooling that guarantees repeatability and correctness. Repeat with: ``` com2ann mesonbuild/ ``` --- mesonbuild/arglist.py | 28 +++++----- mesonbuild/ast/interpreter.py | 16 +++--- mesonbuild/ast/introspection.py | 20 +++---- mesonbuild/ast/postprocess.py | 2 +- mesonbuild/ast/printer.py | 12 ++-- mesonbuild/build.py | 4 +- mesonbuild/cmake/common.py | 42 +++++++------- mesonbuild/cmake/executor.py | 10 ++-- mesonbuild/cmake/fileapi.py | 4 +- mesonbuild/cmake/generator.py | 4 +- mesonbuild/cmake/toolchain.py | 6 +- mesonbuild/cmake/traceparser.py | 36 ++++++------ mesonbuild/compilers/cs.py | 4 +- mesonbuild/compilers/detect.py | 2 +- mesonbuild/compilers/mixins/arm.py | 18 +++--- mesonbuild/compilers/mixins/pgi.py | 4 +- mesonbuild/compilers/mixins/xc16.py | 14 ++--- mesonbuild/compilers/rust.py | 4 +- mesonbuild/compilers/swift.py | 4 +- mesonbuild/dependencies/base.py | 2 +- mesonbuild/dependencies/boost.py | 38 ++++++------- mesonbuild/dependencies/cmake.py | 4 +- mesonbuild/dependencies/hdf5.py | 4 +- mesonbuild/dependencies/mpi.py | 2 +- mesonbuild/envconfig.py | 2 +- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreterbase/interpreterbase.py | 4 +- mesonbuild/linkers/detect.py | 4 +- mesonbuild/mcompile.py | 8 +-- mesonbuild/mintro.py | 26 ++++----- mesonbuild/mlog.py | 8 +-- mesonbuild/modules/cmake.py | 2 +- mesonbuild/mparser.py | 4 +- mesonbuild/mtest.py | 56 +++++++++---------- mesonbuild/scripts/cmake_run_ctgt.py | 2 +- mesonbuild/scripts/depfixer.py | 6 +- mesonbuild/utils/universal.py | 2 +- mesonbuild/wrap/wrap.py | 18 +++--- 38 files changed, 214 insertions(+), 214 deletions(-) diff --git a/mesonbuild/arglist.py b/mesonbuild/arglist.py index dfb3dcd414c7..f50d54eed822 100644 --- a/mesonbuild/arglist.py +++ b/mesonbuild/arglist.py @@ -82,23 +82,23 @@ class CompilerArgs(T.MutableSequence[str]): ''' # Arg prefixes that override by prepending instead of appending - prepend_prefixes = () # type: T.Tuple[str, ...] + prepend_prefixes: T.Tuple[str, ...] = () # Arg prefixes and args that must be de-duped by returning 2 - dedup2_prefixes = () # type: T.Tuple[str, ...] - dedup2_suffixes = () # type: T.Tuple[str, ...] - dedup2_args = () # type: T.Tuple[str, ...] + dedup2_prefixes: T.Tuple[str, ...] = () + dedup2_suffixes: T.Tuple[str, ...] = () + dedup2_args: T.Tuple[str, ...] = () # Arg prefixes and args that must be de-duped by returning 1 # # NOTE: not thorough. A list of potential corner cases can be found in # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 - dedup1_prefixes = () # type: T.Tuple[str, ...] + dedup1_prefixes: T.Tuple[str, ...] = () dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') # Match a .so of the form path/to/libfoo.so.0.1.0 # Only UNIX shared libraries require this. Others have a fixed extension. dedup1_regex = re.compile(r'([\/\\]|\A)lib.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') - dedup1_args = () # type: T.Tuple[str, ...] + dedup1_args: T.Tuple[str, ...] = () # In generate_link() we add external libs without de-dup, but we must # *always* de-dup these because they're special arguments to the linker # TODO: these should probably move too @@ -107,19 +107,19 @@ class CompilerArgs(T.MutableSequence[str]): def __init__(self, compiler: T.Union['Compiler', 'StaticLinker'], iterable: T.Optional[T.Iterable[str]] = None): self.compiler = compiler - self._container = list(iterable) if iterable is not None else [] # type: T.List[str] - self.pre = collections.deque() # type: T.Deque[str] - self.post = collections.deque() # type: T.Deque[str] + self._container: T.List[str] = list(iterable) if iterable is not None else [] + self.pre: T.Deque[str] = collections.deque() + self.post: T.Deque[str] = collections.deque() # Flush the saved pre and post list into the _container list # # This correctly deduplicates the entries after _can_dedup definition # Note: This function is designed to work without delete operations, as deletions are worsening the performance a lot. def flush_pre_post(self) -> None: - new = [] # type: T.List[str] - pre_flush_set = set() # type: T.Set[str] - post_flush = collections.deque() # type: T.Deque[str] - post_flush_set = set() # type: T.Set[str] + new: T.List[str] = [] + pre_flush_set: T.Set[str] = set() + post_flush: T.Deque[str] = collections.deque() + post_flush_set: T.Set[str] = set() #The two lists are here walked from the front to the back, in order to not need removals for deduplication for a in self.pre: @@ -285,7 +285,7 @@ def __iadd__(self, args: T.Iterable[str]) -> 'CompilerArgs': Add two CompilerArgs while taking into account overriding of arguments and while preserving the order of arguments as much as possible ''' - tmp_pre = collections.deque() # type: T.Deque[str] + tmp_pre: T.Deque[str] = collections.deque() if not isinstance(args, collections.abc.Iterable): raise TypeError(f'can only concatenate Iterable[str] (not "{args}") to CompilerArgs') for arg in args: diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 68e2b6e5254f..70a4f1f46e4d 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -97,10 +97,10 @@ class AstInterpreter(InterpreterBase): def __init__(self, source_root: str, subdir: str, subproject: str, visitors: T.Optional[T.List[AstVisitor]] = None): super().__init__(source_root, subdir, subproject) self.visitors = visitors if visitors is not None else [] - self.processed_buildfiles = set() # type: T.Set[str] - self.assignments = {} # type: T.Dict[str, BaseNode] - self.assign_vals = {} # type: T.Dict[str, T.Any] - self.reverse_assignment = {} # type: T.Dict[str, BaseNode] + self.processed_buildfiles: T.Set[str] = set() + self.assignments: T.Dict[str, BaseNode] = {} + self.assign_vals: T.Dict[str, T.Any] = {} + self.reverse_assignment: T.Dict[str, BaseNode] = {} self.funcs.update({'project': self.func_do_nothing, 'test': self.func_do_nothing, 'benchmark': self.func_do_nothing, @@ -274,7 +274,7 @@ def reduce_arguments( duplicate_key_error: T.Optional[str] = None, ) -> T.Tuple[T.List[TYPE_nvar], TYPE_nkwargs]: if isinstance(args, ArgumentNode): - kwargs = {} # type: T.Dict[str, TYPE_nvar] + kwargs: T.Dict[str, TYPE_nvar] = {} for key, val in args.kwargs.items(): kwargs[key_resolver(key)] = val if args.incorrect_order(): @@ -383,7 +383,7 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T elif isinstance(node, MethodNode): src = quick_resolve(node.source_object) margs = self.flatten_args(node.args.arguments, include_unknown_args, id_loop_detect) - mkwargs = {} # type: T.Dict[str, TYPE_nvar] + mkwargs: T.Dict[str, TYPE_nvar] = {} try: if isinstance(src, str): result = StringHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) @@ -402,7 +402,7 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T if isinstance(result, BaseNode): result = self.resolve_node(result, include_unknown_args, id_loop_detect) elif isinstance(result, list): - new_res = [] # type: T.List[TYPE_nvar] + new_res: T.List[TYPE_nvar] = [] for i in result: if isinstance(i, BaseNode): resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) @@ -421,7 +421,7 @@ def flatten_args(self, args_raw: T.Union[TYPE_nvar, T.Sequence[TYPE_nvar]], incl else: args = [args_raw] - flattened_args = [] # type: T.List[TYPE_nvar] + flattened_args: T.List[TYPE_nvar] = [] # Resolve the contents of args for i in args: diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index d31b29fa79d6..e8055c5299de 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -47,8 +47,8 @@ class IntrospectionHelper(argparse.Namespace): def __init__(self, cross_file: str): super().__init__() self.cross_file = cross_file - self.native_file = None # type: str - self.cmd_line_options = {} # type: T.Dict[str, str] + self.native_file: str = None + self.cmd_line_options: T.Dict[str, str] = {} def __eq__(self, other: object) -> bool: return NotImplemented @@ -78,10 +78,10 @@ def __init__(self, self.coredata = self.environment.get_coredata() self.backend = backend self.default_options = {OptionKey('backend'): self.backend} - self.project_data = {} # type: T.Dict[str, T.Any] - self.targets = [] # type: T.List[T.Dict[str, T.Any]] - self.dependencies = [] # type: T.List[T.Dict[str, T.Any]] - self.project_node = None # type: BaseNode + self.project_data: T.Dict[str, T.Any] = {} + self.targets: T.List[T.Dict[str, T.Any]] = [] + self.dependencies: T.List[T.Dict[str, T.Any]] = [] + self.project_node: BaseNode = None self.funcs.update({ 'add_languages': self.func_add_languages, @@ -170,7 +170,7 @@ def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T. self._add_languages(args, required, for_machine) def _add_languages(self, raw_langs: T.List[TYPE_nvar], required: bool, for_machine: MachineChoice) -> None: - langs = [] # type: T.List[str] + langs: T.List[str] = [] for l in self.flatten_args(raw_langs): if isinstance(l, str): langs.append(l) @@ -238,7 +238,7 @@ def build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs_raw: T.Di kwargs = self.flatten_kwargs(kwargs_raw, True) def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: - res = [] # type: T.List[BaseNode] + res: T.List[BaseNode] = [] while inqueue: curr = inqueue.pop(0) arg_node = None @@ -277,8 +277,8 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()} kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)} for_machine = MachineChoice.HOST - objects = [] # type: T.List[T.Any] - empty_sources = [] # type: T.List[T.Any] + objects: T.List[T.Any] = [] + empty_sources: T.List[T.Any] = [] # Passing the unresolved sources list causes errors kwargs_reduced['_allow_no_sources'] = True target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, [], objects, diff --git a/mesonbuild/ast/postprocess.py b/mesonbuild/ast/postprocess.py index 09c339dd6ace..7d2036ed405d 100644 --- a/mesonbuild/ast/postprocess.py +++ b/mesonbuild/ast/postprocess.py @@ -80,7 +80,7 @@ def visit_IfNode(self, node: mparser.IfNode) -> None: class AstIDGenerator(AstVisitor): def __init__(self) -> None: - self.counter = {} # type: T.Dict[str, int] + self.counter: T.Dict[str, int] = {} def visit_default_func(self, node: mparser.BaseNode) -> None: name = type(node).__name__ diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 579a83d00011..ebf63afebe2b 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -240,12 +240,12 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: class AstJSONPrinter(AstVisitor): def __init__(self) -> None: - self.result = {} # type: T.Dict[str, T.Any] + self.result: T.Dict[str, T.Any] = {} self.current = self.result def _accept(self, key: str, node: mparser.BaseNode) -> None: old = self.current - data = {} # type: T.Dict[str, T.Any] + data: T.Dict[str, T.Any] = {} self.current = data node.accept(self) self.current = old @@ -253,7 +253,7 @@ def _accept(self, key: str, node: mparser.BaseNode) -> None: def _accept_list(self, key: str, nodes: T.Sequence[mparser.BaseNode]) -> None: old = self.current - datalist = [] # type: T.List[T.Dict[str, T.Any]] + datalist: T.List[T.Dict[str, T.Any]] = [] for i in nodes: self.current = {} i.accept(self) @@ -388,10 +388,10 @@ def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: self._accept_list('positional', node.arguments) - kwargs_list = [] # type: T.List[T.Dict[str, T.Dict[str, T.Any]]] + kwargs_list: T.List[T.Dict[str, T.Dict[str, T.Any]]] = [] for key, val in node.kwargs.items(): - key_res = {} # type: T.Dict[str, T.Any] - val_res = {} # type: T.Dict[str, T.Any] + key_res: T.Dict[str, T.Any] = {} + val_res: T.Dict[str, T.Any] = {} self._raw_accept(key, key_res) self._raw_accept(val, val_res) kwargs_list += [{'key': key_res, 'val': val_res}] diff --git a/mesonbuild/build.py b/mesonbuild/build.py index a0a38d0ac4a7..e5cdfea5ac48 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -723,7 +723,7 @@ def __init__( kwargs): super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False)) self.all_compilers = compilers - self.compilers = OrderedDict() # type: OrderedDict[str, Compiler] + self.compilers: OrderedDict[str, Compiler] = OrderedDict() self.objects: T.List[ObjectTypes] = [] self.structured_sources = structured_sources self.external_deps: T.List[dependencies.Dependency] = [] @@ -1539,7 +1539,7 @@ def get_langs_used_by_deps(self) -> T.List[str]: See: https://github.com/mesonbuild/meson/issues/1653 ''' - langs = [] # type: T.List[str] + langs: T.List[str] = [] # Check if any of the external libraries were written in this language for dep in self.external_deps: diff --git a/mesonbuild/cmake/common.py b/mesonbuild/cmake/common.py index 002cda713e60..415937ee9d3d 100644 --- a/mesonbuild/cmake/common.py +++ b/mesonbuild/cmake/common.py @@ -123,7 +123,7 @@ def cmake_get_generator_args(env: 'Environment') -> T.List[str]: return ['-G', backend_generator_map[backend_name]] def cmake_defines_to_args(raw: T.List[T.Dict[str, TYPE_var]], permissive: bool = False) -> T.List[str]: - res = [] # type: T.List[str] + res: T.List[str] = [] for i in raw: for key, val in i.items(): @@ -144,7 +144,7 @@ def cmake_defines_to_args(raw: T.List[T.Dict[str, TYPE_var]], permissive: bool = # TODO: this function will become obsolete once the `cmake_args` kwarg is dropped def check_cmake_args(args: T.List[str]) -> T.List[str]: - res = [] # type: T.List[str] + res: T.List[str] = [] dis = ['-D' + x for x in blacklist_cmake_defs] assert dis # Ensure that dis is not empty. for i in args: @@ -166,14 +166,14 @@ def __repr__(self) -> str: class CMakeFileGroup: def __init__(self, data: T.Dict[str, T.Any]) -> None: - self.defines = data.get('defines', '') # type: str + self.defines: str = data.get('defines', '') self.flags = _flags_to_list(data.get('compileFlags', '')) - self.is_generated = data.get('isGenerated', False) # type: bool - self.language = data.get('language', 'C') # type: str + self.is_generated: bool = data.get('isGenerated', False) + self.language: str = data.get('language', 'C') self.sources = [Path(x) for x in data.get('sources', [])] # Fix the include directories - self.includes = [] # type: T.List[CMakeInclude] + self.includes: T.List[CMakeInclude] = [] for i in data.get('includePath', []): if isinstance(i, dict) and 'path' in i: isSystem = i.get('isSystem', False) @@ -199,18 +199,18 @@ def __init__(self, data: T.Dict[str, T.Any]) -> None: self.artifacts = [Path(x) for x in data.get('artifacts', [])] self.src_dir = Path(data.get('sourceDirectory', '')) self.build_dir = Path(data.get('buildDirectory', '')) - self.name = data.get('name', '') # type: str - self.full_name = data.get('fullName', '') # type: str - self.install = data.get('hasInstallRule', False) # type: bool + self.name: str = data.get('name', '') + self.full_name: str = data.get('fullName', '') + self.install: bool = data.get('hasInstallRule', False) self.install_paths = [Path(x) for x in set(data.get('installPaths', []))] - self.link_lang = data.get('linkerLanguage', '') # type: str + self.link_lang: str = data.get('linkerLanguage', '') self.link_libraries = _flags_to_list(data.get('linkLibraries', '')) self.link_flags = _flags_to_list(data.get('linkFlags', '')) self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) # self.link_path = Path(data.get('linkPath', '')) - self.type = data.get('type', 'EXECUTABLE') # type: str + self.type: str = data.get('type', 'EXECUTABLE') # self.is_generator_provided = data.get('isGeneratorProvided', False) # type: bool - self.files = [] # type: T.List[CMakeFileGroup] + self.files: T.List[CMakeFileGroup] = [] for i in data.get('fileGroups', []): self.files += [CMakeFileGroup(i)] @@ -239,8 +239,8 @@ class CMakeProject: def __init__(self, data: T.Dict[str, T.Any]) -> None: self.src_dir = Path(data.get('sourceDirectory', '')) self.build_dir = Path(data.get('buildDirectory', '')) - self.name = data.get('name', '') # type: str - self.targets = [] # type: T.List[CMakeTarget] + self.name: str = data.get('name', '') + self.targets: T.List[CMakeTarget] = [] for i in data.get('targets', []): self.targets += [CMakeTarget(i)] @@ -256,8 +256,8 @@ def log(self) -> None: class CMakeConfiguration: def __init__(self, data: T.Dict[str, T.Any]) -> None: - self.name = data.get('name', '') # type: str - self.projects = [] # type: T.List[CMakeProject] + self.name: str = data.get('name', '') + self.projects: T.List[CMakeProject] = [] for i in data.get('projects', []): self.projects += [CMakeProject(i)] @@ -270,9 +270,9 @@ def log(self) -> None: class SingleTargetOptions: def __init__(self) -> None: - self.opts = {} # type: T.Dict[str, str] - self.lang_args = {} # type: T.Dict[str, T.List[str]] - self.link_args = [] # type: T.List[str] + self.opts: T.Dict[str, str] = {} + self.lang_args: T.Dict[str, T.List[str]] = {} + self.link_args: T.List[str] = [] self.install = 'preserve' def set_opt(self, opt: str, val: str) -> None: @@ -290,7 +290,7 @@ def set_install(self, install: bool) -> None: self.install = 'true' if install else 'false' def get_override_options(self, initial: T.List[str]) -> T.List[str]: - res = [] # type: T.List[str] + res: T.List[str] = [] for i in initial: opt = i[:i.find('=')] if opt not in self.opts: @@ -312,7 +312,7 @@ def get_install(self, initial: bool) -> bool: class TargetOptions: def __init__(self) -> None: self.global_options = SingleTargetOptions() - self.target_options = {} # type: T.Dict[str, SingleTargetOptions] + self.target_options: T.Dict[str, SingleTargetOptions] = {} def __getitem__(self, tgt: str) -> SingleTargetOptions: if tgt not in self.target_options: diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py index c22c0ca99893..7958baf0c62b 100644 --- a/mesonbuild/cmake/executor.py +++ b/mesonbuild/cmake/executor.py @@ -39,9 +39,9 @@ class CMakeExecutor: # The class's copy of the CMake path. Avoids having to search for it # multiple times in the same Meson invocation. - class_cmakebin = PerMachine(None, None) # type: PerMachine[T.Optional[ExternalProgram]] - class_cmakevers = PerMachine(None, None) # type: PerMachine[T.Optional[str]] - class_cmake_cache = {} # type: T.Dict[T.Any, TYPE_result] + class_cmakebin: PerMachine[T.Optional[ExternalProgram]] = PerMachine(None, None) + class_cmakevers: PerMachine[T.Optional[str]] = PerMachine(None, None) + class_cmake_cache: T.Dict[T.Any, TYPE_result] = {} def __init__(self, environment: 'Environment', version: str, for_machine: MachineChoice, silent: bool = False): self.min_version = version @@ -50,8 +50,8 @@ def __init__(self, environment: 'Environment', version: str, for_machine: Machin self.cmakebin, self.cmakevers = self.find_cmake_binary(self.environment, silent=silent) self.always_capture_stderr = True self.print_cmout = False - self.prefix_paths = [] # type: T.List[str] - self.extra_cmake_args = [] # type: T.List[str] + self.prefix_paths: T.List[str] = [] + self.extra_cmake_args: T.List[str] = [] if self.cmakebin is None: return diff --git a/mesonbuild/cmake/fileapi.py b/mesonbuild/cmake/fileapi.py index 9605f920da4a..baf499fc0b1b 100644 --- a/mesonbuild/cmake/fileapi.py +++ b/mesonbuild/cmake/fileapi.py @@ -28,8 +28,8 @@ def __init__(self, build_dir: Path): self.api_base_dir = self.build_dir / '.cmake' / 'api' / 'v1' self.request_dir = self.api_base_dir / 'query' / 'client-meson' self.reply_dir = self.api_base_dir / 'reply' - self.cmake_sources = [] # type: T.List[CMakeBuildFile] - self.cmake_configurations = [] # type: T.List[CMakeConfiguration] + self.cmake_sources: T.List[CMakeBuildFile] = [] + self.cmake_configurations: T.List[CMakeConfiguration] = [] self.kind_resolver_map = { 'codemodel': self._parse_codemodel, 'cmakeFiles': self._parse_cmakeFiles, diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py index f47625c83fa6..750e4c28296c 100644 --- a/mesonbuild/cmake/generator.py +++ b/mesonbuild/cmake/generator.py @@ -98,7 +98,7 @@ def target_file(arg: str) -> str: return ';'.join([x for x in tgt.properties['IMPORTED_LOCATION'] if x]) return '' - supported = { + supported: T.Dict[str, T.Callable[[str], str]] = { # Boolean functions 'BOOL': lambda x: '0' if x.upper() in {'', '0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'} or x.endswith('-NOTFOUND') else '1', 'AND': lambda x: '1' if all(y == '1' for y in x.split(',')) else '0', @@ -140,7 +140,7 @@ def target_file(arg: str) -> str: 'TARGET_NAME_IF_EXISTS': lambda x: x if x in trace.targets else '', 'TARGET_PROPERTY': target_property, 'TARGET_FILE': target_file, - } # type: T.Dict[str, T.Callable[[str], str]] + } # Recursively evaluate generator expressions def eval_generator_expressions() -> str: diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py index 477629e81164..be5bd66fd9bb 100644 --- a/mesonbuild/cmake/toolchain.py +++ b/mesonbuild/cmake/toolchain.py @@ -144,7 +144,7 @@ def generate_cache(self) -> str: return res def get_defaults(self) -> T.Dict[str, T.List[str]]: - defaults = {} # type: T.Dict[str, T.List[str]] + defaults: T.Dict[str, T.List[str]] = {} # Do nothing if the user does not want automatic defaults if not self.properties.get_cmake_defaults(): @@ -153,13 +153,13 @@ def get_defaults(self) -> T.Dict[str, T.List[str]]: # Best effort to map the meson system name to CMAKE_SYSTEM_NAME, which # is not trivial since CMake lacks a list of all supported # CMAKE_SYSTEM_NAME values. - SYSTEM_MAP = { + SYSTEM_MAP: T.Dict[str, str] = { 'android': 'Android', 'linux': 'Linux', 'windows': 'Windows', 'freebsd': 'FreeBSD', 'darwin': 'Darwin', - } # type: T.Dict[str, str] + } # Only set these in a cross build. Otherwise CMake will trip up in native # builds and thing they are cross (which causes TRY_RUN() to break) diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py index 92ff7803bb3c..dd0dfb57f90f 100644 --- a/mesonbuild/cmake/traceparser.py +++ b/mesonbuild/cmake/traceparser.py @@ -67,9 +67,9 @@ def __init__( self.properties = properties self.imported = imported self.tline = tline - self.depends = [] # type: T.List[str] - self.current_bin_dir = None # type: T.Optional[Path] - self.current_src_dir = None # type: T.Optional[Path] + self.depends: T.List[str] = [] + self.current_bin_dir: T.Optional[Path] = None + self.current_src_dir: T.Optional[Path] = None def __repr__(self) -> str: s = 'CMake TARGET:\n -- name: {}\n -- type: {}\n -- imported: {}\n -- properties: {{\n{} }}\n -- tline: {}' @@ -89,10 +89,10 @@ def strip_properties(self) -> None: class CMakeGeneratorTarget(CMakeTarget): def __init__(self, name: str) -> None: super().__init__(name, 'CUSTOM', {}) - self.outputs = [] # type: T.List[Path] - self._outputs_str = [] # type: T.List[str] - self.command = [] # type: T.List[T.List[str]] - self.working_dir = None # type: T.Optional[Path] + self.outputs: T.List[Path] = [] + self._outputs_str: T.List[str] = [] + self.command: T.List[T.List[str]] = [] + self.working_dir: T.Optional[Path] = None class CMakeTraceParser: def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', permissive: bool = True) -> None: @@ -101,10 +101,10 @@ def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', perm self.targets: T.Dict[str, CMakeTarget] = {} self.cache: T.Dict[str, CMakeCacheEntry] = {} - self.explicit_headers = set() # type: T.Set[Path] + self.explicit_headers: T.Set[Path] = set() # T.List of targes that were added with add_custom_command to generate files - self.custom_targets = [] # type: T.List[CMakeGeneratorTarget] + self.custom_targets: T.List[CMakeGeneratorTarget] = [] self.env = env self.permissive = permissive @@ -118,11 +118,11 @@ def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', perm # State for delayed command execution. Delayed command execution is realised # with a custom CMake file that overrides some functions and adds some # introspection information to the trace. - self.delayed_commands = [] # type: T.List[str] - self.stored_commands = [] # type: T.List[CMakeTraceLine] + self.delayed_commands: T.List[str] = [] + self.stored_commands: T.List[CMakeTraceLine] = [] # All supported functions - self.functions = { + self.functions: T.Dict[str, T.Callable[[CMakeTraceLine], None]] = { 'set': self._cmake_set, 'unset': self._cmake_unset, 'add_executable': self._cmake_add_executable, @@ -145,7 +145,7 @@ def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', perm 'meson_ps_execute_delayed_calls': self._meson_ps_execute_delayed_calls, 'meson_ps_reload_vars': self._meson_ps_reload_vars, 'meson_ps_disabled_function': self._meson_ps_disabled_function, - } # type: T.Dict[str, T.Callable[[CMakeTraceLine], None]] + } if version_compare(self.cmake_version, '<3.17.0'): mlog.deprecation(textwrap.dedent(f'''\ @@ -591,10 +591,10 @@ def _cmake_set_target_properties(self, tline: CMakeTraceLine) -> None: # With the JSON output format, introduced in CMake 3.17, spaces are # handled properly and we don't have to do either options - arglist = [] # type: T.List[T.Tuple[str, T.List[str]]] + arglist: T.List[T.Tuple[str, T.List[str]]] = [] if self.trace_format == 'human': name = args.pop(0) - values = [] # type: T.List[str] + values: T.List[str] = [] prop_regex = re.compile(r'^[A-Z_]+$') for a in args: if prop_regex.match(a): @@ -768,7 +768,7 @@ def _lex_trace_json(self, trace: str) -> T.Generator[CMakeTraceLine, None, None] def _flatten_args(self, args: T.List[str]) -> T.List[str]: # Split lists in arguments - res = [] # type: T.List[str] + res: T.List[str] = [] for i in args: res += i.split(';') return res @@ -783,8 +783,8 @@ def _guess_files(self, broken_list: T.List[str]) -> T.List[str]: reg_start = re.compile(r'^([A-Za-z]:)?/(.*/)*[^./]+$') reg_end = re.compile(r'^.*\.[a-zA-Z]+$') - fixed_list = [] # type: T.List[str] - curr_str = None # type: T.Optional[str] + fixed_list: T.List[str] = [] + curr_str: T.Optional[str] = None path_found = False for i in broken_list: diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index f0bed5fb8fdf..cd99c817580a 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -28,7 +28,7 @@ from ..environment import Environment from ..mesonlib import MachineChoice -cs_optimization_args = { +cs_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': [], 'g': [], @@ -36,7 +36,7 @@ '2': ['-optimize+'], '3': ['-optimize+'], 's': ['-optimize+'], - } # type: T.Dict[str, T.List[str]] + } class CsCompiler(BasicLinkerIsCompilerMixin, Compiler): diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 210ec4d4065a..f997247627d4 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -969,7 +969,7 @@ def detect_vala_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> RustCompiler: from . import rust from ..linkers import linkers - popen_exceptions = {} # type: T.Dict[str, Exception] + popen_exceptions: T.Dict[str, Exception] = {} compilers, _, exe_wrap = _get_compilers(env, 'rust', for_machine) is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index 22595a8c87c2..3abc0c8175ad 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -34,16 +34,16 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -arm_buildtype_args = { +arm_buildtype_args: T.Dict[str, T.List[str]] = { 'plain': [], 'debug': [], 'debugoptimized': [], 'release': [], 'minsize': [], 'custom': [], -} # type: T.Dict[str, T.List[str]] +} -arm_optimization_args = { +arm_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], 'g': ['-g'], @@ -51,18 +51,18 @@ '2': [], # Compiler defaults to -O2 '3': ['-O3', '-Otime'], 's': ['-O3'], # Compiler defaults to -Ospace -} # type: T.Dict[str, T.List[str]] +} -armclang_buildtype_args = { +armclang_buildtype_args: T.Dict[str, T.List[str]] = { 'plain': [], 'debug': [], 'debugoptimized': [], 'release': [], 'minsize': [], 'custom': [], -} # type: T.Dict[str, T.List[str]] +} -armclang_optimization_args = { +armclang_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': [], # Compiler defaults to -O0 'g': ['-g'], @@ -70,7 +70,7 @@ '2': ['-O2'], '3': ['-O3'], 's': ['-Oz'] -} # type: T.Dict[str, T.List[str]] +} class ArmCompiler(Compiler): @@ -82,7 +82,7 @@ class ArmCompiler(Compiler): def __init__(self) -> None: if not self.is_cross: raise mesonlib.EnvironmentException('armcc supports only cross-compilation.') - default_warn_args = [] # type: T.List[str] + default_warn_args: T.List[str] = [] self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + [], diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 2fa736c5866e..6362b46ac699 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -32,14 +32,14 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -pgi_buildtype_args = { +pgi_buildtype_args: T.Dict[str, T.List[str]] = { 'plain': [], 'debug': [], 'debugoptimized': [], 'release': [], 'minsize': [], 'custom': [], -} # type: T.Dict[str, T.List[str]] +} class PGICompiler(Compiler): diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py index 8957dd960e76..2b3904628417 100644 --- a/mesonbuild/compilers/mixins/xc16.py +++ b/mesonbuild/compilers/mixins/xc16.py @@ -31,16 +31,16 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -xc16_buildtype_args = { +xc16_buildtype_args: T.Dict[str, T.List[str]] = { 'plain': [], 'debug': [], 'debugoptimized': [], 'release': [], 'minsize': [], 'custom': [], -} # type: T.Dict[str, T.List[str]] +} -xc16_optimization_args = { +xc16_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], 'g': ['-O0'], @@ -48,12 +48,12 @@ '2': ['-O2'], '3': ['-O3'], 's': ['-Os'] -} # type: T.Dict[str, T.List[str]] +} -xc16_debug_args = { +xc16_debug_args: T.Dict[bool, T.List[str]] = { False: [], True: [] -} # type: T.Dict[bool, T.List[str]] +} class Xc16Compiler(Compiler): @@ -66,7 +66,7 @@ def __init__(self) -> None: # Assembly self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('sx') - default_warn_args = [] # type: T.List[str] + default_warn_args: T.List[str] = [] self.warn_args = {'0': [], '1': default_warn_args, '2': default_warn_args + [], diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index ef0390e97794..d722039d1ba2 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -32,7 +32,7 @@ from ..dependencies import Dependency -rust_optimization_args = { +rust_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': [], 'g': ['-C', 'opt-level=0'], @@ -40,7 +40,7 @@ '2': ['-C', 'opt-level=2'], '3': ['-C', 'opt-level=3'], 's': ['-C', 'opt-level=s'], -} # type: T.Dict[str, T.List[str]] +} class RustCompiler(Compiler): diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index 19866e2c0793..68ef99227113 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -26,7 +26,7 @@ from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice -swift_optimization_args = { +swift_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': [], 'g': [], @@ -34,7 +34,7 @@ '2': ['-O'], '3': ['-O'], 's': ['-O'], -} # type: T.Dict[str, T.List[str]] +} class SwiftCompiler(Compiler): diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 72e9f44d99ac..fa94f870219c 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -566,7 +566,7 @@ def strip_system_includedirs(environment: 'Environment', for_machine: MachineCho return [i for i in include_args if i not in exclude] def process_method_kw(possible: T.Iterable[DependencyMethods], kwargs: T.Dict[str, T.Any]) -> T.List[DependencyMethods]: - method = kwargs.get('method', 'auto') # type: T.Union[DependencyMethods, str] + method: T.Union[DependencyMethods, str] = kwargs.get('method', 'auto') if isinstance(method, DependencyMethods): return [method] # TODO: try/except? diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 648c8d2e1a57..788ccbb198f5 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -248,7 +248,7 @@ def fix_python_name(self, tags: T.List[str]) -> T.List[str]: # Handle the boost_python naming madness. # See https://github.com/mesonbuild/meson/issues/4788 for some distro # specific naming variations. - other_tags = [] # type: T.List[str] + other_tags: T.List[str] = [] # Split the current modname into the base name and the version m_cur = BoostLibraryFile.reg_python_mod_split.match(self.mod_name) @@ -331,7 +331,7 @@ def vscrt_matches(self, vscrt: str) -> bool: return True def get_compiler_args(self) -> T.List[str]: - args = [] # type: T.List[str] + args: T.List[str] = [] if self.mod_name in boost_libraries: libdef = boost_libraries[self.mod_name] if self.static: @@ -355,19 +355,19 @@ def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None self.debug = buildtype.startswith('debug') self.multithreading = kwargs.get('threading', 'multi') == 'multi' - self.boost_root = None # type: T.Optional[Path] + self.boost_root: T.Optional[Path] = None self.explicit_static = 'static' in kwargs # Extract and validate modules - self.modules = mesonlib.extract_as_list(kwargs, 'modules') # type: T.List[str] + self.modules: T.List[str] = mesonlib.extract_as_list(kwargs, 'modules') for i in self.modules: if not isinstance(i, str): raise DependencyException('Boost module argument is not a string.') if i.startswith('boost_'): raise DependencyException('Boost modules must be passed without the boost_ prefix') - self.modules_found = [] # type: T.List[str] - self.modules_missing = [] # type: T.List[str] + self.modules_found: T.List[str] = [] + self.modules_missing: T.List[str] = [] # Do we need threads? if 'thread' in self.modules: @@ -450,7 +450,7 @@ def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) - mlog.debug(' - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs])) # 2. Find all boost libraries - libs = [] # type: T.List[BoostLibraryFile] + libs: T.List[BoostLibraryFile] = [] for i in lib_dirs: libs = self.detect_libraries(i) if libs: @@ -471,8 +471,8 @@ def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) - mlog.debug(f' - {j}') # 3. Select the libraries matching the requested modules - not_found = [] # type: T.List[str] - selected_modules = [] # type: T.List[BoostLibraryFile] + not_found: T.List[str] = [] + selected_modules: T.List[BoostLibraryFile] = [] for mod in modules: found = False for l in f_libs: @@ -485,8 +485,8 @@ def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) - # log the result mlog.debug(' - found:') - comp_args = [] # type: T.List[str] - link_args = [] # type: T.List[str] + comp_args: T.List[str] = [] + link_args: T.List[str] = [] for j in selected_modules: c_args = j.get_compiler_args() l_args = j.get_link_args() @@ -524,7 +524,7 @@ def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) - return False def detect_inc_dirs(self, root: Path) -> T.List[BoostIncludeDir]: - candidates = [] # type: T.List[Path] + candidates: T.List[Path] = [] inc_root = root / 'include' candidates += [root / 'boost'] @@ -555,8 +555,8 @@ def detect_lib_dirs(self, root: Path, use_system: bool) -> T.List[Path]: # No system include paths were found --> fall back to manually looking # for library dirs in root - dirs = [] # type: T.List[Path] - subdirs = [] # type: T.List[Path] + dirs: T.List[Path] = [] + subdirs: T.List[Path] = [] for i in root.iterdir(): if i.is_dir() and i.name.startswith('lib'): dirs += [i] @@ -578,7 +578,7 @@ def detect_lib_dirs(self, root: Path, use_system: bool) -> T.List[Path]: raw_list = dirs + subdirs no_arch = [x for x in raw_list if not any(y in x.name for y in arch_list_32 + arch_list_64)] - matching_arch = [] # type: T.List[Path] + matching_arch: T.List[Path] = [] if '32' in self.arch: matching_arch = [x for x in raw_list if any(y in x.name for y in arch_list_32)] elif '64' in self.arch: @@ -624,7 +624,7 @@ def filter_libraries(self, libs: T.List[BoostLibraryFile], lib_vers: str) -> T.L return libs def detect_libraries(self, libdir: Path) -> T.List[BoostLibraryFile]: - libs = set() # type: T.Set[BoostLibraryFile] + libs: T.Set[BoostLibraryFile] = set() for i in libdir.iterdir(): if not i.is_file(): continue @@ -655,7 +655,7 @@ def detect_split_root(self, inc_dir: Path, lib_dir: Path) -> None: self.is_found = self.run_check([boost_inc_dir], [lib_dir]) def detect_roots(self) -> None: - roots = [] # type: T.List[Path] + roots: T.List[Path] = [] # Try getting the BOOST_ROOT from a boost.pc if it exists. This primarily # allows BoostDependency to find boost from Conan. See #5438 @@ -686,7 +686,7 @@ def detect_roots(self) -> None: # Where boost prebuilt binaries are local_boost = Path('C:/local') - candidates = [] # type: T.List[Path] + candidates: T.List[Path] = [] if prog_files.is_dir(): candidates += [*prog_files.iterdir()] if local_boost.is_dir(): @@ -694,7 +694,7 @@ def detect_roots(self) -> None: roots += [x for x in candidates if x.name.lower().startswith('boost') and x.is_dir()] else: - tmp = [] # type: T.List[Path] + tmp: T.List[Path] = [] # Add some default system paths tmp += [Path('/opt/local')] diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 8827c9abdcd8..11d35646d430 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -80,7 +80,7 @@ def _original_module_name(self, module: str) -> str: def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> None: # Gather a list of all languages to support - self.language_list = [] # type: T.List[str] + self.language_list: T.List[str] = [] if language is None or force_use_global_compilers: compilers = None if kwargs.get('native', False): @@ -312,7 +312,7 @@ def search_lib_dirs(path: str) -> bool: return True # Check PATH - system_env = [] # type: T.List[str] + system_env: T.List[str] = [] for i in os.environ.get('PATH', '').split(os.pathsep): if i.endswith('/bin') or i.endswith('\\bin'): i = i[:-4] diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index 501e89d1b9ef..a437e847252d 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -48,7 +48,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. return # some broken pkgconfig don't actually list the full path to the needed includes - newinc = [] # type: T.List[str] + newinc: T.List[str] = [] for arg in self.compile_args: if arg.startswith('-I'): stem = 'static' if self.static else 'shared' @@ -56,7 +56,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. newinc.append('-I' + str(Path(arg[2:]) / stem)) self.compile_args += newinc - link_args = [] # type: T.List[str] + link_args: T.List[str] = [] for larg in self.get_link_args(): lpath = Path(larg) # some pkg-config hdf5.pc (e.g. Ubuntu) don't include the commonly-used HL HDF5 libraries, diff --git a/mesonbuild/dependencies/mpi.py b/mesonbuild/dependencies/mpi.py index 240e6fd95ce5..d9a1585e1e12 100644 --- a/mesonbuild/dependencies/mpi.py +++ b/mesonbuild/dependencies/mpi.py @@ -74,7 +74,7 @@ def mpi_factory(env: 'Environment', elif language == 'fortran': tool_names = [os.environ.get('I_MPI_F90'), 'mpiifort'] - cls = IntelMPIConfigToolDependency # type: T.Type[ConfigToolDependency] + cls: T.Type[ConfigToolDependency] = IntelMPIConfigToolDependency else: # OpenMPI, which doesn't work with intel # # We try the environment variables for the tools first, but then diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 56dee650d8c8..5340521c3a4e 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -460,7 +460,7 @@ def lookup_entry(self, name: str) -> T.Optional[T.List[str]]: class CMakeVariables: def __init__(self, variables: T.Optional[T.Dict[str, T.Any]] = None) -> None: variables = variables or {} - self.variables = {} # type: T.Dict[str, T.List[str]] + self.variables: T.Dict[str, T.List[str]] = {} for key, value in variables.items(): value = mesonlib.listify(value) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index e54f2a661d37..7bba4fa69a58 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -295,7 +295,7 @@ def __init__( self.sanity_check_ast() self.builtin.update({'meson': MesonMain(self.build, self)}) self.generators: T.List[build.Generator] = [] - self.processed_buildfiles = set() # type: T.Set[str] + self.processed_buildfiles: T.Set[str] = set() self.project_args_frozen = False self.global_args_frozen = False # implies self.project_args_frozen self.subprojects: T.Dict[str, SubprojectHolder] = {} diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index d23a23d1f483..902f84a45fd3 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -93,12 +93,12 @@ def __init__(self, source_root: str, subdir: str, subproject: 'SubProject'): self.current_lineno = -1 # Current node set during a function call. This can be used as location # when printing a warning message during a method call. - self.current_node = None # type: mparser.BaseNode + self.current_node: mparser.BaseNode = None # This is set to `version_string` when this statement is evaluated: # meson.version().compare_version(version_string) # If it was part of a if-clause, it is used to temporally override the # current meson version target within that if-block. - self.tmp_meson_version = None # type: T.Optional[str] + self.tmp_meson_version: T.Optional[str] = None def handle_meson_version_from_ast(self, strict: bool = True) -> None: # do nothing in an AST interpreter diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index e09a28ec234f..4261144d0594 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -61,7 +61,7 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty check_args += env.coredata.get_external_link_args(for_machine, comp_class.language) - override = [] # type: T.List[str] + override: T.List[str] = [] value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld') if value is not None: override = comp_class.use_linker_args(value[0], comp_version) @@ -138,7 +138,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty else: check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args - override = [] # type: T.List[str] + override: T.List[str] = [] value = env.lookup_binary_entry(for_machine, comp_class.language + '_ld') if value is not None: override = comp_class.use_linker_args(value[0], comp_version) diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 7ae7175e8b03..c36c65bdbb51 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -54,7 +54,7 @@ def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]: with path_to_intro.open(encoding='utf-8') as f: schema = json.load(f) - parsed_data = defaultdict(list) # type: T.Dict[str, T.List[dict]] + parsed_data: T.Dict[str, T.List[dict]] = defaultdict(list) for target in schema: parsed_data[target['name']] += [target] return parsed_data @@ -100,7 +100,7 @@ def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introsp raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found') intro_targets = introspect_data[target.name] - found_targets = [] # type: T.List[T.Dict[str, T.Any]] + found_targets: T.List[T.Dict[str, T.Any]] = [] resolved_bdir = builddir.resolve() @@ -337,8 +337,8 @@ def run(options: 'argparse.Namespace') -> int: if setup_vsenv(need_vsenv): mlog.log(mlog.green('INFO:'), 'automatically activated MSVC compiler environment') - cmd = [] # type: T.List[str] - env = None # type: T.Optional[T.Dict[str, str]] + cmd: T.List[str] = [] + env: T.Optional[T.Dict[str, str]] = None backend = cdata.get_option(mesonlib.OptionKey('backend')) assert isinstance(backend, str) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 14f8d86b6d21..ab31ec90b492 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -132,7 +132,7 @@ def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]: return res def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]: - plan = { + plan: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]] = { 'targets': { os.path.join(installdata.build_dir, target.fname): { 'destination': target.out_name, @@ -141,7 +141,7 @@ def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[s } for target in installdata.targets }, - } # type: T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]] + } for key, data_list in { 'data': installdata.data, 'man': installdata.man, @@ -178,13 +178,13 @@ def get_target_dir(coredata: cdata.CoreData, subdir: str) -> str: return subdir def list_targets_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]: - tlist = [] # type: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]] + tlist: T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]] = [] root_dir = Path(intr.source_root) def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: - res = [] # type: T.List[Path] + res: T.List[Path] = [] for n in node_list: - args = [] # type: T.List[BaseNode] + args: T.List[BaseNode] = [] if isinstance(n, FunctionNode): args = list(n.args.arguments) if n.func_name in BUILD_TARGET_FUNCTIONS: @@ -231,7 +231,7 @@ def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: return tlist def list_targets(builddata: build.Build, installdata: backends.InstallData, backend: backends.Backend) -> T.List[T.Any]: - tlist = [] # type: T.List[T.Any] + tlist: T.List[T.Any] = [] build_dir = builddata.environment.get_build_dir() src_dir = builddata.environment.get_source_dir() @@ -290,7 +290,7 @@ def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Di return list_buildoptions(intr.coredata, subprojects) def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]: - optlist = [] # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] + optlist: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = [] subprojects = subprojects or [] dir_option_names = set(cdata.BUILTIN_DIR_OPTIONS) @@ -379,7 +379,7 @@ def list_compilers(coredata: cdata.CoreData) -> T.Dict[str, T.Dict[str, T.Dict[s return compilers def list_deps_from_source(intr: IntrospectionInterpreter) -> T.List[T.Dict[str, T.Union[str, bool]]]: - result = [] # type: T.List[T.Dict[str, T.Union[str, bool]]] + result: T.List[T.Dict[str, T.Union[str, bool]]] = [] for i in intr.dependencies: keys = [ 'name', @@ -436,9 +436,9 @@ def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str return list(result.values()) def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]: - result = [] # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]] + result: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]] = [] for t in testdata: - to = {} # type: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]] + to: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]] = {} if isinstance(t.fname, str): fname = [t.fname] else: @@ -541,7 +541,7 @@ def run(options: argparse.Namespace) -> int: if options.builddir is not None: datadir = os.path.join(options.builddir, datadir) indent = 4 if options.indent else None - results = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] + results: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = [] sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] intro_types = get_meson_introspection_types(sourcedir=sourcedir) @@ -594,7 +594,7 @@ def run(options: argparse.Namespace) -> int: return print_results(options, results, indent) -updated_introspection_files = [] # type: T.List[str] +updated_introspection_files: T.List[str] = [] def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T.Any]]]], info_dir: str) -> None: for kind, data in intro_info: @@ -609,7 +609,7 @@ def write_intro_info(intro_info: T.Sequence[T.Tuple[str, T.Union[dict, T.List[T. def generate_introspection_file(builddata: build.Build, backend: backends.Backend) -> None: coredata = builddata.environment.get_coredata() intro_types = get_meson_introspection_types(coredata=coredata, builddata=builddata, backend=backend) - intro_info = [] # type: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] + intro_info: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = [] for key, val in intro_types.items(): if not val.func: diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index e51399b4f5c6..0e62a57d4752 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -60,7 +60,7 @@ def _windows_ansi() -> bool: return bool(kernel.SetConsoleMode(stdout, mode.value | 0x4) or os.environ.get('ANSICON')) def colorize_console() -> bool: - _colorize_console = getattr(sys.stdout, 'colorize_console', None) # type: bool + _colorize_console: bool = getattr(sys.stdout, 'colorize_console', None) if _colorize_console is not None: return _colorize_console @@ -201,7 +201,7 @@ def initialize(self, logdir: str, fatal_warnings: bool = False) -> None: self.log_fatal_warnings = fatal_warnings def process_markup(self, args: T.Sequence[TV_Loggable], keep: bool, display_timestamp: bool = True) -> T.List[str]: - arr = [] # type: T.List[str] + arr: T.List[str] = [] if self.log_timestamp_start is not None and display_timestamp: arr = ['[{:.3f}]'.format(time.monotonic() - self.log_timestamp_start)] for arg in args: @@ -312,7 +312,7 @@ def _log_error(self, severity: _Severity, *rargs: TV_Loggable, # The typing requirements here are non-obvious. Lists are invariant, # therefore T.List[A] and T.List[T.Union[A, B]] are not able to be joined if severity is _Severity.NOTICE: - label = [bold('NOTICE:')] # type: TV_LoggableList + label: TV_LoggableList = [bold('NOTICE:')] elif severity is _Severity.WARNING: label = [yellow('WARNING:')] elif severity is _Severity.ERROR: @@ -373,7 +373,7 @@ def exception(self, e: Exception, prefix: T.Optional[AnsiDecorator] = None) -> N if prefix is None: prefix = red('ERROR:') self.log() - args = [] # type: T.List[T.Union[AnsiDecorator, str]] + args: T.List[T.Union[AnsiDecorator, str]] = [] if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']): # Mypy doesn't follow hasattr, and it's pretty easy to visually inspect # that this is correct, so we'll just ignore it. diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index c6048f92502b..bec1b2a30a0b 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -188,7 +188,7 @@ def found_method(self, state: ModuleState, args: TYPE_var, kwargs: TYPE_kwargs) class CMakeSubprojectOptions(ModuleObject): def __init__(self) -> None: super().__init__() - self.cmake_options = [] # type: T.List[str] + self.cmake_options: T.List[str] = [] self.target_options = TargetOptions() self.methods.update( diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index d4ddff929cb5..fb4e4336795f 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -163,7 +163,7 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: col = 0 while loc < len(self.code): matched = False - value = None # type: T.Union[str, bool, int] + value: T.Union[str, bool, int] = None for (tid, reg) in self.token_specification: mo = reg.match(self.code, loc) if mo: @@ -610,7 +610,7 @@ class Parser: def __init__(self, code: str, filename: str): self.lexer = Lexer(code) self.stream = self.lexer.lex(filename) - self.current = Token('eof', '', 0, 0, 0, (0, 0), None) # type: Token + self.current: Token = Token('eof', '', 0, 0, 0, (0, 0), None) self.getsym() self.in_ternary = False diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 36afd6128b11..1ac27824ced7 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -521,9 +521,9 @@ class ConsoleLogger(TestLogger): RTRI = "\u25B6 " def __init__(self) -> None: - self.running_tests = OrderedSet() # type: OrderedSet['TestRun'] - self.progress_test = None # type: T.Optional['TestRun'] - self.progress_task = None # type: T.Optional[asyncio.Future] + self.running_tests: OrderedSet['TestRun'] = OrderedSet() + self.progress_test: T.Optional['TestRun'] = None + self.progress_task: T.Optional[asyncio.Future] = None self.max_left_width = 0 self.stop = False # TODO: before 3.10 this cannot be created immediately, because @@ -806,7 +806,7 @@ def __init__(self, filename: str) -> None: self.filename = filename self.root = et.Element( 'testsuites', tests='0', errors='0', failures='0') - self.suites = {} # type: T.Dict[str, et.Element] + self.suites: T.Dict[str, et.Element] = {} def log(self, harness: 'TestHarness', test: 'TestRun') -> None: """Log a single test case.""" @@ -924,24 +924,24 @@ def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str], name: str, timeout: T.Optional[int], is_parallel: bool, verbose: bool): self.res = TestResult.PENDING self.test = test - self._num = None # type: T.Optional[int] + self._num: T.Optional[int] = None self.name = name self.timeout = timeout - self.results = [] # type: T.List[TAPParser.Test] - self.returncode = None # type: T.Optional[int] - self.starttime = None # type: T.Optional[float] - self.duration = None # type: T.Optional[float] + self.results: T.List[TAPParser.Test] = [] + self.returncode: T.Optional[int] = None + self.starttime: T.Optional[float] = None + self.duration: T.Optional[float] = None self.stdo = '' self.stde = '' self.additional_error = '' - self.cmd = None # type: T.Optional[T.List[str]] + self.cmd: T.Optional[T.List[str]] = None self.env = test_env self.should_fail = test.should_fail self.project = test.project_name - self.junit = None # type: T.Optional[et.ElementTree] + self.junit: T.Optional[et.ElementTree] = None self.is_parallel = is_parallel self.verbose = verbose - self.warnings = [] # type: T.List[str] + self.warnings: T.List[str] = [] def start(self, cmd: T.List[str]) -> None: self.res = TestResult.RUNNING @@ -1088,7 +1088,7 @@ def complete(self) -> None: async def parse(self, harness: 'TestHarness', lines: T.AsyncIterator[str]) -> None: res = None - warnings = [] # type: T.List[TAPParser.UnknownLine] + warnings: T.List[TAPParser.UnknownLine] = [] version = 12 async for i in TAPParser().parse_async(lines): @@ -1288,8 +1288,8 @@ def __init__(self, p: asyncio.subprocess.Process, self.stdo_task: T.Optional[asyncio.Task[None]] = None self.stde_task: T.Optional[asyncio.Task[None]] = None self.postwait_fn = postwait_fn - self.all_futures = [] # type: T.List[asyncio.Future] - self.queue = None # type: T.Optional[asyncio.Queue[T.Optional[str]]] + self.all_futures: T.List[asyncio.Future] = [] + self.queue: T.Optional[asyncio.Queue[T.Optional[str]]] = None def stdout_lines(self) -> T.AsyncIterator[str]: self.queue = asyncio.Queue() @@ -1535,7 +1535,7 @@ async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: if not self.options.split and not self.runobj.needs_parsing \ else asyncio.subprocess.PIPE - extra_cmd = [] # type: T.List[str] + extra_cmd: T.List[str] = [] if self.test.protocol is TestProtocol.GTEST: gtestname = self.test.name if self.test.workdir: @@ -1570,7 +1570,7 @@ async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: class TestHarness: def __init__(self, options: argparse.Namespace): self.options = options - self.collected_failures = [] # type: T.List[TestRun] + self.collected_failures: T.List[TestRun] = [] self.fail_count = 0 self.expectedfail_count = 0 self.unexpectedpass_count = 0 @@ -1580,13 +1580,13 @@ def __init__(self, options: argparse.Namespace): self.test_count = 0 self.name_max_len = 0 self.is_run = False - self.loggers = [] # type: T.List[TestLogger] + self.loggers: T.List[TestLogger] = [] self.console_logger = ConsoleLogger() self.loggers.append(self.console_logger) self.need_console = False - self.ninja = None # type: T.List[str] + self.ninja: T.List[str] = None - self.logfile_base = None # type: T.Optional[str] + self.logfile_base: T.Optional[str] = None if self.options.logbase and not self.options.gdb: namebase = None self.logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase) @@ -1809,7 +1809,7 @@ def doit(self) -> int: startdir = os.getcwd() try: os.chdir(self.options.wd) - runners = [] # type: T.List[SingleTestRunner] + runners: T.List[SingleTestRunner] = [] for i in range(self.options.repeat): runners.extend(self.get_test_runner(test) for test in tests) if i == 0: @@ -1964,7 +1964,7 @@ def open_logfiles(self) -> None: @staticmethod def get_wrapper(options: argparse.Namespace) -> T.List[str]: - wrap = [] # type: T.List[str] + wrap: T.List[str] = [] if options.gdb: wrap = [options.gdb_path, '--quiet'] if options.repeat > 1: @@ -2007,10 +2007,10 @@ def log_start_test(self, test: TestRun) -> None: async def _run_tests(self, runners: T.List[SingleTestRunner]) -> None: semaphore = asyncio.Semaphore(self.options.num_processes) - futures = deque() # type: T.Deque[asyncio.Future] - running_tests = {} # type: T.Dict[asyncio.Future, str] + futures: T.Deque[asyncio.Future] = deque() + running_tests: T.Dict[asyncio.Future, str] = {} interrupted = False - ctrlc_times = deque(maxlen=MAX_CTRLC) # type: T.Deque[float] + ctrlc_times: T.Deque[float] = deque(maxlen=MAX_CTRLC) loop = asyncio.get_running_loop() async def run_test(test: SingleTestRunner) -> None: @@ -2117,9 +2117,9 @@ def convert_path_to_target(path: str) -> str: assert len(ninja) > 0 - depends = set() # type: T.Set[str] - targets = set() # type: T.Set[str] - intro_targets = {} # type: T.Dict[str, T.List[str]] + depends: T.Set[str] = set() + targets: T.Set[str] = set() + intro_targets: T.Dict[str, T.List[str]] = {} for target in load_info_file(get_infodir(wd), kind='targets'): intro_targets[target['id']] = [ convert_path_to_target(f) diff --git a/mesonbuild/scripts/cmake_run_ctgt.py b/mesonbuild/scripts/cmake_run_ctgt.py index 755530a6805b..df3f3618578d 100755 --- a/mesonbuild/scripts/cmake_run_ctgt.py +++ b/mesonbuild/scripts/cmake_run_ctgt.py @@ -9,7 +9,7 @@ import typing as T def run(argsv: T.List[str]) -> int: - commands = [[]] # type: T.List[T.List[str]] + commands: T.List[T.List[str]] = [[]] SEPARATOR = ';;;' # Generate CMD parameters diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index b9c58fee546c..593efd9f7677 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -123,8 +123,8 @@ class Elf(DataSizes): def __init__(self, bfile: str, verbose: bool = True) -> None: self.bfile = bfile self.verbose = verbose - self.sections = [] # type: T.List[SectionHeader] - self.dynamic = [] # type: T.List[DynamicEntry] + self.sections: T.List[SectionHeader] = [] + self.dynamic: T.List[DynamicEntry] = [] self.open_bf(bfile) try: (self.ptrsize, self.is_le) = self.detect_elf_type() @@ -329,7 +329,7 @@ def fix_rpathtype_entry(self, fname: str, rpath_dirs_to_remove: T.Set[bytes], ne old_rpath = self.read_str() # Some rpath entries may come from multiple sources. # Only add each one once. - new_rpaths = OrderedSet() # type: OrderedSet[bytes] + new_rpaths: OrderedSet[bytes] = OrderedSet() if new_rpath: new_rpaths.update(new_rpath.split(b':')) if old_rpath: diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index c1125fbe8b12..73d4523aef92 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1526,7 +1526,7 @@ def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None, **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: p = subprocess.Popen(args, universal_newlines=False, close_fds=False, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) - input_ = None # type: T.Optional[bytes] + input_: T.Optional[bytes] = None if write is not None: input_ = write.encode('utf-8') o, e = p.communicate(input_) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 2b0a0ba9eb84..c0dd01c27427 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -145,11 +145,11 @@ class PackageDefinition: def __init__(self, fname: str, subproject: str = ''): self.filename = fname self.subproject = SubProject(subproject) - self.type = None # type: T.Optional[str] - self.values = {} # type: T.Dict[str, str] - self.provided_deps = {} # type: T.Dict[str, T.Optional[str]] - self.provided_programs = [] # type: T.List[str] - self.diff_files = [] # type: T.List[Path] + self.type: T.Optional[str] = None + self.values: T.Dict[str, str] = {} + self.provided_deps: T.Dict[str, T.Optional[str]] = {} + self.provided_programs: T.List[str] = [] + self.diff_files: T.List[Path] = [] self.basename = os.path.basename(fname) self.has_wrap = self.basename.endswith('.wrap') self.name = self.basename[:-5] if self.has_wrap else self.basename @@ -290,10 +290,10 @@ class Resolver: def __post_init__(self) -> None: self.subdir_root = os.path.join(self.source_dir, self.subdir) self.cachedir = os.path.join(self.subdir_root, 'packagecache') - self.wraps = {} # type: T.Dict[str, PackageDefinition] + self.wraps: T.Dict[str, PackageDefinition] = {} self.netrc: T.Optional[netrc] = None - self.provided_deps = {} # type: T.Dict[str, PackageDefinition] - self.provided_programs = {} # type: T.Dict[str, PackageDefinition] + self.provided_deps: T.Dict[str, PackageDefinition] = {} + self.provided_programs: T.Dict[str, PackageDefinition] = {} self.wrapdb: T.Dict[str, T.Any] = {} self.wrapdb_provided_deps: T.Dict[str, str] = {} self.wrapdb_provided_programs: T.Dict[str, str] = {} @@ -555,7 +555,7 @@ def get_git(self) -> None: revno = self.wrap.get('revision') checkout_cmd = ['-c', 'advice.detachedHead=false', 'checkout', revno, '--'] is_shallow = False - depth_option = [] # type: T.List[str] + depth_option: T.List[str] = [] if self.wrap.values.get('depth', '') != '': is_shallow = True depth_option = ['--depth', self.wrap.values.get('depth')] From cd676e229b3b5d34550a9a39fa41c2d686c48596 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 11 Aug 2023 09:15:02 -0700 Subject: [PATCH 119/855] interpreter: use typed_kwargs for shared_library(version) --- mesonbuild/build.py | 9 ++------- mesonbuild/interpreter/kwargs.py | 9 +++++++-- mesonbuild/interpreter/type_checking.py | 11 ++++++++++- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index e5cdfea5ac48..979672aebb33 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2139,7 +2139,7 @@ def __init__( compilers: T.Dict[str, 'Compiler'], kwargs): self.soversion = None - self.ltversion = None + self.ltversion: T.Optional[str] = None # Max length 2, first element is compatibility_version, second is current_version self.darwin_versions = [] self.vs_module_defs = None @@ -2350,12 +2350,7 @@ def process_kwargs(self, kwargs): if not self.environment.machines[self.for_machine].is_android(): # Shared library version - if 'version' in kwargs: - self.ltversion = kwargs['version'] - if not isinstance(self.ltversion, str): - raise InvalidArguments('Shared library version needs to be a string, not ' + type(self.ltversion).__name__) - if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', self.ltversion): - raise InvalidArguments(f'Invalid Shared library version "{self.ltversion}". Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.') + self.ltversion = T.cast('T.Optional[str]', kwargs.get('version')) # Try to extract/deduce the soversion if 'soversion' in kwargs: self.soversion = kwargs['soversion'] diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 48e483efc7be..e92f700f99f9 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -338,7 +338,12 @@ class StaticLibrary(_BuildTarget): pass -class SharedLibrary(_BuildTarget): +class _SharedLibMixin(TypedDict): + + version: T.Optional[str] + + +class SharedLibrary(_BuildTarget, _SharedLibMixin): pass @@ -346,7 +351,7 @@ class SharedModule(_BuildTarget): pass -class Library(_BuildTarget): +class Library(_BuildTarget, _SharedLibMixin): """For library, both_library, and as a base for build_target""" diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index b919d6a54903..5ae189acd6d5 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -119,6 +119,13 @@ def _lower_strlist(input: T.List[str]) -> T.List[str]: return [i.lower() for i in input] +def _validate_shlib_version(val: T.Optional[str]) -> T.Optional[str]: + if val is not None and not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', val): + return (f'Invalid Shared library version "{val}". ' + 'Must be of the form X.Y.Z where all three are numbers. Y and Z are optional.') + return None + + def variables_validator(contents: T.Union[str, T.List[str], T.Dict[str, str]]) -> T.Optional[str]: if isinstance(contents, str): contents = [contents] @@ -527,7 +534,9 @@ def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: # Arguments exclusive to SharedLibrary. These are separated to make integrating # them into build_target easier -_EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [] +_EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [ + KwargInfo('version', (str, NoneType), validator=_validate_shlib_version) +] # The total list of arguments used by SharedLibrary SHARED_LIB_KWS = [ From 09bc028c7120b78e01a6be285f9961c58bff7462 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 11 Aug 2023 09:18:10 -0700 Subject: [PATCH 120/855] interpreter: use typed_kwargs for shared_library(soversion) --- mesonbuild/build.py | 12 +++--------- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 979672aebb33..c1427be2136c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2138,7 +2138,7 @@ def __init__( environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], kwargs): - self.soversion = None + self.soversion: T.Optional[str] = None self.ltversion: T.Optional[str] = None # Max length 2, first element is compatibility_version, second is current_version self.darwin_versions = [] @@ -2351,14 +2351,8 @@ def process_kwargs(self, kwargs): if not self.environment.machines[self.for_machine].is_android(): # Shared library version self.ltversion = T.cast('T.Optional[str]', kwargs.get('version')) - # Try to extract/deduce the soversion - if 'soversion' in kwargs: - self.soversion = kwargs['soversion'] - if isinstance(self.soversion, int): - self.soversion = str(self.soversion) - if not isinstance(self.soversion, str): - raise InvalidArguments('Shared library soversion is not a string or integer.') - elif self.ltversion: + self.soversion = T.cast('T.Optional[str]', kwargs.get('soversion')) + if self.soversion is None and self.ltversion is not None: # library version is defined, get the soversion from that # We replicate what Autotools does here and take the first # number of the version by default. diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index e92f700f99f9..c463288372f0 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -340,6 +340,7 @@ class StaticLibrary(_BuildTarget): class _SharedLibMixin(TypedDict): + soversion: T.Optional[str] version: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 5ae189acd6d5..87a4d439ed83 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -535,6 +535,7 @@ def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: # Arguments exclusive to SharedLibrary. These are separated to make integrating # them into build_target easier _EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [ + KwargInfo('soversion', (str, int, NoneType), convertor=lambda x: str(x) if x is not None else None), KwargInfo('version', (str, NoneType), validator=_validate_shlib_version) ] From 9d323020321893093492bc7d538c311c61398a1e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 6 Mar 2023 11:24:10 -0800 Subject: [PATCH 121/855] interpreter: use typed_kwargs for shared_library(darwin_versions) --- mesonbuild/build.py | 47 +++---------------------- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 44 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c1427be2136c..5b9d1525c983 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2141,7 +2141,7 @@ def __init__( self.soversion: T.Optional[str] = None self.ltversion: T.Optional[str] = None # Max length 2, first element is compatibility_version, second is current_version - self.darwin_versions = [] + self.darwin_versions: T.Optional[T.Tuple[str, str]] = None self.vs_module_defs = None # The import library this target will generate self.import_filename = None @@ -2307,44 +2307,6 @@ def determine_filenames(self): if create_debug_file: self.debug_filename = os.path.splitext(self.filename)[0] + '.pdb' - @staticmethod - def _validate_darwin_versions(darwin_versions): - try: - if isinstance(darwin_versions, int): - darwin_versions = str(darwin_versions) - if isinstance(darwin_versions, str): - darwin_versions = 2 * [darwin_versions] - if not isinstance(darwin_versions, list): - raise InvalidArguments('Shared library darwin_versions: must be a string, integer,' - f'or a list, not {darwin_versions!r}') - if len(darwin_versions) > 2: - raise InvalidArguments('Shared library darwin_versions: list must contain 2 or fewer elements') - if len(darwin_versions) == 1: - darwin_versions = 2 * darwin_versions - for i, v in enumerate(darwin_versions[:]): - if isinstance(v, int): - v = str(v) - if not isinstance(v, str): - raise InvalidArguments('Shared library darwin_versions: list elements ' - f'must be strings or integers, not {v!r}') - if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', v): - raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z where ' - 'X, Y, Z are numbers, and Y and Z are optional') - parts = v.split('.') - if len(parts) in {1, 2, 3} and int(parts[0]) > 65535: - raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' - 'where X is [0, 65535] and Y, Z are optional') - if len(parts) in {2, 3} and int(parts[1]) > 255: - raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' - 'where Y is [0, 255] and Y, Z are optional') - if len(parts) == 3 and int(parts[2]) > 255: - raise InvalidArguments('Shared library darwin_versions: must be X.Y.Z ' - 'where Z is [0, 255] and Y, Z are optional') - darwin_versions[i] = v - except ValueError: - raise InvalidArguments('Shared library darwin_versions: value is invalid') - return darwin_versions - def process_kwargs(self, kwargs): super().process_kwargs(kwargs) @@ -2358,11 +2320,10 @@ def process_kwargs(self, kwargs): # number of the version by default. self.soversion = self.ltversion.split('.')[0] # macOS, iOS and tvOS dylib compatibility_version and current_version - if 'darwin_versions' in kwargs: - self.darwin_versions = self._validate_darwin_versions(kwargs['darwin_versions']) - elif self.soversion: + self.darwin_versions = T.cast('T.Optional[T.Tuple[str, str]]', kwargs.get('darwin_versions')) + if self.darwin_versions is None and self.soversion is not None: # If unspecified, pick the soversion - self.darwin_versions = 2 * [self.soversion] + self.darwin_versions = (self.soversion, self.soversion) # Visual Studio module-definitions file if 'vs_module_defs' in kwargs: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index c463288372f0..af5733f4ed21 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -340,6 +340,7 @@ class StaticLibrary(_BuildTarget): class _SharedLibMixin(TypedDict): + darwin_versions: T.Optional[T.Tuple[str, str]] soversion: T.Optional[str] version: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 87a4d439ed83..28c9152955fa 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -504,6 +504,49 @@ def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: return f'Invalid value for win_subsystem: {value}.' return None + +def _validate_darwin_versions(darwin_versions: T.List[T.Union[str, int]]) -> T.Optional[str]: + if len(darwin_versions) > 2: + return f"Must contain between 0 and 2 elements, not {len(darwin_versions)}" + if len(darwin_versions) == 1: + darwin_versions = 2 * darwin_versions + for v in darwin_versions: + if isinstance(v, int): + v = str(v) + if not re.fullmatch(r'[0-9]+(\.[0-9]+){0,2}', v): + return 'must be X.Y.Z where X, Y, Z are numbers, and Y and Z are optional' + try: + parts = v.split('.') + except ValueError: + return f'badly formed value: "{v}, not in X.Y.Z form' + if len(parts) in {1, 2, 3} and int(parts[0]) > 65535: + return 'must be X.Y.Z where X is [0, 65535] and Y, Z are optional' + if len(parts) in {2, 3} and int(parts[1]) > 255: + return 'must be X.Y.Z where Y is [0, 255] and Y, Z are optional' + if len(parts) == 3 and int(parts[2]) > 255: + return 'must be X.Y.Z where Z is [0, 255] and Y, Z are optional' + return None + + +def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tuple[str, str]]: + if not val: + return None + elif len(val) == 1: + v = str(val[0]) + return (v, v) + return (str(val[0]), str(val[1])) + + +_DARWIN_VERSIONS_KW: KwargInfo[T.List[T.Union[str, int]]] = KwargInfo( + 'darwin_versions', + ContainerTypeInfo(list, (str, int)), + default=[], + listify=True, + validator=_validate_darwin_versions, + convertor=_convert_darwin_versions, + since='0.48.0', +) + # Arguments exclusive to Executable. These are separated to make integrating # them into build_target easier _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ @@ -535,6 +578,7 @@ def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: # Arguments exclusive to SharedLibrary. These are separated to make integrating # them into build_target easier _EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [ + _DARWIN_VERSIONS_KW, KwargInfo('soversion', (str, int, NoneType), convertor=lambda x: str(x) if x is not None else None), KwargInfo('version', (str, NoneType), validator=_validate_shlib_version) ] From c7308076966c1c55bc117ce9f7a7f49ac96acfa6 Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Mon, 24 Apr 2023 09:52:28 +0200 Subject: [PATCH 122/855] Python: Add 'limited_api' kwarg to extension_module This commit adds a new keyword arg to extension_module() that enables a user to target the Python Limited API, declaring the version of the limited API that they wish to target. Two new unittests have been added to test this functionality. --- data/test.schema.json | 2 + docs/markdown/Builtin-options.md | 17 ++-- docs/markdown/Python-module.md | 5 ++ .../python_extension_module_limited_api.md | 5 ++ mesonbuild/coredata.py | 2 + mesonbuild/dependencies/python.py | 12 ++- mesonbuild/modules/python.py | 83 +++++++++++++++++-- mesonbuild/scripts/python_info.py | 15 ++++ run_project_tests.py | 14 +++- .../meson.build | 10 +++ .../module.c | 17 ++++ .../python/9 extmodule limited api/limited.c | 19 +++++ .../9 extmodule limited api/meson.build | 16 ++++ .../9 extmodule limited api/not_limited.c | 59 +++++++++++++ .../python/9 extmodule limited api/test.json | 8 ++ 15 files changed, 264 insertions(+), 20 deletions(-) create mode 100644 docs/markdown/snippets/python_extension_module_limited_api.md create mode 100644 test cases/python/10 extmodule limited api disabled/meson.build create mode 100644 test cases/python/10 extmodule limited api disabled/module.c create mode 100644 test cases/python/9 extmodule limited api/limited.c create mode 100644 test cases/python/9 extmodule limited api/meson.build create mode 100644 test cases/python/9 extmodule limited api/not_limited.c create mode 100644 test cases/python/9 extmodule limited api/test.json diff --git a/data/test.schema.json b/data/test.schema.json index a809388b4798..98ae44eeb983 100644 --- a/data/test.schema.json +++ b/data/test.schema.json @@ -26,9 +26,11 @@ "exe", "shared_lib", "python_lib", + "python_limited_lib", "pdb", "implib", "py_implib", + "py_limited_implib", "implibempty", "expr" ] diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index fed893e104c7..ca4fd14c0cdb 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -370,12 +370,13 @@ install prefix. For example: if the install prefix is `/usr` and the ### Python module -| Option | Default value | Possible values | Description | -| ------ | ------------- | ----------------- | ----------- | -| bytecompile | 0 | integer from -1 to 2 | What bytecode optimization level to use (Since 1.2.0) | -| install_env | prefix | {auto,prefix,system,venv} | Which python environment to install to (Since 0.62.0) | -| platlibdir | | Directory path | Directory for site-specific, platform-specific files (Since 0.60.0) | -| purelibdir | | Directory path | Directory for site-specific, non-platform-specific files (Since 0.60.0) | +| Option | Default value | Possible values | Description | +| ------ | ------------- | ----------------- | ----------- | +| bytecompile | 0 | integer from -1 to 2 | What bytecode optimization level to use (Since 1.2.0) | +| install_env | prefix | {auto,prefix,system,venv} | Which python environment to install to (Since 0.62.0) | +| platlibdir | | Directory path | Directory for site-specific, platform-specific files (Since 0.60.0) | +| purelibdir | | Directory path | Directory for site-specific, non-platform-specific files (Since 0.60.0) | +| allow_limited_api | true | true, false | Disables project-wide use of the Python Limited API (Since 1.3.0) | *Since 0.60.0* The `python.platlibdir` and `python.purelibdir` options are used by the python module methods `python.install_sources()` and @@ -405,3 +406,7 @@ python bytecode. Bytecode has 3 optimization levels: To this, Meson adds level `-1`, which is to not attempt to compile bytecode at all. + +*Since 1.3.0* The `python.allow_limited_api` option affects whether the +`limited_api` keyword argument of the `extension_module` method is respected. +If set to `false`, the effect of the `limited_api` argument is disabled. diff --git a/docs/markdown/Python-module.md b/docs/markdown/Python-module.md index f67262abfd4e..05ae57de233a 100644 --- a/docs/markdown/Python-module.md +++ b/docs/markdown/Python-module.md @@ -101,6 +101,11 @@ the addition of the following: `/usr/lib/site-packages`. When subdir is passed to this method, it will be appended to that location. This keyword argument is mutually exclusive with `install_dir` +- `limited_api`: *since 1.3.0* A string containing the Python version + of the [Py_LIMITED_API](https://docs.python.org/3/c-api/stable.html) that + the extension targets. For example, '3.7' to target Python 3.7's version of + the limited API. This behavior can be disabled by setting the value of + `python.allow_limited_api`. See [Python module options](Builtin-options.md#python-module). Additionally, the following diverge from [[shared_module]]'s default behavior: diff --git a/docs/markdown/snippets/python_extension_module_limited_api.md b/docs/markdown/snippets/python_extension_module_limited_api.md new file mode 100644 index 000000000000..f5da9699d9ce --- /dev/null +++ b/docs/markdown/snippets/python_extension_module_limited_api.md @@ -0,0 +1,5 @@ +## Support targeting Python's limited C API + +The Python module's `extension_module` function has gained the ability +to build extensions which target Python's limited C API via a new keyword +argument: `limited_api`. diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e930dfff5586..7bbc09eb1701 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1300,6 +1300,8 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')), (OptionKey('purelibdir', module='python'), BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')), + (OptionKey('allow_limited_api', module='python'), + BuiltinOption(UserBooleanOption, 'Whether to allow use of the Python Limited API', True)), ]) BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 1607728883df..efb904eca471 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -44,6 +44,7 @@ class PythonIntrospectionDict(TypedDict): paths: T.Dict[str, str] platform: str suffix: str + limited_api_suffix: str variables: T.Dict[str, str] version: str @@ -94,6 +95,7 @@ def __init__(self, name: str, command: T.Optional[T.List[str]] = None, 'paths': {}, 'platform': 'sentinel', 'suffix': 'sentinel', + 'limited_api_suffix': 'sentinel', 'variables': {}, 'version': '0.0', } @@ -197,7 +199,7 @@ def __init__(self, name: str, environment: 'Environment', if self.link_libpython: # link args if mesonlib.is_windows(): - self.find_libpy_windows(environment) + self.find_libpy_windows(environment, limited_api=False) else: self.find_libpy(environment) else: @@ -259,7 +261,7 @@ def get_windows_python_arch(self) -> T.Optional[str]: mlog.log(f'Unknown Windows Python platform {self.platform!r}') return None - def get_windows_link_args(self) -> T.Optional[T.List[str]]: + def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: if self.platform.startswith('win'): vernum = self.variables.get('py_version_nodot') verdot = self.variables.get('py_version_short') @@ -277,6 +279,8 @@ def get_windows_link_args(self) -> T.Optional[T.List[str]]: else: libpath = Path(f'python{vernum}.dll') else: + if limited_api: + vernum = vernum[0] libpath = Path('libs') / f'python{vernum}.lib' # For a debug build, pyconfig.h may force linking with # pythonX_d.lib (see meson#10776). This cannot be avoided @@ -317,7 +321,7 @@ def get_windows_link_args(self) -> T.Optional[T.List[str]]: return None return [str(lib)] - def find_libpy_windows(self, env: 'Environment') -> None: + def find_libpy_windows(self, env: 'Environment', limited_api: bool = False) -> None: ''' Find python3 libraries on Windows and also verify that the arch matches what we are building for. @@ -332,7 +336,7 @@ def find_libpy_windows(self, env: 'Environment') -> None: self.is_found = False return # This can fail if the library is not found - largs = self.get_windows_link_args() + largs = self.get_windows_link_args(limited_api) if largs is None: self.is_found = False return diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index d0067db5ae42..c8af224f8976 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import annotations -import copy, json, os, shutil +import copy, json, os, shutil, re import typing as T from . import ExtensionModule, ModuleInfo @@ -32,7 +32,7 @@ InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo, FeatureNew, FeatureNewKwargs, disablerIfNotFound ) -from ..mesonlib import MachineChoice +from ..mesonlib import MachineChoice, OptionKey from ..programs import ExternalProgram, NonExistingExternalProgram if T.TYPE_CHECKING: @@ -65,7 +65,7 @@ class ExtensionModuleKw(SharedModuleKw): MaybePythonProg = T.Union[NonExistingExternalProgram, 'PythonExternalProgram'] -mod_kwargs = {'subdir'} +mod_kwargs = {'subdir', 'limited_api'} mod_kwargs.update(known_shmod_kwargs) mod_kwargs -= {'name_prefix', 'name_suffix'} @@ -114,6 +114,7 @@ def _get_path(self, state: T.Optional['ModuleState'], key: str) -> str: _PURE_KW = KwargInfo('pure', (bool, NoneType)) _SUBDIR_KW = KwargInfo('subdir', str, default='') +_LIMITED_API_KW = KwargInfo('limited_api', str, default='', since='1.3.0') _DEFAULTABLE_SUBDIR_KW = KwargInfo('subdir', (str, NoneType)) class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']): @@ -124,6 +125,7 @@ def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): assert isinstance(prefix, str), 'for mypy' self.variables = info['variables'] self.suffix = info['suffix'] + self.limited_api_suffix = info['limited_api_suffix'] self.paths = info['paths'] self.pure = python.pure self.platlib_install_path = os.path.join(prefix, python.platlib) @@ -148,7 +150,7 @@ def __init__(self, python: 'PythonExternalProgram', interpreter: 'Interpreter'): @permittedKwargs(mod_kwargs) @typed_pos_args('python.extension_module', str, varargs=(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget)) - @typed_kwargs('python.extension_module', *_MOD_KWARGS, _DEFAULTABLE_SUBDIR_KW, allow_unknown=True) + @typed_kwargs('python.extension_module', *_MOD_KWARGS, _DEFAULTABLE_SUBDIR_KW, _LIMITED_API_KW, allow_unknown=True) def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: ExtensionModuleKw) -> 'SharedModule': if 'install_dir' in kwargs: if kwargs['subdir'] is not None: @@ -161,9 +163,11 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs['install_dir'] = self._get_install_dir_impl(False, subdir) + target_suffix = self.suffix + new_deps = mesonlib.extract_as_list(kwargs, 'dependencies') - has_pydep = any(isinstance(dep, _PythonDependencyBase) for dep in new_deps) - if not has_pydep: + pydep = next((dep for dep in new_deps if isinstance(dep, _PythonDependencyBase)), None) + if pydep is None: pydep = self._dependency_method_impl({}) if not pydep.found(): raise mesonlib.MesonException('Python dependency not found') @@ -171,15 +175,62 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], FeatureNew.single_use('python_installation.extension_module with implicit dependency on python', '0.63.0', self.subproject, 'use python_installation.dependency()', self.current_node) + + limited_api_version = kwargs.pop('limited_api') + allow_limited_api = self.interpreter.environment.coredata.get_option(OptionKey('allow_limited_api', module='python')) + if limited_api_version != '' and allow_limited_api: + + target_suffix = self.limited_api_suffix + + limited_api_version_hex = self._convert_api_version_to_py_version_hex(limited_api_version, pydep.version) + limited_api_definition = f'-DPy_LIMITED_API={limited_api_version_hex}' + + new_c_args = mesonlib.extract_as_list(kwargs, 'c_args') + new_c_args.append(limited_api_definition) + kwargs['c_args'] = new_c_args + + new_cpp_args = mesonlib.extract_as_list(kwargs, 'cpp_args') + new_cpp_args.append(limited_api_definition) + kwargs['cpp_args'] = new_cpp_args + + # When compiled under MSVC, Python's PC/pyconfig.h forcibly inserts pythonMAJOR.MINOR.lib + # into the linker path when not running in debug mode via a series #pragma comment(lib, "") + # directives. We manually override these here as this interferes with the intended + # use of the 'limited_api' kwarg + for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + compilers = self.interpreter.environment.coredata.compilers[for_machine] + if any(compiler.get_id() == 'msvc' for compiler in compilers.values()): + pydep_copy = copy.copy(pydep) + pydep_copy.find_libpy_windows(self.env, limited_api=True) + if not pydep_copy.found(): + raise mesonlib.MesonException('Python dependency supporting limited API not found') + + new_deps.remove(pydep) + new_deps.append(pydep_copy) + + pyver = pydep.version.replace('.', '') + python_windows_debug_link_exception = f'/NODEFAULTLIB:python{pyver}_d.lib' + python_windows_release_link_exception = f'/NODEFAULTLIB:python{pyver}.lib' + + new_link_args = mesonlib.extract_as_list(kwargs, 'link_args') + + is_debug = self.interpreter.environment.coredata.options[OptionKey('debug')].value + if is_debug: + new_link_args.append(python_windows_debug_link_exception) + else: + new_link_args.append(python_windows_release_link_exception) + + kwargs['link_args'] = new_link_args + kwargs['dependencies'] = new_deps # msys2's python3 has "-cpython-36m.dll", we have to be clever # FIXME: explain what the specific cleverness is here - split, suffix = self.suffix.rsplit('.', 1) + split, target_suffix = target_suffix.rsplit('.', 1) args = (args[0] + split, args[1]) kwargs['name_prefix'] = '' - kwargs['name_suffix'] = suffix + kwargs['name_suffix'] = target_suffix if 'gnu_symbol_visibility' not in kwargs and \ (self.is_pypy or mesonlib.version_compare(self.version, '>=3.9')): @@ -187,6 +238,22 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], return self.interpreter.build_target(self.current_node, args, kwargs, SharedModule) + def _convert_api_version_to_py_version_hex(self, api_version: str, detected_version: str) -> str: + python_api_version_format = re.compile(r'[0-9]\.[0-9]{1,2}') + decimal_match = python_api_version_format.fullmatch(api_version) + if not decimal_match: + raise InvalidArguments(f'Python API version invalid: "{api_version}".') + if mesonlib.version_compare(api_version, '<3.2'): + raise InvalidArguments(f'Python Limited API version invalid: {api_version} (must be greater than 3.2)') + if mesonlib.version_compare(api_version, '>' + detected_version): + raise InvalidArguments(f'Python Limited API version too high: {api_version} (detected {detected_version})') + + version_components = api_version.split('.') + major = int(version_components[0]) + minor = int(version_components[1]) + + return '0x{:02x}{:02x}0000'.format(major, minor) + def _dependency_method_impl(self, kwargs: TYPE_kwargs) -> Dependency: for_machine = self.interpreter.machine_from_native_kwarg(kwargs) identifier = get_dep_identifier(self._full_path(), kwargs) diff --git a/mesonbuild/scripts/python_info.py b/mesonbuild/scripts/python_info.py index 9c3a0791ac90..0f7787c3ff21 100755 --- a/mesonbuild/scripts/python_info.py +++ b/mesonbuild/scripts/python_info.py @@ -65,6 +65,20 @@ def links_against_libpython(): else: suffix = variables.get('EXT_SUFFIX') +limited_api_suffix = None +if sys.version_info >= (3, 2): + try: + from importlib.machinery import EXTENSION_SUFFIXES + limited_api_suffix = EXTENSION_SUFFIXES[1] + except Exception: + pass + +# pypy supports modules targetting the limited api but +# does not use a special suffix to distinguish them: +# https://doc.pypy.org/en/latest/cpython_differences.html#permitted-abi-tags-in-extensions +if '__pypy__' in sys.builtin_module_names: + limited_api_suffix = suffix + print(json.dumps({ 'variables': variables, 'paths': paths, @@ -76,4 +90,5 @@ def links_against_libpython(): 'is_venv': sys.prefix != variables['base_prefix'], 'link_libpython': links_against_libpython(), 'suffix': suffix, + 'limited_api_suffix': limited_api_suffix, })) diff --git a/run_project_tests.py b/run_project_tests.py index facf1e98f6af..27020caef9fe 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -148,7 +148,7 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa canonical_compiler = 'msvc' python_suffix = python.info['suffix'] - + python_limited_suffix = python.info['limited_api_suffix'] has_pdb = False if self.language in {'c', 'cpp'}: has_pdb = canonical_compiler == 'msvc' @@ -167,7 +167,7 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return None # Handle the different types - if self.typ in {'py_implib', 'python_lib', 'python_file'}: + if self.typ in {'py_implib', 'py_limited_implib', 'python_lib', 'python_limited_lib', 'python_file'}: val = p.as_posix() val = val.replace('@PYTHON_PLATLIB@', python.platlib) val = val.replace('@PYTHON_PURELIB@', python.purelib) @@ -176,6 +176,8 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return p if self.typ == 'python_lib': return p.with_suffix(python_suffix) + if self.typ == 'python_limited_lib': + return p.with_suffix(python_limited_suffix) if self.typ == 'py_implib': p = p.with_suffix(python_suffix) if env.machines.host.is_windows() and canonical_compiler == 'msvc': @@ -184,6 +186,14 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return p.with_suffix('.dll.a') else: return None + if self.typ == 'py_limited_implib': + p = p.with_suffix(python_limited_suffix) + if env.machines.host.is_windows() and canonical_compiler == 'msvc': + return p.with_suffix('.lib') + elif env.machines.host.is_windows() or env.machines.host.is_cygwin(): + return p.with_suffix('.dll.a') + else: + return None elif self.typ in {'file', 'dir'}: return p elif self.typ == 'shared_lib': diff --git a/test cases/python/10 extmodule limited api disabled/meson.build b/test cases/python/10 extmodule limited api disabled/meson.build new file mode 100644 index 000000000000..42cd6186c4ea --- /dev/null +++ b/test cases/python/10 extmodule limited api disabled/meson.build @@ -0,0 +1,10 @@ +project('Python limited api disabled', 'c', + default_options : ['buildtype=release', 'werror=true', 'python.allow_limited_api=false']) + +py_mod = import('python') +py = py_mod.find_installation() + +module = py.extension_module('my_module', + 'module.c', + limited_api: '3.7', +) diff --git a/test cases/python/10 extmodule limited api disabled/module.c b/test cases/python/10 extmodule limited api disabled/module.c new file mode 100644 index 000000000000..a5d3a87ab4c2 --- /dev/null +++ b/test cases/python/10 extmodule limited api disabled/module.c @@ -0,0 +1,17 @@ +#include + +#if defined(Py_LIMITED_API) +#error "Py_LIMITED_API's definition by Meson should have been disabled." +#endif + +static struct PyModuleDef my_module = { + PyModuleDef_HEAD_INIT, + "my_module", + NULL, + -1, + NULL +}; + +PyMODINIT_FUNC PyInit_my_module(void) { + return PyModule_Create(&my_module); +} diff --git a/test cases/python/9 extmodule limited api/limited.c b/test cases/python/9 extmodule limited api/limited.c new file mode 100644 index 000000000000..0d1c718200ba --- /dev/null +++ b/test cases/python/9 extmodule limited api/limited.c @@ -0,0 +1,19 @@ +#include + +#ifndef Py_LIMITED_API +#error Py_LIMITED_API must be defined. +#elif Py_LIMITED_API != 0x03070000 +#error Wrong value for Py_LIMITED_API +#endif + +static struct PyModuleDef limited_module = { + PyModuleDef_HEAD_INIT, + "limited_api_test", + NULL, + -1, + NULL +}; + +PyMODINIT_FUNC PyInit_limited(void) { + return PyModule_Create(&limited_module); +} diff --git a/test cases/python/9 extmodule limited api/meson.build b/test cases/python/9 extmodule limited api/meson.build new file mode 100644 index 000000000000..68afc96996cb --- /dev/null +++ b/test cases/python/9 extmodule limited api/meson.build @@ -0,0 +1,16 @@ +project('Python limited api', 'c', + default_options : ['buildtype=release', 'werror=true']) + +py_mod = import('python') +py = py_mod.find_installation() + +ext_mod_limited = py.extension_module('limited', + 'limited.c', + limited_api: '3.7', + install: true, +) + +ext_mod = py.extension_module('not_limited', + 'not_limited.c', + install: true, +) diff --git a/test cases/python/9 extmodule limited api/not_limited.c b/test cases/python/9 extmodule limited api/not_limited.c new file mode 100644 index 000000000000..105dbb80b374 --- /dev/null +++ b/test cases/python/9 extmodule limited api/not_limited.c @@ -0,0 +1,59 @@ +#include +#include + +#ifdef Py_LIMITED_API +#error Py_LIMITED_API must not be defined. +#endif + +/* This function explicitly calls functions whose declaration is elided when + * Py_LIMITED_API is defined. This is to test that the linker is actually + * linking to the right version of the library on Windows. */ +static PyObject *meth_not_limited(PyObject *self, PyObject *args) +{ + PyObject *list; + Py_ssize_t size; + + if (!PyArg_ParseTuple(args, "o", & list)) + return NULL; + + if (!PyList_Check(list)) { + PyErr_Format(PyExc_TypeError, "expected 'list'"); + return NULL; + } + + /* PyList_GET_SIZE and PyList_GET_ITEM are only available if Py_LIMITED_API + * is not defined. It seems likely that they will remain excluded from the + * limited API as their checked counterparts (PyList_GetSize and + * PyList_GetItem) are made available in that mode instead. */ + size = PyList_GET_SIZE(list); + for(Py_ssize_t i = 0; i < size; ++i) { + PyObject *element = PyList_GET_ITEM(list, i); + if (element == NULL) { + return NULL; + } + + if(PyObject_Print(element, stdout, Py_PRINT_RAW) == -1) { + return NULL; + } + } + + Py_RETURN_NONE; +} + +static struct PyMethodDef not_limited_methods[] = { + { "not_limited", meth_not_limited, METH_VARARGS, + "Calls functions whose declaration is elided by Py_LIMITED_API" }, + { NULL, NULL, 0, NULL } +}; + +static struct PyModuleDef not_limited_module = { + PyModuleDef_HEAD_INIT, + "not_limited_api_test", + NULL, + -1, + not_limited_methods +}; + +PyMODINIT_FUNC PyInit_not_limited(void) { + return PyModule_Create(¬_limited_module); +} diff --git a/test cases/python/9 extmodule limited api/test.json b/test cases/python/9 extmodule limited api/test.json new file mode 100644 index 000000000000..06a170623858 --- /dev/null +++ b/test cases/python/9 extmodule limited api/test.json @@ -0,0 +1,8 @@ +{ + "installed": [ + {"type": "python_limited_lib", "file": "usr/@PYTHON_PLATLIB@/limited"}, + {"type": "py_limited_implib", "file": "usr/@PYTHON_PLATLIB@/limited"}, + {"type": "python_lib", "file": "usr/@PYTHON_PLATLIB@/not_limited"}, + {"type": "py_implib", "file": "usr/@PYTHON_PLATLIB@/not_limited"} + ] +} From 8a7fdd91599823e2d7e693ce8525ed833c6a8126 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 16 Aug 2023 11:29:07 -0400 Subject: [PATCH 123/855] wasm: make generic cross file --- cross/wasm.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cross/wasm.txt b/cross/wasm.txt index 269c77ab4bb4..2a64319789a5 100644 --- a/cross/wasm.txt +++ b/cross/wasm.txt @@ -1,7 +1,7 @@ [binaries] -c = '/home/jpakkane/src/emsdk/upstream/emscripten/emcc' -cpp = '/home/jpakkane/src/emsdk/upstream/emscripten/em++' -ar = '/home/jpakkane/src/emsdk/upstream/emscripten/emar' +c = 'emcc' +cpp = 'em++' +ar = 'emar' [built-in options] c_args = [] From f88a9cd6b374676e8f47da7137c8cd77c5bc2ccf Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 16 Aug 2023 10:18:25 -0400 Subject: [PATCH 124/855] fs.read(): Catch FileNotFoundError --- mesonbuild/modules/fs.py | 4 +++- test cases/common/220 fs module/meson.build | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 7d969958838d..53174d2316aa 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -261,8 +261,10 @@ def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'Rea try: with open(path, encoding=encoding) as f: data = f.read() + except FileNotFoundError: + raise MesonException(f'File {args[0]} does not exist.') except UnicodeDecodeError: - raise MesonException(f'decoding failed for {path}') + raise MesonException(f'decoding failed for {args[0]}') # Reconfigure when this file changes as it can contain data used by any # part of the build configuration (e.g. `project(..., version: # fs.read_file('VERSION')` or `configure_file(...)` diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index a1e9c44fc468..b860fc8a32c8 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -142,3 +142,7 @@ assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compo subdir('subdir') subproject('subbie') + +testcase expect_error('File notfound does not exist.') + fs.read('notfound') +endtestcase From 14892eb8490615ef4123659b1d127226ccb9e3bd Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 7 Aug 2023 11:38:55 -0500 Subject: [PATCH 125/855] Fix some random capitalization in feature.yaml --- docs/yaml/objects/feature.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yaml/objects/feature.yaml b/docs/yaml/objects/feature.yaml index 26b677f7ac80..a5ae7a6910a0 100644 --- a/docs/yaml/objects/feature.yaml +++ b/docs/yaml/objects/feature.yaml @@ -90,7 +90,7 @@ methods: error_message: type: str default: "''" - description: The error Message to print if the check fails + description: The error message to print if the check fails - name: enable_if returns: feature @@ -124,7 +124,7 @@ methods: error_message: type: str default: "''" - description: The error Message to print if the check fails + description: The error message to print if the check fails - name: disable_if returns: feature @@ -162,4 +162,4 @@ methods: error_message: type: str default: "''" - description: The error Message to print if the check fails + description: The error message to print if the check fails From 229757fe912777825f83cf84a12dd75c50831f61 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 17 Aug 2023 11:14:05 -0400 Subject: [PATCH 126/855] README: Document python requirement history This documents useful to target Meson versions for projects that want to support older Python versions. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 868728d4181e..f3a2657b7d05 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@ build system. - [Python](https://python.org) (version 3.7 or newer) - [Ninja](https://ninja-build.org) (version 1.8.2 or newer) +Latest Meson version supporting previous Python versions: +- Python 3.6: **0.61.5** +- Python 3.5: **0.56.2** +- Python 3.4: **0.45.1** + #### Installing from source Meson is available on [PyPi](https://pypi.python.org/pypi/meson), so From cbf8e67f19e384e5f8eb7f65d3020551769de545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charlie=20Ringstr=C3=B6m?= Date: Thu, 17 Aug 2023 20:47:15 +0200 Subject: [PATCH 127/855] Replace deprecated GTK flag --- docs/markdown/Tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Tutorial.md b/docs/markdown/Tutorial.md index f43cc3603847..34e65fc1c05a 100644 --- a/docs/markdown/Tutorial.md +++ b/docs/markdown/Tutorial.md @@ -141,7 +141,7 @@ int main(int argc, char **argv) GtkApplication *app; int status; - app = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE); + app = gtk_application_new(NULL, G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); From f52bcaa27fc125ab9ae583af466ba99c164169f3 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 7 Aug 2023 12:30:15 -0500 Subject: [PATCH 128/855] Add fs.relative_to() Returns a relative path from arg 2 to arg 1 similar to os.path.relpath(). --- docs/markdown/Fs-module.md | 14 ++++++ docs/markdown/snippets/fs_relative_to.md | 17 +++++++ mesonbuild/modules/fs.py | 23 ++++++++- test cases/common/220 fs module/meson.build | 25 +++++++++- test cases/common/220 fs module/subdir/btgt.c | 5 ++ .../common/220 fs module/subdir/meson.build | 50 +++++++++++++++++++ 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/fs_relative_to.md create mode 100644 test cases/common/220 fs module/subdir/btgt.c diff --git a/docs/markdown/Fs-module.md b/docs/markdown/Fs-module.md index cc67355b5df4..bf9ddba9d212 100644 --- a/docs/markdown/Fs-module.md +++ b/docs/markdown/Fs-module.md @@ -224,6 +224,20 @@ fs.stem('foo/bar/baz.dll.a') # baz.dll project. If the file specified by `path` is a `files()` object it cannot refer to a built file. +### relative_to + +*Since 1.3.0* + +Return a relative filepath. In event a relative path could not be found, the +absolute path of `to` is returned. Relative path arguments will be assumed to be +relative to `meson.current_source_dir()`. + +Has the following positional arguments: + - to `str | file | custom_tgt | custom_idx | tgt`: end path + - from `str | file | custom_tgt | custom_idx | tgt`: start path + +returns: + - a string ### copyfile diff --git a/docs/markdown/snippets/fs_relative_to.md b/docs/markdown/snippets/fs_relative_to.md new file mode 100644 index 000000000000..82e6a4268bb8 --- /dev/null +++ b/docs/markdown/snippets/fs_relative_to.md @@ -0,0 +1,17 @@ +## `fs.relative_to()` + +The `fs` module now has a `relative_to` method. The method will return the +relative path from argument one to argument two, if one exists. Otherwise, the +absolute path to argument one is returned. + +```meson +assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') +assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') +assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') + +assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') +assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') +``` + +In addition to strings, it can handle files, custom targets, custom target +indices, and build targets. diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 53174d2316aa..a2dbdf2ebe63 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -20,18 +20,21 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import CustomTarget, InvalidArguments +from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs +from ..interpreterbase.baseobjects import TYPE_kwargs from ..mesonlib import ( File, MesonException, has_path_sep, path_is_in_root, ) +from ..utils.universal import relpath if T.TYPE_CHECKING: from . import ModuleState + from ..build import BuildTargetTypes from ..interpreter import Interpreter from ..mesonlib import FileOrString, FileMode @@ -75,6 +78,7 @@ def __init__(self, interpreter: 'Interpreter') -> None: 'stem': self.stem, 'read': self.read, 'copyfile': self.copyfile, + 'relative_to': self.relative_to, }) def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: @@ -312,6 +316,23 @@ def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[st return ModuleReturnValue(ct, [ct]) + @FeatureNew('fs.relative_to', '1.3.0') + @typed_pos_args('fs.relative_to', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) + @noKwargs + def relative_to(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], T.Union[FileOrString, BuildTargetTypes]], kwargs: TYPE_kwargs) -> str: + def to_path(arg: T.Union[FileOrString, CustomTarget, CustomTargetIndex, BuildTarget]) -> str: + if isinstance(arg, File): + return arg.absolute_path(state.environment.source_dir, state.environment.build_dir) + elif isinstance(arg, (CustomTarget, CustomTargetIndex, BuildTarget)): + return state.backend.get_target_filename_abs(arg) + else: + return os.path.join(state.environment.source_dir, state.subdir, arg) + + t = to_path(args[0]) + f = to_path(args[1]) + + return relpath(t, f) + def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule: return FSModule(*args, **kwargs) diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index b860fc8a32c8..7f113d66eb48 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -1,4 +1,4 @@ -project('fs module test') +project('fs module test', 'c') is_windows = build_machine.system() == 'windows' @@ -139,6 +139,29 @@ assert(fs.name('foo/bar/baz.dll.a') == 'baz.dll.a', 'failed to get basename with assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix') assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix') +# relative_to +if build_machine.system() == 'windows' + # strings + assert(fs.relative_to('c:\\prefix\\lib\\foo', 'c:\\prefix') == 'lib\\foo') + assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') + assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') + assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') + assert(fs.relative_to('prefix\\lib', 'prefix\\bin') == '..\\lib') + assert(fs.relative_to('proj1\\foo', 'proj1\\bar') == '..\\foo') + assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir\\subdirfile.txt') + assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '..\\..\\meson.build') + assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '..\\..\\meson.build') +else + # strings + assert(fs.relative_to('/prefix/lib/foo', '/prefix') == 'lib/foo') + assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') + assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') + assert(fs.relative_to('prefix/lib', 'prefix/bin') == '../lib') + assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir/subdirfile.txt') + assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '../../meson.build') + assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '../../meson.build') +endif + subdir('subdir') subproject('subbie') diff --git a/test cases/common/220 fs module/subdir/btgt.c b/test cases/common/220 fs module/subdir/btgt.c new file mode 100644 index 000000000000..8479e67d1090 --- /dev/null +++ b/test cases/common/220 fs module/subdir/btgt.c @@ -0,0 +1,5 @@ +int +main(void) +{ + return 0; +} diff --git a/test cases/common/220 fs module/subdir/meson.build b/test cases/common/220 fs module/subdir/meson.build index 0cd2475e92d5..3ea902c2fcc8 100644 --- a/test cases/common/220 fs module/subdir/meson.build +++ b/test cases/common/220 fs module/subdir/meson.build @@ -4,3 +4,53 @@ assert(fs.is_samepath(meson.project_source_root(), '..'), 'is_samepath not detec assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory') assert(fs.is_samepath(subdirfiles[0], 'subdirfile.txt'), 'is_samepath not detecting same directory when using File and str') + +# More relative_to to test subdir/builddir components + +python3 = find_program('python3') +build_to_src = fs.relative_to(meson.current_source_dir(), meson.current_build_dir()) +src_to_build = fs.relative_to(meson.current_build_dir(), meson.current_source_dir()) + +btgt = executable('btgt', 'btgt.c') +ctgt = custom_target( + 'copied-files', + command: [ + python3, + '-c', + 'import shutil; shutil.copyfile("@INPUT0@", "@OUTPUT0@"); shutil.copyfile("@INPUT1@", "@OUTPUT1@")' + ], + input: [ + 'subdirfile.txt', + 'meson.build', + ], + output: [ + 'subdirfile.txt', + 'meson.build', + ], +) + +if build_machine.system() == 'windows' + # Test that CustomTarget works + assert(fs.relative_to('subdirfile.txt', ctgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt, 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) + # Test that CustomTargetIndex works + assert(fs.relative_to('meson.build', ctgt[1]) == '..\\@0@\\meson.build'.format(build_to_src)) + assert(fs.relative_to(ctgt[1], 'meson.build') == '..\\@0@\\meson.build'.format(src_to_build)) + # Test that BuildTarget works + assert(fs.relative_to('subdirfile.txt', btgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(btgt, 'subdirfile.txt') == '..\\@0@\\btgt.exe'.format(src_to_build)) +else + # Test that CustomTarget works + assert(fs.relative_to('subdirfile.txt', ctgt) == '../@0@/subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt, 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) + # Test that CustomTargetIndex works + assert(fs.relative_to('meson.build', ctgt[1]) == '../@0@/meson.build'.format(build_to_src)) + assert(fs.relative_to(ctgt[1], 'meson.build') == '../@0@/meson.build'.format(src_to_build)) + # Test that BuildTarget works + assert(fs.relative_to('subdirfile.txt', btgt) == '../@0@/subdirfile.txt'.format(build_to_src)) + if host_machine.system() == 'windows' + assert(fs.relative_to(btgt, 'subdirfile.txt') == '../@0@/btgt.exe'.format(src_to_build)) + else + assert(fs.relative_to(btgt, 'subdirfile.txt') == '../@0@/btgt'.format(src_to_build)) + endif +endif From 543e9ca0cf0c00d752bd723ec403e91b839bf9b4 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 14 Aug 2023 09:03:42 -0500 Subject: [PATCH 129/855] Remove XML filter from testlog.{json,txt} and std streams This was an unintended consequence of the original patch in #11977. Co-authored-by: Benoit Pierre --- mesonbuild/mtest.py | 12 ++++++------ .../110 replace unencodable xml chars/meson.build | 2 +- unittests/allplatformstests.py | 14 ++++++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 1ac27824ced7..1298cc031975 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -869,10 +869,10 @@ def log(self, harness: 'TestHarness', test: 'TestRun') -> None: et.SubElement(testcase, 'system-out').text = subtest.explanation if test.stdo: out = et.SubElement(suite, 'system-out') - out.text = test.stdo.rstrip() + out.text = replace_unencodable_xml_chars(test.stdo.rstrip()) if test.stde: err = et.SubElement(suite, 'system-err') - err.text = test.stde.rstrip() + err.text = replace_unencodable_xml_chars(test.stde.rstrip()) else: if test.project not in self.suites: suite = self.suites[test.project] = et.Element( @@ -895,10 +895,10 @@ def log(self, harness: 'TestHarness', test: 'TestRun') -> None: suite.attrib['failures'] = str(int(suite.attrib['failures']) + 1) if test.stdo: out = et.SubElement(testcase, 'system-out') - out.text = test.stdo.rstrip() + out.text = replace_unencodable_xml_chars(test.stdo.rstrip()) if test.stde: err = et.SubElement(testcase, 'system-err') - err.text = test.stde.rstrip() + err.text = replace_unencodable_xml_chars(test.stde.rstrip()) async def finish(self, harness: 'TestHarness') -> None: """Calculate total test counts and write out the xml result.""" @@ -1182,9 +1182,9 @@ def decode(stream: T.Union[None, bytes]) -> str: if stream is None: return '' try: - return replace_unencodable_xml_chars(stream.decode('utf-8')) + return stream.decode('utf-8') except UnicodeDecodeError: - return replace_unencodable_xml_chars(stream.decode('iso-8859-1', errors='ignore')) + return stream.decode('iso-8859-1', errors='ignore') async def read_decode(reader: asyncio.StreamReader, queue: T.Optional['asyncio.Queue[T.Optional[str]]'], diff --git a/test cases/unit/110 replace unencodable xml chars/meson.build b/test cases/unit/110 replace unencodable xml chars/meson.build index 2e6b1b7930ad..73485b07325b 100644 --- a/test cases/unit/110 replace unencodable xml chars/meson.build +++ b/test cases/unit/110 replace unencodable xml chars/meson.build @@ -1,4 +1,4 @@ project('replace unencodable xml chars') test_script = find_program('script.py') -test('main', test_script) +test('main', test_script, verbose: true) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index f7fb1b0c5f00..819cc2ee79a6 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -463,9 +463,8 @@ def test_replace_unencodable_xml_chars(self): valid_string = base_string_valid + repr(invalid_string)[1:-1] + base_string_valid invalid_string = base_string_invalid + invalid_string + base_string_invalid - broken_xml_stream = invalid_string.encode() - decoded_broken_stream = mtest.decode(broken_xml_stream) - self.assertEqual(decoded_broken_stream, valid_string) + fixed_string = mtest.replace_unencodable_xml_chars(invalid_string) + self.assertEqual(fixed_string, valid_string) def test_replace_unencodable_xml_chars_unit(self): ''' @@ -477,9 +476,16 @@ def test_replace_unencodable_xml_chars_unit(self): raise SkipTest('xmllint not installed') testdir = os.path.join(self.unit_test_dir, '110 replace unencodable xml chars') self.init(testdir) - self.run_tests() + tests_command_output = self.run_tests() junit_xml_logs = Path(self.logdir, 'testlog.junit.xml') subprocess.run(['xmllint', junit_xml_logs], check=True) + # Ensure command output and JSON / text logs are not mangled. + raw_output_sample = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b' + assert raw_output_sample in tests_command_output + text_log = Path(self.logdir, 'testlog.txt').read_text() + assert raw_output_sample in text_log + json_log = json.loads(Path(self.logdir, 'testlog.json').read_bytes()) + assert raw_output_sample in json_log['stdout'] def test_run_target_files_path(self): ''' From 7a2b673d405853fc8596dbafee42926da621a057 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 17 Aug 2023 16:09:39 -0500 Subject: [PATCH 130/855] Remove hacky setup for CustomTargetIndex tests in fs.relative_to() --- .../common/220 fs module/subdir/meson.build | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/test cases/common/220 fs module/subdir/meson.build b/test cases/common/220 fs module/subdir/meson.build index 3ea902c2fcc8..a0f3091fa4ad 100644 --- a/test cases/common/220 fs module/subdir/meson.build +++ b/test cases/common/220 fs module/subdir/meson.build @@ -7,35 +7,19 @@ assert(fs.is_samepath(subdirfiles[0], 'subdirfile.txt'), 'is_samepath not detect # More relative_to to test subdir/builddir components -python3 = find_program('python3') build_to_src = fs.relative_to(meson.current_source_dir(), meson.current_build_dir()) src_to_build = fs.relative_to(meson.current_build_dir(), meson.current_source_dir()) btgt = executable('btgt', 'btgt.c') -ctgt = custom_target( - 'copied-files', - command: [ - python3, - '-c', - 'import shutil; shutil.copyfile("@INPUT0@", "@OUTPUT0@"); shutil.copyfile("@INPUT1@", "@OUTPUT1@")' - ], - input: [ - 'subdirfile.txt', - 'meson.build', - ], - output: [ - 'subdirfile.txt', - 'meson.build', - ], -) +ctgt = fs.copyfile('subdirfile.txt') if build_machine.system() == 'windows' # Test that CustomTarget works assert(fs.relative_to('subdirfile.txt', ctgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) assert(fs.relative_to(ctgt, 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) # Test that CustomTargetIndex works - assert(fs.relative_to('meson.build', ctgt[1]) == '..\\@0@\\meson.build'.format(build_to_src)) - assert(fs.relative_to(ctgt[1], 'meson.build') == '..\\@0@\\meson.build'.format(src_to_build)) + assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) # Test that BuildTarget works assert(fs.relative_to('subdirfile.txt', btgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) assert(fs.relative_to(btgt, 'subdirfile.txt') == '..\\@0@\\btgt.exe'.format(src_to_build)) @@ -44,8 +28,8 @@ else assert(fs.relative_to('subdirfile.txt', ctgt) == '../@0@/subdirfile.txt'.format(build_to_src)) assert(fs.relative_to(ctgt, 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) # Test that CustomTargetIndex works - assert(fs.relative_to('meson.build', ctgt[1]) == '../@0@/meson.build'.format(build_to_src)) - assert(fs.relative_to(ctgt[1], 'meson.build') == '../@0@/meson.build'.format(src_to_build)) + assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '../@0@/subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) # Test that BuildTarget works assert(fs.relative_to('subdirfile.txt', btgt) == '../@0@/subdirfile.txt'.format(build_to_src)) if host_machine.system() == 'windows' From e313f78465f3d3570838f77372f1b35ad6917770 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 17:50:43 -0400 Subject: [PATCH 131/855] fix style errors in fs.relative_to implementation In commit f52bcaa27fc125ab9ae583af466ba99c164169f3 a few issues were added: - doc typo - imports for utils.universal are not intended to be directly used, it's an internal wrapper that exists solely to make mesonlib work well as it always did while simultaneously allowing `meson --internal` codepaths to avoid importing anything other than an extremely stripped down core - type annotation specific import was imported at runtime scope --- docs/markdown/Fs-module.md | 2 +- mesonbuild/modules/fs.py | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/markdown/Fs-module.md b/docs/markdown/Fs-module.md index bf9ddba9d212..f136bb904da2 100644 --- a/docs/markdown/Fs-module.md +++ b/docs/markdown/Fs-module.md @@ -228,7 +228,7 @@ fs.stem('foo/bar/baz.dll.a') # baz.dll *Since 1.3.0* -Return a relative filepath. In event a relative path could not be found, the +Return a relative filepath. In the event a relative path could not be found, the absolute path of `to` is returned. Relative path arguments will be assumed to be relative to `meson.current_source_dir()`. diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index a2dbdf2ebe63..89aead06b1c5 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -23,19 +23,13 @@ from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs -from ..interpreterbase.baseobjects import TYPE_kwargs -from ..mesonlib import ( - File, - MesonException, - has_path_sep, - path_is_in_root, -) -from ..utils.universal import relpath +from ..mesonlib import File, MesonException, has_path_sep, path_is_in_root, relpath if T.TYPE_CHECKING: from . import ModuleState from ..build import BuildTargetTypes from ..interpreter import Interpreter + from ..interpreterbase import TYPE_kwargs from ..mesonlib import FileOrString, FileMode from typing_extensions import TypedDict From 98232eb0364238958996a192d2452ea3b4f8879b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 20:43:14 -0400 Subject: [PATCH 132/855] skip test on pkgconf 2.0.1 that is broken there due to a reported bug --- test cases/common/44 pkgconfig-gen/dependencies/meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test cases/common/44 pkgconfig-gen/dependencies/meson.build b/test cases/common/44 pkgconfig-gen/dependencies/meson.build index f80f58a50806..8243f6f3723a 100644 --- a/test cases/common/44 pkgconfig-gen/dependencies/meson.build +++ b/test cases/common/44 pkgconfig-gen/dependencies/meson.build @@ -1,5 +1,9 @@ project('pkgconfig-gen-dependencies', 'c', version: '1.0') +if find_program('pkg-config').version() == '2.0.1' + error('MESON_SKIP_TEST: cannot test uninstalled.pc due to https://github.com/pkgconf/pkgconf/issues/310#issuecomment-1677844842') +endif + pkgg = import('pkgconfig') # libmain internally use libinternal and expose libexpose in its API From 1fd70a2a004900b7d97d9fc560e87d33266ecfed Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 20:44:42 -0400 Subject: [PATCH 133/855] tests: consolidate MESON_SKIP_TEST reporting and use it in unittests Previously, we only reported the skip reason when running project tests. --- run_project_tests.py | 26 +++++++------------------- run_single_test.py | 13 +++---------- run_tests.py | 9 +++++++++ unittests/baseplatformtests.py | 14 +++++++------- 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index 27020caef9fe..acfa284d79ab 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -53,10 +53,12 @@ from mesonbuild.mlog import blue, bold, cyan, green, red, yellow, normal_green from mesonbuild.coredata import backendlist, version as meson_version from mesonbuild.modules.python import PythonExternalProgram -from run_tests import get_fake_options, run_configure, get_meson_script -from run_tests import get_backend_commands, get_backend_args_for_dir, Backend -from run_tests import ensure_backend_detects_changes -from run_tests import guess_backend +from run_tests import ( + get_fake_options, run_configure, get_meson_script, get_backend_commands, + get_backend_args_for_dir, Backend, ensure_backend_detects_changes, + guess_backend, handle_meson_skip_test, +) + if T.TYPE_CHECKING: from types import FrameType @@ -1206,12 +1208,6 @@ def cancel(self) -> None: RunFutureUnion = T.Union[TestRunFuture, LogRunFuture] -def test_emits_skip_msg(line: str) -> bool: - for prefix in {'Problem encountered', 'Assert failed', 'Failed to configure the CMake subproject'}: - if f'{prefix}: MESON_SKIP_TEST' in line: - return True - return False - def _run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], log_name_base: str, failfast: bool, @@ -1324,15 +1320,7 @@ def tqdm_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: skip_as_expected = True else: # skipped due to test outputting 'MESON_SKIP_TEST' - for l in result.stdo.splitlines(): - if test_emits_skip_msg(l): - is_skipped = True - offset = l.index('MESON_SKIP_TEST') + 16 - skip_reason = l[offset:].strip() - break - else: - is_skipped = False - skip_reason = '' + is_skipped, skip_reason = handle_meson_skip_test(result.stdo) if not skip_dont_care(t): skip_as_expected = (is_skipped == t.skip_expected) else: diff --git a/run_single_test.py b/run_single_test.py index eb9379acc35e..5cd4f5e9feae 100755 --- a/run_single_test.py +++ b/run_single_test.py @@ -13,7 +13,8 @@ import typing as T from mesonbuild import mlog -from run_project_tests import TestDef, load_test_json, run_test, BuildStep, test_emits_skip_msg +from run_tests import handle_meson_skip_test +from run_project_tests import TestDef, load_test_json, run_test, BuildStep from run_project_tests import setup_commands, detect_system_compiler, print_tool_versions if T.TYPE_CHECKING: @@ -69,15 +70,7 @@ def should_fail(path: pathlib.Path) -> str: is_skipped = True skip_reason = 'not run because preconditions were not met' else: - for l in result.stdo.splitlines(): - if test_emits_skip_msg(l): - is_skipped = True - offset = l.index('MESON_SKIP_TEST') + 16 - skip_reason = l[offset:].strip() - break - else: - is_skipped = False - skip_reason = '' + is_skipped, skip_reason = handle_meson_skip_test(result.stdo) if is_skipped: msg = mlog.yellow('SKIP:') diff --git a/run_tests.py b/run_tests.py index cf0633783303..699e29356153 100755 --- a/run_tests.py +++ b/run_tests.py @@ -187,6 +187,15 @@ def get_convincing_fake_env_and_cc(bdir, prefix): else: exe_suffix = '' +def handle_meson_skip_test(out: str) -> T.Tuple[bool, str]: + for line in out.splitlines(): + for prefix in {'Problem encountered', 'Assert failed', 'Failed to configure the CMake subproject'}: + if f'{prefix}: MESON_SKIP_TEST' in line: + offset = line.index('MESON_SKIP_TEST') + 16 + reason = line[offset:].strip() + return (True, reason) + return (False, '') + def get_meson_script() -> str: ''' Guess the meson that corresponds to the `mesonbuild` that has been imported diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 3008eb731850..03ab1c521a86 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -41,7 +41,7 @@ from run_tests import ( Backend, ensure_backend_detects_changes, get_backend_commands, get_builddir_target_args, get_meson_script, run_configure_inprocess, - run_mtest_inprocess + run_mtest_inprocess, handle_meson_skip_test, ) @@ -183,8 +183,9 @@ def _run(self, command, *, workdir=None, override_envvars: T.Optional[T.Mapping[ print('stderr:') print(proc.stderr) if proc.returncode != 0: - if 'MESON_SKIP_TEST' in proc.stdout: - raise SkipTest('Project requested skipping.') + skipped, reason = handle_meson_skip_test(proc.stdout) + if skipped: + raise SkipTest(f'Project requested skipping: {reason}') raise subprocess.CalledProcessError(proc.returncode, command, output=proc.stdout) return proc.stdout @@ -234,8 +235,9 @@ def init(self, srcdir, *, mesonbuild.mlog._logger.log_dir = None mesonbuild.mlog._logger.log_file = None - if 'MESON_SKIP_TEST' in out: - raise SkipTest('Project requested skipping.') + skipped, reason = handle_meson_skip_test(out) + if skipped: + raise SkipTest(f'Project requested skipping: {reason}') if returncode != 0: self._print_meson_log() print('Stdout:\n') @@ -247,8 +249,6 @@ def init(self, srcdir, *, else: try: out = self._run(self.setup_command + args + extra_args + build_and_src_dir_args, override_envvars=override_envvars, workdir=workdir) - except SkipTest: - raise SkipTest('Project requested skipping: ' + srcdir) except Exception: if not allow_fail: self._print_meson_log() From 84c8905d527893bedc673e8a036b8b2ec89368b4 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 23:56:51 -0400 Subject: [PATCH 134/855] Revert "Add fs.relative_to()" This reverts commit f52bcaa27fc125ab9ae583af466ba99c164169f3. It did not pass CI, and was merged anyway because there were two CI errors in the same cygwin job. The other error was not the fault of this commit, and since cygwin errors were glossed over because they were "expected", the presence of a new error *added* by this commit was overlooked. Per the meson development policy, PRs which result in CI errors can/should be reverted at will, no questions asked. --- docs/markdown/Fs-module.md | 14 -------- docs/markdown/snippets/fs_relative_to.md | 17 ---------- mesonbuild/modules/fs.py | 29 ++++------------ test cases/common/220 fs module/meson.build | 25 +------------- test cases/common/220 fs module/subdir/btgt.c | 5 --- .../common/220 fs module/subdir/meson.build | 34 ------------------- 6 files changed, 8 insertions(+), 116 deletions(-) delete mode 100644 docs/markdown/snippets/fs_relative_to.md delete mode 100644 test cases/common/220 fs module/subdir/btgt.c diff --git a/docs/markdown/Fs-module.md b/docs/markdown/Fs-module.md index f136bb904da2..cc67355b5df4 100644 --- a/docs/markdown/Fs-module.md +++ b/docs/markdown/Fs-module.md @@ -224,20 +224,6 @@ fs.stem('foo/bar/baz.dll.a') # baz.dll project. If the file specified by `path` is a `files()` object it cannot refer to a built file. -### relative_to - -*Since 1.3.0* - -Return a relative filepath. In the event a relative path could not be found, the -absolute path of `to` is returned. Relative path arguments will be assumed to be -relative to `meson.current_source_dir()`. - -Has the following positional arguments: - - to `str | file | custom_tgt | custom_idx | tgt`: end path - - from `str | file | custom_tgt | custom_idx | tgt`: start path - -returns: - - a string ### copyfile diff --git a/docs/markdown/snippets/fs_relative_to.md b/docs/markdown/snippets/fs_relative_to.md deleted file mode 100644 index 82e6a4268bb8..000000000000 --- a/docs/markdown/snippets/fs_relative_to.md +++ /dev/null @@ -1,17 +0,0 @@ -## `fs.relative_to()` - -The `fs` module now has a `relative_to` method. The method will return the -relative path from argument one to argument two, if one exists. Otherwise, the -absolute path to argument one is returned. - -```meson -assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') -assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') -assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') - -assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') -assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') -``` - -In addition to strings, it can handle files, custom targets, custom target -indices, and build targets. diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 89aead06b1c5..53174d2316aa 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -20,16 +20,19 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments +from ..build import CustomTarget, InvalidArguments from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs -from ..mesonlib import File, MesonException, has_path_sep, path_is_in_root, relpath +from ..mesonlib import ( + File, + MesonException, + has_path_sep, + path_is_in_root, +) if T.TYPE_CHECKING: from . import ModuleState - from ..build import BuildTargetTypes from ..interpreter import Interpreter - from ..interpreterbase import TYPE_kwargs from ..mesonlib import FileOrString, FileMode from typing_extensions import TypedDict @@ -72,7 +75,6 @@ def __init__(self, interpreter: 'Interpreter') -> None: 'stem': self.stem, 'read': self.read, 'copyfile': self.copyfile, - 'relative_to': self.relative_to, }) def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: @@ -310,23 +312,6 @@ def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[st return ModuleReturnValue(ct, [ct]) - @FeatureNew('fs.relative_to', '1.3.0') - @typed_pos_args('fs.relative_to', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) - @noKwargs - def relative_to(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], T.Union[FileOrString, BuildTargetTypes]], kwargs: TYPE_kwargs) -> str: - def to_path(arg: T.Union[FileOrString, CustomTarget, CustomTargetIndex, BuildTarget]) -> str: - if isinstance(arg, File): - return arg.absolute_path(state.environment.source_dir, state.environment.build_dir) - elif isinstance(arg, (CustomTarget, CustomTargetIndex, BuildTarget)): - return state.backend.get_target_filename_abs(arg) - else: - return os.path.join(state.environment.source_dir, state.subdir, arg) - - t = to_path(args[0]) - f = to_path(args[1]) - - return relpath(t, f) - def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule: return FSModule(*args, **kwargs) diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index 7f113d66eb48..b860fc8a32c8 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -1,4 +1,4 @@ -project('fs module test', 'c') +project('fs module test') is_windows = build_machine.system() == 'windows' @@ -139,29 +139,6 @@ assert(fs.name('foo/bar/baz.dll.a') == 'baz.dll.a', 'failed to get basename with assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix') assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix') -# relative_to -if build_machine.system() == 'windows' - # strings - assert(fs.relative_to('c:\\prefix\\lib\\foo', 'c:\\prefix') == 'lib\\foo') - assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') - assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') - assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') - assert(fs.relative_to('prefix\\lib', 'prefix\\bin') == '..\\lib') - assert(fs.relative_to('proj1\\foo', 'proj1\\bar') == '..\\foo') - assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir\\subdirfile.txt') - assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '..\\..\\meson.build') - assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '..\\..\\meson.build') -else - # strings - assert(fs.relative_to('/prefix/lib/foo', '/prefix') == 'lib/foo') - assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') - assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') - assert(fs.relative_to('prefix/lib', 'prefix/bin') == '../lib') - assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir/subdirfile.txt') - assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '../../meson.build') - assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '../../meson.build') -endif - subdir('subdir') subproject('subbie') diff --git a/test cases/common/220 fs module/subdir/btgt.c b/test cases/common/220 fs module/subdir/btgt.c deleted file mode 100644 index 8479e67d1090..000000000000 --- a/test cases/common/220 fs module/subdir/btgt.c +++ /dev/null @@ -1,5 +0,0 @@ -int -main(void) -{ - return 0; -} diff --git a/test cases/common/220 fs module/subdir/meson.build b/test cases/common/220 fs module/subdir/meson.build index a0f3091fa4ad..0cd2475e92d5 100644 --- a/test cases/common/220 fs module/subdir/meson.build +++ b/test cases/common/220 fs module/subdir/meson.build @@ -4,37 +4,3 @@ assert(fs.is_samepath(meson.project_source_root(), '..'), 'is_samepath not detec assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory') assert(fs.is_samepath(subdirfiles[0], 'subdirfile.txt'), 'is_samepath not detecting same directory when using File and str') - -# More relative_to to test subdir/builddir components - -build_to_src = fs.relative_to(meson.current_source_dir(), meson.current_build_dir()) -src_to_build = fs.relative_to(meson.current_build_dir(), meson.current_source_dir()) - -btgt = executable('btgt', 'btgt.c') -ctgt = fs.copyfile('subdirfile.txt') - -if build_machine.system() == 'windows' - # Test that CustomTarget works - assert(fs.relative_to('subdirfile.txt', ctgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) - assert(fs.relative_to(ctgt, 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) - # Test that CustomTargetIndex works - assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) - assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) - # Test that BuildTarget works - assert(fs.relative_to('subdirfile.txt', btgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) - assert(fs.relative_to(btgt, 'subdirfile.txt') == '..\\@0@\\btgt.exe'.format(src_to_build)) -else - # Test that CustomTarget works - assert(fs.relative_to('subdirfile.txt', ctgt) == '../@0@/subdirfile.txt'.format(build_to_src)) - assert(fs.relative_to(ctgt, 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) - # Test that CustomTargetIndex works - assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '../@0@/subdirfile.txt'.format(build_to_src)) - assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) - # Test that BuildTarget works - assert(fs.relative_to('subdirfile.txt', btgt) == '../@0@/subdirfile.txt'.format(build_to_src)) - if host_machine.system() == 'windows' - assert(fs.relative_to(btgt, 'subdirfile.txt') == '../@0@/btgt.exe'.format(src_to_build)) - else - assert(fs.relative_to(btgt, 'subdirfile.txt') == '../@0@/btgt'.format(src_to_build)) - endif -endif From 88747b4f8d4bb35c82c8855ecbd6a29ea419b6fd Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sat, 12 Aug 2023 10:45:05 +0200 Subject: [PATCH 135/855] docs: Provide example for feature.disable_auto_if --- docs/yaml/objects/feature.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/yaml/objects/feature.yaml b/docs/yaml/objects/feature.yaml index a5ae7a6910a0..3e0ae69df1e0 100644 --- a/docs/yaml/objects/feature.yaml +++ b/docs/yaml/objects/feature.yaml @@ -33,6 +33,20 @@ methods: | Enabled | Enabled | Enabled | | Disabled | Disabled | Disabled | + example: | + `disable_auto_if` is useful to give precedence to mutually exclusive dependencies + (that provide the same API) if either or both are available: + + ``` + # '-Dfoo=auto -Dbar=enabled' will not pick foo even if installed. + use_bar = get_option('bar') + use_foo = get_option('foo').disable_auto_if(use_bar.enabled()) + dep_foo = dependency('foo', required: use_foo) + if not dep_foo.found() + dep_foo = dependency('bar', required: use_bar) + endif + ``` + posargs: value: type: bool From 7cbe37ebd94e9df984328fd9722cc2fc9f61651b Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 10 Aug 2023 14:35:18 -0400 Subject: [PATCH 136/855] Add more descriptive description to CustomTarget Allow modules using CustomTarget to modify the command description used by ninja backend. This result in more precise logs when building a project. --- docs/markdown/snippets/custom_target_description.md | 6 ++++++ mesonbuild/backend/ninjabackend.py | 4 ++-- mesonbuild/build.py | 2 ++ mesonbuild/modules/external_project.py | 1 + mesonbuild/modules/fs.py | 1 + mesonbuild/modules/gnome.py | 10 ++++++++++ mesonbuild/modules/i18n.py | 3 +++ mesonbuild/modules/qt.py | 3 +++ mesonbuild/modules/rust.py | 1 + mesonbuild/modules/windows.py | 1 + 10 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/custom_target_description.md diff --git a/docs/markdown/snippets/custom_target_description.md b/docs/markdown/snippets/custom_target_description.md new file mode 100644 index 000000000000..fd8820eb23a3 --- /dev/null +++ b/docs/markdown/snippets/custom_target_description.md @@ -0,0 +1,6 @@ +## More meaningful description of many generative tasks + +When a module uses a `CustomTarget` to process files, it now has the possibility +to customize the message displayed by ninja. + +Many modules were updated to take advantage of this new feature. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 72c826517ba9..1d563a2d81d8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1147,7 +1147,7 @@ def unwrap_dep_list(self, target): deps.append(os.path.join(self.get_target_dir(i), output)) return deps - def generate_custom_target(self, target): + def generate_custom_target(self, target: build.CustomTarget): self.custom_target_generator_inputs(target) (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) @@ -1185,7 +1185,7 @@ def generate_custom_target(self, target): elem.add_item('pool', 'console') full_name = Path(target.subdir, target.name).as_posix() elem.add_item('COMMAND', cmd) - elem.add_item('description', f'Generating {full_name} with a custom command{cmd_type}') + elem.add_item('description', target.description.format(full_name) + cmd_type) self.add_build(elem) self.processed_targets.add(target.get_id()) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 5b9d1525c983..1463e51e3586 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2535,6 +2535,7 @@ def __init__(self, install_tag: T.Optional[T.List[T.Optional[str]]] = None, absolute_paths: bool = False, backend: T.Optional['Backend'] = None, + description: str = 'Generating {} with a custom command', ): # TODO expose keyword arg to make MachineChoice.HOST configurable super().__init__(name, subdir, subproject, False, MachineChoice.HOST, environment, @@ -2559,6 +2560,7 @@ def __init__(self, self.install_mode = install_mode self.install_tag = _process_install_tag(install_tag, len(self.outputs)) self.name = name if name else self.outputs[0] + self.description = description # Whether to use absolute paths for all files on the commandline self.absolute_paths = absolute_paths diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index f7a72bcedafb..e7b7c43f6985 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -247,6 +247,7 @@ def _create_targets(self, extra_depends: T.List[T.Union['BuildTarget', 'CustomTa depfile=f'{self.name}.d', console=True, extra_depends=extra_depends, + description='Generating external project {}', ) idir = build.InstallDir(self.subdir.as_posix(), diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 53174d2316aa..c14548659919 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -308,6 +308,7 @@ def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[st install_mode=kwargs['install_mode'], install_tag=[kwargs['install_tag']], backend=state.backend, + description='Copying file {}', ) return ModuleReturnValue(ct, [ct]) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 18862e72c96b..6bd0436a6c01 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1242,6 +1242,7 @@ def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs ['gschemas.compiled'], build_by_default=kwargs['build_by_default'], depend_files=kwargs['depend_files'], + description='Compiling gschemas {}', ) self._devenv_prepend('GSETTINGS_SCHEMA_DIR', os.path.join(state.environment.get_build_dir(), state.subdir)) return ModuleReturnValue(target_g, [target_g]) @@ -1355,6 +1356,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y [po_file], [gmo_file], install_tag=['doc'], + description='Generating yelp doc {}', ) targets.append(gmotarget) @@ -1370,6 +1372,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y install=True, install_dir=[l_install_dir], install_tag=['doc'], + description='Generating yelp doc {}', ) targets.append(mergetarget) @@ -1513,6 +1516,7 @@ def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: [f'{modulename}-decl.txt'], build_always_stale=True, extra_depends=new_depends, + description='Generating gtkdoc {}', ) alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject, state.environment) if kwargs['check']: @@ -1656,6 +1660,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un xml_files, [output], build_by_default=build_by_default, + description='Generating gdbus source {}', ) targets.append(cfile_custom_target) @@ -1680,6 +1685,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un install=install_header, install_dir=[install_dir], install_tag=['devel'], + description='Generating gdbus header {}', ) targets.append(hfile_custom_target) @@ -1708,6 +1714,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un outputs, build_by_default=build_by_default, extra_depends=depends, + description='Generating gdbus docbook {}', ) targets.append(docbook_custom_target) @@ -1930,6 +1937,7 @@ def _make_mkenum_impl( extra_depends=depends, # https://github.com/mesonbuild/meson/issues/973 absolute_paths=True, + description='Generating GObject enum file {}', ) @typed_pos_args('gnome.genmarshal', str) @@ -1996,6 +2004,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh install_tag=['devel'], capture=capture, depend_files=kwargs['depend_files'], + description='Generating glib marshaller header {}', ) c_cmd = cmd + ['--body', '@INPUT@'] @@ -2015,6 +2024,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh capture=capture, depend_files=kwargs['depend_files'], extra_depends=extra_deps, + description='Generating glib marshaller source {}', ) rv = [body, header] diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 11dd9ef2cd65..c82e580a2a1b 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -212,6 +212,7 @@ def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'Me install=kwargs['install'], install_dir=[kwargs['install_dir']] if kwargs['install_dir'] is not None else None, install_tag=install_tag, + description='Merging translations for {}', ) return ModuleReturnValue(ct, [ct]) @@ -304,6 +305,7 @@ def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') - # Bonus: the build tree has something usable as an uninstalled bindtextdomain() target dir. install_dir=[path.join(install_dir, l, 'LC_MESSAGES')], install_tag=['i18n'], + description='Building translation {}', ) targets.append(gmotarget) gmotargets.append(gmotarget) @@ -390,6 +392,7 @@ def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' install=kwargs['install'], install_dir=[kwargs['install_dir']] if kwargs['install_dir'] is not None else None, install_tag=install_tag, + description='Merging translations for {}', ) return ModuleReturnValue(ct, [ct]) diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index 85558885343a..20ff11176486 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -348,6 +348,7 @@ def _compile_resources_impl(self, state: 'ModuleState', kwargs: 'ResourceCompile [f'{name}.cpp'], depend_files=qrc_deps, depfile=f'{name}.d', + description='Compiling Qt resources {}', ) targets.append(res_target) else: @@ -368,6 +369,7 @@ def _compile_resources_impl(self, state: 'ModuleState', kwargs: 'ResourceCompile [f'{name}.cpp'], depend_files=qrc_deps, depfile=f'{name}.d', + description='Compiling Qt resources {}', ) targets.append(res_target) @@ -600,6 +602,7 @@ def compile_translations(self, state: 'ModuleState', args: T.Tuple, kwargs: 'Com install_dir=[kwargs['install_dir']], install_tag=['i18n'], build_by_default=kwargs['build_by_default'], + description='Compiling Qt translations {}', ) translations.append(lrelease_target) if qresource: diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 4f5494af31e8..0bda2c250bce 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -263,6 +263,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu extra_depends=depends, depend_files=depend_files, backend=state.backend, + description='Generating bindings for Rust {}', ) return ModuleReturnValue([target], [target]) diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index f9c7c57d80df..b7cdeb33f13d 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -206,6 +206,7 @@ def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, buil depfile=depfile, depend_files=wrc_depend_files, extra_depends=wrc_depends, + description='Compiling Windows resource {}', )) return ModuleReturnValue(res_targets, [res_targets]) From 268276f7acc55a79fbd31a7d510af93d43ac2d8f Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 14 Aug 2023 19:45:35 +0200 Subject: [PATCH 137/855] tests: fix assertion rewriting when pytest is used --- run_unittests.py | 2 +- setup.cfg | 2 +- unittests/__init__.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 unittests/__init__.py diff --git a/run_unittests.py b/run_unittests.py index 4dd674d346e1..7a2502a6e886 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -136,7 +136,7 @@ def main(): # Let there be colors! if 'CI' in os.environ: pytest_args += ['--color=yes'] - pytest_args += ['./run_unittests.py'] + pytest_args += ['unittests'] pytest_args += convert_args(sys.argv[1:]) # Always disable pytest-cov because we use a custom setup try: diff --git a/setup.cfg b/setup.cfg index a23af07c6cd3..dfaba76dd194 100644 --- a/setup.cfg +++ b/setup.cfg @@ -62,4 +62,4 @@ include = mesonbuild, mesonbuild.* [tool:pytest] python_classes = python_files = - run_unittests.py + unittests/*tests.py diff --git a/unittests/__init__.py b/unittests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 From 22f90fd469a2742a2bb2d4f79e4a585a525ea934 Mon Sep 17 00:00:00 2001 From: M Henning Date: Tue, 8 Aug 2023 00:54:30 -0400 Subject: [PATCH 138/855] Suggest fix in MesonVersionMismatchException Every time I update meson, I spend about 20 minutes on frustrated googling to figure out how to update my build directory to work with the new version. I'm forgetful, okay? Ease this pain point by suggesting a potential fix in the error message. --- mesonbuild/coredata.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 7bbc09eb1701..bb84f72c162b 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -91,7 +91,8 @@ class MesonVersionMismatchException(MesonException): '''Build directory generated with Meson version is incompatible with current version''' def __init__(self, old_version: str, current_version: str) -> None: super().__init__(f'Build directory has been generated with Meson version {old_version}, ' - f'which is incompatible with the current version {current_version}.') + f'which is incompatible with the current version {current_version}. ' + f'Consider reconfiguring the directory with meson setup --reconfigure.') self.old_version = old_version self.current_version = current_version From 946a3561c2f45b2e522f695a08516333cf7ec9d4 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 18 Aug 2023 00:04:12 -0500 Subject: [PATCH 139/855] Revert "Revert "Add fs.relative_to()"" This reverts commit 84c8905d527893bedc673e8a036b8b2ec89368b4. Fixed the cygwin failure... --- docs/markdown/Fs-module.md | 14 +++++++++ docs/markdown/snippets/fs_relative_to.md | 17 +++++++++++ mesonbuild/modules/fs.py | 29 +++++++++++++----- test cases/common/220 fs module/meson.build | 25 +++++++++++++++- test cases/common/220 fs module/subdir/btgt.c | 5 ++++ .../common/220 fs module/subdir/meson.build | 30 +++++++++++++++++++ 6 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 docs/markdown/snippets/fs_relative_to.md create mode 100644 test cases/common/220 fs module/subdir/btgt.c diff --git a/docs/markdown/Fs-module.md b/docs/markdown/Fs-module.md index cc67355b5df4..7ba4832a0073 100644 --- a/docs/markdown/Fs-module.md +++ b/docs/markdown/Fs-module.md @@ -224,6 +224,20 @@ fs.stem('foo/bar/baz.dll.a') # baz.dll project. If the file specified by `path` is a `files()` object it cannot refer to a built file. +### relative_to + +*Since 1.3.0* + +Return a relative filepath. In the event a relative path could not be found, the +absolute path of `to` is returned. Relative path arguments will be assumed to be +relative to `meson.current_source_dir()`. + +Has the following positional arguments: + - to `str | file | custom_tgt | custom_idx | build_tgt`: end path + - from `str | file | custom_tgt | custom_idx | build_tgt`: start path + +returns: + - a string ### copyfile diff --git a/docs/markdown/snippets/fs_relative_to.md b/docs/markdown/snippets/fs_relative_to.md new file mode 100644 index 000000000000..82e6a4268bb8 --- /dev/null +++ b/docs/markdown/snippets/fs_relative_to.md @@ -0,0 +1,17 @@ +## `fs.relative_to()` + +The `fs` module now has a `relative_to` method. The method will return the +relative path from argument one to argument two, if one exists. Otherwise, the +absolute path to argument one is returned. + +```meson +assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') +assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') +assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') + +assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') +assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') +``` + +In addition to strings, it can handle files, custom targets, custom target +indices, and build targets. diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index c14548659919..5a9533cba141 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -20,19 +20,16 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import CustomTarget, InvalidArguments +from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs -from ..mesonlib import ( - File, - MesonException, - has_path_sep, - path_is_in_root, -) +from ..mesonlib import File, MesonException, has_path_sep, path_is_in_root, relpath if T.TYPE_CHECKING: from . import ModuleState + from ..build import BuildTargetTypes from ..interpreter import Interpreter + from ..interpreterbase import TYPE_kwargs from ..mesonlib import FileOrString, FileMode from typing_extensions import TypedDict @@ -75,6 +72,7 @@ def __init__(self, interpreter: 'Interpreter') -> None: 'stem': self.stem, 'read': self.read, 'copyfile': self.copyfile, + 'relative_to': self.relative_to, }) def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: @@ -313,6 +311,23 @@ def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[st return ModuleReturnValue(ct, [ct]) + @FeatureNew('fs.relative_to', '1.3.0') + @typed_pos_args('fs.relative_to', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) + @noKwargs + def relative_to(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], T.Union[FileOrString, BuildTargetTypes]], kwargs: TYPE_kwargs) -> str: + def to_path(arg: T.Union[FileOrString, CustomTarget, CustomTargetIndex, BuildTarget]) -> str: + if isinstance(arg, File): + return arg.absolute_path(state.environment.source_dir, state.environment.build_dir) + elif isinstance(arg, (CustomTarget, CustomTargetIndex, BuildTarget)): + return state.backend.get_target_filename_abs(arg) + else: + return os.path.join(state.environment.source_dir, state.subdir, arg) + + t = to_path(args[0]) + f = to_path(args[1]) + + return relpath(t, f) + def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule: return FSModule(*args, **kwargs) diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index b860fc8a32c8..7f113d66eb48 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -1,4 +1,4 @@ -project('fs module test') +project('fs module test', 'c') is_windows = build_machine.system() == 'windows' @@ -139,6 +139,29 @@ assert(fs.name('foo/bar/baz.dll.a') == 'baz.dll.a', 'failed to get basename with assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix') assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix') +# relative_to +if build_machine.system() == 'windows' + # strings + assert(fs.relative_to('c:\\prefix\\lib\\foo', 'c:\\prefix') == 'lib\\foo') + assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') + assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') + assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') + assert(fs.relative_to('prefix\\lib', 'prefix\\bin') == '..\\lib') + assert(fs.relative_to('proj1\\foo', 'proj1\\bar') == '..\\foo') + assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir\\subdirfile.txt') + assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '..\\..\\meson.build') + assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '..\\..\\meson.build') +else + # strings + assert(fs.relative_to('/prefix/lib/foo', '/prefix') == 'lib/foo') + assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') + assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') + assert(fs.relative_to('prefix/lib', 'prefix/bin') == '../lib') + assert(fs.relative_to('subdir/subdirfile.txt', meson.current_source_dir()) == 'subdir/subdirfile.txt') + assert(fs.relative_to(files('meson.build'), files('subdir/meson.build')) == '../../meson.build') + assert(fs.relative_to(files('meson.build'), 'subdir/meson.build') == '../../meson.build') +endif + subdir('subdir') subproject('subbie') diff --git a/test cases/common/220 fs module/subdir/btgt.c b/test cases/common/220 fs module/subdir/btgt.c new file mode 100644 index 000000000000..8479e67d1090 --- /dev/null +++ b/test cases/common/220 fs module/subdir/btgt.c @@ -0,0 +1,5 @@ +int +main(void) +{ + return 0; +} diff --git a/test cases/common/220 fs module/subdir/meson.build b/test cases/common/220 fs module/subdir/meson.build index 0cd2475e92d5..6e2c8be50eb3 100644 --- a/test cases/common/220 fs module/subdir/meson.build +++ b/test cases/common/220 fs module/subdir/meson.build @@ -4,3 +4,33 @@ assert(fs.is_samepath(meson.project_source_root(), '..'), 'is_samepath not detec assert(fs.is_samepath(meson.project_build_root(), meson.current_build_dir() / '..'), 'is_samepath not detecting same directory') assert(fs.is_samepath(subdirfiles[0], 'subdirfile.txt'), 'is_samepath not detecting same directory when using File and str') + +# More relative_to to test subdir/builddir components + +build_to_src = fs.relative_to(meson.current_source_dir(), meson.current_build_dir()) +src_to_build = fs.relative_to(meson.current_build_dir(), meson.current_source_dir()) + +btgt = executable('btgt', 'btgt.c') +ctgt = fs.copyfile('subdirfile.txt') + +if build_machine.system() == 'windows' + # Test that CustomTarget works + assert(fs.relative_to('subdirfile.txt', ctgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt, 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) + # Test that CustomTargetIndex works + assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '..\\@0@\\subdirfile.txt'.format(src_to_build)) + # Test that BuildTarget works + assert(fs.relative_to('subdirfile.txt', btgt) == '..\\@0@\\subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(btgt, 'subdirfile.txt') == '..\\@0@\\@1@'.format(src_to_build, fs.name(btgt.full_path()))) +else + # Test that CustomTarget works + assert(fs.relative_to('subdirfile.txt', ctgt) == '../@0@/subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt, 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) + # Test that CustomTargetIndex works + assert(fs.relative_to('subdirfile.txt', ctgt[0]) == '../@0@/subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(ctgt[0], 'subdirfile.txt') == '../@0@/subdirfile.txt'.format(src_to_build)) + # Test that BuildTarget works + assert(fs.relative_to('subdirfile.txt', btgt) == '../@0@/subdirfile.txt'.format(build_to_src)) + assert(fs.relative_to(btgt, 'subdirfile.txt') == '../@0@/@1@'.format(src_to_build, fs.name(btgt.full_path()))) +endif From 5a827616b50c1d8dcf6a4d96142167dc91e85a1f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 15 Aug 2023 13:06:45 -0400 Subject: [PATCH 140/855] ninja backend: fix the automatic restat of outputs when reconfiguring The most notable problem this causes is that when running `meson setup --reconfigure` the build.ninja file is erroneously seen as out of date, so ninja immediately tries to regenerate it again as it didn't see the file get updated. There are two problems. The first problem is that we looked for the wrong file. Ninja creates a few internal files, and one of them is the one we care about: `.ninja_log`, which contains stat'ed timestamps for build outputs to aid in checking when things are out of date. But the thing we actually checked for is `.ninja_deps`, a file that contains a compressed database of depfile outputs. If the latter exists, then the former surely exists too. Checking for the wrong file meant that we would restat outputs, but only when some build edges were previously built that had depfile outputs. The second problem is that we checked for this in os.getcwd() instead of the configured build directory. This very easily fails to be correct, except when reconfigure is triggered directly by ninja itself, in which case we didn't need the restat to begin with. --- mesonbuild/backend/ninjabackend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1d563a2d81d8..03f33d613523 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -664,9 +664,9 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional os.replace(tempfilename, outfilename) mlog.cmd_ci_include(outfilename) # For CI debugging # Refresh Ninja's caches. https://github.com/ninja-build/ninja/pull/1685 - if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists('.ninja_deps'): - subprocess.call(self.ninja_command + ['-t', 'restat']) - subprocess.call(self.ninja_command + ['-t', 'cleandead']) + if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists(os.path.join(self.environment.build_dir, '.ninja_log')): + subprocess.call(self.ninja_command + ['-t', 'restat'], cwd=self.environment.build_dir) + subprocess.call(self.ninja_command + ['-t', 'cleandead'], cwd=self.environment.build_dir) self.generate_compdb() self.generate_rust_project_json() From 9153b82cc2a1fdd98566d7ec6e1a153e106eb03d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 00:48:31 -0400 Subject: [PATCH 141/855] CI: add pip caching to website job On average, saves 20 seconds for a job that may take 1.5 or 2 minutes. Mostly due to recompiling the same 3 wheels again and again, so that avoids pointless CPU waste. --- .github/workflows/website.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index fa322fb42c59..1b0ed8465fc5 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -31,10 +31,26 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + + - uses: actions/cache/restore@v3 + id: restore-cache + with: + # should use 'pip3 cache dir' to discover this path + path: ~/.cache/pip + key: website-pip-${{ github.run_number }} + restore-keys: website-pip- + - name: Install package run: | sudo apt-get -y install python3-pip ninja-build libjson-glib-dev pip install hotdoc chevron strictyaml + + - uses: actions/cache/save@v3 + with: + # should use 'pip3 cache dir' to discover this path + path: ~/.cache/pip + key: website-pip-${{ github.run_number }} + - name: Setup SSH Keys and known_hosts env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock From 2edcbb452ee30bb173518e51f28f7c192dc070e3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 17 Aug 2023 11:23:52 -0400 Subject: [PATCH 142/855] CI: trigger website job when testing modifications to the website job --- .github/workflows/website.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 1b0ed8465fc5..2c76d87846b8 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -10,9 +10,11 @@ on: branches: - master paths: + - .github/workflows/website.yml - docs/** pull_request: paths: + - .github/workflows/website.yml - docs/** workflow_dispatch: release: From 184277bb4abbc0aa194ac02f592192d91fb109e1 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 16 Aug 2023 12:59:58 -0400 Subject: [PATCH 143/855] docs: use future annotations for genrefman types in typing_extensions And in fact *use* typing_extensions, which is sometimes the only way to get access to TypedDict. Mostly, reindent almost but not quite an entire file to only define annotation classes under TYPE_CHECKING. --- docs/refman/generatorjson.py | 1 + docs/refman/jsonschema.py | 137 ++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/docs/refman/generatorjson.py b/docs/refman/generatorjson.py index d41cb7162c2d..a2edc184aa36 100644 --- a/docs/refman/generatorjson.py +++ b/docs/refman/generatorjson.py @@ -1,5 +1,6 @@ # SPDX-License-Identifer: Apache-2.0 # Copyright 2021 The Meson development team +from __future__ import annotations from pathlib import Path import json diff --git a/docs/refman/jsonschema.py b/docs/refman/jsonschema.py index e64bf06ad2b9..283d3a2d9808 100644 --- a/docs/refman/jsonschema.py +++ b/docs/refman/jsonschema.py @@ -10,79 +10,82 @@ VERSION_MAJOR = 1 # Changes here indicate breaking format changes (changes to existing keys) VERSION_MINOR = 1 # Changes here indicate non-breaking changes (only new keys are added to the existing structure) -class BaseObject(T.TypedDict): - ''' - Base object for most dicts in the JSON doc. +if T.TYPE_CHECKING: + from typing_extensions import TypedDict - All objects inheriting from BaseObject will support - the keys specified here: - ''' - name: str - description: str - since: T.Optional[str] - deprecated: T.Optional[str] - notes: T.List[str] - warnings: T.List[str] + class BaseObject(TypedDict): + ''' + Base object for most dicts in the JSON doc. -class Type(T.TypedDict): - obj: str # References an object from `root.objects` - holds: T.Sequence[object] # Mypy does not support recursive dicts, but this should be T.List[Type]... + All objects inheriting from BaseObject will support + the keys specified here: + ''' + name: str + description: str + since: T.Optional[str] + deprecated: T.Optional[str] + notes: T.List[str] + warnings: T.List[str] -class Argument(BaseObject): - ''' - Object that represents any type of a single function or method argument. - ''' - type: T.List[Type] # A non-empty list of types that are supported. - type_str: str # Formatted version of `type`. Is guaranteed to not contain any whitespaces. - required: bool - default: T.Optional[str] - min_varargs: T.Optional[int] # Only relevant for varargs, must be `null` for all other types of arguments - max_varargs: T.Optional[int] # Only relevant for varargs, must be `null` for all other types of arguments + class Type(TypedDict): + obj: str # References an object from `root.objects` + holds: T.Sequence[object] # Mypy does not support recursive dicts, but this should be T.List[Type]... -class Function(BaseObject): - ''' - Represents a function or method. - ''' - returns: T.List[Type] # A non-empty list of types that are supported. - returns_str: str # Formatted version of `returns`. Is guaranteed to not contain any whitespaces. - example: T.Optional[str] - posargs: T.Dict[str, Argument] - optargs: T.Dict[str, Argument] - kwargs: T.Dict[str, Argument] - varargs: T.Optional[Argument] - arg_flattening: bool + class Argument(BaseObject): + ''' + Object that represents any type of a single function or method argument. + ''' + type: T.List[Type] # A non-empty list of types that are supported. + type_str: str # Formatted version of `type`. Is guaranteed to not contain any whitespaces. + required: bool + default: T.Optional[str] + min_varargs: T.Optional[int] # Only relevant for varargs, must be `null` for all other types of arguments + max_varargs: T.Optional[int] # Only relevant for varargs, must be `null` for all other types of arguments -class Object(BaseObject): - ''' - Represents all types of Meson objects. The specific object type is stored in the `object_type` field. - ''' - example: T.Optional[str] - object_type: str # Defines the object type: Must be one of: ELEMENTARY, BUILTIN, MODULE, RETURNED - methods: T.Dict[str, Function] - is_container: bool - extends: T.Optional[str] - returned_by: T.List[str] - extended_by: T.List[str] - defined_by_module: T.Optional[str] + class Function(BaseObject): + ''' + Represents a function or method. + ''' + returns: T.List[Type] # A non-empty list of types that are supported. + returns_str: str # Formatted version of `returns`. Is guaranteed to not contain any whitespaces. + example: T.Optional[str] + posargs: T.Dict[str, Argument] + optargs: T.Dict[str, Argument] + kwargs: T.Dict[str, Argument] + varargs: T.Optional[Argument] + arg_flattening: bool -class ObjectsByType(T.TypedDict): - ''' - References to other objects are stored here for ease of navigation / filtering - ''' - elementary: T.List[str] - builtins: T.List[str] - returned: T.List[str] - modules: T.Dict[str, T.List[str]] + class Object(BaseObject): + ''' + Represents all types of Meson objects. The specific object type is stored in the `object_type` field. + ''' + example: T.Optional[str] + object_type: str # Defines the object type: Must be one of: ELEMENTARY, BUILTIN, MODULE, RETURNED + methods: T.Dict[str, Function] + is_container: bool + extends: T.Optional[str] + returned_by: T.List[str] + extended_by: T.List[str] + defined_by_module: T.Optional[str] + class ObjectsByType(TypedDict): + ''' + References to other objects are stored here for ease of navigation / filtering + ''' + elementary: T.List[str] + builtins: T.List[str] + returned: T.List[str] + modules: T.Dict[str, T.List[str]] -class Root(T.TypedDict): - ''' - The root object of the JSON reference manual - ''' - version_major: int # See the description above for - version_minor: int # VERSION_MAJOR and VERSION_MINOR - meson_version: str - functions: T.Dict[str, Function] # A mapping of to a `Function` object for *all* Meson functions - objects: T.Dict[str, Object] # A mapping of to a `Object` object for *all* Meson objects (including modules, elementary, etc.) - objects_by_type: ObjectsByType + + class Root(TypedDict): + ''' + The root object of the JSON reference manual + ''' + version_major: int # See the description above for + version_minor: int # VERSION_MAJOR and VERSION_MINOR + meson_version: str + functions: T.Dict[str, Function] # A mapping of to a `Function` object for *all* Meson functions + objects: T.Dict[str, Object] # A mapping of to a `Object` object for *all* Meson objects (including modules, elementary, etc.) + objects_by_type: ObjectsByType From 3ebd570bd538732437ee83c2fe9ac97aef6a03db Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 16 Aug 2023 13:01:21 -0400 Subject: [PATCH 144/855] consistently use Literal annotation from typing_extensions This is our standard annotation policy, and makes mypy safe under python 3.7 --- mesonbuild/dependencies/pkgconfig.py | 4 +++- mesonbuild/utils/universal.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index cfe9cbb7c9c1..e8f349ec469d 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -26,6 +26,8 @@ import typing as T if T.TYPE_CHECKING: + from typing_extensions import Literal + from ..environment import Environment from ..mesonlib import MachineChoice from ..utils.core import EnvironOrDict @@ -78,7 +80,7 @@ class PkgConfigCLI(PkgConfigInterface): # The class's copy of the pkg-config path. Avoids having to search for it # multiple times in the same Meson invocation. - class_pkgbin: PerMachine[T.Union[None, T.Literal[False], ExternalProgram]] = PerMachine(None, None) + class_pkgbin: PerMachine[T.Union[None, Literal[False], ExternalProgram]] = PerMachine(None, None) # We cache all pkg-config subprocess invocations to avoid redundant calls pkgbin_cache: T.Dict[ T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]], diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 73d4523aef92..c0fa15fa844f 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1361,7 +1361,7 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', ''' -def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: T.Literal['c', 'nasm']) -> None: +def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: Literal['c', 'nasm']) -> None: if output_format == 'c': prelude = CONF_C_PRELUDE prefix = '#' From 1ed619d1965e0fa4aa6dadae88843e923ff0d198 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 16 Aug 2023 13:03:44 -0400 Subject: [PATCH 145/855] run_mypy: add option to run once for each supported version of python This allows verifying that meson is type-safe under older versions of Python, which it currently is. Different versions of Python sometimes have different supported types for an API. Verify this in CI. (We flush output to ensure CI prints lines in the right order.) --- .github/workflows/lint.yml | 4 +++- run_mypy.py | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index dea20d4c6678..2c8d3e19b7af 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -47,4 +47,6 @@ jobs: with: python-version: '3.x' - run: python -m pip install mypy types-PyYAML - - run: python run_mypy.py + - run: python run_mypy.py --allver + env: + PYTHONUNBUFFERED: 1 diff --git a/run_mypy.py b/run_mypy.py index 15dd5a628195..cf0e0e3de253 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -104,6 +104,7 @@ def main() -> int: parser.add_argument('-q', '--quiet', action='store_true', help='do not print informational messages') parser.add_argument('-p', '--pretty', action='store_true', help='pretty print mypy errors') parser.add_argument('-C', '--clear', action='store_true', help='clear the terminal before running mypy') + parser.add_argument('--allver', action='store_true', help='Check all supported versions of python') opts, args = parser.parse_known_args() if opts.pretty: @@ -129,8 +130,15 @@ def main() -> int: command = [opts.mypy] if opts.mypy else [sys.executable, '-m', 'mypy'] if not opts.quiet: print('Running mypy (this can take some time) ...') - p = subprocess.run(command + args + to_check, cwd=root) - return p.returncode + retcode = subprocess.run(command + args + to_check, cwd=root).returncode + if opts.allver and retcode == 0: + for minor in range(7, sys.version_info[1]): + if not opts.quiet: + print(f'Checking mypy with python version: 3.{minor}') + p = subprocess.run(command + args + to_check + [f'--python-version=3.{minor}'], cwd=root) + if p.returncode != 0: + retcode = p.returncode + return retcode else: if not opts.quiet: print('nothing to do...') From 253df6f9f821a3052b56673d5427aca9dfe41eba Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 16 Aug 2023 14:27:16 -0400 Subject: [PATCH 146/855] CI: make linters emit colored output Github Actions supports this fine, but is misdetected by flake8/mypy. Even though pylint defaults to text instead of colorized, we might as well do the right thing here though. --- .github/workflows/lint.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2c8d3e19b7af..547a520cc3f9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,7 +27,7 @@ jobs: with: python-version: '3.x' - run: python -m pip install pylint - - run: pylint mesonbuild + - run: pylint --output-format colorized mesonbuild flake8: runs-on: ubuntu-latest @@ -37,7 +37,7 @@ jobs: with: python-version: '3.x' - run: python -m pip install flake8 - - run: flake8 mesonbuild/ + - run: flake8 --color always mesonbuild/ mypy: runs-on: ubuntu-latest @@ -50,3 +50,5 @@ jobs: - run: python run_mypy.py --allver env: PYTHONUNBUFFERED: 1 + TERM: xterm-color + MYPY_FORCE_COLOR: 1 From bde690b06e930020a0ec6ccaea7a76babf77dff5 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 1 May 2023 20:44:23 +0200 Subject: [PATCH 147/855] compilers: fix checks handling of internal dependencies The include directories were not passed to the compiler. --- mesonbuild/compilers/mixins/clike.py | 4 ++++ .../include/test_262_header.h | 1 + .../262 internal dependency includes in checks/meson.build | 7 +++++++ 3 files changed, 12 insertions(+) create mode 100644 test cases/common/262 internal dependency includes in checks/include/test_262_header.h create mode 100644 test cases/common/262 internal dependency includes in checks/meson.build diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index f333357e2312..4999d6054a63 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -450,6 +450,10 @@ def build_wrapper_args(self, env: 'Environment', for d in dependencies: # Add compile flags needed by dependencies cargs += d.get_compile_args() + system_incdir = d.get_include_type() == 'system' + for i in d.get_include_dirs(): + for idir in i.to_string_list(env.get_source_dir(), env.get_build_dir()): + cargs.extend(self.get_include_args(idir, system_incdir)) if mode is CompileCheckMode.LINK: # Add link flags needed to find dependencies largs += d.get_link_args() diff --git a/test cases/common/262 internal dependency includes in checks/include/test_262_header.h b/test cases/common/262 internal dependency includes in checks/include/test_262_header.h new file mode 100644 index 000000000000..5a2ca62ad296 --- /dev/null +++ b/test cases/common/262 internal dependency includes in checks/include/test_262_header.h @@ -0,0 +1 @@ +int foo(void); diff --git a/test cases/common/262 internal dependency includes in checks/meson.build b/test cases/common/262 internal dependency includes in checks/meson.build new file mode 100644 index 000000000000..c8b527758bff --- /dev/null +++ b/test cases/common/262 internal dependency includes in checks/meson.build @@ -0,0 +1,7 @@ +project('test 262', 'c') + +cc = meson.get_compiler('c') + +internal_dep = declare_dependency(include_directories: 'include') + +assert(cc.has_header_symbol('test_262_header.h', 'foo', dependencies: internal_dep)) From 18b96cd0692255b30f8f0597cbf4af89d142a93d Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 6 Aug 2023 14:35:25 -0400 Subject: [PATCH 148/855] machine file: Add @GLOBAL_SOURCE_ROOT@ and @DIRNAME@ --- docs/markdown/Machine-files.md | 12 ++++++++++++ .../snippets/machine_file_source_dir.md | 13 +++++++++++++ mesonbuild/coredata.py | 19 ++++++++++++------- mesonbuild/environment.py | 6 +++--- run_project_tests.py | 8 ++++---- unittests/allplatformstests.py | 8 +++++++- 6 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 docs/markdown/snippets/machine_file_source_dir.md diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index c30076919f5e..a3e876d23f2d 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -128,6 +128,18 @@ b = a + 'World' a = 'Hello' ``` +*Since 1.3.0* Some tokens are replaced in the machine file before parsing it: +- `@GLOBAL_SOURCE_ROOT@`: the absolute path to the project's source tree +- `@DIRNAME@`: the absolute path to the machine file's parent directory. + +It can be used, for example, to have paths relative to the source directory, or +relative to toolchain's installation directory. +```ini +[binaries] +c = '@DIRNAME@/toolchain/gcc' +exe_wrapper = '@GLOBAL_SOURCE_ROOT@' / 'build-aux' / 'my-exe-wrapper.sh' +``` + ### Binaries The binaries section contains a list of binaries. These can be used diff --git a/docs/markdown/snippets/machine_file_source_dir.md b/docs/markdown/snippets/machine_file_source_dir.md new file mode 100644 index 000000000000..5af344e40ca9 --- /dev/null +++ b/docs/markdown/snippets/machine_file_source_dir.md @@ -0,0 +1,13 @@ +## `@GLOBAL_SOURCE_ROOT@` and `@DIRNAME@` in machine files + +Some tokens are now replaced in the machine file before parsing it: +- `@GLOBAL_SOURCE_ROOT@`: the absolute path to the project's source tree +- `@DIRNAME@`: the absolute path to the machine file's parent directory. + +It can be used, for example, to have paths relative to the source directory, or +relative to toolchain's installation directory. +```ini +[binaries] +c = '@DIRNAME@/toolchain/gcc' +exe_wrapper = '@GLOBAL_SOURCE_ROOT@' / 'build-aux' / 'my-exe-wrapper.sh' +``` diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index bb84f72c162b..d59d9b8c5aca 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -964,15 +964,20 @@ def optionxform(self, optionstr: str) -> str: return optionstr class MachineFileParser(): - def __init__(self, filenames: T.List[str]) -> None: + def __init__(self, filenames: T.List[str], sourcedir: str) -> None: self.parser = CmdLineFileParser() self.constants: T.Dict[str, T.Union[str, bool, int, T.List[str]]] = {'True': True, 'False': False} self.sections: T.Dict[str, T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = {} - try: - self.parser.read(filenames) - except configparser.Error as e: - raise EnvironmentException(f'Malformed cross or native file: {e}') + for fname in filenames: + with open(fname, encoding='utf-8') as f: + content = f.read() + content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir) + content = content.replace('@DIRNAME@', os.path.dirname(fname)) + try: + self.parser.read_string(content, fname) + except configparser.Error as e: + raise EnvironmentException(f'Malformed machine file: {e}') # Parse [constants] first so they can be used in other sections if self.parser.has_section('constants'): @@ -1028,8 +1033,8 @@ def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, return os.path.join(l, r) raise EnvironmentException('Unsupported node type') -def parse_machine_files(filenames: T.List[str]): - parser = MachineFileParser(filenames) +def parse_machine_files(filenames: T.List[str], sourcedir: str): + parser = MachineFileParser(filenames, sourcedir) return parser.sections def get_cmd_line_file(build_dir: str) -> str: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index ab6f56ca23a0..36106e4f68e5 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -477,7 +477,7 @@ class Environment: log_dir = 'meson-logs' info_dir = 'meson-info' - def __init__(self, source_dir: T.Optional[str], build_dir: T.Optional[str], options: 'argparse.Namespace') -> None: + def __init__(self, source_dir: str, build_dir: str, options: 'argparse.Namespace') -> None: self.source_dir = source_dir self.build_dir = build_dir # Do not try to create build directories when build_dir is none. @@ -550,7 +550,7 @@ def __init__(self, source_dir: T.Optional[str], build_dir: T.Optional[str], opti ## Read in native file(s) to override build machine configuration if self.coredata.config_files is not None: - config = coredata.parse_machine_files(self.coredata.config_files) + config = coredata.parse_machine_files(self.coredata.config_files, self.source_dir) binaries.build = BinaryTable(config.get('binaries', {})) properties.build = Properties(config.get('properties', {})) cmakevars.build = CMakeVariables(config.get('cmake', {})) @@ -561,7 +561,7 @@ def __init__(self, source_dir: T.Optional[str], build_dir: T.Optional[str], opti ## Read in cross file(s) to override host machine configuration if self.coredata.cross_files: - config = coredata.parse_machine_files(self.coredata.cross_files) + config = coredata.parse_machine_files(self.coredata.cross_files, self.source_dir) properties.host = Properties(config.get('properties', {})) binaries.host = BinaryTable(config.get('binaries', {})) cmakevars.host = CMakeVariables(config.get('cmake', {})) diff --git a/run_project_tests.py b/run_project_tests.py index acfa284d79ab..f279332610d6 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -793,7 +793,7 @@ def _skip_keys(test_def: T.Dict) -> T.Tuple[bool, bool]: # Test is expected to skip if os matches if 'skip_on_os' in test_def: - mesonenv = environment.Environment(None, None, get_fake_options('/')) + mesonenv = environment.Environment('', '', get_fake_options('/')) for skip_os in test_def['skip_on_os']: if skip_os.startswith('!'): if mesonenv.machines.host.system != skip_os[1:]: @@ -966,7 +966,7 @@ def have_d_compiler() -> bool: def have_objc_compiler(use_tmp: bool) -> bool: with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: - env = environment.Environment(None, build_dir, get_fake_options('/')) + env = environment.Environment('', build_dir, get_fake_options('/')) try: objc_comp = detect_objc_compiler(env, MachineChoice.HOST) except mesonlib.MesonException: @@ -982,7 +982,7 @@ def have_objc_compiler(use_tmp: bool) -> bool: def have_objcpp_compiler(use_tmp: bool) -> bool: with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: - env = environment.Environment(None, build_dir, get_fake_options('/')) + env = environment.Environment('', build_dir, get_fake_options('/')) try: objcpp_comp = detect_objcpp_compiler(env, MachineChoice.HOST) except mesonlib.MesonException: @@ -1458,7 +1458,7 @@ def detect_system_compiler(options: 'CompilerArgumentType') -> None: if options.native_file: fake_opts.native_file = [options.native_file] - env = environment.Environment(None, None, fake_opts) + env = environment.Environment('', '', fake_opts) print_compilers(env, MachineChoice.HOST) if options.cross_file: diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 819cc2ee79a6..b5252f776d64 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -3982,17 +3982,23 @@ def test_cross_file_constants(self): [properties] c_args = common_flags + ['-DSOMETHING'] cpp_args = c_args + ['-DSOMETHING_ELSE'] + rel_to_src = '@GLOBAL_SOURCE_ROOT@' / 'tool' + rel_to_file = '@DIRNAME@' / 'tool' + no_escaping = '@@DIRNAME@@' / 'tool' [binaries] c = toolchain / compiler ''')) - values = mesonbuild.coredata.parse_machine_files([crossfile1, crossfile2]) + values = mesonbuild.coredata.parse_machine_files([crossfile1, crossfile2], self.builddir) self.assertEqual(values['binaries']['c'], '/toolchain/gcc') self.assertEqual(values['properties']['c_args'], ['--sysroot=/toolchain/sysroot', '-DSOMETHING']) self.assertEqual(values['properties']['cpp_args'], ['--sysroot=/toolchain/sysroot', '-DSOMETHING', '-DSOMETHING_ELSE']) + self.assertEqual(values['properties']['rel_to_src'], os.path.join(self.builddir, 'tool')) + self.assertEqual(values['properties']['rel_to_file'], os.path.join(os.path.dirname(crossfile2), 'tool')) + self.assertEqual(values['properties']['no_escaping'], os.path.join(f'@{os.path.dirname(crossfile2)}@', 'tool')) @skipIf(is_windows(), 'Directory cleanup fails for some reason') def test_wrap_git(self): From 078dc2ca101f3fea115471d1a488c72fbd80c065 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Tue, 22 Aug 2023 18:34:02 +0200 Subject: [PATCH 149/855] Fix completely broken support for `static: true` with dependency('cuda') --- mesonbuild/dependencies/cuda.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index e16808b6a5c8..45df11b41560 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -45,8 +45,16 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No super().__init__('cuda', environment, kwargs, language=language) self.lib_modules: T.Dict[str, T.List[str]] = {} self.requested_modules = self.get_requested(kwargs) - if 'cudart' not in self.requested_modules: - self.requested_modules = ['cudart'] + self.requested_modules + if not any(runtime in self.requested_modules for runtime in ['cudart', 'cudart_static']): + req_modules = ['cudart'] + if kwargs.get('static', False): + req_modules = ['cudart_static'] + machine = self.env.machines[self.for_machine] + if machine.is_linux(): + # extracted by running + # nvcc -v foo.o + req_modules += ['rt', 'pthread', 'dl'] + self.requested_modules = req_modules + self.requested_modules (self.cuda_path, self.version, self.is_found) = self._detect_cuda_path_and_version() if not self.is_found: From 10e8995fc8394c71e5def6d055f542c5f80ca06c Mon Sep 17 00:00:00 2001 From: David Seifert Date: Tue, 22 Aug 2023 18:34:03 +0200 Subject: [PATCH 150/855] Use `cudart_static` by default in dependency('cuda') * Without this, using nvcc as the sole driver vs dependency('cuda') and host compiler driver yields differently linked binaries. --- mesonbuild/dependencies/cuda.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index 45df11b41560..aaed6b32c9f3 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -46,8 +46,10 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No self.lib_modules: T.Dict[str, T.List[str]] = {} self.requested_modules = self.get_requested(kwargs) if not any(runtime in self.requested_modules for runtime in ['cudart', 'cudart_static']): + # By default, we prefer to link the static CUDA runtime, since this is what nvcc also does by default: + # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#cudart-none-shared-static-cudart req_modules = ['cudart'] - if kwargs.get('static', False): + if kwargs.get('static', True): req_modules = ['cudart_static'] machine = self.env.machines[self.for_machine] if machine.is_linux(): From 6f87215f1f7c104de2f8720e3c0926bcffdc7232 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 19 Aug 2023 20:40:21 -0400 Subject: [PATCH 151/855] build: Simplify import_filename handling This removes deadcode, vs_import_filename and gcc_import_filename were not needed. --- mesonbuild/build.py | 56 ++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 1463e51e3586..d064fff0b213 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1950,10 +1950,6 @@ def post_init(self) -> None: # The import library this target will generate self.import_filename = None - # The import library that Visual Studio would generate (and accept) - self.vs_import_filename = None - # The import library that GCC would generate (and prefer) - self.gcc_import_filename = None # The debugging information file this target will generate self.debug_filename = None @@ -1963,12 +1959,10 @@ def post_init(self) -> None: if isinstance(self.implib, str): implib_basename = self.implib if machine.is_windows() or machine.is_cygwin(): - self.vs_import_filename = f'{implib_basename}.lib' - self.gcc_import_filename = f'lib{implib_basename}.a' if self.get_using_msvc(): - self.import_filename = self.vs_import_filename + self.import_filename = f'{implib_basename}.lib' else: - self.import_filename = self.gcc_import_filename + self.import_filename = f'lib{implib_basename}.a' create_debug_file = ( machine.is_windows() @@ -1997,11 +1991,6 @@ def get_import_filename(self) -> T.Optional[str]: """ return self.import_filename - def get_import_filenameslist(self): - if self.import_filename: - return [self.vs_import_filename, self.gcc_import_filename] - return [] - def get_debug_filename(self) -> T.Optional[str]: """ The name of debuginfo file that will be created by the compiler @@ -2083,6 +2072,9 @@ def post_init(self) -> None: # libfoo.a. However, we cannot use foo.lib because that's the same as # the import library. Using libfoo.a is ok because people using MSVC # always pass the library filename while linking anyway. + # + # See our FAQ for more detailed rationale: + # https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa if not hasattr(self, 'prefix'): self.prefix = 'lib' if not hasattr(self, 'suffix'): @@ -2145,10 +2137,6 @@ def __init__( self.vs_module_defs = None # The import library this target will generate self.import_filename = None - # The import library that Visual Studio would generate (and accept) - self.vs_import_filename = None - # The import library that GCC would generate (and prefer) - self.gcc_import_filename = None # The debugging information file this target will generate self.debug_filename = None # Use by the pkgconfig module @@ -2203,21 +2191,16 @@ def determine_filenames(self): The template is needed while creating aliases (self.get_aliases), which are needed while generating .so shared libraries for Linux. - Besides this, there's also the import library name, which is only used - on Windows since on that platform the linker uses a separate library - called the "import library" during linking instead of the shared - library (DLL). The toolchain will output an import library in one of - two formats: GCC or Visual Studio. - - When we're building with Visual Studio, the import library that will be - generated by the toolchain is self.vs_import_filename, and with - MinGW/GCC, it's self.gcc_import_filename. self.import_filename will - always contain the import library name this target will generate. + Besides this, there's also the import library name (self.import_filename), + which is only used on Windows since on that platform the linker uses a + separate library called the "import library" during linking instead of + the shared library (DLL). """ prefix = '' suffix = '' create_debug_file = False self.filename_tpl = self.basic_filename_tpl + import_filename_tpl = None # NOTE: manual prefix/suffix override is currently only tested for C/C++ # C# and Mono if 'cs' in self.compilers: @@ -2230,20 +2213,18 @@ def determine_filenames(self): # For all other targets/platforms import_filename stays None elif self.environment.machines[self.for_machine].is_windows(): suffix = 'dll' - self.vs_import_filename = '{}{}.lib'.format(self.prefix if self.prefix is not None else '', self.name) - self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) if self.uses_rust(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.dll.lib - self.import_filename = f'{self.name}.dll.lib' + import_filename_tpl = '{0.prefix}{0.name}.dll.lib' # .pdb file is only created when debug symbols are enabled create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) elif self.get_using_msvc(): # Shared library is of the form foo.dll prefix = '' # Import library is called foo.lib - self.import_filename = self.vs_import_filename + import_filename_tpl = '{0.prefix}{0.name}.lib' # .pdb file is only created when debug symbols are enabled create_debug_file = self.environment.coredata.get_option(OptionKey("debug")) # Assume GCC-compatible naming @@ -2251,7 +2232,7 @@ def determine_filenames(self): # Shared library is of the form libfoo.dll prefix = 'lib' # Import library is called libfoo.dll.a - self.import_filename = self.gcc_import_filename + import_filename_tpl = '{0.prefix}{0.name}.dll.a' # Shared library has the soversion if it is defined if self.soversion: self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' @@ -2259,12 +2240,12 @@ def determine_filenames(self): self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' elif self.environment.machines[self.for_machine].is_cygwin(): suffix = 'dll' - self.gcc_import_filename = '{}{}.dll.a'.format(self.prefix if self.prefix is not None else 'lib', self.name) # Shared library is of the form cygfoo.dll # (ld --dll-search-prefix=cyg is the default) prefix = 'cyg' # Import library is called libfoo.dll.a - self.import_filename = self.gcc_import_filename + import_prefix = self.prefix if self.prefix is not None else 'lib' + import_filename_tpl = import_prefix + '{0.name}.dll.a' if self.soversion: self.filename_tpl = '{0.prefix}{0.name}-{0.soversion}.{0.suffix}' else: @@ -2301,6 +2282,8 @@ def determine_filenames(self): if self.suffix is None: self.suffix = suffix self.filename = self.filename_tpl.format(self) + if import_filename_tpl: + self.import_filename = import_filename_tpl.format(self) # There may have been more outputs added by the time we get here, so # only replace the first entry self.outputs[0] = self.filename @@ -2370,11 +2353,6 @@ def get_debug_filename(self) -> T.Optional[str]: """ return self.debug_filename - def get_import_filenameslist(self): - if self.import_filename: - return [self.vs_import_filename, self.gcc_import_filename] - return [] - def get_all_link_deps(self): return [self] + self.get_transitive_link_deps() From f720105e242111f4b68c0cb2aa77a4301a2fd10f Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 24 May 2023 09:39:01 -0400 Subject: [PATCH 152/855] find_program: Fallback if version mismatch Fixes: #11797 --- mesonbuild/interpreter/interpreter.py | 70 +++++++++++-------- mesonbuild/modules/__init__.py | 3 +- .../common/182 find override/meson.build | 6 ++ .../common/182 find override/prog-version.py | 3 + .../182 find override/subprojects/sub2.wrap | 5 ++ .../subprojects/sub2/meson.build | 4 ++ .../subprojects/sub2/prog-version.py | 3 + 7 files changed, 65 insertions(+), 29 deletions(-) create mode 100755 test cases/common/182 find override/prog-version.py create mode 100644 test cases/common/182 find override/subprojects/sub2.wrap create mode 100644 test cases/common/182 find override/subprojects/sub2/meson.build create mode 100755 test cases/common/182 find override/subprojects/sub2/prog-version.py diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 7bba4fa69a58..4751af9e81a4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -131,6 +131,8 @@ BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources] + ProgramVersionFunc = T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str] + def _project_version_validator(value: T.Union[T.List, str, mesonlib.File, None]) -> T.Optional[str]: if isinstance(value, list): @@ -1621,46 +1623,23 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString], required: bool = True, silent: bool = True, wanted: T.Union[str, T.List[str]] = '', search_dirs: T.Optional[T.List[str]] = None, - version_func: T.Optional[T.Callable[[T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']], str]] = None + version_func: T.Optional[ProgramVersionFunc] = None ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']: args = mesonlib.listify(args) extra_info: T.List[mlog.TV_Loggable] = [] - progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, extra_info) - if progobj is None: + progobj = self.program_lookup(args, for_machine, default_options, required, search_dirs, wanted, version_func, extra_info) + if progobj is None or not self.check_program_version(progobj, wanted, version_func, extra_info): progobj = self.notfound_program(args) if isinstance(progobj, ExternalProgram) and not progobj.found(): if not silent: - mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO')) + mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info) if required: m = 'Program {!r} not found or not executable' raise InterpreterException(m.format(progobj.get_name())) return progobj - if wanted: - if version_func: - version = version_func(progobj) - elif isinstance(progobj, build.Executable): - if progobj.subproject: - interp = self.subprojects[progobj.subproject].held_object - else: - interp = self - assert isinstance(interp, Interpreter) - version = interp.project_version - else: - version = progobj.get_version(self) - is_found, not_found, _ = mesonlib.version_compare_many(version, wanted) - if not is_found: - mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.red('NO'), - 'found', mlog.normal_cyan(version), 'but need:', - mlog.bold(', '.join([f"'{e}'" for e in not_found])), *extra_info) - if required: - m = 'Invalid version of program, need {!r} {!r} found {!r}.' - raise InterpreterException(m.format(progobj.name, not_found, version)) - return self.notfound_program(args) - extra_info.insert(0, mlog.normal_cyan(version)) - # Only store successful lookups self.store_name_lookups(args) if not silent: @@ -1671,7 +1650,11 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString], def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice, default_options: T.Optional[T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]]], - required: bool, search_dirs: T.List[str], extra_info: T.List[mlog.TV_Loggable] + required: bool, + search_dirs: T.List[str], + wanted: T.Union[str, T.List[str]], + version_func: T.Optional[ProgramVersionFunc], + extra_info: T.List[mlog.TV_Loggable] ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: progobj = self.program_from_overrides(args, extra_info) if progobj: @@ -1694,11 +1677,42 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi if progobj is None and args[0].endswith('python3'): prog = ExternalProgram('python3', mesonlib.python_command, silent=True) progobj = prog if prog.found() else None + + if progobj and not self.check_program_version(progobj, wanted, version_func, extra_info): + progobj = None + if progobj is None and fallback and required: + progobj = self.notfound_program(args) + mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info) + extra_info.clear() progobj = self.find_program_fallback(fallback, args, default_options, required, extra_info) return progobj + def check_program_version(self, progobj: T.Union[ExternalProgram, build.Executable, OverrideProgram], + wanted: T.Union[str, T.List[str]], + version_func: T.Optional[ProgramVersionFunc], + extra_info: T.List[mlog.TV_Loggable]) -> bool: + if wanted: + if version_func: + version = version_func(progobj) + elif isinstance(progobj, build.Executable): + if progobj.subproject: + interp = self.subprojects[progobj.subproject].held_object + else: + interp = self + assert isinstance(interp, Interpreter) + version = interp.project_version + else: + version = progobj.get_version(self) + is_found, not_found, _ = mesonlib.version_compare_many(version, wanted) + if not is_found: + extra_info[:0] = ['found', mlog.normal_cyan(version), 'but need:', + mlog.bold(', '.join([f"'{e}'" for e in not_found]))] + return False + extra_info.insert(0, mlog.normal_cyan(version)) + return True + def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], default_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]], required: bool, extra_info: T.List[mlog.TV_Loggable] diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index b46b3007708c..57c169d0bd50 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -26,6 +26,7 @@ if T.TYPE_CHECKING: from ..interpreter import Interpreter + from ..interpreter.interpreter import ProgramVersionFunc from ..interpreter.interpreterobjects import MachineHolder from ..interpreterbase import TYPE_var, TYPE_kwargs from ..programs import OverrideProgram @@ -86,7 +87,7 @@ def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDi def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]], required: bool = True, - version_func: T.Optional[T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str]] = None, + version_func: T.Optional[ProgramVersionFunc] = None, wanted: T.Optional[str] = None, silent: bool = False, for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.Executable, OverrideProgram]: if not isinstance(prog, list): diff --git a/test cases/common/182 find override/meson.build b/test cases/common/182 find override/meson.build index f21700140e02..edb16873f5b2 100644 --- a/test cases/common/182 find override/meson.build +++ b/test cases/common/182 find override/meson.build @@ -23,3 +23,9 @@ six_prog = find_program('six_meson_exe') assert(six_prog.found()) assert(six_prog.full_path() != '') assert(six_prog.full_path() == six_prog.path()) + +# We have prog-version.py in current directory, but it's version 1.0. +# This needs to use fallback for "prog-version" name which will be version 2.0. +prog = find_program('prog-version.py', 'prog-version', version: '>= 2.0') +assert(prog.found()) +assert(prog.version() == '2.0') diff --git a/test cases/common/182 find override/prog-version.py b/test cases/common/182 find override/prog-version.py new file mode 100755 index 000000000000..c00dd99df778 --- /dev/null +++ b/test cases/common/182 find override/prog-version.py @@ -0,0 +1,3 @@ +#! /usr/bin/env python3 + +print('1.0') diff --git a/test cases/common/182 find override/subprojects/sub2.wrap b/test cases/common/182 find override/subprojects/sub2.wrap new file mode 100644 index 000000000000..035629fa8641 --- /dev/null +++ b/test cases/common/182 find override/subprojects/sub2.wrap @@ -0,0 +1,5 @@ +[wrap-file] +directory = sub2 + +[provide] +program_names = prog-version diff --git a/test cases/common/182 find override/subprojects/sub2/meson.build b/test cases/common/182 find override/subprojects/sub2/meson.build new file mode 100644 index 000000000000..f542073c5e6c --- /dev/null +++ b/test cases/common/182 find override/subprojects/sub2/meson.build @@ -0,0 +1,4 @@ +project('sub2') + +prog = find_program('prog-version.py') +meson.override_find_program('prog-version', prog) diff --git a/test cases/common/182 find override/subprojects/sub2/prog-version.py b/test cases/common/182 find override/subprojects/sub2/prog-version.py new file mode 100755 index 000000000000..78401bb201c3 --- /dev/null +++ b/test cases/common/182 find override/subprojects/sub2/prog-version.py @@ -0,0 +1,3 @@ +#! /usr/bin/env python3 + +print('2.0') From b4b1395ef5d2a625389902797816109c2e8340e3 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 23 Aug 2023 09:09:06 -0400 Subject: [PATCH 153/855] Suggest using --reconfigure only when not already using it --- mesonbuild/coredata.py | 10 +++++----- mesonbuild/environment.py | 4 ++-- mesonbuild/utils/universal.py | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index d59d9b8c5aca..b0dad1395e01 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -89,10 +89,10 @@ def get_genvs_default_buildtype_list() -> list[str]: class MesonVersionMismatchException(MesonException): '''Build directory generated with Meson version is incompatible with current version''' - def __init__(self, old_version: str, current_version: str) -> None: + def __init__(self, old_version: str, current_version: str, extra_msg: str = '') -> None: super().__init__(f'Build directory has been generated with Meson version {old_version}, ' - f'which is incompatible with the current version {current_version}. ' - f'Consider reconfiguring the directory with meson setup --reconfigure.') + f'which is incompatible with the current version {current_version}.' + + extra_msg) self.old_version = old_version self.current_version = current_version @@ -1099,9 +1099,9 @@ def major_versions_differ(v1: str, v2: str) -> bool: # Major version differ, or one is development version but not the other. return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor) -def load(build_dir: str) -> CoreData: +def load(build_dir: str, suggest_reconfigure: bool = True) -> CoreData: filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') - return pickle_load(filename, 'Coredata', CoreData) + return pickle_load(filename, 'Coredata', CoreData, suggest_reconfigure) def save(obj: CoreData, build_dir: str) -> str: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 36106e4f68e5..75909318dbbe 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -490,7 +490,7 @@ def __init__(self, source_dir: str, build_dir: str, options: 'argparse.Namespace os.makedirs(self.log_dir, exist_ok=True) os.makedirs(self.info_dir, exist_ok=True) try: - self.coredata: coredata.CoreData = coredata.load(self.get_build_dir()) + self.coredata: coredata.CoreData = coredata.load(self.get_build_dir(), suggest_reconfigure=False) self.first_invocation = False except FileNotFoundError: self.create_new_coredata(options) @@ -508,7 +508,7 @@ def __init__(self, source_dir: str, build_dir: str, options: 'argparse.Namespace coredata.read_cmd_line_file(self.build_dir, options) self.create_new_coredata(options) else: - raise e + raise MesonException(f'{str(e)} Try regenerating using "meson setup --wipe".') else: # Just create a fresh coredata in this case self.scratch_dir = '' diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index c0fa15fa844f..a39825faf49a 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -2411,22 +2411,22 @@ def is_base(self) -> bool: return self.type is OptionType.BASE -def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL]) -> _PL: - load_fail_msg = f'{object_name} file {filename!r} is corrupted. Try with a fresh build tree.' +def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL], suggest_reconfigure: bool = True) -> _PL: + load_fail_msg = f'{object_name} file {filename!r} is corrupted.' + extra_msg = ' Consider reconfiguring the directory with "meson setup --reconfigure".' if suggest_reconfigure else '' try: with open(filename, 'rb') as f: obj = pickle.load(f) except (pickle.UnpicklingError, EOFError): - raise MesonException(load_fail_msg) + raise MesonException(load_fail_msg + extra_msg) except (TypeError, ModuleNotFoundError, AttributeError): - build_dir = os.path.dirname(os.path.dirname(filename)) raise MesonException( f"{object_name} file {filename!r} references functions or classes that don't " "exist. This probably means that it was generated with an old " - "version of meson. Try running from the source directory " - f'meson setup {build_dir} --wipe') + "version of meson." + extra_msg) + if not isinstance(obj, object_type): - raise MesonException(load_fail_msg) + raise MesonException(load_fail_msg + extra_msg) # Because these Protocols are not available at runtime (and cannot be made # available at runtime until we drop support for Python < 3.8), we have to @@ -2440,7 +2440,7 @@ def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL]) -> _P from ..coredata import version as coredata_version from ..coredata import major_versions_differ, MesonVersionMismatchException if major_versions_differ(version, coredata_version): - raise MesonVersionMismatchException(version, coredata_version) + raise MesonVersionMismatchException(version, coredata_version, extra_msg) return obj From 1bb29b1b329ec056c61a54070024b6b003cf5ca4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 19 Jul 2023 15:21:36 +1000 Subject: [PATCH 154/855] minstall: move the "Installing foo to bar" message up Move this message up before we attempt to change anything in the file system (in this case creating the directory structure). If an error occurs it will thus occur immediately after the message, allowing us to debug what failed to install. --- mesonbuild/minstall.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index a9c561f770a3..0d397b23e306 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -403,13 +403,15 @@ def do_copyfile(self, from_file: str, to_file: str, append_to_log(self.lf, f'# Preserving old file {to_file}\n') self.preserved_file_count += 1 return False + self.log(f'Installing {from_file} to {outdir}') self.remove(to_file) - elif makedirs: - # Unpack tuple - dirmaker, outdir = makedirs - # Create dirs if needed - dirmaker.makedirs(outdir, exist_ok=True) - self.log(f'Installing {from_file} to {outdir}') + else: + self.log(f'Installing {from_file} to {outdir}') + if makedirs: + # Unpack tuple + dirmaker, outdir = makedirs + # Create dirs if needed + dirmaker.makedirs(outdir, exist_ok=True) if os.path.islink(from_file): if not os.path.exists(from_file): # Dangling symlink. Replicate as is. From e3a71a7b58ac559f8669ca6fa95617a537b47f98 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 30 Mar 2023 09:29:27 -0400 Subject: [PATCH 155/855] msetup: Update options when builddir is already configured `meson setup -Dfoo=bar builddir` command was returning success ignoring new option values. This now also update options. It is useful because it means `meson setup -Dfoo=bar builddir && ninja -C builddir` works regardless whether builddir already exists or not, and when done in a script, changing options in the script will automatically trigger a reconfigure if needed. This was already possible by always passing --reconfigure argument, but that triggers a reconfigure even when options did not change. --- docs/markdown/Commands.md | 11 ++++++++++ docs/markdown/snippets/msetup.md | 13 ++++++++++++ mesonbuild/mconf.py | 9 +++++--- mesonbuild/msetup.py | 34 +++++++++++++----------------- unittests/baseplatformtests.py | 7 ++++++ unittests/platformagnostictests.py | 7 ++++++ 6 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 docs/markdown/snippets/msetup.md diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index 75b22817dd57..efc316ce7fbb 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -244,6 +244,17 @@ Configures a build directory for the Meson project. was no COMMAND supplied). However, supplying the command is necessary to avoid clashes with future added commands, so "setup" should be used explicitly. +*Since 1.1.0* `--reconfigure` is allowed even if the build directory does not +already exist, that argument is ignored in that case. + +*Since 1.3.0* If the build directory already exists, options are updated with +their new value given on the command line (`-Dopt=value`). Unless `--reconfigure` +is also specified, this won't reconfigure immediately. This has the same behaviour +as `meson configure -Dopt=value`. + +*Since 1.3.0* It is possible to clear the cache and reconfigure in a single command +with `meson setup --clearcache --reconfigure `. + {{ setup_arguments.inc }} See [Meson introduction diff --git a/docs/markdown/snippets/msetup.md b/docs/markdown/snippets/msetup.md new file mode 100644 index 000000000000..f68313d67477 --- /dev/null +++ b/docs/markdown/snippets/msetup.md @@ -0,0 +1,13 @@ +## Update options with `meson setup -Dopt=value` + +If the build directory already exists, options are updated with their new value +given on the command line (`-Dopt=value`). Unless `--reconfigure` is also specified, +this won't reconfigure immediately. This has the same behaviour as +`meson configure -Dopt=value`. + +Previous Meson versions were simply a no-op. + +## Clear persistent cache with `meson setup --clearcache` + +Just like `meson configure --clearcache`, it is now possible to clear the cache +and reconfigure in a single command with `meson setup --clearcache --reconfigure `. diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index d4ecce8719bf..9f6c6856f5fc 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -301,9 +301,7 @@ def print_nondefault_buildtype_options(self) -> None: for m in mismatching: mlog.log(f'{m[0]:21}{m[1]:10}{m[2]:10}') -def run(options: argparse.Namespace) -> int: - coredata.parse_cmd_line_options(options) - builddir = os.path.abspath(os.path.realpath(options.builddir)) +def run_impl(options: argparse.Namespace, builddir: str) -> int: print_only = not options.cmd_line_options and not options.clearcache c = None try: @@ -334,3 +332,8 @@ def run(options: argparse.Namespace) -> int: # Pager quit before we wrote everything. pass return 0 + +def run(options: argparse.Namespace) -> int: + coredata.parse_cmd_line_options(options) + builddir = os.path.abspath(os.path.realpath(options.builddir)) + return run_impl(options, builddir) diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 73c9fb3cc25b..4ff60000ff06 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -55,15 +55,15 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: help='Wipe build directory and reconfigure using previous command line options. ' + 'Useful when build directory got corrupted, or when rebuilding with a ' + 'newer version of meson.') + parser.add_argument('--clearcache', action='store_true', default=False, + help='Clear cached state (e.g. found dependencies). Since 1.3.0.') parser.add_argument('builddir', nargs='?', default=None) parser.add_argument('sourcedir', nargs='?', default=None) class MesonApp: def __init__(self, options: argparse.Namespace) -> None: - (self.source_dir, self.build_dir) = self.validate_dirs(options.builddir, - options.sourcedir, - options.reconfigure, - options.wipe) + self.options = options + (self.source_dir, self.build_dir) = self.validate_dirs() if options.wipe: # Make a copy of the cmd line file to make sure we can always # restore that file if anything bad happens. For example if @@ -96,8 +96,6 @@ def __init__(self, options: argparse.Namespace) -> None: os.makedirs(os.path.dirname(f), exist_ok=True) shutil.move(b, f) - self.options = options - def has_build_file(self, dirname: str) -> bool: fname = os.path.join(dirname, environment.build_filename) return os.path.exists(fname) @@ -144,8 +142,8 @@ def add_vcs_ignore_files(self, build_dir: str) -> None: with open(os.path.join(build_dir, '.hgignore'), 'w', encoding='utf-8') as ofile: ofile.write(hg_ignore_file) - def validate_dirs(self, dir1: T.Optional[str], dir2: T.Optional[str], reconfigure: bool, wipe: bool) -> T.Tuple[str, str]: - (src_dir, build_dir) = self.validate_core_dirs(dir1, dir2) + def validate_dirs(self) -> T.Tuple[str, str]: + (src_dir, build_dir) = self.validate_core_dirs(self.options.builddir, self.options.sourcedir) if Path(build_dir) in Path(src_dir).parents: raise MesonException(f'Build directory {build_dir} cannot be a parent of source directory {src_dir}') if not os.listdir(build_dir): @@ -155,21 +153,17 @@ def validate_dirs(self, dir1: T.Optional[str], dir2: T.Optional[str], reconfigur has_valid_build = os.path.exists(os.path.join(priv_dir, 'coredata.dat')) has_partial_build = os.path.isdir(priv_dir) if has_valid_build: - if not reconfigure and not wipe: + if not self.options.reconfigure and not self.options.wipe: print('Directory already configured.\n\n' 'Just run your build command (e.g. ninja) and Meson will regenerate as necessary.\n' - 'If ninja fails, run "ninja reconfigure" or "meson setup --reconfigure"\n' - 'to force Meson to regenerate.\n\n' + 'Run "meson setup --reconfigure to force Meson to regenerate.\n\n' 'If build failures persist, run "meson setup --wipe" to rebuild from scratch\n' - 'using the same options as passed when configuring the build.\n' - 'To change option values, run "meson configure" instead.') - # FIXME: This returns success and ignores new option values from CLI. - # We should either make this a hard error, or update options and - # return success. - # Note that making this an error would not be backward compatible (and also isn't - # universally agreed on): https://github.com/mesonbuild/meson/pull/4249. + 'using the same options as passed when configuring the build.') + if self.options.cmd_line_options: + from . import mconf + raise SystemExit(mconf.run_impl(self.options, build_dir)) raise SystemExit(0) - elif not has_partial_build and wipe: + elif not has_partial_build and self.options.wipe: raise MesonException(f'Directory is not empty and does not contain a previous build:\n{build_dir}') return src_dir, build_dir @@ -179,6 +173,8 @@ def generate(self, capture: bool = False, vslite_ctx: T.Optional[dict] = None) - mlog.initialize(env.get_log_dir(), self.options.fatal_warnings) if self.options.profile: mlog.set_timestamp_start(time.monotonic()) + if self.options.clearcache: + env.coredata.clear_cache() with mesonlib.BuildDirLock(self.build_dir): return self._generate(env, capture, vslite_ctx) diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 03ab1c521a86..514f3b759b80 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -303,6 +303,13 @@ def setconf(self, arg, will_build=True): ensure_backend_detects_changes(self.backend) self._run(self.mconf_command + arg + [self.builddir]) + def getconf(self, optname: str): + opts = self.introspect('--buildoptions') + for x in opts: + if x.get('name') == optname: + return x.get('value') + self.fail(f'Option {optname} not found') + def wipe(self): windows_proof_rmtree(self.builddir) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index fd012939c408..efe3109d73dc 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -183,6 +183,13 @@ def test_validate_dirs(self): Path(self.builddir, 'dummy').touch() self.init(testdir, extra_args=['--reconfigure']) + # Setup a valid builddir should update options but not reconfigure + self.assertEqual(self.getconf('buildtype'), 'debug') + o = self.init(testdir, extra_args=['-Dbuildtype=release']) + self.assertIn('Directory already configured', o) + self.assertNotIn('The Meson build system', o) + self.assertEqual(self.getconf('buildtype'), 'release') + # Wipe of empty builddir should work self.new_builddir() self.init(testdir, extra_args=['--wipe']) From 237b4c0f4181ffb947f311f612dad05fd8b6a7b4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 27 Aug 2023 08:45:04 -0400 Subject: [PATCH 156/855] FAQ: MinGW UCRT are compatible with MSVC and also use libfoo.a Prior to Windows 10, libfoo.a were usually not usable with MSVC. This is not true any more since Autotools projects built with UCRT produce libfoo.a that are compatible with MSVC. This is another reason for using that naming convention in Meson. --- docs/markdown/FAQ.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/markdown/FAQ.md b/docs/markdown/FAQ.md index 8bcea204477b..ffc9e1718eb6 100644 --- a/docs/markdown/FAQ.md +++ b/docs/markdown/FAQ.md @@ -405,6 +405,9 @@ advantages: not care what the extension is](https://docs.microsoft.com/en-us/cpp/build/reference/link-input-files?view=vs-2019), so specifying `libfoo.a` instead of `foo.lib` does not change the workflow, and is an improvement since it's less ambiguous. +1. Projects built with the MinGW compiler are fully compatible with + MSVC as long as they use the same CRT (e.g. UCRT with MSYS2). + These projects also name their static libraries `libfoo.a`. If, for some reason, you really need your project to output static libraries of the form `foo.lib` when building with MSVC, you can set From 83d3bf85cf0d34a73bffc3c79f758f4ff3b13fbd Mon Sep 17 00:00:00 2001 From: Bruce Merry Date: Mon, 28 Aug 2023 14:16:40 +0200 Subject: [PATCH 157/855] Add CUDA id and flags to reference tables --- docs/markdown/Reference-tables.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 377b36286523..4a869ad83c82 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -30,6 +30,7 @@ These are return values of the `get_id` (Compiler family) and | msvc | Microsoft Visual Studio | msvc | | nagfor | The NAG Fortran compiler | | | nvidia_hpc| NVidia HPC SDK compilers | | +| nvcc | NVidia CUDA compiler | | | open64 | The Open64 Fortran Compiler | | | pathscale | The Pathscale Fortran compiler | | | pgi | Portland PGI C/C++/Fortran compilers | | @@ -208,6 +209,7 @@ to your build target. | C | c_args | c_link_args | | C++ | cpp_args | cpp_link_args | | C# | cs_args | cs_link_args | +| CUDA | cuda_args | cuda_link_args | | D | d_args | d_link_args | | Fortran | fortran_args | fortran_link_args | | Java | java_args | java_link_args | @@ -239,6 +241,7 @@ arguments](#language-arguments-parameter-names) instead. | ----- | ------- | | CFLAGS | Flags for the C compiler | | CXXFLAGS | Flags for the C++ compiler | +| CUFLAGS | Flags for the CUDA compiler | | OBJCFLAGS | Flags for the Objective C compiler | | FFLAGS | Flags for the Fortran compiler | | DFLAGS | Flags for the D compiler | From 4eb9c84cf97427a11af7ec928c849e4289862202 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 25 Aug 2023 13:08:17 -0400 Subject: [PATCH 158/855] include_directories: Always add both source and build dirs Compiler checks were not adding build dir side, which prevents using headers generated with configure_file(). --- mesonbuild/build.py | 5 ++--- mesonbuild/interpreter/compiler.py | 2 +- mesonbuild/mintro.py | 2 +- test cases/common/28 try compile/foo.h.in | 0 test cases/common/28 try compile/meson.build | 13 +++++++++++++ 5 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 test cases/common/28 try compile/foo.h.in diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d064fff0b213..8fed7853163e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -389,7 +389,7 @@ def get_incdirs(self) -> T.List[str]: def get_extra_build_dirs(self) -> T.List[str]: return self.extra_build_dirs - def to_string_list(self, sourcedir: str, builddir: T.Optional[str] = None) -> T.List[str]: + def to_string_list(self, sourcedir: str, builddir: str) -> T.List[str]: """Convert IncludeDirs object to a list of strings. :param sourcedir: The absolute source directory @@ -400,8 +400,7 @@ def to_string_list(self, sourcedir: str, builddir: T.Optional[str] = None) -> T. strlist: T.List[str] = [] for idir in self.incdirs: strlist.append(os.path.join(sourcedir, self.curdir, idir)) - if builddir: - strlist.append(os.path.join(builddir, self.curdir, idir)) + strlist.append(os.path.join(builddir, self.curdir, idir)) return strlist @dataclass(eq=False) diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 0e34f6c91da3..b85aa37ed872 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -257,7 +257,7 @@ def _determine_args(self, kwargs: BaseCompileKW, mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]: args: T.List[str] = [] for i in kwargs['include_directories']: - for idir in i.to_string_list(self.environment.get_source_dir()): + for idir in i.to_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()): args.extend(self.compiler.get_include_args(idir, False)) if not kwargs['no_builtin_args']: opts = self.environment.coredata.options diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index ab31ec90b492..039153532489 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -412,7 +412,7 @@ def _create_result(d: Dependency, varname: T.Optional[str] = None) -> T.Dict[str 'version': d.get_version(), 'compile_args': d.get_compile_args(), 'link_args': d.get_link_args(), - 'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.to_string_list(backend.source_dir)], + 'include_directories': [i for idirs in d.get_include_dirs() for i in idirs.to_string_list(backend.source_dir, backend.build_dir)], 'sources': [f for s in d.get_sources() for f in _src_to_str(s)], 'extra_files': [f for s in d.get_extra_files() for f in _src_to_str(s)], 'dependencies': [e.name for e in d.ext_deps], diff --git a/test cases/common/28 try compile/foo.h.in b/test cases/common/28 try compile/foo.h.in new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/common/28 try compile/meson.build b/test cases/common/28 try compile/meson.build index 83cd29e87f89..9f457c5fc534 100644 --- a/test cases/common/28 try compile/meson.build +++ b/test cases/common/28 try compile/meson.build @@ -12,9 +12,22 @@ warncode = '''#warning This is a warning int main(void) { return 0; } ''' +configure_file( + input: 'foo.h.in', + output: 'foo.h', + configuration: {}, +) + +header_code = '#include "foo.h"' + foreach lang : ['c', 'cpp'] compiler = meson.get_compiler(lang) + assert(not compiler.compiles(header_code, name: 'Should not include . by default')) + assert(compiler.compiles(header_code, name: 'Should include builddir', + include_directories: include_directories('.'), + )) + if compiler.compiles(code, name : 'code should succeed') == false error('Compiler ' + compiler.get_id() + ' is fail.') endif From 494bdbd3345d1c2d20cf2520249962bd32fc61e6 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 27 Aug 2023 11:02:09 -0400 Subject: [PATCH 159/855] gnome: Fix crash in gtkdoc and generate_gir in C++ projects gtkdoc() and generate_gir() methods assumes there is a C compiler, but pure C++ projects might not add it explicitly. Fixes: #12162 --- mesonbuild/modules/__init__.py | 2 ++ mesonbuild/modules/gnome.py | 6 ++++++ .../frameworks/36 gtkdoc cpp/foo-docs.xml | 16 ++++++++++++++++ test cases/frameworks/36 gtkdoc cpp/foo.cpp | 5 +++++ test cases/frameworks/36 gtkdoc cpp/foo.h | 1 + test cases/frameworks/36 gtkdoc cpp/meson.build | 13 +++++++++++++ test cases/frameworks/36 gtkdoc cpp/test.json | 17 +++++++++++++++++ test cases/frameworks/37 gir cpp/foo.cpp | 5 +++++ test cases/frameworks/37 gir cpp/foo.h | 1 + test cases/frameworks/37 gir cpp/meson.build | 16 ++++++++++++++++ test cases/frameworks/37 gir cpp/test.json | 3 +++ 11 files changed, 85 insertions(+) create mode 100644 test cases/frameworks/36 gtkdoc cpp/foo-docs.xml create mode 100644 test cases/frameworks/36 gtkdoc cpp/foo.cpp create mode 100644 test cases/frameworks/36 gtkdoc cpp/foo.h create mode 100644 test cases/frameworks/36 gtkdoc cpp/meson.build create mode 100644 test cases/frameworks/36 gtkdoc cpp/test.json create mode 100644 test cases/frameworks/37 gir cpp/foo.cpp create mode 100644 test cases/frameworks/37 gir cpp/foo.h create mode 100644 test cases/frameworks/37 gir cpp/meson.build create mode 100644 test cases/frameworks/37 gir cpp/test.json diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 57c169d0bd50..eef67a1c7431 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -167,6 +167,8 @@ def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T else: yield self._interpreter.build_incdir_object([d]) + def add_language(self, lang: str, for_machine: MachineChoice) -> None: + self._interpreter.add_languages([lang], True, for_machine) class ModuleObject(HoldableObject): """Base class for all objects returned by modules diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 6bd0436a6c01..039e122408bd 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1113,6 +1113,9 @@ def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]: ) def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[Executable, build.SharedLibrary, build.StaticLibrary]]], kwargs: 'GenerateGir') -> ModuleReturnValue: + # Ensure we have a C compiler even in C++ projects. + state.add_language('c', MachineChoice.HOST) + girtargets = [self._unwrap_gir_target(arg, state) for arg in args[0]] if len(girtargets) > 1 and any(isinstance(el, Executable) for el in girtargets): raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable') @@ -1430,6 +1433,9 @@ def gtkdoc(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GtkDoc') -> namespace = kwargs['namespace'] + # Ensure we have a C compiler even in C++ projects. + state.add_language('c', MachineChoice.HOST) + def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]: for f in files: if isinstance(f, mesonlib.File): diff --git a/test cases/frameworks/36 gtkdoc cpp/foo-docs.xml b/test cases/frameworks/36 gtkdoc cpp/foo-docs.xml new file mode 100644 index 000000000000..85c673c57b4b --- /dev/null +++ b/test cases/frameworks/36 gtkdoc cpp/foo-docs.xml @@ -0,0 +1,16 @@ + + + +]> + + + Foo Reference Manual + + + + GLib Core Application Support + + + diff --git a/test cases/frameworks/36 gtkdoc cpp/foo.cpp b/test cases/frameworks/36 gtkdoc cpp/foo.cpp new file mode 100644 index 000000000000..15fa269806a2 --- /dev/null +++ b/test cases/frameworks/36 gtkdoc cpp/foo.cpp @@ -0,0 +1,5 @@ +#include "foo.h" + +int foo_do_something(void) { + return 42; +} diff --git a/test cases/frameworks/36 gtkdoc cpp/foo.h b/test cases/frameworks/36 gtkdoc cpp/foo.h new file mode 100644 index 000000000000..cac03d3c1a70 --- /dev/null +++ b/test cases/frameworks/36 gtkdoc cpp/foo.h @@ -0,0 +1 @@ +int foo_do_something(void); diff --git a/test cases/frameworks/36 gtkdoc cpp/meson.build b/test cases/frameworks/36 gtkdoc cpp/meson.build new file mode 100644 index 000000000000..747eae546741 --- /dev/null +++ b/test cases/frameworks/36 gtkdoc cpp/meson.build @@ -0,0 +1,13 @@ +project('gnome module without C', 'cpp') + +gtkdoc = find_program('gtkdoc-scan', required: false) +if not gtkdoc.found() + error('MESON_SKIP_TEST gtkdoc not found.') +endif + +gnome = import('gnome') + +lib = library('foo++', 'foo.cpp') +gnome.gtkdoc('foo', + src_dir: '.', + main_xml : 'foo-docs.xml',) diff --git a/test cases/frameworks/36 gtkdoc cpp/test.json b/test cases/frameworks/36 gtkdoc cpp/test.json new file mode 100644 index 000000000000..b2d9bc88f6a0 --- /dev/null +++ b/test cases/frameworks/36 gtkdoc cpp/test.json @@ -0,0 +1,17 @@ +{ + "installed": [ + {"type": "file", "file": "usr/share/gtk-doc/html/foo/up-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/home.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/foo.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/foo-foo.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/style.css"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/index.html"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/foo.devhelp2"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/left.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/left-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/right-insensitive.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/up.png"}, + {"type": "file", "file": "usr/share/gtk-doc/html/foo/right.png"} + ], + "skip_on_jobname": ["azure", "msys2"] +} diff --git a/test cases/frameworks/37 gir cpp/foo.cpp b/test cases/frameworks/37 gir cpp/foo.cpp new file mode 100644 index 000000000000..15fa269806a2 --- /dev/null +++ b/test cases/frameworks/37 gir cpp/foo.cpp @@ -0,0 +1,5 @@ +#include "foo.h" + +int foo_do_something(void) { + return 42; +} diff --git a/test cases/frameworks/37 gir cpp/foo.h b/test cases/frameworks/37 gir cpp/foo.h new file mode 100644 index 000000000000..cac03d3c1a70 --- /dev/null +++ b/test cases/frameworks/37 gir cpp/foo.h @@ -0,0 +1 @@ +int foo_do_something(void); diff --git a/test cases/frameworks/37 gir cpp/meson.build b/test cases/frameworks/37 gir cpp/meson.build new file mode 100644 index 000000000000..c8bf4281250c --- /dev/null +++ b/test cases/frameworks/37 gir cpp/meson.build @@ -0,0 +1,16 @@ +project('gnome module without C', 'cpp') + +gi = dependency('gobject-introspection-1.0', required: false) +if not gi.found() + error('MESON_SKIP_TEST gobject-introspection not found.') +endif + +gnome = import('gnome') + +lib = library('foo++', 'foo.cpp') +gnome.generate_gir( + lib, + sources: ['foo.cpp', 'foo.h'], + namespace: 'foo', + nsversion: meson.project_version(), +) diff --git a/test cases/frameworks/37 gir cpp/test.json b/test cases/frameworks/37 gir cpp/test.json new file mode 100644 index 000000000000..a9d74fb8a9b0 --- /dev/null +++ b/test cases/frameworks/37 gir cpp/test.json @@ -0,0 +1,3 @@ +{ + "skip_on_jobname": ["azure", "macos", "msys2"] +} From 8758e1353e93782b38cbea93d6d4c0f84c0614da Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 30 Aug 2023 13:41:53 -0400 Subject: [PATCH 160/855] ci: Skip gir test on cygwin --- test cases/frameworks/37 gir cpp/meson.build | 6 ++++++ test cases/frameworks/37 gir cpp/test.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test cases/frameworks/37 gir cpp/meson.build b/test cases/frameworks/37 gir cpp/meson.build index c8bf4281250c..0d228b0fe610 100644 --- a/test cases/frameworks/37 gir cpp/meson.build +++ b/test cases/frameworks/37 gir cpp/meson.build @@ -5,6 +5,12 @@ if not gi.found() error('MESON_SKIP_TEST gobject-introspection not found.') endif +if host_machine.system() == 'cygwin' + # FIXME: g-ir-scanner seems broken on cygwin: + # ERROR: can't resolve libraries to shared libraries: foo++ + error('MESON_SKIP_TEST g-ir-scanner is broken on cygwin.') +endif + gnome = import('gnome') lib = library('foo++', 'foo.cpp') diff --git a/test cases/frameworks/37 gir cpp/test.json b/test cases/frameworks/37 gir cpp/test.json index a9d74fb8a9b0..3641d75ca9e8 100644 --- a/test cases/frameworks/37 gir cpp/test.json +++ b/test cases/frameworks/37 gir cpp/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "macos", "msys2"] + "skip_on_jobname": ["azure", "macos", "msys2", "cygwin"] } From 1b1946c4e12647609b0c23e62355ca85afa8db70 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 30 Aug 2023 10:37:40 -0400 Subject: [PATCH 161/855] Disable failing test on cygwin due to broken cmake See https://gitlab.kitware.com/cmake/cmake/-/issues/25200. --- test cases/linuxlike/13 cmake dependency/meson.build | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test cases/linuxlike/13 cmake dependency/meson.build b/test cases/linuxlike/13 cmake dependency/meson.build index 193ad184b637..f612e1d52d6d 100644 --- a/test cases/linuxlike/13 cmake dependency/meson.build +++ b/test cases/linuxlike/13 cmake dependency/meson.build @@ -2,13 +2,20 @@ # due to use of setup_env.json project('external CMake dependency', ['c', 'cpp']) -if not find_program('cmake', required: false).found() +cmake = find_program('cmake', required: false) +if not cmake.found() error('MESON_SKIP_TEST cmake binary not available.') endif # Zlib is probably on all dev machines. dep = dependency('ZLIB', version : '>=1.2', method : 'cmake') + +if '#define' in dep.version() and cmake.version().version_compare('< 3.27.4') + # ZLIB 1.3 version is broken with those cmake versions + error('MESON_SKIP_TEST known bug in cmake (https://gitlab.kitware.com/cmake/cmake/-/issues/25200)') +endif + exe = executable('zlibprog', 'prog-checkver.c', dependencies : dep, c_args : '-DFOUND_ZLIB="' + dep.version() + '"') From 9cc18c5f7afa7fd4a0d1581eba26019e39847dc5 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 30 Aug 2023 17:20:30 -0500 Subject: [PATCH 162/855] Re-enable "11 runpath rpath ldlibrarypath" The bug it was blocked on was fixed in a0514a7c4183a9e42d436865087d2f887d658d54. --- test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c | 2 +- test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c b/test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c index 5009531698e1..b5e7b3006734 100644 --- a/test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c +++ b/test cases/linuxlike/11 runpath rpath ldlibrarypath/main.c @@ -2,7 +2,7 @@ int some_symbol (void); -int main () { +int main (void) { int ret = some_symbol (); if (ret == 1) return 0; diff --git a/test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build b/test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build index a3103acfa75c..b49da66d2762 100644 --- a/test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build +++ b/test cases/linuxlike/11 runpath rpath ldlibrarypath/meson.build @@ -1,7 +1,5 @@ project('runpath rpath ldlibrarypath', 'c') -error('MESON_SKIP_TEST test disabled due to bug #1635.') - libsrc = files('lib.c') subdir('lib1') From 08ad7e770c88a1cda44befd26182b147e341494a Mon Sep 17 00:00:00 2001 From: Bruce Merry Date: Thu, 31 Aug 2023 10:18:08 +0200 Subject: [PATCH 163/855] Doc: fix type signature for add_languages.required It was listed as `bool`, but it can be a `feature` too. --- docs/yaml/functions/add_languages.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/yaml/functions/add_languages.yaml b/docs/yaml/functions/add_languages.yaml index 6851c4e00d8a..3a77225aa7ce 100644 --- a/docs/yaml/functions/add_languages.yaml +++ b/docs/yaml/functions/add_languages.yaml @@ -36,7 +36,7 @@ varargs: kwargs: required: - type: bool + type: bool | feature default: true description: | If set to `true`, Meson will halt if any of the languages From cd30d1889f2bae34f17231b9cabe665edd57e7ba Mon Sep 17 00:00:00 2001 From: Bruce Merry Date: Thu, 24 Aug 2023 14:50:05 +0200 Subject: [PATCH 164/855] Document that dicts can be indexed with [] --- docs/markdown/Syntax.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index 9958db5429eb..b69ad00aef57 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -454,6 +454,15 @@ Keys must be unique: my_dict = {'foo': 42, 'foo': 43} ``` +Accessing elements of a dictionary works similarly to array indexing: + +```meson +my_dict = {'foo': 42, 'bar': 'baz'} +forty_two = my_dict['foo'] +# This will fail +my_dict['does_not_exist'] +``` + Dictionaries are immutable and do not have a guaranteed order. Dictionaries are available since 0.47.0. From cf5adf0c646474f0259d123fad60ca5ed38ec891 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 17 Mar 2023 16:27:37 -0400 Subject: [PATCH 165/855] add json output format to configure file --- docs/markdown/snippets/json_output_format.md | 5 ++ docs/yaml/functions/configure_file.yaml | 2 +- mesonbuild/interpreter/interpreter.py | 4 +- mesonbuild/interpreter/kwargs.py | 2 +- mesonbuild/utils/universal.py | 50 +++++++++++-------- .../compare.py | 5 ++ .../expected/config.h | 21 ++++++++ .../expected/config.json | 1 + .../expected/config.nasm | 17 +++++++ .../meson.build | 38 ++++++++++++++ 10 files changed, 121 insertions(+), 24 deletions(-) create mode 100644 docs/markdown/snippets/json_output_format.md create mode 100644 test cases/common/269 configure file output format/compare.py create mode 100644 test cases/common/269 configure file output format/expected/config.h create mode 100644 test cases/common/269 configure file output format/expected/config.json create mode 100644 test cases/common/269 configure file output format/expected/config.nasm create mode 100644 test cases/common/269 configure file output format/meson.build diff --git a/docs/markdown/snippets/json_output_format.md b/docs/markdown/snippets/json_output_format.md new file mode 100644 index 000000000000..626840f76b52 --- /dev/null +++ b/docs/markdown/snippets/json_output_format.md @@ -0,0 +1,5 @@ +## Added 'json' output_format to configure_file() + +When no input file is specified, [[configure_file]] can now +generate a `json` file from given [[@cfg_data]]. +Field descriptions are not preserved in the json file. diff --git a/docs/yaml/functions/configure_file.yaml b/docs/yaml/functions/configure_file.yaml index df37ff5811d2..6fb972b3e6d8 100644 --- a/docs/yaml/functions/configure_file.yaml +++ b/docs/yaml/functions/configure_file.yaml @@ -134,7 +134,7 @@ kwargs: The format of the output to generate when no input was specified. It defaults to `c`, in which case preprocessor directives will be prefixed with `#`, you can also use `nasm`, in which case the - prefix will be `%`. + prefix will be `%`. *(since 1.3.0)* `json` format can also be used. encoding: type: str diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 4751af9e81a4..0ba8dc76c5de 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2594,8 +2594,8 @@ def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], KwargInfo('install_dir', (str, bool), default='', validator=lambda x: 'must be `false` if boolean' if x is True else None), OUTPUT_KW, - KwargInfo('output_format', str, default='c', since='0.47.0', - validator=in_set_validator({'c', 'nasm'})), + KwargInfo('output_format', str, default='c', since='0.47.0', since_values={'json': '1.3.0'}, + validator=in_set_validator({'c', 'json', 'nasm'})), ) def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], kwargs: kwtypes.ConfigureFile): diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index af5733f4ed21..0aee16432c43 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -286,7 +286,7 @@ class ConfigureFile(TypedDict): output: str capture: bool format: T.Literal['meson', 'cmake', 'cmake@'] - output_format: T.Literal['c', 'nasm'] + output_format: T.Literal['c', 'json', 'nasm'] depfile: T.Optional[str] install: T.Optional[bool] install_dir: T.Union[str, T.Literal[False]] diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index a39825faf49a..d44ec03a8e99 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -32,6 +32,7 @@ import copy import pickle import errno +import json from mesonbuild import mlog from .core import MesonException, HoldableObject @@ -1361,34 +1362,43 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', ''' -def dump_conf_header(ofilename: str, cdata: 'ConfigurationData', output_format: Literal['c', 'nasm']) -> None: +def _dump_c_header(ofile: T.TextIO, cdata: ConfigurationData, output_format: Literal['c', 'nasm']) -> None: + format_desc: T.Callable[[str], str] if output_format == 'c': prelude = CONF_C_PRELUDE prefix = '#' - else: + format_desc = lambda desc: f'/* {desc} */\n' + else: # nasm prelude = CONF_NASM_PRELUDE prefix = '%' + format_desc = lambda desc: '; ' + '\n; '.join(desc.splitlines()) + '\n' + + ofile.write(prelude) + for k in sorted(cdata.keys()): + (v, desc) = cdata.get(k) + if desc: + ofile.write(format_desc(desc)) + if isinstance(v, bool): + if v: + ofile.write(f'{prefix}define {k}\n\n') + else: + ofile.write(f'{prefix}undef {k}\n\n') + elif isinstance(v, (int, str)): + ofile.write(f'{prefix}define {k} {v}\n\n') + else: + raise MesonException('Unknown data type in configuration file entry: ' + k) + +def dump_conf_header(ofilename: str, cdata: ConfigurationData, + output_format: Literal['c', 'nasm', 'json']) -> None: ofilename_tmp = ofilename + '~' with open(ofilename_tmp, 'w', encoding='utf-8') as ofile: - ofile.write(prelude) - for k in sorted(cdata.keys()): - (v, desc) = cdata.get(k) - if desc: - if output_format == 'c': - ofile.write('/* %s */\n' % desc) - elif output_format == 'nasm': - for line in desc.split('\n'): - ofile.write('; %s\n' % line) - if isinstance(v, bool): - if v: - ofile.write(f'{prefix}define {k}\n\n') - else: - ofile.write(f'{prefix}undef {k}\n\n') - elif isinstance(v, (int, str)): - ofile.write(f'{prefix}define {k} {v}\n\n') - else: - raise MesonException('Unknown data type in configuration file entry: ' + k) + if output_format == 'json': + data = {k: v[0] for k, v in cdata.values.items()} + json.dump(data, ofile, sort_keys=True) + else: # c, nasm + _dump_c_header(ofile, cdata, output_format) + replace_if_different(ofilename, ofilename_tmp) diff --git a/test cases/common/269 configure file output format/compare.py b/test cases/common/269 configure file output format/compare.py new file mode 100644 index 000000000000..5188b0237cd9 --- /dev/null +++ b/test cases/common/269 configure file output format/compare.py @@ -0,0 +1,5 @@ +import sys + +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') diff --git a/test cases/common/269 configure file output format/expected/config.h b/test cases/common/269 configure file output format/expected/config.h new file mode 100644 index 000000000000..33cfd89b0173 --- /dev/null +++ b/test cases/common/269 configure file output format/expected/config.h @@ -0,0 +1,21 @@ +/* + * Autogenerated by the Meson build system. + * Do not edit, your changes will be lost. + */ + +#pragma once + +#define bool + +#undef false + +/* ultimate question of life, the universe, and everything */ +#define int 42 + +/* This is +a multiline +description */ +#define str "hello world!" + +#define unquoted float + diff --git a/test cases/common/269 configure file output format/expected/config.json b/test cases/common/269 configure file output format/expected/config.json new file mode 100644 index 000000000000..47d7832591ca --- /dev/null +++ b/test cases/common/269 configure file output format/expected/config.json @@ -0,0 +1 @@ +{"bool": true, "false": false, "int": 42, "str": "\"hello world!\"", "unquoted": "float"} \ No newline at end of file diff --git a/test cases/common/269 configure file output format/expected/config.nasm b/test cases/common/269 configure file output format/expected/config.nasm new file mode 100644 index 000000000000..63c5c2221e72 --- /dev/null +++ b/test cases/common/269 configure file output format/expected/config.nasm @@ -0,0 +1,17 @@ +; Autogenerated by the Meson build system. +; Do not edit, your changes will be lost. + +%define bool + +%undef false + +; ultimate question of life, the universe, and everything +%define int 42 + +; This is +; a multiline +; description +%define str "hello world!" + +%define unquoted float + diff --git a/test cases/common/269 configure file output format/meson.build b/test cases/common/269 configure file output format/meson.build new file mode 100644 index 000000000000..796b9d6a26cb --- /dev/null +++ b/test cases/common/269 configure file output format/meson.build @@ -0,0 +1,38 @@ +project('configure file output format') + +data = configuration_data() +data.set_quoted('str', 'hello world!', description: '''This is +a multiline +description''') +data.set('unquoted', 'float') +data.set('int', 42, description: 'ultimate question of life, the universe, and everything') +data.set('bool', true) +data.set('false', false) + +config_h = configure_file( + configuration: data, + output_format: 'c', + output: 'config.h' +) + +config_nasm = configure_file( + configuration: data, + output_format: 'nasm', + output: 'config.nasm' +) + +config_json = configure_file( + configuration: data, + output_format: 'json', + output: 'config.json' +) + +py = find_program('python3') +compare_py = files('compare.py') +expected_config_h = files('expected/config.h') +expected_config_nasm = files('expected/config.nasm') +expected_config_json = files('expected/config.json') + +test('c_output', py, args: [compare_py, expected_config_h, config_h]) +test('nasm_output', py, args: [compare_py, expected_config_nasm, config_nasm]) +test('json_output', py, args: [compare_py, expected_config_json, config_json]) From 025bcc0d9d1f7ebdc3ba483ef77bc515327364bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Fri, 1 Sep 2023 02:08:53 +0100 Subject: [PATCH 166/855] compilers: fix compiler detection when the "ccache" string is in the path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe Laíns --- mesonbuild/compilers/detect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index f997247627d4..0bfedd13921a 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -1034,7 +1034,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust extra_args['machine'] = cc.linker.machine else: exelist = cc.linker.exelist + cc.linker.get_always_args() - if 'ccache' in exelist[0]: + if os.path.basename(exelist[0]) in {'ccache', 'sccache'}: del exelist[0] c = exelist.pop(0) compiler.extend(cls.use_linker_args(c, '')) From 12e23f55d4e1789da822d7ea543dc89662503ad7 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Aug 2023 13:36:31 -0400 Subject: [PATCH 167/855] tests: make run_project_tests finish off the verbose logs with a summary List each testcase name that failed so we can see at a glance which ones they are. --- run_project_tests.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/run_project_tests.py b/run_project_tests.py index f279332610d6..042bcf1b16b6 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -300,6 +300,7 @@ def __lt__(self, other: object) -> bool: return (s_id, self.path, self.name or '') < (o_id, other.path, other.name or '') return NotImplemented +failing_testcases: T.List[str] = [] failing_logs: T.List[str] = [] print_debug = 'MESON_PRINT_TEST_OUTPUT' in os.environ under_ci = 'CI' in os.environ @@ -1367,6 +1368,7 @@ def tqdm_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: left_w = max(3, left_w) right_w = cols - left_w - name_len - 2 right_w = max(3, right_w) + failing_testcases.append(name_str) failing_logs.append(f'\n\x1b[31m{"="*left_w}\x1b[0m {name_str} \x1b[31m{"="*right_w}\x1b[0m\n') if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: # For configure failures, instead of printing stdout, @@ -1633,6 +1635,9 @@ def clear_transitive_files() -> None: print(l, '\n') except UnicodeError: print(l.encode('ascii', errors='replace').decode(), '\n') + print('All failures:') + for c in failing_testcases: + print(f' -> {c}') for name, dirs, _ in all_tests: dir_names = list({x.path.name for x in dirs}) for k, g in itertools.groupby(dir_names, key=lambda x: x.split()[0]): From 0ecc8d5c8da91f210ca5216faabda0e0ee222cf2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Aug 2023 13:58:34 -0400 Subject: [PATCH 168/855] tests: make summary section for project tests more like pytest Logs for failing tests come first, then the list of pass/fail. --- run_project_tests.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index 042bcf1b16b6..af5b58db089a 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1624,10 +1624,6 @@ def clear_transitive_files() -> None: (passing_tests, failing_tests, skipped_tests) = res except StopException: pass - print() - print('Total passed tests: ', green(str(passing_tests))) - print('Total failed tests: ', red(str(failing_tests))) - print('Total skipped tests:', yellow(str(skipped_tests))) if failing_tests > 0: print('\nMesonlogs of failing tests\n') for l in failing_logs: @@ -1635,7 +1631,12 @@ def clear_transitive_files() -> None: print(l, '\n') except UnicodeError: print(l.encode('ascii', errors='replace').decode(), '\n') - print('All failures:') + print() + print('Total passed tests: ', green(str(passing_tests))) + print('Total failed tests: ', red(str(failing_tests))) + print('Total skipped tests:', yellow(str(skipped_tests))) + if failing_tests > 0: + print('\nAll failures:') for c in failing_testcases: print(f' -> {c}') for name, dirs, _ in all_tests: From e7c30e803b511d68c0e7ccdf389d205d85a4e6a9 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Aug 2023 14:04:40 -0400 Subject: [PATCH 169/855] tests: sync ninja stdout/stderr instead of listing them separately It is fairly confusing for all the "ninja explain" to be the last thing you see, instead of the compile error. --- run_project_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index af5b58db089a..2290cd578b57 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -711,8 +711,8 @@ def _run_test(test: TestDef, # Build with subprocess def build_step() -> None: build_start = time.time() - pc, o, e = Popen_safe(compile_commands + dir_args, cwd=test_build_dir) - testresult.add_step(BuildStep.build, o, e, '', time.time() - build_start) + pc, o, _ = Popen_safe(compile_commands + dir_args, cwd=test_build_dir, stderr=subprocess.STDOUT) + testresult.add_step(BuildStep.build, o, '', '', time.time() - build_start) if should_fail == 'build': if pc.returncode != 0: raise testresult From 1ec4a0900a0787358464d8bf8623a81bd6dc69dd Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Aug 2023 16:47:46 -0400 Subject: [PATCH 170/855] tests: move the newline to the right place in ci includes Make sure this is generic enough to be properly usable --- run_project_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index 2290cd578b57..f6568d47d95b 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -445,9 +445,9 @@ def _run_ci_include(args: T.List[str]) -> str: return 'At least one parameter required' try: data = Path(args[0]).read_text(errors='ignore', encoding='utf-8') - return f'{header}\n{data}\n{footer}' + return f'{header}\n{data}\n{footer}\n' except Exception: - return 'Failed to open {}'.format(args[0]) + return 'Failed to open {}\n'.format(args[0]) ci_commands = { 'ci_include': _run_ci_include @@ -461,7 +461,7 @@ def run_ci_commands(raw_log: str) -> T.List[str]: cmd = shlex.split(l[11:]) if not cmd or cmd[0] not in ci_commands: continue - res += ['CI COMMAND {}:\n{}\n'.format(cmd[0], ci_commands[cmd[0]](cmd[1:]))] + res += ['CI COMMAND {}:\n{}'.format(cmd[0], ci_commands[cmd[0]](cmd[1:]))] return res class OutputMatch: From 0833a0fa670cf741ffb7f50e777d443d39115b6a Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 30 Aug 2023 14:20:41 -0400 Subject: [PATCH 171/855] tests: move a couple log files into collapsed github groups where possible --- run_project_tests.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index f6568d47d95b..523db105584f 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -565,11 +565,11 @@ def run_test_inprocess(testdir: str) -> T.Tuple[int, str, str, str]: sys.stderr = mystderr = StringIO() old_cwd = os.getcwd() os.chdir(testdir) - test_log_fname = Path('meson-logs', 'testlog.txt') + test_log_fname = os.path.join('meson-logs', 'testlog.txt') try: returncode_test = mtest.run_with_args(['--no-rebuild']) - if test_log_fname.exists(): - test_log = test_log_fname.open(encoding='utf-8', errors='ignore').read() + if os.path.exists(test_log_fname): + test_log = _run_ci_include([test_log_fname]) else: test_log = '' returncode_benchmark = mtest.run_with_args(['--no-rebuild', '--benchmark', '--logbase', 'benchmarklog']) @@ -679,11 +679,10 @@ def _run_test(test: TestDef, returncode, stdo, stde = res cmd = '(inprocess) $ ' if inprocess else '$ ' cmd += mesonlib.join_args(gen_args) - try: - logfile = Path(test_build_dir, 'meson-logs', 'meson-log.txt') - with logfile.open(errors='ignore', encoding='utf-8') as fid: - mesonlog = '\n'.join((cmd, fid.read())) - except Exception: + logfile = os.path.join(test_build_dir, 'meson-logs', 'meson-log.txt') + if os.path.exists(logfile): + mesonlog = '\n'.join((cmd, _run_ci_include([logfile]))) + else: mesonlog = no_meson_log_msg cicmds = run_ci_commands(mesonlog) testresult = TestResult(cicmds) From 156a9baab5f8b62d6a54f26fd361b493d1ddad4c Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 31 Aug 2023 17:17:55 -0400 Subject: [PATCH 172/855] tests: repeat the failure reason in the detailed logs --- run_project_tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run_project_tests.py b/run_project_tests.py index 523db105584f..446dc12b8e93 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1369,6 +1369,9 @@ def tqdm_print(*args: mlog.TV_Loggable, sep: str = ' ') -> None: right_w = max(3, right_w) failing_testcases.append(name_str) failing_logs.append(f'\n\x1b[31m{"="*left_w}\x1b[0m {name_str} \x1b[31m{"="*right_w}\x1b[0m\n') + _during = bold('Failed during:') + _reason = bold('Reason:') + failing_logs.append(f'{_during} {result.step.name}\n{_reason} {result.msg}\n') if result.step == BuildStep.configure and result.mlog != no_meson_log_msg: # For configure failures, instead of printing stdout, # print the meson log if available since it's a superset From b504fe1b3e31e68ba475a8bb5b1107ad9e80c20e Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Sun, 3 Sep 2023 18:54:55 -0500 Subject: [PATCH 173/855] Add trilo xtest to users --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 6fcbec625d4f..4b7208a1b4aa 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -160,6 +160,7 @@ format files - [Terminology](https://github.com/billiob/terminology), a terminal emulator based on the Enlightenment Foundation Libraries - [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 + - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code - [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 6b63c4161d06f7ca79e71246900df1c276a4c1d8 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Sun, 3 Sep 2023 19:23:43 -0500 Subject: [PATCH 174/855] Adding Meson-UI back on IDE-integration.md --- docs/markdown/IDE-integration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index 9c16cdb09226..ad7185a1fd7f 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -424,4 +424,5 @@ schema is defined by the class structure given in - [Meson Syntax Highlighter](https://plugins.jetbrains.com/plugin/13269-meson-syntax-highlighter) plugin for JetBrains IDEs. - [vscode-meson](https://github.com/mesonbuild/vscode-meson) extension for VS Code/Codium - [Qt Creator](https://doc.qt.io/qtcreator/creator-project-meson.html) +- [Meson-UI](https://github.com/dreamer-coding-555/meson-ui) (build GUI for Meson) - [mmeson](https://github.com/stephanlachnit/mmeson) (ccmake clone for Meson) From f07476a89677f5c87a62b6756b76a0e8ebc4bceb Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 6 Jul 2023 11:43:58 -0400 Subject: [PATCH 175/855] wrap: Remove duplicated code --- mesonbuild/wrap/wrap.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index c0dd01c27427..c8570500c53d 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -568,12 +568,6 @@ def get_git(self) -> None: revno = self.wrap.get('revision') verbose_git(['fetch', *depth_option, 'origin', revno], self.dirname, check=True) verbose_git(checkout_cmd, self.dirname, check=True) - if self.wrap.values.get('clone-recursive', '').lower() == 'true': - verbose_git(['submodule', 'update', '--init', '--checkout', - '--recursive', *depth_option], self.dirname, check=True) - push_url = self.wrap.values.get('push-url') - if push_url: - verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True) else: if not is_shallow: verbose_git(['clone', self.wrap.get('url'), self.directory], self.subdir_root, check=True) @@ -587,12 +581,12 @@ def get_git(self) -> None: args += ['--branch', revno] args += [self.wrap.get('url'), self.directory] verbose_git(args, self.subdir_root, check=True) - if self.wrap.values.get('clone-recursive', '').lower() == 'true': - verbose_git(['submodule', 'update', '--init', '--checkout', '--recursive', *depth_option], - self.dirname, check=True) - push_url = self.wrap.values.get('push-url') - if push_url: - verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True) + if self.wrap.values.get('clone-recursive', '').lower() == 'true': + verbose_git(['submodule', 'update', '--init', '--checkout', '--recursive', *depth_option], + self.dirname, check=True) + push_url = self.wrap.values.get('push-url') + if push_url: + verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True) def validate(self) -> None: # This check is only for subprojects with wraps. From fe9af72684f85d709ce45096534aa51854a6da9b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 4 Sep 2023 08:49:39 -0400 Subject: [PATCH 176/855] wrap: Use MESON_PACKAGE_CACHE_DIR as default packagecache path Allow packagecache to contain already extracted directory to match what some distro does with Cargo source packages in /usr/share/cargo/registry. Note that there is no need to lock the cache directory because we download into a temporary name and atomically rename afterward. It means we could be downloading the same file twice, but at least integrity is guaranteed. Fixes: #12211 --- docs/markdown/Wrap-dependency-system-manual.md | 6 ++++++ docs/markdown/snippets/meson_home.md | 7 +++++++ mesonbuild/wrap/wrap.py | 14 ++++++++++++-- .../cache_dir/bar/meson.build | 1 + .../116 meson package cache dir/cache_dir/foo.zip | Bin 0 -> 373 bytes .../unit/116 meson package cache dir/meson.build | 4 ++++ .../subprojects/bar.wrap | 3 +++ .../subprojects/foo.wrap | 5 +++++ unittests/platformagnostictests.py | 10 ++++++++++ 9 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/meson_home.md create mode 100644 test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build create mode 100644 test cases/unit/116 meson package cache dir/cache_dir/foo.zip create mode 100644 test cases/unit/116 meson package cache dir/meson.build create mode 100644 test cases/unit/116 meson package cache dir/subprojects/bar.wrap create mode 100644 test cases/unit/116 meson package cache dir/subprojects/foo.wrap diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index c8b91d53eea4..3aeea144afd7 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -109,6 +109,12 @@ project's `subprojects/packagecache` directory, it will be used instead of downloading the file, even if `--wrap-mode` option is set to `nodownload`. The file's hash will be checked. +Since *1.3.0* if the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of +the project's `subprojects/packagecache`. This allows sharing the cache across multiple +projects. In addition it can contain an already extracted source tree as long as it +has the same directory name as the `directory` field in the wrap file. In that +case, the directory will be copied into `subprojects/` before applying patches. + ### Specific to VCS-based wraps - `url` - name of the wrap-git repository to clone. Required. - `revision` - name of the revision to checkout. Must be either: a diff --git a/docs/markdown/snippets/meson_home.md b/docs/markdown/snippets/meson_home.md new file mode 100644 index 000000000000..2d656fc1e28b --- /dev/null +++ b/docs/markdown/snippets/meson_home.md @@ -0,0 +1,7 @@ +## New environment variable `MESON_PACKAGE_CACHE_DIR` + +If the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of the +project's `subprojects/packagecache`. This allows sharing the cache across multiple +projects. In addition it can contain an already extracted source tree as long as it +has the same directory name as the `directory` field in the wrap file. In that +case, the directory will be copied into `subprojects/` before applying patches. diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index c8570500c53d..941da3de86bf 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -289,7 +289,7 @@ class Resolver: def __post_init__(self) -> None: self.subdir_root = os.path.join(self.source_dir, self.subdir) - self.cachedir = os.path.join(self.subdir_root, 'packagecache') + self.cachedir = os.environ.get('MESON_PACKAGE_CACHE_DIR') or os.path.join(self.subdir_root, 'packagecache') self.wraps: T.Dict[str, PackageDefinition] = {} self.netrc: T.Optional[netrc] = None self.provided_deps: T.Dict[str, PackageDefinition] = {} @@ -462,7 +462,17 @@ def resolve(self, packagename: str, method: str) -> str: if not os.path.isdir(self.dirname): raise WrapException('Path already exists but is not a directory') else: - if self.wrap.type == 'file': + # Check first if we have the extracted directory in our cache. This can + # happen for example when MESON_PACKAGE_CACHE_DIR=/usr/share/cargo/registry + # on distros that ships Rust source code. + # TODO: We don't currently clone git repositories into the cache + # directory, but we should to avoid cloning multiple times the same + # repository. In that case, we could do something smarter than + # copy_tree() here. + cached_directory = os.path.join(self.cachedir, self.directory) + if os.path.isdir(cached_directory): + self.copy_tree(cached_directory, self.dirname) + elif self.wrap.type == 'file': self.get_file() else: self.check_can_download() diff --git a/test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build b/test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build new file mode 100644 index 000000000000..dca36f65671e --- /dev/null +++ b/test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build @@ -0,0 +1 @@ +project('bar') diff --git a/test cases/unit/116 meson package cache dir/cache_dir/foo.zip b/test cases/unit/116 meson package cache dir/cache_dir/foo.zip new file mode 100644 index 0000000000000000000000000000000000000000..91bc36aca2d5fab32afa38937d68bff7c1bdb43c GIT binary patch literal 373 zcmWIWW@Zs#0DxYK$GO%xF{+0s6r4`%^j4Ush85qDs0N4Z$ z1`ZSx_<^SILrus{EzZx=ODfIGNg-sIw#KRRUcP!41N={)55N9|i6Ow7onv0(vl)V5 z^B919MkWzv+%AUs;IAWyMV$K~Cc=DxY#Yc2FtDZ332Gt<{t57AWdj+&1cd8>^ac=z F0RV&QQPBVZ literal 0 HcmV?d00001 diff --git a/test cases/unit/116 meson package cache dir/meson.build b/test cases/unit/116 meson package cache dir/meson.build new file mode 100644 index 000000000000..2057bba89328 --- /dev/null +++ b/test cases/unit/116 meson package cache dir/meson.build @@ -0,0 +1,4 @@ +project('meson package cache dir') + +subproject('foo') +subproject('bar') diff --git a/test cases/unit/116 meson package cache dir/subprojects/bar.wrap b/test cases/unit/116 meson package cache dir/subprojects/bar.wrap new file mode 100644 index 000000000000..3ec58343bb0c --- /dev/null +++ b/test cases/unit/116 meson package cache dir/subprojects/bar.wrap @@ -0,0 +1,3 @@ +[wrap-file] +directory = bar + diff --git a/test cases/unit/116 meson package cache dir/subprojects/foo.wrap b/test cases/unit/116 meson package cache dir/subprojects/foo.wrap new file mode 100644 index 000000000000..b7dd41de5339 --- /dev/null +++ b/test cases/unit/116 meson package cache dir/subprojects/foo.wrap @@ -0,0 +1,5 @@ +[wrap-file] +directory = foo +source_url = http://server.invalid/foo.zip +source_filename = foo.zip +source_hash = c5dd7e8fca93045f736c83700686722b0fbc20b7dc4597b295060684c5b05b72 diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index efe3109d73dc..92c613d916d7 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -18,6 +18,7 @@ import tempfile import subprocess import textwrap +import shutil from unittest import skipIf, SkipTest from pathlib import Path @@ -261,3 +262,12 @@ def test_setup_loaded_modules(self): self.assertEqual(data['modules'], expected) self.assertEqual(data['count'], 68) + + def test_meson_package_cache_dir(self): + # Copy testdir into temporary directory to not pollute meson source tree. + testdir = os.path.join(self.unit_test_dir, '116 meson package cache dir') + srcdir = os.path.join(self.builddir, 'srctree') + shutil.copytree(testdir, srcdir) + builddir = os.path.join(srcdir, '_build') + self.change_builddir(builddir) + self.init(srcdir, override_envvars={'MESON_PACKAGE_CACHE_DIR': os.path.join(srcdir, 'cache_dir')}) From 599f37eb5611707b2e32e5f6d1e12f6c609dde52 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 5 Sep 2023 13:43:20 -0400 Subject: [PATCH 177/855] qt module: fix substitution for depfile in moc --- mesonbuild/modules/qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index 20ff11176486..d5c327368001 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -474,7 +474,7 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') - if kwargs['sources']: moc_gen = build.Generator( self.tools['moc'], arguments, ['@BASENAME@.moc'], - depfile='@BASENAME.moc.d@', + depfile='@BASENAME@.moc.d', name=f'Qt{self.qt_version} moc source') output.append(moc_gen.process_files(kwargs['sources'], state)) From 84466b735986c9f548899f7e7669be782de091e8 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 5 Sep 2023 13:51:18 -0400 Subject: [PATCH 178/855] qt module: add include_directories to moc compile Fixes #12182 --- mesonbuild/modules/qt.py | 7 +++++-- test cases/frameworks/4 qt/manualinclude.cpp | 1 + test cases/frameworks/4 qt/meson.build | 13 ++++++++++--- test cases/frameworks/4 qt/mocdep/meson.build | 3 +++ test cases/frameworks/4 qt/mocdep/mocdep.h | 1 + 5 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test cases/frameworks/4 qt/mocdep/meson.build create mode 100644 test cases/frameworks/4 qt/mocdep/mocdep.h diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index d5c327368001..83dcf31bdfb3 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -23,7 +23,7 @@ from .. import build from .. import coredata from .. import mlog -from ..dependencies import find_external_dependency, Dependency, ExternalLibrary +from ..dependencies import find_external_dependency, Dependency, ExternalLibrary, InternalDependency from ..mesonlib import MesonException, File, version_compare, Popen_safe from ..interpreter import extract_required_kwarg from ..interpreter.type_checking import INSTALL_DIR_KW, INSTALL_KW, NoneType @@ -457,7 +457,10 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') - inc = state.get_include_args(include_dirs=kwargs['include_directories']) compile_args: T.List[str] = [] for dep in kwargs['dependencies']: - compile_args.extend([a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))]) + compile_args.extend(a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))) + if isinstance(dep, InternalDependency): + for incl in dep.include_directories: + compile_args.extend(f'-I{i}' for i in incl.to_string_list(self.interpreter.source_root, self.interpreter.environment.build_dir)) output: T.List[build.GeneratedList] = [] diff --git a/test cases/frameworks/4 qt/manualinclude.cpp b/test cases/frameworks/4 qt/manualinclude.cpp index 60b94e510e12..ef151a44aad6 100644 --- a/test cases/frameworks/4 qt/manualinclude.cpp +++ b/test cases/frameworks/4 qt/manualinclude.cpp @@ -1,4 +1,5 @@ #include"manualinclude.h" +#include #include #include diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index 825cd5766fa6..04a5288bf1c4 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -2,6 +2,9 @@ project('qt4, qt5, and qt6 build test', 'cpp', # Qt6 requires C++ 17 support default_options : ['cpp_std=c++17']) +# Visit the subdir before entering the loop +subdir('mocdep') + qt5_modules = ['Widgets'] qt6_modules = ['Widgets'] foreach qt : ['qt4', 'qt5', 'qt6'] @@ -114,17 +117,21 @@ foreach qt : ['qt4', 'qt5', 'qt6'] moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` moc_sources : 'manualinclude.cpp', moc_headers : 'manualinclude.h', - method : get_option('method')) + method : get_option('method'), + dependencies: mocdep, + ) manpreprocessed = qtmodule.compile_moc( extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` sources : 'manualinclude.cpp', headers : 'manualinclude.h', - method : get_option('method')) + method : get_option('method'), + dependencies: mocdep, + ) qtmaninclude = executable(qt + 'maninclude', sources : ['manualinclude.cpp', manpreprocessed], - dependencies : qtcore) + dependencies : [qtcore, mocdep]) test(qt + 'maninclude', qtmaninclude) diff --git a/test cases/frameworks/4 qt/mocdep/meson.build b/test cases/frameworks/4 qt/mocdep/meson.build new file mode 100644 index 000000000000..174b42679090 --- /dev/null +++ b/test cases/frameworks/4 qt/mocdep/meson.build @@ -0,0 +1,3 @@ +mocdep = declare_dependency( + include_directories: include_directories('.'), +) diff --git a/test cases/frameworks/4 qt/mocdep/mocdep.h b/test cases/frameworks/4 qt/mocdep/mocdep.h new file mode 100644 index 000000000000..357a52c3dd2b --- /dev/null +++ b/test cases/frameworks/4 qt/mocdep/mocdep.h @@ -0,0 +1 @@ +#define MOC_DEP 1 From 15811e362e0d38981bdb62c0fbc50356b660b6fd Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 25 Jul 2022 10:11:31 -0700 Subject: [PATCH 179/855] backends/ninja: run `ranlib -c $out` when using the apple ar Apple's AR is old, and doesn't add externed symbols to the symbol table, instead relying on the user calling ranlib with -c. We need to do that for the user --- mesonbuild/backend/ninjabackend.py | 13 ++++++++++++- mesonbuild/linkers/linkers.py | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 03f33d613523..6c739ed0a1bf 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2350,7 +2350,7 @@ def generate_static_link_rules(self): if static_linker is None: continue rule = 'STATIC_LINKER{}'.format(self.get_rule_suffix(for_machine)) - cmdlist = [] + cmdlist: T.List[T.Union[str, NinjaCommandArg]] = [] args = ['$in'] # FIXME: Must normalize file names with pathlib.Path before writing # them out to fix this properly on Windows. See: @@ -2364,6 +2364,17 @@ def generate_static_link_rules(self): cmdlist += static_linker.get_exelist() cmdlist += ['$LINK_ARGS'] cmdlist += NinjaCommandArg.list(static_linker.get_output_args('$out'), Quoting.none) + # The default ar on MacOS (at least through version 12), does not + # add extern'd variables to the symbol table by default, and + # requires that apple's ranlib be called with a special flag + # instead after linking + if static_linker.id == 'applear': + # This is a bit of a hack, but we assume that that we won't need + # an rspfile on MacOS, otherwise the arguments are passed to + # ranlib, not to ar + cmdlist.extend(args) + args = [] + cmdlist.extend(['&&', 'ranlib', '-c', '$out']) description = 'Linking static target $out' if num_pools > 0: pool = 'pool = link_pool' diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 9176090404a4..0c2bf73be77a 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -349,6 +349,8 @@ class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker): """Microsoft's lib static linker.""" + id = 'lib' + def __init__(self, exelist: T.List[str], machine: str): StaticLinker.__init__(self, exelist) VisualStudioLikeLinker.__init__(self, machine) @@ -358,6 +360,8 @@ class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker): """Intel's xilib static linker.""" + id = 'xilib' + def __init__(self, exelist: T.List[str], machine: str): StaticLinker.__init__(self, exelist) VisualStudioLikeLinker.__init__(self, machine) From 0e99c076c4663985e021b9bbcf1515e08b3c8e30 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Mon, 25 Jul 2022 10:24:09 -0700 Subject: [PATCH 180/855] tests: Test extern'd globals on MacOS with the Apple Archiver This forces the use of the Apple archiver, since that archiver doesn't add extern'd variables to the symbol table automatically, and instead requires that ranlib be used. A native file is used to ensure that Apple's ar is used even in the presence of llvm or gcc in the path with their superior archivers. Co-authored-by: Dylan Baker --- test cases/osx/9 global variable ar/libfile.c | 9 +++++++++ test cases/osx/9 global variable ar/libfile2.c | 7 +++++++ test cases/osx/9 global variable ar/meson.build | 6 ++++++ test cases/osx/9 global variable ar/nativefile.ini | 2 ++ test cases/osx/9 global variable ar/prog.c | 7 +++++++ 5 files changed, 31 insertions(+) create mode 100644 test cases/osx/9 global variable ar/libfile.c create mode 100644 test cases/osx/9 global variable ar/libfile2.c create mode 100644 test cases/osx/9 global variable ar/meson.build create mode 100644 test cases/osx/9 global variable ar/nativefile.ini create mode 100644 test cases/osx/9 global variable ar/prog.c diff --git a/test cases/osx/9 global variable ar/libfile.c b/test cases/osx/9 global variable ar/libfile.c new file mode 100644 index 000000000000..b258d7b8250f --- /dev/null +++ b/test cases/osx/9 global variable ar/libfile.c @@ -0,0 +1,9 @@ +// Source: https://lists.gnu.org/archive/html/libtool/2002-07/msg00025.html + +#include + +extern int l2; +void l1(void) +{ + printf("l1 %d\n", l2); +} diff --git a/test cases/osx/9 global variable ar/libfile2.c b/test cases/osx/9 global variable ar/libfile2.c new file mode 100644 index 000000000000..1499c4dc7f8a --- /dev/null +++ b/test cases/osx/9 global variable ar/libfile2.c @@ -0,0 +1,7 @@ +// Source: https://lists.gnu.org/archive/html/libtool/2002-07/msg00025.html + +int l2; +void l2_func(void) +{ + l2 = 77; +} diff --git a/test cases/osx/9 global variable ar/meson.build b/test cases/osx/9 global variable ar/meson.build new file mode 100644 index 000000000000..313dd1b37653 --- /dev/null +++ b/test cases/osx/9 global variable ar/meson.build @@ -0,0 +1,6 @@ +# Source: https://lists.gnu.org/archive/html/libtool/2002-07/msg00025.html + +project('global variable test', 'c') + +lib = static_library('mylib', 'libfile.c', 'libfile2.c') +test('global variable', executable('prog', 'prog.c', link_with: lib)) diff --git a/test cases/osx/9 global variable ar/nativefile.ini b/test cases/osx/9 global variable ar/nativefile.ini new file mode 100644 index 000000000000..4fb5e7f7db1b --- /dev/null +++ b/test cases/osx/9 global variable ar/nativefile.ini @@ -0,0 +1,2 @@ +[binaries] +ar = 'ar' diff --git a/test cases/osx/9 global variable ar/prog.c b/test cases/osx/9 global variable ar/prog.c new file mode 100644 index 000000000000..4665016f6149 --- /dev/null +++ b/test cases/osx/9 global variable ar/prog.c @@ -0,0 +1,7 @@ +// Source: https://lists.gnu.org/archive/html/libtool/2002-07/msg00025.html + +extern void l1(void); +int main(void) +{ + l1(); +} From 6a62d4912216fa6413326dafdbfdac5e98afbe43 Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Fri, 17 Feb 2023 18:22:03 +0000 Subject: [PATCH 181/855] completions: bash: added a bunch of missing completion options. --- data/shell-completions/bash/meson | 179 +++++++++++++++++++++++------- 1 file changed, 137 insertions(+), 42 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index 4357a3f68025..b1cbe81fde6f 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -103,20 +103,28 @@ _meson_complete_filedir() { cur=$2 case $option in prefix |\ - libdir |\ - libexecdir |\ bindir |\ - sbindir |\ - includedir |\ datadir |\ - mandir |\ + includedir |\ infodir |\ + libdir |\ + licensedir |\ + libexecdir |\ localedir |\ - sysconfdir |\ localstatedir |\ - sharedstatedir) + mandir |\ + sbindir |\ + sharedstatedir |\ + sysconfdir |\ + python.platlibdir |\ + python.purelibdir |\ + pkg-config-path |\ + build.pkg-config-path |\ + cmake-prefix-path |\ + build.cmake-prefix-path) _filedir -d ;; + cross-file) _filedir COMPREPLY+=($(_filedir_in "$XDG_DATA_DIRS"/meson/cross)) @@ -125,6 +133,16 @@ _meson_complete_filedir() { COMPREPLY+=($(_filedir_in "$XDG_DATA_HOME"/meson/cross)) COMPREPLY+=($(_filedir_in ~/.local/share/meson/cross)) ;; + + native-file) + _filedir + COMPREPLY+=($(_filedir_in "$XDG_DATA_DIRS"/meson/native)) + COMPREPLY+=($(_filedir_in /usr/local/share/meson/native)) + COMPREPLY+=($(_filedir_in /usr/share/meson/native)) + COMPREPLY+=($(_filedir_in "$XDG_DATA_HOME"/meson/native)) + COMPREPLY+=($(_filedir_in ~/.local/share/meson/native)) + ;; + *) return 1;; esac @@ -132,41 +150,63 @@ _meson_complete_filedir() { } _meson-setup() { - shortopts=( h D v ) + # backend-startup-project is currently VS backend only. + longopts=( help prefix - libdir - libexecdir bindir - sbindir - includedir datadir - mandir + includedir infodir + libdir + libexecdir + licensedir localedir - sysconfdir localstatedir + mandir + sbindir sharedstatedir + sysconfdir + auto-features backend buildtype + debug + default-library + errorlogs + install-umask + layout + optimization + prefer-static + stdsplit strip unity - werror - layout - default-library + unity-size warnlevel - stdsplit - errorlogs + werror + wrap-mode + force-fallback-for + pkgconfig.relocatable + python.install-env + python.platlibdir + python.purelibdir + pkg-config-path + build.pkg-config-path + cmake-prefix-path + build.cmake-prefix-path + native-file cross-file + vsenv version - wrap-mode + fatal-meson-warnings + reconfigure + wipe ) local cur prev @@ -204,7 +244,6 @@ _meson-setup() { } _meson-configure() { - shortopts=( h D @@ -212,7 +251,49 @@ _meson-configure() { longopts=( help + prefix + bindir + datadir + includedir + infodir + libdir + libexecdir + licensedir + localedir + localstatedir + mandir + sbindir + sharedstatedir + sysconfdir + auto-features + backend + buildtype + debug + default-library + errorlogs + install-umask + layout + optimization + prefer-static + stdsplit + strip + unity + unity-size + warnlevel + werror + wrap-mode + force-fallback-for + backend-startup-project + pkgconfig.relocatable + python.install-env + python.platlibdir + python.purelibdir + pkg-config-path + build.pkg-config-path + cmake-prefix-path + build.cmake-prefix-path clearcache + no-pager ) local cur prev @@ -259,17 +340,27 @@ _meson-install() { _meson-introspect() { shortopts=( h + a + i + f ) longopts=( - targets - installed - buildsystem-files - buildoptions - tests + ast benchmarks + buildoptions + buildsystem-files dependencies + scan-dependencies + installed + install-plan projectinfo + targets + tests + backend + all + indent + force-object-output ) local cur prev @@ -306,7 +397,6 @@ _meson-init() { C n e - e d l b @@ -315,14 +405,15 @@ _meson-init() { longopts=( help - name - executable - deps - language - builddir - force - type - version + name + executable + deps + language + build + builddir + force + type + version ) if [[ "$cur" == "--"* ]]; then @@ -340,6 +431,7 @@ _meson-init() { _meson-test() { shortopts=( + h q v t @@ -347,21 +439,24 @@ _meson-test() { ) longopts=( - quiet - verbose - timeout-multiplier + help + maxfail repeat no-rebuild gdb + gdb-path list - wrapper --wrap - no-suite + wrapper suite + no-suite no-stdsplit print-errorlogs benchmark logbase num-processes + verbose + quiet + timeout-multiplier setup test-args ) @@ -369,7 +464,7 @@ _meson-test() { local cur prev if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then case $prev in - --repeat) + --maxfail | --repeat) # number, can't be completed return ;; @@ -377,7 +472,7 @@ _meson-test() { _command_offset $COMP_CWORD return ;; - -C) + --gdb-path | -C) _filedir -d return ;; From 7e3f419c7aeeab8997189aa13ca348cc54ea8e1b Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Sat, 18 Feb 2023 12:11:28 +0000 Subject: [PATCH 182/855] completions: bash: fix -x. If x was a known short option, would complete to "-". If unknown, "--". --- data/shell-completions/bash/meson | 93 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index b1cbe81fde6f..d40620487617 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -149,6 +149,25 @@ _meson_complete_filedir() { return 0 } +_meson_compgen_options() { + local -r cur=$1 + + if [[ ${cur:0:2} == -- ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ ${cur:0:1} == - ]]; then + if [[ ${#cur} == 1 ]]; then + # Only add longopts if cur not "-something" + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "")) + fi + + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + return 1 + fi + + return 0 +} + _meson-setup() { shortopts=( h @@ -210,14 +229,16 @@ _meson-setup() { ) local cur prev - if _get_comp_words_by_ref cur prev &>/dev/null && - [ "${prev:0:2}" = '--' ] && _meson_complete_option "${prev:2}" "$cur"; then - return - elif _get_comp_words_by_ref cur prev &>/dev/null && - [ "${prev:0:1}" = '-' ] && [ "${prev:1:2}" != '-' ] && _meson_complete_option "${prev:1}"; then - return - elif _get_comp_words_by_ref -n '=' cur prev &>/dev/null; then - if [ $prev == -D ]; then + if _get_comp_words_by_ref cur prev &>/dev/null; then + if [[ ${prev:0:2} == -- ]] && _meson_complete_option "${prev:2}" "$cur"; then + return + elif [[ ${prev:0:1} == - ]] && [[ ${prev:1:2} != - ]] && _meson_complete_option "${prev:1}"; then + return + fi + fi + + if _get_comp_words_by_ref -n '=' cur prev &>/dev/null; then + if [[ $prev == -D ]]; then _meson_complete_option "$cur" return fi @@ -225,19 +246,14 @@ _meson-setup() { cur="${COMP_WORDS[COMP_CWORD]}" fi - if [[ "$cur" == "--"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - elif [[ "$cur" == "-"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) - else + if ! _meson_compgen_options "$cur"; then _filedir -d - if [ -z "$cur" ]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) fi - if [ $COMP_CWORD -eq 1 ]; then + if [[ $COMP_CWORD == 1 ]]; then COMPREPLY+=($(compgen -W "${meson_subcommands[*]}" -- "$cur")) fi fi @@ -298,7 +314,7 @@ _meson-configure() { local cur prev if _get_comp_words_by_ref -n '=' cur prev &>/dev/null; then - if [ $prev == -D ]; then + if [[ $prev == -D ]]; then _meson_complete_option "$cur" return fi @@ -306,25 +322,20 @@ _meson-configure() { cur="${COMP_WORDS[COMP_CWORD]}" fi - if [[ "$cur" == "--"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - elif [[ "$cur" == "-"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) - else + if ! _meson_compgen_options "$cur"; then for dir in "${COMP_WORDS[@]}"; do - if [ -d "$dir" ]; then + if [[ -d "$dir" ]]; then break fi dir=. done - if [ ! -d "$dir/meson-private" ]; then + if [[ ! -d "$dir/meson-private" ]]; then _filedir -d fi - if [ -z "$cur" ]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) fi fi } @@ -368,12 +379,7 @@ _meson-introspect() { cur="${COMP_WORDS[COMP_CWORD]}" fi - if [[ "$cur" == "--"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - elif [[ "$cur" == "-"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) - else + if ! _meson_compgen_options "$cur"; then for dir in "${COMP_WORDS[@]}"; do if [ -d "$dir" ]; then break @@ -416,17 +422,12 @@ _meson-init() { version ) - if [[ "$cur" == "--"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - elif [[ "$cur" == "-"* && ${#cur} -gt 1 ]]; then - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) - else - if [ -z "$cur" ]; then + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) fi fi - } _meson-test() { @@ -520,11 +521,7 @@ for test in json.load(sys.stdin): cur="${COMP_WORDS[COMP_CWORD]}" fi - if [[ "$cur" == "--"* ]]; then - COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) - elif [[ "$cur" == "-"* && ${#cur} -gt 1 ]]; then - COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) - else + if ! _meson_compgen_options "$cur"; then for dir in "${COMP_WORDS[@]}"; do if [ -d "$dir" ]; then break From df24e36a62f8e6cb667f4beb1b43e99bd360269d Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Sat, 18 Feb 2023 09:35:40 +0000 Subject: [PATCH 183/855] completions: bash: added "compile" (and "help") completion. --- data/shell-completions/bash/meson | 65 ++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index d40620487617..300c504d4119 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -564,7 +564,27 @@ _meson-subprojects() { } _meson-help() { - : # Nothing to do + longopts=( + setup + configure + dist + install + introspect + init + test + wrap + subprojects + rewrite + compile + devenv + env2mfile + ) + + local cur prev + + if _get_comp_words_by_ref cur prev &>/dev/null; then + COMPREPLY+=($(compgen -W '${longopts[*]}' -- "${cur}")) + fi } _meson-rewrite() { @@ -572,7 +592,48 @@ _meson-rewrite() { } _meson-compile() { - : TODO + shortopts=( + h + C + j + l + v + ) + + longopts=( + help + clean + jobs + load-average + verbose + ninja-args + vs-args + xcode-args + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + if [[ ${prev:0:2} == -- ]] && _meson_complete_option "${prev:2}" "$cur"; then + return + elif [[ ${prev:0:1} == - ]] && [[ ${prev:1:2} != - ]] && _meson_complete_option "${prev:1}"; then + return + fi + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + _filedir -d + + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + + if [[ $COMP_CWORD == 1 ]]; then + COMPREPLY+=($(compgen -W "${meson_subcommands[*]}" -- "$cur")) + fi + fi } _meson-devenv() { From 2c2231173784ce41ed8cc28f8cdc516ffc53cf99 Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Mon, 20 Feb 2023 09:45:48 +0000 Subject: [PATCH 184/855] completions: bash: don't show json errors when completing "meson test". E.g. "meson test" json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) --- data/shell-completions/bash/meson | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index 300c504d4119..3dd16cc49167 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -469,14 +469,17 @@ _meson-test() { # number, can't be completed return ;; + --wrapper) _command_offset $COMP_CWORD return ;; + --gdb-path | -C) _filedir -d return ;; + --suite | --no-suite) for i in "${!COMP_WORDS[@]}"; do opt="${COMP_WORDS[i]}" @@ -488,31 +491,40 @@ _meson-test() { esac dir=. done - suites=($(python3 -c 'import sys, json; + + suites=$(meson introspect "$dir" --tests | python3 -c 'import sys, json; for test in json.load(sys.stdin): for suite in test["suite"]: print(suite) - ' <<< "$(meson introspect "$dir" --tests)")) -# TODO - COMPREPLY+=($(compgen -W "${suites[*]}" -- "$cur")) +' 2> /dev/null) +# TODO - what? + + if [[ $? == 0 ]]; then + COMPREPLY+=($(compgen -W "${suites[*]}" -- "$cur")) + fi return ;; + --logbase) # free string, can't be completed return ;; + --num-processes) # number, can't be completed return ;; + -t | --timeout-multiplier) # number, can't be completed return ;; + --setup) # TODO return ;; + --test-args) return ;; @@ -528,6 +540,7 @@ for test in json.load(sys.stdin): fi dir=. done + if [ ! -d "$dir/meson-private" ]; then _filedir -d fi @@ -542,11 +555,15 @@ for test in json.load(sys.stdin): esac dir=. done - tests=($(python3 -c 'import sys, json; + + tests=$(meson introspect "$dir" --tests | python3 -c 'import sys, json; for test in json.load(sys.stdin): print(test["name"]) -' <<< "$(meson introspect "$dir" --tests)")) - COMPREPLY+=($(compgen -W "${tests[*]}" -- "$cur")) +' 2> /dev/null) + + if [[ $? == 0 ]]; then + COMPREPLY+=($(compgen -W "${tests[*]}" -- "$cur")) + fi if [ -z "$cur" ]; then COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) From 3fc16f05b513f26aa5da614673116074f5d60396 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Wed, 6 Sep 2023 03:12:55 +0200 Subject: [PATCH 185/855] Add compiler.has_define Adds a new method to the compiler object, has_define. This makes it possible to check if a preprocessor macro/define is set or not. This is especially helpful if the define in question is empty, for example: #define MESON_EMPTY_DEFINE This would yield the same results as a missing define with the existing get_define method, as it would return an empty string for both cases. Therefore this additional method is needed. --- docs/markdown/snippets/compiler_has_define.md | 10 +++ docs/yaml/objects/compiler.yaml | 11 +++ mesonbuild/compilers/mixins/clike.py | 27 ++++-- mesonbuild/interpreter/compiler.py | 22 ++++- test cases/common/132 get define/meson.build | 89 ++++++++++--------- 5 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 docs/markdown/snippets/compiler_has_define.md diff --git a/docs/markdown/snippets/compiler_has_define.md b/docs/markdown/snippets/compiler_has_define.md new file mode 100644 index 000000000000..64de26b391ae --- /dev/null +++ b/docs/markdown/snippets/compiler_has_define.md @@ -0,0 +1,10 @@ +## Compilers now have a `has_define` method + +This method returns true if the given preprocessor symbol is +defined, else false is returned. This is useful is cases where +an empty define has to be distinguished from a non-set one, which +is not possible using `get_define`. + +Additionally it makes intent clearer for code that only needs +to check if a specific define is set at all and does not care +about its value. \ No newline at end of file diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index d5d7df5696b4..977cbdf0d72c 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -327,6 +327,17 @@ methods: type: str description: The define to check. +- name: has_define + returns: bool + since: 1.3.0 + description: | + Returns true if the given preprocessor symbol is *defined*. + kwargs_inherit: compiler._common + posargs: + definename: + type: str + description: The define to check. + - name: compiles returns: bool description: Returns true if the code compiles. diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 4999d6054a63..f37bcf441e3a 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -672,13 +672,15 @@ def get_define(self, dname: str, prefix: str, env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], dependencies: T.Optional[T.List['Dependency']], disable_cache: bool = False) -> T.Tuple[str, bool]: - delim = '"MESON_GET_DEFINE_DELIMITER"' + delim_start = '"MESON_GET_DEFINE_DELIMITER_START"\n' + delim_end = '\n"MESON_GET_DEFINE_DELIMITER_END"' + sentinel_undef = '"MESON_GET_DEFINE_UNDEFINED_SENTINEL"' code = f''' {prefix} #ifndef {dname} - # define {dname} + # define {dname} {sentinel_undef} #endif - {delim}\n{dname}''' + {delim_start}{dname}{delim_end}''' args = self.build_wrapper_args(env, extra_args, dependencies, mode=CompileCheckMode.PREPROCESS).to_native() func = functools.partial(self.cached_compile, code, env.coredata, extra_args=args, mode=CompileCheckMode.PREPROCESS) @@ -688,10 +690,21 @@ def get_define(self, dname: str, prefix: str, env: 'Environment', cached = p.cached if p.returncode != 0: raise mesonlib.EnvironmentException(f'Could not get define {dname!r}') - # Get the preprocessed value after the delimiter, - # minus the extra newline at the end and - # merge string literals. - return self._concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]).strip(), cached + + # Get the preprocessed value between the delimiters + star_idx = p.stdout.find(delim_start) + end_idx = p.stdout.rfind(delim_end) + if (star_idx == -1) or (end_idx == -1) or (star_idx == end_idx): + raise AssertionError('BUG: Delimiters not found in preprocessor output!') + define_value = p.stdout[star_idx + len(delim_start):end_idx] + + if define_value == sentinel_undef: + define_value = None + else: + # Merge string literals + define_value = self._concatenate_string_literals(define_value).strip() + + return define_value, cached def get_return_value(self, fname: str, rtype: str, prefix: str, env: 'Environment', extra_args: T.Optional[T.List[str]], diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index b85aa37ed872..b6a1a85f3d81 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -189,6 +189,7 @@ def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'): 'compute_int': self.compute_int_method, 'sizeof': self.sizeof_method, 'get_define': self.get_define_method, + 'has_define': self.has_define_method, 'check_header': self.check_header_method, 'has_header': self.has_header_method, 'has_header_symbol': self.has_header_symbol_method, @@ -475,8 +476,25 @@ def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str: extra_args=extra_args, dependencies=deps) cached_msg = mlog.blue('(cached)') if cached else '' - mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached_msg) - return value + value_msg = '(undefined)' if value is None else value + mlog.log('Fetching value of define', mlog.bold(element, True), msg, value_msg, cached_msg) + return value if value is not None else '' + + @FeatureNew('compiler.has_define', '1.3.0') + @typed_pos_args('compiler.has_define', str) + @typed_kwargs('compiler.has_define', *_COMMON_KWS) + def has_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: + define_name = args[0] + extra_args = functools.partial(self._determine_args, kwargs) + deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None) + value, cached = self.compiler.get_define(define_name, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if cached else '' + h = mlog.green('YES') if value is not None else mlog.red('NO') + mlog.log('Checking if define', mlog.bold(define_name, True), msg, 'exists:', h, cached_msg) + + return value is not None @typed_pos_args('compiler.compiles', (str, mesonlib.File)) @typed_kwargs('compiler.compiles', *_COMPILES_KWS) diff --git a/test cases/common/132 get define/meson.build b/test cases/common/132 get define/meson.build index 02e5a0c956e5..019b17afc933 100644 --- a/test cases/common/132 get define/meson.build +++ b/test cases/common/132 get define/meson.build @@ -2,49 +2,50 @@ project('get define', 'c', 'cpp') host_system = host_machine.system() +system_define_map = { + 'linux' : ['__linux__', '1'], + 'darwin' : ['__APPLE__', '1'], + 'windows' : ['_WIN32', '1'], + 'cygwin' : ['__CYGWIN__', '1'], + 'haiku' : ['__HAIKU__', '1'], + 'dragonfly' : ['__DragonFly__', '1'], + 'netbsd' : ['__NetBSD__', '1'], + 'openbsd' : ['__OpenBSD__', '1'], + 'gnu' : ['__GNU__', '1'], + 'sunos' : ['__sun__', '1'], + + # The __FreeBSD__ define will be equal to the major version of the release + # (ex, in FreeBSD 11.x, __FreeBSD__ == 11). To make the test robust when + # being run on various versions of FreeBSD, just test that the define is + # set. + 'freebsd' : ['__FreeBSD__'], +} + foreach lang : ['c', 'cpp'] cc = meson.get_compiler(lang) - if host_system == 'linux' - d = cc.get_define('__linux__') - assert(d == '1', '__linux__ value is @0@ instead of 1'.format(d)) - elif host_system == 'darwin' - d = cc.get_define('__APPLE__') - assert(d == '1', '__APPLE__ value is @0@ instead of 1'.format(d)) - elif host_system == 'windows' - d = cc.get_define('_WIN32') - assert(d == '1', '_WIN32 value is @0@ instead of 1'.format(d)) - elif host_system == 'cygwin' - d = cc.get_define('__CYGWIN__') - assert(d == '1', '__CYGWIN__ value is @0@ instead of 1'.format(d)) - elif host_system == 'haiku' - d = cc.get_define('__HAIKU__') - assert(d == '1', '__HAIKU__ value is @0@ instead of 1'.format(d)) - elif host_system == 'freebsd' - # the __FreeBSD__ define will be equal to the major version of the release - # (ex, in FreeBSD 11.x, __FreeBSD__ == 11). To make the test robust when - # being run on various versions of FreeBSD, just test that the define is - # set. - d = cc.get_define('__FreeBSD__') - assert(d != '', '__FreeBSD__ value is unset') - elif host_system == 'dragonfly' - d = cc.get_define('__DragonFly__') - assert(d == '1', '__DragonFly__ value is @0@ instead of 1'.format(d)) - elif host_system == 'netbsd' - d = cc.get_define('__NetBSD__') - assert(d == '1', '__NetBSD__ value is @0@ instead of 1'.format(d)) - elif host_system == 'openbsd' - d = cc.get_define('__OpenBSD__') - assert(d == '1', '__OpenBSD__ value is @0@ instead of 1'.format(d)) - elif host_system == 'gnu' - d = cc.get_define('__GNU__') - assert(d == '1', '__GNU__ value is @0@ instead of 1'.format(d)) - elif host_system == 'sunos' - d = cc.get_define('__sun__') - assert(d == '1', '__sun__ value is @0@ instead of 1'.format(d)) - else + + if not system_define_map.has_key(host_system) error('Please report a bug and help us improve support for this platform') endif + system_define = system_define_map.get(host_system) + + def_name = system_define[0] + def_val = cc.get_define(system_define[0]) + def_exist = cc.has_define(system_define[0]) + + assert((def_val != '') == def_exist, + 'The has_define and get_define results for @0@ disagree with each other'.format(def_name)) + + if system_define.length() == 2 + assert(def_val == system_define[1], + '@0@ value is @1@ instead of @2@'.format(def_name, def_val, system_define[1])) + elif system_define.length() == 1 + assert(def_val != '', '@0@ value is unset'.format(def_name)) + else + assert('Invalid number of items in system_define array, this is a bug in the test!') + endif + if cc.find_library('z', required : false).found() # When a C file containing #include is pre-processed and foo.h is # found in the compiler's default search path, GCC inserts an extra comment @@ -63,8 +64,16 @@ foreach lang : ['c', 'cpp'] endif # Check that an undefined value is empty. - have = cc.get_define('MESON_FAIL_VALUE') - assert(have == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have)) + have_val = cc.get_define('MESON_FAIL_VALUE') + have = cc.has_define('MESON_FAIL_VALUE') + assert(have_val == '', 'MESON_FAIL_VALUE value is "@0@" instead of ""'.format(have_val)) + assert(not have, 'MESON_FAIL_VALUE was found even though it should not have been') + + # Check that an empty define is reported as existing. + have_val = cc.get_define('MESON_EMPTY_VALUE', prefix: ['#define MESON_EMPTY_VALUE']) + have = cc.has_define('MESON_EMPTY_VALUE', prefix: ['#define MESON_EMPTY_VALUE']) + assert(have_val == '', 'MESON_EMPTY_VALUE value is "@0@" instead of ""'.format(have_val)) + assert(have, 'MESON_EMPTY_VALUE was not found even though it should have been') # Check if prefix array works properly and has the expected order have = cc.get_define('MESON_FAIL_VALUE', prefix: ['#define MESON_FAIL_VALUE 1', '#undef MESON_FAIL_VALUE']) From d5f17bc9ffea9537057eb249fc68776eb53d5f58 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 3 Sep 2023 12:07:32 -0400 Subject: [PATCH 186/855] Rename OptionOverrideProxy to OptionsView and move to coredata Coredata is where all option handling is done so it makes sense there. It is a view on a list of options for a given subproject and with optional overrides. This change prepare for using that view in a more generic way in the future. --- mesonbuild/build.py | 6 ++--- mesonbuild/compilers/cuda.py | 4 +-- mesonbuild/coredata.py | 46 +++++++++++++++++++++++++++++--- mesonbuild/utils/universal.py | 50 +---------------------------------- 4 files changed, 48 insertions(+), 58 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8fed7853163e..edec75d9097e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -34,7 +34,7 @@ File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, extract_as_list, typeslistify, stringlistify, classify_unity_sources, get_filenames_templates_dict, substitute_values, has_path_sep, - OptionKey, PerMachineDefaultable, OptionOverrideProxy, + OptionKey, PerMachineDefaultable, MesonBugException, EnvironmentVariables, pickle_load, ) from .compilers import ( @@ -535,7 +535,7 @@ def __post_init__(self, overrides: T.Optional[T.Dict[OptionKey, str]]) -> None: for k, v in overrides.items()} else: ovr = {} - self.options = OptionOverrideProxy(ovr, self.environment.coredata.options, self.subproject) + self.options = coredata.OptionsView(self.environment.coredata.options, self.subproject, ovr) # XXX: this should happen in the interpreter if has_path_sep(self.name): # Fix failing test 53 when this becomes an error. @@ -655,7 +655,7 @@ def set_option_overrides(self, option_overrides: T.Dict[OptionKey, str]) -> None else: self.options.overrides[k] = v - def get_options(self) -> OptionOverrideProxy: + def get_options(self) -> coredata.OptionsView: return self.options def get_option(self, key: 'OptionKey') -> T.Union[str, int, bool, 'WrapMode']: diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 8ed7fa41cfcc..09a7d6af0614 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -21,7 +21,7 @@ from .. import coredata from .. import mlog from ..mesonlib import ( - EnvironmentException, Popen_safe, OptionOverrideProxy, + EnvironmentException, Popen_safe, is_windows, LibType, OptionKey, version_compare, ) from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, @@ -650,7 +650,7 @@ def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOpt host_options = {key: options.get(key, opt) for key, opt in self.host_compiler.get_options().items()} std_key = OptionKey('std', machine=self.for_machine, lang=self.host_compiler.language) overrides = {std_key: 'none'} - return OptionOverrideProxy(overrides, host_options) + return coredata.OptionsView(host_options, overrides=overrides) def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args = self.get_ccbin_args(options) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 4b0f9af58d04..f151c7b81f99 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -19,7 +19,9 @@ import sys from itertools import chain from pathlib import PurePath -from collections import OrderedDict +from collections import OrderedDict, abc +from dataclasses import dataclass + from .mesonlib import ( HoldableObject, MesonException, EnvironmentException, MachineChoice, PerMachine, @@ -42,12 +44,12 @@ from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode from .dependencies.detect import TV_DepID from .environment import Environment - from .mesonlib import OptionOverrideProxy, FileOrString + from .mesonlib import FileOrString from .cmake.traceparser import CMakeCacheEntry - OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy] + OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], 'OptionsView'] MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]'] - KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, OptionOverrideProxy] + KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView'] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode] # code, args RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]] @@ -375,6 +377,42 @@ def validate_value(self, value: T.Union[str, T.List[str]]) -> str: raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' + f'Possible values are {self.choices}') +@dataclass +class OptionsView(abc.Mapping): + '''A view on an options dictionary for a given subproject and with overrides. + ''' + + # TODO: the typing here could be made more explicit using a TypeDict from + # python 3.8 or typing_extensions + options: KeyedOptionDictType + subproject: T.Optional[str] = None + overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None + + def __getitem__(self, key: OptionKey) -> UserOption: + # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). + # We should try to share the code somehow. + key = key.evolve(subproject=self.subproject) + if not key.is_project(): + opt = self.options.get(key) + if opt is None or opt.yielding: + opt = self.options[key.as_root()] + else: + opt = self.options[key] + if opt.yielding: + opt = self.options.get(key.as_root(), opt) + if self.overrides: + override_value = self.overrides.get(key.as_root()) + if override_value is not None: + opt = copy.copy(opt) + opt.set_value(override_value) + return opt + + def __iter__(self) -> T.Iterator[OptionKey]: + return iter(self.options) + + def __len__(self) -> int: + return len(self.options) + class DependencyCacheType(enum.Enum): OTHER = 0 diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index d44ec03a8e99..7f0f3852a903 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -29,7 +29,6 @@ from tempfile import TemporaryDirectory, NamedTemporaryFile import typing as T import textwrap -import copy import pickle import errno import json @@ -42,7 +41,7 @@ from .._typing import ImmutableListProtocol from ..build import ConfigurationData - from ..coredata import KeyedOptionDictType, UserOption, StrOrBytesPath + from ..coredata import StrOrBytesPath from ..environment import Environment from ..compilers.compilers import Compiler from ..interpreterbase.baseobjects import SubProject @@ -79,7 +78,6 @@ class _VerPickleLoadable(Protocol): 'GitException', 'OptionKey', 'dump_conf_header', - 'OptionOverrideProxy', 'OptionType', 'OrderedSet', 'PerMachine', @@ -2124,52 +2122,6 @@ def wrapper(*args: T.Any, **kwargs: T.Any) -> T.List[_T]: return wrapper -class OptionOverrideProxy(collections.abc.Mapping): - '''Mimic an option list but transparently override selected option - values. - ''' - - # TODO: the typing here could be made more explicit using a TypeDict from - # python 3.8 or typing_extensions - - def __init__(self, overrides: T.Dict['OptionKey', T.Any], options: 'KeyedOptionDictType', - subproject: T.Optional[str] = None): - self.overrides = overrides - self.options = options - self.subproject = subproject - - def __getitem__(self, key: 'OptionKey') -> 'UserOption': - # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). - # We should try to share the code somehow. - key = key.evolve(subproject=self.subproject) - if not key.is_project(): - opt = self.options.get(key) - if opt is None or opt.yielding: - opt = self.options[key.as_root()] - else: - opt = self.options[key] - if opt.yielding: - opt = self.options.get(key.as_root(), opt) - override_value = self.overrides.get(key.as_root()) - if override_value is not None: - opt = copy.copy(opt) - opt.set_value(override_value) - return opt - - def __iter__(self) -> T.Iterator['OptionKey']: - return iter(self.options) - - def __len__(self) -> int: - return len(self.options) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, OptionOverrideProxy): - return NotImplemented - t1 = (self.overrides, self.subproject, self.options) - t2 = (other.overrides, other.subproject, other.options) - return t1 == t2 - - class OptionType(enum.IntEnum): """Enum used to specify what kind of argument a thing is.""" From 025aea1dab4bcf9aafdd72acf48476d999a729b9 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 3 Sep 2023 12:27:47 -0400 Subject: [PATCH 187/855] Compiler checks must use per-subproject options Fixes: #12202 --- mesonbuild/interpreter/compiler.py | 2 +- .../223 persubproject options/subprojects/sub2/meson.build | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index b6a1a85f3d81..5528abe7ade5 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -261,7 +261,7 @@ def _determine_args(self, kwargs: BaseCompileKW, for idir in i.to_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()): args.extend(self.compiler.get_include_args(idir, False)) if not kwargs['no_builtin_args']: - opts = self.environment.coredata.options + opts = coredata.OptionsView(self.environment.coredata.options, self.subproject) args += self.compiler.get_option_compile_args(opts) if mode is CompileCheckMode.LINK: args.extend(self.compiler.get_option_link_args(opts)) diff --git a/test cases/common/223 persubproject options/subprojects/sub2/meson.build b/test cases/common/223 persubproject options/subprojects/sub2/meson.build index cf1435a4f500..88622207df26 100644 --- a/test cases/common/223 persubproject options/subprojects/sub2/meson.build +++ b/test cases/common/223 persubproject options/subprojects/sub2/meson.build @@ -14,3 +14,7 @@ shared_library('lib1', 'foo.c') # Parent project is c++11 but this one uses c++14 to build. libcpp14 = library('lib2', 'foo.cpp') meson.override_dependency('libcpp14', declare_dependency(link_with: libcpp14)) + +# Compiler checks should be using c++14 as well +cxx = meson.get_compiler('cpp') +assert(cxx.compiles(files('foo.cpp'))) From b2654b2d43089c933e66ab1d3dfb547caecfea71 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 5 Sep 2023 07:49:18 -0400 Subject: [PATCH 188/855] Fix crash when installing a vala library and python sources Installing python sources causes the python module to call create_install_data() before Ninja backends adds extra outputs to Vala targets. Target objects are supposed to be immutable, adding outputs that late is totally wrong. Add extra vala outputs immediately, but be careful because the main output is only added later in post_init(). Luckily the base class already puts a placeholder item in self.outputs for the main filename so we can just replace self.outputs[0] instead of replacing the whole list which would contain vala outputs at that stage. This is surprisingly what SharedLibrary was already doing. --- data/test.schema.json | 1 + mesonbuild/backend/ninjabackend.py | 4 ---- mesonbuild/build.py | 10 ++++++++-- run_project_tests.py | 5 ++++- test cases/vala/7 shared library/lib/meson.build | 5 +++++ test cases/vala/7 shared library/lib/source.py | 0 test cases/vala/7 shared library/test.json | 4 +++- 7 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 test cases/vala/7 shared library/lib/source.py diff --git a/data/test.schema.json b/data/test.schema.json index 98ae44eeb983..b5f6aba629ce 100644 --- a/data/test.schema.json +++ b/data/test.schema.json @@ -27,6 +27,7 @@ "shared_lib", "python_lib", "python_limited_lib", + "python_bytecode", "pdb", "implib", "py_implib", diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 6c739ed0a1bf..491f2a63d834 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1694,8 +1694,6 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ # Without this, it will write it inside c_out_dir args += ['--vapi', os.path.join('..', target.vala_vapi)] valac_outputs.append(vapiname) - target.outputs += [target.vala_header, target.vala_vapi] - target.install_tag += ['devel', 'devel'] # Install header and vapi to default locations if user requests this if len(target.install_dir) > 1 and target.install_dir[1] is True: target.install_dir[1] = self.environment.get_includedir() @@ -1706,8 +1704,6 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ girname = os.path.join(self.get_target_dir(target), target.vala_gir) args += ['--gir', os.path.join('..', target.vala_gir)] valac_outputs.append(girname) - target.outputs.append(target.vala_gir) - target.install_tag.append('devel') # Install GIR to default location if requested by user if len(target.install_dir) > 3 and target.install_dir[3] is True: target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') diff --git a/mesonbuild/build.py b/mesonbuild/build.py index edec75d9097e..09437037a89e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -789,6 +789,12 @@ def post_init(self) -> None: # relocation-model=pic is rustc's default and Meson does not # currently have a way to disable PIC. self.pic = True + if 'vala' in self.compilers and self.is_linkable_target(): + self.outputs += [self.vala_header, self.vala_vapi] + self.install_tag += ['devel', 'devel'] + if self.vala_gir: + self.outputs.append(self.vala_gir) + self.install_tag.append('devel') def __repr__(self): repr_str = "<{0} {1}: {2}>" @@ -1945,7 +1951,7 @@ def post_init(self) -> None: self.filename = self.name if self.suffix: self.filename += '.' + self.suffix - self.outputs = [self.filename] + self.outputs[0] = self.filename # The import library this target will generate self.import_filename = None @@ -2086,7 +2092,7 @@ def post_init(self) -> None: else: self.suffix = 'a' self.filename = self.prefix + self.name + '.' + self.suffix - self.outputs = [self.filename] + self.outputs[0] = self.filename def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: return {} diff --git a/run_project_tests.py b/run_project_tests.py index 446dc12b8e93..8e0af2659899 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -40,6 +40,7 @@ import typing as T import xml.etree.ElementTree as ET import collections +import importlib.util from mesonbuild import build from mesonbuild import environment @@ -169,7 +170,7 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return None # Handle the different types - if self.typ in {'py_implib', 'py_limited_implib', 'python_lib', 'python_limited_lib', 'python_file'}: + if self.typ in {'py_implib', 'py_limited_implib', 'python_lib', 'python_limited_lib', 'python_file', 'python_bytecode'}: val = p.as_posix() val = val.replace('@PYTHON_PLATLIB@', python.platlib) val = val.replace('@PYTHON_PURELIB@', python.purelib) @@ -196,6 +197,8 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return p.with_suffix('.dll.a') else: return None + if self.typ == 'python_bytecode': + return p.parent / importlib.util.cache_from_source(p.name) elif self.typ in {'file', 'dir'}: return p elif self.typ == 'shared_lib': diff --git a/test cases/vala/7 shared library/lib/meson.build b/test cases/vala/7 shared library/lib/meson.build index edeeb96d19bb..bbd3862f1611 100644 --- a/test cases/vala/7 shared library/lib/meson.build +++ b/test cases/vala/7 shared library/lib/meson.build @@ -33,3 +33,8 @@ shared_library('installed_vala_onlyvapi', 'mylib.vala', dependencies : valadeps, install : true, install_dir : [false, false, join_paths(get_option('datadir'), 'vala', 'vapi')]) + +# Regression test: Vala libraries were broken when also installing python modules. +# https://gitlab.gnome.org/GNOME/gitg/-/issues/412 +python = import('python').find_installation() +python.install_sources('source.py') diff --git a/test cases/vala/7 shared library/lib/source.py b/test cases/vala/7 shared library/lib/source.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/vala/7 shared library/test.json b/test cases/vala/7 shared library/test.json index eee3c3dca845..08bd707347c3 100644 --- a/test cases/vala/7 shared library/test.json +++ b/test cases/vala/7 shared library/test.json @@ -9,6 +9,8 @@ {"type": "file", "file": "usr/include/installed_vala_onlyh.h"}, {"type": "file", "file": "usr/share/vala/vapi/installed_vala_all.vapi"}, {"type": "file", "file": "usr/share/vala-1.0/vapi/installed_vala_all_nolib.vapi"}, - {"type": "file", "file": "usr/share/vala/vapi/installed_vala_onlyvapi.vapi"} + {"type": "file", "file": "usr/share/vala/vapi/installed_vala_onlyvapi.vapi"}, + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/source.py"}, + {"type": "python_bytecode", "file": "usr/@PYTHON_PURELIB@/source.py"} ] } From c663476075b18739066e727db9b4f0f4f882b9d1 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 3 Nov 2022 09:08:18 -0400 Subject: [PATCH 189/855] gnome: Fix glib tool lookup consistency It was not always using the pkg-config file. --- mesonbuild/modules/gnome.py | 44 ++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 039e122408bd..aee3af2b085b 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -203,6 +203,8 @@ class MkEnums(_MkEnumsCommon): vtail: T.Optional[str] depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]] + ToolType = T.Union[Executable, ExternalProgram, OverrideProgram] + # Differs from the CustomTarget version in that it straight defaults to True _BUILD_BY_DEFAULT: KwargInfo[bool] = KwargInfo( @@ -317,6 +319,22 @@ def _print_gdbus_warning() -> None: mlog.bold('https://github.com/mesonbuild/meson/issues/1387'), once=True, fatal=False) + @staticmethod + def _find_tool(state: 'ModuleState', tool: str) -> 'ToolType': + tool_map = { + 'gio-querymodules': 'gio-2.0', + 'glib-compile-schemas': 'gio-2.0', + 'glib-compile-resources': 'gio-2.0', + 'gdbus-codegen': 'gio-2.0', + 'glib-genmarshal': 'glib-2.0', + 'glib-mkenums': 'glib-2.0', + 'g-ir-scanner': 'gobject-introspection-1.0', + 'g-ir-compiler': 'gobject-introspection-1.0', + } + depname = tool_map[tool] + varname = tool.replace('-', '_') + return state.find_tool(tool, depname, varname) + @typed_kwargs( 'gnome.post_install', KwargInfo('glib_compile_schemas', bool, default=False), @@ -332,7 +350,7 @@ def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' datadir_abs = os.path.join(state.environment.get_prefix(), state.environment.get_datadir()) if kwargs['glib_compile_schemas'] and not self.install_glib_compile_schemas: self.install_glib_compile_schemas = True - prog = state.find_tool('glib-compile-schemas', 'gio-2.0', 'glib_compile_schemas') + prog = self._find_tool(state, 'glib-compile-schemas') schemasdir = os.path.join(datadir_abs, 'glib-2.0', 'schemas') script = state.backend.get_executable_serialisation([prog, schemasdir]) script.skip_if_destdir = True @@ -340,7 +358,7 @@ def post_install(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' for d in kwargs['gio_querymodules']: if d not in self.install_gio_querymodules: self.install_gio_querymodules.append(d) - prog = state.find_tool('gio-querymodules', 'gio-2.0', 'gio_querymodules') + prog = self._find_tool(state, 'gio-querymodules') moduledir = os.path.join(state.environment.get_prefix(), d) script = state.backend.get_executable_serialisation([prog, moduledir]) script.skip_if_destdir = True @@ -390,8 +408,8 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri self.__print_gresources_warning(state) glib_version = self._get_native_glib_version(state) - glib_compile_resources = state.find_program('glib-compile-resources') - cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [glib_compile_resources, '@INPUT@'] + glib_compile_resources = self._find_tool(state, 'glib-compile-resources') + cmd: T.List[T.Union['ToolType', str]] = [glib_compile_resources, '@INPUT@'] source_dirs = kwargs['source_dir'] dependencies = kwargs['dependencies'] @@ -481,7 +499,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri raise MesonException('GResource header is installed yet export is not enabled') depfile: T.Optional[str] = None - target_cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] + target_cmd: T.List[T.Union['ToolType', str]] if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): # This will eventually go out of sync if dependencies are added target_cmd = cmd @@ -780,8 +798,8 @@ def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[Exec T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]: if not self.gir_dep: self.gir_dep = state.dependency('gobject-introspection-1.0') - self.giscanner = state.find_tool('g-ir-scanner', 'gobject-introspection-1.0', 'g_ir_scanner') - self.gicompiler = state.find_tool('g-ir-compiler', 'gobject-introspection-1.0', 'g_ir_compiler') + self.giscanner = self._find_tool(state, 'g-ir-scanner') + self.gicompiler = self._find_tool(state, 'g-ir-compiler') return self.gir_dep, self.giscanner, self.gicompiler @functools.lru_cache(maxsize=None) @@ -1230,7 +1248,7 @@ def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs srcdir = os.path.join(state.build_to_src, state.subdir) outdir = state.subdir - cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('glib-compile-schemas'), '--targetdir', outdir, srcdir] + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-compile-schemas'), '--targetdir', outdir, srcdir] if state.subdir == '': targetname = 'gsettings-compile' else: @@ -1602,7 +1620,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un kwargs: 'GdbusCodegen') -> ModuleReturnValue: namebase = args[0] xml_files: T.List[T.Union['FileOrString', build.GeneratedTypes]] = [args[1]] if args[1] else [] - cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('gdbus-codegen')] + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'gdbus-codegen')] cmd.extend(kwargs['extra_args']) # Autocleanup supported? @@ -1912,8 +1930,8 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn return ModuleReturnValue([c_file, h_file], [c_file, h_file]) - @staticmethod def _make_mkenum_impl( + self, state: 'ModuleState', sources: T.Sequence[T.Union[str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList]], output: str, @@ -1922,8 +1940,8 @@ def _make_mkenum_impl( install: bool = False, install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None, depends: T.Optional[T.Sequence[T.Union[CustomTarget, CustomTargetIndex, BuildTarget]]] = None - ) -> CustomTarget: - real_cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program(['glib-mkenums', 'mkenums'])] + ) -> build.CustomTarget: + real_cmd: T.List[T.Union[str, 'ToolType']] = [self._find_tool(state, 'glib-mkenums')] real_cmd.extend(cmd) _install_dir = install_dir or state.environment.coredata.get_option(mesonlib.OptionKey('includedir')) assert isinstance(_install_dir, str), 'for mypy' @@ -1968,7 +1986,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') - cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [state.find_program('glib-genmarshal')] + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-genmarshal')] if kwargs['prefix']: cmd.extend(['--prefix', kwargs['prefix']]) if kwargs['extra_args']: From ba1ba1f5b052ff3873045fc8e608cc58bab937b7 Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Sun, 27 Aug 2023 20:14:12 -0400 Subject: [PATCH 190/855] docs: refman: add vim syntax file generator Signed-off-by: Liam Beguin --- docs/refman/generatorvim.py | 37 ++++++++ docs/refman/main.py | 4 +- docs/refman/templates/meson.vim.mustache | 103 +++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 docs/refman/generatorvim.py create mode 100644 docs/refman/templates/meson.vim.mustache diff --git a/docs/refman/generatorvim.py b/docs/refman/generatorvim.py new file mode 100644 index 000000000000..ea725740ffce --- /dev/null +++ b/docs/refman/generatorvim.py @@ -0,0 +1,37 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright 2023 The Meson development team +from __future__ import annotations + +from pathlib import Path + +from .generatorbase import GeneratorBase +from .model import ReferenceManual + + +class GeneratorVim(GeneratorBase): + def __init__(self, manual: ReferenceManual, out_dir: Path) -> None: + super().__init__(manual) + self.out_dir = out_dir + + def generate(self) -> None: + template_dir = Path(__file__).resolve().parent / 'templates' + outname = 'meson.vim' + template_name = f'{outname}.mustache' + template_file = template_dir / template_name + + builtin_funcs = [f.name for f in self.sorted_and_filtered(self.functions)] + data = { + 'builtin_funcs': '\n \\ '.join(builtin_funcs) + } + + # Import here, so that other generators don't also depend on it + import chevron + result = chevron.render( + template=template_file.read_text(encoding='utf-8'), + data=data, + warn=True, + ) + + self.out_dir.mkdir(parents=True, exist_ok=True) + out_file = self.out_dir / outname + out_file.write_text(result, encoding='utf-8') diff --git a/docs/refman/main.py b/docs/refman/main.py index 5727c20c5e6d..9a3d16a610ec 100644 --- a/docs/refman/main.py +++ b/docs/refman/main.py @@ -28,13 +28,14 @@ from .generatorpickle import GeneratorPickle from .generatormd import GeneratorMD from .generatorman import GeneratorMan +from .generatorvim import GeneratorVim meson_root = Path(__file__).absolute().parents[2] def main() -> int: parser = argparse.ArgumentParser(description='Meson reference manual generator') parser.add_argument('-l', '--loader', type=str, default='yaml', choices=['yaml', 'fastyaml', 'pickle'], help='Information loader backend') - parser.add_argument('-g', '--generator', type=str, choices=['print', 'pickle', 'md', 'json', 'man'], required=True, help='Generator backend') + parser.add_argument('-g', '--generator', type=str, choices=['print', 'pickle', 'md', 'json', 'man', 'vim'], required=True, help='Generator backend') parser.add_argument('-s', '--sitemap', type=Path, default=meson_root / 'docs' / 'sitemap.txt', help='Path to the input sitemap.txt') parser.add_argument('-o', '--out', type=Path, required=True, help='Output directory for generated files') parser.add_argument('-i', '--input', type=Path, default=meson_root / 'docs' / 'yaml', help='Input path for the selected loader') @@ -66,6 +67,7 @@ def main() -> int: 'md': lambda: GeneratorMD(refMan, args.out, args.sitemap, args.link_defs, not args.no_modules), 'json': lambda: GeneratorJSON(refMan, args.out, not args.no_modules), 'man': lambda: GeneratorMan(refMan, args.out, not args.no_modules), + 'vim': lambda: GeneratorVim(refMan, args.out), } generator = generators[args.generator]() diff --git a/docs/refman/templates/meson.vim.mustache b/docs/refman/templates/meson.vim.mustache new file mode 100644 index 000000000000..d8f009ee95cb --- /dev/null +++ b/docs/refman/templates/meson.vim.mustache @@ -0,0 +1,103 @@ +" Vim syntax file +" Language: Meson +" License: VIM License +" Maintainer: Nirbheek Chauhan +" Liam Beguin +" Last Change: 2023 Aug 27 +" Credits: Zvezdan Petkovic +" Neil Schemenauer +" Dmitry Vasiliev +" +" This version is copied and edited from python.vim +" It's very basic, and doesn't do many things I'd like it to +" For instance, it should show errors for syntax that is valid in +" Python but not in Meson. +" +" Optional highlighting can be controlled using these variables. +" +" let meson_space_error_highlight = 1 +" + +if exists("b:current_syntax") + finish +endif + +" We need nocompatible mode in order to continue lines with backslashes. +" Original setting will be restored. +let s:cpo_save = &cpo +set cpo&vim + +" http://mesonbuild.com/Syntax.html +syn keyword mesonConditional elif else if endif +syn keyword mesonRepeat foreach endforeach +syn keyword mesonOperator and not or in +syn keyword mesonStatement continue break + +syn match mesonComment "#.*$" contains=mesonTodo,@Spell +syn keyword mesonTodo FIXME NOTE NOTES TODO XXX contained + +" Strings can either be single quoted or triple counted across multiple lines, +" but always with a ' +syn region mesonString + \ start="\z('\)" end="\z1" skip="\\\\\|\\\z1" + \ contains=mesonEscape,@Spell +syn region mesonString + \ start="\z('''\)" end="\z1" keepend + \ contains=mesonEscape,mesonSpaceError,@Spell + +syn match mesonEscape "\\[abfnrtv'\\]" contained +syn match mesonEscape "\\\o\{1,3}" contained +syn match mesonEscape "\\x\x\{2}" contained +syn match mesonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained +" Meson allows case-insensitive Unicode IDs: http://www.unicode.org/charts/ +syn match mesonEscape "\\N{\a\+\%(\s\a\+\)*}" contained +syn match mesonEscape "\\$" + +" Meson only supports integer numbers +" http://mesonbuild.com/Syntax.html#numbers +syn match mesonNumber "\<\d\+\>" +syn match mesonNumber "\<0x\x\+\>" +syn match mesonNumber "\<0o\o\+\>" + +" booleans +syn keyword mesonBoolean false true + +" Built-in functions +syn keyword mesonBuiltin + \ build_machine + \ host_machine + \ meson + \ option + \ target_machine + \ {{builtin_funcs}} + +if exists("meson_space_error_highlight") + " trailing whitespace + syn match mesonSpaceError display excludenl "\s\+$" + " mixed tabs and spaces + syn match mesonSpaceError display " \+\t" + syn match mesonSpaceError display "\t\+ " +endif + +" The default highlight links. Can be overridden later. +hi def link mesonStatement Statement +hi def link mesonConditional Conditional +hi def link mesonRepeat Repeat +hi def link mesonOperator Operator +hi def link mesonComment Comment +hi def link mesonTodo Todo +hi def link mesonString String +hi def link mesonEscape Special +hi def link mesonNumber Number +hi def link mesonBuiltin Function +hi def link mesonBoolean Boolean +if exists("meson_space_error_highlight") + hi def link mesonSpaceError Error +endif + +let b:current_syntax = "meson" + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim:set sw=2 sts=2 ts=8 noet: From 983562c66e9ee28ce4204d69811cd870e2e1960f Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Sun, 27 Aug 2023 13:43:28 -0400 Subject: [PATCH 191/855] syntax-highlighting: vim: update builtin function list Update builtin function list using the refman python docs/genrefman.py \ -g vim \ -o data/syntax-highlighting/vim/syntax/ This also drops gettext() and find_library() from the list of builtin functions that have been deprecated since 2016. Changes are squashed here because test_vim_syntax_highlighting() would validate the file against the list of builtin functions that no longer matches the yaml documentation. Signed-off-by: Liam Beguin --- data/syntax-highlighting/vim/syntax/meson.vim | 20 +++++++++---------- mesonbuild/ast/interpreter.py | 2 -- mesonbuild/interpreter/interpreter.py | 11 ---------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/data/syntax-highlighting/vim/syntax/meson.vim b/data/syntax-highlighting/vim/syntax/meson.vim index 1b576d9bc94e..a1679e0d7105 100644 --- a/data/syntax-highlighting/vim/syntax/meson.vim +++ b/data/syntax-highlighting/vim/syntax/meson.vim @@ -3,7 +3,7 @@ " License: VIM License " Maintainer: Nirbheek Chauhan " Liam Beguin -" Last Change: 2021 Aug 16 +" Last Change: 2023 Aug 27 " Credits: Zvezdan Petkovic " Neil Schemenauer " Dmitry Vasiliev @@ -64,6 +64,11 @@ syn keyword mesonBoolean false true " Built-in functions syn keyword mesonBuiltin + \ build_machine + \ host_machine + \ meson + \ option + \ target_machine \ add_global_arguments \ add_global_link_arguments \ add_languages @@ -75,11 +80,11 @@ syn keyword mesonBuiltin \ assert \ benchmark \ both_libraries - \ build_machine \ build_target \ configuration_data \ configure_file \ custom_target + \ debug \ declare_dependency \ dependency \ disabler @@ -87,30 +92,26 @@ syn keyword mesonBuiltin \ error \ executable \ files - \ find_library \ find_program \ generator \ get_option \ get_variable - \ gettext - \ host_machine \ import \ include_directories \ install_data + \ install_emptydir \ install_headers \ install_man \ install_subdir \ install_symlink - \ install_emptydir \ is_disabler \ is_variable \ jar \ join_paths \ library - \ meson \ message - \ option \ project + \ range \ run_command \ run_target \ set_variable @@ -122,13 +123,10 @@ syn keyword mesonBuiltin \ subdir_done \ subproject \ summary - \ target_machine \ test \ unset_variable \ vcs_tag \ warning - \ range - \ debug if exists("meson_space_error_highlight") " trailing whitespace diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 70a4f1f46e4d..9e098d0be00a 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -148,14 +148,12 @@ def __init__(self, source_root: str, subdir: str, subproject: str, visitors: T.O 'is_disabler': self.func_do_nothing, 'is_variable': self.func_do_nothing, 'disabler': self.func_do_nothing, - 'gettext': self.func_do_nothing, 'jar': self.func_do_nothing, 'warning': self.func_do_nothing, 'shared_module': self.func_do_nothing, 'option': self.func_do_nothing, 'both_libraries': self.func_do_nothing, 'add_test_setup': self.func_do_nothing, - 'find_library': self.func_do_nothing, 'subdir_done': self.func_do_nothing, 'alias_target': self.func_do_nothing, 'summary': self.func_do_nothing, diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 0ba8dc76c5de..5657b2012e10 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -372,12 +372,10 @@ def build_func_dict(self) -> None: 'error': self.func_error, 'executable': self.func_executable, 'files': self.func_files, - 'find_library': self.func_find_library, 'find_program': self.func_find_program, 'generator': self.func_generator, 'get_option': self.func_get_option, 'get_variable': self.func_get_variable, - 'gettext': self.func_gettext, 'import': self.func_import, 'include_directories': self.func_include_directories, 'install_data': self.func_install_data, @@ -848,9 +846,6 @@ def run_command_impl(self, self.environment.get_build_command() + ['introspect'], in_builddir=in_builddir, check=check, capture=capture) - def func_gettext(self, nodes, args, kwargs): - raise InterpreterException('Gettext() function has been moved to module i18n. Import it and use i18n.gettext() instead') - def func_option(self, nodes, args, kwargs): raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.') @@ -1754,12 +1749,6 @@ def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonli silent=False, wanted=kwargs['version'], search_dirs=search_dirs) - def func_find_library(self, node, args, kwargs): - raise InvalidCode('find_library() is removed, use meson.get_compiler(\'name\').find_library() instead.\n' - 'Look here for documentation: http://mesonbuild.com/Reference-manual.html#compiler-object\n' - 'Look here for example: http://mesonbuild.com/howtox.html#add-math-library-lm-portably\n' - ) - # When adding kwargs, please check if they make sense in dependencies.get_dep_identifier() @FeatureNewKwargs('dependency', '0.57.0', ['cmake_package_version']) @FeatureNewKwargs('dependency', '0.56.0', ['allow_fallback']) From 204fe3c5772f3f6ec9583fb9216412a4eb6018b9 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 7 Sep 2023 14:46:11 -0400 Subject: [PATCH 192/855] Fix include_directories test for relative path - On Windows, it was not detected if include directory was an absolute path to source directory, because of the mis of path separators. - In the edgecase the include directory begins with the exact same string as the source directory, but is a different directory, it was falsely reported as an error. Fixes #12217. --- mesonbuild/interpreter/interpreter.py | 6 ++-- run_project_tests.py | 2 ++ test cases/common/18 includedir/meson.build | 28 +++++++++++++++++++ .../common/18 includedirxyz/do_not_delete | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 test cases/common/18 includedirxyz/do_not_delete diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 5657b2012e10..d9a260cff8ea 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -25,7 +25,7 @@ from .. import mesonlib from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject, FileMode, MachineChoice, OptionKey, listify, - extract_as_list, has_path_sep, PerMachine) + extract_as_list, has_path_sep, path_is_in_root, PerMachine) from ..programs import ExternalProgram, NonExistingExternalProgram from ..dependencies import Dependency from ..depfile import DepFile @@ -551,7 +551,7 @@ def add_build_def_file(self, f: mesonlib.FileOrString) -> None: if f.is_built: return f = os.path.normpath(f.relative_name()) - elif os.path.isfile(f) and not f.startswith('/dev'): + elif os.path.isfile(f) and not f.startswith('/dev/'): srcdir = Path(self.environment.get_source_dir()) builddir = Path(self.environment.get_build_dir()) try: @@ -2773,7 +2773,7 @@ def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = Fal absbase_build = os.path.join(build_root, self.subdir) for a in incdir_strings: - if a.startswith(src_root): + if path_is_in_root(Path(a), Path(src_root)): raise InvalidArguments(textwrap.dedent('''\ Tried to form an absolute path to a dir in the source tree. You should not do that but use relative paths instead, for diff --git a/run_project_tests.py b/run_project_tests.py index 8e0af2659899..78fa89c82811 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -942,6 +942,8 @@ def gather_tests(testdir: Path, stdout_mandatory: bool, only: T.List[str], skip_ # Filter non-tests files (dot files, etc) if not t.is_dir() or t.name.startswith('.'): continue + if t.name in {'18 includedirxyz'}: + continue if only and not any(t.name.startswith(prefix) for prefix in only): continue test_def = TestDef(t, None, [], skip_category=skip_category) diff --git a/test cases/common/18 includedir/meson.build b/test cases/common/18 includedir/meson.build index 17eec0e576ff..3180587270c6 100644 --- a/test cases/common/18 includedir/meson.build +++ b/test cases/common/18 includedir/meson.build @@ -2,3 +2,31 @@ project('include dir test', 'c') inc = include_directories('include') subdir('src') + +errormsg = '''Tried to form an absolute path to a dir in the source tree. +You should not do that but use relative paths instead, for +directories that are part of your project. + +To get include path to any directory relative to the current dir do + +incdir = include_directories(dirname) + +After this incdir will contain both the current source dir as well as the +corresponding build dir. It can then be used in any subdirectory and +Meson will take care of all the busywork to make paths work. + +Dirname can even be '.' to mark the current directory. Though you should +remember that the current source and build directories are always +put in the include directories by default so you only need to do +include_directories('.') if you intend to use the result in a +different subdirectory. + +Note that this error message can also be triggered by +external dependencies being installed within your source +tree - it's not recommended to do this. +''' +testcase expect_error(errormsg) + include_directories(meson.current_source_dir() / 'include') +endtestcase +# Test for issue #12217 +include_directories(meson.current_source_dir() + 'xyz') diff --git a/test cases/common/18 includedirxyz/do_not_delete b/test cases/common/18 includedirxyz/do_not_delete new file mode 100644 index 000000000000..8bd0f8805a9d --- /dev/null +++ b/test cases/common/18 includedirxyz/do_not_delete @@ -0,0 +1 @@ +This file is to ensure this directory exists From 6cfd2b4d5bd30b372268c25308b1cb00afd0996d Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 31 Aug 2023 14:13:50 +0530 Subject: [PATCH 193/855] Override config-tool get_variable args for qmake --- mesonbuild/dependencies/configtool.py | 5 ++++- mesonbuild/dependencies/qt.py | 3 +++ test cases/frameworks/4 qt/meson.build | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index 5a4294e7dccc..8dda298d7d78 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -150,8 +150,11 @@ def get_config_value(self, args: T.List[str], stage: str) -> T.List[str]: return [] return split_args(out) + def get_variable_args(self, variable_name: str) -> T.List[str]: + return [f'--{variable_name}'] + def get_configtool_variable(self, variable_name: str) -> str: - p, out, _ = Popen_safe(self.config + [f'--{variable_name}']) + p, out, _ = Popen_safe(self.config + self.get_variable_args(variable_name)) if p.returncode != 0: if self.required: raise DependencyException( diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index 1a86bd28a8ea..ceb0321e5a99 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -350,6 +350,9 @@ def _sanitize_version(self, version: str) -> str: return m.group(0).rstrip('.') return version + def get_variable_args(self, variable_name: str) -> T.List[str]: + return ['-query', f'{variable_name}'] + @abc.abstractmethod def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]: pass diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index 04a5288bf1c4..f8ba1751fb51 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -50,6 +50,9 @@ foreach qt : ['qt4', 'qt5', 'qt6'] qtmodule = import(qt) assert(qtmodule.has_tools()) + # Test that fetching a variable works and yields a non-empty value + assert(qtdep.get_variable('prefix', configtool: 'QT_INSTALL_PREFIX') != '') + # The following has two resource files because having two in one target # requires you to do it properly or you get linker symbol clashes. From 306efbd5b77abdc6ffca27bcb049f3196b7e3451 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 4 Sep 2023 19:35:04 -0400 Subject: [PATCH 194/855] dependencies: fix crash in Qt if private_headers dir not found You cannot listdir() a directory that doesn't exist. This header directory may not exist if suitable devel packages in distros with split devel packages, aren't installed. In theory we could raise a suitable error here. But it would be inconsistent -- we don't otherwise validate that the Qt include directories exist, usually just assuming they do because the dependency was found. And this is niche code inside a non-default special kwarg. At least for pkg-config, it's probably a bug in the distro if pkg-config files exist but the headers don't. The qmake status is less clear. Avoiding a crash means that at the very least, if those headers are in fact directly used by the project, an obvious compiler error occurs instead of a noisy meson traceback. Fixes #12214 --- mesonbuild/dependencies/qt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index ceb0321e5a99..d8a94074bc48 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -53,7 +53,7 @@ def _qt_get_private_includes(mod_inc_dir: str, module: str, mod_version: str) -> private_dir = os.path.join(mod_inc_dir, mod_version) # fallback, let's try to find a directory with the latest version - if not os.path.exists(private_dir): + if os.path.isdir(mod_inc_dir) and not os.path.exists(private_dir): dirs = [filename for filename in os.listdir(mod_inc_dir) if os.path.isdir(os.path.join(mod_inc_dir, filename))] From 3c47216fe945a45834daa38f71e287dcfaf345c7 Mon Sep 17 00:00:00 2001 From: Moody Liu Date: Tue, 5 Sep 2023 00:47:48 +0800 Subject: [PATCH 195/855] clike compilers: fix cross_* functions' include A standard C library may not exist for cross-compile environments, thus the existence of cannot be guaranteed. Use instead, this header contains compiler-specific defines thus it usually comes from the compiler. --- .../snippets/clike_compilers_implicit_includes.md | 13 +++++++++++++ docs/yaml/objects/compiler.yaml | 15 +++++++++++++-- mesonbuild/compilers/mixins/clike.py | 8 +++++--- 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/clike_compilers_implicit_includes.md diff --git a/docs/markdown/snippets/clike_compilers_implicit_includes.md b/docs/markdown/snippets/clike_compilers_implicit_includes.md new file mode 100644 index 000000000000..a26ec0312a7c --- /dev/null +++ b/docs/markdown/snippets/clike_compilers_implicit_includes.md @@ -0,0 +1,13 @@ +## Clarify of implicitly-included headers in C-like compiler checks + +Compiler check methods `compiler.compute_int()`, `compiler.alignment()` +and `compiler.sizeof()` now have their implicitly-included headers +corrected and documented. + +`` was included unintentionally when cross-compiling, which +is less than ideal because there is no guarantee that a standard library +is available for the target platform. Only `` is included instead. + +For projects that depend on the old behavior, the compiler check methods +have an optional argument `prefix`, which can be used to specify additional +`#include` directives. diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index 977cbdf0d72c..239a9bcfd801 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -180,7 +180,11 @@ methods: - name: alignment returns: int - description: Returns the alignment of the specified type. + description: | + Returns the alignment of the specified type. For C-like languages, + For C-like languages, the header `stddef.h` and `stdio.h` are included + implicitly for native compilation, only `stddef.h` is included when + cross-compiling. posargs: typename: @@ -283,6 +287,9 @@ methods: (defaults to -1024), `high` (defaults to 1024) and `guess` to specify max and min values for the search and the value to try first. + For C-like languages, the header `stddef.h` and `stdio.h` are included + implicitly for native compilation, only `stddef.h` is included when + cross-compiling. posargs: expr: @@ -304,7 +311,11 @@ methods: - name: sizeof returns: int - description: returns the size of the given type (e.g. `'int'`) or -1 if the type is unknown. + description: | + returns the size of the given type (e.g. `'int'`) or -1 if the type is unknown. + For C-like languages, the header `stddef.h` and `stdio.h` are included + implicitly for native compilation, only `stddef.h` is included when + cross-compiling. kwargs_inherit: compiler._common posargs: typename: diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index f37bcf441e3a..61e671921e6a 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -502,7 +502,7 @@ def _compile_int(self, expression: str, prefix: str, env: 'Environment', extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], dependencies: T.Optional[T.List['Dependency']]) -> bool: t = f'''{prefix} - #include + #include int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' return self.compiles(t, env, extra_args=extra_args, dependencies=dependencies)[0] @@ -563,6 +563,7 @@ def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[in if self.is_cross: return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies) t = f'''{prefix} + #include #include int main(void) {{ printf("%ld\\n", (long)({expression})); @@ -582,7 +583,7 @@ def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *, if extra_args is None: extra_args = [] t = f'''{prefix} - #include + #include int main(void) {{ {typename} something; return 0; @@ -602,6 +603,7 @@ def sizeof(self, typename: str, prefix: str, env: 'Environment', *, dependencies=dependencies) return r, False t = f'''{prefix} + #include #include int main(void) {{ printf("%ld\\n", (long)(sizeof({typename}))); @@ -621,7 +623,7 @@ def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *, if extra_args is None: extra_args = [] t = f'''{prefix} - #include + #include int main(void) {{ {typename} something; return 0; From b51bce070eead2b65e56f087acf23829a6304ae2 Mon Sep 17 00:00:00 2001 From: Nicholas Vinson Date: Mon, 4 Sep 2023 13:04:00 -0400 Subject: [PATCH 196/855] Add macro_name option to configure_file Allow macro_name to be speficied as a parameter to configure_file(). This allows C macro-style include guards to be added to configure_file()'s output when a template file is not given. This change simplifies the creation of configure files that define macros with dynamic names and want the C-style include guards. --- .../snippets/configure_file_macro_guard.md | 6 +++++ docs/yaml/functions/configure_file.yaml | 7 ++++++ mesonbuild/interpreter/interpreter.py | 4 +++- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/utils/universal.py | 19 +++++++++++---- .../expected/config.mg | 23 +++++++++++++++++++ .../meson.build | 9 ++++++++ 7 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 docs/markdown/snippets/configure_file_macro_guard.md create mode 100644 test cases/common/269 configure file output format/expected/config.mg diff --git a/docs/markdown/snippets/configure_file_macro_guard.md b/docs/markdown/snippets/configure_file_macro_guard.md new file mode 100644 index 000000000000..ebb4fc554936 --- /dev/null +++ b/docs/markdown/snippets/configure_file_macro_guard.md @@ -0,0 +1,6 @@ +## [[configure_file]] now has a `macro_name` parameter. + +This new paramater, `macro_name` allows C macro-style include guards to be added +to [[configure_file]]'s output when a template file is not given. This change +simplifies the creation of configure files that define macros with dynamic names +and want the C-style include guards. diff --git a/docs/yaml/functions/configure_file.yaml b/docs/yaml/functions/configure_file.yaml index 6fb972b3e6d8..34cb3c1bd8b3 100644 --- a/docs/yaml/functions/configure_file.yaml +++ b/docs/yaml/functions/configure_file.yaml @@ -144,3 +144,10 @@ kwargs: Set the file encoding for the input and output file. The supported encodings are those of python3, see [standard-encodings](https://docs.python.org/3/library/codecs.html#standard-encodings). + + macro_name: + type: str + since: 1.3.0 + description: | + When specified, macro guards will be used instead of '#pragma once'. The + macro guard name will be the specified name. diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d9a260cff8ea..9b005cb7899c 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2585,6 +2585,7 @@ def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], OUTPUT_KW, KwargInfo('output_format', str, default='c', since='0.47.0', since_values={'json': '1.3.0'}, validator=in_set_validator({'c', 'json', 'nasm'})), + KwargInfo('macro_name', (str, NoneType), default=None, since='1.3.0'), ) def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], kwargs: kwtypes.ConfigureFile): @@ -2676,7 +2677,8 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var], 'copy a file to the build dir, use the \'copy:\' keyword ' 'argument added in 0.47.0', location=node) else: - mesonlib.dump_conf_header(ofile_abs, conf, output_format) + macro_name = kwargs['macro_name'] + mesonlib.dump_conf_header(ofile_abs, conf, output_format, macro_name) conf.used = True elif kwargs['command'] is not None: if len(inputs) > 1: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 0aee16432c43..1aee41435d38 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -296,6 +296,7 @@ class ConfigureFile(TypedDict): command: T.Optional[T.List[T.Union[build.Executable, ExternalProgram, Compiler, File, str]]] input: T.List[FileOrString] configuration: T.Optional[T.Union[T.Dict[str, T.Union[str, int, bool]], build.ConfigurationData]] + macro_name: T.Optional[str] class Subproject(ExtractRequired): diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 7f0f3852a903..1d0e382a835d 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1351,7 +1351,7 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', * Do not edit, your changes will be lost. */ -#pragma once +{} ''' @@ -1360,10 +1360,16 @@ def do_conf_file(src: str, dst: str, confdata: 'ConfigurationData', ''' -def _dump_c_header(ofile: T.TextIO, cdata: ConfigurationData, output_format: Literal['c', 'nasm']) -> None: +def _dump_c_header(ofile: T.TextIO, + cdata: ConfigurationData, + output_format: Literal['c', 'nasm'], + macro_name: T.Optional[str]) -> None: format_desc: T.Callable[[str], str] if output_format == 'c': - prelude = CONF_C_PRELUDE + if macro_name: + prelude = CONF_C_PRELUDE.format('#ifndef {0}\n#define {0}'.format(macro_name)) + else: + prelude = CONF_C_PRELUDE.format('#pragma once') prefix = '#' format_desc = lambda desc: f'/* {desc} */\n' else: # nasm @@ -1385,17 +1391,20 @@ def _dump_c_header(ofile: T.TextIO, cdata: ConfigurationData, output_format: Lit ofile.write(f'{prefix}define {k} {v}\n\n') else: raise MesonException('Unknown data type in configuration file entry: ' + k) + if output_format == 'c' and macro_name: + ofile.write('#endif\n') def dump_conf_header(ofilename: str, cdata: ConfigurationData, - output_format: Literal['c', 'nasm', 'json']) -> None: + output_format: Literal['c', 'nasm', 'json'], + macro_name: T.Optional[str]) -> None: ofilename_tmp = ofilename + '~' with open(ofilename_tmp, 'w', encoding='utf-8') as ofile: if output_format == 'json': data = {k: v[0] for k, v in cdata.values.items()} json.dump(data, ofile, sort_keys=True) else: # c, nasm - _dump_c_header(ofile, cdata, output_format) + _dump_c_header(ofile, cdata, output_format, macro_name) replace_if_different(ofilename, ofilename_tmp) diff --git a/test cases/common/269 configure file output format/expected/config.mg b/test cases/common/269 configure file output format/expected/config.mg new file mode 100644 index 000000000000..ccdb4e720f3f --- /dev/null +++ b/test cases/common/269 configure file output format/expected/config.mg @@ -0,0 +1,23 @@ +/* + * Autogenerated by the Meson build system. + * Do not edit, your changes will be lost. + */ + +#ifndef CONFIG_MAGNESIUM_H +#define CONFIG_MAGNESIUM_H + +#define bool + +#undef false + +/* ultimate question of life, the universe, and everything */ +#define int 42 + +/* This is +a multiline +description */ +#define str "hello world!" + +#define unquoted float + +#endif diff --git a/test cases/common/269 configure file output format/meson.build b/test cases/common/269 configure file output format/meson.build index 796b9d6a26cb..17650e3c0654 100644 --- a/test cases/common/269 configure file output format/meson.build +++ b/test cases/common/269 configure file output format/meson.build @@ -27,12 +27,21 @@ config_json = configure_file( output: 'config.json' ) +config_mg = configure_file( + configuration: data, + macro_name: 'CONFIG_MAGNESIUM_H', + output_format: 'c', + output: 'config_mg.h' +) + py = find_program('python3') compare_py = files('compare.py') expected_config_h = files('expected/config.h') expected_config_nasm = files('expected/config.nasm') expected_config_json = files('expected/config.json') +expected_config_mg = files('expected/config.mg') test('c_output', py, args: [compare_py, expected_config_h, config_h]) test('nasm_output', py, args: [compare_py, expected_config_nasm, config_nasm]) test('json_output', py, args: [compare_py, expected_config_json, config_json]) +test('c_mg_output', py, args: [compare_py, expected_config_mg, config_mg]) From 5f46ea116c6f80edd3633c03aacd7427ef3d0cec Mon Sep 17 00:00:00 2001 From: Nomura Date: Thu, 7 Sep 2023 20:26:20 +0200 Subject: [PATCH 197/855] Add support for padding zeroes in int.to_string() method --- docs/markdown/snippets/int_to_string_fill.md | 20 +++++++++++++++++++ docs/yaml/elementary/int.yml | 12 +++++++++++ mesonbuild/interpreter/primitives/integer.py | 13 +++++++----- .../common/270 int_to_str_fill/meson.build | 9 +++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/int_to_string_fill.md create mode 100644 test cases/common/270 int_to_str_fill/meson.build diff --git a/docs/markdown/snippets/int_to_string_fill.md b/docs/markdown/snippets/int_to_string_fill.md new file mode 100644 index 000000000000..2b0d250858f9 --- /dev/null +++ b/docs/markdown/snippets/int_to_string_fill.md @@ -0,0 +1,20 @@ +## Added 'fill' kwarg to int.to_string() + +int.to_string() now accepts a `fill` argument. This allows you to pad the +string representation of the integer with leading zeroes: + +```meson +n = 4 +message(n.to_string()) +message(n.to_string(length: 3)) + +n = -4 +message(n.to_string(length: 3)) +``` + +OUTPUT: +```meson +4 +004 +-04 +``` \ No newline at end of file diff --git a/docs/yaml/elementary/int.yml b/docs/yaml/elementary/int.yml index 65ab959d36f7..f8d8e2586c9e 100644 --- a/docs/yaml/elementary/int.yml +++ b/docs/yaml/elementary/int.yml @@ -14,3 +14,15 @@ methods: - name: to_string returns: str description: Returns the value of the number as a string. + + optargs: + fill: + type: int + description: | + Left fill the string with zeros until it reaches the length + specified by this argument. A leading negative sign counts towards + the length, and is handled by inserting the padding after the `-` + character rather than before. The original string is returned if the + value provided is less than or equal to the former's length. + + diff --git a/mesonbuild/interpreter/primitives/integer.py b/mesonbuild/interpreter/primitives/integer.py index b7f353210134..50def2cb7b19 100644 --- a/mesonbuild/interpreter/primitives/integer.py +++ b/mesonbuild/interpreter/primitives/integer.py @@ -3,8 +3,8 @@ from __future__ import annotations from ...interpreterbase import ( - FeatureBroken, InvalidArguments, MesonOperator, ObjectHolder, - noKwargs, noPosargs, typed_operator, + FeatureBroken, InvalidArguments, MesonOperator, ObjectHolder, KwargInfo, + noKwargs, noPosargs, typed_operator, typed_kwargs ) import typing as T @@ -65,10 +65,13 @@ def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: def is_odd_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool: return self.held_object % 2 != 0 - @noKwargs + @typed_kwargs( + 'to_string', + KwargInfo('fill', int, default=0, since='1.3.0') + ) @noPosargs - def to_string_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: - return str(self.held_object) + def to_string_method(self, args: T.List[TYPE_var], kwargs: T.Dict[str, T.Any]) -> str: + return str(self.held_object).zfill(kwargs['fill']) @typed_operator(MesonOperator.DIV, int) def op_div(self, other: int) -> int: diff --git a/test cases/common/270 int_to_str_fill/meson.build b/test cases/common/270 int_to_str_fill/meson.build new file mode 100644 index 000000000000..a549d941edf4 --- /dev/null +++ b/test cases/common/270 int_to_str_fill/meson.build @@ -0,0 +1,9 @@ +project('test_fill_in_int_to_string') + +n = 4 +assert(n.to_string() == '4') +assert(n.to_string(fill: 3) == '004') +assert(n.to_string(fill: -3) == '4') + +n = -4 +assert(n.to_string(fill: 3) == '-04') From 10708676ade79037f2d2ceeb98500a40a977abef Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 25 Sep 2022 13:51:07 -0400 Subject: [PATCH 198/855] gnome.mkenum_simple(): Fix include path when header is in subdir It was generating #include with the basename of every header file. That assumes that every directory where there are headers are also included into search path when compiling the .c file. Change to use path relative to current subdir, which can be both in build or source directory. That means that we assume that when the .c file is compiled, the target has a include_directories pointing to the directory where gnome.mkenum_simple() has been called, which is generally '.' and added automatically. Also fix type annotation to only allow str and File sources, other types have never been working, it would require to iterate over custom target outputs, etc. Fixes: #7582 --- docs/markdown/Gnome-module.md | 7 +++++ mesonbuild/modules/gnome.py | 27 ++++++++++++------- .../frameworks/7 gnome/mkenums/meson.build | 10 +++++++ .../frameworks/7 gnome/mkenums/subdir/h2.h.in | 5 ++++ .../frameworks/7 gnome/mkenums/subdir/h3.h | 5 ++++ .../7 gnome/mkenums/subdir/meson.build | 2 ++ 6 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 test cases/frameworks/7 gnome/mkenums/subdir/h2.h.in create mode 100644 test cases/frameworks/7 gnome/mkenums/subdir/h3.h create mode 100644 test cases/frameworks/7 gnome/mkenums/subdir/meson.build diff --git a/docs/markdown/Gnome-module.md b/docs/markdown/Gnome-module.md index d0cd24a046e6..013e8c8241ce 100644 --- a/docs/markdown/Gnome-module.md +++ b/docs/markdown/Gnome-module.md @@ -204,6 +204,13 @@ for a build target, you must add the generated header to the build target's list of sources to codify the dependency. This is true for all generated sources, not just `mkenums_simple`. +The generated source file includes all headers passed to the sources keyword +argument, using paths relative to current build or source directory. That means +that targets that compile the generated source file must have the current +directory in its `include_directories`. *Since 1.3.0* `sources` outside of +current directory do not require adding those directories into +`include_directories` anymore. + * `body_prefix`: additional prefix at the top of the body file, e.g. for extra includes * `decorator`: optional decorator for the function declarations, diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index aee3af2b085b..7de9d46b39f5 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -176,7 +176,6 @@ class GenerateVapi(TypedDict): class _MkEnumsCommon(TypedDict): - sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] install_header: bool install_dir: T.Optional[str] identifier_prefix: T.Optional[str] @@ -184,6 +183,7 @@ class _MkEnumsCommon(TypedDict): class MkEnumsSimple(_MkEnumsCommon): + sources: T.List[FileOrString] header_prefix: str decorator: str function_prefix: str @@ -191,6 +191,7 @@ class MkEnumsSimple(_MkEnumsCommon): class MkEnums(_MkEnumsCommon): + sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] c_template: T.Optional[FileOrString] h_template: T.Optional[FileOrString] comments: T.Optional[str] @@ -221,12 +222,6 @@ class MkEnums(_MkEnumsCommon): _MK_ENUMS_COMMON_KWS: T.List[KwargInfo] = [ INSTALL_KW.evolve(name='install_header'), INSTALL_DIR_KW, - KwargInfo( - 'sources', - ContainerTypeInfo(list, (str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList)), - listify=True, - required=True, - ), KwargInfo('identifier_prefix', (str, NoneType)), KwargInfo('symbol_prefix', (str, NoneType)), ] @@ -1749,6 +1744,13 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un 'gnome.mkenums', *_MK_ENUMS_COMMON_KWS, DEPENDS_KW, + KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, mesonlib.File, CustomTarget, CustomTargetIndex, + GeneratedList)), + listify=True, + required=True, + ), KwargInfo('c_template', (str, mesonlib.File, NoneType)), KwargInfo('h_template', (str, mesonlib.File, NoneType)), KwargInfo('comments', (str, NoneType)), @@ -1824,6 +1826,12 @@ def mkenums(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEnums') - @typed_kwargs( 'gnome.mkenums_simple', *_MK_ENUMS_COMMON_KWS, + KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, mesonlib.File)), + listify=True, + required=True, + ), KwargInfo('header_prefix', str, default=''), KwargInfo('function_prefix', str, default=''), KwargInfo('body_prefix', str, default=''), @@ -1851,8 +1859,9 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn if body_prefix != '': fhead += '%s\n' % body_prefix fhead += '#include "%s"\n' % hdr_filename - for hdr in kwargs['sources']: - fhead += '#include "{}"\n'.format(os.path.basename(str(hdr))) + for hdr in self.interpreter.source_strings_to_files(kwargs['sources']): + hdr_path = os.path.relpath(hdr.relative_name(), state.subdir) + fhead += f'#include "{hdr_path}"\n' fhead += textwrap.dedent( ''' #define C_ENUM(v) ((gint) v) diff --git a/test cases/frameworks/7 gnome/mkenums/meson.build b/test cases/frameworks/7 gnome/mkenums/meson.build index 4cf4dcf8a01a..2886be91ab23 100644 --- a/test cases/frameworks/7 gnome/mkenums/meson.build +++ b/test cases/frameworks/7 gnome/mkenums/meson.build @@ -162,3 +162,13 @@ main = configure_file( enumexe6 = executable('enumprog6', main, enums_c2, enums_h6, dependencies : gobj) test('enum test 4', enumexe6) + +# Test with headers coming from other directories +# https://github.com/mesonbuild/meson/pull/10855 +subdir('subdir') +enums7 = gnome.mkenums_simple('enums7', sources: ['meson-sample.h', h2, h3]) +main = configure_file( + input : 'main.c', + output : 'mai7.c', + configuration : {'ENUM_FILE': 'enums7.h'}) +test('enums7 test', executable('enumprog7', main, enums7, dependencies : gobj)) diff --git a/test cases/frameworks/7 gnome/mkenums/subdir/h2.h.in b/test cases/frameworks/7 gnome/mkenums/subdir/h2.h.in new file mode 100644 index 000000000000..7b40c4be1c87 --- /dev/null +++ b/test cases/frameworks/7 gnome/mkenums/subdir/h2.h.in @@ -0,0 +1,5 @@ +#pragma once + +typedef enum { + MESON_SUBDIR_FOO, +} MesonSubdir; diff --git a/test cases/frameworks/7 gnome/mkenums/subdir/h3.h b/test cases/frameworks/7 gnome/mkenums/subdir/h3.h new file mode 100644 index 000000000000..9049d5c225b3 --- /dev/null +++ b/test cases/frameworks/7 gnome/mkenums/subdir/h3.h @@ -0,0 +1,5 @@ +#pragma once + +typedef enum { + MESON_SUBDIR2_FOO, +} MesonSubdir2; diff --git a/test cases/frameworks/7 gnome/mkenums/subdir/meson.build b/test cases/frameworks/7 gnome/mkenums/subdir/meson.build new file mode 100644 index 000000000000..0b03846f20b4 --- /dev/null +++ b/test cases/frameworks/7 gnome/mkenums/subdir/meson.build @@ -0,0 +1,2 @@ +h2 = configure_file(input: 'h2.h.in', output: 'h2.h', copy: true) +h3 = files('h3.h') From bd3341f8085686863cb1160f2ab72e6fd6bf47c7 Mon Sep 17 00:00:00 2001 From: Dan Hawson <18214721+GertyP@users.noreply.github.com> Date: Sat, 15 Jul 2023 10:39:37 +0100 Subject: [PATCH 199/855] Recognise more include search path opts when populating 'NMakeIncludeSearchPath' to help intellisense Added to existing '/I' and '-I' extraction with '-isystem', '/clang:-isystem', '/imsvc', '/external:I', which are forms of 'system' header include search path options for gcc, clang, clang-cl, and cl (msvc). Factored 3 separate 'extract_...(...)' functions into one since they were always called together on the same args; a new combined '_extract_nmake_fields(...)' func avoids repeated iterations and checks. --- mesonbuild/backend/vs2010backend.py | 73 +++++++++++++---------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 0a382be22551..bb72594c4d59 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -137,10 +137,7 @@ def get_non_primary_lang_intellisense_fields(vslite_ctx: dict, for src_lang, args_list in non_primary_build_args_per_src_lang: if src_lang not in defs_paths_opts_per_lang_and_buildtype: defs_paths_opts_per_lang_and_buildtype[src_lang] = {} - defs = Vs2010Backend.extract_nmake_preprocessor_defs(args_list) - paths = Vs2010Backend.extract_nmake_include_paths(args_list) - opts = Vs2010Backend.extract_intellisense_additional_compiler_options(args_list) - defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = (defs, paths, opts) + defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = Vs2010Backend._extract_nmake_fields(args_list) return defs_paths_opts_per_lang_and_buildtype class Vs2010Backend(backends.Backend): @@ -1172,44 +1169,39 @@ def get_build_args(compiler, buildtype: str, optimization_level: str, debug: boo return build_args - #Convert a list of compile arguments from - - # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] - #to - - # 'SOME_DEF=1;ANOTHER_DEF=someval;' - #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. + # Used in populating a simple nmake-style project's intellisense fields. + # Given a list of compile args, for example - + # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] + # returns a tuple of pre-processor defs (for this example) - + # 'SOME_DEF=1;ANOTHER_DEF=someval;' + # and include paths, e.g. - + # '..\\some\\dir\\include;../../some/other/dir;' + # and finally any remaining compiler options, e.g. - + # '/MDd;/W2;/std:c++17;/Od/Zi' @staticmethod - def extract_nmake_preprocessor_defs(captured_build_args: list[str]) -> str: - defs = '' - for arg in captured_build_args: - if arg.startswith(('-D', '/D')): - defs += arg[2:] + ';' - return defs + def _extract_nmake_fields(captured_build_args: list[str]) -> T.Tuple[str, str, str]: + include_dir_options = [ + '-I', + '/I', + '-isystem', # regular gcc / clang option to denote system header include search paths + '/clang:-isystem', # clang-cl (msvc 'cl'-style clang wrapper) option to pass '-isystem' option to clang driver + '/imsvc', # clang-cl option to 'Add directory to system include search path' + '/external:I', # msvc cl option to add 'external' include search paths + ] - #Convert a list of compile arguments from - - # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] - #to - - # '..\\some\\dir\\include;../../some/other/dir;' - #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. - @staticmethod - def extract_nmake_include_paths(captured_build_args: list[str]) -> str: + defs = '' paths = '' - for arg in captured_build_args: - if arg.startswith(('-I', '/I')): - paths += arg[2:] + ';' - return paths - - #Convert a list of compile arguments from - - # [ '-I..\\some\\dir\\include', '-I../../some/other/dir', '/MDd', '/W2', '/std:c++17', '/Od', '/Zi', '-DSOME_DEF=1', '-DANOTHER_DEF=someval', ...] - #to - - # '/MDd;/W2;/std:c++17;/Od/Zi' - #which is the format required by the visual studio project's NMakePreprocessorDefinitions field. - @staticmethod - def extract_intellisense_additional_compiler_options(captured_build_args: list[str]) -> str: additional_opts = '' for arg in captured_build_args: - if (not arg.startswith(('-D', '/D', '-I', '/I'))) and arg.startswith(('-', '/')): - additional_opts += arg + ';' - return additional_opts + if arg.startswith(('-D', '/D')): + defs += arg[2:] + ';' + else: + opt_match = next((opt for opt in include_dir_options if arg.startswith(opt)), None) + if opt_match: + paths += arg[len(opt_match):] + ';' + elif arg.startswith(('-', '/')): + additional_opts += arg + ';' + return (defs, paths, additional_opts) @staticmethod def get_nmake_base_meson_command_and_exe_search_paths() -> T.Tuple[str, str]: @@ -1300,9 +1292,10 @@ def add_gen_lite_makefile_vcxproj_elements(self, # We may not have any src files and so won't have a primary src language. In which case, we've nothing to fill in for this target's intellisense fields - if primary_src_lang: primary_src_type_build_args = captured_build_args[primary_src_lang] - ET.SubElement(per_config_prop_group, 'NMakePreprocessorDefinitions').text = Vs2010Backend.extract_nmake_preprocessor_defs(primary_src_type_build_args) - ET.SubElement(per_config_prop_group, 'NMakeIncludeSearchPath').text = Vs2010Backend.extract_nmake_include_paths(primary_src_type_build_args) - ET.SubElement(per_config_prop_group, 'AdditionalOptions').text = Vs2010Backend.extract_intellisense_additional_compiler_options(primary_src_type_build_args) + preproc_defs, inc_paths, other_compile_opts = Vs2010Backend._extract_nmake_fields(primary_src_type_build_args) + ET.SubElement(per_config_prop_group, 'NMakePreprocessorDefinitions').text = preproc_defs + ET.SubElement(per_config_prop_group, 'NMakeIncludeSearchPath').text = inc_paths + ET.SubElement(per_config_prop_group, 'AdditionalOptions').text = other_compile_opts # Unless we explicitly specify the following empty path elements, the project is assigned a load of nasty defaults that fill these # with values like - From 79ed2415e9a50e5181b203790ec057c6229609a3 Mon Sep 17 00:00:00 2001 From: JCWasmx86 Date: Mon, 31 Oct 2022 16:47:40 +0100 Subject: [PATCH 200/855] Add ParenthesizedNode --- mesonbuild/ast/visitor.py | 4 ++++ mesonbuild/interpreterbase/interpreterbase.py | 2 ++ mesonbuild/mparser.py | 11 ++++++++++- mesonbuild/optinterpreter.py | 2 ++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 8a0e77bb8e3b..51a662024454 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -144,3 +144,7 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: for key, val in node.kwargs.items(): key.accept(self) val.accept(self) + + def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: + self.visit_default_func(node) + node.inner.accept(self) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 902f84a45fd3..f35da33bd2f5 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -239,6 +239,8 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj raise ContinueRequest() elif isinstance(cur, mparser.BreakNode): raise BreakRequest() + elif isinstance(cur, mparser.ParenthesizedNode): + return self.evaluate_statement(cur.inner) elif isinstance(cur, mparser.TestCaseClauseNode): return self.evaluate_testcase(cur) else: diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index fb4e4336795f..3697d8a1a879 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -577,6 +577,15 @@ def __init__(self, condition: BaseNode, trueblock: BaseNode, falseblock: BaseNod self.trueblock = trueblock self.falseblock = falseblock +@dataclass(unsafe_hash=True) +class ParenthesizedNode(BaseNode): + + inner: BaseNode + + def __init__(self, inner: BaseNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + super().__init__(lineno, colno, inner.filename, end_lineno=end_lineno, end_colno=end_colno) + self.inner = inner + if T.TYPE_CHECKING: COMPARISONS = Literal['==', '!=', '<', '<=', '>=', '>', 'in', 'notin'] @@ -778,7 +787,7 @@ def e8(self) -> BaseNode: if self.accept('lparen'): e = self.statement() self.block_expect('rparen', block_start) - return e + return ParenthesizedNode(e, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) elif self.accept('lbracket'): args = self.args() self.block_expect('rbracket', block_start) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 8ad84aaa8331..37ef55ab0673 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -113,6 +113,8 @@ def process(self, option_file: str) -> None: def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var': if isinstance(arg, str): return arg + if isinstance(arg, mparser.ParenthesizedNode): + return self.reduce_single(arg.inner) elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, mparser.NumberNode)): return arg.value From 3ff3b8abf6f24f676b6c03250ba96a365ae77b03 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 22 Aug 2023 22:05:40 -0400 Subject: [PATCH 201/855] parser: more specific error for float numbers --- mesonbuild/mparser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 3697d8a1a879..9867c7164fd3 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -863,6 +863,9 @@ def args(self) -> ArgumentNode: def method_call(self, source_object: BaseNode) -> MethodNode: methodname = self.e9() if not isinstance(methodname, IdNode): + if isinstance(source_object, NumberNode) and isinstance(methodname, NumberNode): + raise ParseException('meson does not support float numbers', + self.getline(), source_object.lineno, source_object.colno) raise ParseException('Method name must be plain id', self.getline(), self.current.lineno, self.current.colno) assert isinstance(methodname.value, str) From 5707d390174b7e8db431bc9cee2257043ea59f84 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 09:32:21 -0400 Subject: [PATCH 202/855] parser: preserve number base --- mesonbuild/cargo/builder.py | 2 +- mesonbuild/cmake/interpreter.py | 2 +- mesonbuild/mparser.py | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index fb086d1640ef..2442fbfa76a2 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -45,7 +45,7 @@ def number(value: int, filename: str) -> mparser.NumberNode: :param filename: the file that the value came from :return: A NumberNode """ - return mparser.NumberNode(_token('number', filename, value)) + return mparser.NumberNode(_token('number', filename, str(value))) def bool(value: builtins.bool, filename: str) -> mparser.BooleanNode: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index f88d091ab15b..f577ba774a64 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -966,7 +966,7 @@ def id_node(value: str) -> IdNode: return IdNode(token(val=value)) def number(value: int) -> NumberNode: - return NumberNode(token(val=value)) + return NumberNode(token(val=str(value))) def nodeify(value: TYPE_mixed_list) -> BaseNode: if isinstance(value, str): diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 9867c7164fd3..5ab76e7dcacc 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -217,7 +217,7 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: lineno += len(lines) - 1 line_start = mo.end() - len(lines[-1]) elif tid == 'number': - value = int(match_text, base=0) + value = match_text elif tid == 'eol_cont': lineno += 1 line_start = loc @@ -285,8 +285,16 @@ class IdNode(ElementaryNode[str]): def __str__(self) -> str: return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) +@dataclass(unsafe_hash=True) class NumberNode(ElementaryNode[int]): - pass + + raw_value: str = field(hash=False) + + def __init__(self, token: Token[str]): + BaseNode.__init__(self, token.lineno, token.colno, token.filename) + self.raw_value = token.value + self.value = int(token.value, base=0) + self.bytespan = token.bytespan class StringNode(ElementaryNode[str]): def __str__(self) -> str: From a730a2fe215ae45c928370b5e28d2a844c082f38 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 15:51:58 -0400 Subject: [PATCH 203/855] parser: remove useless __str__ methods on nodes --- mesonbuild/mparser.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 5ab76e7dcacc..f9b896759b1d 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -282,8 +282,7 @@ class BooleanNode(ElementaryNode[bool]): pass class IdNode(ElementaryNode[str]): - def __str__(self) -> str: - return "Id node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + pass @dataclass(unsafe_hash=True) class NumberNode(ElementaryNode[int]): @@ -297,16 +296,13 @@ def __init__(self, token: Token[str]): self.bytespan = token.bytespan class StringNode(ElementaryNode[str]): - def __str__(self) -> str: - return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno) + pass class FormatStringNode(ElementaryNode[str]): - def __str__(self) -> str: - return f"Format string node: '{self.value}' ({self.lineno}, {self.colno})." + pass class MultilineFormatStringNode(FormatStringNode): - def __str__(self) -> str: - return f"Multiline Format string node: '{self.value}' ({self.lineno}, {self.colno})." + pass class ContinueNode(ElementaryNode): pass From 35936283d24ed5a0aa76b184a7489d637d3e49c4 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 09:24:05 -0400 Subject: [PATCH 204/855] parser: preserve escape chars in strings use separate Node for multiline strings --- mesonbuild/ast/interpreter.py | 2 +- mesonbuild/ast/introspection.py | 8 ++--- mesonbuild/ast/printer.py | 12 ++++++- mesonbuild/ast/visitor.py | 6 ++++ mesonbuild/cmake/interpreter.py | 2 +- mesonbuild/coredata.py | 2 +- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreterbase/helpers.py | 4 +-- mesonbuild/interpreterbase/interpreterbase.py | 20 +++++------ mesonbuild/mintro.py | 4 +-- mesonbuild/mparser.py | 33 ++++++++++++------- mesonbuild/optinterpreter.py | 4 +-- mesonbuild/rewriter.py | 24 +++++++------- 13 files changed, 74 insertions(+), 49 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 9e098d0be00a..501be7dfef2f 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -239,7 +239,7 @@ def evaluate_ternary(self, node: TernaryNode) -> None: def evaluate_dictstatement(self, node: mparser.DictNode) -> TYPE_nkwargs: def resolve_key(node: mparser.BaseNode) -> str: - if isinstance(node, mparser.StringNode): + if isinstance(node, mparser.BaseStringNode): return node.value return '__AST_UNKNOWN__' arguments, kwargs = self.reduce_arguments(node.args, key_resolver=resolve_key) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index e8055c5299de..50aa7444cc31 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -27,7 +27,7 @@ from ..compilers import detect_compiler_for from ..interpreterbase import InvalidArguments from ..mesonlib import MachineChoice, OptionKey -from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode +from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, BaseStringNode from .interpreter import AstInterpreter if T.TYPE_CHECKING: @@ -128,7 +128,7 @@ def func_project(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[s if not self.is_subproject() and 'subproject_dir' in kwargs: spdirname = kwargs['subproject_dir'] - if isinstance(spdirname, StringNode): + if isinstance(spdirname, BaseStringNode): assert isinstance(spdirname.value, str) self.subproject_dir = spdirname.value if not self.is_subproject(): @@ -174,7 +174,7 @@ def _add_languages(self, raw_langs: T.List[TYPE_nvar], required: bool, for_machi for l in self.flatten_args(raw_langs): if isinstance(l, str): langs.append(l) - elif isinstance(l, StringNode): + elif isinstance(l, BaseStringNode): langs.append(l.value) for lang in sorted(langs, key=compilers.sort_clink): @@ -263,7 +263,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: # Pop the first element if the function is a build target function if isinstance(curr, FunctionNode) and curr.func_name in BUILD_TARGET_FUNCTIONS: arg_nodes.pop(0) - elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, StringNode))] + elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, BaseStringNode))] inqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] if elementary_nodes: res += [curr] diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index ebf63afebe2b..4626e5eedf36 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -84,7 +84,17 @@ def visit_StringNode(self, node: mparser.StringNode) -> None: def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: assert isinstance(node.value, str) - self.append("f'" + node.value + "'", node) + self.append("f'" + self.escape(node.value) + "'", node) + node.lineno = self.curr_line or node.lineno + + def visit_MultilineStringNode(self, node: mparser.StringNode) -> None: + assert isinstance(node.value, str) + self.append("'''" + node.value + "'''", node) + node.lineno = self.curr_line or node.lineno + + def visit_FormatMultilineStringNode(self, node: mparser.FormatStringNode) -> None: + assert isinstance(node.value, str) + self.append("f'''" + node.value + "'''", node) node.lineno = self.curr_line or node.lineno def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 51a662024454..69b93c7f08c8 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -43,6 +43,12 @@ def visit_StringNode(self, node: mparser.StringNode) -> None: def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.visit_default_func(node) + def visit_MultilineStringNode(self, node: mparser.StringNode) -> None: + self.visit_default_func(node) + + def visit_FormatMultilineStringNode(self, node: mparser.FormatStringNode) -> None: + self.visit_default_func(node) + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: self.visit_default_func(node) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index f577ba774a64..80dfff50adbc 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -960,7 +960,7 @@ def token(tid: str = 'string', val: TYPE_mixed = '') -> Token: return Token(tid, self.subdir.as_posix(), 0, 0, 0, None, val) def string(value: str) -> StringNode: - return StringNode(token(val=value)) + return StringNode(token(val=value), escape=False) def id_node(value: str) -> IdNode: return IdNode(token(val=value)) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index f151c7b81f99..f91c5837fdf0 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1098,7 +1098,7 @@ def _parse_section(self, s: str) -> T.Dict[str, T.Union[str, bool, int, T.List[s return section def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, T.List[str]]: - if isinstance(node, (mparser.StringNode)): + if isinstance(node, (mparser.BaseStringNode)): return node.value elif isinstance(node, mparser.BooleanNode): return node.value diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 9b005cb7899c..0814739f5a37 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -536,7 +536,7 @@ def handle_meson_version_from_ast(self) -> None: assert isinstance(kw, mparser.IdNode), 'for mypy' if kw.value == 'meson_version': # mypy does not understand "and isinstance" - if isinstance(val, mparser.StringNode): + if isinstance(val, mparser.BaseStringNode): self.handle_meson_version(val.value, val) def get_build_def_files(self) -> mesonlib.OrderedSet[str]: diff --git a/mesonbuild/interpreterbase/helpers.py b/mesonbuild/interpreterbase/helpers.py index f2ee1b1a9f2f..917969b26d47 100644 --- a/mesonbuild/interpreterbase/helpers.py +++ b/mesonbuild/interpreterbase/helpers.py @@ -25,7 +25,7 @@ from .baseobjects import TYPE_var, TYPE_kwargs, SubProject def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var']: - if isinstance(args, mparser.StringNode): + if isinstance(args, mparser.BaseStringNode): assert isinstance(args.value, str) return [args.value] if not isinstance(args, collections.abc.Sequence): @@ -35,7 +35,7 @@ def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var'] if isinstance(a, list): rest = flatten(a) result = result + rest - elif isinstance(a, mparser.StringNode): + elif isinstance(a, mparser.BaseStringNode): result.append(a.value) else: result.append(a) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index f35da33bd2f5..eab96efb1025 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -196,8 +196,13 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj self.assignment(cur) elif isinstance(cur, mparser.MethodNode): return self.method_call(cur) - elif isinstance(cur, mparser.StringNode): - return self._holderify(cur.value) + elif isinstance(cur, mparser.BaseStringNode): + if isinstance(cur, mparser.MultilineFormatStringNode): + return self.evaluate_multiline_fstring(cur) + elif isinstance(cur, mparser.FormatStringNode): + return self.evaluate_fstring(cur) + else: + return self._holderify(cur.value) elif isinstance(cur, mparser.BooleanNode): return self._holderify(cur.value) elif isinstance(cur, mparser.IfClauseNode): @@ -230,11 +235,6 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj return self.evaluate_indexing(cur) elif isinstance(cur, mparser.TernaryNode): return self.evaluate_ternary(cur) - elif isinstance(cur, mparser.FormatStringNode): - if isinstance(cur, mparser.MultilineFormatStringNode): - return self.evaluate_multiline_fstring(cur) - else: - return self.evaluate_fstring(cur) elif isinstance(cur, mparser.ContinueNode): raise ContinueRequest() elif isinstance(cur, mparser.BreakNode): @@ -256,7 +256,7 @@ def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> InterpreterObject: @FeatureNew('dict', '0.47.0') def evaluate_dictstatement(self, cur: mparser.DictNode) -> InterpreterObject: def resolve_key(key: mparser.BaseNode) -> str: - if not isinstance(key, mparser.StringNode): + if not isinstance(key, mparser.BaseStringNode): FeatureNew.single_use('Dictionary entry using non literal key', '0.53.0', self.subproject) key_holder = self.evaluate_statement(key) if key_holder is None: @@ -428,9 +428,7 @@ def evaluate_multiline_fstring(self, node: mparser.MultilineFormatStringNode) -> return self.evaluate_fstring(node) @FeatureNew('format strings', '0.58.0') - def evaluate_fstring(self, node: mparser.FormatStringNode) -> InterpreterObject: - assert isinstance(node, mparser.FormatStringNode) - + def evaluate_fstring(self, node: T.Union[mparser.FormatStringNode, mparser.MultilineFormatStringNode]) -> InterpreterObject: def replace(match: T.Match[str]) -> str: var = str(match.group(1)) try: diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 039153532489..cf4a53ab0759 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -36,7 +36,7 @@ from . import environment from .interpreterbase import ObjectHolder from .mesonlib import OptionKey -from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode +from .mparser import FunctionNode, ArrayNode, ArgumentNode, BaseStringNode if T.TYPE_CHECKING: import argparse @@ -194,7 +194,7 @@ def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: elif isinstance(n, ArgumentNode): args = n.arguments for j in args: - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): assert isinstance(j.value, str) res += [Path(j.value)] elif isinstance(j, str): diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index f9b896759b1d..61447946652e 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -193,23 +193,15 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: elif tid == 'dblquote': raise ParseException('Double quotes are not supported. Use single quotes.', self.getline(line_start), lineno, col) elif tid in {'string', 'fstring'}: - # Handle here and not on the regexp to give a better error message. if match_text.find("\n") != -1: msg = ("Newline character in a string detected, use ''' (three single quotes) " "for multiline strings instead.\n" "This will become a hard error in a future Meson release.") mlog.warning(mlog.code_line(msg, self.getline(line_start), col), location=BaseNode(lineno, col, filename)) value = match_text[2 if tid == 'fstring' else 1:-1] - value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, value) elif tid in {'multiline_string', 'multiline_fstring'}: - # For multiline strings, parse out the value and pass - # through the normal string logic. - # For multiline format strings, we have to emit a - # different AST node so we can add a feature check, - # but otherwise, it follows the normal fstring logic. if tid == 'multiline_string': value = match_text[3:-3] - tid = 'string' else: value = match_text[4:-3] lines = match_text.split('\n') @@ -295,13 +287,30 @@ def __init__(self, token: Token[str]): self.value = int(token.value, base=0) self.bytespan = token.bytespan -class StringNode(ElementaryNode[str]): +class BaseStringNode(ElementaryNode[str]): pass -class FormatStringNode(ElementaryNode[str]): +@dataclass(unsafe_hash=True) +class StringNode(BaseStringNode): + + raw_value: str = field(hash=False) + + def __init__(self, token: Token[str], escape: bool = True): + super().__init__(token) + self.value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, token.value) if escape else token.value + self.raw_value = token.value + +class FormatStringNode(StringNode): pass -class MultilineFormatStringNode(FormatStringNode): +@dataclass(unsafe_hash=True) +class MultilineStringNode(BaseStringNode): + + def __init__(self, token: Token[str]): + super().__init__(token) + self.value = token.value + +class MultilineFormatStringNode(MultilineStringNode): pass class ContinueNode(ElementaryNode): @@ -819,6 +828,8 @@ def e9(self) -> BaseNode: return StringNode(t) if self.accept('fstring'): return FormatStringNode(t) + if self.accept('multiline_string'): + return MultilineStringNode(t) if self.accept('multiline_fstring'): return MultilineFormatStringNode(t) return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 37ef55ab0673..9eeb3fdc679a 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -115,7 +115,7 @@ def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var': return arg if isinstance(arg, mparser.ParenthesizedNode): return self.reduce_single(arg.inner) - elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, + elif isinstance(arg, (mparser.BaseStringNode, mparser.BooleanNode, mparser.NumberNode)): return arg.value elif isinstance(arg, mparser.ArrayNode): @@ -123,7 +123,7 @@ def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var': elif isinstance(arg, mparser.DictNode): d = {} for k, v in arg.args.kwargs.items(): - if not isinstance(k, mparser.StringNode): + if not isinstance(k, mparser.BaseStringNode): raise OptionException('Dictionary keys must be a string literal') d[k.value] = self.reduce_single(v) return d diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index a9b2e881c356..0d7b111c4405 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -28,7 +28,7 @@ from mesonbuild.mesonlib import MesonException, setup_vsenv from . import mlog, environment from functools import wraps -from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode +from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseStringNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode import json, os, re, sys import typing as T @@ -267,12 +267,12 @@ def _new_element_node(self, value): return StringNode(Token('', '', 0, 0, 0, None, str(value))) def _check_is_equal(self, node, value) -> bool: - if isinstance(node, StringNode): + if isinstance(node, BaseStringNode): return node.value == value return False def _check_regex_matches(self, node, regex: str) -> bool: - if isinstance(node, StringNode): + if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False @@ -292,7 +292,7 @@ def _check_is_equal(self, node, value) -> bool: return False def _check_regex_matches(self, node, regex: str) -> bool: - if isinstance(node, StringNode): + if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False @@ -652,7 +652,7 @@ def arg_list_from_node(n): src_list = [] for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): src_list += [j.value] # Generate the new String nodes @@ -686,7 +686,7 @@ def arg_list_from_node(n): def find_node(src): for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): if j.value == src: return i, j return None, None @@ -745,7 +745,7 @@ def find_node(src): extra_files_list = [] for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): extra_files_list += [j.value] # Generate the new String nodes @@ -776,7 +776,7 @@ def find_node(src): def find_node(src): for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): if j.value == src: return i, j return None, None @@ -845,12 +845,12 @@ def find_node(src): src_list = [] for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): src_list += [j.value] extra_files_list = [] for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, StringNode): + if isinstance(j, BaseStringNode): extra_files_list += [j.value] test_data = { 'name': target['name'], @@ -865,8 +865,8 @@ def find_node(src): alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] path_sorter = lambda key: ([(key.count('/') <= idx, alphanum_key(x)) for idx, x in enumerate(key.split('/'))]) - unknown = [x for x in i.arguments if not isinstance(x, StringNode)] - sources = [x for x in i.arguments if isinstance(x, StringNode)] + unknown = [x for x in i.arguments if not isinstance(x, BaseStringNode)] + sources = [x for x in i.arguments if isinstance(x, BaseStringNode)] sources = sorted(sources, key=lambda x: path_sorter(x.value)) i.arguments = unknown + sources From 306562b4666dea7828af680afbd4d111e667027f Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 14:22:15 -0400 Subject: [PATCH 205/855] parser: use IdNode for function name and assignment name --- mesonbuild/ast/interpreter.py | 19 +++++++------ mesonbuild/ast/introspection.py | 2 +- mesonbuild/ast/printer.py | 16 +++++------ mesonbuild/ast/visitor.py | 4 +++ mesonbuild/cargo/builder.py | 6 ++-- mesonbuild/cmake/interpreter.py | 6 ++-- mesonbuild/interpreter/interpreter.py | 4 +-- mesonbuild/interpreterbase/interpreterbase.py | 10 +++---- mesonbuild/mintro.py | 2 +- mesonbuild/mparser.py | 28 ++++++++----------- mesonbuild/optinterpreter.py | 2 +- mesonbuild/rewriter.py | 14 +++++----- 12 files changed, 57 insertions(+), 56 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 501be7dfef2f..1dea817b1e28 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -254,10 +254,10 @@ def resolve_key(node: mparser.BaseNode) -> str: def evaluate_plusassign(self, node: PlusAssignmentNode) -> None: assert isinstance(node, PlusAssignmentNode) # Cheat by doing a reassignment - self.assignments[node.var_name] = node.value # Save a reference to the value node + self.assignments[node.var_name.value] = node.value # Save a reference to the value node if node.value.ast_id: self.reverse_assignment[node.value.ast_id] = node - self.assign_vals[node.var_name] = self.evaluate_statement(node.value) + self.assign_vals[node.var_name.value] = self.evaluate_statement(node.value) def evaluate_indexing(self, node: IndexNode) -> int: return 0 @@ -319,10 +319,10 @@ def get_variable(self, varname: str) -> int: def assignment(self, node: AssignmentNode) -> None: assert isinstance(node, AssignmentNode) - self.assignments[node.var_name] = node.value # Save a reference to the value node + self.assignments[node.var_name.value] = node.value # Save a reference to the value node if node.value.ast_id: self.reverse_assignment[node.value.ast_id] = node - self.assign_vals[node.var_name] = self.evaluate_statement(node.value) # Evaluate the value just in case + self.assign_vals[node.var_name.value] = self.evaluate_statement(node.value) # Evaluate the value just in case def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.Optional[T.Any]: def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T.Any: @@ -382,17 +382,18 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T src = quick_resolve(node.source_object) margs = self.flatten_args(node.args.arguments, include_unknown_args, id_loop_detect) mkwargs: T.Dict[str, TYPE_nvar] = {} + method_name = node.name.value try: if isinstance(src, str): - result = StringHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + result = StringHolder(src, T.cast('Interpreter', self)).method_call(method_name, margs, mkwargs) elif isinstance(src, bool): - result = BooleanHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + result = BooleanHolder(src, T.cast('Interpreter', self)).method_call(method_name, margs, mkwargs) elif isinstance(src, int): - result = IntegerHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + result = IntegerHolder(src, T.cast('Interpreter', self)).method_call(method_name, margs, mkwargs) elif isinstance(src, list): - result = ArrayHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + result = ArrayHolder(src, T.cast('Interpreter', self)).method_call(method_name, margs, mkwargs) elif isinstance(src, dict): - result = DictHolder(src, T.cast('Interpreter', self)).method_call(node.name, margs, mkwargs) + result = DictHolder(src, T.cast('Interpreter', self)).method_call(method_name, margs, mkwargs) except mesonlib.MesonException: return None diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 50aa7444cc31..fa4b8d3024c2 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -261,7 +261,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: continue arg_nodes = arg_node.arguments.copy() # Pop the first element if the function is a build target function - if isinstance(curr, FunctionNode) and curr.func_name in BUILD_TARGET_FUNCTIONS: + if isinstance(curr, FunctionNode) and curr.func_name.value in BUILD_TARGET_FUNCTIONS: arg_nodes.pop(0) elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, BaseStringNode))] inqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 4626e5eedf36..020299d6b8aa 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -162,24 +162,24 @@ def visit_IndexNode(self, node: mparser.IndexNode) -> None: def visit_MethodNode(self, node: mparser.MethodNode) -> None: node.lineno = self.curr_line or node.lineno node.source_object.accept(self) - self.append('.' + node.name + '(', node) + self.append('.' + node.name.value + '(', node) node.args.accept(self) self.append(')', node) def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: node.lineno = self.curr_line or node.lineno - self.append(node.func_name + '(', node) + self.append(node.func_name.value + '(', node) node.args.accept(self) self.append(')', node) def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: node.lineno = self.curr_line or node.lineno - self.append(node.var_name + ' = ', node) + self.append(node.var_name.value + ' = ', node) node.value.accept(self) def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: node.lineno = self.curr_line or node.lineno - self.append(node.var_name + ' += ', node) + self.append(node.var_name.value + ' += ', node) node.value.accept(self) def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: @@ -352,22 +352,22 @@ def visit_IndexNode(self, node: mparser.IndexNode) -> None: def visit_MethodNode(self, node: mparser.MethodNode) -> None: self._accept('object', node.source_object) self._accept('args', node.args) - self.current['name'] = node.name + self.current['name'] = node.name.value self.setbase(node) def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: self._accept('args', node.args) - self.current['name'] = node.func_name + self.current['name'] = node.func_name.value self.setbase(node) def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: self._accept('value', node.value) - self.current['var_name'] = node.var_name + self.current['var_name'] = node.var_name.value self.setbase(node) def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: self._accept('value', node.value) - self.current['var_name'] = node.var_name + self.current['var_name'] = node.var_name.value self.setbase(node) def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 69b93c7f08c8..6e40ea0b4baa 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -103,18 +103,22 @@ def visit_IndexNode(self, node: mparser.IndexNode) -> None: def visit_MethodNode(self, node: mparser.MethodNode) -> None: self.visit_default_func(node) node.source_object.accept(self) + node.name.accept(self) node.args.accept(self) def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: self.visit_default_func(node) + node.func_name.accept(self) node.args.accept(self) def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: self.visit_default_func(node) + node.var_name.accept(self) node.value.accept(self) def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: self.visit_default_func(node) + node.var_name.accept(self) node.value.accept(self) def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 2442fbfa76a2..6ef66eeca7a8 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -97,7 +97,7 @@ def method(name: str, id_: mparser.IdNode, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} - return mparser.MethodNode(id_.filename, -1, -1, id_, name, args) + return mparser.MethodNode(id_.filename, -1, -1, id_, identifier(name, id_.filename), args) def function(name: str, filename: str, @@ -117,7 +117,7 @@ def function(name: str, filename: str, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, filename): v for k, v in kw.items()} - return mparser.FunctionNode(filename, -1, -1, -1, -1, name, args) + return mparser.FunctionNode(filename, -1, -1, -1, -1, identifier(name, filename), args) def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: @@ -168,7 +168,7 @@ def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.Assi :param filename: The filename :return: An AssignmentNode """ - return mparser.AssignmentNode(filename, -1, -1, varname, value) + return mparser.AssignmentNode(filename, -1, -1, identifier(varname, filename), value) def block(filename: str) -> mparser.CodeBlockNode: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 80dfff50adbc..0703c1b93838 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -1002,7 +1002,7 @@ def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Opti args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, name, args_n) + func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, id_node(name), args_n) return func_n def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode: @@ -1014,10 +1014,10 @@ def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, k args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - return MethodNode(self.subdir.as_posix(), 0, 0, obj, name, args_n) + return MethodNode(self.subdir.as_posix(), 0, 0, obj, id_node(name), args_n) def assign(var_name: str, value: BaseNode) -> AssignmentNode: - return AssignmentNode(self.subdir.as_posix(), 0, 0, var_name, value) + return AssignmentNode(self.subdir.as_posix(), 0, 0, id_node(var_name), value) # Generate the root code block and the project function call root_cb = CodeBlockNode(token()) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 0814739f5a37..c6370870c3e9 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2942,7 +2942,7 @@ def _warn_about_builtin_args(self, args: T.List[str]) -> None: def _add_global_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]], args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: if self.is_subproject(): - msg = f'Function \'{node.func_name}\' cannot be used in subprojects because ' \ + msg = f'Function \'{node.func_name.value}\' cannot be used in subprojects because ' \ 'there is no way to make that reliable.\nPlease only call ' \ 'this if is_subproject() returns false. Alternatively, ' \ 'define a variable that\ncontains your language-specific ' \ @@ -2962,7 +2962,7 @@ def _add_project_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[st def _add_arguments(self, node: mparser.FunctionNode, argsdict: T.Dict[str, T.List[str]], args_frozen: bool, args: T.List[str], kwargs: 'kwtypes.FuncAddProjectArgs') -> None: if args_frozen: - msg = f'Tried to use \'{node.func_name}\' after a build target has been declared.\n' \ + msg = f'Tried to use \'{node.func_name.value}\' after a build target has been declared.\n' \ 'This is not permitted. Please declare all arguments before your targets.' raise InvalidCode(msg) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index eab96efb1025..1c0912835950 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -137,7 +137,7 @@ def sanity_check_ast(self) -> None: if not self.ast.lines: raise InvalidCode('No statements in code.') first = self.ast.lines[0] - if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': + if not isinstance(first, mparser.FunctionNode) or first.func_name.value != 'project': p = pathlib.Path(self.source_root).resolve() found = p for parent in p.parents: @@ -476,7 +476,7 @@ def evaluate_foreach(self, node: mparser.ForeachClauseNode) -> None: def evaluate_plusassign(self, node: mparser.PlusAssignmentNode) -> None: assert isinstance(node, mparser.PlusAssignmentNode) - varname = node.var_name + varname = node.var_name.value addition = self.evaluate_statement(node.value) if addition is None: raise InvalidCodeOnVoid('plus assign') @@ -504,7 +504,7 @@ def evaluate_indexing(self, node: mparser.IndexNode) -> InterpreterObject: return self._holderify(iobject.operator_call(MesonOperator.INDEX, index)) def function_call(self, node: mparser.FunctionNode) -> T.Optional[InterpreterObject]: - func_name = node.func_name + func_name = node.func_name.value (h_posargs, h_kwargs) = self.reduce_arguments(node.args) (posargs, kwargs) = self._unholder_args(h_posargs, h_kwargs) if is_disabled(posargs, kwargs) and func_name not in {'get_variable', 'set_variable', 'unset_variable', 'is_disabler'}: @@ -532,7 +532,7 @@ def method_call(self, node: mparser.MethodNode) -> T.Optional[InterpreterObject] else: object_display_name = invocable.__class__.__name__ obj = self.evaluate_statement(invocable) - method_name = node.name + method_name = node.name.value (h_args, h_kwargs) = self.reduce_arguments(node.args) (args, kwargs) = self._unholder_args(h_args, h_kwargs) if is_disabled(args, kwargs): @@ -628,7 +628,7 @@ def assignment(self, node: mparser.AssignmentNode) -> None: Tried to assign values inside an argument list. To specify a keyword argument, use : instead of =. ''')) - var_name = node.var_name + var_name = node.var_name.value if not isinstance(var_name, str): raise InvalidArguments('Tried to assign value to a non-variable.') value = self.evaluate_statement(node.value) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index cf4a53ab0759..7bd420510334 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -187,7 +187,7 @@ def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: args: T.List[BaseNode] = [] if isinstance(n, FunctionNode): args = list(n.args.arguments) - if n.func_name in BUILD_TARGET_FUNCTIONS: + if n.func_name.value in BUILD_TARGET_FUNCTIONS: args.pop(0) elif isinstance(n, ArrayNode): args = n.args.arguments diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 61447946652e..ceddf0a52a6b 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -470,52 +470,48 @@ def __init__(self, iobject: BaseNode, index: BaseNode): class MethodNode(BaseNode): source_object: BaseNode - name: str + name: IdNode args: ArgumentNode - def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: str, args: ArgumentNode): + def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: IdNode, args: ArgumentNode): super().__init__(lineno, colno, filename) self.source_object = source_object self.name = name - assert isinstance(self.name, str) self.args = args @dataclass(unsafe_hash=True) class FunctionNode(BaseNode): - func_name: str + func_name: IdNode args: ArgumentNode - def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: str, args: ArgumentNode): + def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: IdNode, args: ArgumentNode): super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno) self.func_name = func_name - assert isinstance(func_name, str) self.args = args @dataclass(unsafe_hash=True) class AssignmentNode(BaseNode): - var_name: str + var_name: IdNode value: BaseNode - def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): + def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, value: BaseNode): super().__init__(lineno, colno, filename) self.var_name = var_name - assert isinstance(var_name, str) self.value = value @dataclass(unsafe_hash=True) class PlusAssignmentNode(BaseNode): - var_name: str + var_name: IdNode value: BaseNode - def __init__(self, filename: str, lineno: int, colno: int, var_name: str, value: BaseNode): + def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, value: BaseNode): super().__init__(lineno, colno, filename) self.var_name = var_name - assert isinstance(var_name, str) self.value = value @@ -687,14 +683,14 @@ def e1(self) -> BaseNode: if not isinstance(left, IdNode): raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return PlusAssignmentNode(left.filename, left.lineno, left.colno, left.value, value) + return PlusAssignmentNode(left.filename, left.lineno, left.colno, left, value) elif self.accept('assign'): value = self.e1() if not isinstance(left, IdNode): raise ParseException('Assignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return AssignmentNode(left.filename, left.lineno, left.colno, left.value, value) + return AssignmentNode(left.filename, left.lineno, left.colno, left, value) elif self.accept('questionmark'): if self.in_ternary: raise ParseException('Nested ternary operators are not allowed.', @@ -783,7 +779,7 @@ def e7(self) -> BaseNode: raise ParseException('Function call must be applied to plain id', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - left = FunctionNode(left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left.value, args) + left = FunctionNode(left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left, args) go_again = True while go_again: go_again = False @@ -887,7 +883,7 @@ def method_call(self, source_object: BaseNode) -> MethodNode: self.expect('lparen') args = self.args() self.expect('rparen') - method = MethodNode(methodname.filename, methodname.lineno, methodname.colno, source_object, methodname.value, args) + method = MethodNode(methodname.filename, methodname.lineno, methodname.colno, source_object, methodname, args) if self.accept('dot'): return self.method_call(method) return method diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 9eeb3fdc679a..895cada54ae8 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -164,7 +164,7 @@ def reduce_arguments(self, args: mparser.ArgumentNode) -> T.Tuple['TYPE_var', 'T def evaluate_statement(self, node: mparser.BaseNode) -> None: if not isinstance(node, mparser.FunctionNode): raise OptionException('Option file may only contain option definitions') - func_name = node.func_name + func_name = node.func_name.value if func_name != 'option': raise OptionException('Only calls to option() are allowed in option files.') (posargs, kwargs) = self.reduce_arguments(node.args) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 0d7b111c4405..af3210cf3315 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -420,7 +420,7 @@ def check_list(name: str) -> T.List[BaseNode]: if target in self.interpreter.assignments: node = self.interpreter.assignments[target] if isinstance(node, FunctionNode): - if node.func_name in {'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries'}: + if node.func_name.value in {'executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries'}: tgt = self.interpreter.assign_vals[target] return tgt @@ -440,7 +440,7 @@ def check_list(name: str): if dependency in self.interpreter.assignments: node = self.interpreter.assignments[dependency] if isinstance(node, FunctionNode): - if node.func_name == 'dependency': + if node.func_name.value == 'dependency': name = self.interpreter.flatten_args(node.args)[0] dep = check_list(name) @@ -630,7 +630,7 @@ def arg_list_from_node(n): args = [] if isinstance(n, FunctionNode): args = list(n.args.arguments) - if n.func_name in BUILD_TARGET_FUNCTIONS: + if n.func_name.value in BUILD_TARGET_FUNCTIONS: args.pop(0) elif isinstance(n, ArrayNode): args = n.args.arguments @@ -814,15 +814,15 @@ def find_node(src): src_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) src_arr_node = ArrayNode(src_arg_node, 0, 0, 0, 0) src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - src_fun_node = FunctionNode(filename, 0, 0, 0, 0, 'files', src_far_node) - src_ass_node = AssignmentNode(filename, 0, 0, source_id, src_fun_node) + src_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), src_far_node) + src_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), src_fun_node) src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']] src_far_node.arguments = [src_arr_node] # Build target tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, cmd['target_type'], tgt_arg_node) - tgt_ass_node = AssignmentNode(filename, 0, 0, target_id, tgt_fun_node) + tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), tgt_arg_node) + tgt_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), tgt_fun_node) tgt_arg_node.arguments = [ StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])), IdNode(Token('string', filename, 0, 0, 0, None, source_id)) From 8d357ba62cba0c5ddf3265743454b0ddcb08d83f Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 14:28:40 -0400 Subject: [PATCH 206/855] parser: use IdNode for foreach varnames --- mesonbuild/ast/printer.py | 4 ++-- mesonbuild/ast/visitor.py | 2 ++ mesonbuild/interpreterbase/interpreterbase.py | 4 ++-- mesonbuild/mparser.py | 8 ++++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 020299d6b8aa..410aabd4619e 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -185,7 +185,7 @@ def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: node.lineno = self.curr_line or node.lineno self.append_padded('foreach', node) - self.append_padded(', '.join(node.varnames), node) + self.append_padded(', '.join(varname.value for varname in node.varnames), node) self.append_padded(':', node) node.items.accept(self) self.newline() @@ -373,7 +373,7 @@ def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self._accept('items', node.items) self._accept('block', node.block) - self.current['varnames'] = node.varnames + self.current['varnames'] = [varname.value for varname in node.varnames] self.setbase(node) def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 6e40ea0b4baa..5b1fb6a0985b 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -123,6 +123,8 @@ def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: self.visit_default_func(node) + for varname in node.varnames: + varname.accept(self) node.items.accept(self) node.block.accept(self) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 1c0912835950..7e3f8da5a47a 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -459,14 +459,14 @@ def evaluate_foreach(self, node: mparser.ForeachClauseNode) -> None: if tsize is None: if isinstance(i, tuple): raise mesonlib.MesonBugException(f'Iteration of {items} returned a tuple even though iter_tuple_size() is None') - self.set_variable(node.varnames[0], self._holderify(i)) + self.set_variable(node.varnames[0].value, self._holderify(i)) else: if not isinstance(i, tuple): raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}') if len(i) != tsize: raise mesonlib.MesonBugException(f'Iteration of {items} did not return a tuple even though iter_tuple_size() is {tsize}') for j in range(tsize): - self.set_variable(node.varnames[j], self._holderify(i[j])) + self.set_variable(node.varnames[j].value, self._holderify(i[j])) try: self.evaluate_codeblock(node.block) except ContinueRequest: diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index ceddf0a52a6b..2d7f11505881 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -518,11 +518,11 @@ def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, val @dataclass(unsafe_hash=True) class ForeachClauseNode(BaseNode): - varnames: T.List[str] = field(hash=False) + varnames: T.List[IdNode] = field(hash=False) items: BaseNode block: CodeBlockNode - def __init__(self, token: Token, varnames: T.List[str], items: BaseNode, block: CodeBlockNode): + def __init__(self, token: Token, varnames: T.List[IdNode], items: BaseNode, block: CodeBlockNode): super().__init__(token.lineno, token.colno, token.filename) self.varnames = varnames self.items = items @@ -898,13 +898,13 @@ def foreachblock(self) -> ForeachClauseNode: self.expect('id') assert isinstance(t.value, str) varname = t - varnames = [t.value] + varnames = [IdNode(t)] if self.accept('comma'): t = self.current self.expect('id') assert isinstance(t.value, str) - varnames.append(t.value) + varnames.append(IdNode(t)) self.expect('colon') items = self.statement() From b94167ef50e891355a7d9a0014e6b0cf4ea1302d Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 15:10:07 -0400 Subject: [PATCH 207/855] parser: preserve value of all tokens --- mesonbuild/mparser.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 2d7f11505881..2ff32dc282e5 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -163,7 +163,7 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: col = 0 while loc < len(self.code): matched = False - value: T.Union[str, bool, int] = None + value: str = '' for (tid, reg) in self.token_specification: mo = reg.match(self.code, loc) if mo: @@ -175,7 +175,7 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: loc = mo.end() span_end = loc bytespan = (span_start, span_end) - match_text = mo.group() + value = mo.group() if tid in {'ignore', 'comment'}: break elif tid == 'lparen': @@ -193,23 +193,18 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: elif tid == 'dblquote': raise ParseException('Double quotes are not supported. Use single quotes.', self.getline(line_start), lineno, col) elif tid in {'string', 'fstring'}: - if match_text.find("\n") != -1: + if value.find("\n") != -1: msg = ("Newline character in a string detected, use ''' (three single quotes) " "for multiline strings instead.\n" "This will become a hard error in a future Meson release.") mlog.warning(mlog.code_line(msg, self.getline(line_start), col), location=BaseNode(lineno, col, filename)) - value = match_text[2 if tid == 'fstring' else 1:-1] + value = value[2 if tid == 'fstring' else 1:-1] elif tid in {'multiline_string', 'multiline_fstring'}: - if tid == 'multiline_string': - value = match_text[3:-3] - else: - value = match_text[4:-3] - lines = match_text.split('\n') + value = value[4 if tid == 'multiline_fstring' else 3:-3] + lines = value.split('\n') if len(lines) > 1: lineno += len(lines) - 1 line_start = mo.end() - len(lines[-1]) - elif tid == 'number': - value = match_text elif tid == 'eol_cont': lineno += 1 line_start = loc @@ -220,13 +215,12 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: if par_count > 0 or bracket_count > 0 or curl_count > 0: break elif tid == 'id': - if match_text in self.keywords: - tid = match_text + if value in self.keywords: + tid = value else: - if match_text in self.future_keywords: - mlog.warning(f"Identifier '{match_text}' will become a reserved keyword in a future release. Please rename it.", + if value in self.future_keywords: + mlog.warning(f"Identifier '{value}' will become a reserved keyword in a future release. Please rename it.", location=BaseNode(lineno, col, filename)) - value = match_text yield Token(tid, filename, curline_start, curline, col, bytespan, value) break if not matched: From 4b7a56caa265c54a9b77381e2db1819ed87f21de Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 08:58:23 -0400 Subject: [PATCH 208/855] parser: remember previous Token --- mesonbuild/mparser.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 2ff32dc282e5..ce83cc283102 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -623,10 +623,12 @@ def __init__(self, code: str, filename: str): self.lexer = Lexer(code) self.stream = self.lexer.lex(filename) self.current: Token = Token('eof', '', 0, 0, 0, (0, 0), None) + self.previous = self.current self.getsym() self.in_ternary = False def getsym(self) -> None: + self.previous = self.current try: self.current = next(self.stream) except StopIteration: @@ -831,10 +833,9 @@ def key_values(self) -> ArgumentNode: while not isinstance(s, EmptyNode): if self.accept('colon'): a.set_kwarg_no_check(s, self.statement()) - potential = self.current if not self.accept('comma'): return a - a.commas.append(potential) + a.commas.append(self.previous) else: raise ParseException('Only key:value pairs are valid in dict construction.', self.getline(), s.lineno, s.colno) @@ -846,19 +847,17 @@ def args(self) -> ArgumentNode: a = ArgumentNode(self.current) while not isinstance(s, EmptyNode): - potential = self.current if self.accept('comma'): - a.commas.append(potential) + a.commas.append(self.previous) a.append(s) elif self.accept('colon'): if not isinstance(s, IdNode): raise ParseException('Dictionary key must be a plain identifier.', self.getline(), s.lineno, s.colno) a.set_kwarg(s, self.statement()) - potential = self.current if not self.accept('comma'): return a - a.commas.append(potential) + a.commas.append(self.previous) else: a.append(s) return a @@ -888,17 +887,15 @@ def index_call(self, source_object: BaseNode) -> IndexNode: return IndexNode(source_object, index_statement) def foreachblock(self) -> ForeachClauseNode: - t = self.current self.expect('id') - assert isinstance(t.value, str) - varname = t - varnames = [IdNode(t)] + assert isinstance(self.previous.value, str) + varname = self.previous + varnames = [IdNode(self.previous)] if self.accept('comma'): - t = self.current self.expect('id') - assert isinstance(t.value, str) - varnames.append(IdNode(t)) + assert isinstance(self.previous.value, str) + varnames.append(IdNode(self.previous)) self.expect('colon') items = self.statement() From f13260dd43771bd7e9594cbad942b7d9aa4292fc Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 09:18:21 -0400 Subject: [PATCH 209/855] parser: add ElseNode --- mesonbuild/ast/interpreter.py | 2 +- mesonbuild/ast/visitor.py | 4 ++++ mesonbuild/interpreterbase/interpreterbase.py | 2 +- mesonbuild/mparser.py | 17 +++++++++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 1dea817b1e28..da2119c89ee7 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -312,7 +312,7 @@ def evaluate_if(self, node: IfClauseNode) -> None: for i in node.ifs: self.evaluate_codeblock(i.block) if not isinstance(node.elseblock, EmptyNode): - self.evaluate_codeblock(node.elseblock) + self.evaluate_codeblock(node.elseblock.block) def get_variable(self, varname: str) -> int: return 0 diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 5b1fb6a0985b..a8378265596f 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -143,6 +143,10 @@ def visit_IfNode(self, node: mparser.IfNode) -> None: node.condition.accept(self) node.block.accept(self) + def visit_ElseNode(self, node: mparser.IfNode) -> None: + self.visit_default_func(node) + node.block.accept(self) + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: self.visit_default_func(node) node.condition.accept(self) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 7e3f8da5a47a..5b07dc0752ab 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -303,7 +303,7 @@ def evaluate_if(self, node: mparser.IfClauseNode) -> T.Optional[Disabler]: mesonlib.project_meson_versions[self.subproject] = prev_meson_version return None if not isinstance(node.elseblock, mparser.EmptyNode): - self.evaluate_codeblock(node.elseblock) + self.evaluate_codeblock(node.elseblock.block) return None def evaluate_testcase(self, node: mparser.TestCaseClauseNode) -> T.Optional[Disabler]: diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index ce83cc283102..6b578b5afd27 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -534,17 +534,25 @@ def __init__(self, linenode: BaseNode, condition: BaseNode, block: CodeBlockNode self.condition = condition self.block = block +@dataclass(unsafe_hash=True) +class ElseNode(BaseNode): + + block: CodeBlockNode + + def __init__(self, block: CodeBlockNode): + super().__init__(block.lineno, block.colno, block.filename) + self.block = block @dataclass(unsafe_hash=True) class IfClauseNode(BaseNode): ifs: T.List[IfNode] = field(hash=False) - elseblock: T.Union[EmptyNode, CodeBlockNode] + elseblock: T.Union[EmptyNode, ElseNode] def __init__(self, linenode: BaseNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) self.ifs = [] - self.elseblock = None + self.elseblock = EmptyNode(linenode.lineno, linenode.colno, linenode.filename) @dataclass(unsafe_hash=True) class TestCaseClauseNode(BaseNode): @@ -919,10 +927,11 @@ def elseifblock(self, clause: IfClauseNode) -> None: b = self.codeblock() clause.ifs.append(IfNode(s, s, b)) - def elseblock(self) -> T.Union[CodeBlockNode, EmptyNode]: + def elseblock(self) -> T.Union[ElseNode, EmptyNode]: if self.accept('else'): self.expect('eol') - return self.codeblock() + block = self.codeblock() + return ElseNode(block) return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) def testcaseblock(self) -> TestCaseClauseNode: From 02ff9553dbe09f3f2b7a93221dfd28fc53926d0e Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 09:24:17 -0400 Subject: [PATCH 210/855] parser: add SymbolNode to preserve operators --- mesonbuild/ast/visitor.py | 6 + mesonbuild/cargo/builder.py | 20 ++- mesonbuild/cmake/interpreter.py | 14 +- mesonbuild/mparser.py | 266 ++++++++++++++++++++++++-------- mesonbuild/rewriter.py | 19 ++- 5 files changed, 239 insertions(+), 86 deletions(-) diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index a8378265596f..d05d3ffe519e 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -55,6 +55,12 @@ def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: def visit_BreakNode(self, node: mparser.BreakNode) -> None: self.visit_default_func(node) + def visit_SymbolNode(self, node: mparser.SymbolNode) -> None: + self.visit_default_func(node) + + def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: + self.visit_default_func(node) + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self.visit_default_func(node) node.args.accept(self) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 6ef66eeca7a8..9c650b945864 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -28,6 +28,10 @@ def _token(tid: str, filename: str, value: mparser.TV_TokenTypes) -> mparser.Tok return mparser.Token(tid, filename, -1, -1, -1, (-1, -1), value) +def _symbol(filename: str, val: str) -> mparser.SymbolNode: + return mparser.SymbolNode(_token('', filename, val)) + + def string(value: str, filename: str) -> mparser.StringNode: """Build A StringNode @@ -67,7 +71,7 @@ def array(value: T.List[mparser.BaseNode], filename: str) -> mparser.ArrayNode: """ args = mparser.ArgumentNode(_token('array', filename, 'unused')) args.arguments = value - return mparser.ArrayNode(args, -1, -1, -1, -1) + return mparser.ArrayNode(_symbol(filename, '['), args, _symbol(filename, ']'), -1, -1, -1, -1) def identifier(value: str, filename: str) -> mparser.IdNode: @@ -97,7 +101,7 @@ def method(name: str, id_: mparser.IdNode, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} - return mparser.MethodNode(id_.filename, -1, -1, id_, identifier(name, id_.filename), args) + return mparser.MethodNode(id_.filename, -1, -1, id_, _symbol(id_.filename, '.'), identifier(name, id_.filename), _symbol(id_.filename, '('), args, _symbol(id_.filename, ')')) def function(name: str, filename: str, @@ -117,7 +121,7 @@ def function(name: str, filename: str, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, filename): v for k, v in kw.items()} - return mparser.FunctionNode(filename, -1, -1, -1, -1, identifier(name, filename), args) + return mparser.FunctionNode(filename, -1, -1, -1, -1, identifier(name, filename), _symbol(filename, '('), args, _symbol(filename, ')')) def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: @@ -127,7 +131,7 @@ def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNod :param rhs: the right hand side of the equal :return: A compraison node """ - return mparser.ComparisonNode('==', lhs, rhs) + return mparser.ComparisonNode('==', lhs, _symbol(lhs.filename, '=='), rhs) def or_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: @@ -137,7 +141,7 @@ def or_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: :param rhs: The Right of the Node :return: The OrNode """ - return mparser.OrNode(lhs, rhs) + return mparser.OrNode(lhs, _symbol(lhs.filename, 'or'), rhs) def and_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: @@ -147,7 +151,7 @@ def and_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: :param rhs: The right of the And :return: The AndNode """ - return mparser.AndNode(lhs, rhs) + return mparser.AndNode(lhs, _symbol(lhs.filename, 'and'), rhs) def not_(value: mparser.BaseNode, filename: str) -> mparser.NotNode: @@ -157,7 +161,7 @@ def not_(value: mparser.BaseNode, filename: str) -> mparser.NotNode: :param filename: the string filename :return: The NotNode """ - return mparser.NotNode(_token('not', filename, ''), value) + return mparser.NotNode(_token('not', filename, ''), _symbol(filename, 'not'), value) def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.AssignmentNode: @@ -168,7 +172,7 @@ def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.Assi :param filename: The filename :return: An AssignmentNode """ - return mparser.AssignmentNode(filename, -1, -1, identifier(varname, filename), value) + return mparser.AssignmentNode(filename, -1, -1, identifier(varname, filename), _symbol(filename, '='), value) def block(filename: str) -> mparser.CodeBlockNode: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 0703c1b93838..4f3b31e59440 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -48,6 +48,7 @@ IndexNode, MethodNode, NumberNode, + SymbolNode, ) @@ -959,6 +960,9 @@ def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode: def token(tid: str = 'string', val: TYPE_mixed = '') -> Token: return Token(tid, self.subdir.as_posix(), 0, 0, 0, None, val) + def symbol(val: str) -> SymbolNode: + return SymbolNode(token('', val)) + def string(value: str) -> StringNode: return StringNode(token(val=value), escape=False) @@ -984,14 +988,14 @@ def nodeify(value: TYPE_mixed_list) -> BaseNode: raise RuntimeError('invalid type of value: {} ({})'.format(type(value).__name__, str(value))) def indexed(node: BaseNode, index: int) -> IndexNode: - return IndexNode(node, nodeify(index)) + return IndexNode(node, symbol('['), nodeify(index), symbol(']')) def array(elements: TYPE_mixed_list) -> ArrayNode: args = ArgumentNode(token()) if not isinstance(elements, list): elements = [args] args.arguments += [nodeify(x) for x in elements if x is not None] - return ArrayNode(args, 0, 0, 0, 0) + return ArrayNode(symbol('['), args, symbol(']'), 0, 0, 0, 0) def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> FunctionNode: args = [] if args is None else args @@ -1002,7 +1006,7 @@ def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Opti args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, id_node(name), args_n) + func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, id_node(name), symbol('('), args_n, symbol(')')) return func_n def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode: @@ -1014,10 +1018,10 @@ def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, k args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - return MethodNode(self.subdir.as_posix(), 0, 0, obj, id_node(name), args_n) + return MethodNode(self.subdir.as_posix(), 0, 0, obj, symbol('.'), id_node(name), symbol('('), args_n, symbol(')')) def assign(var_name: str, value: BaseNode) -> AssignmentNode: - return AssignmentNode(self.subdir.as_posix(), 0, 0, id_node(var_name), value) + return AssignmentNode(self.subdir.as_posix(), 0, 0, id_node(var_name), symbol('='), value) # Generate the root code block and the project function call root_cb = CodeBlockNode(token()) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 6b578b5afd27..7f329dd0acfa 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -26,6 +26,8 @@ from .ast import AstVisitor + BaseNodeT = T.TypeVar('BaseNodeT', bound='BaseNode') + # This is the regex for the supported escape sequences of a regular string # literal, like 'abc\x00' ESCAPE_SEQUENCE_SINGLE_RE = re.compile(r''' @@ -234,12 +236,14 @@ class BaseNode: end_lineno: int = field(hash=False) end_colno: int = field(hash=False) - def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None: + def __init__(self, lineno: int, colno: int, filename: str, + end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None: self.lineno = lineno self.colno = colno self.filename = filename self.end_lineno = end_lineno if end_lineno is not None else lineno self.end_colno = end_colno if end_colno is not None else colno + self.whitespaces = None # Attributes for the visitors self.level = 0 @@ -313,17 +317,22 @@ class ContinueNode(ElementaryNode): class BreakNode(ElementaryNode): pass +class SymbolNode(ElementaryNode[str]): + pass + @dataclass(unsafe_hash=True) class ArgumentNode(BaseNode): arguments: T.List[BaseNode] = field(hash=False) - commas: T.List[Token] = field(hash=False) + commas: T.List[SymbolNode] = field(hash=False) + columns: T.List[SymbolNode] = field(hash=False) kwargs: T.Dict[BaseNode, BaseNode] = field(hash=False) def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) self.arguments = [] self.commas = [] + self.columns = [] self.kwargs = {} self.order_error = False @@ -363,20 +372,30 @@ def __len__(self) -> int: @dataclass(unsafe_hash=True) class ArrayNode(BaseNode): + lbracket: SymbolNode args: ArgumentNode + rbracket: SymbolNode - def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + def __init__(self, lbracket: SymbolNode, args: ArgumentNode, rbracket: SymbolNode, + lineno: int, colno: int, end_lineno: int, end_colno: int): super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + self.lbracket = lbracket self.args = args + self.rbracket = rbracket @dataclass(unsafe_hash=True) class DictNode(BaseNode): + lcurl: SymbolNode args: ArgumentNode + rcurl: SymbolNode - def __init__(self, args: ArgumentNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + def __init__(self, lcurl: SymbolNode, args: ArgumentNode, rcurl: SymbolNode, + lineno: int, colno: int, end_lineno: int, end_colno: int): super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + self.lcurl = lcurl self.args = args + self.rcurl = rcurl class EmptyNode(BaseNode): pass @@ -385,34 +404,40 @@ class EmptyNode(BaseNode): class OrNode(BaseNode): left: BaseNode + operator: SymbolNode right: BaseNode - def __init__(self, left: BaseNode, right: BaseNode): + def __init__(self, left: BaseNode, operator: SymbolNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) self.left = left + self.operator = operator self.right = right @dataclass(unsafe_hash=True) class AndNode(BaseNode): left: BaseNode + operator: SymbolNode right: BaseNode - def __init__(self, left: BaseNode, right: BaseNode): + def __init__(self, left: BaseNode, operator: SymbolNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) self.left = left + self.operator = operator self.right = right @dataclass(unsafe_hash=True) class ComparisonNode(BaseNode): left: BaseNode + operator: SymbolNode right: BaseNode ctype: COMPARISONS - def __init__(self, ctype: COMPARISONS, left: BaseNode, right: BaseNode): + def __init__(self, ctype: COMPARISONS, left: BaseNode, operator: SymbolNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) self.left = left + self.operator = operator self.right = right self.ctype = ctype @@ -423,21 +448,25 @@ class ArithmeticNode(BaseNode): right: BaseNode # TODO: use a Literal for operation operation: str + operator: SymbolNode - def __init__(self, operation: str, left: BaseNode, right: BaseNode): + def __init__(self, operation: str, left: BaseNode, operator: SymbolNode, right: BaseNode): super().__init__(left.lineno, left.colno, left.filename) self.left = left self.right = right self.operation = operation + self.operator = operator @dataclass(unsafe_hash=True) class NotNode(BaseNode): + operator: SymbolNode value: BaseNode - def __init__(self, token: Token[TV_TokenTypes], value: BaseNode): + def __init__(self, token: Token[TV_TokenTypes], operator: SymbolNode, value: BaseNode): super().__init__(token.lineno, token.colno, token.filename) + self.operator = operator self.value = value @dataclass(unsafe_hash=True) @@ -447,53 +476,73 @@ class CodeBlockNode(BaseNode): def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) + self.pre_whitespaces = None self.lines = [] @dataclass(unsafe_hash=True) class IndexNode(BaseNode): iobject: BaseNode + lbracket: SymbolNode index: BaseNode + rbracket: SymbolNode - def __init__(self, iobject: BaseNode, index: BaseNode): + def __init__(self, iobject: BaseNode, lbracket: SymbolNode, index: BaseNode, rbracket: SymbolNode): super().__init__(iobject.lineno, iobject.colno, iobject.filename) self.iobject = iobject + self.lbracket = lbracket self.index = index + self.rbracket = rbracket @dataclass(unsafe_hash=True) class MethodNode(BaseNode): source_object: BaseNode + dot: SymbolNode name: IdNode + lpar: SymbolNode args: ArgumentNode + rpar: SymbolNode - def __init__(self, filename: str, lineno: int, colno: int, source_object: BaseNode, name: IdNode, args: ArgumentNode): + def __init__(self, filename: str, lineno: int, colno: int, + source_object: BaseNode, dot: SymbolNode, name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): super().__init__(lineno, colno, filename) self.source_object = source_object + self.dot = dot self.name = name + self.lpar = lpar self.args = args + self.rpar = rpar @dataclass(unsafe_hash=True) class FunctionNode(BaseNode): func_name: IdNode + lpar: SymbolNode args: ArgumentNode + rpar: SymbolNode - def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, func_name: IdNode, args: ArgumentNode): + def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, + func_name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno) self.func_name = func_name + self.lpar = lpar self.args = args + self.rpar = rpar @dataclass(unsafe_hash=True) class AssignmentNode(BaseNode): var_name: IdNode + operator: SymbolNode value: BaseNode - def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, value: BaseNode): + def __init__(self, filename: str, lineno: int, colno: int, + var_name: IdNode, operator: SymbolNode, value: BaseNode): super().__init__(lineno, colno, filename) self.var_name = var_name + self.operator = operator self.value = value @@ -501,46 +550,61 @@ def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, val class PlusAssignmentNode(BaseNode): var_name: IdNode + operator: SymbolNode value: BaseNode - def __init__(self, filename: str, lineno: int, colno: int, var_name: IdNode, value: BaseNode): + def __init__(self, filename: str, lineno: int, colno: int, + var_name: IdNode, operator: SymbolNode, value: BaseNode): super().__init__(lineno, colno, filename) self.var_name = var_name + self.operator = operator self.value = value @dataclass(unsafe_hash=True) class ForeachClauseNode(BaseNode): + foreach_: SymbolNode = field(hash=False) varnames: T.List[IdNode] = field(hash=False) + commas: T.List[SymbolNode] = field(hash=False) + column: SymbolNode = field(hash=False) items: BaseNode block: CodeBlockNode + endforeach: SymbolNode = field(hash=False) - def __init__(self, token: Token, varnames: T.List[IdNode], items: BaseNode, block: CodeBlockNode): - super().__init__(token.lineno, token.colno, token.filename) + def __init__(self, foreach_: SymbolNode, varnames: T.List[IdNode], commas: T.List[SymbolNode], column: SymbolNode, items: BaseNode, block: CodeBlockNode, endforeach: SymbolNode): + super().__init__(foreach_.lineno, foreach_.colno, foreach_.filename) + self.foreach_ = foreach_ self.varnames = varnames + self.commas = commas + self.column = column self.items = items self.block = block + self.endforeach = endforeach @dataclass(unsafe_hash=True) class IfNode(BaseNode): + if_: SymbolNode condition: BaseNode block: CodeBlockNode - def __init__(self, linenode: BaseNode, condition: BaseNode, block: CodeBlockNode): + def __init__(self, linenode: BaseNode, if_node: SymbolNode, condition: BaseNode, block: CodeBlockNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) + self.if_ = if_node self.condition = condition self.block = block @dataclass(unsafe_hash=True) class ElseNode(BaseNode): + else_: SymbolNode block: CodeBlockNode - def __init__(self, block: CodeBlockNode): + def __init__(self, else_: SymbolNode, block: CodeBlockNode): super().__init__(block.lineno, block.colno, block.filename) + self.else_ = else_ self.block = block @dataclass(unsafe_hash=True) @@ -548,30 +612,38 @@ class IfClauseNode(BaseNode): ifs: T.List[IfNode] = field(hash=False) elseblock: T.Union[EmptyNode, ElseNode] + endif: SymbolNode def __init__(self, linenode: BaseNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) self.ifs = [] self.elseblock = EmptyNode(linenode.lineno, linenode.colno, linenode.filename) + self.endif = None @dataclass(unsafe_hash=True) class TestCaseClauseNode(BaseNode): + testcase: SymbolNode condition: BaseNode block: CodeBlockNode + endtestcase: SymbolNode - def __init__(self, condition: BaseNode, block: CodeBlockNode): + def __init__(self, testcase: SymbolNode, condition: BaseNode, block: CodeBlockNode, endtestcase: SymbolNode): super().__init__(condition.lineno, condition.colno, condition.filename) + self.testcase = testcase self.condition = condition self.block = block + self.endtestcase = endtestcase @dataclass(unsafe_hash=True) class UMinusNode(BaseNode): + operator: SymbolNode value: BaseNode - def __init__(self, current_location: Token, value: BaseNode): + def __init__(self, current_location: Token, operator: SymbolNode, value: BaseNode): super().__init__(current_location.lineno, current_location.colno, current_location.filename) + self.operator = operator self.value = value @@ -579,23 +651,32 @@ def __init__(self, current_location: Token, value: BaseNode): class TernaryNode(BaseNode): condition: BaseNode + questionmark: SymbolNode trueblock: BaseNode + column: SymbolNode falseblock: BaseNode - def __init__(self, condition: BaseNode, trueblock: BaseNode, falseblock: BaseNode): + def __init__(self, condition: BaseNode, questionmark: SymbolNode, trueblock: BaseNode, column: SymbolNode, falseblock: BaseNode): super().__init__(condition.lineno, condition.colno, condition.filename) self.condition = condition + self.questionmark = questionmark self.trueblock = trueblock + self.column = column self.falseblock = falseblock + @dataclass(unsafe_hash=True) class ParenthesizedNode(BaseNode): + lpar: SymbolNode = field(hash=False) inner: BaseNode + rpar: SymbolNode = field(hash=False) - def __init__(self, inner: BaseNode, lineno: int, colno: int, end_lineno: int, end_colno: int): + def __init__(self, lpar: SymbolNode, inner: BaseNode, rpar: SymbolNode, lineno: int, colno: int, end_lineno: int, end_colno: int): super().__init__(lineno, colno, inner.filename, end_lineno=end_lineno, end_colno=end_colno) + self.lpar = lpar self.inner = inner + self.rpar = rpar if T.TYPE_CHECKING: COMPARISONS = Literal['==', '!=', '<', '<=', '>=', '>', 'in', 'notin'] @@ -632,13 +713,19 @@ def __init__(self, code: str, filename: str): self.stream = self.lexer.lex(filename) self.current: Token = Token('eof', '', 0, 0, 0, (0, 0), None) self.previous = self.current + self.getsym() self.in_ternary = False + def create_node(self, node_type: T.Type[BaseNodeT], *args: T.Any, **kwargs: T.Any) -> BaseNodeT: + node = node_type(*args, **kwargs) + return node + def getsym(self) -> None: self.previous = self.current try: self.current = next(self.stream) + except StopIteration: self.current = Token('eof', '', self.current.line_start, self.current.lineno, self.current.colno + self.current.bytespan[1] - self.current.bytespan[0], (0, 0), None) @@ -683,55 +770,69 @@ def statement(self) -> BaseNode: def e1(self) -> BaseNode: left = self.e2() if self.accept('plusassign'): + operator = self.create_node(SymbolNode, self.previous) value = self.e1() if not isinstance(left, IdNode): raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return PlusAssignmentNode(left.filename, left.lineno, left.colno, left, value) + return self.create_node(PlusAssignmentNode, left.filename, left.lineno, left.colno, left, operator, value) elif self.accept('assign'): + operator = self.create_node(SymbolNode, self.previous) value = self.e1() if not isinstance(left, IdNode): raise ParseException('Assignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return AssignmentNode(left.filename, left.lineno, left.colno, left, value) + return self.create_node(AssignmentNode, left.filename, left.lineno, left.colno, left, operator, value) elif self.accept('questionmark'): if self.in_ternary: raise ParseException('Nested ternary operators are not allowed.', self.getline(), left.lineno, left.colno) + + qm_node = self.create_node(SymbolNode, self.previous) self.in_ternary = True trueblock = self.e1() self.expect('colon') + column_node = self.create_node(SymbolNode, self.previous) falseblock = self.e1() self.in_ternary = False - return TernaryNode(left, trueblock, falseblock) + return self.create_node(TernaryNode, left, qm_node, trueblock, column_node, falseblock) return left def e2(self) -> BaseNode: left = self.e3() while self.accept('or'): + operator = self.create_node(SymbolNode, self.previous) if isinstance(left, EmptyNode): raise ParseException('Invalid or clause.', self.getline(), left.lineno, left.colno) - left = OrNode(left, self.e3()) + left = self.create_node(OrNode, left, operator, self.e3()) return left def e3(self) -> BaseNode: left = self.e4() while self.accept('and'): + operator = self.create_node(SymbolNode, self.previous) if isinstance(left, EmptyNode): raise ParseException('Invalid and clause.', self.getline(), left.lineno, left.colno) - left = AndNode(left, self.e4()) + left = self.create_node(AndNode, left, operator, self.e4()) return left def e4(self) -> BaseNode: left = self.e5() for nodename, operator_type in comparison_map.items(): if self.accept(nodename): - return ComparisonNode(operator_type, left, self.e5()) - if self.accept('not') and self.accept('in'): - return ComparisonNode('notin', left, self.e5()) + operator = self.create_node(SymbolNode, self.previous) + return self.create_node(ComparisonNode, operator_type, left, operator, self.e5()) + if self.accept('not'): + not_token = self.previous + if self.accept('in'): + in_token = self.previous + not_token.bytespan = (not_token.bytespan[0], in_token.bytespan[1]) + not_token.value += in_token.value + operator = self.create_node(SymbolNode, not_token) + return self.create_node(ComparisonNode, 'notin', left, operator, self.e5()) return left def e5(self) -> BaseNode: @@ -746,7 +847,8 @@ def e5addsub(self) -> BaseNode: while True: op = self.accept_any(tuple(op_map.keys())) if op: - left = ArithmeticNode(op_map[op], left, self.e5muldiv()) + operator = self.create_node(SymbolNode, self.previous) + left = self.create_node(ArithmeticNode, op_map[op], left, operator, self.e5muldiv()) else: break return left @@ -761,29 +863,34 @@ def e5muldiv(self) -> BaseNode: while True: op = self.accept_any(tuple(op_map.keys())) if op: - left = ArithmeticNode(op_map[op], left, self.e6()) + operator = self.create_node(SymbolNode, self.previous) + left = self.create_node(ArithmeticNode, op_map[op], left, operator, self.e6()) else: break return left def e6(self) -> BaseNode: if self.accept('not'): - return NotNode(self.current, self.e7()) + operator = self.create_node(SymbolNode, self.previous) + return self.create_node(NotNode, self.current, operator, self.e7()) if self.accept('dash'): - return UMinusNode(self.current, self.e7()) + operator = self.create_node(SymbolNode, self.previous) + return self.create_node(UMinusNode, self.current, operator, self.e7()) return self.e7() def e7(self) -> BaseNode: left = self.e8() block_start = self.current if self.accept('lparen'): + lpar = self.create_node(SymbolNode, block_start) args = self.args() self.block_expect('rparen', block_start) + rpar = self.create_node(SymbolNode, self.previous) if not isinstance(left, IdNode): raise ParseException('Function call must be applied to plain id', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - left = FunctionNode(left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left, args) + left = self.create_node(FunctionNode, left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left, lpar, args, rpar) go_again = True while go_again: go_again = False @@ -798,17 +905,23 @@ def e7(self) -> BaseNode: def e8(self) -> BaseNode: block_start = self.current if self.accept('lparen'): + lpar = self.create_node(SymbolNode, block_start) e = self.statement() self.block_expect('rparen', block_start) - return ParenthesizedNode(e, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + rpar = self.create_node(SymbolNode, self.previous) + return ParenthesizedNode(lpar, e, rpar, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) elif self.accept('lbracket'): + lbracket = self.create_node(SymbolNode, block_start) args = self.args() self.block_expect('rbracket', block_start) - return ArrayNode(args, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + rbracket = self.create_node(SymbolNode, self.previous) + return self.create_node(ArrayNode, lbracket, args, rbracket, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) elif self.accept('lcurl'): + lcurl = self.create_node(SymbolNode, block_start) key_values = self.key_values() self.block_expect('rcurl', block_start) - return DictNode(key_values, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + rcurl = self.create_node(SymbolNode, self.previous) + return self.create_node(DictNode, lcurl, key_values, rcurl, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) else: return self.e9() @@ -816,34 +929,35 @@ def e9(self) -> BaseNode: t = self.current if self.accept('true'): t.value = True - return BooleanNode(t) + return self.create_node(BooleanNode, t) if self.accept('false'): t.value = False - return BooleanNode(t) + return self.create_node(BooleanNode, t) if self.accept('id'): - return IdNode(t) + return self.create_node(IdNode, t) if self.accept('number'): - return NumberNode(t) + return self.create_node(NumberNode, t) if self.accept('string'): - return StringNode(t) + return self.create_node(StringNode, t) if self.accept('fstring'): - return FormatStringNode(t) + return self.create_node(FormatStringNode, t) if self.accept('multiline_string'): - return MultilineStringNode(t) + return self.create_node(MultilineStringNode, t) if self.accept('multiline_fstring'): - return MultilineFormatStringNode(t) + return self.create_node(MultilineFormatStringNode, t) return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) def key_values(self) -> ArgumentNode: s = self.statement() - a = ArgumentNode(self.current) + a = self.create_node(ArgumentNode, self.current) while not isinstance(s, EmptyNode): if self.accept('colon'): + a.columns.append(self.create_node(SymbolNode, self.previous)) a.set_kwarg_no_check(s, self.statement()) if not self.accept('comma'): return a - a.commas.append(self.previous) + a.commas.append(self.create_node(SymbolNode, self.previous)) else: raise ParseException('Only key:value pairs are valid in dict construction.', self.getline(), s.lineno, s.colno) @@ -852,20 +966,21 @@ def key_values(self) -> ArgumentNode: def args(self) -> ArgumentNode: s = self.statement() - a = ArgumentNode(self.current) + a = self.create_node(ArgumentNode, self.current) while not isinstance(s, EmptyNode): if self.accept('comma'): - a.commas.append(self.previous) + a.commas.append(self.create_node(SymbolNode, self.previous)) a.append(s) elif self.accept('colon'): + a.columns.append(self.create_node(SymbolNode, self.previous)) if not isinstance(s, IdNode): raise ParseException('Dictionary key must be a plain identifier.', self.getline(), s.lineno, s.colno) a.set_kwarg(s, self.statement()) if not self.accept('comma'): return a - a.commas.append(self.previous) + a.commas.append(self.create_node(SymbolNode, self.previous)) else: a.append(s) return a @@ -873,6 +988,7 @@ def args(self) -> ArgumentNode: return a def method_call(self, source_object: BaseNode) -> MethodNode: + dot = self.create_node(SymbolNode, self.previous) methodname = self.e9() if not isinstance(methodname, IdNode): if isinstance(source_object, NumberNode) and isinstance(methodname, NumberNode): @@ -882,63 +998,78 @@ def method_call(self, source_object: BaseNode) -> MethodNode: self.getline(), self.current.lineno, self.current.colno) assert isinstance(methodname.value, str) self.expect('lparen') + lpar = self.create_node(SymbolNode, self.previous) args = self.args() + rpar = self.create_node(SymbolNode, self.current) self.expect('rparen') - method = MethodNode(methodname.filename, methodname.lineno, methodname.colno, source_object, methodname, args) + method = self.create_node(MethodNode, methodname.filename, methodname.lineno, methodname.colno, + source_object, dot, methodname, lpar, args, rpar) if self.accept('dot'): return self.method_call(method) return method def index_call(self, source_object: BaseNode) -> IndexNode: + lbracket = self.create_node(SymbolNode, self.previous) index_statement = self.statement() self.expect('rbracket') - return IndexNode(source_object, index_statement) + rbracket = self.create_node(SymbolNode, self.previous) + return self.create_node(IndexNode, source_object, lbracket, index_statement, rbracket) def foreachblock(self) -> ForeachClauseNode: + foreach_ = self.create_node(SymbolNode, self.previous) self.expect('id') assert isinstance(self.previous.value, str) - varname = self.previous - varnames = [IdNode(self.previous)] + varnames = [self.create_node(IdNode, self.previous)] + commas = [] if self.accept('comma'): + commas.append(self.create_node(SymbolNode, self.previous)) self.expect('id') assert isinstance(self.previous.value, str) - varnames.append(IdNode(self.previous)) + varnames.append(self.create_node(IdNode, self.previous)) self.expect('colon') + column = self.create_node(SymbolNode, self.previous) items = self.statement() block = self.codeblock() - return ForeachClauseNode(varname, varnames, items, block) + endforeach = self.create_node(SymbolNode, self.current) + return self.create_node(ForeachClauseNode, foreach_, varnames, commas, column, items, block, endforeach) def ifblock(self) -> IfClauseNode: + if_node = self.create_node(SymbolNode, self.previous) condition = self.statement() - clause = IfClauseNode(condition) + clause = self.create_node(IfClauseNode, condition) self.expect('eol') block = self.codeblock() - clause.ifs.append(IfNode(clause, condition, block)) + clause.ifs.append(self.create_node(IfNode, clause, if_node, condition, block)) self.elseifblock(clause) clause.elseblock = self.elseblock() + clause.endif = self.create_node(SymbolNode, self.current) return clause def elseifblock(self, clause: IfClauseNode) -> None: while self.accept('elif'): + elif_ = self.create_node(SymbolNode, self.previous) s = self.statement() self.expect('eol') b = self.codeblock() - clause.ifs.append(IfNode(s, s, b)) + clause.ifs.append(self.create_node(IfNode, s, elif_, s, b)) def elseblock(self) -> T.Union[ElseNode, EmptyNode]: if self.accept('else'): + else_ = self.create_node(SymbolNode, self.previous) self.expect('eol') block = self.codeblock() - return ElseNode(block) + return ElseNode(else_, block) return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) def testcaseblock(self) -> TestCaseClauseNode: + testcase = self.create_node(SymbolNode, self.previous) condition = self.statement() self.expect('eol') block = self.codeblock() - return TestCaseClauseNode(condition, block) + endtestcase = SymbolNode(self.current) + return self.create_node(TestCaseClauseNode, testcase, condition, block, endtestcase) def line(self) -> BaseNode: block_start = self.current @@ -953,9 +1084,9 @@ def line(self) -> BaseNode: self.block_expect('endforeach', block_start) return forblock if self.accept('continue'): - return ContinueNode(self.current) + return self.create_node(ContinueNode, self.current) if self.accept('break'): - return BreakNode(self.current) + return self.create_node(BreakNode, self.current) if self.lexer.in_unit_test and self.accept('testcase'): block = self.testcaseblock() self.block_expect('endtestcase', block_start) @@ -963,15 +1094,20 @@ def line(self) -> BaseNode: return self.statement() def codeblock(self) -> CodeBlockNode: - block = CodeBlockNode(self.current) + block = self.create_node(CodeBlockNode, self.current) cond = True + try: while cond: curline = self.line() + if not isinstance(curline, EmptyNode): block.lines.append(curline) + cond = self.accept('eol') + except ParseException as e: e.ast = block raise + return block diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index af3210cf3315..64eb2f2f1873 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -28,7 +28,7 @@ from mesonbuild.mesonlib import MesonException, setup_vsenv from . import mlog, environment from functools import wraps -from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseStringNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode +from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseStringNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode, SymbolNode import json, os, re, sys import typing as T @@ -104,6 +104,9 @@ def wrapped(*wrapped_args, **wrapped_kwargs): return wrapped +def _symbol(val: str) -> SymbolNode: + return SymbolNode(Token('', '', 0, 0, 0, (0, 0), val)) + class MTypeBase: def __init__(self, node: T.Optional[BaseNode] = None): if node is None: @@ -189,7 +192,7 @@ def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) def _new_node(self): - return ArrayNode(ArgumentNode(Token('', '', 0, 0, 0, None, '')), 0, 0, 0, 0) + return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']'), 0, 0, 0, 0) def _new_element_node(self, value): # Overwrite in derived class @@ -728,7 +731,7 @@ def find_node(src): node = tgt_function.args.kwargs[extra_files_key] except StopIteration: # Target has no extra_files kwarg, create one - node = ArrayNode(ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno) + node = ArrayNode(_symbol('['), ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), _symbol(']'), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno) tgt_function.args.kwargs[IdNode(Token('string', tgt_function.filename, 0, 0, 0, None, 'extra_files'))] = node mark_array = False if tgt_function not in self.modified_nodes: @@ -812,17 +815,17 @@ def find_node(src): # Build src list src_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - src_arr_node = ArrayNode(src_arg_node, 0, 0, 0, 0) + src_arr_node = ArrayNode(_symbol('['), src_arg_node, _symbol(']'), 0, 0, 0, 0) src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - src_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), src_far_node) - src_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), src_fun_node) + src_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), _symbol('('), src_far_node, _symbol(')')) + src_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), _symbol('='), src_fun_node) src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']] src_far_node.arguments = [src_arr_node] # Build target tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), tgt_arg_node) - tgt_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), tgt_fun_node) + tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), _symbol('('), tgt_arg_node, _symbol(')')) + tgt_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), _symbol('='), tgt_fun_node) tgt_arg_node.arguments = [ StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])), IdNode(Token('string', filename, 0, 0, 0, None, source_id)) From 0f4891cdf46e28d900cc35d57999fecff3ba8598 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 09:58:32 -0400 Subject: [PATCH 211/855] parser: simplify Assignment and PlusAssignment nodes --- mesonbuild/cargo/builder.py | 2 +- mesonbuild/cmake/interpreter.py | 2 +- mesonbuild/interpreterbase/interpreterbase.py | 4 +-- mesonbuild/mparser.py | 27 +++++-------------- mesonbuild/rewriter.py | 4 +-- 5 files changed, 12 insertions(+), 27 deletions(-) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 9c650b945864..76d2e8bbab9e 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -172,7 +172,7 @@ def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.Assi :param filename: The filename :return: An AssignmentNode """ - return mparser.AssignmentNode(filename, -1, -1, identifier(varname, filename), _symbol(filename, '='), value) + return mparser.AssignmentNode(identifier(varname, filename), _symbol(filename, '='), value) def block(filename: str) -> mparser.CodeBlockNode: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 4f3b31e59440..88e5183bc7f6 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -1021,7 +1021,7 @@ def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, k return MethodNode(self.subdir.as_posix(), 0, 0, obj, symbol('.'), id_node(name), symbol('('), args_n, symbol(')')) def assign(var_name: str, value: BaseNode) -> AssignmentNode: - return AssignmentNode(self.subdir.as_posix(), 0, 0, id_node(var_name), symbol('='), value) + return AssignmentNode(id_node(var_name), symbol('='), value) # Generate the root code block and the project function call root_cb = CodeBlockNode(token()) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 5b07dc0752ab..ea6e37ca67ae 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -192,6 +192,8 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj self.current_node = cur if isinstance(cur, mparser.FunctionNode): return self.function_call(cur) + elif isinstance(cur, mparser.PlusAssignmentNode): + self.evaluate_plusassign(cur) elif isinstance(cur, mparser.AssignmentNode): self.assignment(cur) elif isinstance(cur, mparser.MethodNode): @@ -229,8 +231,6 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj return self.evaluate_arithmeticstatement(cur) elif isinstance(cur, mparser.ForeachClauseNode): self.evaluate_foreach(cur) - elif isinstance(cur, mparser.PlusAssignmentNode): - self.evaluate_plusassign(cur) elif isinstance(cur, mparser.IndexNode): return self.evaluate_indexing(cur) elif isinstance(cur, mparser.TernaryNode): diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 7f329dd0acfa..ffe775037153 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -530,7 +530,6 @@ def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_ self.args = args self.rpar = rpar - @dataclass(unsafe_hash=True) class AssignmentNode(BaseNode): @@ -538,28 +537,14 @@ class AssignmentNode(BaseNode): operator: SymbolNode value: BaseNode - def __init__(self, filename: str, lineno: int, colno: int, - var_name: IdNode, operator: SymbolNode, value: BaseNode): - super().__init__(lineno, colno, filename) - self.var_name = var_name - self.operator = operator - self.value = value - - -@dataclass(unsafe_hash=True) -class PlusAssignmentNode(BaseNode): - - var_name: IdNode - operator: SymbolNode - value: BaseNode - - def __init__(self, filename: str, lineno: int, colno: int, - var_name: IdNode, operator: SymbolNode, value: BaseNode): - super().__init__(lineno, colno, filename) + def __init__(self, var_name: IdNode, operator: SymbolNode, value: BaseNode): + super().__init__(var_name.lineno, var_name.colno, var_name.filename) self.var_name = var_name self.operator = operator self.value = value +class PlusAssignmentNode(AssignmentNode): + pass @dataclass(unsafe_hash=True) class ForeachClauseNode(BaseNode): @@ -775,7 +760,7 @@ def e1(self) -> BaseNode: if not isinstance(left, IdNode): raise ParseException('Plusassignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return self.create_node(PlusAssignmentNode, left.filename, left.lineno, left.colno, left, operator, value) + return self.create_node(PlusAssignmentNode, left, operator, value) elif self.accept('assign'): operator = self.create_node(SymbolNode, self.previous) value = self.e1() @@ -783,7 +768,7 @@ def e1(self) -> BaseNode: raise ParseException('Assignment target must be an id.', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - return self.create_node(AssignmentNode, left.filename, left.lineno, left.colno, left, operator, value) + return self.create_node(AssignmentNode, left, operator, value) elif self.accept('questionmark'): if self.in_ternary: raise ParseException('Nested ternary operators are not allowed.', diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 64eb2f2f1873..7527daba12f8 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -818,14 +818,14 @@ def find_node(src): src_arr_node = ArrayNode(_symbol('['), src_arg_node, _symbol(']'), 0, 0, 0, 0) src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) src_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), _symbol('('), src_far_node, _symbol(')')) - src_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), _symbol('='), src_fun_node) + src_ass_node = AssignmentNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), _symbol('='), src_fun_node) src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']] src_far_node.arguments = [src_arr_node] # Build target tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), _symbol('('), tgt_arg_node, _symbol(')')) - tgt_ass_node = AssignmentNode(filename, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), _symbol('='), tgt_fun_node) + tgt_ass_node = AssignmentNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), _symbol('='), tgt_fun_node) tgt_arg_node.arguments = [ StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])), IdNode(Token('string', filename, 0, 0, 0, None, source_id)) From 13ddf8bd025c3ff6257049cab6f3df1072ac0daf Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 09:41:47 -0400 Subject: [PATCH 212/855] parser: simplify by using Unary and Binary Operator Node --- mesonbuild/mparser.py | 59 +++++++++++++------------------------------ 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index ffe775037153..00b87318cb31 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -401,7 +401,7 @@ class EmptyNode(BaseNode): pass @dataclass(unsafe_hash=True) -class OrNode(BaseNode): +class BinaryOperatorNode(BaseNode): left: BaseNode operator: SymbolNode @@ -413,53 +413,33 @@ def __init__(self, left: BaseNode, operator: SymbolNode, right: BaseNode): self.operator = operator self.right = right -@dataclass(unsafe_hash=True) -class AndNode(BaseNode): - - left: BaseNode - operator: SymbolNode - right: BaseNode +class OrNode(BinaryOperatorNode): + pass - def __init__(self, left: BaseNode, operator: SymbolNode, right: BaseNode): - super().__init__(left.lineno, left.colno, left.filename) - self.left = left - self.operator = operator - self.right = right +class AndNode(BinaryOperatorNode): + pass @dataclass(unsafe_hash=True) -class ComparisonNode(BaseNode): +class ComparisonNode(BinaryOperatorNode): - left: BaseNode - operator: SymbolNode - right: BaseNode ctype: COMPARISONS def __init__(self, ctype: COMPARISONS, left: BaseNode, operator: SymbolNode, right: BaseNode): - super().__init__(left.lineno, left.colno, left.filename) - self.left = left - self.operator = operator - self.right = right + super().__init__(left, operator, right) self.ctype = ctype @dataclass(unsafe_hash=True) -class ArithmeticNode(BaseNode): +class ArithmeticNode(BinaryOperatorNode): - left: BaseNode - right: BaseNode # TODO: use a Literal for operation operation: str - operator: SymbolNode def __init__(self, operation: str, left: BaseNode, operator: SymbolNode, right: BaseNode): - super().__init__(left.lineno, left.colno, left.filename) - self.left = left - self.right = right + super().__init__(left, operator, right) self.operation = operation - self.operator = operator - @dataclass(unsafe_hash=True) -class NotNode(BaseNode): +class UnaryOperatorNode(BaseNode): operator: SymbolNode value: BaseNode @@ -469,6 +449,12 @@ def __init__(self, token: Token[TV_TokenTypes], operator: SymbolNode, value: Bas self.operator = operator self.value = value +class NotNode(UnaryOperatorNode): + pass + +class UMinusNode(UnaryOperatorNode): + pass + @dataclass(unsafe_hash=True) class CodeBlockNode(BaseNode): @@ -620,18 +606,6 @@ def __init__(self, testcase: SymbolNode, condition: BaseNode, block: CodeBlockNo self.block = block self.endtestcase = endtestcase -@dataclass(unsafe_hash=True) -class UMinusNode(BaseNode): - - operator: SymbolNode - value: BaseNode - - def __init__(self, current_location: Token, operator: SymbolNode, value: BaseNode): - super().__init__(current_location.lineno, current_location.colno, current_location.filename) - self.operator = operator - self.value = value - - @dataclass(unsafe_hash=True) class TernaryNode(BaseNode): @@ -663,6 +637,7 @@ def __init__(self, lpar: SymbolNode, inner: BaseNode, rpar: SymbolNode, lineno: self.inner = inner self.rpar = rpar + if T.TYPE_CHECKING: COMPARISONS = Literal['==', '!=', '<', '<=', '>=', '>', 'in', 'notin'] From 5b29eff8ad02348ff0495cd307b29259567e11df Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 10:21:53 -0400 Subject: [PATCH 213/855] parser: simplify other node constructors --- mesonbuild/cargo/builder.py | 6 +++--- mesonbuild/cmake/interpreter.py | 6 +++--- mesonbuild/mparser.py | 35 ++++++++++++++------------------- mesonbuild/rewriter.py | 10 +++++----- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 76d2e8bbab9e..3f7f6885e3d6 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -71,7 +71,7 @@ def array(value: T.List[mparser.BaseNode], filename: str) -> mparser.ArrayNode: """ args = mparser.ArgumentNode(_token('array', filename, 'unused')) args.arguments = value - return mparser.ArrayNode(_symbol(filename, '['), args, _symbol(filename, ']'), -1, -1, -1, -1) + return mparser.ArrayNode(_symbol(filename, '['), args, _symbol(filename, ']')) def identifier(value: str, filename: str) -> mparser.IdNode: @@ -101,7 +101,7 @@ def method(name: str, id_: mparser.IdNode, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} - return mparser.MethodNode(id_.filename, -1, -1, id_, _symbol(id_.filename, '.'), identifier(name, id_.filename), _symbol(id_.filename, '('), args, _symbol(id_.filename, ')')) + return mparser.MethodNode(id_, _symbol(id_.filename, '.'), identifier(name, id_.filename), _symbol(id_.filename, '('), args, _symbol(id_.filename, ')')) def function(name: str, filename: str, @@ -121,7 +121,7 @@ def function(name: str, filename: str, args.arguments = pos if kw is not None: args.kwargs = {identifier(k, filename): v for k, v in kw.items()} - return mparser.FunctionNode(filename, -1, -1, -1, -1, identifier(name, filename), _symbol(filename, '('), args, _symbol(filename, ')')) + return mparser.FunctionNode(identifier(name, filename), _symbol(filename, '('), args, _symbol(filename, ')')) def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 88e5183bc7f6..2f7cb69114f6 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -995,7 +995,7 @@ def array(elements: TYPE_mixed_list) -> ArrayNode: if not isinstance(elements, list): elements = [args] args.arguments += [nodeify(x) for x in elements if x is not None] - return ArrayNode(symbol('['), args, symbol(']'), 0, 0, 0, 0) + return ArrayNode(symbol('['), args, symbol(']')) def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> FunctionNode: args = [] if args is None else args @@ -1006,7 +1006,7 @@ def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Opti args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - func_n = FunctionNode(self.subdir.as_posix(), 0, 0, 0, 0, id_node(name), symbol('('), args_n, symbol(')')) + func_n = FunctionNode(id_node(name), symbol('('), args_n, symbol(')')) return func_n def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode: @@ -1018,7 +1018,7 @@ def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, k args = [args] args_n.arguments = [nodeify(x) for x in args if x is not None] args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None} - return MethodNode(self.subdir.as_posix(), 0, 0, obj, symbol('.'), id_node(name), symbol('('), args_n, symbol(')')) + return MethodNode(obj, symbol('.'), id_node(name), symbol('('), args_n, symbol(')')) def assign(var_name: str, value: BaseNode) -> AssignmentNode: return AssignmentNode(id_node(var_name), symbol('='), value) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 00b87318cb31..75a12aa4ca08 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -376,9 +376,8 @@ class ArrayNode(BaseNode): args: ArgumentNode rbracket: SymbolNode - def __init__(self, lbracket: SymbolNode, args: ArgumentNode, rbracket: SymbolNode, - lineno: int, colno: int, end_lineno: int, end_colno: int): - super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + def __init__(self, lbracket: SymbolNode, args: ArgumentNode, rbracket: SymbolNode): + super().__init__(lbracket.lineno, lbracket.colno, args.filename, end_lineno=rbracket.lineno, end_colno=rbracket.colno+1) self.lbracket = lbracket self.args = args self.rbracket = rbracket @@ -390,9 +389,8 @@ class DictNode(BaseNode): args: ArgumentNode rcurl: SymbolNode - def __init__(self, lcurl: SymbolNode, args: ArgumentNode, rcurl: SymbolNode, - lineno: int, colno: int, end_lineno: int, end_colno: int): - super().__init__(lineno, colno, args.filename, end_lineno=end_lineno, end_colno=end_colno) + def __init__(self, lcurl: SymbolNode, args: ArgumentNode, rcurl: SymbolNode): + super().__init__(lcurl.lineno, lcurl.colno, args.filename, end_lineno=rcurl.lineno, end_colno=rcurl.colno+1) self.lcurl = lcurl self.args = args self.rcurl = rcurl @@ -490,9 +488,8 @@ class MethodNode(BaseNode): args: ArgumentNode rpar: SymbolNode - def __init__(self, filename: str, lineno: int, colno: int, - source_object: BaseNode, dot: SymbolNode, name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): - super().__init__(lineno, colno, filename) + def __init__(self, source_object: BaseNode, dot: SymbolNode, name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): + super().__init__(name.lineno, name.colno, name.filename, end_lineno=rpar.lineno, end_colno=rpar.colno+1) self.source_object = source_object self.dot = dot self.name = name @@ -508,9 +505,8 @@ class FunctionNode(BaseNode): args: ArgumentNode rpar: SymbolNode - def __init__(self, filename: str, lineno: int, colno: int, end_lineno: int, end_colno: int, - func_name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): - super().__init__(lineno, colno, filename, end_lineno=end_lineno, end_colno=end_colno) + def __init__(self, func_name: IdNode, lpar: SymbolNode, args: ArgumentNode, rpar: SymbolNode): + super().__init__(func_name.lineno, func_name.colno, func_name.filename, end_lineno=rpar.end_lineno, end_colno=rpar.end_colno+1) self.func_name = func_name self.lpar = lpar self.args = args @@ -631,8 +627,8 @@ class ParenthesizedNode(BaseNode): inner: BaseNode rpar: SymbolNode = field(hash=False) - def __init__(self, lpar: SymbolNode, inner: BaseNode, rpar: SymbolNode, lineno: int, colno: int, end_lineno: int, end_colno: int): - super().__init__(lineno, colno, inner.filename, end_lineno=end_lineno, end_colno=end_colno) + def __init__(self, lpar: SymbolNode, inner: BaseNode, rpar: SymbolNode): + super().__init__(lpar.lineno, lpar.colno, inner.filename, end_lineno=rpar.lineno, end_colno=rpar.colno+1) self.lpar = lpar self.inner = inner self.rpar = rpar @@ -850,7 +846,7 @@ def e7(self) -> BaseNode: raise ParseException('Function call must be applied to plain id', self.getline(), left.lineno, left.colno) assert isinstance(left.value, str) - left = self.create_node(FunctionNode, left.filename, left.lineno, left.colno, self.current.lineno, self.current.colno, left, lpar, args, rpar) + left = self.create_node(FunctionNode, left, lpar, args, rpar) go_again = True while go_again: go_again = False @@ -869,19 +865,19 @@ def e8(self) -> BaseNode: e = self.statement() self.block_expect('rparen', block_start) rpar = self.create_node(SymbolNode, self.previous) - return ParenthesizedNode(lpar, e, rpar, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + return ParenthesizedNode(lpar, e, rpar) elif self.accept('lbracket'): lbracket = self.create_node(SymbolNode, block_start) args = self.args() self.block_expect('rbracket', block_start) rbracket = self.create_node(SymbolNode, self.previous) - return self.create_node(ArrayNode, lbracket, args, rbracket, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + return self.create_node(ArrayNode, lbracket, args, rbracket) elif self.accept('lcurl'): lcurl = self.create_node(SymbolNode, block_start) key_values = self.key_values() self.block_expect('rcurl', block_start) rcurl = self.create_node(SymbolNode, self.previous) - return self.create_node(DictNode, lcurl, key_values, rcurl, block_start.lineno, block_start.colno, self.current.lineno, self.current.colno) + return self.create_node(DictNode, lcurl, key_values, rcurl) else: return self.e9() @@ -962,8 +958,7 @@ def method_call(self, source_object: BaseNode) -> MethodNode: args = self.args() rpar = self.create_node(SymbolNode, self.current) self.expect('rparen') - method = self.create_node(MethodNode, methodname.filename, methodname.lineno, methodname.colno, - source_object, dot, methodname, lpar, args, rpar) + method = self.create_node(MethodNode, source_object, dot, methodname, lpar, args, rpar) if self.accept('dot'): return self.method_call(method) return method diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 7527daba12f8..a86b97eccabb 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -192,7 +192,7 @@ def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) def _new_node(self): - return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']'), 0, 0, 0, 0) + return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']')) def _new_element_node(self, value): # Overwrite in derived class @@ -731,7 +731,7 @@ def find_node(src): node = tgt_function.args.kwargs[extra_files_key] except StopIteration: # Target has no extra_files kwarg, create one - node = ArrayNode(_symbol('['), ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), _symbol(']'), tgt_function.end_lineno, tgt_function.end_colno, tgt_function.end_lineno, tgt_function.end_colno) + node = ArrayNode(_symbol('['), ArgumentNode(Token('', tgt_function.filename, 0, 0, 0, None, '[]')), _symbol(']')) tgt_function.args.kwargs[IdNode(Token('string', tgt_function.filename, 0, 0, 0, None, 'extra_files'))] = node mark_array = False if tgt_function not in self.modified_nodes: @@ -815,16 +815,16 @@ def find_node(src): # Build src list src_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - src_arr_node = ArrayNode(_symbol('['), src_arg_node, _symbol(']'), 0, 0, 0, 0) + src_arr_node = ArrayNode(_symbol('['), src_arg_node, _symbol(']')) src_far_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - src_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), _symbol('('), src_far_node, _symbol(')')) + src_fun_node = FunctionNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), 'files')), _symbol('('), src_far_node, _symbol(')')) src_ass_node = AssignmentNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), source_id)), _symbol('='), src_fun_node) src_arg_node.arguments = [StringNode(Token('string', filename, 0, 0, 0, None, x)) for x in cmd['sources']] src_far_node.arguments = [src_arr_node] # Build target tgt_arg_node = ArgumentNode(Token('string', filename, 0, 0, 0, None, '')) - tgt_fun_node = FunctionNode(filename, 0, 0, 0, 0, IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), _symbol('('), tgt_arg_node, _symbol(')')) + tgt_fun_node = FunctionNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), cmd['target_type'])), _symbol('('), tgt_arg_node, _symbol(')')) tgt_ass_node = AssignmentNode(IdNode(Token('id', filename, 0, 0, 0, (0, 0), target_id)), _symbol('='), tgt_fun_node) tgt_arg_node.arguments = [ StringNode(Token('string', filename, 0, 0, 0, None, cmd['target'])), From 11ef2a536c6c9fec0b048da74b36a0231ef2199a Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 25 Aug 2023 10:08:24 -0400 Subject: [PATCH 214/855] parser: preserve whitespaces and comments --- mesonbuild/mparser.py | 67 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 75a12aa4ca08..a161842e6d0e 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -116,7 +116,7 @@ def __init__(self, code: str): self.keywords.update({'testcase', 'endtestcase'}) self.token_specification = [ # Need to be sorted longest to shortest. - ('ignore', re.compile(r'[ \t]')), + ('whitespace', re.compile(r'[ \t]+')), ('multiline_fstring', re.compile(r"f'''(.|\n)*?'''", re.M)), ('fstring', re.compile(r"f'([^'\\]|(\\.))*'")), ('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')), @@ -178,9 +178,7 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: span_end = loc bytespan = (span_start, span_end) value = mo.group() - if tid in {'ignore', 'comment'}: - break - elif tid == 'lparen': + if tid == 'lparen': par_count += 1 elif tid == 'rparen': par_count -= 1 @@ -210,12 +208,12 @@ def lex(self, filename: str) -> T.Generator[Token, None, None]: elif tid == 'eol_cont': lineno += 1 line_start = loc - break + tid = 'whitespace' elif tid == 'eol': lineno += 1 line_start = loc if par_count > 0 or bracket_count > 0 or curl_count > 0: - break + tid = 'whitespace' elif tid == 'id': if value in self.keywords: tid = value @@ -235,6 +233,7 @@ class BaseNode: filename: str = field(hash=False) end_lineno: int = field(hash=False) end_colno: int = field(hash=False) + whitespaces: T.Optional[WhitespaceNode] = field(hash=False) def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None: @@ -257,6 +256,26 @@ def accept(self, visitor: 'AstVisitor') -> None: if callable(func): func(self) + def append_whitespaces(self, token: Token) -> None: + if self.whitespaces is None: + self.whitespaces = WhitespaceNode(token) + else: + self.whitespaces.append(token) + + +@dataclass(unsafe_hash=True) +class WhitespaceNode(BaseNode): + + value: str + + def __init__(self, token: Token[str]): + super().__init__(token.lineno, token.colno, token.filename) + self.value = '' + self.append(token) + + def append(self, token: Token[str]) -> None: + self.value += token.value + @dataclass(unsafe_hash=True) class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode): @@ -456,6 +475,7 @@ class UMinusNode(UnaryOperatorNode): @dataclass(unsafe_hash=True) class CodeBlockNode(BaseNode): + pre_whitespaces: T.Optional[WhitespaceNode] = field(hash=False) lines: T.List[BaseNode] = field(hash=False) def __init__(self, token: Token[TV_TokenTypes]): @@ -463,6 +483,14 @@ def __init__(self, token: Token[TV_TokenTypes]): self.pre_whitespaces = None self.lines = [] + def append_whitespaces(self, token: Token) -> None: + if self.lines: + self.lines[-1].append_whitespaces(token) + elif self.pre_whitespaces is None: + self.pre_whitespaces = WhitespaceNode(token) + else: + self.pre_whitespaces.append(token) + @dataclass(unsafe_hash=True) class IndexNode(BaseNode): @@ -669,12 +697,16 @@ def __init__(self, code: str, filename: str): self.stream = self.lexer.lex(filename) self.current: Token = Token('eof', '', 0, 0, 0, (0, 0), None) self.previous = self.current + self.current_ws: T.List[Token] = [] self.getsym() self.in_ternary = False def create_node(self, node_type: T.Type[BaseNodeT], *args: T.Any, **kwargs: T.Any) -> BaseNodeT: node = node_type(*args, **kwargs) + for ws_token in self.current_ws: + node.append_whitespaces(ws_token) + self.current_ws = [] return node def getsym(self) -> None: @@ -682,6 +714,12 @@ def getsym(self) -> None: try: self.current = next(self.stream) + while self.current.tid in {'eol', 'comment', 'whitespace'}: + self.current_ws.append(self.current) + if self.current.tid == 'eol': + break + self.current = next(self.stream) + except StopIteration: self.current = Token('eof', '', self.current.line_start, self.current.lineno, self.current.colno + self.current.bytespan[1] - self.current.bytespan[0], (0, 0), None) @@ -782,11 +820,17 @@ def e4(self) -> BaseNode: operator = self.create_node(SymbolNode, self.previous) return self.create_node(ComparisonNode, operator_type, left, operator, self.e5()) if self.accept('not'): + ws = self.current_ws.copy() not_token = self.previous if self.accept('in'): in_token = self.previous + self.current_ws = self.current_ws[len(ws):] # remove whitespaces between not and in + temp_node = EmptyNode(in_token.lineno, in_token.colno, in_token.filename) + for w in ws: + temp_node.append_whitespaces(w) + not_token.bytespan = (not_token.bytespan[0], in_token.bytespan[1]) - not_token.value += in_token.value + not_token.value += temp_node.whitespaces.value + in_token.value operator = self.create_node(SymbolNode, not_token) return self.create_node(ComparisonNode, 'notin', left, operator, self.e5()) return left @@ -1054,6 +1098,10 @@ def codeblock(self) -> CodeBlockNode: try: while cond: + for ws_token in self.current_ws: + block.append_whitespaces(ws_token) + self.current_ws = [] + curline = self.line() if not isinstance(curline, EmptyNode): @@ -1065,4 +1113,9 @@ def codeblock(self) -> CodeBlockNode: e.ast = block raise + # Remaining whitespaces will not be catched since there are no more nodes + for ws_token in self.current_ws: + block.append_whitespaces(ws_token) + self.current_ws = [] + return block From 6a18ae48b33c345185a8eda49e93adb1fb4594a9 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Mon, 28 Aug 2023 11:42:55 -0400 Subject: [PATCH 215/855] ast: fully resolve nodes for add operation Otherwise, string + stringmethod results in a list of two strings instead of the concatenation of the strings --- mesonbuild/ast/interpreter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index da2119c89ee7..c51af09f4498 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -371,8 +371,8 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T elif isinstance(node, ArithmeticNode): if node.operation != 'add': return None # Only handle string and array concats - l = quick_resolve(node.left) - r = quick_resolve(node.right) + l = self.resolve_node(node.left, include_unknown_args, id_loop_detect) + r = self.resolve_node(node.right, include_unknown_args, id_loop_detect) if isinstance(l, str) and isinstance(r, str): result = l + r # String concatenation detected else: From d3a26d158e4607ce677404920ad72508eb6f9de2 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 12:46:18 -0400 Subject: [PATCH 216/855] raw printer this printer preserves all whitespaces and comments in original meson.build file. It will be useful for rewrite and potential auto-formatter --- docs/markdown/Syntax.md | 2 +- mesonbuild/ast/printer.py | 219 ++++++++++++++++++++++++ run_format_tests.py | 1 + test cases/unit/118 rewrite/meson.build | 189 ++++++++++++++++++++ unittests/rewritetests.py | 22 +++ 5 files changed, 432 insertions(+), 1 deletion(-) create mode 100644 test cases/unit/118 rewrite/meson.build diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index b69ad00aef57..59ec5f7ba07d 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -109,7 +109,7 @@ Strings in Meson are declared with single quotes. To enter a literal single quote do it like this: ```meson -single quote = 'contains a \' character' +single_quote = 'contains a \' character' ``` The full list of escape sequences is: diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 410aabd4619e..155b5fc5e75d 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -18,6 +18,8 @@ from .. import mparser from .visitor import AstVisitor + +from itertools import zip_longest import re import typing as T @@ -248,6 +250,223 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: else: self.result = re.sub(r', $', '', self.result) +class RawPrinter(AstVisitor): + + def __init__(self): + self.result = '' + + def visit_default_func(self, node: mparser.BaseNode): + self.result += node.value + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_unary_operator(self, node: mparser.UnaryOperatorNode): + node.operator.accept(self) + node.value.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_binary_operator(self, node: mparser.BinaryOperatorNode): + node.left.accept(self) + node.operator.accept(self) + node.right.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.result += 'true' if node.value else 'false' + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.result += node.raw_value + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + self.result += f"'{node.raw_value}'" + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: + self.result += f"'''{node.value}'''" + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: + self.result += 'f' + self.visit_StringNode(node) + + def visit_MultilineFormatStringNode(self, node: mparser.MultilineFormatStringNode) -> None: + self.result += 'f' + self.visit_MultilineStringNode(node) + + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: + self.result += 'continue' + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.result += 'break' + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + node.lbracket.accept(self) + node.args.accept(self) + node.rbracket.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + node.lcurl.accept(self) + node.args.accept(self) + node.rcurl.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: + node.lpar.accept(self) + node.inner.accept(self) + node.rpar.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + self.visit_binary_operator(node) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + self.visit_binary_operator(node) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + self.visit_binary_operator(node) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + self.visit_binary_operator(node) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + self.visit_unary_operator(node) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + if node.pre_whitespaces: + node.pre_whitespaces.accept(self) + for i in node.lines: + i.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + node.iobject.accept(self) + node.lbracket.accept(self) + node.index.accept(self) + node.rbracket.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + node.source_object.accept(self) + node.dot.accept(self) + node.name.accept(self) + node.lpar.accept(self) + node.args.accept(self) + node.rpar.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + node.func_name.accept(self) + node.lpar.accept(self) + node.args.accept(self) + node.rpar.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + node.var_name.accept(self) + node.operator.accept(self) + node.value.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + node.var_name.accept(self) + node.operator.accept(self) + node.value.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + node.foreach_.accept(self) + for varname, comma in zip_longest(node.varnames, node.commas): + varname.accept(self) + if comma is not None: + comma.accept(self) + node.column.accept(self) + node.items.accept(self) + node.block.accept(self) + node.endforeach.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + for i in node.ifs: + i.accept(self) + if not isinstance(node.elseblock, mparser.EmptyNode): + node.elseblock.accept(self) + node.endif.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + self.visit_unary_operator(node) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + node.if_.accept(self) + node.condition.accept(self) + node.block.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_ElseNode(self, node: mparser.ElseNode) -> None: + node.else_.accept(self) + node.block.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + node.condition.accept(self) + node.questionmark.accept(self) + node.trueblock.accept(self) + node.column.accept(self) + node.falseblock.accept(self) + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + commas_iter = iter(node.commas) + + for arg in node.arguments: + arg.accept(self) + try: + comma = next(commas_iter) + comma.accept(self) + except StopIteration: + pass + + assert len(node.columns) == len(node.kwargs) + for (key, val), column in zip(node.kwargs.items(), node.columns): + key.accept(self) + column.accept(self) + val.accept(self) + try: + comma = next(commas_iter) + comma.accept(self) + except StopIteration: + pass + + if node.whitespaces: + node.whitespaces.accept(self) + class AstJSONPrinter(AstVisitor): def __init__(self) -> None: self.result: T.Dict[str, T.Any] = {} diff --git a/run_format_tests.py b/run_format_tests.py index 1f41f3d10eca..1bf997ccc179 100644 --- a/run_format_tests.py +++ b/run_format_tests.py @@ -63,6 +63,7 @@ def check_format() -> None: 'work area', '.eggs', '_cache', # e.g. .mypy_cache 'venv', # virtualenvs have DOS line endings + '118 rewrite', # we explicitly test for tab in meson.build file } for (root, _, filenames) in os.walk('.'): if any([x in root for x in skip_dirs]): diff --git a/test cases/unit/118 rewrite/meson.build b/test cases/unit/118 rewrite/meson.build new file mode 100644 index 000000000000..cb8c15fe62c4 --- /dev/null +++ b/test cases/unit/118 rewrite/meson.build @@ -0,0 +1,189 @@ +# This file should expose all possible meson syntaxes + # and ensure the AstInterpreter and RawPrinter are able + + # to parse and write a file identical to the original. + + project ( # project comment 1 + # project comment 2 + 'rewrite' , # argument comment + # project comment 3 + 'cpp', + 'c', + default_options: [ + 'unity=on', + 'unity_size=50', # number of cpp / unity. default is 4... + 'warning_level=2', # eqv to /W3 + 'werror=true', # treat warnings as errors + 'b_ndebug=if-release', # disable assert in Release + 'cpp_eh=a', # /EHa exception handling + 'cpp_std=c++17', + 'cpp_winlibs=' + ','.join([ # array comment + # in array + # comment + 'kernel32.lib', + 'user32.lib', + 'gdi32.lib', + 'winspool.lib', + 'comdlg32.lib', + 'advapi32.lib', + 'shell32.lib' + # before comma comment + , + # after comma comment + 'ole32.lib', + 'oleaut32.lib', + 'uuid.lib', + 'odbc32.lib', + 'odbccp32.lib', + 'Delayimp.lib', # For delay loaded dll + 'OLDNAMES.lib', + 'dbghelp.lib', + 'psapi.lib', + ]), + ], + meson_version: '>=1.2', + version: '1.0.0', + ) # project comment 4 + +cppcoro_dep = dependency('andreasbuhr-cppcoro-cppcoro') +cppcoro = declare_dependency( + dependencies: [cppcoro_dep.partial_dependency( + includes: true, + link_args: true, + links: true, + sources: true, + )], + # '/await:strict' allows to use rather than with C++17. + # We can remove '/await:strict' once we update to C++20. + compile_args: ['/await:strict'], + # includes:true doesn't work for now in partial_dependency() + # This line could be removed once https://github.com/mesonbuild/meson/pull/10122 is released. + include_directories: cppcoro_dep.get_variable('includedir1'), +) + + +if get_option('unicode') #if comment +#if comment 2 + mfc=cpp_compiler.find_library(get_option('debug')?'mfc140ud':'mfc140u') + # if comment 3 +else#elsecommentnowhitespaces + # else comment 1 + mfc = cpp_compiler.find_library( get_option( 'debug' ) ? 'mfc140d' : 'mfc140') +# else comment 2 +endif #endif comment + + +assert(1 in [1, 2], '''1 should be in [1, 2]''') +assert(3 not in [1, 2], '''3 shouldn't be in [1, 2]''') +assert(not (3 in [1, 2]), '''3 shouldn't be in [1, 2]''') + +assert('b' in ['a', 'b'], ''''b' should be in ['a', 'b']''') +assert('c' not in ['a', 'b'], ''''c' shouldn't be in ['a', 'b']''') + +assert(exe1 in [exe1, exe2], ''''exe1 should be in [exe1, exe2]''') +assert(exe3 not in [exe1, exe2], ''''exe3 shouldn't be in [exe1, exe2]''') + +assert('a' in {'a': 'b'}, '''1 should be in {'a': 'b'}''') +assert('b'not in{'a':'b'}, '''1 should be in {'a': 'b'}''') + +assert('a'in'abc') +assert('b' not in 'def') + + +w = 'world' +d = {'a': 1, 'b': 0b10101010, 'c': 'pi', 'd': '''a +b +c''', 'e': f'hello @w@', 'f': f'''triple + formatted + string # this is not a comment + hello @w@ +''', 'g': [1, 2, 3], + + 'h' # comment a + : # comment b +0xDEADBEEF # comment c +, # comment d +'hh': 0xfeedc0de, # lowercase hexa +'hhh': 0XaBcD0123, # mixed case hexa +'oo': 0O123456, # upper O octa +'bb': 0B1111, # upper B binary +'i': {'aa': 11, # this is a comment + 'bb': 22}, # a comment inside a dict +'o': 0o754, +'m': -12, # minus number +'eq': 1 + 3 - 3 % 4 + -( 7 * 8 ), +} # end of dict comment + +hw = d['e'] +one = d['g'][0] + w += '!' + + +components = { + 'foo': ['foo.c'], + 'bar': ['bar.c'], + 'baz': ['baz.c'], # this line is indented with a tab! +} + +# compute a configuration based on system dependencies, custom logic +conf = configuration_data() +conf.set('USE_FOO', 1) + +# Determine the sources to compile +sources_to_compile = [] +foreach name, sources : components + if conf.get('USE_@0@'.format(name.to_upper()), 0) == 1 + sources_to_compile += sources + endif +endforeach + + +items = ['a', 'continue', 'b', 'break', 'c'] +result = [] +foreach i : items + if i == 'continue' + continue + elif i == 'break' + break + endif + result += i +endforeach +# result is ['a', 'b'] + + + +if a and b + # do something +endif +if c or d + # do something +endif +if not e + # do something +endif +if not (f or g) + # do something +endif + +single_quote = 'contains a \' character' +string_escapes = '\\\'\a\b\f\n\r\t\v\046\x26\u2D4d\U00002d4d\N{GREEK CAPITAL LETTER DELTA}' +no_string_escapes = '''\\\'\a\b\f\n\r\t\v\046\x26\u2D4d\U00002d4d\N{GREEK CAPITAL LETTER DELTA}''' + +# FIXME: is it supposed to work? (cont_eol inside string) +# cont_string = 'blablabla\ +# blablabla' + +# FIXME: is it supposed to work? (cont_eol with whitespace and comments after) +# if a \ # comment in cont 1 +# and b \ # comment in cont 2 +# or c # comment in cont 3 +# message('ok') +# endif + +if a \ + or b + debug('help!') +endif + + +# End of file comment with no linebreak \ No newline at end of file diff --git a/unittests/rewritetests.py b/unittests/rewritetests.py index ca30fe9c2cc7..c33884442675 100644 --- a/unittests/rewritetests.py +++ b/unittests/rewritetests.py @@ -13,11 +13,15 @@ # limitations under the License. import subprocess +from itertools import zip_longest import json import os +from pathlib import Path import shutil import unittest +from mesonbuild.ast import IntrospectionInterpreter, AstIDGenerator +from mesonbuild.ast.printer import RawPrinter from mesonbuild.mesonlib import windows_proof_rmtree from .baseplatformtests import BasePlatformTests @@ -396,3 +400,21 @@ def test_target_remove_extra_files(self): # Check the written file out = self.rewrite(self.builddir, os.path.join(self.builddir, 'info.json')) self.assertDictEqual(out, expected) + + def test_raw_printer_is_idempotent(self): + test_path = Path(self.unit_test_dir, '118 rewrite') + meson_build_file = test_path / 'meson.build' + # original_contents = meson_build_file.read_bytes() + original_contents = meson_build_file.read_text(encoding='utf-8') + + interpreter = IntrospectionInterpreter(test_path, '', 'ninja', visitors = [AstIDGenerator()]) + interpreter.analyze() + + printer = RawPrinter() + interpreter.ast.accept(printer) + # new_contents = printer.result.encode('utf-8') + new_contents = printer.result + + # Do it line per line because it is easier to debug like that + for orig_line, new_line in zip_longest(original_contents.splitlines(), new_contents.splitlines()): + self.assertEqual(orig_line, new_line) From 14e35b63c02a16f69dd1ad5bde775e6868965eb2 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 23 Aug 2023 15:39:43 -0400 Subject: [PATCH 217/855] parser: allow whitespaces and comments in cont_eol FIXME: another approach would be to consider cont_eol as comment (i.e. add backslash and whitespaces to the comment regex). In both cases it works until we want to parse comments separately. TODO?: handle eol_cont inside a string (to split long string without breaking lines). Probably a bad idea and better to simply join a multiline string. --- mesonbuild/mparser.py | 2 +- test cases/unit/118 rewrite/meson.build | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index a161842e6d0e..0f63c9e5a47e 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -121,7 +121,7 @@ def __init__(self, code: str): ('fstring', re.compile(r"f'([^'\\]|(\\.))*'")), ('id', re.compile('[_a-zA-Z][_0-9a-zA-Z]*')), ('number', re.compile(r'0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-fA-F]+|0|[1-9]\d*')), - ('eol_cont', re.compile(r'\\\n')), + ('eol_cont', re.compile(r'\\[ \t]*(#.*)?\n')), ('eol', re.compile(r'\n')), ('multiline_string', re.compile(r"'''(.|\n)*?'''", re.M)), ('comment', re.compile(r'#.*')), diff --git a/test cases/unit/118 rewrite/meson.build b/test cases/unit/118 rewrite/meson.build index cb8c15fe62c4..7d0330b9e2e3 100644 --- a/test cases/unit/118 rewrite/meson.build +++ b/test cases/unit/118 rewrite/meson.build @@ -173,12 +173,12 @@ no_string_escapes = '''\\\'\a\b\f\n\r\t\v\046\x26\u2D4d\U00002d4d\N{GREEK CAPITA # cont_string = 'blablabla\ # blablabla' -# FIXME: is it supposed to work? (cont_eol with whitespace and comments after) -# if a \ # comment in cont 1 -# and b \ # comment in cont 2 -# or c # comment in cont 3 -# message('ok') -# endif +# cont_eol with whitespace and comments after +if a \ # comment in cont 1 + and b \ # comment in cont 2 + or c # comment in cont 3 + message('ok') +endif if a \ or b From 57178e8ae7f6fc7bc898e55fed1a18d32d25c2ce Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 6 Sep 2023 15:51:20 -0400 Subject: [PATCH 218/855] fix bug with openssl when cmake is missing Fixes #12098 DependencyFactory was returning a lambda, but it has no log_tried() function --- mesonbuild/dependencies/cmake.py | 16 ++++++++++++++++ mesonbuild/dependencies/misc.py | 8 ++++---- .../unit/117 openssl cmake bug/meson.build | 5 +++++ .../unit/117 openssl cmake bug/nativefile.ini | 7 +++++++ unittests/platformagnostictests.py | 7 +++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test cases/unit/117 openssl cmake bug/meson.build create mode 100644 test cases/unit/117 openssl cmake bug/nativefile.ini diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 11d35646d430..2bb1f6b74eeb 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -652,3 +652,19 @@ def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[s if default_value is not None: return default_value raise DependencyException(f'Could not get cmake variable and no default provided for {self!r}') + + +class CMakeDependencyFactory: + + def __init__(self, name: T.Optional[str] = None, modules: T.Optional[T.List[str]] = None): + self.name = name + self.modules = modules + + def __call__(self, name: str, env: Environment, kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None, force_use_global_compilers: bool = False) -> CMakeDependency: + if self.modules: + kwargs['modules'] = self.modules + return CMakeDependency(self.name or name, env, kwargs, language, force_use_global_compilers) + + @staticmethod + def log_tried() -> str: + return CMakeDependency.log_tried() diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 1a5502f69e8c..b186b5dda83d 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -23,7 +23,7 @@ from .. import mlog from .base import DependencyException, DependencyMethods from .base import BuiltinDependency, SystemDependency -from .cmake import CMakeDependency +from .cmake import CMakeDependency, CMakeDependencyFactory from .configtool import ConfigToolDependency from .detect import packages from .factory import DependencyFactory, factory_methods @@ -599,19 +599,19 @@ def shaderc_factory(env: 'Environment', 'openssl', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, - cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto', 'OpenSSL::SSL'])), + cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::Crypto', 'OpenSSL::SSL']), ) packages['libcrypto'] = libcrypto_factory = DependencyFactory( 'libcrypto', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, - cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::Crypto'])), + cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::Crypto']), ) packages['libssl'] = libssl_factory = DependencyFactory( 'libssl', [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM, DependencyMethods.CMAKE], system_class=OpensslSystemDependency, - cmake_class=lambda name, env, kwargs: CMakeDependency('OpenSSL', env, dict(kwargs, modules=['OpenSSL::SSL'])), + cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::SSL']), ) diff --git a/test cases/unit/117 openssl cmake bug/meson.build b/test cases/unit/117 openssl cmake bug/meson.build new file mode 100644 index 000000000000..d08a8ef429a2 --- /dev/null +++ b/test cases/unit/117 openssl cmake bug/meson.build @@ -0,0 +1,5 @@ +project('bug', 'cpp') + +# When cmake is not available, +# this triggers the bug described in #12098 +openssl_dep = dependency('openssl') diff --git a/test cases/unit/117 openssl cmake bug/nativefile.ini b/test cases/unit/117 openssl cmake bug/nativefile.ini new file mode 100644 index 000000000000..dd6b0ff299c9 --- /dev/null +++ b/test cases/unit/117 openssl cmake bug/nativefile.ini @@ -0,0 +1,7 @@ +[binaries] + +cmake = '/path/to/nothing' + +[built-in options] + +pkg_config_path = '' \ No newline at end of file diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 92c613d916d7..204a22ba5302 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -271,3 +271,10 @@ def test_meson_package_cache_dir(self): builddir = os.path.join(srcdir, '_build') self.change_builddir(builddir) self.init(srcdir, override_envvars={'MESON_PACKAGE_CACHE_DIR': os.path.join(srcdir, 'cache_dir')}) + + def test_cmake_openssl_not_found_bug(self): + """Issue #12098""" + testdir = os.path.join(self.unit_test_dir, '117 openssl cmake bug') + self.meson_native_files.append(os.path.join(testdir, 'nativefile.ini')) + out = self.init(testdir, allow_fail=True) + self.assertNotIn('Unhandled python exception', out) From 1b6c9ad02ab88d92fd055ccc1307456105c064fe Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 31 Aug 2023 15:25:31 -0400 Subject: [PATCH 219/855] msubprojects: Speedup subproject_dir extraction The interpreter takes significant amount of time to initialize everything in project() function. We only need to extract a string from AST, just like we do in handle_meson_version_from_ast(). --- mesonbuild/ast/introspection.py | 19 +++++++++++++++++++ mesonbuild/msubprojects.py | 8 +++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index e8055c5299de..987e355e78ba 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -362,3 +362,22 @@ def analyze(self) -> None: self.sanity_check_ast() self.parse_project() self.run() + + def extract_subproject_dir(self) -> T.Optional[str]: + '''Fast path to extract subproject_dir kwarg. + This is faster than self.parse_project() which also initialize options + and also calls parse_project() on every subproject. + ''' + if not self.ast.lines: + return + project = self.ast.lines[0] + # first line is always project() + if not isinstance(project, FunctionNode): + return + for kw, val in project.args.kwargs.items(): + assert isinstance(kw, IdNode), 'for mypy' + if kw.value == 'subproject_dir': + # mypy does not understand "and isinstance" + if isinstance(val, StringNode): + return val.value + return None diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index d1b51f04859e..64a09b01720f 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -14,7 +14,7 @@ import zipfile from . import mlog -from .ast import IntrospectionInterpreter, AstIDGenerator +from .ast import IntrospectionInterpreter from .mesonlib import quiet_git, GitException, Popen_safe, MesonException, windows_proof_rmtree from .wrap.wrap import (Resolver, WrapException, ALL_TYPES, parse_patch_url, update_wrap_file, get_releases) @@ -693,11 +693,9 @@ def run(options: 'Arguments') -> int: mlog.error('Directory', mlog.bold(source_dir), 'does not seem to be a Meson source directory.') return 1 with mlog.no_logging(): - intr = IntrospectionInterpreter(source_dir, '', 'none', visitors = [AstIDGenerator()]) + intr = IntrospectionInterpreter(source_dir, '', 'none') intr.load_root_meson_file() - intr.sanity_check_ast() - intr.parse_project() - subproject_dir = intr.subproject_dir + subproject_dir = intr.extract_subproject_dir() or 'subprojects' if not os.path.isdir(os.path.join(source_dir, subproject_dir)): mlog.log('Directory', mlog.bold(source_dir), 'does not seem to have subprojects.') return 0 From 8caf40e5ae9283f2c463ab8a2ddd829e30d0bf37 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 8 Sep 2023 08:47:27 -0400 Subject: [PATCH 220/855] Allow unit test to parse testcase blocks When a unittest introspect a meson.build file from a test case, the file may contain a testcase block. We should ignore this block. --- mesonbuild/ast/interpreter.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index c51af09f4498..382fa41970e0 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -29,6 +29,7 @@ InvalidArguments, BreakRequest, ContinueRequest, + Disabler, default_resolve_key, ) @@ -53,6 +54,7 @@ NotNode, PlusAssignmentNode, TernaryNode, + TestCaseClauseNode, ) if T.TYPE_CHECKING: @@ -444,3 +446,6 @@ def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_nvar], include_unknown_args: b elif isinstance(val, (str, bool, int, float)) or include_unknown_args: flattened_kwargs[key] = val return flattened_kwargs + + def evaluate_testcase(self, node: TestCaseClauseNode) -> Disabler | None: + return Disabler(subproject=self.subproject) From 923b95f3d11141417f27ecbbf43b9ae849dc9e64 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 7 Sep 2023 15:06:23 -0400 Subject: [PATCH 221/855] Fix assertion raised with invalid option name When option name contains more that one dot, it should be detected earlier to prevent an assert to be raised. Fixes #11904. --- mesonbuild/interpreter/interpreter.py | 5 +++++ test cases/common/40 options/meson.build | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c6370870c3e9..838ad2fdea54 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -37,6 +37,7 @@ from ..interpreterbase import ObjectHolder, ContextManagerObject from ..interpreterbase import stringifyUserArguments from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule +from ..optinterpreter import optname_regex from . import interpreterobjects as OBJ from . import compiler as compilerOBJ @@ -1090,6 +1091,10 @@ def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str], raise InterpreterException('Having a colon in option name is forbidden, ' 'projects are not allowed to directly access ' 'options of other subprojects.') + + if optname_regex.search(optname.split('.', maxsplit=1)[-1]) is not None: + raise InterpreterException(f'Invalid option name {optname!r}') + opt = self.get_option_internal(optname) if isinstance(opt, coredata.UserFeatureOption): opt.name = optname diff --git a/test cases/common/40 options/meson.build b/test cases/common/40 options/meson.build index a10ff28f0c6e..de4a7d50db14 100644 --- a/test cases/common/40 options/meson.build +++ b/test cases/common/40 options/meson.build @@ -46,3 +46,11 @@ assert(get_option('wrap_mode') == 'default', 'Wrap mode option is broken.') assert(get_option('boolean_string') == false) assert(get_option('boolean_string2') == true) assert(get_option('integer_string') == 42) + +testcase expect_error('Invalid option name \'..invalid\'') + get_option('..invalid') +endtestcase + +testcase expect_error('Invalid option name \'this.is.also.invalid\'') + get_option('this.is.also.invalid') +endtestcase From ef5931f12dc462a6fd3357e1d6d694429a7f330f Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 12 Sep 2023 11:14:48 -0400 Subject: [PATCH 222/855] fix undefined StringNode from previous commit --- mesonbuild/ast/introspection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 1525a2d6971c..7d91a85d581c 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -378,6 +378,6 @@ def extract_subproject_dir(self) -> T.Optional[str]: assert isinstance(kw, IdNode), 'for mypy' if kw.value == 'subproject_dir': # mypy does not understand "and isinstance" - if isinstance(val, StringNode): + if isinstance(val, BaseStringNode): return val.value return None From 56ef698426bb58b7ffd32b0711e064b54166e10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Fri, 18 Aug 2023 14:24:15 +0200 Subject: [PATCH 223/855] run_project_tests: support checking for symlinks --- data/test.schema.json | 3 ++- run_project_tests.py | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/data/test.schema.json b/data/test.schema.json index b5f6aba629ce..6f6a19381bf2 100644 --- a/data/test.schema.json +++ b/data/test.schema.json @@ -33,7 +33,8 @@ "py_implib", "py_limited_implib", "implibempty", - "expr" + "expr", + "link" ] }, "platform": { diff --git a/run_project_tests.py b/run_project_tests.py index 78fa89c82811..7413c6843033 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -199,7 +199,7 @@ def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Pa return None if self.typ == 'python_bytecode': return p.parent / importlib.util.cache_from_source(p.name) - elif self.typ in {'file', 'dir'}: + elif self.typ in {'file', 'dir', 'link'}: return p elif self.typ == 'shared_lib': if env.machines.host.is_windows() or env.machines.host.is_cygwin(): @@ -263,6 +263,11 @@ def get_paths(self, compiler: str, env: environment.Environment, installdir: Pat if not abs_p.is_dir(): raise RuntimeError(f'{p} is not a directory') return [x.relative_to(installdir) for x in abs_p.rglob('*') if x.is_file() or x.is_symlink()] + elif self.typ == 'link': + abs_p = installdir / p + if not abs_p.is_symlink(): + raise RuntimeError(f'{p} is not a symlink') + return [p] else: return [p] From 0af126fec798d6dbb0d1ad52168cc1f3f1758acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Tue, 12 Jul 2022 15:26:22 +0200 Subject: [PATCH 224/855] install_{data,headers,subdir}: implement follow_symlinks This permits users who rely on following symlinks to stay on the old default of following them. --- .../snippets/install_follow_symlink_arg.md | 7 ++++ docs/yaml/functions/install_data.yaml | 8 ++++ docs/yaml/functions/install_headers.yaml | 8 ++++ docs/yaml/functions/install_subdir.yaml | 8 ++++ mesonbuild/backend/backends.py | 14 ++++--- mesonbuild/build.py | 3 ++ mesonbuild/interpreter/interpreter.py | 20 +++++++--- mesonbuild/interpreter/kwargs.py | 3 ++ mesonbuild/interpreter/type_checking.py | 6 +++ mesonbuild/minstall.py | 31 ++++++++------- .../foo/file1 | 1 + .../foo/link1 | 1 + .../foo/link2.h | 1 + .../meson.build | 38 +++++++++++++++++++ .../test.json | 14 +++++++ 15 files changed, 139 insertions(+), 24 deletions(-) create mode 100644 docs/markdown/snippets/install_follow_symlink_arg.md create mode 100644 test cases/common/266 install functions and follow_symlinks/foo/file1 create mode 120000 test cases/common/266 install functions and follow_symlinks/foo/link1 create mode 120000 test cases/common/266 install functions and follow_symlinks/foo/link2.h create mode 100644 test cases/common/266 install functions and follow_symlinks/meson.build create mode 100644 test cases/common/266 install functions and follow_symlinks/test.json diff --git a/docs/markdown/snippets/install_follow_symlink_arg.md b/docs/markdown/snippets/install_follow_symlink_arg.md new file mode 100644 index 000000000000..ce971d7ff722 --- /dev/null +++ b/docs/markdown/snippets/install_follow_symlink_arg.md @@ -0,0 +1,7 @@ +## Added follow_symlinks arg to install_data, install_header, and install_subdir + +The [[install_data]], [[install_headers]], [[install_subdir]] functions now +have an optional argument `follow_symlinks` that, if set to `true`, makes it so +symbolic links in the source are followed, rather than copied into the +destination tree, to match the old behavior. The default, which is currently +to follow links, is subject to change in the future. diff --git a/docs/yaml/functions/install_data.yaml b/docs/yaml/functions/install_data.yaml index 5ecc318a9bbf..ff4f3363d6ba 100644 --- a/docs/yaml/functions/install_data.yaml +++ b/docs/yaml/functions/install_data.yaml @@ -69,3 +69,11 @@ kwargs: sources: type: list[file | str] description: Additional files to install. + + follow_symlinks: + type: bool + since: 1.3.0 + default: true + description: | + If true, dereferences links and copies their target instead. The default + value will become false in the future. diff --git a/docs/yaml/functions/install_headers.yaml b/docs/yaml/functions/install_headers.yaml index 958ab156e4b2..0ac4fc5860d7 100644 --- a/docs/yaml/functions/install_headers.yaml +++ b/docs/yaml/functions/install_headers.yaml @@ -73,3 +73,11 @@ kwargs: Disable stripping child-directories from header files when installing. This is equivalent to GNU Automake's `nobase` option. + + follow_symlinks: + type: bool + since: 1.3.0 + default: true + description: | + If true, dereferences links and copies their target instead. The default + value will become false in the future. diff --git a/docs/yaml/functions/install_subdir.yaml b/docs/yaml/functions/install_subdir.yaml index 1907cec40bb3..19abee37d63b 100644 --- a/docs/yaml/functions/install_subdir.yaml +++ b/docs/yaml/functions/install_subdir.yaml @@ -106,3 +106,11 @@ kwargs: description: | Install directory contents. If `strip_directory=true` only the last component of the source path is used. + + follow_symlinks: + type: bool + since: 1.3.0 + default: true + description: | + If true, dereferences links and copies their target instead. The default + value will become false in the future. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 62cf16296a0f..1d2283f30000 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -172,6 +172,7 @@ class InstallDataBase: subproject: str tag: T.Optional[str] = None data_type: T.Optional[str] = None + follow_symlinks: T.Optional[bool] = None @dataclass(eq=False) class InstallSymlinkData: @@ -186,8 +187,9 @@ class InstallSymlinkData: class SubdirInstallData(InstallDataBase): def __init__(self, path: str, install_path: str, install_path_name: str, install_mode: 'FileMode', exclude: T.Tuple[T.Set[str], T.Set[str]], - subproject: str, tag: T.Optional[str] = None, data_type: T.Optional[str] = None): - super().__init__(path, install_path, install_path_name, install_mode, subproject, tag, data_type) + subproject: str, tag: T.Optional[str] = None, data_type: T.Optional[str] = None, + follow_symlinks: T.Optional[bool] = None): + super().__init__(path, install_path, install_path_name, install_mode, subproject, tag, data_type, follow_symlinks) self.exclude = exclude @@ -1832,7 +1834,7 @@ def generate_header_install(self, d: InstallData) -> None: if not isinstance(f, File): raise MesonException(f'Invalid header type {f!r} can\'t be installed') abspath = f.absolute_path(srcdir, builddir) - i = InstallDataBase(abspath, outdir, outdir_name, h.get_custom_install_mode(), h.subproject, tag='devel') + i = InstallDataBase(abspath, outdir, outdir_name, h.get_custom_install_mode(), h.subproject, tag='devel', follow_symlinks=h.follow_symlinks) d.headers.append(i) def generate_man_install(self, d: InstallData) -> None: @@ -1877,7 +1879,8 @@ def generate_data_install(self, d: InstallData) -> None: dstdir_name = os.path.join(subdir_name, dst_name) tag = de.install_tag or self.guess_install_tag(dst_abs) i = InstallDataBase(src_file.absolute_path(srcdir, builddir), dst_abs, dstdir_name, - de.install_mode, de.subproject, tag=tag, data_type=de.data_type) + de.install_mode, de.subproject, tag=tag, data_type=de.data_type, + follow_symlinks=de.follow_symlinks) d.data.append(i) def generate_symlink_install(self, d: InstallData) -> None: @@ -1908,7 +1911,8 @@ def generate_subdir_install(self, d: InstallData) -> None: dst_dir = os.path.join(dst_dir, os.path.basename(src_dir)) dst_name = os.path.join(dst_name, os.path.basename(src_dir)) tag = sd.install_tag or self.guess_install_tag(os.path.join(sd.install_dir, 'dummy')) - i = SubdirInstallData(src_dir, dst_dir, dst_name, sd.install_mode, sd.exclude, sd.subproject, tag) + i = SubdirInstallData(src_dir, dst_dir, dst_name, sd.install_mode, sd.exclude, sd.subproject, tag, + follow_symlinks=sd.follow_symlinks) d.install_subdirs.append(i) def get_introspection_data(self, target_id: str, target: build.Target) -> T.List['TargetIntrospectionData']: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 09437037a89e..fece0bebc8e2 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -156,6 +156,7 @@ class Headers(HoldableObject): custom_install_dir: T.Optional[str] custom_install_mode: 'FileMode' subproject: str + follow_symlinks: T.Optional[bool] = None # TODO: we really don't need any of these methods, but they're preserved to # keep APIs relying on them working. @@ -214,6 +215,7 @@ class InstallDir(HoldableObject): subproject: str from_source_dir: bool = True install_tag: T.Optional[str] = None + follow_symlinks: T.Optional[bool] = None @dataclass(eq=False) class DepManifest: @@ -2973,6 +2975,7 @@ class Data(HoldableObject): rename: T.List[str] = None install_tag: T.Optional[str] = None data_type: str = None + follow_symlinks: T.Optional[bool] = None def __post_init__(self) -> None: if self.rename is None: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 838ad2fdea54..6fcefd14d6c8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -78,6 +78,7 @@ INSTALL_KW, INSTALL_DIR_KW, INSTALL_MODE_KW, + INSTALL_FOLLOW_SYMLINKS, LINK_WITH_KW, LINK_WHOLE_KW, CT_INSTALL_TAG_KW, @@ -2238,6 +2239,7 @@ def add_test(self, node: mparser.BaseNode, KwargInfo('subdir', (str, NoneType)), INSTALL_MODE_KW.evolve(since='0.47.0'), INSTALL_DIR_KW, + INSTALL_FOLLOW_SYMLINKS, ) def func_install_headers(self, node: mparser.BaseNode, args: T.Tuple[T.List['mesonlib.FileOrString']], @@ -2264,7 +2266,8 @@ def func_install_headers(self, node: mparser.BaseNode, for childdir in dirs: h = build.Headers(dirs[childdir], os.path.join(install_subdir, childdir), kwargs['install_dir'], - install_mode, self.subproject) + install_mode, self.subproject, + follow_symlinks=kwargs['follow_symlinks']) ret_headers.append(h) self.build.headers.append(h) @@ -2459,6 +2462,7 @@ def _warn_kwarg_install_mode_sticky(self, mode: FileMode) -> None: INSTALL_TAG_KW.evolve(since='0.60.0'), INSTALL_DIR_KW, PRESERVE_PATH_KW.evolve(since='0.64.0'), + INSTALL_FOLLOW_SYMLINKS, ) def func_install_data(self, node: mparser.BaseNode, args: T.Tuple[T.List['mesonlib.FileOrString']], @@ -2486,15 +2490,16 @@ def func_install_data(self, node: mparser.BaseNode, install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode']) return self.install_data_impl(sources, install_dir, install_mode, rename, kwargs['install_tag'], - preserve_path=kwargs['preserve_path']) + preserve_path=kwargs['preserve_path'], + follow_symlinks=kwargs['follow_symlinks']) def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str, install_mode: FileMode, rename: T.Optional[str], tag: T.Optional[str], install_data_type: T.Optional[str] = None, - preserve_path: bool = False) -> build.Data: + preserve_path: bool = False, + follow_symlinks: T.Optional[bool] = None) -> build.Data: install_dir_name = install_dir.optname if isinstance(install_dir, P_OBJ.OptionString) else install_dir - dirs = collections.defaultdict(list) if preserve_path: for file in sources: @@ -2506,7 +2511,8 @@ def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str, ret_data = [] for childdir, files in dirs.items(): d = build.Data(files, os.path.join(install_dir, childdir), os.path.join(install_dir_name, childdir), - install_mode, self.subproject, rename, tag, install_data_type) + install_mode, self.subproject, rename, tag, install_data_type, + follow_symlinks) ret_data.append(d) self.build.data.extend(ret_data) @@ -2525,6 +2531,7 @@ def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str, validator=lambda x: 'cannot be absolute' if any(os.path.isabs(d) for d in x) else None), INSTALL_MODE_KW.evolve(since='0.38.0'), INSTALL_TAG_KW.evolve(since='0.60.0'), + INSTALL_FOLLOW_SYMLINKS, ) def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtypes.FuncInstallSubdir') -> build.InstallDir: @@ -2550,7 +2557,8 @@ def func_install_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], exclude, kwargs['strip_directory'], self.subproject, - install_tag=kwargs['install_tag']) + install_tag=kwargs['install_tag'], + follow_symlinks=kwargs['follow_symlinks']) self.build.install_dirs.append(idir) return idir diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 1aee41435d38..e67ebf0c0e4b 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -124,6 +124,7 @@ class FuncInstallSubdir(TypedDict): exclude_files: T.List[str] exclude_directories: T.List[str] install_mode: FileMode + follow_symlinks: T.Optional[bool] class FuncInstallData(TypedDict): @@ -132,6 +133,7 @@ class FuncInstallData(TypedDict): sources: T.List[FileOrString] rename: T.List[str] install_mode: FileMode + follow_symlinks: T.Optional[bool] class FuncInstallHeaders(TypedDict): @@ -139,6 +141,7 @@ class FuncInstallHeaders(TypedDict): install_dir: T.Optional[str] install_mode: FileMode subdir: T.Optional[str] + follow_symlinks: T.Optional[bool] class FuncInstallMan(TypedDict): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 28c9152955fa..047aff867392 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -368,6 +368,12 @@ def _output_validator(outputs: T.List[str]) -> T.Optional[str]: INSTALL_TAG_KW: KwargInfo[T.Optional[str]] = KwargInfo('install_tag', (str, NoneType)) +INSTALL_FOLLOW_SYMLINKS: KwargInfo[T.Optional[bool]] = KwargInfo( + 'follow_symlinks', + (bool, NoneType), + since='1.3.0', +) + INSTALL_KW = KwargInfo('install', bool, default=False) CT_INSTALL_DIR_KW: KwargInfo[T.List[T.Union[str, Literal[False]]]] = KwargInfo( diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 0d397b23e306..5f8629b7fe47 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -64,9 +64,11 @@ class ArgumentType(Protocol): strip: bool -symlink_warning = '''Warning: trying to copy a symlink that points to a file. This will copy the file, -but this will be changed in a future version of Meson to copy the symlink as is. Please update your -build definitions so that it will not break when the change happens.''' +symlink_warning = '''\ +Warning: trying to copy a symlink that points to a file. This currently copies +the file by default, but will be changed in a future version of Meson to copy +the link instead. Set follow_symlinks to true to preserve current behavior, or +false to copy the link.''' selinux_updates: T.List[str] = [] @@ -389,7 +391,8 @@ def should_preserve_existing_file(self, from_file: str, to_file: str) -> bool: return from_time <= to_time def do_copyfile(self, from_file: str, to_file: str, - makedirs: T.Optional[T.Tuple[T.Any, str]] = None) -> bool: + makedirs: T.Optional[T.Tuple[T.Any, str]] = None, + follow_symlinks: T.Optional[bool] = None) -> bool: outdir = os.path.split(to_file)[0] if not os.path.isfile(from_file) and not os.path.islink(from_file): raise MesonException(f'Tried to install something that isn\'t a file: {from_file!r}') @@ -417,10 +420,10 @@ def do_copyfile(self, from_file: str, to_file: str, # Dangling symlink. Replicate as is. self.copy(from_file, outdir, follow_symlinks=False) else: - # Remove this entire branch when changing the behaviour to duplicate - # symlinks rather than copying what they point to. - print(symlink_warning) - self.copy2(from_file, to_file) + if follow_symlinks is None: + follow_symlinks = True # TODO: change to False when removing the warning + print(symlink_warning) + self.copy2(from_file, to_file, follow_symlinks=follow_symlinks) else: self.copy2(from_file, to_file) selinux_updates.append(to_file) @@ -454,7 +457,7 @@ def do_symlink(self, target: str, link: str, destdir: str, full_dst_dir: str, al def do_copydir(self, data: InstallData, src_dir: str, dst_dir: str, exclude: T.Optional[T.Tuple[T.Set[str], T.Set[str]]], - install_mode: 'FileMode', dm: DirMaker) -> None: + install_mode: 'FileMode', dm: DirMaker, follow_symlinks: T.Optional[bool] = None) -> None: ''' Copies the contents of directory @src_dir into @dst_dir. @@ -519,7 +522,7 @@ def do_copydir(self, data: InstallData, src_dir: str, dst_dir: str, dm.makedirs(parent_dir) self.copystat(os.path.dirname(abs_src), parent_dir) # FIXME: what about symlinks? - self.do_copyfile(abs_src, abs_dst) + self.do_copyfile(abs_src, abs_dst, follow_symlinks=follow_symlinks) self.set_mode(abs_dst, install_mode, data.install_umask) def do_install(self, datafilename: str) -> None: @@ -613,7 +616,8 @@ def install_subdirs(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix full_dst_dir = get_destdir_path(destdir, fullprefix, i.install_path) self.log(f'Installing subdir {i.path} to {full_dst_dir}') dm.makedirs(full_dst_dir, exist_ok=True) - self.do_copydir(d, i.path, full_dst_dir, i.exclude, i.install_mode, dm) + self.do_copydir(d, i.path, full_dst_dir, i.exclude, i.install_mode, dm, + follow_symlinks=i.follow_symlinks) def install_data(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: for i in d.data: @@ -622,7 +626,7 @@ def install_data(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: s fullfilename = i.path outfilename = get_destdir_path(destdir, fullprefix, i.install_path) outdir = os.path.dirname(outfilename) - if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)): + if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir), follow_symlinks=i.follow_symlinks): self.did_install_something = True self.set_mode(outfilename, i.install_mode, d.install_umask) @@ -668,7 +672,8 @@ def install_headers(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix fname = os.path.basename(fullfilename) outdir = get_destdir_path(destdir, fullprefix, t.install_path) outfilename = os.path.join(outdir, fname) - if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir)): + if self.do_copyfile(fullfilename, outfilename, makedirs=(dm, outdir), + follow_symlinks=t.follow_symlinks): self.did_install_something = True self.set_mode(outfilename, t.install_mode, d.install_umask) diff --git a/test cases/common/266 install functions and follow_symlinks/foo/file1 b/test cases/common/266 install functions and follow_symlinks/foo/file1 new file mode 100644 index 000000000000..9daeafb9864c --- /dev/null +++ b/test cases/common/266 install functions and follow_symlinks/foo/file1 @@ -0,0 +1 @@ +test diff --git a/test cases/common/266 install functions and follow_symlinks/foo/link1 b/test cases/common/266 install functions and follow_symlinks/foo/link1 new file mode 120000 index 000000000000..08219db9b096 --- /dev/null +++ b/test cases/common/266 install functions and follow_symlinks/foo/link1 @@ -0,0 +1 @@ +file1 \ No newline at end of file diff --git a/test cases/common/266 install functions and follow_symlinks/foo/link2.h b/test cases/common/266 install functions and follow_symlinks/foo/link2.h new file mode 120000 index 000000000000..08219db9b096 --- /dev/null +++ b/test cases/common/266 install functions and follow_symlinks/foo/link2.h @@ -0,0 +1 @@ +file1 \ No newline at end of file diff --git a/test cases/common/266 install functions and follow_symlinks/meson.build b/test cases/common/266 install functions and follow_symlinks/meson.build new file mode 100644 index 000000000000..327c02131fb3 --- /dev/null +++ b/test cases/common/266 install functions and follow_symlinks/meson.build @@ -0,0 +1,38 @@ +project('install_data following symlinks') + +install_data( + 'foo/link1', + install_dir: get_option('datadir') / 'followed', + follow_symlinks: true, +) + +install_headers( + 'foo/link2.h', + follow_symlinks: true, + subdir: 'followed' +) + +install_data( + 'foo/link1', + install_dir: get_option('datadir'), + follow_symlinks: false, +) + +install_headers( + 'foo/link2.h', + follow_symlinks: false, +) + +install_subdir( + 'foo', + install_dir: get_option('datadir') / 'subdir', + strip_directory: true, + follow_symlinks: false, +) + +install_subdir( + 'foo', + install_dir: get_option('datadir') / 'subdir_followed', + strip_directory: true, + follow_symlinks: true, +) diff --git a/test cases/common/266 install functions and follow_symlinks/test.json b/test cases/common/266 install functions and follow_symlinks/test.json new file mode 100644 index 000000000000..6a395177d28c --- /dev/null +++ b/test cases/common/266 install functions and follow_symlinks/test.json @@ -0,0 +1,14 @@ +{ + "installed": [ + {"type": "link", "file": "usr/share/link1"}, + {"type": "link", "file": "usr/include/link2.h"}, + {"type": "file", "file": "usr/share/followed/link1"}, + {"type": "file", "file": "usr/include/followed/link2.h"}, + {"type": "link", "file": "usr/share/subdir/link1"}, + {"type": "link", "file": "usr/share/subdir/link2.h"}, + {"type": "file", "file": "usr/share/subdir/file1"}, + {"type": "file", "file": "usr/share/subdir_followed/link1"}, + {"type": "file", "file": "usr/share/subdir_followed/link2.h"}, + {"type": "file", "file": "usr/share/subdir_followed/file1"} + ] +} From 22da2c3c2df035220ea01e368120549987fa43ea Mon Sep 17 00:00:00 2001 From: Nomura Date: Wed, 13 Sep 2023 20:40:08 +0200 Subject: [PATCH 225/855] Use @DIRNAME@ in Metrowerks cross files to point to linker script --- cross/metrowerks-arm.txt | 13 ++++--------- cross/metrowerks-eppc.txt | 13 ++++--------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/cross/metrowerks-arm.txt b/cross/metrowerks-arm.txt index a13175b1782b..a98643ee8a75 100644 --- a/cross/metrowerks-arm.txt +++ b/cross/metrowerks-arm.txt @@ -2,12 +2,6 @@ # toolchain is added to the environment(PATH) variable, so that # Meson can find the binaries while building. -# You should also do one of the following to ensure Meson can -# locate the .lcf linker script: -# - Add the cross directory to PATH as well -# - Edit c_link_args and cpp_link_args with the full -# path to the .lcf file on your machine - [binaries] c = 'mwccarm' c_ld = 'mwldarm' @@ -18,11 +12,12 @@ as = 'mwasmarm' [built-in options] c_args = ['-lang', 'c99', '-D_NITRO', '-nosyspath'] -c_link_args = 'metrowerks.lcf' +c_link_args = '@DIRNAME@' / 'metrowerks.lcf' cpp_args = ['-lang', 'c++', '-D_NITRO', '-nosyspath'] -cpp_link_args = 'metrowerks.lcf' +cpp_link_args = '@DIRNAME@' / 'metrowerks.lcf' [host_machine] system = 'bare metal' +cpu = 'arm' cpu_family = 'arm' -endian = 'little' \ No newline at end of file +endian = 'little' diff --git a/cross/metrowerks-eppc.txt b/cross/metrowerks-eppc.txt index e5e0e42fe4d8..63a4543e0726 100644 --- a/cross/metrowerks-eppc.txt +++ b/cross/metrowerks-eppc.txt @@ -2,12 +2,6 @@ # of choice is added to the environment(PATH) variable, so that # Meson can find the binaries while building. -# You should also do one of the following to ensure Meson can -# locate the .lcf linker script: -# - Add the cross directory to PATH as well -# - Edit c_link_args and cpp_link_args with the full -# path to the lcf file on your machine - [binaries] c = 'mwcceppc' c_ld = 'mwldeppc' @@ -18,11 +12,12 @@ as = 'mwasmeppc' [built-in options] c_args = ['-lang', 'c99', '-nosyspath'] -c_link_args = 'metrowerks.lcf' +c_link_args = '@DIRNAME@' / 'metrowerks.lcf' cpp_args = ['-lang', 'c++', '-nosyspath'] -cpp_link_args = 'metrowerks.lcf' +cpp_link_args = '@DIRNAME@' / 'metrowerks.lcf' [host_machine] system = 'bare metal' +cpu = 'ppc' cpu_family = 'ppc' -endian = 'little' \ No newline at end of file +endian = 'little' From 718c86a7d577e6474ff325957248724d9b786174 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 12 Sep 2023 10:03:07 -0400 Subject: [PATCH 226/855] Wrap: Use git instead of patch by default This solves problems with Strawberry Perl providing patch.exe on Windows with an unconsistent line ending support. Fixes: #12092 --- mesonbuild/wrap/wrap.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 941da3de86bf..c0f0f0728c06 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -801,15 +801,17 @@ def apply_diff_files(self) -> None: if not path.exists(): raise WrapException(f'Diff file "{path}" does not exist') relpath = os.path.relpath(str(path), self.dirname) - if PATCH: - # Always pass a POSIX path to patch, because on Windows it's MSYS - cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] - elif GIT: - # If the `patch` command is not available, fall back to `git - # apply`. The `--work-tree` is necessary in case we're inside a + if GIT: + # Git is more likely to be available on Windows and more likely + # to apply correctly assuming patches are often generated by git. + # See https://github.com/mesonbuild/meson/issues/12092. + # The `--work-tree` is necessary in case we're inside a # Git repository: by default, Git will try to apply the patch to # the repository root. cmd = [GIT, '--work-tree', '.', 'apply', '-p1', relpath] + elif PATCH: + # Always pass a POSIX path to patch, because on Windows it's MSYS + cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] else: raise WrapException('Missing "patch" or "git" commands to apply diff files') From 1306d156163fcbae2e1bf8cf89b98f7eec1465a3 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sun, 3 Sep 2023 18:04:00 +0200 Subject: [PATCH 227/855] Revert "tests: skip a test that fails with new Python 3.11 from MSYS2" This reverts commit 68dce66bf9a2bcb3d23c291beb2354225a74b954. The upstream issues https://github.com/msys2-contrib/cpython-mingw/issues/141 has been fixed now. --- unittests/windowstests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/unittests/windowstests.py b/unittests/windowstests.py index c201953276cc..37e92996d97a 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -462,9 +462,6 @@ def test_non_utf8_fails(self): @unittest.skipIf(is_cygwin(), "Needs visual studio") def test_vsenv_option(self): - if mesonbuild.environment.detect_msys2_arch(): - # https://github.com/msys2-contrib/cpython-mingw/issues/141 - raise SkipTest('mingw python fails with /bin being removed from PATH') if self.backend is not Backend.ninja: raise SkipTest('Only ninja backend is valid for test') env = os.environ.copy() From 878d950887f5d02b830ea190262af5d0491ae0f8 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Aug 2023 22:37:21 -0300 Subject: [PATCH 228/855] environment, env2mfile: Don't shell split paths if they point to a valid executable Fixes #11128 --- mesonbuild/environment.py | 5 ++++- mesonbuild/scripts/env2mfile.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 75909318dbbe..53cb1206fef0 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -747,7 +747,10 @@ def _set_default_binaries_from_env(self) -> None: for (name, evar), for_machine in itertools.product(opts, MachineChoice): p_env = _get_env_var(for_machine, self.is_cross_build(), evar) if p_env is not None: - self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env)) + if os.path.exists(p_env): + self.binaries[for_machine].binaries.setdefault(name, [p_env]) + else: + self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env)) def _set_default_properties_from_env(self) -> None: """Properties which can also be set from the environment.""" diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index df93730424de..1a6d0ce97ba4 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -296,7 +296,10 @@ def detect_compilers_from_envvars(envvar_suffix: str = '') -> MachineInfo: compilerstr = os.environ.get(envvarname + envvar_suffix) if not compilerstr: continue - compiler = shlex.split(compilerstr) + if os.path.exists(compilerstr): + compiler = [compilerstr] + else: + compiler = shlex.split(compilerstr) infos.compilers[langname] = compiler lang_compile_args, lang_link_args = detect_language_args_from_envvars(langname, envvar_suffix) if lang_compile_args: From ca60f71b2e70c0af09b5f77f3a03fd42b7109c0a Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Aug 2023 22:38:22 -0300 Subject: [PATCH 229/855] reference tables: Document how to set compiler paths with spaces in environment variables See #11128 --- docs/markdown/Reference-tables.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 4a869ad83c82..a21b40b2d0d9 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -377,6 +377,26 @@ machine](#Environment-variables-per-machine) section for details. *The old environment variables are still supported, but are deprecated and will be removed in a future version of Meson.* +*changed in 1.3.0* Paths with spaces were split unconditionally to extract +components such as the [path to Ccache](Feature-autodetection.md#ccache), +intrinsic compiler flags like `-m32` or `--target`, etc. This broke passing +a hardcoded compiler path to CMake subprojects. To work around this, paths +must be wrapped with double quotes: + +```bash +export CC='"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe"' +``` + +You can also set the values through [machine files](Machine-files.md#binaries). + +*New in 1.3.0* Paths that point to an existing executable no longer need +wrapping: + +```bash +export CC='C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.34.31933/bin/Hostx64/x64/cl.exe' +``` + + ## Environment variables per machine Since *0.54.0*, Following Autotool and other legacy build systems, From 665275a78506b68638f4e996ef8e8b8e549d5c8f Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 29 Jul 2023 12:13:07 -0500 Subject: [PATCH 230/855] xcode: Check for apple framework deps by name If `dependencies.platform.AppleFrameworks` has not been imported by this time, Meson crashes. Better to check by name instead. --- mesonbuild/backend/xcodebackend.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index a2020e16c165..ec03627dd04b 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -18,7 +18,6 @@ from . import backends from .. import build -from .. import dependencies from .. import mesonlib from .. import mlog from ..mesonlib import MesonBugException, MesonException, OptionKey @@ -456,7 +455,7 @@ def generate_native_frameworks_map(self) -> None: self.native_frameworks_fileref = {} for t in self.build_targets.values(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.platform.AppleFrameworks): + if dep.name == 'appleframeworks': for f in dep.frameworks: self.native_frameworks[f] = self.gen_id() self.native_frameworks_fileref[f] = self.gen_id() @@ -598,7 +597,7 @@ def generate_pbx_aggregate_target(self, objects_dict): def generate_pbx_build_file(self, objects_dict): for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.platform.AppleFrameworks): + if dep.name == 'appleframeworks': for f in dep.frameworks: fw_dict = PbxDict() fwkey = self.native_frameworks[f] @@ -708,7 +707,7 @@ def generate_pbx_container_item_proxy(self, objects_dict): def generate_pbx_file_reference(self, objects_dict): for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.platform.AppleFrameworks): + if dep.name == 'appleframeworks': for f in dep.frameworks: fw_dict = PbxDict() framework_fileref = self.native_frameworks_fileref[f] @@ -868,7 +867,7 @@ def generate_pbx_frameworks_buildphase(self, objects_dict): file_list = PbxArray() bt_dict.add_item('files', file_list) for dep in t.get_external_deps(): - if isinstance(dep, dependencies.platform.AppleFrameworks): + if dep.name == 'appleframeworks': for f in dep.frameworks: file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks') bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0) @@ -916,7 +915,7 @@ def generate_pbx_group(self, objects_dict): for t in self.build_targets.values(): for dep in t.get_external_deps(): - if isinstance(dep, dependencies.platform.AppleFrameworks): + if dep.name == 'appleframeworks': for f in dep.frameworks: frameworks_children.add_item(self.native_frameworks_fileref[f], f) From e7ed45396d28105492036d38ca93c6b3f146ed4b Mon Sep 17 00:00:00 2001 From: Nomura Date: Wed, 13 Sep 2023 20:33:44 +0200 Subject: [PATCH 231/855] Metrowerks: remove duplicate optimization args The args were in both buildtype and optimization. This broke buildtypes other than plain or custom unless manually setting the optimization level to 0, because Metrowerks chokes on duplicate arguments. --- mesonbuild/compilers/mixins/metrowerks.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py index 83a1c1d7fcbd..69fa10a202d1 100644 --- a/mesonbuild/compilers/mixins/metrowerks.py +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -32,10 +32,10 @@ mwcc_buildtype_args: T.Dict[str, T.List[str]] = { 'plain': [], - 'debug': ['-g'], - 'debugoptimized': ['-g', '-O4'], - 'release': ['-O4,p'], - 'minsize': ['-Os'], + 'debug': [], + 'debugoptimized': [], + 'release': [], + 'minsize': [], 'custom': [], } From 319b1505e8ef733b96abfd8c5842f4059a08db92 Mon Sep 17 00:00:00 2001 From: Nomura Date: Wed, 13 Sep 2023 20:36:30 +0200 Subject: [PATCH 232/855] Metrowerks: set optlevel 3 to max optimization args According to the Meson documentation, optimization level 3 should set the highest possible optimization for the compiler in use. In Metrowerks, this is 'O4,p'. However, Meson's Metrowerks implementation mapped opt level 3 to '-O3'. This has been fixed. --- mesonbuild/compilers/mixins/metrowerks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py index 69fa10a202d1..8c3eca586b8a 100644 --- a/mesonbuild/compilers/mixins/metrowerks.py +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -173,7 +173,7 @@ 'g': ['-Op'], '1': ['-O1'], '2': ['-O2'], - '3': ['-O3'], + '3': ['-O4,p'], 's': ['-Os'] } From 2b4002e60fd05a11ca6a36395307d27c3dcef6f7 Mon Sep 17 00:00:00 2001 From: Nomura Date: Wed, 13 Sep 2023 20:45:38 +0200 Subject: [PATCH 233/855] Metrowerks assembler should not inherit opt args from mixin The Metrowerks assembler does not support optimization flags. However, it received the same opt args as the Metrowerks C and C++ compilers, because it inherits from the 'MetrowerksCompiler' mixin. This broke builds with opt level higher than 0 that used the Metrowerks Assembler, as the latter received unsupported args. This is now fixed. --- mesonbuild/compilers/asm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index f25473b20fbc..19f7b643b698 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -306,6 +306,9 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: return [] + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + def get_pic_args(self) -> T.List[str]: return [] From 5d8e2f301ee477da44f207e00a042f795d2d8a2d Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 18 Sep 2023 17:14:43 +0200 Subject: [PATCH 234/855] Update link to lcov lcov moved from sourceforge to github, so this change updates the link. --- docs/markdown/Unit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 18ab11165ffc..030eb19c4dc8 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -49,7 +49,7 @@ targets. These targets are `coverage-xml` and `coverage-text` which are both provided by [Gcovr](http://gcovr.com) (version 3.3 or higher) `coverage-sonarqube` which is provided by [Gcovr](http://gcovr.com) (version 4.2 or higher) and `coverage-html`, which requires -[Lcov](https://ltp.sourceforge.io/coverage/lcov.php) and +[lcov](https://github.com/linux-test-project/lcov) and [GenHTML](https://linux.die.net/man/1/genhtml) or [Gcovr](http://gcovr.com). As a convenience, a high-level `coverage` target is also generated which will produce all 3 coverage report From e0c4cffd70761c9b8176724145fb42d11e5313c4 Mon Sep 17 00:00:00 2001 From: yyyyyiiiiii <144423405+yyyyyiiiiii@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:42:05 +0300 Subject: [PATCH 235/855] fix links Wayland, Weston, wlroots migrated to gitlab.freedesktop.org --- docs/markdown/Users.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 4b7208a1b4aa..c06f376afc08 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -167,8 +167,8 @@ format files - [Venom](https://github.com/naxuroqa/Venom), a modern Tox client for the GNU/Linux desktop - [vkQuake](https://github.com/Novum/vkQuake), a port of id Software's Quake using Vulkan instead of OpenGL for rendering - [VMAF](https://github.com/Netflix/vmaf) (by Netflix), a perceptual video quality assessment based on multi-method fusion - - [Wayland](https://github.com/wayland-project/wayland) and [Weston](https://github.com/wayland-project/weston), a next generation display server - - [wlroots](https://github.com/swaywm/wlroots), a modular Wayland compositor library + - [Wayland](https://gitlab.freedesktop.org/wayland/wayland) and [Weston](https://gitlab.freedesktop.org/wayland/weston), a next generation display server + - [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots), a modular Wayland compositor library - [xi-gtk](https://github.com/eyelash/xi-gtk), a GTK+ front-end for the Xi editor - [Xorg](https://gitlab.freedesktop.org/xorg/xserver), the X.org display server (not the default yet) - [X Test Suite](https://gitlab.freedesktop.org/xorg/test/xts), The X.org test suite From 30d7f506c7ffe4af52feab1a68263a4bd8d78c8a Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 15 Aug 2023 16:56:23 -0400 Subject: [PATCH 236/855] Remove get_pkgconfig_variable() Make sure that pkgconfig_define is a pair of strings and not a list with more than 2 strings. --- mesonbuild/backend/backends.py | 2 +- mesonbuild/dependencies/base.py | 17 ++-------- mesonbuild/dependencies/boost.py | 2 +- mesonbuild/dependencies/cmake.py | 3 +- mesonbuild/dependencies/configtool.py | 3 +- mesonbuild/dependencies/pkgconfig.py | 32 +++++++------------ mesonbuild/dependencies/qt.py | 14 ++++---- mesonbuild/dependencies/scalapack.py | 2 +- mesonbuild/interpreter/interpreterobjects.py | 23 ++++++------- mesonbuild/interpreter/kwargs.py | 6 ++-- mesonbuild/interpreter/type_checking.py | 9 ++++++ mesonbuild/mdevenv.py | 2 +- .../unit/114 empty project/expected_mods.json | 1 + unittests/failuretests.py | 2 +- unittests/linuxliketests.py | 12 +++---- 15 files changed, 62 insertions(+), 68 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 1d2283f30000..aef45b344c9d 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1143,7 +1143,7 @@ def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: if dep.type_name == 'pkgconfig': # If by chance pkg-config knows the bin dir... - bindir = dep.get_pkgconfig_variable('bindir', [], default='') + bindir = dep.get_variable(pkgconfig='bindir', default_value='') if bindir: results.add(bindir) continue diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index fa94f870219c..6da9a6665d5e 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -30,7 +30,6 @@ #from ..interpreterbase import FeatureDeprecated, FeatureNew if T.TYPE_CHECKING: - from .._typing import ImmutableListProtocol from ..compilers.compilers import Compiler from ..environment import Environment from ..interpreterbase import FeatureCheckBase @@ -38,6 +37,7 @@ CustomTarget, IncludeDirs, CustomTargetIndex, LibTypes, StaticLibrary, StructuredSources, ExtractedObjects, GeneratedTypes ) + from ..interpreter.type_checking import PkgConfigDefineType class DependencyException(MesonException): @@ -193,11 +193,6 @@ def get_include_type(self) -> str: def get_exe_args(self, compiler: 'Compiler') -> T.List[str]: return [] - def get_pkgconfig_variable(self, variable_name: str, - define_variable: 'ImmutableListProtocol[str]', - default: T.Optional[str]) -> str: - raise DependencyException(f'{self.name!r} is not a pkgconfig dependency') - def get_configtool_variable(self, variable_name: str) -> str: raise DependencyException(f'{self.name!r} is not a config-tool dependency') @@ -238,7 +233,7 @@ def _add_sub_dependency(self, deplist: T.Iterable[T.Callable[[], 'Dependency']]) def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> str: + pkgconfig_define: PkgConfigDefineType = None) -> str: if default_value is not None: return default_value raise DependencyException(f'No default provided for dependency {self!r}, which is not pkg-config, cmake, or config-tool based.') @@ -297,12 +292,6 @@ def is_built(self) -> bool: return True return any(d.is_built() for d in self.ext_deps) - def get_pkgconfig_variable(self, variable_name: str, - define_variable: 'ImmutableListProtocol[str]', - default: T.Optional[str]) -> str: - raise DependencyException('Method "get_pkgconfig_variable()" is ' - 'invalid for an internal dependency') - def get_configtool_variable(self, variable_name: str) -> str: raise DependencyException('Method "get_configtool_variable()" is ' 'invalid for an internal dependency') @@ -332,7 +321,7 @@ def get_include_dirs(self) -> T.List['IncludeDirs']: def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> str: + pkgconfig_define: PkgConfigDefineType = None) -> str: val = self.variables.get(internal, default_value) if val is not None: return val diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 788ccbb198f5..19c629d5beed 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -662,7 +662,7 @@ def detect_roots(self) -> None: try: boost_pc = PkgConfigDependency('boost', self.env, {'required': False}) if boost_pc.found(): - boost_root = boost_pc.get_pkgconfig_variable('prefix', [], None) + boost_root = boost_pc.get_variable(pkgconfig='prefix') if boost_root: roots += [Path(boost_root)] except DependencyException: diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 2bb1f6b74eeb..5263e5643431 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -30,6 +30,7 @@ from ..cmake import CMakeTarget from ..environment import Environment from ..envconfig import MachineInfo + from ..interpreter.type_checking import PkgConfigDefineType class CMakeInfo(T.NamedTuple): module_paths: T.List[str] @@ -632,7 +633,7 @@ def log_details(self) -> str: def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> str: + pkgconfig_define: PkgConfigDefineType = None) -> str: if cmake and self.traceparser is not None: try: v = self.traceparser.vars[cmake] diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index 8dda298d7d78..bd6a9ff73413 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -24,6 +24,7 @@ if T.TYPE_CHECKING: from ..environment import Environment + from ..interpreter.type_checking import PkgConfigDefineType class ConfigToolDependency(ExternalDependency): @@ -171,7 +172,7 @@ def log_tried() -> str: def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> str: + pkgconfig_define: PkgConfigDefineType = None) -> str: if configtool: # In the not required case '' (empty string) will be returned if the # variable is not found. Since '' is a valid value to return we diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index e8f349ec469d..1d9863a1cdb1 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -31,7 +31,7 @@ from ..environment import Environment from ..mesonlib import MachineChoice from ..utils.core import EnvironOrDict - from .._typing import ImmutableListProtocol + from ..interpreter.type_checking import PkgConfigDefineType class PkgConfigInterface: '''Base class wrapping a pkg-config implementation''' @@ -52,14 +52,14 @@ def version(self, name: str) -> T.Optional[str]: raise NotImplementedError def cflags(self, name: str, allow_system: bool = False, - define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> T.List[str]: '''Return module cflags @allow_system: If False, remove default system include paths ''' raise NotImplementedError def libs(self, name: str, static: bool = False, allow_system: bool = False, - define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> T.List[str]: '''Return module libs @static: If True, also include private libraries @allow_system: If False, remove default system libraries search paths @@ -67,7 +67,7 @@ def libs(self, name: str, static: bool = False, allow_system: bool = False, raise NotImplementedError def variable(self, name: str, variable_name: str, - define_variable: ImmutableListProtocol[str]) -> T.Optional[str]: + define_variable: PkgConfigDefineType) -> T.Optional[str]: '''Return module variable or None if variable is not defined''' raise NotImplementedError @@ -103,13 +103,13 @@ def version(self, name: str) -> T.Optional[str]: return version if ret == 0 else None @staticmethod - def _define_variable_args(define_variable: T.Optional[ImmutableListProtocol[str]]) -> T.List[str]: + def _define_variable_args(define_variable: PkgConfigDefineType) -> T.List[str]: if define_variable: return ['--define-variable=' + '='.join(define_variable)] return [] def cflags(self, name: str, allow_system: bool = False, - define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> T.List[str]: env = None if allow_system: env = os.environ.copy() @@ -123,7 +123,7 @@ def cflags(self, name: str, allow_system: bool = False, return self._split_args(out) def libs(self, name: str, static: bool = False, allow_system: bool = False, - define_variable: T.Optional[ImmutableListProtocol[str]] = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> T.List[str]: env = None if allow_system: env = os.environ.copy() @@ -139,7 +139,7 @@ def libs(self, name: str, static: bool = False, allow_system: bool = False, return self._split_args(out) def variable(self, name: str, variable_name: str, - define_variable: ImmutableListProtocol[str]) -> T.Optional[str]: + define_variable: PkgConfigDefineType) -> T.Optional[str]: args: T.List[str] = [] args += self._define_variable_args(define_variable) args += ['--variable=' + variable_name, name] @@ -516,16 +516,6 @@ def _set_libs(self) -> None: raw_libs = self.pkgconfig.libs(self.name, self.static, allow_system=False) self.link_args, self.raw_link_args = self._search_libs(libs, raw_libs) - def get_pkgconfig_variable(self, variable_name: str, - define_variable: ImmutableListProtocol[str], - default: T.Optional[str]) -> str: - variable = self.pkgconfig.variable(self.name, variable_name, define_variable) - if variable is None: - if default is None: - mlog.warning(f'Pkg-config variable {variable_name!r} not defined for dependency {self.name}.') - variable = default or '' - return variable - def extract_field(self, la_file: str, fieldname: str) -> T.Optional[str]: with open(la_file, encoding='utf-8') as f: for line in f: @@ -568,10 +558,12 @@ def log_tried() -> str: def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, configtool: T.Optional[str] = None, internal: T.Optional[str] = None, default_value: T.Optional[str] = None, - pkgconfig_define: T.Optional[T.List[str]] = None) -> str: + pkgconfig_define: PkgConfigDefineType = None) -> str: if pkgconfig: try: - return self.get_pkgconfig_variable(pkgconfig, pkgconfig_define or [], default_value) + variable = self.pkgconfig.variable(self.name, pkgconfig, pkgconfig_define) + if variable is not None: + return variable except DependencyException: pass if default_value is not None: diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index d8a94074bc48..25cf610f094e 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -198,7 +198,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): self.is_found = False return if self.private_headers: - qt_inc_dir = mod.get_pkgconfig_variable('includedir', [], None) + qt_inc_dir = mod.get_variable(pkgconfig='includedir') mod_private_dir = os.path.join(qt_inc_dir, 'Qt' + m) if not os.path.isdir(mod_private_dir): # At least some versions of homebrew don't seem to set this @@ -220,7 +220,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): if arg == f'-l{debug_lib_name}' or arg.endswith(f'{debug_lib_name}.lib') or arg.endswith(f'{debug_lib_name}.a'): is_debug = True break - libdir = self.get_pkgconfig_variable('libdir', [], None) + libdir = self.get_variable(pkgconfig='libdir') if not self._link_with_qt_winmain(is_debug, libdir): self.is_found = False return @@ -228,7 +228,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): self.bindir = self.get_pkgconfig_host_bins(self) if not self.bindir: # If exec_prefix is not defined, the pkg-config file is broken - prefix = self.get_pkgconfig_variable('exec_prefix', [], None) + prefix = self.get_variable(pkgconfig='exec_prefix') if prefix: self.bindir = os.path.join(prefix, 'bin') @@ -422,7 +422,7 @@ def get_pkgconfig_host_bins(core: PkgConfigDependency) -> T.Optional[str]: applications = ['moc', 'uic', 'rcc', 'lupdate', 'lrelease'] for application in applications: try: - return os.path.dirname(core.get_pkgconfig_variable(f'{application}_location', [], None)) + return os.path.dirname(core.get_variable(pkgconfig=f'{application}_location')) except mesonlib.MesonException: pass return None @@ -439,7 +439,7 @@ class Qt5PkgConfigDependency(QtPkgConfigDependency): @staticmethod def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str: - return core.get_pkgconfig_variable('host_bins', [], None) + return core.get_variable(pkgconfig='host_bins') @staticmethod def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str: @@ -460,12 +460,12 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): @staticmethod def get_pkgconfig_host_bins(core: PkgConfigDependency) -> str: - return core.get_pkgconfig_variable('bindir', [], None) + return core.get_variable(pkgconfig='bindir') @staticmethod def get_pkgconfig_host_libexecs(core: PkgConfigDependency) -> str: # Qt6 pkg-config for Qt defines libexecdir from 6.3+ - return core.get_pkgconfig_variable('libexecdir', [], None) + return core.get_variable(pkgconfig='libexecdir') def get_private_includes(self, mod_inc_dir: str, module: str) -> T.List[str]: return _qt_get_private_includes(mod_inc_dir, module, self.version) diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index fc2f7206423e..158056fa0311 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -148,5 +148,5 @@ def _set_cargs(self) -> None: # gfortran doesn't appear to look in system paths for INCLUDE files, # so don't allow pkg-config to suppress -I flags for system paths allow_system = True - cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=['prefix', self.__mklroot.as_posix()]) + cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=('prefix', self.__mklroot.as_posix())) self.compile_args = self._convert_mingw_paths(cflags) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index f1f8ea8fbc23..a76a0cbd919c 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -21,7 +21,7 @@ typed_pos_args, typed_kwargs, typed_operator, noArgsFlattening, noPosargs, noKwargs, unholder_return, flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode) -from ..interpreter.type_checking import NoneType, ENV_SEPARATOR_KW +from ..interpreter.type_checking import NoneType, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW from ..dependencies import Dependency, ExternalLibrary, InternalDependency from ..programs import ExternalProgram from ..mesonlib import HoldableObject, OptionKey, listify, Popen_safe @@ -487,17 +487,18 @@ def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: @typed_pos_args('dependency.get_pkgconfig_variable', str) @typed_kwargs( 'dependency.get_pkgconfig_variable', - KwargInfo('default', (str, NoneType)), - KwargInfo( - 'define_variable', - ContainerTypeInfo(list, str, pairs=True), - default=[], - listify=True, - validator=lambda x: 'must be of length 2 or empty' if len(x) not in {0, 2} else None, - ), + KwargInfo('default', str, default=''), + PKGCONFIG_DEFINE_KW.evolve(name='define_variable') ) def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConfigVar') -> str: - return self.held_object.get_pkgconfig_variable(args[0], **kwargs) + from ..dependencies.pkgconfig import PkgConfigDependency + if not isinstance(self.held_object, PkgConfigDependency): + raise InvalidArguments(f'{self.held_object.get_name()!r} is not a pkgconfig dependency') + return self.held_object.get_variable( + pkgconfig=args[0], + default_value=kwargs['default'], + pkgconfig_define=kwargs['define_variable'], + ) @FeatureNew('dependency.get_configtool_variable', '0.44.0') @FeatureDeprecated('dependency.get_configtool_variable', '0.56.0', @@ -523,7 +524,7 @@ def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.Dep KwargInfo('configtool', (str, NoneType)), KwargInfo('internal', (str, NoneType), since='0.54.0'), KwargInfo('default_value', (str, NoneType)), - KwargInfo('pkgconfig_define', ContainerTypeInfo(list, str, pairs=True), default=[], listify=True), + PKGCONFIG_DEFINE_KW, ) def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> str: default_varname = args[0] diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index e67ebf0c0e4b..35b8fb65bcf7 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -16,7 +16,7 @@ from ..mesonlib import EnvironmentVariables, MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram - +from .type_checking import PkgConfigDefineType class FuncAddProjectArgs(TypedDict): @@ -256,7 +256,7 @@ class FeatureOptionRequire(TypedDict): class DependencyPkgConfigVar(TypedDict): default: T.Optional[str] - define_variable: T.List[str] + define_variable: PkgConfigDefineType class DependencyGetVariable(TypedDict): @@ -266,7 +266,7 @@ class DependencyGetVariable(TypedDict): configtool: T.Optional[str] internal: T.Optional[str] default_value: T.Optional[str] - pkgconfig_define: T.List[str] + pkgconfig_define: PkgConfigDefineType class ConfigurationDataSet(TypedDict): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 047aff867392..645b27363024 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -29,6 +29,7 @@ from ..mesonlib import EnvInitValueType _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] + PkgConfigDefineType = T.Optional[T.Tuple[str, str]] def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]: @@ -648,3 +649,11 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup } ) ] + +PKGCONFIG_DEFINE_KW: KwargInfo = KwargInfo( + 'pkgconfig_define', + ContainerTypeInfo(list, str, pairs=True), + default=[], + validator=lambda x: 'must be of length 2 or empty' if len(x) not in {0, 2} else None, + convertor=lambda x: tuple(x) if x else None +) diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 46b1b605de35..aea5da2e00dd 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -85,7 +85,7 @@ def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List datadir = b.environment.coredata.get_option(OptionKey('datadir')) assert isinstance(datadir, str), 'for mypy' datadir_abs = os.path.join(prefix, datadir) - completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=['datadir', datadir_abs]) + completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=('datadir', datadir_abs)) assert isinstance(completionsdir, str), 'for mypy' completionsdir_path = Path(completionsdir) for f in install_data.data: diff --git a/test cases/unit/114 empty project/expected_mods.json b/test cases/unit/114 empty project/expected_mods.json index 7463bcb1275a..6cd65c315cea 100644 --- a/test cases/unit/114 empty project/expected_mods.json +++ b/test cases/unit/114 empty project/expected_mods.json @@ -188,6 +188,7 @@ "mesonbuild.dependencies", "mesonbuild.dependencies.base", "mesonbuild.dependencies.detect", + "mesonbuild.dependencies.pkgconfig", "mesonbuild.depfile", "mesonbuild.envconfig", "mesonbuild.environment", diff --git a/unittests/failuretests.py b/unittests/failuretests.py index ce58f3f2bc09..1fe29a266e9e 100644 --- a/unittests/failuretests.py +++ b/unittests/failuretests.py @@ -242,7 +242,7 @@ def test_dependency_invalid_method(self): dep = declare_dependency(dependencies : zlib_dep) dep.get_pkgconfig_variable('foo') ''' - self.assertMesonRaises(code, "Method.*pkgconfig.*is invalid.*internal") + self.assertMesonRaises(code, ".*is not a pkgconfig dependency") code = '''zlib_dep = dependency('zlib', required : false) dep = declare_dependency(dependencies : zlib_dep) dep.get_configtool_variable('foo') diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 2de4dbcf0d25..cbce5229d91d 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -164,19 +164,19 @@ def test_pkgconfig_gen(self): self.assertTrue(foo_dep.found()) self.assertEqual(foo_dep.get_version(), '1.0') self.assertIn('-lfoo', foo_dep.get_link_args()) - self.assertEqual(foo_dep.get_pkgconfig_variable('foo', [], None), 'bar') - self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir', [], None), '/usr/data') + self.assertEqual(foo_dep.get_variable(pkgconfig='foo'), 'bar') + self.assertPathEqual(foo_dep.get_variable(pkgconfig='datadir'), '/usr/data') libhello_nolib = PkgConfigDependency('libhello_nolib', env, kwargs) self.assertTrue(libhello_nolib.found()) self.assertEqual(libhello_nolib.get_link_args(), []) self.assertEqual(libhello_nolib.get_compile_args(), []) - self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', [], None), 'bar') - self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', [], None), self.prefix) + self.assertEqual(libhello_nolib.get_variable(pkgconfig='foo'), 'bar') + self.assertEqual(libhello_nolib.get_variable(pkgconfig='prefix'), self.prefix) impl = libhello_nolib.pkgconfig if not isinstance(impl, PkgConfigCLI) or version_compare(PkgConfigCLI.check_pkgconfig(env, impl.pkgbin),">=0.29.1"): - self.assertEqual(libhello_nolib.get_pkgconfig_variable('escaped_var', [], None), r'hello\ world') - self.assertEqual(libhello_nolib.get_pkgconfig_variable('unescaped_var', [], None), 'hello world') + self.assertEqual(libhello_nolib.get_variable(pkgconfig='escaped_var'), r'hello\ world') + self.assertEqual(libhello_nolib.get_variable(pkgconfig='unescaped_var'), 'hello world') cc = detect_c_compiler(env, MachineChoice.HOST) if cc.get_id() in {'gcc', 'clang'}: From dec85c41a9e5d6f8bb2c4431a78a0a9ade3651fd Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 15 Aug 2023 21:03:07 -0400 Subject: [PATCH 237/855] Remove get_configtool_variable() This also makes it more consistent with get_pkgconfig_variable() which always return empty value instead of failing when the variable does not exist. Linking that to self.required makes no sense and was never documented any way. --- mesonbuild/dependencies/base.py | 7 ----- mesonbuild/dependencies/configtool.py | 28 ++++--------------- mesonbuild/interpreter/interpreterobjects.py | 8 +++++- .../unit/114 empty project/expected_mods.json | 1 - unittests/failuretests.py | 2 +- 5 files changed, 13 insertions(+), 33 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 6da9a6665d5e..c4861ff12116 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -193,9 +193,6 @@ def get_include_type(self) -> str: def get_exe_args(self, compiler: 'Compiler') -> T.List[str]: return [] - def get_configtool_variable(self, variable_name: str) -> str: - raise DependencyException(f'{self.name!r} is not a config-tool dependency') - def get_partial_dependency(self, *, compile_args: bool = False, link_args: bool = False, links: bool = False, includes: bool = False, sources: bool = False) -> 'Dependency': @@ -292,10 +289,6 @@ def is_built(self) -> bool: return True return any(d.is_built() for d in self.ext_deps) - def get_configtool_variable(self, variable_name: str) -> str: - raise DependencyException('Method "get_configtool_variable()" is ' - 'invalid for an internal dependency') - def get_partial_dependency(self, *, compile_args: bool = False, link_args: bool = False, links: bool = False, includes: bool = False, sources: bool = False, diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index bd6a9ff73413..3c523560115b 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -154,17 +154,6 @@ def get_config_value(self, args: T.List[str], stage: str) -> T.List[str]: def get_variable_args(self, variable_name: str) -> T.List[str]: return [f'--{variable_name}'] - def get_configtool_variable(self, variable_name: str) -> str: - p, out, _ = Popen_safe(self.config + self.get_variable_args(variable_name)) - if p.returncode != 0: - if self.required: - raise DependencyException( - 'Could not get variable "{}" for dependency {}'.format( - variable_name, self.name)) - variable = out.strip() - mlog.debug(f'Got config-tool variable {variable_name} : {variable}') - return variable - @staticmethod def log_tried() -> str: return 'config-tool' @@ -174,18 +163,11 @@ def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[s default_value: T.Optional[str] = None, pkgconfig_define: PkgConfigDefineType = None) -> str: if configtool: - # In the not required case '' (empty string) will be returned if the - # variable is not found. Since '' is a valid value to return we - # set required to True here to force and error, and use the - # finally clause to ensure it's restored. - restore = self.required - self.required = True - try: - return self.get_configtool_variable(configtool) - except DependencyException: - pass - finally: - self.required = restore + p, out, _ = Popen_safe(self.config + self.get_variable_args(configtool)) + if p.returncode == 0: + variable = out.strip() + mlog.debug(f'Got config-tool variable {configtool} : {variable}') + return variable if default_value is not None: return default_value raise DependencyException(f'Could not get config-tool variable and no default provided for {self!r}') diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index a76a0cbd919c..46b4cc1e51c1 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -506,7 +506,13 @@ def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConf @noKwargs @typed_pos_args('dependency.get_config_tool_variable', str) def configtool_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> str: - return self.held_object.get_configtool_variable(args[0]) + from ..dependencies.configtool import ConfigToolDependency + if not isinstance(self.held_object, ConfigToolDependency): + raise InvalidArguments(f'{self.held_object.get_name()!r} is not a config-tool dependency') + return self.held_object.get_variable( + configtool=args[0], + default_value='', + ) @FeatureNew('dependency.partial_dependency', '0.46.0') @noPosargs diff --git a/test cases/unit/114 empty project/expected_mods.json b/test cases/unit/114 empty project/expected_mods.json index 6cd65c315cea..7463bcb1275a 100644 --- a/test cases/unit/114 empty project/expected_mods.json +++ b/test cases/unit/114 empty project/expected_mods.json @@ -188,7 +188,6 @@ "mesonbuild.dependencies", "mesonbuild.dependencies.base", "mesonbuild.dependencies.detect", - "mesonbuild.dependencies.pkgconfig", "mesonbuild.depfile", "mesonbuild.envconfig", "mesonbuild.environment", diff --git a/unittests/failuretests.py b/unittests/failuretests.py index 1fe29a266e9e..2b7c73ea5eb9 100644 --- a/unittests/failuretests.py +++ b/unittests/failuretests.py @@ -247,7 +247,7 @@ def test_dependency_invalid_method(self): dep = declare_dependency(dependencies : zlib_dep) dep.get_configtool_variable('foo') ''' - self.assertMesonRaises(code, "Method.*configtool.*is invalid.*internal") + self.assertMesonRaises(code, ".* is not a config-tool dependency") def test_objc_cpp_detection(self): ''' From dacd11a6247b97be4981ceabaa75b3a25282f3b4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 15 Aug 2023 17:38:39 -0400 Subject: [PATCH 238/855] pkgconfig: Cache the implementation instance --- mesonbuild/dependencies/pkgconfig.py | 73 ++++++++++++---------------- mesonbuild/utils/universal.py | 4 ++ run_tests.py | 13 ++--- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 1d9863a1cdb1..9729baa840f9 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -16,7 +16,7 @@ from pathlib import Path from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName -from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged +from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged, MachineChoice from ..programs import find_external_program, ExternalProgram from .. import mlog from pathlib import PurePath @@ -29,20 +29,31 @@ from typing_extensions import Literal from ..environment import Environment - from ..mesonlib import MachineChoice from ..utils.core import EnvironOrDict from ..interpreter.type_checking import PkgConfigDefineType class PkgConfigInterface: '''Base class wrapping a pkg-config implementation''' + class_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigInterface]]] = PerMachine(False, False) + @staticmethod def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[PkgConfigInterface]: - impl = PkgConfigCLI(env, for_machine, silent) - if not impl.found(): - return None + for_machine = for_machine if env.is_cross_build() else MachineChoice.HOST + impl = PkgConfigInterface.class_impl[for_machine] + if impl is False: + impl = PkgConfigCLI(env, for_machine, silent) + if not impl.found(): + impl = None + if not impl and not silent: + mlog.log('Found pkg-config:', mlog.red('NO')) + PkgConfigInterface.class_impl[for_machine] = impl return impl + def __init__(self, env: Environment, for_machine: MachineChoice) -> None: + self.env = env + self.for_machine = for_machine + def found(self) -> bool: '''Return whether pkg-config is supported''' raise NotImplementedError @@ -78,9 +89,6 @@ def list_all(self) -> T.List[str]: class PkgConfigCLI(PkgConfigInterface): '''pkg-config CLI implementation''' - # The class's copy of the pkg-config path. Avoids having to search for it - # multiple times in the same Meson invocation. - class_pkgbin: PerMachine[T.Union[None, Literal[False], ExternalProgram]] = PerMachine(None, None) # We cache all pkg-config subprocess invocations to avoid redundant calls pkgbin_cache: T.Dict[ T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]], @@ -88,11 +96,12 @@ class PkgConfigCLI(PkgConfigInterface): ] = {} def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None: - self.env = env - self.for_machine = for_machine + super().__init__(env, for_machine) # Store a copy of the pkg-config path on the object itself so it is # stored in the pickled coredata and recovered. - self.pkgbin = self._detect_pkgbin(env, for_machine, silent) + self.pkgbin = self._detect_pkgbin(env, for_machine) + if self.pkgbin and not silent: + mlog.log('Found pkg-config:', mlog.green('YES'), mlog.blue(self.pkgbin.get_path())) def found(self) -> bool: return bool(self.pkgbin) @@ -162,41 +171,21 @@ def list_all(self) -> T.List[str]: raise DependencyException(f'could not list modules:\n{err}\n') return [i.split(' ', 1)[0] for i in out.splitlines()] - def _split_args(self, cmd: str) -> T.List[str]: + @staticmethod + def _split_args(cmd: str) -> T.List[str]: # pkg-config paths follow Unix conventions, even on Windows; split the # output using shlex.split rather than mesonlib.split_args return shlex.split(cmd) - @classmethod - def _detect_pkgbin(cls, env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[ExternalProgram]: - # Only search for pkg-config for each machine the first time and store - # the result in the class definition - if cls.class_pkgbin[for_machine] is False: - mlog.debug(f'Pkg-config binary for {for_machine} is cached as not found.') - elif cls.class_pkgbin[for_machine] is not None: - mlog.debug(f'Pkg-config binary for {for_machine} is cached.') - else: - assert cls.class_pkgbin[for_machine] is None, 'for mypy' - mlog.debug(f'Pkg-config binary for {for_machine} is not cached.') - for potential_pkgbin in find_external_program( - env, for_machine, 'pkgconfig', 'Pkg-config', - env.default_pkgconfig, allow_default_for_cross=False): - version_if_ok = cls.check_pkgconfig(env, potential_pkgbin) - if not version_if_ok: - continue - if not silent: - mlog.log('Found pkg-config:', mlog.bold(potential_pkgbin.get_path()), - f'({version_if_ok})') - cls.class_pkgbin[for_machine] = potential_pkgbin - break - else: - if not silent: - mlog.log('Found pkg-config:', mlog.red('NO')) - # Set to False instead of None to signify that we've already - # searched for it and not found it - cls.class_pkgbin[for_machine] = False - - return cls.class_pkgbin[for_machine] or None + @staticmethod + def _detect_pkgbin(env: Environment, for_machine: MachineChoice) -> T.Optional[ExternalProgram]: + for potential_pkgbin in find_external_program( + env, for_machine, 'pkgconfig', 'Pkg-config', + env.default_pkgconfig, allow_default_for_cross=False): + version_if_ok = PkgConfigCLI.check_pkgconfig(env, potential_pkgbin) + if version_if_ok: + return potential_pkgbin + return None def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]: assert isinstance(self.pkgbin, ExternalProgram) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 1d0e382a835d..8216e780420c 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -524,6 +524,10 @@ def miss_defaulting(self) -> "PerMachineDefaultable[T.Optional[_T]]": unfreeze.host = None return unfreeze + def assign(self, build: _T, host: _T) -> None: + self.build = build + self.host = host + def __repr__(self) -> str: return f'PerMachine({self.build!r}, {self.host!r})' diff --git a/run_tests.py b/run_tests.py index 699e29356153..a959d6ab5833 100755 --- a/run_tests.py +++ b/run_tests.py @@ -36,7 +36,7 @@ from mesonbuild.compilers.c import CCompiler from mesonbuild.compilers.detect import detect_c_compiler -from mesonbuild.dependencies.pkgconfig import PkgConfigCLI +from mesonbuild.dependencies.pkgconfig import PkgConfigInterface from mesonbuild import mesonlib from mesonbuild import mesonmain from mesonbuild import mtest @@ -161,6 +161,8 @@ def get_fake_env(sdir='', bdir=None, prefix='', opts=None): env = Environment(sdir, bdir, opts) env.coredata.options[OptionKey('args', lang='c')] = FakeCompilerOptions() env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library + # Invalidate cache when using a different Environment object. + clear_meson_configure_class_caches() return env def get_convincing_fake_env_and_cc(bdir, prefix): @@ -309,11 +311,10 @@ def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: return returncode, out.getvalue() def clear_meson_configure_class_caches() -> None: - CCompiler.find_library_cache = {} - CCompiler.find_framework_cache = {} - PkgConfigCLI.pkgbin_cache = {} - PkgConfigCLI.class_pkgbin = mesonlib.PerMachine(None, None) - mesonlib.project_meson_versions = collections.defaultdict(str) + CCompiler.find_library_cache.clear() + CCompiler.find_framework_cache.clear() + PkgConfigInterface.class_impl.assign(False, False) + mesonlib.project_meson_versions.clear() def run_configure_inprocess(commandlist: T.List[str], env: T.Optional[T.Dict[str, str]] = None, catch_exception: bool = False) -> T.Tuple[int, str, str]: stderr = StringIO() From 2a6245e6b3079f5775ca6fb3695d3cbe8cc1932e Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 15 Aug 2023 17:57:06 -0400 Subject: [PATCH 239/855] pkgconfig: Use lru_cache instead of caching command lines --- mesonbuild/dependencies/pkgconfig.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 9729baa840f9..d6f42864df0b 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -20,6 +20,7 @@ from ..programs import find_external_program, ExternalProgram from .. import mlog from pathlib import PurePath +from functools import lru_cache import re import os import shlex @@ -89,12 +90,6 @@ def list_all(self) -> T.List[str]: class PkgConfigCLI(PkgConfigInterface): '''pkg-config CLI implementation''' - # We cache all pkg-config subprocess invocations to avoid redundant calls - pkgbin_cache: T.Dict[ - T.Tuple[ExternalProgram, T.Tuple[str, ...], T.FrozenSet[T.Tuple[str, str]]], - T.Tuple[int, str, str] - ] = {} - def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None: super().__init__(env, for_machine) # Store a copy of the pkg-config path on the object itself so it is @@ -106,6 +101,7 @@ def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) - def found(self) -> bool: return bool(self.pkgbin) + @lru_cache(maxsize=None) def version(self, name: str) -> T.Optional[str]: mlog.debug(f'Determining dependency {name!r} with pkg-config executable {self.pkgbin.get_path()!r}') ret, version, _ = self._call_pkgbin(['--modversion', name]) @@ -117,6 +113,7 @@ def _define_variable_args(define_variable: PkgConfigDefineType) -> T.List[str]: return ['--define-variable=' + '='.join(define_variable)] return [] + @lru_cache(maxsize=None) def cflags(self, name: str, allow_system: bool = False, define_variable: PkgConfigDefineType = None) -> T.List[str]: env = None @@ -131,6 +128,7 @@ def cflags(self, name: str, allow_system: bool = False, raise DependencyException(f'Could not generate cflags for {name}:\n{err}\n') return self._split_args(out) + @lru_cache(maxsize=None) def libs(self, name: str, static: bool = False, allow_system: bool = False, define_variable: PkgConfigDefineType = None) -> T.List[str]: env = None @@ -147,6 +145,7 @@ def libs(self, name: str, static: bool = False, allow_system: bool = False, raise DependencyException(f'Could not generate libs for {name}:\n{err}\n') return self._split_args(out) + @lru_cache(maxsize=None) def variable(self, name: str, variable_name: str, define_variable: PkgConfigDefineType) -> T.Optional[str]: args: T.List[str] = [] @@ -165,6 +164,7 @@ def variable(self, name: str, variable_name: str, mlog.debug(f'Got pkg-config variable {variable_name} : {variable}') return variable + @lru_cache(maxsize=None) def list_all(self) -> T.List[str]: ret, out, err = self._call_pkgbin(['--list-all']) if ret != 0: @@ -187,12 +187,6 @@ def _detect_pkgbin(env: Environment, for_machine: MachineChoice) -> T.Optional[E return potential_pkgbin return None - def _call_pkgbin_real(self, args: T.List[str], env: T.Dict[str, str]) -> T.Tuple[int, str, str]: - assert isinstance(self.pkgbin, ExternalProgram) - cmd = self.pkgbin.get_command() + args - p, out, err = Popen_safe_logged(cmd, env=env) - return p.returncode, out.strip(), err.strip() - @staticmethod def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str]: if not pkgbin.found(): @@ -253,13 +247,9 @@ def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) assert isinstance(self.pkgbin, ExternalProgram) env = env or os.environ env = self.setup_env(env, self.env, self.for_machine) - - fenv = frozenset(env.items()) - targs = tuple(args) - cache = self.pkgbin_cache - if (self.pkgbin, targs, fenv) not in cache: - cache[(self.pkgbin, targs, fenv)] = self._call_pkgbin_real(args, env) - return cache[(self.pkgbin, targs, fenv)] + cmd = self.pkgbin.get_command() + args + p, out, err = Popen_safe_logged(cmd, env=env) + return p.returncode, out.strip(), err.strip() class PkgConfigDependency(ExternalDependency): From 0eae4e0936181b7f89d73fcb15d752cdf1bea05a Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 16 Aug 2023 08:50:34 -0400 Subject: [PATCH 240/855] pkgconfig: Restore logging of pkg-config version While at it, make more methods private by storing the version found on the instance. That avoids having to call check_pkgconfig() as static method from unittests. --- mesonbuild/dependencies/pkgconfig.py | 26 ++++++++++++-------------- unittests/linuxliketests.py | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index d6f42864df0b..ab6896ef9309 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -92,11 +92,9 @@ class PkgConfigCLI(PkgConfigInterface): def __init__(self, env: Environment, for_machine: MachineChoice, silent: bool) -> None: super().__init__(env, for_machine) - # Store a copy of the pkg-config path on the object itself so it is - # stored in the pickled coredata and recovered. - self.pkgbin = self._detect_pkgbin(env, for_machine) + self._detect_pkgbin() if self.pkgbin and not silent: - mlog.log('Found pkg-config:', mlog.green('YES'), mlog.blue(self.pkgbin.get_path())) + mlog.log('Found pkg-config:', mlog.green('YES'), mlog.bold(f'({self.pkgbin.get_path()})'), mlog.blue(self.pkgbin_version)) def found(self) -> bool: return bool(self.pkgbin) @@ -177,18 +175,18 @@ def _split_args(cmd: str) -> T.List[str]: # output using shlex.split rather than mesonlib.split_args return shlex.split(cmd) - @staticmethod - def _detect_pkgbin(env: Environment, for_machine: MachineChoice) -> T.Optional[ExternalProgram]: + def _detect_pkgbin(self) -> None: for potential_pkgbin in find_external_program( - env, for_machine, 'pkgconfig', 'Pkg-config', - env.default_pkgconfig, allow_default_for_cross=False): - version_if_ok = PkgConfigCLI.check_pkgconfig(env, potential_pkgbin) + self.env, self.for_machine, 'pkgconfig', 'Pkg-config', + self.env.default_pkgconfig, allow_default_for_cross=False): + version_if_ok = self._check_pkgconfig(potential_pkgbin) if version_if_ok: - return potential_pkgbin - return None + self.pkgbin = potential_pkgbin + self.pkgbin_version = version_if_ok + return + self.pkgbin = None - @staticmethod - def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str]: + def _check_pkgconfig(self, pkgbin: ExternalProgram) -> T.Optional[str]: if not pkgbin.found(): mlog.log(f'Did not find pkg-config by name {pkgbin.name!r}') return None @@ -207,7 +205,7 @@ def check_pkgconfig(env: Environment, pkgbin: ExternalProgram) -> T.Optional[str return None except PermissionError: msg = f'Found pkg-config {command_as_string!r} but didn\'t have permissions to run it.' - if not env.machines.build.is_windows(): + if not self.env.machines.build.is_windows(): msg += '\n\nOn Unix-like systems this is often caused by scripts that are not executable.' mlog.warning(msg) return None diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index cbce5229d91d..8760fae1aee7 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -174,7 +174,7 @@ def test_pkgconfig_gen(self): self.assertEqual(libhello_nolib.get_variable(pkgconfig='foo'), 'bar') self.assertEqual(libhello_nolib.get_variable(pkgconfig='prefix'), self.prefix) impl = libhello_nolib.pkgconfig - if not isinstance(impl, PkgConfigCLI) or version_compare(PkgConfigCLI.check_pkgconfig(env, impl.pkgbin),">=0.29.1"): + if not isinstance(impl, PkgConfigCLI) or version_compare(impl.pkgbin_version, ">=0.29.1"): self.assertEqual(libhello_nolib.get_variable(pkgconfig='escaped_var'), r'hello\ world') self.assertEqual(libhello_nolib.get_variable(pkgconfig='unescaped_var'), 'hello world') From 6a56f6d98fb7806a59967b0df3ede26544eac4a4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 18 Aug 2023 12:58:18 -0400 Subject: [PATCH 241/855] pkgconfig: Deprecate "pkgconfig" in favor of "pkg-config" in [binaries] --- mesonbuild/dependencies/pkgconfig.py | 2 +- mesonbuild/envconfig.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index ab6896ef9309..89442af87ce9 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -177,7 +177,7 @@ def _split_args(cmd: str) -> T.List[str]: def _detect_pkgbin(self) -> None: for potential_pkgbin in find_external_program( - self.env, self.for_machine, 'pkgconfig', 'Pkg-config', + self.env, self.for_machine, 'pkg-config', 'Pkg-config', self.env.default_pkgconfig, allow_default_for_cross=False): version_if_ok = self._check_pkgconfig(potential_pkgbin) if version_if_ok: diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 5340521c3a4e..c6b543a3421c 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -133,7 +133,6 @@ # Other tools 'cmake': 'CMAKE', 'qmake': 'QMAKE', - 'pkgconfig': 'PKG_CONFIG', 'pkg-config': 'PKG_CONFIG', 'make': 'MAKE', 'vapigen': 'VAPIGEN', @@ -403,6 +402,11 @@ def __init__( if not isinstance(command, (list, str)): raise mesonlib.MesonException( f'Invalid type {command!r} for entry {name!r} in cross file') + if name == 'pkgconfig': + if 'pkg-config' in binaries: + raise mesonlib.MesonException('Both pkgconfig and pkg-config entries in machine file.') + mlog.deprecation('"pkgconfig" entry is deprecated and should be replaced by "pkg-config"') + name = 'pkg-config' self.binaries[name] = mesonlib.listify(command) @staticmethod From f1c35b561f80174ae1ea936da282d8736c19e247 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 18 Aug 2023 09:56:13 -0400 Subject: [PATCH 242/855] pkgconfig: Set PKG_CONFIG in env for devenv and g-ir-scanner --- mesonbuild/dependencies/pkgconfig.py | 56 +++++++++++++++++++------- mesonbuild/modules/external_project.py | 9 +++-- mesonbuild/modules/gnome.py | 4 +- mesonbuild/modules/pkgconfig.py | 4 +- unittests/linuxliketests.py | 4 +- 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 89442af87ce9..7035eabb10ee 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -16,7 +16,7 @@ from pathlib import Path from .base import ExternalDependency, DependencyException, sort_libpaths, DependencyTypeName -from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged, MachineChoice +from ..mesonlib import EnvironmentVariables, OptionKey, OrderedSet, PerMachine, Popen_safe, Popen_safe_logged, MachineChoice, join_args from ..programs import find_external_program, ExternalProgram from .. import mlog from pathlib import PurePath @@ -37,9 +37,11 @@ class PkgConfigInterface: '''Base class wrapping a pkg-config implementation''' class_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigInterface]]] = PerMachine(False, False) + class_cli_impl: PerMachine[T.Union[Literal[False], T.Optional[PkgConfigCLI]]] = PerMachine(False, False) @staticmethod def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Optional[PkgConfigInterface]: + '''Return a pkg-config implementation singleton''' for_machine = for_machine if env.is_cross_build() else MachineChoice.HOST impl = PkgConfigInterface.class_impl[for_machine] if impl is False: @@ -51,6 +53,35 @@ def instance(env: Environment, for_machine: MachineChoice, silent: bool) -> T.Op PkgConfigInterface.class_impl[for_machine] = impl return impl + @staticmethod + def _cli(env: Environment, for_machine: MachineChoice, silent: bool = False) -> T.Optional[PkgConfigCLI]: + '''Return the CLI pkg-config implementation singleton + Even when we use another implementation internally, external tools might + still need the CLI implementation. + ''' + for_machine = for_machine if env.is_cross_build() else MachineChoice.HOST + impl: T.Union[Literal[False], T.Optional[PkgConfigInterface]] # Help confused mypy + impl = PkgConfigInterface.instance(env, for_machine, silent) + if impl and not isinstance(impl, PkgConfigCLI): + impl = PkgConfigInterface.class_cli_impl[for_machine] + if impl is False: + impl = PkgConfigCLI(env, for_machine, silent) + if not impl.found(): + impl = None + PkgConfigInterface.class_cli_impl[for_machine] = impl + return T.cast('T.Optional[PkgConfigCLI]', impl) # Trust me, mypy + + @staticmethod + def get_env(env: Environment, for_machine: MachineChoice, uninstalled: bool = False) -> EnvironmentVariables: + cli = PkgConfigInterface._cli(env, for_machine) + return cli._get_env(uninstalled) if cli else EnvironmentVariables() + + @staticmethod + def setup_env(environ: EnvironOrDict, env: Environment, for_machine: MachineChoice, + uninstalled: bool = False) -> EnvironOrDict: + cli = PkgConfigInterface._cli(env, for_machine) + return cli._setup_env(environ, uninstalled) if cli else environ + def __init__(self, env: Environment, for_machine: MachineChoice) -> None: self.env = env self.for_machine = for_machine @@ -211,29 +242,26 @@ def _check_pkgconfig(self, pkgbin: ExternalProgram) -> T.Optional[str]: return None return out.strip() - @staticmethod - def get_env(environment: Environment, for_machine: MachineChoice, - uninstalled: bool = False) -> EnvironmentVariables: + def _get_env(self, uninstalled: bool = False) -> EnvironmentVariables: env = EnvironmentVariables() - key = OptionKey('pkg_config_path', machine=for_machine) - extra_paths: T.List[str] = environment.coredata.options[key].value[:] + key = OptionKey('pkg_config_path', machine=self.for_machine) + extra_paths: T.List[str] = self.env.coredata.options[key].value[:] if uninstalled: - uninstalled_path = Path(environment.get_build_dir(), 'meson-uninstalled').as_posix() + uninstalled_path = Path(self.env.get_build_dir(), 'meson-uninstalled').as_posix() if uninstalled_path not in extra_paths: extra_paths.append(uninstalled_path) env.set('PKG_CONFIG_PATH', extra_paths) - sysroot = environment.properties[for_machine].get_sys_root() + sysroot = self.env.properties[self.for_machine].get_sys_root() if sysroot: env.set('PKG_CONFIG_SYSROOT_DIR', [sysroot]) - pkg_config_libdir_prop = environment.properties[for_machine].get_pkg_config_libdir() + pkg_config_libdir_prop = self.env.properties[self.for_machine].get_pkg_config_libdir() if pkg_config_libdir_prop: env.set('PKG_CONFIG_LIBDIR', pkg_config_libdir_prop) + env.set('PKG_CONFIG', [join_args(self.pkgbin.get_command())]) return env - @staticmethod - def setup_env(env: EnvironOrDict, environment: Environment, for_machine: MachineChoice, - uninstalled: bool = False) -> T.Dict[str, str]: - envvars = PkgConfigCLI.get_env(environment, for_machine, uninstalled) + def _setup_env(self, env: EnvironOrDict, uninstalled: bool = False) -> T.Dict[str, str]: + envvars = self._get_env(uninstalled) env = envvars.get_env(env) # Dump all PKG_CONFIG environment variables for key, value in env.items(): @@ -244,7 +272,7 @@ def setup_env(env: EnvironOrDict, environment: Environment, for_machine: Machine def _call_pkgbin(self, args: T.List[str], env: T.Optional[EnvironOrDict] = None) -> T.Tuple[int, str, str]: assert isinstance(self.pkgbin, ExternalProgram) env = env or os.environ - env = self.setup_env(env, self.env, self.for_machine) + env = self._setup_env(env) cmd = self.pkgbin.get_command() + args p, out, err = Popen_safe_logged(cmd, env=env) return p.returncode, out.strip(), err.strip() diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index e7b7c43f6985..bd6eba494156 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -24,7 +24,7 @@ from ..compilers.compilers import CFLAGS_MAPPING from ..envconfig import ENV_VAR_PROG_MAP from ..dependencies import InternalDependency -from ..dependencies.pkgconfig import PkgConfigCLI +from ..dependencies.pkgconfig import PkgConfigInterface from ..interpreterbase import FeatureNew from ..interpreter.type_checking import ENV_KW, DEPENDS_KW from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -40,6 +40,7 @@ from ..interpreter import Interpreter from ..interpreterbase import TYPE_var from ..mesonlib import EnvironmentVariables + from ..utils.core import EnvironOrDict class Dependency(TypedDict): @@ -144,7 +145,7 @@ def _configure(self, state: 'ModuleState') -> None: # Set common env variables like CFLAGS, CC, etc. link_exelist: T.List[str] = [] link_args: T.List[str] = [] - self.run_env = os.environ.copy() + self.run_env: EnvironOrDict = os.environ.copy() for lang, compiler in self.env.coredata.compilers[MachineChoice.HOST].items(): if any(lang not in i for i in (ENV_VAR_PROG_MAP, CFLAGS_MAPPING)): continue @@ -165,8 +166,8 @@ def _configure(self, state: 'ModuleState') -> None: self.run_env['LDFLAGS'] = self._quote_and_join(link_args) self.run_env = self.user_env.get_env(self.run_env) - self.run_env = PkgConfigCLI.setup_env(self.run_env, self.env, MachineChoice.HOST, - uninstalled=True) + self.run_env = PkgConfigInterface.setup_env(self.run_env, self.env, MachineChoice.HOST, + uninstalled=True) self.build_dir.mkdir(parents=True, exist_ok=True) self._run('configure', configure_cmd, workdir) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 7de9d46b39f5..b0bca1590955 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -34,7 +34,7 @@ from .. import mlog from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments from ..dependencies import Dependency, InternalDependency -from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI +from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, in_set_validator from ..interpreterbase import noPosargs, noKwargs, FeatureNew, FeatureDeprecated from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo @@ -980,7 +980,7 @@ def _make_gir_target( # -uninstalled.pc files Meson generated. It also must respect pkgconfig # settings user could have set in machine file, like PKG_CONFIG_LIBDIR, # SYSROOT, etc. - run_env = PkgConfigCLI.get_env(state.environment, MachineChoice.HOST, uninstalled=True) + run_env = PkgConfigInterface.get_env(state.environment, MachineChoice.HOST, uninstalled=True) # g-ir-scanner uses Python's distutils to find the compiler, which uses 'CC' cc_exelist = state.environment.coredata.compilers.host['c'].get_exelist() run_env.set('CC', [quote_arg(x) for x in cc_exelist], ' ') diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 44182d785feb..75521b886869 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -26,7 +26,7 @@ from .. import mesonlib from .. import mlog from ..coredata import BUILTIN_DIR_OPTIONS -from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI +from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface from ..interpreter.type_checking import D_MODULE_VERSIONS_KW, INSTALL_DIR_KW, VARIABLES_KW, NoneType from ..interpreterbase import FeatureNew, FeatureDeprecated from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args @@ -741,7 +741,7 @@ def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]: self._metadata[lib.get_id()] = MetaData( filebase, name, state.current_node) if self.devenv is None: - self.devenv = PkgConfigCLI.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) + self.devenv = PkgConfigInterface.get_env(state.environment, mesonlib.MachineChoice.HOST, uninstalled=True) return ModuleReturnValue(res, [res]) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 8760fae1aee7..7d99d8bf5fea 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -45,7 +45,7 @@ from mesonbuild.compilers.cpp import AppleClangCPPCompiler from mesonbuild.compilers.objc import AppleClangObjCCompiler from mesonbuild.compilers.objcpp import AppleClangObjCPPCompiler -from mesonbuild.dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI +from mesonbuild.dependencies.pkgconfig import PkgConfigDependency, PkgConfigCLI, PkgConfigInterface import mesonbuild.modules.pkgconfig PKG_CONFIG = os.environ.get('PKG_CONFIG', 'pkg-config') @@ -1169,7 +1169,7 @@ def test_pkgconfig_duplicate_path_entries(self): # Regression test: This used to modify the value of `pkg_config_path` # option, adding the meson-uninstalled directory to it. - PkgConfigCLI.setup_env({}, env, MachineChoice.HOST, uninstalled=True) + PkgConfigInterface.setup_env({}, env, MachineChoice.HOST, uninstalled=True) pkg_config_path = env.coredata.options[OptionKey('pkg_config_path')].value self.assertEqual(pkg_config_path, [pkg_dir]) From 8cb0217c4e726e37dcca6ce6a76bac36896152b4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 18 Sep 2023 13:02:30 -0400 Subject: [PATCH 243/855] pkgconfig: Use ImmutableListProtocol[str] for cached lists This ensures that we are not modifying lists from lru cache. --- mesonbuild/dependencies/pkgconfig.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 7035eabb10ee..93422defd67f 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -28,6 +28,7 @@ if T.TYPE_CHECKING: from typing_extensions import Literal + from .._typing import ImmutableListProtocol from ..environment import Environment from ..utils.core import EnvironOrDict @@ -95,14 +96,14 @@ def version(self, name: str) -> T.Optional[str]: raise NotImplementedError def cflags(self, name: str, allow_system: bool = False, - define_variable: PkgConfigDefineType = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> ImmutableListProtocol[str]: '''Return module cflags @allow_system: If False, remove default system include paths ''' raise NotImplementedError def libs(self, name: str, static: bool = False, allow_system: bool = False, - define_variable: PkgConfigDefineType = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> ImmutableListProtocol[str]: '''Return module libs @static: If True, also include private libraries @allow_system: If False, remove default system libraries search paths @@ -114,7 +115,7 @@ def variable(self, name: str, variable_name: str, '''Return module variable or None if variable is not defined''' raise NotImplementedError - def list_all(self) -> T.List[str]: + def list_all(self) -> ImmutableListProtocol[str]: '''Return all available pkg-config modules''' raise NotImplementedError @@ -144,7 +145,7 @@ def _define_variable_args(define_variable: PkgConfigDefineType) -> T.List[str]: @lru_cache(maxsize=None) def cflags(self, name: str, allow_system: bool = False, - define_variable: PkgConfigDefineType = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> ImmutableListProtocol[str]: env = None if allow_system: env = os.environ.copy() @@ -159,7 +160,7 @@ def cflags(self, name: str, allow_system: bool = False, @lru_cache(maxsize=None) def libs(self, name: str, static: bool = False, allow_system: bool = False, - define_variable: PkgConfigDefineType = None) -> T.List[str]: + define_variable: PkgConfigDefineType = None) -> ImmutableListProtocol[str]: env = None if allow_system: env = os.environ.copy() @@ -194,7 +195,7 @@ def variable(self, name: str, variable_name: str, return variable @lru_cache(maxsize=None) - def list_all(self) -> T.List[str]: + def list_all(self) -> ImmutableListProtocol[str]: ret, out, err = self._call_pkgbin(['--list-all']) if ret != 0: raise DependencyException(f'could not list modules:\n{err}\n') @@ -319,7 +320,7 @@ def __repr__(self) -> str: return s.format(self.__class__.__name__, self.name, self.is_found, self.version_reqs) - def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]: + def _convert_mingw_paths(self, args: ImmutableListProtocol[str]) -> T.List[str]: ''' Both MSVC and native Python on Windows cannot handle MinGW-esque /c/foo paths so convert them to C:/foo. We cannot resolve other paths starting @@ -327,7 +328,7 @@ def _convert_mingw_paths(self, args: T.List[str]) -> T.List[str]: error/warning from the compiler/linker. ''' if not self.env.machines.build.is_windows(): - return args + return args.copy() converted = [] for arg in args: pargs: T.Tuple[str, ...] = tuple() @@ -359,7 +360,7 @@ def _set_cargs(self) -> None: cflags = self.pkgconfig.cflags(self.name, allow_system) self.compile_args = self._convert_mingw_paths(cflags) - def _search_libs(self, libs_in: T.List[str], raw_libs_in: T.List[str]) -> T.Tuple[T.List[str], T.List[str]]: + def _search_libs(self, libs_in: ImmutableListProtocol[str], raw_libs_in: ImmutableListProtocol[str]) -> T.Tuple[T.List[str], T.List[str]]: ''' @libs_in: PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 pkg-config --libs @raw_libs_in: pkg-config --libs From 94f330fd9d5f4a8a6f2e742e985a30fc4850c434 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 23 Aug 2023 14:52:10 -0400 Subject: [PATCH 244/855] interpreter: Allow regex matching in expect_error() --- mesonbuild/interpreter/interpreter.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 6fcefd14d6c8..10a6abc4715f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1446,23 +1446,28 @@ def func_debug(self, node, args, kwargs): def func_exception(self, node, args, kwargs): raise RuntimeError('unit test traceback :)') - @noKwargs @typed_pos_args('expect_error', str) + @typed_kwargs( + 'expect_error', + KwargInfo('how', str, default='literal', validator=in_set_validator({'literal', 're'})), + ) def func_expect_error(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: TYPE_kwargs) -> ContextManagerObject: class ExpectErrorObject(ContextManagerObject): - def __init__(self, msg: str, subproject: str) -> None: + def __init__(self, msg: str, how: str, subproject: str) -> None: super().__init__(subproject) self.msg = msg + self.how = how def __exit__(self, exc_type, exc_val, exc_tb): if exc_val is None: raise InterpreterException('Expecting an error but code block succeeded') if isinstance(exc_val, mesonlib.MesonException): msg = str(exc_val) - if msg != self.msg: + if (self.how == 'literal' and self.msg != msg) or \ + (self.how == 're' and not re.match(self.msg, msg)): raise InterpreterException(f'Expecting error {self.msg!r} but got {msg!r}') return True - return ExpectErrorObject(args[0], self.subproject) + return ExpectErrorObject(args[0], kwargs['how'], self.subproject) def add_languages(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: success = self.add_languages_for(args, required, for_machine) From dd22546bdd5b7de34025437ae1360f6dd20491eb Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 24 Aug 2023 12:06:37 -0400 Subject: [PATCH 245/855] interpreter: Use common definition for sources type --- mesonbuild/interpreter/interpreter.py | 32 +++++++++++++------------ mesonbuild/interpreter/type_checking.py | 3 +++ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 10a6abc4715f..1c02c5fa16f8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -90,6 +90,7 @@ SHARED_LIB_KWS, SHARED_MOD_KWS, SOURCES_KW, + SOURCES_VARARGS, STATIC_LIB_KWS, VARIABLES_KW, TEST_KWS, @@ -121,6 +122,7 @@ from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs from ..programs import OverrideProgram + from .type_checking import SourcesVarargsType # Input source types passed to Targets SourceInputs = T.Union[mesonlib.File, build.GeneratedList, build.BuildTarget, build.BothLibraries, @@ -1820,58 +1822,58 @@ def func_disabler(self, node, args, kwargs): @FeatureNewKwargs('executable', '0.42.0', ['implib']) @permittedKwargs(build.known_exe_kwargs) - @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('executable', str, varargs=SOURCES_VARARGS) @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) def func_executable(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Executable) -> build.Executable: return self.build_target(node, args, kwargs, build.Executable) @permittedKwargs(build.known_stlib_kwargs) - @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('static_library', str, varargs=SOURCES_VARARGS) @typed_kwargs('static_library', *STATIC_LIB_KWS, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.StaticLibrary) -> build.StaticLibrary: return self.build_target(node, args, kwargs, build.StaticLibrary) @permittedKwargs(build.known_shlib_kwargs) - @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('shared_library', str, varargs=SOURCES_VARARGS) @typed_kwargs('shared_library', *SHARED_LIB_KWS, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.SharedLibrary) -> build.SharedLibrary: holder = self.build_target(node, args, kwargs, build.SharedLibrary) holder.shared_library_only = True return holder @permittedKwargs(known_library_kwargs) - @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('both_libraries', str, varargs=SOURCES_VARARGS) @typed_kwargs('both_libraries', *LIBRARY_KWS, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: return self.build_both_libraries(node, args, kwargs) @FeatureNew('shared_module', '0.37.0') @permittedKwargs(build.known_shmod_kwargs) - @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('shared_module', str, varargs=SOURCES_VARARGS) @typed_kwargs('shared_module', *SHARED_MOD_KWS, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.SharedModule) -> build.SharedModule: return self.build_target(node, args, kwargs, build.SharedModule) @permittedKwargs(known_library_kwargs) - @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('library', str, varargs=SOURCES_VARARGS) @typed_kwargs('library', *LIBRARY_KWS, allow_unknown=True) def func_library(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.Executable: return self.build_library(node, args, kwargs) @permittedKwargs(build.known_jar_kwargs) - @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('jar', str, varargs=SOURCES_VARARGS) @typed_kwargs('jar', *JAR_KWS, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], @@ -1880,10 +1882,10 @@ def func_jar(self, node: mparser.BaseNode, @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @permittedKwargs(known_build_target_kwargs) - @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('build_target', str, varargs=SOURCES_VARARGS) @typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.BuildTarget ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, build.SharedModule, build.BothLibraries, build.Jar]: diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 645b27363024..59dae9a0f0d2 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -30,6 +30,7 @@ _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] PkgConfigDefineType = T.Optional[T.Tuple[str, str]] + SourcesVarargsType = T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget]] def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]: @@ -464,6 +465,8 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus default=[], ) +SOURCES_VARARGS = (str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget) + VARIABLES_KW: KwargInfo[T.Dict[str, str]] = KwargInfo( 'variables', # str is listified by validator/convertor, cannot use listify=True here because From 8ccdb881374084ddb90ef259539cfd3bb748c904 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 9 Aug 2023 16:20:34 -0700 Subject: [PATCH 246/855] Rust: Add a rust.proc_macro() method --- docs/markdown/Rust-module.md | 29 +++++++++++++++++++++++ mesonbuild/modules/rust.py | 23 +++++++++++++++--- test cases/rust/18 proc-macro/meson.build | 13 ++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index bbc92fc2582c..0fb9edef748b 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -105,3 +105,32 @@ were never turned on by Meson. [properties] bindgen_clang_arguments = ['--target', 'x86_64-linux-gnu'] ``` + +### proc_macro() + +```meson +rustmod.proc_macro(name, sources, ...) +``` + +*Since 1.3.0* + +This function creates a Rust `proc-macro` crate, similar to: +```meson +[[shared_library]](name, sources, + rust_crate_type: 'proc-macro', + native: true) +``` + +`proc-macro` targets can be passed to `link_with` keyword argument of other Rust +targets. + +Only a subset of [[shared_library]] keyword arguments are allowed: +- rust_args +- rust_dependency_map +- sources +- dependencies +- extra_files +- link_args +- link_depends +- link_with +- override_options diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 0bda2c250bce..b6dd731491cc 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -15,13 +15,15 @@ import os import typing as T +from mesonbuild.interpreterbase.decorators import FeatureNew from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources +from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, + CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) from ..compilers.compilers import are_asserts_disabled -from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES -from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs +from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS +from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File if T.TYPE_CHECKING: @@ -32,6 +34,7 @@ from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs from ..programs import ExternalProgram, OverrideProgram + from ..interpreter.type_checking import SourcesVarargsType from typing_extensions import TypedDict @@ -64,6 +67,7 @@ def __init__(self, interpreter: Interpreter) -> None: self.methods.update({ 'test': self.test, 'bindgen': self.bindgen, + 'proc_macro': self.proc_macro, }) @typed_pos_args('rust.test', str, BuildTarget) @@ -268,6 +272,19 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu return ModuleReturnValue([target], [target]) + # Allow a limited set of kwargs, but still use the full set of typed_kwargs() + # because it could be setting required default values. + @FeatureNew('rust.proc_macro', '1.3.0') + @permittedKwargs({'rust_args', 'rust_dependency_map', 'sources', 'dependencies', 'extra_files', + 'link_args', 'link_depends', 'link_with', 'override_options'}) + @typed_pos_args('rust.proc_macro', str, varargs=SOURCES_VARARGS) + @typed_kwargs('rust.proc_macro', *SHARED_LIB_KWS, allow_unknown=True) + def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType], kwargs: T.Dict) -> SharedLibrary: + kwargs['native'] = True + kwargs['rust_crate_type'] = 'proc-macro' + target = state._interpreter.build_target(state.current_node, args, kwargs, SharedLibrary) + return T.cast('SharedLibrary', target) + def initialize(interp: Interpreter) -> RustModule: return RustModule(interp) diff --git a/test cases/rust/18 proc-macro/meson.build b/test cases/rust/18 proc-macro/meson.build index 2958df1af6c1..c5f0dfc82aee 100644 --- a/test cases/rust/18 proc-macro/meson.build +++ b/test cases/rust/18 proc-macro/meson.build @@ -18,3 +18,16 @@ main = executable( ) test('main_test', main) + +rust = import('rust') + +pm = rust.proc_macro('proc_macro_examples2', 'proc.rs') + +main = executable( + 'main2', + 'use.rs', + link_with : pm, + rust_dependency_map : {'proc_macro_examples2' : 'proc_macro_examples'} +) + +test('main_test2', main) From 10dcd87d002f6f36b1f60371dc807b8d9959d97b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 21 Apr 2023 16:21:48 -0400 Subject: [PATCH 247/855] Rust: Replace rust_crate_type with rust_abi Meson already knows if it's a shared or static library, user only need to specify the ABI (Rust or C). --- docs/markdown/snippets/rust_crate_type.md | 11 +++ docs/yaml/functions/_build_target_base.yaml | 5 ++ docs/yaml/functions/library.yaml | 11 +++ docs/yaml/functions/shared_library.yaml | 8 ++ docs/yaml/functions/shared_module.yaml | 8 ++ docs/yaml/functions/static_library.yaml | 8 ++ mesonbuild/backend/ninjabackend.py | 11 +-- mesonbuild/build.py | 78 +++++++++-------- mesonbuild/interpreter/type_checking.py | 25 ++++++ test cases/rust/4 polyglot/meson.build | 51 ++++++++++- test cases/rust/4 polyglot/proc.rs | 7 ++ test cases/rust/4 polyglot/stuff.rs | 2 - test cases/rust/4 polyglot/test.json | 94 +++++++++++++++++++-- 13 files changed, 263 insertions(+), 56 deletions(-) create mode 100644 docs/markdown/snippets/rust_crate_type.md create mode 100644 test cases/rust/4 polyglot/proc.rs diff --git a/docs/markdown/snippets/rust_crate_type.md b/docs/markdown/snippets/rust_crate_type.md new file mode 100644 index 000000000000..9b32f0ee86f2 --- /dev/null +++ b/docs/markdown/snippets/rust_crate_type.md @@ -0,0 +1,11 @@ +## Deprecated `rust_crate_type` and replaced by `rust_abi` + +The new `rust_abi` keyword argument is accepted by [[shared_library]], +[[static_library]], [[library]] and [[shared_module]] functions. It can be either +`'rust'` (the default) or `'c'` strings. + +`rust_crate_type` is now deprecated because Meson already knows if it's a shared +or static library, user only need to specify the ABI (Rust or C). + +`proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) +method. diff --git a/docs/yaml/functions/_build_target_base.yaml b/docs/yaml/functions/_build_target_base.yaml index 724b6a4ece12..3f0e88158c36 100644 --- a/docs/yaml/functions/_build_target_base.yaml +++ b/docs/yaml/functions/_build_target_base.yaml @@ -289,6 +289,7 @@ kwargs: rust_crate_type: type: str since: 0.42.0 + deprecated: 1.3.0 description: | Set the specific type of rust crate to compile (when compiling rust). @@ -306,6 +307,10 @@ kwargs: "proc-macro" is new in 0.62.0. + *Since 1.3.0* this is deprecated and replaced by "rust_abi" keyword argument. + `proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) + method. + rust_dependency_map: type: dict[str] since: 1.2.0 diff --git a/docs/yaml/functions/library.yaml b/docs/yaml/functions/library.yaml index f10ef8e88c84..f9e336b9b808 100644 --- a/docs/yaml/functions/library.yaml +++ b/docs/yaml/functions/library.yaml @@ -21,3 +21,14 @@ varargs_inherit: _build_target_base kwargs_inherit: - shared_library - static_library + +kwargs: + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "rlib" or "dylib" crate depending on the library + type being build. + - 'c': Create a "cdylib" or "staticlib" crate depending on the library + type being build. diff --git a/docs/yaml/functions/shared_library.yaml b/docs/yaml/functions/shared_library.yaml index 956fb2cb2ce1..5076b9341b2a 100644 --- a/docs/yaml/functions/shared_library.yaml +++ b/docs/yaml/functions/shared_library.yaml @@ -44,3 +44,11 @@ kwargs: description: | Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "dylib" crate. + - 'c': Create a "cdylib" crate. diff --git a/docs/yaml/functions/shared_module.yaml b/docs/yaml/functions/shared_module.yaml index 20bd5c48802c..46086ba3096d 100644 --- a/docs/yaml/functions/shared_module.yaml +++ b/docs/yaml/functions/shared_module.yaml @@ -39,3 +39,11 @@ kwargs: description: | Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "dylib" crate. + - 'c': Create a "cdylib" crate. diff --git a/docs/yaml/functions/static_library.yaml b/docs/yaml/functions/static_library.yaml index 1d42d600a4b6..615baa229976 100644 --- a/docs/yaml/functions/static_library.yaml +++ b/docs/yaml/functions/static_library.yaml @@ -23,3 +23,11 @@ kwargs: If `true` the object files in the target will be prelinked, meaning that it will contain only one prelinked object file rather than the individual object files. + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "rlib" crate. + - 'c': Create a "staticlib" crate. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 491f2a63d834..767baeaf4675 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1937,16 +1937,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: if main_rust_file is None: raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report') target_name = os.path.join(target.subdir, target.get_filename()) - if isinstance(target, build.Executable): - cratetype = 'bin' - elif hasattr(target, 'rust_crate_type'): - cratetype = target.rust_crate_type - elif isinstance(target, build.SharedLibrary): - cratetype = 'dylib' - elif isinstance(target, build.StaticLibrary): - cratetype = 'rlib' - else: - raise InvalidArguments('Unknown target type for rustc.') + cratetype = target.rust_crate_type args.extend(['--crate-type', cratetype]) # If we're dynamically linking, add those arguments diff --git a/mesonbuild/build.py b/mesonbuild/build.py index fece0bebc8e2..5820b5076dde 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -115,9 +115,9 @@ cs_kwargs) known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} -known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} -known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'} -known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'} +known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'} +known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'} +known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'} known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'} def _process_install_tag(install_tag: T.Optional[T.List[T.Optional[str]]], @@ -1980,6 +1980,13 @@ def post_init(self) -> None: if create_debug_file: self.debug_filename = self.name + '.pdb' + def process_kwargs(self, kwargs): + super().process_kwargs(kwargs) + + self.rust_crate_type = kwargs.get('rust_crate_type') or 'bin' + if self.rust_crate_type != 'bin': + raise InvalidArguments('Invalid rust_crate_type: must be "bin" for executables.') + def get_default_install_dir(self) -> T.Tuple[str, str]: return self.environment.get_bindir(), '{bindir}' @@ -2052,18 +2059,12 @@ def post_init(self) -> None: super().post_init() if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.') - if 'rust' in self.compilers: - # If no crate type is specified, or it's the generic lib type, use rlib - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': - mlog.debug('Defaulting Rust static library target crate type to rlib') - self.rust_crate_type = 'rlib' - # Don't let configuration proceed with a non-static crate type - elif self.rust_crate_type not in ['rlib', 'staticlib']: - raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"') + if self.uses_rust(): # See https://github.com/rust-lang/rust/issues/110460 if self.rust_crate_type == 'rlib' and any(c in self.name for c in ['-', ' ', '.']): - raise InvalidArguments('Rust crate type "rlib" does not allow spaces, periods or dashes in the library name ' - 'due to a limitation of rustc. Replace them with underscores, for example') + raise InvalidArguments(f'Rust crate {self.name} type {self.rust_crate_type} does not allow spaces, ' + 'periods or dashes in the library name due to a limitation of rustc. ' + 'Replace them with underscores, for example') if self.rust_crate_type == 'staticlib': # FIXME: In the case of no-std we should not add those libraries, # but we have no way to know currently. @@ -2085,8 +2086,8 @@ def post_init(self) -> None: if not hasattr(self, 'prefix'): self.prefix = 'lib' if not hasattr(self, 'suffix'): - if 'rust' in self.compilers: - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'rlib': + if self.uses_rust(): + if self.rust_crate_type == 'rlib': # default Rust static library suffix self.suffix = 'rlib' elif self.rust_crate_type == 'staticlib': @@ -2107,12 +2108,20 @@ def type_suffix(self): def process_kwargs(self, kwargs): super().process_kwargs(kwargs) - if 'rust_crate_type' in kwargs: - rust_crate_type = kwargs['rust_crate_type'] - if isinstance(rust_crate_type, str): + + rust_abi = kwargs.get('rust_abi') + rust_crate_type = kwargs.get('rust_crate_type') + if rust_crate_type: + if rust_abi: + raise InvalidArguments('rust_abi and rust_crate_type are mutually exclusive.') + if rust_crate_type == 'lib': + self.rust_crate_type = 'rlib' + elif rust_crate_type in {'rlib', 'staticlib'}: self.rust_crate_type = rust_crate_type else: - raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') + raise InvalidArguments(f'Crate type {rust_crate_type!r} invalid for static libraries; must be "rlib" or "staticlib"') + else: + self.rust_crate_type = 'staticlib' if rust_abi == 'c' else 'rlib' def is_linkable_target(self): return True @@ -2153,18 +2162,12 @@ def __init__( def post_init(self) -> None: super().post_init() - if 'rust' in self.compilers: - # If no crate type is specified, or it's the generic lib type, use dylib - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': - mlog.debug('Defaulting Rust dynamic library target crate type to "dylib"') - self.rust_crate_type = 'dylib' - # Don't let configuration proceed with a non-dynamic crate type - elif self.rust_crate_type not in ['dylib', 'cdylib', 'proc-macro']: - raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for dynamic libraries; must be "dylib", "cdylib", or "proc-macro"') + if self.uses_rust(): # See https://github.com/rust-lang/rust/issues/110460 if self.rust_crate_type != 'cdylib' and any(c in self.name for c in ['-', ' ', '.']): - raise InvalidArguments('Rust crate types "dylib" and "proc-macro" do not allow spaces, periods or dashes in the library name ' - 'due to a limitation of rustc. Replace them with underscores, for example') + raise InvalidArguments(f'Rust crate {self.name} type {self.rust_crate_type} does not allow spaces, ' + 'periods or dashes in the library name due to a limitation of rustc. ' + 'Replace them with underscores, for example') if not hasattr(self, 'prefix'): self.prefix = None @@ -2335,14 +2338,19 @@ def process_kwargs(self, kwargs): 'a file object or a Custom Target') self.process_link_depends(path) - if 'rust_crate_type' in kwargs: - rust_crate_type = kwargs['rust_crate_type'] - if isinstance(rust_crate_type, str): + rust_abi = kwargs.get('rust_abi') + rust_crate_type = kwargs.get('rust_crate_type') + if rust_crate_type: + if rust_abi: + raise InvalidArguments('rust_abi and rust_crate_type are mutually exclusive.') + if rust_crate_type == 'lib': + self.rust_crate_type = 'dylib' + elif rust_crate_type in {'dylib', 'cdylib', 'proc-macro'}: self.rust_crate_type = rust_crate_type else: - raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') - if rust_crate_type == 'proc-macro': - FeatureNew.single_use('Rust crate type "proc-macro"', '0.62.0', self.subproject) + raise InvalidArguments(f'Crate type {rust_crate_type!r} invalid for shared libraries; must be "dylib", "cdylib" or "proc-macro"') + else: + self.rust_crate_type = 'cdylib' if rust_abi == 'c' else 'dylib' def get_import_filename(self) -> T.Optional[str]: """ diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 59dae9a0f0d2..9a1904d57cb1 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -498,6 +498,21 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('verbose', bool, default=False, since='0.62.0'), ] +# Cannot have a default value because we need to check that rust_crate_type and +# rust_abi are mutually exclusive. +RUST_CRATE_TYPE_KW: KwargInfo[T.Union[str, None]] = KwargInfo( + 'rust_crate_type', (str, NoneType), + since='0.42.0', + since_values={'proc-macro': '0.62.0'}, + deprecated='1.3.0', + deprecated_message='Use rust_abi or rust.proc_macro() instead.', + validator=in_set_validator({'bin', 'lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro'})) + +RUST_ABI_KW: KwargInfo[T.Union[str, None]] = KwargInfo( + 'rust_abi', (str, NoneType), + since='1.3.0', + validator=in_set_validator({'rust', 'c'})) + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, @@ -506,6 +521,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, + RUST_CRATE_TYPE_KW, ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: @@ -575,6 +591,11 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_EXECUTABLE_KWS, ] +# Arguments exclusive to library types +_EXCLUSIVE_LIB_KWS: T.List[KwargInfo] = [ + RUST_ABI_KW, +] + # Arguments exclusive to StaticLibrary. These are separated to make integrating # them into build_target easier _EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [] @@ -583,6 +604,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup STATIC_LIB_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to SharedLibrary. These are separated to make integrating @@ -597,6 +619,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup SHARED_LIB_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_LIB_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to SharedModule. These are separated to make integrating @@ -607,6 +630,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup SHARED_MOD_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to JAR. These are separated to make integrating @@ -625,6 +649,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # Arguments used by both_library and library LIBRARY_KWS = [ *_BUILD_TARGET_KWS, + *_EXCLUSIVE_LIB_KWS, *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build index 3601d5ed84d5..60922fed1a63 100644 --- a/test cases/rust/4 polyglot/meson.build +++ b/test cases/rust/4 polyglot/meson.build @@ -4,6 +4,51 @@ if host_machine.system() == 'darwin' error('MESON_SKIP_TEST: does not work right on macos, please fix!') endif -l = shared_library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true) -e = executable('prog', 'prog.c', link_with : l, install : true) -test('polyglottest', e) +cc = meson.get_compiler('c') + +# Test all combinations of crate and target types. +# - 'clib' gets translated to `rust_abi: 'c'` instead. +# - '' gets translated to no kwargs. +allowed_map = { + 'static_library': ['rlib', 'staticlib', 'lib', 'clib', ''], + 'shared_library': ['dylib', 'cdylib', 'lib', 'proc-macro', 'clib', ''], + 'both_libraries': ['lib', 'clib', ''], +} +foreach crate_type : ['lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro', 'clib', '', 'invalid'] + foreach target_type, allowed : allowed_map + name = f'stuff_@crate_type@_@target_type@'.underscorify() + src = crate_type == 'proc-macro' ? 'proc.rs' : 'stuff.rs' + if crate_type not in allowed + # Note: in the both_libraries() case it is possible that the static part + # is still being built because the shared part raised an error but we + # don't rollback correctly. + testcase expect_error('(Crate type .* invalid for .*)|(.*must be one of.*not invalid)', how: 're') + build_target(name, src, + target_type: target_type, + rust_crate_type: crate_type, + install: true) + endtestcase + continue + endif + rust_kwargs = {} + if crate_type == 'clib' + rust_kwargs = {'rust_abi': 'c'} + elif crate_type != '' + rust_kwargs = {'rust_crate_type': crate_type} + endif + l = build_target(name, src, + target_type: target_type, + kwargs: rust_kwargs, + install: true) + if crate_type in ['cdylib', 'staticlib', 'clib'] + e = executable(f'prog-@name@', 'prog.c', + link_with: l, + rust_dependency_map: {name: 'stuff'}, + install: true) + test(f'polyglottest-@name@', e) + else + # FIXME: Verify that linking Rust ABI with C ABI executable raises an error. + # Currently it only fails at build time. + endif + endforeach +endforeach diff --git a/test cases/rust/4 polyglot/proc.rs b/test cases/rust/4 polyglot/proc.rs new file mode 100644 index 000000000000..53935e45d17f --- /dev/null +++ b/test cases/rust/4 polyglot/proc.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} diff --git a/test cases/rust/4 polyglot/stuff.rs b/test cases/rust/4 polyglot/stuff.rs index ecf623c644e1..30c3a3624783 100644 --- a/test cases/rust/4 polyglot/stuff.rs +++ b/test cases/rust/4 polyglot/stuff.rs @@ -1,5 +1,3 @@ -#![crate_name = "stuff"] - #[no_mangle] pub extern fn f() { println!("Hello from Rust!"); diff --git a/test cases/rust/4 polyglot/test.json b/test cases/rust/4 polyglot/test.json index a8837a195f78..d963ad84064c 100644 --- a/test cases/rust/4 polyglot/test.json +++ b/test cases/rust/4 polyglot/test.json @@ -1,10 +1,92 @@ { "installed": [ - {"type": "exe", "file": "usr/bin/prog"}, - {"type": "pdb", "file": "usr/bin/prog"}, - {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"}, - {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"}, - {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.dll.lib"}, - {"type": "pdb", "file": "usr/bin/stuff"} + {"type": "exe", "file": "usr/bin/prog-stuff_clib_both_libraries"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_both_libraries"}, + {"type": "pdb", "file": "usr/bin/stuff_clib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_clib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_clib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_clib_both_libraries.dll.lib"}, + {"type": "file", "file": "usr/lib/libstuff_clib_both_libraries.a"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_clib_shared_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_shared_library"}, + {"type": "pdb", "file": "usr/bin/stuff_clib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_clib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_clib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_clib_shared_library.dll.lib"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_clib_static_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_static_library"}, + {"type": "file", "file": "usr/lib/libstuff_clib_static_library.a"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_cdylib_shared_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_cdylib_shared_library"}, + {"type": "pdb", "file": "usr/bin/stuff_cdylib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_cdylib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_cdylib_shared_library.dll.lib"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_staticlib_static_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_staticlib_static_library"}, + {"type": "file", "file": "usr/lib/libstuff_staticlib_static_library.a"}, + + {"type": "pdb", "file": "usr/bin/stuff__both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__both_libraries.so"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff__both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff__both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff__both_libraries.dll.lib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff__static_library.rlib"}, + + {"type": "pdb", "file": "usr/bin/stuff_proc_macro_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_proc_macro_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_proc_macro_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_proc_macro_shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_lib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_both_libraries.rlib"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_lib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_lib_both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_lib_both_libraries.dll.lib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_rlib_static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_rlib_static_library.rlib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_lib_static_library.rlib"}, + + {"type": "pdb", "file": "usr/bin/stuff__shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff__shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff__shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_lib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_lib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_lib_shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_dylib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_dylib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_dylib_shared_library.dll.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_dylib_shared_library.dll"}, + + {"type": "pdb", "file": "usr/bin/stuff_cdylib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_both_libraries.so"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_cdylib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_cdylib_both_libraries.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_proc_macro_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_proc_macro_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_proc_macro_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_proc_macro_both_libraries.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_dylib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_dylib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_dylib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_dylib_both_libraries.dll.lib"} ] } From bdf1f3c0e2a772a81fd6a19ec1a2f495948406fc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 23 Aug 2023 16:05:58 -0400 Subject: [PATCH 248/855] Rust: Remove unit test already covered in "rust/4 polyglot" --- test cases/failing/53 wrong shared crate type/foo.rs | 0 test cases/failing/53 wrong shared crate type/meson.build | 7 ------- test cases/failing/53 wrong shared crate type/test.json | 7 ------- test cases/failing/54 wrong static crate type/foo.rs | 0 test cases/failing/54 wrong static crate type/meson.build | 7 ------- test cases/failing/54 wrong static crate type/test.json | 7 ------- 6 files changed, 28 deletions(-) delete mode 100644 test cases/failing/53 wrong shared crate type/foo.rs delete mode 100644 test cases/failing/53 wrong shared crate type/meson.build delete mode 100644 test cases/failing/53 wrong shared crate type/test.json delete mode 100644 test cases/failing/54 wrong static crate type/foo.rs delete mode 100644 test cases/failing/54 wrong static crate type/meson.build delete mode 100644 test cases/failing/54 wrong static crate type/test.json diff --git a/test cases/failing/53 wrong shared crate type/foo.rs b/test cases/failing/53 wrong shared crate type/foo.rs deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test cases/failing/53 wrong shared crate type/meson.build b/test cases/failing/53 wrong shared crate type/meson.build deleted file mode 100644 index 90020faf854b..000000000000 --- a/test cases/failing/53 wrong shared crate type/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -project('test') - -if not add_languages('rust', required: false) - error('MESON_SKIP_TEST test requires rust compiler') -endif - -shared_library('mytest', 'foo.rs', rust_crate_type : 'staticlib') diff --git a/test cases/failing/53 wrong shared crate type/test.json b/test cases/failing/53 wrong shared crate type/test.json deleted file mode 100644 index 5faaece2b664..000000000000 --- a/test cases/failing/53 wrong shared crate type/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/53 wrong shared crate type/meson.build:7:0: ERROR: Crate type \"staticlib\" invalid for dynamic libraries; must be \"dylib\", \"cdylib\", or \"proc-macro\"" - } - ] -} diff --git a/test cases/failing/54 wrong static crate type/foo.rs b/test cases/failing/54 wrong static crate type/foo.rs deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test cases/failing/54 wrong static crate type/meson.build b/test cases/failing/54 wrong static crate type/meson.build deleted file mode 100644 index 179d7cd5365f..000000000000 --- a/test cases/failing/54 wrong static crate type/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -project('test') - -if not add_languages('rust', required: false) - error('MESON_SKIP_TEST test requires rust compiler') -endif - -static_library('mytest', 'foo.rs', rust_crate_type : 'cdylib') diff --git a/test cases/failing/54 wrong static crate type/test.json b/test cases/failing/54 wrong static crate type/test.json deleted file mode 100644 index 83ae5e1b60bb..000000000000 --- a/test cases/failing/54 wrong static crate type/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/54 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\" or \"staticlib\"" - } - ] -} From 759200348476752b304ffca0cb3737a5b61f9137 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 23 Aug 2023 16:03:10 -0400 Subject: [PATCH 249/855] Rust: Prevent linking Rust ABI with C library/executable --- mesonbuild/build.py | 28 +++++++++++++++----------- test cases/rust/4 polyglot/meson.build | 5 +++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 5820b5076dde..9a87225dd434 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1408,12 +1408,7 @@ def link(self, targets): msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if self.for_machine is not t.for_machine: - msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' - if self.environment.is_cross_build(): - raise InvalidArguments(msg + ' This is not possible in a cross build.') - else: - mlog.warning(msg + ' This will fail in cross build.') + self.check_can_link_together(t) self.link_targets.append(t) def link_whole(self, targets, promoted: bool = False): @@ -1429,12 +1424,7 @@ def link_whole(self, targets, promoted: bool = False): msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if self.for_machine is not t.for_machine: - msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' - if self.environment.is_cross_build(): - raise InvalidArguments(msg + ' This is not possible in a cross build.') - else: - mlog.warning(msg + ' This will fail in cross build.') + self.check_can_link_together(t) if isinstance(self, StaticLibrary) and not self.uses_rust(): # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. @@ -1480,6 +1470,17 @@ def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origi f' and thus has to include objects from {t.name!r} to be usable.') raise InvalidArguments(m) + def check_can_link_together(self, t: BuildTargetTypes) -> None: + links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() + if not self.uses_rust() and links_with_rust_abi: + raise InvalidArguments(f'Try to link Rust ABI library {t.name!r} with a non-Rust target {self.name!r}') + if self.for_machine is not t.for_machine: + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') + def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: return @@ -1645,6 +1646,9 @@ def get_used_stdlib_args(self, link_language: str) -> T.List[str]: def uses_rust(self) -> bool: return 'rust' in self.compilers + def uses_rust_abi(self) -> bool: + return self.uses_rust() and self.rust_crate_type in {'dylib', 'rlib', 'proc-macro'} + def uses_fortran(self) -> bool: return 'fortran' in self.compilers diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build index 60922fed1a63..b2fd8f913a61 100644 --- a/test cases/rust/4 polyglot/meson.build +++ b/test cases/rust/4 polyglot/meson.build @@ -47,8 +47,9 @@ foreach crate_type : ['lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro install: true) test(f'polyglottest-@name@', e) else - # FIXME: Verify that linking Rust ABI with C ABI executable raises an error. - # Currently it only fails at build time. + testcase expect_error('Try to link Rust ABI library .*', how: 're') + executable(f'prog-@name@', 'prog.c', link_with: l) + endtestcase endif endforeach endforeach From c6f33aed2d1da362e35340c2623ffc76624d3903 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 24 Aug 2023 12:11:28 -0400 Subject: [PATCH 250/855] Rust: Fix proc-macro usage when cross compiling Force BUILD machine and allow to link with HOST machine. --- mesonbuild/build.py | 2 +- mesonbuild/interpreter/interpreter.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 9a87225dd434..c58447b55db8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1474,7 +1474,7 @@ def check_can_link_together(self, t: BuildTargetTypes) -> None: links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() if not self.uses_rust() and links_with_rust_abi: raise InvalidArguments(f'Try to link Rust ABI library {t.name!r} with a non-Rust target {self.name!r}') - if self.for_machine is not t.for_machine: + if self.for_machine is not t.for_machine and (not links_with_rust_abi or t.rust_crate_type != 'proc-macro'): msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' if self.environment.is_cross_build(): raise InvalidArguments(msg + ' This is not possible in a cross build.') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 1c02c5fa16f8..464ebea28020 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3247,6 +3247,10 @@ def build_target_decorator_caller(self, node, args, kwargs): name, sources = args for_machine = self.machine_from_native_kwarg(kwargs) + if kwargs.get('rust_crate_type') == 'proc-macro': + # Silently force to native because that's the only sensible value + # and rust_crate_type is deprecated any way. + for_machine = MachineChoice.BUILD if 'sources' in kwargs: sources += listify(kwargs['sources']) if any(isinstance(s, build.BuildTarget) for s in sources): From 7321f01678d6dc286a4616a843f835cb6b949520 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 23 Aug 2023 14:52:41 -0400 Subject: [PATCH 251/855] Rust: Use Popen_safe_logged in sanity checks --- mesonbuild/compilers/rust.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index d722039d1ba2..b5e6a6a0c5a7 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -18,8 +18,8 @@ import re import typing as T -from .. import coredata, mlog -from ..mesonlib import EnvironmentException, MesonException, Popen_safe, OptionKey, join_args +from .. import coredata +from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged, OptionKey from .compilers import Compiler, rust_buildtype_args, clike_debug_args if T.TYPE_CHECKING: @@ -82,13 +82,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: ''')) cmdlist = self.exelist + ['-o', output_name, source_name] - pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) - mlog.debug('Sanity check compiler command line:', join_args(cmdlist)) - mlog.debug('Sanity check compile stdout:') - mlog.debug(stdo) - mlog.debug('-----\nSanity check compile stderr:') - mlog.debug(stde) - mlog.debug('-----') + pc, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) if pc.returncode != 0: raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.') if self.is_cross: @@ -104,7 +98,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.') # Get libraries needed to link with a Rust staticlib cmdlist = self.exelist + ['--crate-type', 'staticlib', '--print', 'native-static-libs', source_name] - p, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) + p, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) if p.returncode == 0: match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE) if match: @@ -123,7 +117,7 @@ def get_buildtype_args(self, buildtype: str) -> T.List[str]: def get_sysroot(self) -> str: cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot'] - p, stdo, stde = Popen_safe(cmd) + p, stdo, stde = Popen_safe_logged(cmd) return stdo.split('\n', maxsplit=1)[0] def get_debug_args(self, is_debug: bool) -> T.List[str]: From dbf081c9ce7c145908d96eb9fa664b8b5b1f5896 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 22 Apr 2023 09:13:44 -0400 Subject: [PATCH 252/855] Rust: Fix both_libraries() case Rustc does not produce object files we can reuse to build both libraries. Ideally this should be done with a single target that has both `--crate-type` arguments instead of having 2 different build rules. As temporary workaround, build twice and ensure they don't get conflicts in intermediary files created by rustc by passing target's private directory as --out-dir. See https://github.com/rust-lang/rust/issues/111083. --- mesonbuild/backend/ninjabackend.py | 5 ++--- mesonbuild/interpreter/interpreter.py | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 767baeaf4675..3d3eefdcc733 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1951,10 +1951,9 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] depfile = os.path.join(target.subdir, target.name + '.d') - args += ['--emit', f'dep-info={depfile}', '--emit', 'link'] + args += ['--emit', f'dep-info={depfile}', '--emit', f'link={target_name}'] + args += ['--out-dir', self.get_target_private_dir(target)] args += target.get_extra_args('rust') - output = rustc.get_output_args(os.path.join(target.subdir, target.get_filename())) - args += output linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 464ebea28020..a5c8a5a2d4aa 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3206,6 +3206,10 @@ def build_both_libraries(self, node, args, kwargs): # Feel free to submit patches to get this fixed if it is an # issue for you. reuse_object_files = False + elif shared_lib.uses_rust(): + # FIXME: rustc supports generating both libraries in a single invocation, + # but for now compile twice. + reuse_object_files = False else: reuse_object_files = static_lib.pic From 74407670e1a4fb12605e17806b53c42b0559b343 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Tue, 19 Sep 2023 12:26:58 +0200 Subject: [PATCH 253/855] docs: fix `add_project_link_arguments` documentation It should refer to `add_project_arguments`, not `add_global_arguments`. --- docs/yaml/functions/add_project_link_arguments.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yaml/functions/add_project_link_arguments.yaml b/docs/yaml/functions/add_project_link_arguments.yaml index 8ae4763065a4..e259b6ccf365 100644 --- a/docs/yaml/functions/add_project_link_arguments.yaml +++ b/docs/yaml/functions/add_project_link_arguments.yaml @@ -1,9 +1,9 @@ name: add_project_link_arguments returns: void description: | - Adds global arguments to the linker command line. + Adds project specific arguments to the linker command line. - Like [[add_global_arguments]] but the arguments are passed to the linker. + Like [[add_project_arguments]] but the arguments are passed to the linker. notes: - You must pass always arguments individually `arg1, arg2, ...` @@ -14,4 +14,4 @@ varargs: name: Linker argument description: The linker arguments to add -kwargs_inherit: add_global_arguments +kwargs_inherit: add_project_arguments From 54950544c2a3e36a827144c82df5dbbc5c51c6c3 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Tue, 20 Jun 2023 14:35:29 -0700 Subject: [PATCH 254/855] objective-c++: add support for current supported standards in Apple Clang Pulled from this list on Xcode 15 beta: $ clang -E -dM -xobjective-c++ -std=arglbargle -o - /dev/null error: invalid value 'arglbargle' in '-std=arglbargle' note: use 'c++98' or 'c++03' for 'ISO C++ 1998 with amendments' standard note: use 'gnu++98' or 'gnu++03' for 'ISO C++ 1998 with amendments and GNU extensions' standard note: use 'c++11' for 'ISO C++ 2011 with amendments' standard note: use 'gnu++11' for 'ISO C++ 2011 with amendments and GNU extensions' standard note: use 'c++14' for 'ISO C++ 2014 with amendments' standard note: use 'gnu++14' for 'ISO C++ 2014 with amendments and GNU extensions' standard note: use 'c++17' for 'ISO C++ 2017 with amendments' standard note: use 'gnu++17' for 'ISO C++ 2017 with amendments and GNU extensions' standard note: use 'c++20' for 'ISO C++ 2020 DIS' standard note: use 'gnu++20' for 'ISO C++ 2020 DIS with GNU extensions' standard note: use 'c++2b' for 'Working draft for ISO C++ 2023 DIS' standard note: use 'gnu++2b' for 'Working draft for ISO C++ 2023 DIS with GNU extensions' standard Signed-off-by: Steven Noonan --- mesonbuild/compilers/objcpp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 530bc7cb63cb..2297196f8f53 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -96,7 +96,9 @@ def get_options(self) -> 'coredata.MutableKeyedOptionDictType': opts.update({ OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption( 'C++ language standard to use', - ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17'], + ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b', + 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20', + 'gnu++2b'], 'none', ) }) From fa7c7d919a8dbac8f09ef7a043e23116d655033d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 21 Sep 2023 20:45:22 -0700 Subject: [PATCH 255/855] rust: properly rematerialize static dependencies as well as dynamic ones Rustc expects to be provided both a search path `-L`, and a link arg `-l kind=libname`, but we don't handle that correctly. Because we combine -L and -l arguments from pkg-config the backend must rematerialize the -L and -l split. We currently don't do this for static archives. --- 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 3d3eefdcc733..a57b249fe45d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2090,13 +2090,14 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: if a in rustc.native_static_libs: # Exclude link args that rustc already add by default continue - if a.endswith(('.dll', '.so', '.dylib')): + if a.endswith(('.dll', '.so', '.dylib', '.a', '.lib')): dir_, lib = os.path.split(a) linkdirs.add(dir_) lib, ext = os.path.splitext(lib) if lib.startswith('lib'): lib = lib[3:] - args.extend(['-l', f'dylib={lib}']) + _type = 'static' if a.endswith(('.a', '.lib')) else 'dylib' + args.extend(['-l', f'{_type}={lib}']) elif a.startswith('-L'): args.append(a) elif a.startswith('-l'): From ded5bd77ad4cf078506ec3ed38278cd5d69d510a Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Mar 2023 15:51:48 -0700 Subject: [PATCH 256/855] ZlibSystemDependency: pass libtype to clib_compiler.find_library Makes it stop reporting that it found a static zlib on Solaris which does not ship a static library file for libz, and thus allows "test cases/rust/13 external c dependencies" to pass. Fixes #10906 --- mesonbuild/dependencies/dev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index ec7015103b7a..09f55b705d42 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -536,7 +536,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. else: libs = ['z'] for lib in libs: - l = self.clib_compiler.find_library(lib, environment, []) + l = self.clib_compiler.find_library(lib, environment, [], self.libtype) h = self.clib_compiler.has_header('zlib.h', '', environment, dependencies=[self]) if l and h[0]: self.is_found = True From c0da998afa7466d58c12d8a54baf09d09ae3225e Mon Sep 17 00:00:00 2001 From: "Kunwu.Chan" Date: Fri, 22 Sep 2023 23:33:19 +0800 Subject: [PATCH 257/855] CPU family support 'sw_64' and remove the compile warning (#12273) add sw_64 to the list of known cpus --- docs/markdown/Reference-tables.md | 2 ++ mesonbuild/envconfig.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index a21b40b2d0d9..86f3e9ea5668 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -128,11 +128,13 @@ set in the cross file. | sh4 | SuperH SH-4 | | sparc | 32 bit SPARC | | sparc64 | SPARC v9 processor | +| sw_64 | 64 bit sunway processor | | wasm32 | 32 bit Webassembly | | wasm64 | 64 bit Webassembly | | x86 | 32 bit x86 processor | | x86_64 | 64 bit x86 processor | + Any cpu family not listed in the above list is not guaranteed to remain stable in future releases. diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index c6b543a3421c..5621b99feff8 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -68,6 +68,7 @@ 'sh4', 'sparc', 'sparc64', + 'sw_64', 'wasm32', 'wasm64', 'x86', @@ -86,6 +87,7 @@ 'riscv64', 's390x', 'sparc64', + 'sw_64', 'wasm64', 'x86_64', ] From 49e7e3b9ccba7f9b0a135188f892b37d4e52cafc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 24 Apr 2023 22:42:09 -0400 Subject: [PATCH 258/855] Allow to fallback to cmake subproject The method can be overridden by setting the `method` key in the wrap file and always defaults to 'meson'. cmake.subproject() is still needed in case specific cmake options need to be passed. This also makes it easier to extend to other methods in the future e.g. cargo. --- .../markdown/Wrap-dependency-system-manual.md | 24 +++++++++++ docs/markdown/snippets/wrap.md | 12 ++++++ mesonbuild/interpreter/dependencyfallbacks.py | 2 +- mesonbuild/interpreter/interpreter.py | 14 +++---- mesonbuild/modules/cmake.py | 2 +- mesonbuild/msubprojects.py | 6 +-- mesonbuild/wrap/wrap.py | 40 ++++++++++++------- .../cmake/26 dependency fallback/main.cpp | 10 +++++ .../cmake/26 dependency fallback/meson.build | 30 ++++++++++++++ .../subprojects/broken_method.wrap | 2 + .../subprojects/cmMod.wrap | 5 +++ .../subprojects/cmMod/CMakeLists.txt | 20 ++++++++++ .../subprojects/cmMod/cmMod.cpp | 15 +++++++ .../subprojects/cmMod/cmMod.hpp | 18 +++++++++ .../subprojects/cmMod/cpp_pch.hpp | 2 + .../subprojects/cmake_subp/CMakeLists.txt | 2 + .../subprojects/force_cmake.wrap | 2 + .../subprojects/force_cmake/CMakeLists.txt | 2 + .../subprojects/force_cmake/meson.build | 4 ++ .../subprojects/meson_method.wrap | 2 + .../subprojects/meson_subp/meson.build | 1 + 21 files changed, 188 insertions(+), 27 deletions(-) create mode 100644 docs/markdown/snippets/wrap.md create mode 100644 test cases/cmake/26 dependency fallback/main.cpp create mode 100644 test cases/cmake/26 dependency fallback/meson.build create mode 100644 test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp create mode 100644 test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt create mode 100644 test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap create mode 100644 test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt create mode 100644 test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build create mode 100644 test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap create mode 100644 test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index 3aeea144afd7..9000c40c7c16 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -87,6 +87,10 @@ previously reserved to `wrap-file`: `subprojects/packagefiles`. - `diff_files` - *Since 0.63.0* Comma-separated list of local diff files (see [Diff files](#diff-files) below). +- `method` - *Since 1.3.0* The build system used by this subproject. Defaults to `meson`. + Supported methods: + - `meson` requires `meson.build` file. + - `cmake` requires `CMakeLists.txt` file. [See details](#cmake-wraps). ### Specific to wrap-file - `source_url` - download url to retrieve the wrap-file source archive @@ -290,6 +294,26 @@ With such wrap file, `find_program('myprog')` will automatically fallback to use the subproject, assuming it uses `meson.override_find_program('myprog')`. +### CMake wraps + +Since the CMake module does not know the public name of the provided +dependencies, a CMake `.wrap` file cannot use the `dependency_names = foo` +syntax. Instead, the `dep_name = _dep` syntax should be used, where +`` is the name of a CMake library with all non alphanumeric +characters replaced by underscores `_`. + +For example, a CMake project that contains `add_library(foo-bar ...)` in its +`CMakeList.txt` and that applications would usually find using the dependency +name `foo-bar-1.0` (e.g. via pkg-config) would have a wrap file like this: + +```ini +[wrap-file] +... +method = cmake +[provide] +foo-bar-1.0 = foo_bar_dep +``` + ## Using wrapped projects Wraps provide a convenient way of obtaining a project into your diff --git a/docs/markdown/snippets/wrap.md b/docs/markdown/snippets/wrap.md new file mode 100644 index 000000000000..6e03c2e13ffa --- /dev/null +++ b/docs/markdown/snippets/wrap.md @@ -0,0 +1,12 @@ +## Automatic fallback to `cmake` subproject + +CMake subprojects have been supported for a while using the `cmake.subproject()` +module method. However until now it was not possible to use a CMake subproject +as fallback in a `dependency()` call. + +A wrap file can now specify the method used to build it by setting the `method` +key in the wrap file's first section. The method defaults to `meson`. + +Supported methods: +- `meson` requires `meson.build` file. +- `cmake` requires `CMakeLists.txt` file. [See details](Wrap-dependency-system-manual.md#cmake-wraps). diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index 7ef152796c1c..eca6a2c71796 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -127,7 +127,7 @@ def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs func_kwargs.setdefault('version', []) if 'default_options' in kwargs and isinstance(kwargs['default_options'], str): func_kwargs['default_options'] = listify(kwargs['default_options']) - self.interpreter.do_subproject(subp_name, 'meson', func_kwargs) + self.interpreter.do_subproject(subp_name, func_kwargs) return self._get_subproject_dep(subp_name, varname, kwargs) def _get_subproject(self, subp_name: str) -> T.Optional[SubprojectHolder]: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index a5c8a5a2d4aa..e0c17e6ee26a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -116,8 +116,6 @@ if T.TYPE_CHECKING: import argparse - from typing_extensions import Literal - from . import kwargs as kwtypes from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs @@ -868,7 +866,7 @@ def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: k 'options': None, 'cmake_options': [], } - return self.do_subproject(args[0], 'meson', kw) + return self.do_subproject(args[0], kw) def disabled_subproject(self, subp_name: str, disabled_feature: T.Optional[str] = None, exception: T.Optional[Exception] = None) -> SubprojectHolder: @@ -877,7 +875,7 @@ def disabled_subproject(self, subp_name: str, disabled_feature: T.Optional[str] self.subprojects[subp_name] = sub return sub - def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwargs: kwtypes.DoSubproject) -> SubprojectHolder: + def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None) -> SubprojectHolder: disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') @@ -913,7 +911,7 @@ def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwarg r = self.environment.wrap_resolver try: - subdir = r.resolve(subp_name, method) + subdir, method = r.resolve(subp_name, force_method) except wrap.WrapException as e: if not required: mlog.log(e) @@ -1009,8 +1007,8 @@ def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, prefix = self.coredata.options[OptionKey('prefix')].value from ..modules.cmake import CMakeSubprojectOptions - options = kwargs['options'] or CMakeSubprojectOptions() - cmake_options = kwargs['cmake_options'] + options.cmake_options + options = kwargs.get('options') or CMakeSubprojectOptions() + cmake_options = kwargs.get('cmake_options', []) + options.cmake_options cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend) cm_int.initialise(cmake_options) cm_int.analyse() @@ -1734,7 +1732,7 @@ def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrStrin 'cmake_options': [], 'options': None, } - self.do_subproject(fallback, 'meson', sp_kwargs) + self.do_subproject(fallback, sp_kwargs) return self.program_from_overrides(args, extra_info) @typed_pos_args('find_program', varargs=(str, mesonlib.File), min_varargs=1) diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index bec1b2a30a0b..ee4e844d10c0 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -435,7 +435,7 @@ def subproject(self, state: ModuleState, args: T.Tuple[str], kwargs_: Subproject 'default_options': {}, 'version': [], } - subp = self.interpreter.do_subproject(dirname, 'cmake', kw) + subp = self.interpreter.do_subproject(dirname, kw, force_method='cmake') if not subp.found(): return subp return CMakeSubproject(subp) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 64a09b01720f..45b711d13140 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -189,7 +189,7 @@ def update_file(self) -> bool: # cached. windows_proof_rmtree(self.repo_dir) try: - self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.wrap_resolver.resolve(self.wrap.name) self.log(' -> New version extracted') return True except WrapException as e: @@ -292,7 +292,7 @@ def update_git(self) -> bool: # Delete existing directory and redownload windows_proof_rmtree(self.repo_dir) try: - self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.wrap_resolver.resolve(self.wrap.name) self.update_git_done() return True except WrapException as e: @@ -464,7 +464,7 @@ def download(self) -> bool: self.log(' -> Already downloaded') return True try: - self.wrap_resolver.resolve(self.wrap.name, 'meson') + self.wrap_resolver.resolve(self.wrap.name) self.log(' -> done') except WrapException as e: self.log(' ->', mlog.red(str(e))) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index c0f0f0728c06..a1bf72511363 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -45,6 +45,9 @@ if T.TYPE_CHECKING: import http.client + from typing_extensions import Literal + + Method = Literal['meson', 'cmake'] try: # Importing is just done to check if SSL exists, so all warnings @@ -406,7 +409,7 @@ def find_program_provider(self, names: T.List[str]) -> T.Optional[str]: return wrap_name return None - def resolve(self, packagename: str, method: str) -> str: + def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> T.Tuple[str, Method]: self.packagename = packagename self.directory = packagename self.wrap = self.wraps.get(packagename) @@ -443,17 +446,28 @@ def resolve(self, packagename: str, method: str) -> str: self.dirname = self.wrap.filename rel_path = os.path.relpath(self.dirname, self.source_dir) - if method == 'meson': - buildfile = os.path.join(self.dirname, 'meson.build') - elif method == 'cmake': - buildfile = os.path.join(self.dirname, 'CMakeLists.txt') - else: - raise WrapException('Only the methods "meson" and "cmake" are supported') + # Map each supported method to a file that must exist at the root of source tree. + methods_map: T.Dict[Method, str] = { + 'meson': 'meson.build', + 'cmake': 'CMakeLists.txt', + } + + # Check if this wrap forces a specific method, use meson otherwise. + method = T.cast('T.Optional[Method]', self.wrap.values.get('method', force_method)) + if method and method not in methods_map: + allowed_methods = ', '.join(methods_map.keys()) + raise WrapException(f'Wrap method {method!r} is not supported, must be one of: {allowed_methods}') + if force_method and method != force_method: + raise WrapException(f'Wrap method is {method!r} but we are trying to configure it with {force_method}') + method = method or 'meson' + + def has_buildfile() -> bool: + return os.path.exists(os.path.join(self.dirname, methods_map[method])) # The directory is there and has meson.build? Great, use it. - if os.path.exists(buildfile): + if has_buildfile(): self.validate() - return rel_path + return rel_path, method # Check if the subproject is a git submodule self.resolve_git_submodule() @@ -491,16 +505,14 @@ def resolve(self, packagename: str, method: str) -> str: windows_proof_rmtree(self.dirname) raise - # A meson.build or CMakeLists.txt file is required in the directory - if not os.path.exists(buildfile): - raise WrapException(f'Subproject exists but has no {os.path.basename(buildfile)} file') + if not has_buildfile(): + raise WrapException(f'Subproject exists but has no {methods_map[method]} file.') # At this point, the subproject has been successfully resolved for the # first time so save off the hash of the entire wrap file for future # reference. self.wrap.update_hash_cache(self.dirname) - - return rel_path + return rel_path, method def check_can_download(self) -> None: # Don't download subproject data based on wrap file if requested. diff --git a/test cases/cmake/26 dependency fallback/main.cpp b/test cases/cmake/26 dependency fallback/main.cpp new file mode 100644 index 000000000000..95079615ab06 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/main.cpp @@ -0,0 +1,10 @@ +#include +#include + +using namespace std; + +int main(void) { + cmModClass obj("Hello"); + cout << obj.getStr() << endl; + return 0; +} diff --git a/test cases/cmake/26 dependency fallback/meson.build b/test cases/cmake/26 dependency fallback/meson.build new file mode 100644 index 000000000000..b36aaac58e37 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/meson.build @@ -0,0 +1,30 @@ +project('cmakeSubTest', ['c', 'cpp']) + +# Fallback to a CMake subproject +sub_dep = dependency('cmModLib++') +exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep]) +test('test1', exe1) + +# Subproject contains both meson.build and CMakeLists.txt. It should default +# to meson but wrap force cmake. +subproject('force_cmake') + +testcase expect_error('Wrap method \'notfound\' is not supported, must be one of: meson, cmake') + subproject('broken_method') +endtestcase + +# With method=meson we can't use cmake.subproject() +cmake = import('cmake') +testcase expect_error('Wrap method is \'meson\' but we are trying to configure it with cmake') + cmake.subproject('meson_method') +endtestcase + +# cmake.subproject() force cmake method even if meson.build exists. +testcase expect_error('Subproject exists but has no CMakeLists.txt file.') + cmake.subproject('meson_subp') +endtestcase + +# Without specifying the method it defaults to meson even if CMakeLists.txt exists. +testcase expect_error('Subproject exists but has no meson.build file.') + subproject('cmake_subp') +endtestcase diff --git a/test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap b/test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap new file mode 100644 index 000000000000..ce0690a51286 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap @@ -0,0 +1,2 @@ +[wrap-file] +method=notfound diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap b/test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap new file mode 100644 index 000000000000..9e6d855f0446 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap @@ -0,0 +1,5 @@ +[wrap-file] +method = cmake + +[provide] +cmModLib++ = cmModLib___dep diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt new file mode 100644 index 000000000000..d08e55cdf4ac --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.5) + +project(cmMod) +set(CMAKE_CXX_STANDARD 14) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_definitions("-DDO_NOTHING_JUST_A_FLAG=1") + +add_library(cmModLib++ SHARED cmMod.cpp) +target_compile_definitions(cmModLib++ PRIVATE MESON_MAGIC_FLAG=21) +target_compile_definitions(cmModLib++ INTERFACE MESON_MAGIC_FLAG=42) + +# Test PCH support +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0") + target_precompile_headers(cmModLib++ PRIVATE "cpp_pch.hpp") +endif() + +include(GenerateExportHeader) +generate_export_header(cmModLib++) diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp new file mode 100644 index 000000000000..f4cbea0ce0dd --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp @@ -0,0 +1,15 @@ +#include "cmMod.hpp" + +using namespace std; + +#if MESON_MAGIC_FLAG != 21 +#error "Invalid MESON_MAGIC_FLAG (private)" +#endif + +cmModClass::cmModClass(string foo) { + str = foo + " World"; +} + +string cmModClass::getStr() const { + return str; +} diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp new file mode 100644 index 000000000000..4445e1f53c67 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "cmmodlib++_export.h" +#include + +#if MESON_MAGIC_FLAG != 42 && MESON_MAGIC_FLAG != 21 +#error "Invalid MESON_MAGIC_FLAG" +#endif + +class CMMODLIB___EXPORT cmModClass { +private: + std::string str; + +public: + cmModClass(std::string foo); + + std::string getStr() const; +}; diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp new file mode 100644 index 000000000000..aa7ceb36144f --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp @@ -0,0 +1,2 @@ +#include +#include diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt b/test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt new file mode 100644 index 000000000000..6443fcadd69a --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 3.5) +project(cmModDummy) diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap b/test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap new file mode 100644 index 000000000000..b24754ecadc8 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap @@ -0,0 +1,2 @@ +[wrap-file] +method=cmake diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt b/test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt new file mode 100644 index 000000000000..497beb95ee18 --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required(VERSION 3.5) +project(cmModBoth) diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build b/test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build new file mode 100644 index 000000000000..92649744ebab --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build @@ -0,0 +1,4 @@ +project('both methods') + +# Ensure the meson method is not used. +notfound() diff --git a/test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap b/test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap new file mode 100644 index 000000000000..e52701e5773e --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap @@ -0,0 +1,2 @@ +[wrap-file] +method=meson diff --git a/test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build b/test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build new file mode 100644 index 000000000000..e4746ce6b0ba --- /dev/null +++ b/test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build @@ -0,0 +1 @@ +project('dummy') From e9369be086dc8381cda91725fb2073c4daf29b91 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 08:55:46 -0400 Subject: [PATCH 259/855] CMakeInterpreter: Remove useless arguments --- mesonbuild/cmake/interpreter.py | 6 ++---- mesonbuild/interpreter/interpreter.py | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 2f7cb69114f6..8e9ea187e239 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -56,7 +56,6 @@ from .common import CMakeConfiguration, TargetOptions from .traceparser import CMakeGeneratorTarget from .._typing import ImmutableListProtocol - from ..build import Build from ..backend.backends import Backend from ..environment import Environment @@ -766,10 +765,9 @@ def log(self) -> None: mlog.log(' -- depends: ', mlog.bold(str(self.depends))) class CMakeInterpreter: - def __init__(self, build: 'Build', subdir: Path, src_dir: Path, install_prefix: Path, env: 'Environment', backend: 'Backend'): - self.build = build + def __init__(self, subdir: Path, install_prefix: Path, env: 'Environment', backend: 'Backend'): self.subdir = subdir - self.src_dir = src_dir + self.src_dir = Path(env.get_source_dir(), subdir) self.build_dir_rel = subdir / '__CMake_build' self.build_dir = Path(env.get_build_dir()) / self.build_dir_rel self.install_prefix = install_prefix diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index e0c17e6ee26a..505099fcedc9 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -919,7 +919,6 @@ def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_meth return self.disabled_subproject(subp_name, exception=e) raise e - subdir_abs = os.path.join(self.environment.get_source_dir(), subdir) os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True @@ -933,7 +932,7 @@ def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_meth if method == 'meson': return self._do_subproject_meson(subp_name, subdir, default_options, kwargs) elif method == 'cmake': - return self._do_subproject_cmake(subp_name, subdir, subdir_abs, default_options, kwargs) + return self._do_subproject_cmake(subp_name, subdir, default_options, kwargs) else: raise mesonlib.MesonBugException(f'The method {method} is invalid for the subproject {subp_name}') # Invalid code is always an error @@ -998,18 +997,17 @@ def _do_subproject_meson(self, subp_name: str, subdir: str, self.build.subprojects[subp_name] = subi.project_version return self.subprojects[subp_name] - def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, + def _do_subproject_cmake(self, subp_name: str, subdir: str, default_options: T.Dict[OptionKey, str], kwargs: kwtypes.DoSubproject) -> SubprojectHolder: from ..cmake import CMakeInterpreter with mlog.nested(subp_name): - new_build = self.build.copy() prefix = self.coredata.options[OptionKey('prefix')].value from ..modules.cmake import CMakeSubprojectOptions options = kwargs.get('options') or CMakeSubprojectOptions() cmake_options = kwargs.get('cmake_options', []) + options.cmake_options - cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend) + cm_int = CMakeInterpreter(Path(subdir), Path(prefix), self.build.environment, self.backend) cm_int.initialise(cmake_options) cm_int.analyse() From 586bd1136d38e6695369617dfcc1dba50c35b279 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 09:38:49 -0400 Subject: [PATCH 260/855] interpreter: Move code that dumps generated AST That code is common to any method that generates an AST, like cargo subprojects coming soon. --- mesonbuild/interpreter/interpreter.py | 38 ++++++++++----------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 505099fcedc9..6afc2aace2b4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -953,12 +953,24 @@ def _do_subproject_meson(self, subp_name: str, subdir: str, kwargs: kwtypes.DoSubproject, ast: T.Optional[mparser.CodeBlockNode] = None, build_def_files: T.Optional[T.List[str]] = None, - is_translated: bool = False, relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None) -> SubprojectHolder: with mlog.nested(subp_name): + if ast: + # Debug print the generated meson file + from ..ast import AstIndentationGenerator, AstPrinter + printer = AstPrinter(update_ast_line_nos=True) + ast.accept(AstIndentationGenerator()) + ast.accept(printer) + printer.post_process() + meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build') + with open(meson_filename, "w", encoding='utf-8') as f: + f.write(printer.result) + mlog.log('Generated Meson AST:', meson_filename) + mlog.cmd_ci_include(meson_filename) + new_build = self.build.copy() subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir, - default_options, ast=ast, is_translated=is_translated, + default_options, ast=ast, is_translated=(ast is not None), relaxations=relaxations, user_defined_options=self.user_defined_options) # Those lists are shared by all interpreters. That means that @@ -1013,37 +1025,15 @@ def _do_subproject_cmake(self, subp_name: str, subdir: str, # Generate a meson ast and execute it with the normal do_subproject_meson ast = cm_int.pretend_to_be_meson(options.target_options) - - mlog.log() - with mlog.nested('cmake-ast'): - mlog.log('Processing generated meson AST') - - # Debug print the generated meson file - from ..ast import AstIndentationGenerator, AstPrinter - printer = AstPrinter(update_ast_line_nos=True) - ast.accept(AstIndentationGenerator()) - ast.accept(printer) - printer.post_process() - meson_filename = os.path.join(self.build.environment.get_build_dir(), subdir, 'meson.build') - with open(meson_filename, "w", encoding='utf-8') as f: - f.write(printer.result) - - mlog.log('Build file:', meson_filename) - mlog.cmd_ci_include(meson_filename) - mlog.log() - result = self._do_subproject_meson( subp_name, subdir, default_options, kwargs, ast, [str(f) for f in cm_int.bs_files], - is_translated=True, relaxations={ InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES, } ) result.cm_interpreter = cm_int - - mlog.log() return result def get_option_internal(self, optname: str) -> coredata.UserOption: From d0b09898c703f6c10ec5a6b2aeace0df2e3570aa Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 23 Sep 2023 17:21:43 +0200 Subject: [PATCH 261/855] get_llvm_tool_names: add llvm 17 this fixes the "frameworks: 15 llvm" tests with llvm 17 --- mesonbuild/environment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 53cb1206fef0..5c7d78b90289 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -157,6 +157,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: # unless it becomes a stable release. suffixes = [ '', # base (no suffix) + '-17', '17', '-16', '16', '-15', '15', '-14', '14', From 9c74c73bc7107c794e7f9896cc4220e50ad32bba Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 23 Sep 2023 14:10:29 +0200 Subject: [PATCH 262/855] openmp: add 5.1/5.2, fixes openmp with llvm v17 llvm v17 defaults to 5.1 and without this meson fails to find openmp: 'ERROR: Dependency "openmp" not found, tried system' Add 5.2 as well while at it. --- mesonbuild/dependencies/misc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index b186b5dda83d..b41f3c2610d7 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -85,6 +85,8 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): class OpenMPDependency(SystemDependency): # Map date of specification release (which is the macro value) to a version. VERSIONS = { + '202111': '5.2', + '202011': '5.1', '201811': '5.0', '201611': '5.0-revision1', # This is supported by ICC 19.x '201511': '4.5', From f20f33149495b5b43bba5f06aa5b9ff4ee59a474 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 23 Sep 2023 15:48:43 +0200 Subject: [PATCH 263/855] cpp: restore c++26 support c++26 support was added in #11986, but regressed in #10332 because the versions now get checked against the global _ALL_STDS list, and c++26 was missing there. Fix by adding c++26 to _ALL_STDS --- mesonbuild/compilers/cpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 3e96682621d1..ba7539c6f858 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -55,7 +55,7 @@ else: CompilerMixinBase = object -_ALL_STDS = ['c++98', 'c++0x', 'c++03', 'c++1y', 'c++1z', 'c++11', 'c++14', 'c++17', 'c++2a', 'c++20', 'c++23'] +_ALL_STDS = ['c++98', 'c++0x', 'c++03', 'c++1y', 'c++1z', 'c++11', 'c++14', 'c++17', 'c++2a', 'c++20', 'c++23', 'c++26'] _ALL_STDS += [f'gnu{std[1:]}' for std in _ALL_STDS] _ALL_STDS += ['vc++11', 'vc++14', 'vc++17', 'vc++20', 'vc++latest', 'c++latest'] From 8d6b474bf67bb8a75e8f60196f7eaf7528a85c62 Mon Sep 17 00:00:00 2001 From: Lei YU Date: Wed, 30 Aug 2023 06:47:14 +0000 Subject: [PATCH 264/855] Add clang-tidy-fix target Add the `clang-tidy-fix` target to apply clang-tidy fixes to the source code. This is done by calling `run-clang-tidy` with `-fix` argument. Add a test case to run `clang-tidy-fix` and verify the file is changed. Signed-off-by: Lei YU --- .../markdown/snippets/meson_clang_tidy_fix.md | 9 ++++++++ mesonbuild/backend/ninjabackend.py | 1 + mesonbuild/scripts/clangtidy.py | 7 +++++- unittests/allplatformstests.py | 22 ++++++++++++++++++- unittests/helpers.py | 5 ++++- 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 docs/markdown/snippets/meson_clang_tidy_fix.md diff --git a/docs/markdown/snippets/meson_clang_tidy_fix.md b/docs/markdown/snippets/meson_clang_tidy_fix.md new file mode 100644 index 000000000000..3a8c772f3f63 --- /dev/null +++ b/docs/markdown/snippets/meson_clang_tidy_fix.md @@ -0,0 +1,9 @@ +## clang-tidy-fix target + +If `clang-tidy` is installed and the project's source root contains a +`.clang-tidy` (or `_clang-tidy`) file, Meson will automatically define +a `clang-tidy-fix` target that runs `run-clang-tidy` tool with `-fix` +option to apply the changes found by clang-tidy to the source code. + +If you have defined your own `clang-tidy-fix` target, Meson will not +generate its own target. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a57b249fe45d..925941a965ac 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3659,6 +3659,7 @@ def generate_clangtidy(self) -> None: if not shutil.which('clang-tidy'): return self.generate_clangtool('tidy') + self.generate_clangtool('tidy', 'fix') def generate_tags(self, tool: str, target_name: str) -> None: import shutil diff --git a/mesonbuild/scripts/clangtidy.py b/mesonbuild/scripts/clangtidy.py index 324a26ea00e5..943bde578ac6 100644 --- a/mesonbuild/scripts/clangtidy.py +++ b/mesonbuild/scripts/clangtidy.py @@ -23,8 +23,12 @@ def run_clang_tidy(fname: Path, builddir: Path) -> subprocess.CompletedProcess: return subprocess.run(['clang-tidy', '-p', str(builddir), str(fname)]) +def run_clang_tidy_fix(fname: Path, builddir: Path) -> subprocess.CompletedProcess: + return subprocess.run(['run-clang-tidy', '-fix', '-format', '-quiet', '-p', str(builddir), str(fname)]) + def run(args: T.List[str]) -> int: parser = argparse.ArgumentParser() + parser.add_argument('--fix', action='store_true') parser.add_argument('sourcedir') parser.add_argument('builddir') options = parser.parse_args(args) @@ -32,4 +36,5 @@ def run(args: T.List[str]) -> int: srcdir = Path(options.sourcedir) builddir = Path(options.builddir) - return run_tool('clang-tidy', srcdir, builddir, run_clang_tidy, builddir) + run_func = run_clang_tidy_fix if options.fix else run_clang_tidy + return run_tool('clang-tidy', srcdir, builddir, run_func, builddir) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index acab026e954c..f06279a2fafd 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -42,7 +42,7 @@ is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg, relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix, MesonException, EnvironmentException, OptionKey, - windows_proof_rm + windows_proof_rm, quiet_git ) from mesonbuild.programs import ExternalProgram @@ -3029,6 +3029,26 @@ def test_clang_tidy(self): self.assertIn('cttest.cpp:4:20', out) self.assertNotIn(dummydir, out) + @skipIfNoExecutable('clang-tidy') + @unittest.skipIf(not is_git_repo(), 'Skipping because this is not in git repo') + def test_clang_tidy_fix(self): + if self.backend is not Backend.ninja: + raise SkipTest(f'Clang-tidy is for now only supported on Ninja, not {self.backend.name}') + if shutil.which('c++') is None: + raise SkipTest('Clang-tidy breaks when ccache is used and "c++" not in path.') + if is_osx(): + raise SkipTest('Apple ships a broken clang-tidy that chokes on -pipe.') + testdir = os.path.join(self.unit_test_dir, '68 clang-tidy') + dummydir = os.path.join(testdir, 'dummydir.h') + self.init(testdir, override_envvars={'CXX': 'c++'}) + out = self.run_target('clang-tidy-fix') + self.assertIn('cttest.cpp:4:20', out) + self.assertNotIn(dummydir, out) + ret = quiet_git(['diff', '--exit-code', 'test cases/unit/68 clang-tidy/cttest.cpp'], '.') + self.assertFalse(ret[0]) + # Restore the file + quiet_git(['checkout', '--', 'test cases/unit/68 clang-tidy/cttest.cpp'], '.') + def test_identity_cross(self): testdir = os.path.join(self.unit_test_dir, '69 cross') # Do a build to generate a cross file where the host is this target diff --git a/unittests/helpers.py b/unittests/helpers.py index 7483f51b75df..83327cbad86a 100644 --- a/unittests/helpers.py +++ b/unittests/helpers.py @@ -12,7 +12,7 @@ from mesonbuild.compilers import detect_c_compiler, compiler_from_language from mesonbuild.mesonlib import ( MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice, - OrderedSet + OrderedSet, quiet_git ) from run_tests import get_fake_env @@ -135,6 +135,9 @@ def is_tarball(): return True return False +def is_git_repo(): + return quiet_git(['branch'], '.')[0] + @contextmanager def chdir(path: str): curdir = os.getcwd() From c1ac252f4ffecc381abe24e13584e1c48516e0eb Mon Sep 17 00:00:00 2001 From: Alan Brooks Date: Fri, 15 Sep 2023 22:27:05 -0500 Subject: [PATCH 265/855] fix bug where all java builds & tests fail to run SanityCheck on JDK11 Needed a classpath set in the current working directory. This was on a Zulu build of OpenJDK 11.0.17 on a macOS ARM machine. The errors folks might encounter: Error: Could not find or load main class SanityCheck Caused by: java.lang.ClassNotFoundException: SanityCheck --- mesonbuild/compilers/java.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index 42cf0a159ce0..9f508d637313 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -100,7 +100,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: raise EnvironmentException(f'Java compiler {self.name_string()} cannot compile programs.') runner = shutil.which(self.javarunner) if runner: - cmdlist = [runner, obj] + cmdlist = [runner, '-cp', '.', obj] pe = subprocess.Popen(cmdlist, cwd=work_dir) pe.wait() if pe.returncode != 0: From d5546bdceaa2f3040d16a33fcbd824ba94b8cfde Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 22 Sep 2023 13:40:35 -0700 Subject: [PATCH 266/855] rust: apply global, project, and environment C args to bindgen This means that arguments set via `add_global_arguments`, `add_project_arguments` and by either the `-Dc_args` or `CFLAGS` are applied to bindgen as well. This can be important when, among other things, #defines are set via these mechanisms. Fixes: #12065 --- mesonbuild/modules/rust.py | 6 ++++++ test cases/rust/12 bindgen/meson.build | 18 ++++++++++++++++++ .../rust/12 bindgen/src/global-project.h | 10 ++++++++++ test cases/rust/12 bindgen/src/global.c | 5 +++++ test cases/rust/12 bindgen/src/global.rs | 14 ++++++++++++++ test cases/rust/12 bindgen/test.json | 5 ++++- 6 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test cases/rust/12 bindgen/src/global-project.h create mode 100644 test cases/rust/12 bindgen/src/global.c create mode 100644 test cases/rust/12 bindgen/src/global.rs diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index b6dd731491cc..382a72de9adc 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -236,6 +236,12 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu elif isinstance(s, CustomTarget): depends.append(s) + clang_args.extend(state.global_args.get('c', [])) + clang_args.extend(state.project_args.get('c', [])) + cargs = state.get_option('args', state.subproject, lang='c') + assert isinstance(cargs, list), 'for mypy' + clang_args.extend(cargs) + if self._bindgen_bin is None: self._bindgen_bin = state.find_program('bindgen') diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index c05cc063136c..e7cb5f3db2c0 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -8,6 +8,9 @@ if not prog_bindgen.found() error('MESON_SKIP_TEST bindgen not found') endif +add_project_arguments('-DPROJECT_ARG', language : 'c') +add_global_arguments('-DGLOBAL_ARG', language : 'c') + # This seems to happen on windows when libclang.dll is not in path or is not # valid. We must try to process a header file for this to work. # @@ -81,3 +84,18 @@ test('generated header', rust_bin2) subdir('sub') subdir('dependencies') + +gp = rust.bindgen( + input : 'src/global-project.h', + output : 'global-project.rs', +) + +gp_lib = static_library('gp_lib', 'src/global.c') + +gp_exe = executable( + 'gp_exe', + structured_sources(['src/global.rs', gp]), + link_with : gp_lib, +) + +test('global and project arguments', gp_exe) diff --git a/test cases/rust/12 bindgen/src/global-project.h b/test cases/rust/12 bindgen/src/global-project.h new file mode 100644 index 000000000000..6084e8ed6b0b --- /dev/null +++ b/test cases/rust/12 bindgen/src/global-project.h @@ -0,0 +1,10 @@ +#ifndef GLOBAL_ARG +char * success(void); +#endif +#ifndef PROJECT_ARG +char * success(void); +#endif +#ifndef CMD_ARG +char * success(void); +#endif +int success(void); diff --git a/test cases/rust/12 bindgen/src/global.c b/test cases/rust/12 bindgen/src/global.c new file mode 100644 index 000000000000..10f6676f7a1b --- /dev/null +++ b/test cases/rust/12 bindgen/src/global.c @@ -0,0 +1,5 @@ +#include "src/global-project.h" + +int success(void) { + return 0; +} diff --git a/test cases/rust/12 bindgen/src/global.rs b/test cases/rust/12 bindgen/src/global.rs new file mode 100644 index 000000000000..4b70b1ecc728 --- /dev/null +++ b/test cases/rust/12 bindgen/src/global.rs @@ -0,0 +1,14 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("global-project.rs"); + +fn main() { + unsafe { + std::process::exit(success()); + }; +} diff --git a/test cases/rust/12 bindgen/test.json b/test cases/rust/12 bindgen/test.json index f94ee85f9740..b3a758562969 100644 --- a/test cases/rust/12 bindgen/test.json +++ b/test cases/rust/12 bindgen/test.json @@ -1,7 +1,10 @@ { + "env": { + "CFLAGS": "-DCMD_ARG" + }, "stdout": [ { - "line": "test cases/rust/12 bindgen/meson.build:27: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." + "line": "test cases/rust/12 bindgen/meson.build:30: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." } ] } From 5b16e830cc40827369cf3949a337112be74dec0e Mon Sep 17 00:00:00 2001 From: CorrodedCoder <38778644+CorrodedCoder@users.noreply.github.com> Date: Mon, 18 Sep 2023 18:03:57 +0100 Subject: [PATCH 267/855] Adjust kernel detection to support Solaris 5.10 or earlier The logic previously added to distinguish between illumos and Solaris made use of a uname invocation with a -o switch which is not supported on Solaris 5.10 or earlier. illumos started with version 5.11 so the logic has been shortcut to report 'solaris' in such cases where the version is 5.10 or below. --- mesonbuild/environment.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 5c7d78b90289..7bd8c2ca60af 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -411,6 +411,11 @@ def detect_cpu(compilers: CompilersDict) -> str: def detect_kernel(system: str) -> T.Optional[str]: if system == 'sunos': + # Solaris 5.10 uname doesn't support the -o switch, and illumos started + # with version 5.11 so shortcut the logic to report 'solaris' in such + # cases where the version is 5.10 or below. + if mesonlib.version_compare(platform.uname().release, '<=5.10'): + return 'solaris' # This needs to be /usr/bin/uname because gnu-uname could be installed and # won't provide the necessary information p, out, _ = Popen_safe(['/usr/bin/uname', '-o']) From c3fe1b046d540734974cbd331ed0f3b61aa6256b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 25 Sep 2023 23:29:48 -0400 Subject: [PATCH 268/855] tests: fix broken promises with linker scripts This has never, ever, ever worked. You can get away with it a tiny, tiny bit, iff you magically assume several things about both internal implementations, as well as the project source layout and builddir location. This can be witnessed by the way using files() was mercilessly tortured through joining the undefined stringified format value of the file to the current source dir... because it didn't actually *work*, the stringified value isn't an absolute path or a builddir-relative one, but it works as long as you do it from the root meson.build file. Furthermore, this triggers a deprecation warning if you do it. And using it for files() is frivolous, the "static map file" case was correct all along. Fix the configure_file case to demonstrate the same painful hoops we must jump through to get custom_target outputs to work correctly. Fixes #12259 --- test cases/linuxlike/3 linker script/meson.build | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/test cases/linuxlike/3 linker script/meson.build b/test cases/linuxlike/3 linker script/meson.build index 5901bf7cf716..660858792cb2 100644 --- a/test cases/linuxlike/3 linker script/meson.build +++ b/test cases/linuxlike/3 linker script/meson.build @@ -22,7 +22,7 @@ m = configure_file( output : 'bob-conf.map', configuration : conf, ) -vflag = '-Wl,--version-script,@0@'.format(m) +vflag = '-Wl,--version-script,@0@'.format(meson.current_build_dir() / 'bob-conf.map') l = shared_library('bob-conf', 'bob.c', link_args : vflag, link_depends : m) e = executable('prog-conf', 'prog.c', link_with : l) @@ -43,14 +43,6 @@ l = shared_library('bob-ct', ['bob.c', m], link_args : vflag, link_depends : m) e = executable('prog-ct', 'prog.c', link_with : l) test('core', e) -# File -mapfile = files('bob.map') -vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile[0]) - -l = shared_library('bob-files', 'bob.c', link_args : vflag, link_depends : mapfile) -e = executable('prog-files', 'prog.c', link_with : l) -test('core', e) - subdir('sub') # With map file in subdir From 14ac4e3528bfcf5d12c20020fab7dbf95757e8a8 Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Wed, 9 Aug 2023 08:35:50 +0100 Subject: [PATCH 269/855] Revert "Visual studio: Generate vcxproj.filters files to adds filters to imitated directories to navigate more easily in the source files." This reverts commit e94de2b872a2d87074d49926574a8c8623c27b72. --- mesonbuild/backend/vs2010backend.py | 63 ----------------------------- 1 file changed, 63 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index bb72594c4d59..943dffa4f611 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -618,11 +618,6 @@ def add_target_deps(self, root: ET.Element, target): tid = self.environment.coredata.target_guids[dep.get_id()] self.add_project_reference(root, vcxproj, tid) - def create_basic_project_filters(self) -> ET.Element: - root = ET.Element('Project', {'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) - return root - def create_basic_project(self, target_name, *, temp_dir, guid, @@ -933,39 +928,6 @@ def escape_additional_option(option: str) -> str: option += '\\' return f'"{option}"' - @staticmethod - def add_filter_info(list_filters_path, filter_group, sub_element, file_path, forced_filter_name=None, down=''): - filter_inc_cl = ET.SubElement(filter_group, sub_element, Include=file_path) - - # Force the subdir - if forced_filter_name: - filter_path = forced_filter_name - else: - # Create a subdir following the placement if on the same drive - filter_path = Path(file_path).resolve().parent - if Path(file_path).drive == Path(down).drive: - filter_path = Path(os.path.relpath(str(filter_path), down)).as_posix().replace('../', '').replace('..', '') - else: - return # No filter needed - - # Needed to have non posix path - filter_path = filter_path.replace('/', '\\') - - if filter_path and filter_path != '.': - # Remove ending backslash - filter_path = filter_path.rstrip('\\') - # Create a hierarchical level of directories - list_path = filter_path.split('\\') - new_filter_path = '' - for path in list_path: - if new_filter_path: - new_filter_path = new_filter_path + '\\' + path - else: - new_filter_path = path - list_filters_path.add(new_filter_path) - # Create a new filter node for the current file added - ET.SubElement(filter_inc_cl, 'Filter').text = filter_path - @staticmethod def split_link_args(args): """ @@ -1674,9 +1636,6 @@ def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ target_ext=tfilename[1], target_platform=platform) - # vcxproj.filters file - root_filter = self.create_basic_project_filters() - generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands( target, root) (gen_src, gen_hdrs, gen_objs, _gen_langs) = self.split_sources(generated_files) @@ -1738,8 +1697,6 @@ def path_normalize_add(path, lis): # used with a vs backend pch_sources[lang] = [pch[0], None, lang, None] - list_filters_path = set() - previous_includes = [] if len(headers) + len(gen_hdrs) + len(target.extra_files) + len(pch_sources) > 0: if self.gen_lite and gen_hdrs: @@ -1747,28 +1704,21 @@ def path_normalize_add(path, lis): # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. self.relocate_generated_file_paths_to_concrete_build_dir(gen_hdrs, target) - # Filter information - filter_group_include = ET.SubElement(root_filter, 'ItemGroup') - inc_hdrs = ET.SubElement(root, 'ItemGroup') for h in headers: relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_includes): - self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) for h in gen_hdrs: if path_normalize_add(h, previous_includes): - self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', h) ET.SubElement(inc_hdrs, 'CLInclude', Include=h) for h in target.extra_files: relpath = os.path.join(proj_to_build_root, h.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_includes): - self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', relpath, h.subdir) ET.SubElement(inc_hdrs, 'CLInclude', Include=relpath) for headers in pch_sources.values(): path = os.path.join(proj_to_src_dir, headers[0]) if path_normalize_add(path, previous_includes): - self.add_filter_info(list_filters_path, filter_group_include, 'ClInclude', path, 'pch') ET.SubElement(inc_hdrs, 'CLInclude', Include=path) previous_sources = [] @@ -1784,14 +1734,10 @@ def path_normalize_add(path, lis): # in our concrete build directories (e.g. '..._debug'), where generated files will exist after building. self.relocate_generated_file_paths_to_concrete_build_dir(gen_src, target) - # Filter information - filter_group_compile = ET.SubElement(root_filter, 'ItemGroup') - inc_src = ET.SubElement(root, 'ItemGroup') for s in sources: relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_sources): - self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', relpath, s.subdir) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=relpath) if self.gen_lite: self.add_project_nmake_defs_incs_and_opts(inc_cl, relpath, defs_paths_opts_per_lang_and_buildtype, platform) @@ -1805,7 +1751,6 @@ def path_normalize_add(path, lis): self.object_filename_from_source(target, s) for s in gen_src: if path_normalize_add(s, previous_sources): - self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', s) inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=s) if self.gen_lite: self.add_project_nmake_defs_incs_and_opts(inc_cl, s, defs_paths_opts_per_lang_and_buildtype, platform) @@ -1821,7 +1766,6 @@ def path_normalize_add(path, lis): for lang, headers in pch_sources.items(): impl = headers[1] if impl and path_normalize_add(impl, previous_sources): - self.add_filter_info(list_filters_path, filter_group_compile, 'CLCompile', impl, 'pch') inc_cl = ET.SubElement(inc_src, 'CLCompile', Include=impl) self.create_pch(pch_sources, lang, inc_cl) if self.gen_lite: @@ -1838,12 +1782,6 @@ def path_normalize_add(path, lis): self.add_include_dirs(lang, inc_cl, inc_dirs) # XXX: Do we need to set the object file name here too? - # Filter information - filter_group = ET.SubElement(root_filter, 'ItemGroup') - for filter_dir in list_filters_path: - filter = ET.SubElement(filter_group, 'Filter', Include=filter_dir) - ET.SubElement(filter, 'UniqueIdentifier').text = '{' + str(uuid.uuid4()) + '}' - additional_objects = [] for o in self.flatten_object_list(target, proj_to_build_root)[0]: assert isinstance(o, str) @@ -1871,7 +1809,6 @@ def path_normalize_add(path, lis): # build system as possible. self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) - self._prettyprint_vcxproj_xml(ET.ElementTree(root_filter), ofname + '.filters') return True def gen_regenproj(self): From b6b68d7ee687682ce529617e8ace48b582d0dbf1 Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Wed, 9 Aug 2023 08:39:08 +0100 Subject: [PATCH 270/855] vs2010backend: avoid duplicated directory structure in vcxproj.filters Root the vcxproj.filters at the directory containing the meson.build defining the target. Co-authored-by: Joshua Ashton --- mesonbuild/backend/vs2010backend.py | 70 ++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 943dffa4f611..0b6be1c79aad 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -20,7 +20,7 @@ import xml.etree.ElementTree as ET import uuid import typing as T -from pathlib import Path, PurePath +from pathlib import Path, PurePath, PureWindowsPath import re from collections import Counter @@ -1809,8 +1809,76 @@ def path_normalize_add(path, lis): # build system as possible. self.add_target_deps(root, target) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) + if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': + self.gen_vcxproj_filters(target, ofname) return True + def gen_vcxproj_filters(self, target, ofname): + # Generate pitchfork of filters based on directory structure. + root = ET.Element('Project', {'ToolsVersion': '4.0', + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) + filter_folders = ET.SubElement(root, 'ItemGroup') + filter_items = ET.SubElement(root, 'ItemGroup') + mlog.debug(f'Generating vcxproj filters {target.name}.') + + def relative_to_defined_in(file): + # Get the relative path to file's directory from the location of the meson.build that defines this target. + return os.path.dirname(self.relpath(PureWindowsPath(file.subdir, file.fname), self.get_target_dir(target))) + + found_folders_to_filter = {} + all_files = target.sources + target.extra_files + + # Build a dictionary of all used relative paths (i.e. from the meson.build defining this target) + # for all sources. + for i in all_files: + if not os.path.isabs(i.fname): + dirname = relative_to_defined_in(i) + if dirname: + found_folders_to_filter[dirname] = '' + + # Now walk up each of those relative paths checking for empty intermediate dirs to generate the filter. + for folder in found_folders_to_filter: + dirname = folder + filter = '' + + while dirname: + basename = os.path.basename(dirname) + + if filter == '': + filter = basename + else: + # Use '/' to squash empty dirs. To actually get a '\', use '%255c'. + filter = basename + ('\\' if dirname in found_folders_to_filter else '/') + filter + + dirname = os.path.dirname(dirname) + + # Don't add an empty filter, breaks all other (?) filters. + if filter != '': + found_folders_to_filter[folder] = filter + filter_element = ET.SubElement(filter_folders, 'Filter', {'Include': filter}) + uuid_element = ET.SubElement(filter_element, 'UniqueIdentifier') + uuid_element.text = '{' + str(uuid.uuid4()).upper() + '}' + + sources, headers, objects, _ = self.split_sources(all_files) + down = self.target_to_build_root(target) + + def add_element(type_name, elements): + for i in elements: + if not os.path.isabs(i.fname): + dirname = relative_to_defined_in(i) + + if dirname and dirname in found_folders_to_filter: + relpath = os.path.join(down, i.rel_to_builddir(self.build_to_src)) + target_element = ET.SubElement(filter_items, type_name, {'Include': relpath}) + filter_element = ET.SubElement(target_element, 'Filter') + filter_element.text = found_folders_to_filter[dirname] + + add_element('ClCompile', sources) + add_element('ClInclude', headers) + add_element('Object', objects) + + self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname + '.filters') + def gen_regenproj(self): # To fully adapt the REGEN work for a 'genvslite' solution, to check timestamps, settings, and regenerate the # '[builddir]_vs' solution/vcxprojs, as well as regenerating the accompanying buildtype-suffixed ninja build From fb6fd5aa1770970e94968b302dfe3026aa08e245 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Mon, 21 Aug 2023 10:13:05 -0500 Subject: [PATCH 271/855] tests: Skip "withIncludeFile" for PCH on Xcode backend Xcode always fails here because this makes the PCH not be the first included header, causing Xcode to ignore it completely. There is no way around this. --- test cases/common/13 pch/meson.build | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build index 4bb3e1f275ba..d83291963284 100644 --- a/test cases/common/13 pch/meson.build +++ b/test cases/common/13 pch/meson.build @@ -13,7 +13,11 @@ subdir('cpp') subdir('generated') subdir('userDefined') subdir('withIncludeDirectories') -subdir('withIncludeFile') +if meson.backend() == 'xcode' + warning('Xcode backend does not support forced includes. Skipping "withIncludeFile" which requires this.') +else + subdir('withIncludeFile') +endif if meson.backend() == 'xcode' warning('Xcode backend only supports one precompiled header per target. Skipping "mixed" which has various precompiled headers.') From 5b317c5658f5865aea76b5a5afda2cdc8bd50959 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 1 Sep 2023 17:23:29 -0400 Subject: [PATCH 272/855] compilers: use correct version comparison for openbsd libraries It should *be* a version comparison. We are guaranteed to get a two-element version number, which also parses as a float but a float doesn't correctly handle version sorting when the second component differs in number of digits. The standard way to handle this is by comparing tuples such that each component is an integer. Do so here. Fixes #12195 Co-authored-by: George Koehler (for unittests) --- mesonbuild/compilers/mixins/clike.py | 9 ++++++--- unittests/internaltests.py | 5 ++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 61e671921e6a..38af08c42c26 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1084,6 +1084,10 @@ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool @staticmethod def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]: + def tuple_key(x: str) -> T.Tuple[int, ...]: + ver = x.rsplit('.so.', maxsplit=1)[1] + return tuple(int(i) for i in ver.split('.')) + filtered: T.List[str] = [] for lib in libs: # Validate file as a shared library of type libfoo.so.X.Y @@ -1091,12 +1095,11 @@ def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]: if len(ret) != 2: continue try: - float(ret[1]) + tuple(int(i) for i in ret[1].split('.')) except ValueError: continue filtered.append(lib) - float_cmp = lambda x: float(x.rsplit('.so.', maxsplit=1)[1]) - return sorted(filtered, key=float_cmp, reverse=True) + return sorted(filtered, key=tuple_key, reverse=True) @classmethod def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> T.List[Path]: diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 56d36117a454..eb3b1717a66b 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -549,11 +549,14 @@ def _test_all_naming(self, cc, env, patterns, platform): if platform != 'openbsd': return with tempfile.TemporaryDirectory() as tmpdir: - for i in ['libfoo.so.6.0', 'libfoo.so.5.0', 'libfoo.so.54.0', 'libfoo.so.66a.0b', 'libfoo.so.70.0.so.1']: + for i in ['libfoo.so.6.0', 'libfoo.so.5.0', 'libfoo.so.54.0', 'libfoo.so.66a.0b', 'libfoo.so.70.0.so.1', + 'libbar.so.7.10', 'libbar.so.7.9', 'libbar.so.7.9.3']: libpath = Path(tmpdir) / i libpath.write_text('', encoding='utf-8') found = cc._find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED, lib_prefix_warning=True) self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') + found = cc._find_library_real('bar', env, [tmpdir], '', LibType.PREFER_SHARED, lib_prefix_warning=True) + self.assertEqual(os.path.basename(found[0]), 'libbar.so.7.10') def test_find_library_patterns(self): ''' From a843a997437286f7ddce4d8fde843fab39888a23 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 6 Sep 2023 09:21:01 -0400 Subject: [PATCH 273/855] mypy: replace fchmod by chmod The former is unix-only, which complains when running on the Windows platform -- even though this code is in a unix-specific branch. But per the docs: > As of Python 3.3, this is equivalent to os.chmod(fd, mode). So we can just use the identical function that is available in more places. --- 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 593efd9f7677..10399332cfc9 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -154,7 +154,7 @@ def open_bf(self, bfile: str) -> None: def close_bf(self) -> None: if self.bf is not None: if self.bf_perms is not None: - os.fchmod(self.bf.fileno(), self.bf_perms) + os.chmod(self.bf.fileno(), self.bf_perms) self.bf_perms = None self.bf.close() self.bf = None From 3c88c73c59237ac9163a6c30590f520e8f9d1535 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Sep 2023 10:31:36 -0700 Subject: [PATCH 274/855] interpreter: annotate build_target function This uses an overload to try to get more accurate information from the function. --- mesonbuild/interpreter/interpreter.py | 27 +++++++++++++++++++++++++-- mesonbuild/modules/rust.py | 8 ++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 6afc2aace2b4..3e6d3b8e8100 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1862,7 +1862,7 @@ def func_library(self, node: mparser.BaseNode, @typed_pos_args('jar', str, varargs=SOURCES_VARARGS) @typed_kwargs('jar', *JAR_KWS, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Jar) -> build.Jar: return self.build_target(node, args, kwargs, build.Jar) @@ -3224,7 +3224,30 @@ def build_library(self, node, args, kwargs): else: raise InterpreterException(f'Unknown default_library value: {default_library}.') - def build_target(self, node: mparser.BaseNode, args, kwargs, targetclass): + @T.overload + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: kwtypes.Executable, targetclass: T.Type[build.Executable]) -> build.Executable: ... + + @T.overload + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: kwtypes.StaticLibrary, targetclass: T.Type[build.StaticLibrary]) -> build.StaticLibrary: ... + + @T.overload + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: kwtypes.SharedLibrary, targetclass: T.Type[build.SharedLibrary]) -> build.SharedLibrary: ... + + @T.overload + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: kwtypes.SharedModule, targetclass: T.Type[build.SharedModule]) -> build.SharedModule: ... + + @T.overload + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: kwtypes.Jar, targetclass: T.Type[build.Jar]) -> build.Jar: ... + + def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], + kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], + targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] + ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: @FeatureNewKwargs('build target', '1.2.0', ['rust_dependency_map']) @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories']) @FeatureNewKwargs('build target', '0.41.0', ['rust_args']) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 382a72de9adc..08aee16c8453 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -285,11 +285,11 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu 'link_args', 'link_depends', 'link_with', 'override_options'}) @typed_pos_args('rust.proc_macro', str, varargs=SOURCES_VARARGS) @typed_kwargs('rust.proc_macro', *SHARED_LIB_KWS, allow_unknown=True) - def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType], kwargs: T.Dict) -> SharedLibrary: - kwargs['native'] = True - kwargs['rust_crate_type'] = 'proc-macro' + def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType], kwargs: _kwargs.SharedLibrary) -> SharedLibrary: + kwargs['native'] = True # type: ignore + kwargs['rust_crate_type'] = 'proc-macro' # type: ignore target = state._interpreter.build_target(state.current_node, args, kwargs, SharedLibrary) - return T.cast('SharedLibrary', target) + return target def initialize(interp: Interpreter) -> RustModule: From e27dbb42a0f174634c63cc6fa96445dea112e6bb Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Sep 2023 10:39:50 -0700 Subject: [PATCH 275/855] interpreter: add rust_abi to type annotations --- mesonbuild/interpreter/kwargs.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 35b8fb65bcf7..dd2e147f0602 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -332,13 +332,17 @@ class _BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" +class _LibraryMixin(TypedDict): + + rust_abi: T.Optional[Literal['c', 'rust']] + class Executable(_BuildTarget): gui_app: T.Optional[bool] win_subsystem: T.Optional[str] -class StaticLibrary(_BuildTarget): +class StaticLibrary(_BuildTarget, _LibraryMixin): pass @@ -349,15 +353,15 @@ class _SharedLibMixin(TypedDict): version: T.Optional[str] -class SharedLibrary(_BuildTarget, _SharedLibMixin): +class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): pass -class SharedModule(_BuildTarget): +class SharedModule(_BuildTarget, _LibraryMixin): pass -class Library(_BuildTarget, _SharedLibMixin): +class Library(_BuildTarget, _SharedLibMixin, _LibraryMixin): """For library, both_library, and as a base for build_target""" From 07597088a567ae91397810ed3c1aec063f38fcfd Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Sep 2023 10:42:38 -0700 Subject: [PATCH 276/855] interpreter: used typed_kwargs for rust_dependency_map --- mesonbuild/interpreter/interpreter.py | 1 - mesonbuild/interpreter/kwargs.py | 2 ++ mesonbuild/interpreter/type_checking.py | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 3e6d3b8e8100..c06b5a1eac8e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3248,7 +3248,6 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: - @FeatureNewKwargs('build target', '1.2.0', ['rust_dependency_map']) @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories']) @FeatureNewKwargs('build target', '0.41.0', ['rust_args']) @FeatureNewKwargs('build target', '0.38.0', ['build_by_default']) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index dd2e147f0602..a80d489ec383 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -331,6 +331,8 @@ class _BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" + rust_dependency_map: T.Dict[str, str] + class _LibraryMixin(TypedDict): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 9a1904d57cb1..dfc3ae2e9515 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -522,6 +522,12 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, RUST_CRATE_TYPE_KW, + KwargInfo( + 'rust_dependency_map', + ContainerTypeInfo(dict, str), + default={}, + since='1.2.0', + ), ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: From 5ff59f2fb515f47ed61598fed7749982fb20e49f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Sep 2023 10:46:20 -0700 Subject: [PATCH 277/855] interpreter: remove rust_crate_type from the build_target checker This is already handled by the typed_kwargs --- mesonbuild/interpreter/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c06b5a1eac8e..8950f0c445f8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3248,7 +3248,7 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: - @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories']) + @FeatureNewKwargs('build target', '0.42.0', ['build_rpath', 'implicit_include_directories']) @FeatureNewKwargs('build target', '0.41.0', ['rust_args']) @FeatureNewKwargs('build target', '0.38.0', ['build_by_default']) @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) From dac25ba9a8dc3833edbc0d0fd133bc61c706f84a Mon Sep 17 00:00:00 2001 From: Lei YU Date: Thu, 28 Sep 2023 07:26:12 +0000 Subject: [PATCH 278/855] unittest: Fix clang-tidy-fix The unittest case for `clang-tidy-fix` checks if the whole project is in git or not, and skips if not. Fix this by creating a temporary git repo, copy the test files and run the tests, following how `clang-format` does. It also reverts some help code introduced in the previous test. Tested: Verify the test case passes. Signed-off-by: Lei YU --- .../unit/68 clang-tidy/cttest_fixed.cpp | 7 ++++++ unittests/allplatformstests.py | 23 ++++++++++++++----- unittests/helpers.py | 5 +--- 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 test cases/unit/68 clang-tidy/cttest_fixed.cpp diff --git a/test cases/unit/68 clang-tidy/cttest_fixed.cpp b/test cases/unit/68 clang-tidy/cttest_fixed.cpp new file mode 100644 index 000000000000..5b422f6e9089 --- /dev/null +++ b/test cases/unit/68 clang-tidy/cttest_fixed.cpp @@ -0,0 +1,7 @@ +#include + +int main(int, char**) { + bool intbool = true; + printf("Intbool is %d\n", (int)intbool); + return 0; +} diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index f06279a2fafd..4ee0de469026 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -42,7 +42,7 @@ is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg, relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix, MesonException, EnvironmentException, OptionKey, - windows_proof_rm, quiet_git + windows_proof_rm ) from mesonbuild.programs import ExternalProgram @@ -3030,7 +3030,6 @@ def test_clang_tidy(self): self.assertNotIn(dummydir, out) @skipIfNoExecutable('clang-tidy') - @unittest.skipIf(not is_git_repo(), 'Skipping because this is not in git repo') def test_clang_tidy_fix(self): if self.backend is not Backend.ninja: raise SkipTest(f'Clang-tidy is for now only supported on Ninja, not {self.backend.name}') @@ -3039,15 +3038,27 @@ def test_clang_tidy_fix(self): if is_osx(): raise SkipTest('Apple ships a broken clang-tidy that chokes on -pipe.') testdir = os.path.join(self.unit_test_dir, '68 clang-tidy') + + # Ensure that test project is in git even when running meson from tarball. + srcdir = os.path.join(self.builddir, 'src') + shutil.copytree(testdir, srcdir) + git_init(srcdir) + testdir = srcdir + self.new_builddir() + dummydir = os.path.join(testdir, 'dummydir.h') + testfile = os.path.join(testdir, 'cttest.cpp') + fixedfile = os.path.join(testdir, 'cttest_fixed.cpp') self.init(testdir, override_envvars={'CXX': 'c++'}) + # Make sure test files are different + self.assertNotEqual(Path(testfile).read_text(encoding='utf-8'), + Path(fixedfile).read_text(encoding='utf-8')) out = self.run_target('clang-tidy-fix') self.assertIn('cttest.cpp:4:20', out) self.assertNotIn(dummydir, out) - ret = quiet_git(['diff', '--exit-code', 'test cases/unit/68 clang-tidy/cttest.cpp'], '.') - self.assertFalse(ret[0]) - # Restore the file - quiet_git(['checkout', '--', 'test cases/unit/68 clang-tidy/cttest.cpp'], '.') + # Make sure the test file is fixed + self.assertEqual(Path(testfile).read_text(encoding='utf-8'), + Path(fixedfile).read_text(encoding='utf-8')) def test_identity_cross(self): testdir = os.path.join(self.unit_test_dir, '69 cross') diff --git a/unittests/helpers.py b/unittests/helpers.py index 83327cbad86a..7483f51b75df 100644 --- a/unittests/helpers.py +++ b/unittests/helpers.py @@ -12,7 +12,7 @@ from mesonbuild.compilers import detect_c_compiler, compiler_from_language from mesonbuild.mesonlib import ( MachineChoice, is_osx, is_cygwin, EnvironmentException, OptionKey, MachineChoice, - OrderedSet, quiet_git + OrderedSet ) from run_tests import get_fake_env @@ -135,9 +135,6 @@ def is_tarball(): return True return False -def is_git_repo(): - return quiet_git(['branch'], '.')[0] - @contextmanager def chdir(path: str): curdir = os.getcwd() From 798791baac3c41e87a7bf8fedbff7892f789a07c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 11 Aug 2023 15:56:57 -0700 Subject: [PATCH 279/855] interpreter: use typed_kwargs for static_library(prelink) --- mesonbuild/build.py | 4 +--- mesonbuild/interpreter/kwargs.py | 9 +++++++-- mesonbuild/interpreter/type_checking.py | 4 +++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index c58447b55db8..1db78ff9031b 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2053,9 +2053,7 @@ def __init__( environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], kwargs): - self.prelink = kwargs.get('prelink', False) - if not isinstance(self.prelink, bool): - raise InvalidArguments('Prelink keyword argument must be a boolean.') + self.prelink = T.cast('bool', kwargs.get('prelink', False)) super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, environment, compilers, kwargs) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index a80d489ec383..839771279ba3 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -344,7 +344,12 @@ class Executable(_BuildTarget): win_subsystem: T.Optional[str] -class StaticLibrary(_BuildTarget, _LibraryMixin): +class _StaticLibMixin(TypedDict): + + prelink: bool + + +class StaticLibrary(_BuildTarget, _StaticLibMixin, _LibraryMixin): pass @@ -363,7 +368,7 @@ class SharedModule(_BuildTarget, _LibraryMixin): pass -class Library(_BuildTarget, _SharedLibMixin, _LibraryMixin): +class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): """For library, both_library, and as a base for build_target""" diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index dfc3ae2e9515..aaa71daf5388 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -604,7 +604,9 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # Arguments exclusive to StaticLibrary. These are separated to make integrating # them into build_target easier -_EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [] +_EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [ + KwargInfo('prelink', bool, default=False, since='0.57.0'), +] # The total list of arguments used by StaticLibrary STATIC_LIB_KWS = [ From f485a8cf1678b5303e38fc5940ef76a30fbea6a2 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 11 Aug 2023 16:00:44 -0700 Subject: [PATCH 280/855] interpreter: use typed_kwargs for static_library(pic) --- mesonbuild/build.py | 6 +++--- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 1db78ff9031b..4152be7786d4 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1240,7 +1240,7 @@ def process_kwargs(self, kwargs): raise InvalidArguments(f'Invalid rust_dependency_map "{rust_dependency_map}": must be a dictionary with string values.') self.rust_dependency_map = rust_dependency_map - def _extract_pic_pie(self, kwargs, arg: str, option: str): + def _extract_pic_pie(self, kwargs: T.Dict[str, T.Any], arg: str, option: str) -> bool: # Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags all_flags = self.extra_args['c'] + self.extra_args['cpp'] if '-f' + arg.lower() in all_flags or '-f' + arg.upper() in all_flags: @@ -1248,8 +1248,8 @@ def _extract_pic_pie(self, kwargs, arg: str, option: str): return True k = OptionKey(option) - if arg in kwargs: - val = kwargs[arg] + if kwargs.get(arg) is not None: + val = T.cast('bool', kwargs[arg]) elif k in self.environment.coredata.options: val = self.environment.coredata.options[k].value else: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 839771279ba3..bf0c64cc9e3e 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -347,6 +347,7 @@ class Executable(_BuildTarget): class _StaticLibMixin(TypedDict): prelink: bool + pic: T.Optional[bool] class StaticLibrary(_BuildTarget, _StaticLibMixin, _LibraryMixin): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index aaa71daf5388..286bdcab3bcc 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -606,6 +606,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # them into build_target easier _EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [ KwargInfo('prelink', bool, default=False, since='0.57.0'), + KwargInfo('pic', (bool, NoneType), since='0.36.0'), ] # The total list of arguments used by StaticLibrary From f4ea89be6041b4351d34695f71f9678cc8dd092b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Sat, 29 Jul 2023 21:36:17 -0700 Subject: [PATCH 281/855] interpreter: use typed_kwargs for build_target(vs_module_defs) --- mesonbuild/build.py | 2 +- mesonbuild/interpreter/kwargs.py | 4 +++- mesonbuild/interpreter/type_checking.py | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 4152be7786d4..7b5cfa78657c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2321,7 +2321,7 @@ def process_kwargs(self, kwargs): self.darwin_versions = (self.soversion, self.soversion) # Visual Studio module-definitions file - if 'vs_module_defs' in kwargs: + if kwargs.get('vs_module_defs') is not None: path = kwargs['vs_module_defs'] if isinstance(path, str): if os.path.isabs(path): diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index bf0c64cc9e3e..ba5b5d0cc6e3 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -359,6 +359,7 @@ class _SharedLibMixin(TypedDict): darwin_versions: T.Optional[T.Tuple[str, str]] soversion: T.Optional[str] version: T.Optional[str] + vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget]] class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): @@ -366,7 +367,8 @@ class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): class SharedModule(_BuildTarget, _LibraryMixin): - pass + + vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget]] class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 286bdcab3bcc..8f5fd0848a70 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -513,6 +513,11 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since='1.3.0', validator=in_set_validator({'rust', 'c'})) +_VS_MODULE_DEFS_KW: KwargInfo[T.Optional[T.Union[str, File, CustomTarget]]] = KwargInfo( + 'vs_module_defs', + (str, File, CustomTarget, NoneType), +) + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, @@ -629,6 +634,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_LIB_KWS, + _VS_MODULE_DEFS_KW, ] # Arguments exclusive to SharedModule. These are separated to make integrating @@ -640,6 +646,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_LIB_KWS, + _VS_MODULE_DEFS_KW, ] # Arguments exclusive to JAR. These are separated to make integrating @@ -662,6 +669,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, + _VS_MODULE_DEFS_KW, ] # Arguments used by build_Target From 5421c24ea02ac50292db51bcab6150bb7e91bf1c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 31 Jul 2023 05:16:39 -0700 Subject: [PATCH 282/855] fix using a CustomTargetIndex for vs_module_defs Because `CustomTargetIndex`es don't have a `subdir` property, but they do implement the `get_subdir()` method --- .../markdown/snippets/vs_module_defs_customtargetindex.md | 8 ++++++++ docs/yaml/functions/shared_library.yaml | 2 ++ docs/yaml/functions/shared_module.yaml | 2 ++ mesonbuild/build.py | 6 +++--- mesonbuild/interpreter/kwargs.py | 4 ++-- mesonbuild/interpreter/type_checking.py | 5 +++-- .../subdir/meson.build | 2 ++ 7 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 docs/markdown/snippets/vs_module_defs_customtargetindex.md diff --git a/docs/markdown/snippets/vs_module_defs_customtargetindex.md b/docs/markdown/snippets/vs_module_defs_customtargetindex.md new file mode 100644 index 000000000000..d50d04ecb516 --- /dev/null +++ b/docs/markdown/snippets/vs_module_defs_customtargetindex.md @@ -0,0 +1,8 @@ +## vs_module_defs keyword now supports indexes of custom_target + +This means you can do something like: +```meson +defs = custom_target('generate_module_defs', ...) +shared_library('lib1', vs_module_defs : defs[0]) +shared_library('lib2', vs_module_defs : defs[2]) +``` diff --git a/docs/yaml/functions/shared_library.yaml b/docs/yaml/functions/shared_library.yaml index 5076b9341b2a..f633aca966fe 100644 --- a/docs/yaml/functions/shared_library.yaml +++ b/docs/yaml/functions/shared_library.yaml @@ -45,6 +45,8 @@ kwargs: Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + *(Since 1.3.0)* [[@custom_idx]] are supported + rust_abi: type: str since: 1.3.0 diff --git a/docs/yaml/functions/shared_module.yaml b/docs/yaml/functions/shared_module.yaml index 46086ba3096d..6b94e56add4a 100644 --- a/docs/yaml/functions/shared_module.yaml +++ b/docs/yaml/functions/shared_module.yaml @@ -40,6 +40,8 @@ kwargs: Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + *(Since 1.3.0)* [[@custom_idx]] are supported + rust_abi: type: str since: 1.3.0 diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7b5cfa78657c..10f226117359 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2331,13 +2331,13 @@ def process_kwargs(self, kwargs): elif isinstance(path, File): # When passing a generated file. self.vs_module_defs = path - elif isinstance(path, CustomTarget): + elif isinstance(path, (CustomTarget, CustomTargetIndex)): # When passing output of a Custom Target - self.vs_module_defs = File.from_built_file(path.subdir, path.get_filename()) + self.vs_module_defs = File.from_built_file(path.get_subdir(), path.get_filename()) else: raise InvalidArguments( 'Shared library vs_module_defs must be either a string, ' - 'a file object or a Custom Target') + 'a file object, a Custom Target, or a Custom Target Index') self.process_link_depends(path) rust_abi = kwargs.get('rust_abi') diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index ba5b5d0cc6e3..cbe440513f6e 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -359,7 +359,7 @@ class _SharedLibMixin(TypedDict): darwin_versions: T.Optional[T.Tuple[str, str]] soversion: T.Optional[str] version: T.Optional[str] - vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget]] + vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): @@ -368,7 +368,7 @@ class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): class SharedModule(_BuildTarget, _LibraryMixin): - vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget]] + vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 8f5fd0848a70..0d0267d54f30 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -513,9 +513,10 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since='1.3.0', validator=in_set_validator({'rust', 'c'})) -_VS_MODULE_DEFS_KW: KwargInfo[T.Optional[T.Union[str, File, CustomTarget]]] = KwargInfo( +_VS_MODULE_DEFS_KW: KwargInfo[T.Optional[T.Union[str, File, CustomTarget, CustomTargetIndex]]] = KwargInfo( 'vs_module_defs', - (str, File, CustomTarget, NoneType), + (str, File, CustomTarget, CustomTargetIndex, NoneType), + since_values={CustomTargetIndex: '1.3.0'} ) # Applies to all build_target like classes diff --git a/test cases/windows/10 vs module defs generated custom target/subdir/meson.build b/test cases/windows/10 vs module defs generated custom target/subdir/meson.build index c4ae33ae4c29..027769244a36 100644 --- a/test cases/windows/10 vs module defs generated custom target/subdir/meson.build +++ b/test cases/windows/10 vs module defs generated custom target/subdir/meson.build @@ -5,3 +5,5 @@ def_file = custom_target('gen_def', output: 'somedll.def') shlib = shared_library('somedll', 'somedll.c', vs_module_defs: def_file) + +shared_library('somedll2', 'somedll.c', vs_module_defs: def_file[0]) From 32be9bd6de0a4769cdf6d9528496925643739918 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Sat, 29 Jul 2023 21:41:10 -0700 Subject: [PATCH 283/855] add support for vs_module_defs to Executables fixes: #9254 --- .../snippets/executable_vs_module_defs.md | 4 ++ docs/yaml/functions/executable.yaml | 10 ++++ mesonbuild/backend/ninjabackend.py | 2 + mesonbuild/backend/vs2010backend.py | 2 +- mesonbuild/build.py | 46 +++++++++++-------- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + .../9 vs module defs generated/exe.def | 2 + .../9 vs module defs generated/meson.build | 2 +- .../windows/9 vs module defs generated/prog.c | 6 ++- 10 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 docs/markdown/snippets/executable_vs_module_defs.md create mode 100644 test cases/windows/9 vs module defs generated/exe.def diff --git a/docs/markdown/snippets/executable_vs_module_defs.md b/docs/markdown/snippets/executable_vs_module_defs.md new file mode 100644 index 000000000000..79017488d09f --- /dev/null +++ b/docs/markdown/snippets/executable_vs_module_defs.md @@ -0,0 +1,4 @@ +## Executable gains vs_module_defs keyword + +This allows using a .def file to control which functions an [[executable]] will +expose to a [[shared_module]]. diff --git a/docs/yaml/functions/executable.yaml b/docs/yaml/functions/executable.yaml index cdf764a07387..38075945782c 100644 --- a/docs/yaml/functions/executable.yaml +++ b/docs/yaml/functions/executable.yaml @@ -44,3 +44,13 @@ kwargs: type: bool since: 0.49.0 description: Build a position-independent executable. + + vs_module_defs: + type: str | file | custom_tgt | custom_idx + since: 1.3.0 + description: | + Specify a Microsoft module definition file for controlling symbol exports, + etc., on platforms where that is possible (e.g. Windows). + + This can be used to expose which functions a shared_module loaded by an + executable will be allowed to use. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 925941a965ac..04f3505f41b1 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3248,6 +3248,8 @@ def get_target_type_link_args(self, target, linker): commands += linker.gen_import_library_args(self.get_import_filename(target)) if target.pie: commands += linker.get_pie_link_args() + if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): + commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): commands += linker.get_std_shared_module_link_args(target.get_options()) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 0b6be1c79aad..fd19ff3d37cd 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1530,7 +1530,7 @@ def add_non_makefile_vcxproj_elements( # DLLs built with MSVC always have an import library except when # they're data-only DLLs, but we don't support those yet. ET.SubElement(link, 'ImportLibrary').text = target.get_import_filename() - if isinstance(target, build.SharedLibrary): + if isinstance(target, (build.SharedLibrary, build.Executable)): # Add module definitions file, if provided if target.vs_module_defs: relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 10f226117359..013733561ca7 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -114,7 +114,7 @@ rust_kwargs | cs_kwargs) -known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} +known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie', 'vs_module_defs'} known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'} known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'} known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'} @@ -1702,6 +1702,28 @@ def check_module_linking(self): 'use shared_library() with `override_options: [\'b_lundef=false\']` instead.') link_target.force_soname = True + def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None: + if kwargs.get('vs_module_defs') is None: + return + + path: T.Union[str, File, CustomTarget, CustomTargetIndex] = kwargs['vs_module_defs'] + if isinstance(path, str): + if os.path.isabs(path): + self.vs_module_defs = File.from_absolute_file(path) + else: + self.vs_module_defs = File.from_source_file(self.environment.source_dir, self.subdir, path) + elif isinstance(path, File): + # When passing a generated file. + self.vs_module_defs = path + elif isinstance(path, (CustomTarget, CustomTargetIndex)): + # When passing output of a Custom Target + self.vs_module_defs = File.from_built_file(path.get_subdir(), path.get_filename()) + else: + raise InvalidArguments( + 'vs_module_defs must be either a string, ' + 'a file object, a Custom Target, or a Custom Target Index') + self.process_link_depends(path) + class FileInTargetPrivateDir: """Represents a file with the path '/path/to/build/target_private_dir/fname'. target_private_dir is the return value of get_target_private_dir which is e.g. 'subdir/target.p'. @@ -1925,6 +1947,9 @@ def __init__( # Remember that this exe was returned by `find_program()` through an override self.was_returned_by_find_program = False + self.vs_module_defs: T.Optional[File] = None + self.process_vs_module_defs_kw(kwargs) + def post_init(self) -> None: super().post_init() machine = self.environment.machines[self.for_machine] @@ -2321,24 +2346,7 @@ def process_kwargs(self, kwargs): self.darwin_versions = (self.soversion, self.soversion) # Visual Studio module-definitions file - if kwargs.get('vs_module_defs') is not None: - path = kwargs['vs_module_defs'] - if isinstance(path, str): - if os.path.isabs(path): - self.vs_module_defs = File.from_absolute_file(path) - else: - self.vs_module_defs = File.from_source_file(self.environment.source_dir, self.subdir, path) - elif isinstance(path, File): - # When passing a generated file. - self.vs_module_defs = path - elif isinstance(path, (CustomTarget, CustomTargetIndex)): - # When passing output of a Custom Target - self.vs_module_defs = File.from_built_file(path.get_subdir(), path.get_filename()) - else: - raise InvalidArguments( - 'Shared library vs_module_defs must be either a string, ' - 'a file object, a Custom Target, or a Custom Target Index') - self.process_link_depends(path) + self.process_vs_module_defs_kw(kwargs) rust_abi = kwargs.get('rust_abi') rust_crate_type = kwargs.get('rust_crate_type') diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index cbe440513f6e..26fe28cf0e7f 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -341,6 +341,7 @@ class _LibraryMixin(TypedDict): class Executable(_BuildTarget): gui_app: T.Optional[bool] + vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] win_subsystem: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 0d0267d54f30..6e105410a235 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -601,6 +601,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup EXECUTABLE_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, + _VS_MODULE_DEFS_KW.evolve(since='1.3.0', since_values=None), ] # Arguments exclusive to library types diff --git a/test cases/windows/9 vs module defs generated/exe.def b/test cases/windows/9 vs module defs generated/exe.def new file mode 100644 index 000000000000..9031a843dc61 --- /dev/null +++ b/test cases/windows/9 vs module defs generated/exe.def @@ -0,0 +1,2 @@ +EXPORTS + exefunc diff --git a/test cases/windows/9 vs module defs generated/meson.build b/test cases/windows/9 vs module defs generated/meson.build index 7728ca77a050..fd064420d740 100644 --- a/test cases/windows/9 vs module defs generated/meson.build +++ b/test cases/windows/9 vs module defs generated/meson.build @@ -1,5 +1,5 @@ project('generated_dll_module_defs', 'c') subdir('subdir') -exe = executable('prog', 'prog.c', link_with : shlib) +exe = executable('prog', 'prog.c', link_with : shlib, vs_module_defs : 'exe.def') test('runtest', exe) diff --git a/test cases/windows/9 vs module defs generated/prog.c b/test cases/windows/9 vs module defs generated/prog.c index 066ac227a717..4466a8c85935 100644 --- a/test cases/windows/9 vs module defs generated/prog.c +++ b/test cases/windows/9 vs module defs generated/prog.c @@ -1,5 +1,9 @@ int somedllfunc(void); +int exefunc(void) { + return 42; +} + int main(void) { - return somedllfunc() == 42 ? 0 : 1; + return somedllfunc() == exefunc() ? 0 : 1; } From fc45b57cf9f81f47c0f166dd45628d4254c71b93 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 28 Sep 2023 18:35:14 -0400 Subject: [PATCH 284/855] fix regression that broke sanity checking of jar sources In commit dd22546bdd5b7de34025437ae1360f6dd20491eb the various typed_pos_args for different BuildTarget functions was refactored into a common tuple of types. It overlooked the fact that jar specifically does NOT accept the same types, and began to allow passing structured_sources in. --- mesonbuild/interpreter/interpreter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 8950f0c445f8..3093ad2efa15 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1859,10 +1859,10 @@ def func_library(self, node: mparser.BaseNode, return self.build_library(node, args, kwargs) @permittedKwargs(build.known_jar_kwargs) - @typed_pos_args('jar', str, varargs=SOURCES_VARARGS) + @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) @typed_kwargs('jar', *JAR_KWS, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, - args: T.Tuple[str, SourcesVarargsType], + args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], kwargs: kwtypes.Jar) -> build.Jar: return self.build_target(node, args, kwargs, build.Jar) From 6402f53a13cdcd103b92ab6ef8dec9bf323a9e2c Mon Sep 17 00:00:00 2001 From: Xiang Gao Date: Wed, 27 Sep 2023 15:57:46 -0700 Subject: [PATCH 285/855] Allow share/cmake/ as cmake_prefix_path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to allow passing the path share/cmake/ as cmake_prefix_path. This is a case supported by cmake and is relied on by PyTorch. The cmake prefix of PyTorch can be found by running: python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)' you will see something like below from the above command: /home/gaoxiang/.virtualenvs/nvfuser/lib/python3.11/site-packages/torch/share/cmake Inspecting this directory: ❯ tree /home/gaoxiang/.virtualenvs/nvfuser/lib/python3.11/site-packages/torch/share/cmake /home/gaoxiang/.virtualenvs/nvfuser/lib/python3.11/site-packages/torch/share/cmake ├── ATen │   └── ATenConfig.cmake ├── Caffe2 │   ├── Caffe2Config.cmake │   ├── Caffe2Targets.cmake │   ├── Caffe2Targets-release.cmake │   ├── FindCUDAToolkit.cmake │   ├── FindCUSPARSELT.cmake │   ├── Modules_CUDA_fix │   │   ├── FindCUDA.cmake │   │   ├── FindCUDNN.cmake │   │   └── upstream │   │   ├── CMakeInitializeConfigs.cmake │   │   ├── FindCUDA │   │   │   ├── make2cmake.cmake │   │   │   ├── parse_cubin.cmake │   │   │   ├── run_nvcc.cmake │   │   │   └── select_compute_arch.cmake │   │   ├── FindCUDA.cmake │   │   ├── FindPackageHandleStandardArgs.cmake │   │   └── FindPackageMessage.cmake │   └── public │   ├── cuda.cmake │   ├── gflags.cmake │   ├── glog.cmake │   ├── LoadHIP.cmake │   ├── mkl.cmake │   ├── mkldnn.cmake │   ├── protobuf.cmake │   └── utils.cmake ├── Tensorpipe │   ├── TensorpipeTargets.cmake │   └── TensorpipeTargets-release.cmake └── Torch ├── TorchConfig.cmake └── TorchConfigVersion.cmake 9 directories, 28 files However, meson currently filters this directory out by `_preliminary_find_check`. As a result, doing torch_dep = dependency('Torch') will fail, even if you set `cmake_prefix_path` with the value returned by PyTorch. Possibly related issues: https://stackoverflow.com/questions/68884434/libtorch-c-meson-dependency https://github.com/mesonbuild/meson/issues/9740 https://discuss.pytorch.org/t/libtorch-meson-build/139648 --- mesonbuild/dependencies/cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 5263e5643431..46a58c13456b 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -226,7 +226,7 @@ def process_paths(l: T.List[str]) -> T.Set[str]: module_paths = [x for x in module_paths if os.path.isdir(x)] archs = temp_parser.get_cmake_var('MESON_ARCH_LIST') - common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share'] + common_paths = ['lib', 'lib32', 'lib64', 'libx32', 'share', ''] for i in archs: common_paths += [os.path.join('lib', i)] From c84dcd309d45ffe4d3257ea5d7f4335ee81c9247 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Sat, 29 Jul 2023 21:30:10 -0700 Subject: [PATCH 286/855] interpreter: use typed_kwargs for executable(export_dynamic) --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 26fe28cf0e7f..80ded8c33841 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -340,6 +340,7 @@ class _LibraryMixin(TypedDict): class Executable(_BuildTarget): + export_dynamic: bool gui_app: T.Optional[bool] vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] win_subsystem: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 6e105410a235..f6df868ba4ac 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -588,6 +588,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # Arguments exclusive to Executable. These are separated to make integrating # them into build_target easier _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ + KwargInfo('export_dynamic', bool, default=False, since='0.45.0'), KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead"), KwargInfo( 'win_subsystem', From 2ded5a8faaded8c3cf943163fb03e948ef691bfb Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 11:15:02 -0700 Subject: [PATCH 287/855] interpreter: use typed_kwargs for executable's "pie" keyword argument --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 80ded8c33841..9a71d468c348 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -342,6 +342,7 @@ class Executable(_BuildTarget): export_dynamic: bool gui_app: T.Optional[bool] + pie: T.Optional[bool] vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] win_subsystem: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index f6df868ba4ac..e63fda052743 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -590,6 +590,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ KwargInfo('export_dynamic', bool, default=False, since='0.45.0'), KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead"), + KwargInfo('pie', (bool, NoneType)), KwargInfo( 'win_subsystem', (str, NoneType), From c9bdf441dd5e9d910069fb7dc7a8efe391b5ae07 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 11:18:23 -0700 Subject: [PATCH 288/855] interpreter: use typed_kwargs for executable's "implib" keyword argument --- mesonbuild/interpreter/interpreter.py | 1 - mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 3093ad2efa15..794d2533b9e1 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1806,7 +1806,6 @@ def func_dependency(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kw def func_disabler(self, node, args, kwargs): return Disabler() - @FeatureNewKwargs('executable', '0.42.0', ['implib']) @permittedKwargs(build.known_exe_kwargs) @typed_pos_args('executable', str, varargs=SOURCES_VARARGS) @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 9a71d468c348..d0bfbc434863 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -342,6 +342,7 @@ class Executable(_BuildTarget): export_dynamic: bool gui_app: T.Optional[bool] + implib: T.Optional[T.Union[str, bool]] pie: T.Optional[bool] vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] win_subsystem: T.Optional[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index e63fda052743..3487a09d08db 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -590,6 +590,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ KwargInfo('export_dynamic', bool, default=False, since='0.45.0'), KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead"), + KwargInfo('implib', (bool, str, NoneType), since='0.42.0'), KwargInfo('pie', (bool, NoneType)), KwargInfo( 'win_subsystem', From 937aab09c0971276da9dee239505c1233562708e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 11:40:53 -0700 Subject: [PATCH 289/855] interpreter: handle implib/export_dynamic conflicts in the interpreter This differentiates export_dynamic being explicitly set to False from it being unset. This allows us to deprecate explicitly setting export_dynamic to false, but setting implib. This is already the case in the other direction, if implib is False but export_dynamic is enabled then we get a hard error. This also moves the validation up to the Interpreter and out of the build level. --- mesonbuild/build.py | 4 ---- mesonbuild/interpreter/interpreter.py | 16 ++++++++++++++++ mesonbuild/interpreter/kwargs.py | 2 +- mesonbuild/interpreter/type_checking.py | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 013733561ca7..621b6c780b12 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1938,10 +1938,6 @@ def __init__( self.implib = kwargs.get('implib') if not isinstance(self.implib, (bool, str, type(None))): raise InvalidArguments('"export_dynamic" keyword argument must be a boolean or string') - if self.implib: - self.export_dynamic = True - if self.export_dynamic and self.implib is False: - raise InvalidArguments('"implib" keyword argument must not be false for if "export_dynamic" is true') # Only linkwithable if using export_dynamic self.is_linkwithable = self.export_dynamic # Remember that this exe was returned by `find_program()` through an override diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 794d2533b9e1..cd3c5a59bef1 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3327,6 +3327,7 @@ def build_target_decorator_caller(self, node, args, kwargs): kwargs['include_directories'] = self.extract_incdirs(kwargs) if targetclass is build.Executable: + kwargs = T.cast('kwtypes.Executable', kwargs) if kwargs['gui_app'] is not None: if kwargs['win_subsystem'] is not None: raise InvalidArguments.from_node( @@ -3337,6 +3338,21 @@ def build_target_decorator_caller(self, node, args, kwargs): if kwargs['win_subsystem'] is None: kwargs['win_subsystem'] = 'console' + if kwargs['implib']: + if kwargs['export_dynamic'] is False: + FeatureDeprecated.single_use('implib overrides explict export_dynamic off', '1.3.0', self.subprojct, + 'Do not set ths if want export_dynamic disabled if implib is enabled', + location=node) + kwargs['export_dynamic'] = True + elif kwargs['export_dynamic']: + if kwargs['implib'] is False: + raise InvalidArguments('"implib" keyword" must not be false if "export_dynamic" is set and not false.') + kwargs['implib'] = True + if kwargs['export_dynamic'] is None: + kwargs['export_dynamic'] = False + if kwargs['implib'] is None: + kwargs['implib'] = False + target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, self.environment, self.compilers[for_machine], kwargs) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index d0bfbc434863..015886ecf614 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -340,7 +340,7 @@ class _LibraryMixin(TypedDict): class Executable(_BuildTarget): - export_dynamic: bool + export_dynamic: T.Optional[bool] gui_app: T.Optional[bool] implib: T.Optional[T.Union[str, bool]] pie: T.Optional[bool] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 3487a09d08db..4fb11c497924 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -588,7 +588,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # Arguments exclusive to Executable. These are separated to make integrating # them into build_target easier _EXCLUSIVE_EXECUTABLE_KWS: T.List[KwargInfo] = [ - KwargInfo('export_dynamic', bool, default=False, since='0.45.0'), + KwargInfo('export_dynamic', (bool, NoneType), since='0.45.0'), KwargInfo('gui_app', (bool, NoneType), deprecated='0.56.0', deprecated_message="Use 'win_subsystem' instead"), KwargInfo('implib', (bool, str, NoneType), since='0.42.0'), KwargInfo('pie', (bool, NoneType)), From 184927eaf57042d617c18ca76c05b147952f745a Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Fri, 29 Sep 2023 22:25:46 -0500 Subject: [PATCH 290/855] Update Users.md --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index c06f376afc08..7aef3221995b 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -161,6 +161,7 @@ format files - [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 - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code + - [Trilobite XCore](https://github.com/trilobite-stdlib/trilo-xcore-c), a core essential library for C code - [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 d7b25662ce5c7f9831b003581054e174b97c4865 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 30 Sep 2023 15:03:36 +0200 Subject: [PATCH 291/855] find_tool: don't assume the pkgconfig variable is a valid command ExternalProgram currently assumes that if a command is passed it exists and can be used as is. In case we extract the path from pkgconfig the path might not exist, on Windows it might be missing the ".exe" suffix. By passing the variables as a name ExternalProgram will validate that the command exists at configure time and will fail if not, and it will try to fixup the command by appending .exe etc. Fixes #12271 --- mesonbuild/modules/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index eef67a1c7431..a1aa2334495a 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -112,7 +112,7 @@ def find_tool(self, name: str, depname: str, varname: str, required: bool = True if dep.found() and dep.type_name == 'pkgconfig': value = dep.get_variable(pkgconfig=varname) if value: - return ExternalProgram(name, [value]) + return ExternalProgram(value) # Normal program lookup return self.find_program(name, required=required, wanted=wanted) From 9bccc96c4ee35328a48e1991cc5d18dc53572ed3 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 29 Sep 2023 14:02:52 +0300 Subject: [PATCH 292/855] Mangle dashes as needed by WiX. --- packaging/createmsi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/createmsi.py b/packaging/createmsi.py index 6f198f3088b6..fef2b38759d0 100755 --- a/packaging/createmsi.py +++ b/packaging/createmsi.py @@ -291,7 +291,7 @@ def create_xml(self, nodes, current_dir, parent_xml_node, staging_dir): }) for dirname in cur_node.dirs: - dir_id = os.path.join(current_dir, dirname).replace('\\', '_').replace('/', '_') + dir_id = os.path.join(current_dir, dirname).replace('\\', '_').replace('/', '_').replace('-', '_') dir_node = ET.SubElement(parent_xml_node, 'Directory', { 'Id': dir_id, 'Name': dirname, From 710a753c78077220b13a9f7e999dcdb61339efb1 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Mon, 2 Oct 2023 13:46:39 -0700 Subject: [PATCH 293/855] nasm tests: skip asm language test on Solaris & illumos The code in this test to make Linux system calls is not compatible with the SunOS kernel system call conventions. --- test cases/nasm/2 asm language/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test cases/nasm/2 asm language/meson.build b/test cases/nasm/2 asm language/meson.build index 0eecd99a648b..d025d43ea9b7 100644 --- a/test cases/nasm/2 asm language/meson.build +++ b/test cases/nasm/2 asm language/meson.build @@ -7,6 +7,8 @@ endif if host_machine.system() == 'windows' error('MESON_SKIP_TEST: this test asm is not made for Windows') +elif host_machine.system() == 'sunos' + error('MESON_SKIP_TEST: this test asm is not made for Solaris or illumos') endif if meson.backend().startswith('vs') From 9f610ad5b72ea91de2d7aeb6f3266d0a7477062e Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 8 Sep 2023 16:54:48 -0400 Subject: [PATCH 294/855] python dependency: ensure that setuptools doesn't inject itself into distutils We do not use setuptools for anything, and only lightly use distutils. Unpredictable issues can occur due to setuptools monkey-patching, which interferes with our intended use. Tell setuptools to simply never get involved. Note: while it's otherwise possible to check if the probe is run using sys.executable and avoid forking, setuptools unconditionally injects itself at startup in a way that requires subprocess isolation to disable. --- mesonbuild/dependencies/python.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index efb904eca471..fe778aff6c90 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -115,7 +115,9 @@ def sanity(self) -> bool: with importlib.resources.path('mesonbuild.scripts', 'python_info.py') as f: cmd = self.get_command() + [str(f)] - p, stdout, stderr = mesonlib.Popen_safe(cmd) + env = os.environ.copy() + env['SETUPTOOLS_USE_DISTUTILS'] = 'stdlib' + p, stdout, stderr = mesonlib.Popen_safe(cmd, env=env) try: info = json.loads(stdout) From 40f897fa92f7d3cc43788d3000733310ce77cf0c Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 21 Nov 2022 20:47:14 -0500 Subject: [PATCH 295/855] python module: stop using distutils schemes on sufficiently new Debian Since 3.10.3, Debian finally started patching sysconfig with custom paths, instead of just distutils. This means we can now go use that instead. It reduces our reliance on the deprecated distutils module. Partial fix for #7702 --- mesonbuild/scripts/python_info.py | 32 +++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/mesonbuild/scripts/python_info.py b/mesonbuild/scripts/python_info.py index 0f7787c3ff21..e62bf0e40661 100755 --- a/mesonbuild/scripts/python_info.py +++ b/mesonbuild/scripts/python_info.py @@ -13,7 +13,6 @@ del sys.path[0] import json, os, sysconfig -import distutils.command.install def get_distutils_paths(scheme=None, prefix=None): import distutils.dist @@ -37,15 +36,32 @@ def get_distutils_paths(scheme=None, prefix=None): # default scheme to a custom one pointing to /usr/local and replacing # site-packages with dist-packages. # See https://github.com/mesonbuild/meson/issues/8739. -# XXX: We should be using sysconfig, but Debian only patches distutils. +# +# We should be using sysconfig, but before 3.10.3, Debian only patches distutils. +# So we may end up falling back. -if 'deb_system' in distutils.command.install.INSTALL_SCHEMES: - paths = get_distutils_paths(scheme='deb_system') - install_paths = get_distutils_paths(scheme='deb_system', prefix='') -else: - paths = sysconfig.get_paths() +def get_install_paths(): + if sys.version_info >= (3, 10): + scheme = sysconfig.get_default_scheme() + else: + scheme = sysconfig._get_default_scheme() + + if sys.version_info >= (3, 10, 3): + if 'deb_system' in sysconfig.get_scheme_names(): + scheme = 'deb_system' + else: + import distutils.command.install + if 'deb_system' in distutils.command.install.INSTALL_SCHEMES: + paths = get_distutils_paths(scheme='deb_system') + install_paths = get_distutils_paths(scheme='deb_system', prefix='') + return paths, install_paths + + paths = sysconfig.get_paths(scheme=scheme) empty_vars = {'base': '', 'platbase': '', 'installed_base': ''} - install_paths = sysconfig.get_paths(vars=empty_vars) + install_paths = sysconfig.get_paths(scheme=scheme, vars=empty_vars) + return paths, install_paths + +paths, install_paths = get_install_paths() def links_against_libpython(): from distutils.core import Distribution, Extension From 3d3a10ef022284c8377bd9f8e1b1adec73c50d95 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 2 Oct 2023 16:40:15 -0400 Subject: [PATCH 296/855] python module: refactor pypy detection into a consistent variable --- mesonbuild/scripts/python_info.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/scripts/python_info.py b/mesonbuild/scripts/python_info.py index e62bf0e40661..d14f21fcee38 100755 --- a/mesonbuild/scripts/python_info.py +++ b/mesonbuild/scripts/python_info.py @@ -72,6 +72,8 @@ def links_against_libpython(): variables = sysconfig.get_config_vars() variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)}) +is_pypy = '__pypy__' in sys.builtin_module_names + if sys.version_info < (3, 0): suffix = variables.get('SO') elif sys.version_info < (3, 8, 7): @@ -92,7 +94,7 @@ def links_against_libpython(): # pypy supports modules targetting the limited api but # does not use a special suffix to distinguish them: # https://doc.pypy.org/en/latest/cpython_differences.html#permitted-abi-tags-in-extensions -if '__pypy__' in sys.builtin_module_names: +if is_pypy: limited_api_suffix = suffix print(json.dumps({ @@ -102,7 +104,7 @@ def links_against_libpython(): 'install_paths': install_paths, 'version': sysconfig.get_python_version(), 'platform': sysconfig.get_platform(), - 'is_pypy': '__pypy__' in sys.builtin_module_names, + 'is_pypy': is_pypy, 'is_venv': sys.prefix != variables['base_prefix'], 'link_libpython': links_against_libpython(), 'suffix': suffix, From 2d6c10908b3771216e7ce086af1ee4dc77e698c2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 22 Nov 2022 22:56:10 -0500 Subject: [PATCH 297/855] python module: stop using distutils "link to libpython" probe on recent python On python >=3.8, this information is expected to be encoded in the sysconfig vars. In distutils, it is always necessary to link to libpython on Windows; for posix platforms, it depends on the value of LIBPYTHON (which is the library to link to, possibly the empty string) as generated by configure.ac and embedded into python.pc and python-config.sh, and then coded a second time in the distutils python sources. There are a couple of caveats which have ramifications for Cygwin and Android: - python.pc and python-config.sh disagree with distutils when python is not built shared. In that case, the former act the same as a shared build, while the latter *never* links to libpython - python.pc disagrees with python-config.sh and distutils when python is built shared. The former never links to libpython, while the latter do The disagreement is resolved in favor of distutils' behavior in all cases, and python.pc is correct for our purposes on python 3.12; see: https://github.com/python/cpython/pull/100356 https://github.com/python/cpython/pull/100967 Although it was not backported to older releases, Cygwin at least has always patched in a fix for python.pc, which behavior is now declared canonical. We can reliably assume it is always correct. This is the other half of the fix for #7702 --- mesonbuild/scripts/python_info.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mesonbuild/scripts/python_info.py b/mesonbuild/scripts/python_info.py index d14f21fcee38..5b048ca4288a 100755 --- a/mesonbuild/scripts/python_info.py +++ b/mesonbuild/scripts/python_info.py @@ -64,10 +64,19 @@ def get_install_paths(): paths, install_paths = get_install_paths() def links_against_libpython(): - from distutils.core import Distribution, Extension - cmd = Distribution().get_command_obj('build_ext') - cmd.ensure_finalized() - return bool(cmd.get_libraries(Extension('dummy', []))) + # on versions supporting python-embed.pc, this is the non-embed lib + # + # PyPy is not yet up to 3.12 and work is still pending to export the + # relevant information (it doesn't automatically provide arbitrary + # Makefile vars) + if sys.version_info >= (3, 8) and not is_pypy: + variables = sysconfig.get_config_vars() + return bool(variables.get('LIBPYTHON', 'yes')) + else: + from distutils.core import Distribution, Extension + cmd = Distribution().get_command_obj('build_ext') + cmd.ensure_finalized() + return bool(cmd.get_libraries(Extension('dummy', []))) variables = sysconfig.get_config_vars() variables.update({'base_prefix': getattr(sys, 'base_prefix', sys.prefix)}) From ecf261330c498783760cbde00b613b7469f8d3c0 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 2 Oct 2023 23:51:57 -0400 Subject: [PATCH 298/855] tests: fix test case to not import distutils on python 3.12 Testing the correctness of the `modules: ` kwarg can be done with other guaranteed stdlib modules that are even more guaranteed since they didn't get deprecated for removal. --- test cases/python/5 modules kwarg/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/python/5 modules kwarg/meson.build b/test cases/python/5 modules kwarg/meson.build index 9751adaaba2b..41a9a4faee9a 100644 --- a/test cases/python/5 modules kwarg/meson.build +++ b/test cases/python/5 modules kwarg/meson.build @@ -1,7 +1,7 @@ project('python kwarg') py = import('python') -prog_python = py.find_installation('python3', modules : ['distutils']) +prog_python = py.find_installation('python3', modules : ['os', 'sys', 're']) assert(prog_python.found() == true, 'python not found when should be') prog_python = py.find_installation('python3', modules : ['thisbetternotexistmod'], required : false) assert(prog_python.found() == false, 'python not found but reported as found') From 880f21281ee359e01de659fe7d45549d19e6b84d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 3 Oct 2023 00:22:25 -0400 Subject: [PATCH 299/855] mark the PyPI metadata as supporting python 3.12 meson itself runs okay on 3.12, and the last issue for *probing* against 3.12 is solved. Tests pass here locally. --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index dfaba76dd194..2f2962eedcba 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Topic :: Software Development :: Build Tools long_description = Meson is a cross-platform build system designed to be both as fast and as user friendly as possible. It supports many languages and compilers, including GCC, Clang, PGI, Intel, and Visual Studio. Its build definitions are written in a simple non-Turing complete DSL. From 4589e155473b73abfb9d9d24df76246d591fa259 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 3 Oct 2023 11:48:46 -0400 Subject: [PATCH 300/855] temp disable pylint falsepositive on dub.py This was introduced by pylint 3.0.0. See https://github.com/pylint-dev/pylint/issues/9095. --- mesonbuild/dependencies/dub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/dub.py b/mesonbuild/dependencies/dub.py index 37a9ea11e5eb..c206ce9e73bf 100644 --- a/mesonbuild/dependencies/dub.py +++ b/mesonbuild/dependencies/dub.py @@ -53,7 +53,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. self.is_found = False return - (self.dubbin, dubver) = DubDependency.class_dubbin + (self.dubbin, dubver) = DubDependency.class_dubbin # pylint: disable=unpacking-non-sequence assert isinstance(self.dubbin, ExternalProgram) From 59a34330f688aa466ae5a399e76157ec8563ee3b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 3 Oct 2023 01:19:13 -0400 Subject: [PATCH 301/855] CI: install an older java on opensuse They do not appear to have 20 in their repos anymore, and no traces can be found of it in the history, as usual. They do have 11, 17, and 21. Last time we chose one randomly and hoped it doesn't keep changing value. This dismally failed: 20 was upgraded to 21. It looks like 17 may have some staying power. --- ci/ciimage/opensuse/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/opensuse/install.sh b/ci/ciimage/opensuse/install.sh index 40c109ce9055..b0097172a8a9 100755 --- a/ci/ciimage/opensuse/install.sh +++ b/ci/ciimage/opensuse/install.sh @@ -9,7 +9,7 @@ pkgs=( ninja make git autoconf automake patch libjpeg-devel elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-obj-c++ vala rust bison flex curl lcov mono-core gtkmm3-devel gtest gmock protobuf-devel wxGTK3-3_2-devel gobject-introspection-devel - itstool gtk3-devel java-20-openjdk-devel gtk-doc llvm-devel clang-devel libSDL2-devel graphviz-devel zlib-devel zlib-devel-static + itstool gtk3-devel java-17-openjdk-devel gtk-doc llvm-devel clang-devel libSDL2-devel graphviz-devel zlib-devel zlib-devel-static #hdf5-devel netcdf-devel libscalapack2-openmpi3-devel libscalapack2-gnu-openmpi3-hpc-devel openmpi3-devel doxygen vulkan-devel vulkan-validationlayers openssh mercurial gtk-sharp3-complete gtk-sharp2-complete libpcap-devel libgpgme-devel libqt5-qtbase-devel libqt5-qttools-devel libqt5-linguist libqt5-qtbase-private-headers-devel From 1f000de55ac96648c74775d2e3a49ae99e92d949 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 3 Oct 2023 11:20:50 -0400 Subject: [PATCH 302/855] CI: fix broken ciimage builder script failing to correctly copy meson Regression in commit 0af126fec798d6dbb0d1ad52168cc1f3f1758acd. We added support for some "test cases/" stuff that actually relies on test files being a symlink, but when testing the image builder, we copied the meson repository contents into the docker container without telling python that it is in fact super important to copy symlinks as symlinks. As a result, the tests themselves ran fine when merging, but caused the image builder to thereafter fail. --- ci/ciimage/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py index 559723c0c1cc..b9d318158411 100755 --- a/ci/ciimage/build.py +++ b/ci/ciimage/build.py @@ -143,13 +143,14 @@ def copy_meson(self) -> None: shutil.copytree( self.meson_root, self.temp_dir / 'meson', + symlinks=True, ignore=shutil.ignore_patterns( '.git', '*_cache', '__pycache__', # 'work area', self.temp_dir.name, - ) + ), ) def do_test(self, tty: bool = False) -> None: From 7143a695fd0e62149eca62bd1fc00e8c92d80202 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 3 Oct 2023 11:43:28 -0400 Subject: [PATCH 303/855] CI: fix the fix for python actually being mildly useful In commit 5c479d7a13a518c18ccb4dc3b6bdd7bfc2a9bdb5, we deleted bad stuff that makes python not work. But we missed the case where it is installed to lib64. --- ci/ciimage/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ciimage/common.sh b/ci/ciimage/common.sh index 6209ef9a1c08..67d59978f5a7 100644 --- a/ci/ciimage/common.sh +++ b/ci/ciimage/common.sh @@ -39,11 +39,11 @@ dub_fetch() { } install_minimal_python_packages() { - rm -f /usr/lib/python3.*/EXTERNALLY-MANAGED + rm -f /usr/lib*/python3.*/EXTERNALLY-MANAGED python3 -m pip install "${base_python_pkgs[@]}" $* } install_python_packages() { - rm -f /usr/lib/python3.*/EXTERNALLY-MANAGED + rm -f /usr/lib*/python3.*/EXTERNALLY-MANAGED python3 -m pip install "${base_python_pkgs[@]}" "${python_pkgs[@]}" $* } From dec4f72da465b37414216aae12ee6d9ce7cbf079 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Tue, 3 Oct 2023 21:56:28 +0200 Subject: [PATCH 304/855] clike compilers: use MesonBugException instead of AssertionError Follow-up to #12223 --- 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 38af08c42c26..b3c80d44060c 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -697,7 +697,7 @@ def get_define(self, dname: str, prefix: str, env: 'Environment', star_idx = p.stdout.find(delim_start) end_idx = p.stdout.rfind(delim_end) if (star_idx == -1) or (end_idx == -1) or (star_idx == end_idx): - raise AssertionError('BUG: Delimiters not found in preprocessor output!') + raise mesonlib.MesonBugException('Delimiters not found in preprocessor output.') define_value = p.stdout[star_idx + len(delim_start):end_idx] if define_value == sentinel_undef: From 00007e197ef7fa2c83fe8dcd4b9084afa5a7bb55 Mon Sep 17 00:00:00 2001 From: Marvin Scholz Date: Tue, 3 Oct 2023 21:59:07 +0200 Subject: [PATCH 305/855] test: get_define: do not use assert incorrectly This should be an error, not an assert as it asserts nothing, in fact, if this wouldn't error out because of the wrong type passed to the assert, it would even do the wrong thing. Follow-up to #12223 --- test cases/common/132 get define/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/common/132 get define/meson.build b/test cases/common/132 get define/meson.build index 019b17afc933..66ac3f9ebc29 100644 --- a/test cases/common/132 get define/meson.build +++ b/test cases/common/132 get define/meson.build @@ -43,7 +43,7 @@ foreach lang : ['c', 'cpp'] elif system_define.length() == 1 assert(def_val != '', '@0@ value is unset'.format(def_name)) else - assert('Invalid number of items in system_define array, this is a bug in the test!') + error('Invalid number of items in system_define array, this is a bug in the test!') endif if cc.find_library('z', required : false).found() From 922af7dfce1a57de9c56b4e5f6d2221524848822 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 11:02:08 -0700 Subject: [PATCH 306/855] interpreter: rename SOURCE_KW to DEPENDENCY_SOURCES_KW Since that's what this actually is. --- mesonbuild/interpreter/interpreter.py | 4 ++-- mesonbuild/interpreter/type_checking.py | 2 +- mesonbuild/modules/gnome.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index cd3c5a59bef1..a65647580b2a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -89,7 +89,7 @@ REQUIRED_KW, SHARED_LIB_KWS, SHARED_MOD_KWS, - SOURCES_KW, + DEPENDENCY_SOURCES_KW, SOURCES_VARARGS, STATIC_LIB_KWS, VARIABLES_KW, @@ -687,7 +687,7 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa INCLUDE_DIRECTORIES, LINK_WITH_KW, LINK_WHOLE_KW.evolve(since='0.46.0'), - SOURCES_KW, + DEPENDENCY_SOURCES_KW, KwargInfo('extra_files', ContainerTypeInfo(list, (mesonlib.File, str)), listify=True, default=[], since='1.2.0'), VARIABLES_KW.evolve(since='0.54.0', since_values={list: '0.56.0'}), KwargInfo('version', (str, NoneType)), diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 4fb11c497924..166cb58e9f0d 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -458,7 +458,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus validator=link_whole_validator, ) -SOURCES_KW: KwargInfo[T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]]] = KwargInfo( +DEPENDENCY_SOURCES_KW: KwargInfo[T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]]] = KwargInfo( 'sources', ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, GeneratedList)), listify=True, diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index b0bca1590955..d8367ddbe260 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -35,7 +35,7 @@ from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments from ..dependencies import Dependency, InternalDependency from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface -from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, SOURCES_KW, in_set_validator +from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, DEPENDENCY_SOURCES_KW, in_set_validator from ..interpreterbase import noPosargs, noKwargs, FeatureNew, FeatureDeprecated from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo from ..interpreterbase.decorators import typed_pos_args @@ -1593,7 +1593,7 @@ def gtkdoc_html_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'TYP @typed_kwargs( 'gnome.gdbus_codegen', _BUILD_BY_DEFAULT.evolve(since='0.40.0'), - SOURCES_KW.evolve(since='0.46.0'), + DEPENDENCY_SOURCES_KW.evolve(since='0.46.0'), KwargInfo('extra_args', ContainerTypeInfo(list, str), since='0.47.0', default=[], listify=True), KwargInfo('interface_prefix', (str, NoneType)), KwargInfo('namespace', (str, NoneType)), From c4458a9a693bfd0ccb23c5fbbfb7be6c4a008f82 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 28 Sep 2023 15:44:05 -0700 Subject: [PATCH 307/855] interpreter: add another overload of source_strings_to_files So that we can handle SourcesVarargsType --- mesonbuild/interpreter/interpreter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index a65647580b2a..a56e922e66d8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3103,6 +3103,9 @@ def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, @T.overload def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811 + @T.overload + def source_strings_to_files(self, sources: T.List[SourcesVarargsType], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811 + def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: # noqa: F811 """Lower inputs to a list of Targets and Files, replacing any strings. From 179355bf18f3c4216e8bb820fc19567e2a4bb640 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 28 Sep 2023 15:37:02 -0700 Subject: [PATCH 308/855] interpreter: use typed_kwargs for "sources" keyword argument of build targets --- mesonbuild/interpreter/interpreter.py | 4 ++-- mesonbuild/interpreter/kwargs.py | 4 +++- mesonbuild/interpreter/type_checking.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index a56e922e66d8..05581afebc8d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3265,8 +3265,8 @@ def build_target_decorator_caller(self, node, args, kwargs): # Silently force to native because that's the only sensible value # and rust_crate_type is deprecated any way. for_machine = MachineChoice.BUILD - if 'sources' in kwargs: - sources += listify(kwargs['sources']) + # Avoid mutating, since there could be other references to sources + sources = sources + kwargs['sources'] if any(isinstance(s, build.BuildTarget) for s in sources): FeatureBroken.single_use('passing references to built targets as a source file', '1.1.0', self.subproject, 'Consider using `link_with` or `link_whole` if you meant to link, or dropping them as otherwise they are ignored.', diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 015886ecf614..7396229db708 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -16,7 +16,7 @@ from ..mesonlib import EnvironmentVariables, MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram -from .type_checking import PkgConfigDefineType +from .type_checking import PkgConfigDefineType, SourcesVarargsType class FuncAddProjectArgs(TypedDict): @@ -332,6 +332,7 @@ class _BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" rust_dependency_map: T.Dict[str, str] + sources: SourcesVarargsType class _LibraryMixin(TypedDict): @@ -390,6 +391,7 @@ class Jar(_BaseBuildTarget): main_class: str java_resources: T.Optional[build.StructuredSources] + sources: T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget] class FuncDeclareDependency(TypedDict): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 166cb58e9f0d..27a05523f953 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -467,6 +467,13 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus SOURCES_VARARGS = (str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget) +BT_SOURCES_KW: KwargInfo[SourcesVarargsType] = KwargInfo( + 'sources', + ContainerTypeInfo(list, SOURCES_VARARGS), + listify=True, + default=[], +) + VARIABLES_KW: KwargInfo[T.Dict[str, str]] = KwargInfo( 'variables', # str is listified by validator/convertor, cannot use listify=True here because @@ -527,6 +534,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, + BT_SOURCES_KW, RUST_CRATE_TYPE_KW, KwargInfo( 'rust_dependency_map', @@ -665,6 +673,12 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup JAR_KWS = [ *_ALL_TARGET_KWS, *_EXCLUSIVE_JAR_KWS, + KwargInfo( + 'sources', + ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, GeneratedList, ExtractedObjects, BuildTarget)), + listify=True, + default=[], + ) ] # Arguments used by both_library and library From 54c30c96a041a33f708a36c7e5b2a4ecf096d3dc Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 9 Aug 2023 17:06:51 -0500 Subject: [PATCH 309/855] Remove unnecessary isinstance call This code predated typed_pos_args/typed_kwargs. --- mesonbuild/modules/sourceset.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py index c35416e5a800..ae594b5aa197 100644 --- a/mesonbuild/modules/sourceset.py +++ b/mesonbuild/modules/sourceset.py @@ -197,8 +197,6 @@ def add_all_method(self, state: ModuleState, args: T.Tuple[T.List[SourceSetImpl] raise InterpreterException('add_all called with both positional and keyword arguments') keys, dependencies = self.check_conditions(when) for s in if_true: - if not isinstance(s, SourceSetImpl): - raise InvalidCode('Arguments to \'add_all\' after the first must be source sets') s.frozen = True self.rules.append(SourceSetRule(keys, dependencies, [], [], if_true, [])) From 87993b8210bf923d7120c7442fe987cdb04e6b12 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 9 Aug 2023 19:30:52 -0500 Subject: [PATCH 310/855] Move modtest to the new extension module API --- mesonbuild/modules/modtest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/modules/modtest.py b/mesonbuild/modules/modtest.py index 15f823778618..5c2584061196 100644 --- a/mesonbuild/modules/modtest.py +++ b/mesonbuild/modules/modtest.py @@ -15,7 +15,7 @@ from __future__ import annotations import typing as T -from . import ExtensionModule, ModuleInfo +from . import NewExtensionModule, ModuleInfo from ..interpreterbase import noKwargs, noPosargs if T.TYPE_CHECKING: @@ -24,12 +24,12 @@ from ..interpreterbase.baseobjects import TYPE_kwargs, TYPE_var -class TestModule(ExtensionModule): +class TestModule(NewExtensionModule): INFO = ModuleInfo('modtest') def __init__(self, interpreter: Interpreter) -> None: - super().__init__(interpreter) + super().__init__() self.methods.update({ 'print_hello': self.print_hello, }) From 88b337b77c264d3f39744b3b3bea8a29778a73c4 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 10 Aug 2023 10:53:09 -0500 Subject: [PATCH 311/855] Remove unused code in interpreterbase --- mesonbuild/interpreterbase/__init__.py | 8 -------- mesonbuild/interpreterbase/baseobjects.py | 3 --- mesonbuild/interpreterbase/decorators.py | 16 ---------------- 3 files changed, 27 deletions(-) diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py index 3cb95303fbcd..8a2e0788ffc5 100644 --- a/mesonbuild/interpreterbase/__init__.py +++ b/mesonbuild/interpreterbase/__init__.py @@ -46,7 +46,6 @@ 'disablerIfNotFound', 'permittedKwargs', 'typed_operator', - 'unary_operator', 'typed_pos_args', 'ContainerTypeInfo', 'KwargInfo', @@ -62,9 +61,6 @@ 'SubProject', - 'TV_fw_var', - 'TV_fw_args', - 'TV_fw_kwargs', 'TV_func', 'TYPE_elementary', 'TYPE_var', @@ -85,9 +81,6 @@ MutableInterpreterObject, ContextManagerObject, - TV_fw_var, - TV_fw_args, - TV_fw_kwargs, TV_func, TYPE_elementary, TYPE_var, @@ -115,7 +108,6 @@ ContainerTypeInfo, KwargInfo, typed_operator, - unary_operator, typed_kwargs, FeatureCheckBase, FeatureNew, diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py index 4966978a0c2b..38b181e27324 100644 --- a/mesonbuild/interpreterbase/baseobjects.py +++ b/mesonbuild/interpreterbase/baseobjects.py @@ -35,9 +35,6 @@ class OperatorCall(Protocol[__T]): def __call__(self, other: __T) -> 'TYPE_var': ... -TV_fw_var = T.Union[str, int, bool, list, dict, 'InterpreterObject'] -TV_fw_args = T.List[T.Union[mparser.BaseNode, TV_fw_var]] -TV_fw_kwargs = T.Dict[str, T.Union[mparser.BaseNode, TV_fw_var]] TV_func = T.TypeVar('TV_func', bound=T.Callable[..., T.Any]) diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index 5bb8306a563b..17c6c8c8fdf8 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -142,22 +142,6 @@ def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var: return T.cast('_TV_FN_Operator', wrapper) return inner -def unary_operator(operator: MesonOperator) -> T.Callable[['_TV_FN_Operator'], '_TV_FN_Operator']: - """Decorator that does type checking for unary operator calls. - - This decorator is for unary operators that do not take any other objects. - It should be impossible for a user to accidentally break this. Triggering - this check always indicates a bug in the Meson interpreter. - """ - def inner(f: '_TV_FN_Operator') -> '_TV_FN_Operator': - @wraps(f) - def wrapper(self: 'InterpreterObject', other: TYPE_var) -> TYPE_var: - if other is not None: - raise mesonlib.MesonBugException(f'The unary operator `{operator.value}` of {self.display_name()} was passed the object {other} of type {type(other).__name__}') - return f(self, other) - return T.cast('_TV_FN_Operator', wrapper) - return inner - def typed_pos_args(name: str, *types: T.Union[T.Type, T.Tuple[T.Type, ...]], varargs: T.Optional[T.Union[T.Type, T.Tuple[T.Type, ...]]] = None, From 1991ad87061d068413cb6a593f3f29c9426df2b9 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 14 Aug 2023 17:51:51 -0500 Subject: [PATCH 312/855] Remove type comments in run_project_tests.py --- mesonbuild/cmake/common.py | 2 +- run_project_tests.py | 24 ++++++++++++------------ tools/cmake2meson.py | 4 ++-- unittests/internaltests.py | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mesonbuild/cmake/common.py b/mesonbuild/cmake/common.py index 415937ee9d3d..aa0bbbf0b4b0 100644 --- a/mesonbuild/cmake/common.py +++ b/mesonbuild/cmake/common.py @@ -209,7 +209,7 @@ def __init__(self, data: T.Dict[str, T.Any]) -> None: self.link_lang_flags = _flags_to_list(data.get('linkLanguageFlags', '')) # self.link_path = Path(data.get('linkPath', '')) self.type: str = data.get('type', 'EXECUTABLE') - # self.is_generator_provided = data.get('isGeneratorProvided', False) # type: bool + # self.is_generator_provided: bool = data.get('isGeneratorProvided', False) self.files: T.List[CMakeFileGroup] = [] for i in data.get('fileGroups', []): diff --git a/run_project_tests.py b/run_project_tests.py index 7413c6843033..7ff164086678 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -134,11 +134,11 @@ def __init__(self, raw: T.Dict[str, str]): self.path = raw['file'] self.typ = raw['type'] self.platform = raw.get('platform', None) - self.language = raw.get('language', 'c') # type: str + self.language = raw.get('language', 'c') - version = raw.get('version', '') # type: str + version = raw.get('version', '') if version: - self.version = version.split('.') # type: T.List[str] + self.version = version.split('.') else: # split on '' will return [''], we want an empty list though self.version = [] @@ -280,9 +280,9 @@ def __init__(self, path: Path, name: T.Optional[str], args: T.List[str], skip: b self.args = args self.skip = skip self.env = os.environ.copy() - self.installed_files = [] # type: T.List[InstalledFile] - self.do_not_set_opts = [] # type: T.List[str] - self.stdout = [] # type: T.List[T.Dict[str, str]] + self.installed_files: T.List[InstalledFile] = [] + self.do_not_set_opts: T.List[str] = [] + self.stdout: T.List[T.Dict[str, str]] = [] self.skip_category = skip_category self.skip_expected = False @@ -399,7 +399,7 @@ def platform_fix_name(fname: str, canonical_compiler: str, env: environment.Envi def validate_install(test: TestDef, installdir: Path, env: environment.Environment) -> str: ret_msg = '' - expected_raw = [] # type: T.List[Path] + expected_raw: T.List[Path] = [] for i in test.installed_files: try: expected_raw += i.get_paths(host_c_compiler, env, installdir) @@ -828,7 +828,7 @@ def load_test_json(t: TestDef, stdout_mandatory: bool, skip_category: bool = Fal test_def = json.loads(test_def_file.read_text(encoding='utf-8')) # Handle additional environment variables - env = {} # type: T.Dict[str, str] + env: T.Dict[str, str] = {} if 'env' in test_def: assert isinstance(test_def['env'], dict) env = test_def['env'] @@ -838,7 +838,7 @@ def load_test_json(t: TestDef, stdout_mandatory: bool, skip_category: bool = Fal env[key] = val # Handle installed files - installed = [] # type: T.List[InstalledFile] + installed: T.List[InstalledFile] = [] if 'installed' in test_def: installed = [InstalledFile(x) for x in test_def['installed']] @@ -848,7 +848,7 @@ def load_test_json(t: TestDef, stdout_mandatory: bool, skip_category: bool = Fal raise RuntimeError(f"{test_def_file} must contain a non-empty stdout key") # Handle the do_not_set_opts list - do_not_set_opts = test_def.get('do_not_set_opts', []) # type: T.List[str] + do_not_set_opts: T.List[str] = test_def.get('do_not_set_opts', []) (t.skip, t.skip_expected) = _skip_keys(test_def) @@ -872,12 +872,12 @@ def load_test_json(t: TestDef, stdout_mandatory: bool, skip_category: bool = Fal new_opt_list: T.List[T.List[T.Tuple[str, str, bool, bool]]] # 'matrix; entry is present, so build multiple tests from matrix definition - opt_list = [] # type: T.List[T.List[T.Tuple[str, str, bool, bool]]] + opt_list: T.List[T.List[T.Tuple[str, str, bool, bool]]] = [] matrix = test_def['matrix'] assert "options" in matrix for key, val in matrix["options"].items(): assert isinstance(val, list) - tmp_opts = [] # type: T.List[T.Tuple[str, str, bool, bool]] + tmp_opts: T.List[T.Tuple[str, str, bool, bool]] = [] for i in val: assert isinstance(i, dict) assert "val" in i diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py index a12d9cf1f389..7889cd8251ad 100755 --- a/tools/cmake2meson.py +++ b/tools/cmake2meson.py @@ -119,7 +119,7 @@ def statement(self) -> Statement: return Statement(cur.value, args) def arguments(self) -> T.List[T.Union[Token, T.Any]]: - args = [] # type: T.List[T.Union[Token, T.Any]] + args: T.List[T.Union[Token, T.Any]] = [] if self.accept('lparen'): args.append(self.arguments()) self.expect('rparen') @@ -159,7 +159,7 @@ def __init__(self, cmake_root: str): self.cmake_root = Path(cmake_root).expanduser() self.indent_unit = ' ' self.indent_level = 0 - self.options = [] # type: T.List[tuple] + self.options: T.List[T.Tuple[str, str, T.Optional[str]]] = [] def convert_args(self, args: T.List[Token], as_array: bool = True) -> str: res = [] diff --git a/unittests/internaltests.py b/unittests/internaltests.py index eb3b1717a66b..1c55b2976016 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1020,7 +1020,7 @@ def test_validate_json(self) -> None: schema = json.loads(Path('data/test.schema.json').read_text(encoding='utf-8')) - errors = [] # type: T.Tuple[str, Exception] + errors: T.List[T.Tuple[Path, Exception]] = [] for p in Path('test cases').glob('**/test.json'): try: validate(json.loads(p.read_text(encoding='utf-8')), schema=schema) From e107b40225e90331613686982b07f16853c52cab Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 14 Aug 2023 18:35:48 -0500 Subject: [PATCH 313/855] Remove unused parameter in IntroCommand::get_meson_introspection_types() --- mesonbuild/mintro.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 7bd420510334..e3f2e51b17f0 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -64,8 +64,7 @@ def __init__(self, def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None, builddata: T.Optional[build.Build] = None, - backend: T.Optional[backends.Backend] = None, - sourcedir: T.Optional[str] = None) -> 'T.Mapping[str, IntroCommand]': + backend: T.Optional[backends.Backend] = None) -> 'T.Mapping[str, IntroCommand]': if backend and builddata: benchmarkdata = backend.create_test_serialisation(builddata.get_benchmarks()) testdata = backend.create_test_serialisation(builddata.get_tests()) @@ -543,7 +542,7 @@ def run(options: argparse.Namespace) -> int: indent = 4 if options.indent else None results: T.List[T.Tuple[str, T.Union[dict, T.List[T.Any]]]] = [] sourcedir = '.' if options.builddir == 'meson.build' else options.builddir[:-11] - intro_types = get_meson_introspection_types(sourcedir=sourcedir) + intro_types = get_meson_introspection_types() if 'meson.build' in [os.path.basename(options.builddir), options.builddir]: # Make sure that log entries in other parts of meson don't interfere with the JSON output From ed9d03a0888d376000aa5781704ee3b139fcb8eb Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 14 Aug 2023 20:38:19 -0500 Subject: [PATCH 314/855] Remove unused isinstance() in backends.py This dead code was made impossible in 251dff5. --- mesonbuild/backend/backends.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index aef45b344c9d..4cee7a49805f 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1831,8 +1831,6 @@ def generate_header_install(self, d: InstallData) -> None: outdir_name = os.path.join('{includedir}', subdir) for f in h.get_sources(): - if not isinstance(f, File): - raise MesonException(f'Invalid header type {f!r} can\'t be installed') abspath = f.absolute_path(srcdir, builddir) i = InstallDataBase(abspath, outdir, outdir_name, h.get_custom_install_mode(), h.subproject, tag='devel', follow_symlinks=h.follow_symlinks) d.headers.append(i) From 4fadb2a2962d0cdb39da7cadd5c7b1b12984eeb5 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Wed, 22 Feb 2023 22:02:45 -0600 Subject: [PATCH 315/855] msvc: unify debug filename handling The MSVC code is extremely confusing, and it turns out it actually constructs debug (pdb) files names/path independently in separate places. This is really hard to parse. Instead, refactor it so that the source of the debug filename is within the target itself (get_debug_filename). Add a couple of generic methods to retrieve the full path of the debug filename name in the backend and use that when needed. --- mesonbuild/backend/backends.py | 14 ++++++++++++++ mesonbuild/backend/ninjabackend.py | 16 +++++++++------- mesonbuild/build.py | 10 ++++++++++ mesonbuild/linkers/linkers.py | 3 +-- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 4cee7a49805f..a8bf387f91e5 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -316,6 +316,20 @@ def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], def get_target_filename_abs(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)) + def get_target_debug_filename(self, target: build.BuildTarget) -> T.Optional[str]: + assert isinstance(target, build.BuildTarget), target + if target.get_debug_filename(): + debug_filename = target.get_debug_filename() + return os.path.join(self.get_target_dir(target), debug_filename) + else: + return None + + def get_target_debug_filename_abs(self, target: build.BuildTarget) -> T.Optional[str]: + assert isinstance(target, build.BuildTarget), target + if not target.get_debug_filename(): + return None + return os.path.join(self.environment.get_build_dir(), self.get_target_debug_filename(target)) + def get_source_dir_include_args(self, target: build.BuildTarget, compiler: 'Compiler', *, absolute_path: bool = False) -> T.List[str]: curdir = target.get_subdir() if absolute_path: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 04f3505f41b1..2b9a64eb5492 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2797,16 +2797,18 @@ def get_compile_debugfile_args(self, compiler, target, objfile): # this is actually doable, please send patches. if target.has_pch(): - tfilename = self.get_target_filename_abs(target) + tfilename = self.get_target_debug_filename_abs(target) + if not tfilename: + tfilename = self.get_target_filename_abs(target) return compiler.get_compile_debugfile_args(tfilename, pch=True) else: return compiler.get_compile_debugfile_args(objfile, pch=False) - def get_link_debugfile_name(self, linker, target, outname) -> T.Optional[str]: - return linker.get_link_debugfile_name(outname) + def get_link_debugfile_name(self, linker, target) -> T.Optional[str]: + return linker.get_link_debugfile_name(self.get_target_debug_filename(target)) - def get_link_debugfile_args(self, linker, target, outname): - return linker.get_link_debugfile_args(outname) + def get_link_debugfile_args(self, linker, target): + return linker.get_link_debugfile_args(self.get_target_debug_filename(target)) def generate_llvm_ir_compile(self, target, src): base_proxy = target.get_options() @@ -3440,8 +3442,8 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. commands += linker.get_buildtype_linker_args(target.get_option(OptionKey('buildtype'))) # Add /DEBUG and the pdb filename when using MSVC if target.get_option(OptionKey('debug')): - commands += self.get_link_debugfile_args(linker, target, outname) - debugfile = self.get_link_debugfile_name(linker, target, outname) + commands += self.get_link_debugfile_args(linker, target) + debugfile = self.get_link_debugfile_name(linker, target) if debugfile is not None: implicit_outs += [debugfile] # Add link args specific to this BuildTarget type, such as soname args, diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 621b6c780b12..4c07d9691c1c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -737,6 +737,8 @@ def __init__( self.name_prefix_set = False self.name_suffix_set = False self.filename = 'no_name' + # The debugging information file this target will generate + self.debug_filename = None # The list of all files outputted by this target. Useful in cases such # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] @@ -1262,6 +1264,14 @@ def _extract_pic_pie(self, kwargs: T.Dict[str, T.Any], arg: str, option: str) -> def get_filename(self) -> str: return self.filename + def get_debug_filename(self) -> T.Optional[str]: + """ + The name of debuginfo file that will be created by the compiler + + Returns None if the build won't create any debuginfo file + """ + return self.debug_filename + def get_outputs(self) -> T.List[str]: return self.outputs diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 0c2bf73be77a..5911a9fa34ef 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1272,8 +1272,7 @@ def get_std_shared_lib_args(self) -> T.List[str]: return self._apply_prefix('/DLL') def get_debugfile_name(self, targetfile: str) -> str: - basename = targetfile.rsplit('.', maxsplit=1)[0] - return basename + '.pdb' + return targetfile def get_debugfile_args(self, targetfile: str) -> T.List[str]: return self._apply_prefix(['/DEBUG', '/PDB:' + self.get_debugfile_name(targetfile)]) From adb1a360b9f9edb26eda233326b1d539baeccd5b Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Wed, 22 Feb 2023 22:09:11 -0600 Subject: [PATCH 316/855] build: use suffix when getting target id for exes When checking target names, meson explictly forbids having multiple targets with the same name. This is good, but it is strict and it is impossible to have targets with the same basename and differing suffixes (e.g. foo and foo.bin) in the same directory. Allow this for executables by including the suffix (if it exists) in the interal target id. So foo would be foo@exe and foo.bin would be foo.bin@exe. --- docs/markdown/snippets/executable-suffixes.md | 14 ++++++++++++++ docs/yaml/functions/executable.yaml | 3 +++ mesonbuild/build.py | 14 ++++++++++++-- mesonbuild/interpreter/interpreter.py | 8 ++++++-- test cases/unit/119 executable suffix/main.c | 1 + test cases/unit/119 executable suffix/meson.build | 3 +++ unittests/allplatformstests.py | 10 ++++++++++ 7 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 docs/markdown/snippets/executable-suffixes.md create mode 100644 test cases/unit/119 executable suffix/main.c create mode 100644 test cases/unit/119 executable suffix/meson.build diff --git a/docs/markdown/snippets/executable-suffixes.md b/docs/markdown/snippets/executable-suffixes.md new file mode 100644 index 000000000000..44471e9dd4c6 --- /dev/null +++ b/docs/markdown/snippets/executable-suffixes.md @@ -0,0 +1,14 @@ +## Target names for executables now take into account suffixes. + +In previous versions of meson, a `meson.build` file like this: + +``` +exectuable('foo', 'main.c') +exectuable('foo', 'main.c', name_suffix: 'bar') +``` + +would result in a configure error because meson internally used +the same id for both executables. This build file is now allowed +since meson takes into account the `bar` suffix when generating the +second executable. This allows for executables with the same basename +but different suffixes to be built in the same subdirectory. diff --git a/docs/yaml/functions/executable.yaml b/docs/yaml/functions/executable.yaml index 38075945782c..abbc5feee909 100644 --- a/docs/yaml/functions/executable.yaml +++ b/docs/yaml/functions/executable.yaml @@ -10,6 +10,9 @@ description: | The returned object also has methods that are documented in [[@exe]]. + *Since 1.3.0* executable names can be the same across multiple targets as + long as they each have a different `name_suffix`. + warnings: - The `link_language` kwarg was broken until 0.55.0 diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 4c07d9691c1c..d1888d7b2f27 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -634,8 +634,11 @@ def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str: return my_id def get_id(self) -> str: + name = self.name + if getattr(self, 'name_suffix_set', False): + name += '.' + self.suffix return self.construct_id_from_path( - self.subdir, self.name, self.type_suffix()) + self.subdir, name, self.type_suffix()) def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None: if 'build_by_default' in kwargs: @@ -2013,7 +2016,14 @@ def post_init(self) -> None: and self.environment.coredata.get_option(OptionKey("debug")) ) if create_debug_file: - self.debug_filename = self.name + '.pdb' + # If the target is has a standard exe extension (i.e. 'foo.exe'), + # then the pdb name simply becomes 'foo.pdb'. If the extension is + # something exotic, then include that in the name for uniqueness + # reasons (e.g. 'foo_com.pdb'). + name = self.name + if getattr(self, 'suffix', 'exe') != 'exe': + name += '_' + self.suffix + self.debug_filename = name + '.pdb' def process_kwargs(self, kwargs): super().process_kwargs(kwargs) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 05581afebc8d..0b6ccef22044 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3169,8 +3169,12 @@ def add_target(self, name: str, tobj: build.Target) -> None: # To permit an executable and a shared library to have the # same name, such as "foo.exe" and "libfoo.a". idname = tobj.get_id() - if idname in self.build.targets: - raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') + for t in self.build.targets.values(): + if t.get_id() == idname: + raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') + if isinstance(tobj, build.Executable) and isinstance(t, build.Executable) and t.name == tobj.name: + FeatureNew.single_use('multiple executables with the same name but different suffixes', + '1.3.0', self.subproject, location=self.current_node) if isinstance(tobj, build.BuildTarget): self.add_languages(tobj.missing_languages, True, tobj.for_machine) diff --git a/test cases/unit/119 executable suffix/main.c b/test cases/unit/119 executable suffix/main.c new file mode 100644 index 000000000000..78f2de106c92 --- /dev/null +++ b/test cases/unit/119 executable suffix/main.c @@ -0,0 +1 @@ +int main(void) { return 0; } diff --git a/test cases/unit/119 executable suffix/meson.build b/test cases/unit/119 executable suffix/meson.build new file mode 100644 index 000000000000..8f952260cbf9 --- /dev/null +++ b/test cases/unit/119 executable suffix/meson.build @@ -0,0 +1,3 @@ +project('exectuable suffix', 'c') +foo = executable('foo', 'main.c') +foo_bin = executable('foo', 'main.c', name_suffix: 'bin') diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 4ee0de469026..030b216d7786 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2039,6 +2039,16 @@ def get_opt(): original = get_opt() self.assertDictEqual(original, expected) + def test_executable_names(self): + testdir = os.path.join(self.unit_test_dir, '119 executable suffix') + self.init(testdir) + self.build() + exe1 = os.path.join(self.builddir, 'foo' + exe_suffix) + exe2 = os.path.join(self.builddir, 'foo.bin') + self.assertPathExists(exe1) + self.assertPathExists(exe2) + self.assertNotEqual(exe1, exe2) + def opt_has(self, name, value): res = self.introspect('--buildoptions') found = False From 03a0d3ddfb092ceb48f1a30fdf5e4b6af2890235 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Sun, 6 Aug 2023 21:02:18 -0500 Subject: [PATCH 317/855] mcompile: add suffix as an additional parameter Since the previous commit allows for more scenarios with name collisions, it makes sense to expand the compile command so that it can also take into account suffixes. i.e. meson compile -C build foo.exe can now work if the executable has an exe suffix along with being named foo. --- docs/markdown/Commands.md | 7 +++- .../snippets/meson_compile_suffixes.md | 7 ++++ mesonbuild/mcompile.py | 40 ++++++++++++++++--- unittests/allplatformstests.py | 9 +++++ 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 docs/markdown/snippets/meson_compile_suffixes.md diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index efc316ce7fbb..3fcdedd03ca3 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -58,14 +58,17 @@ Builds a default or a specified target of a configured Meson project. *(since 0.55.0)* -`TARGET` has the following syntax `[PATH/]NAME[:TYPE]`, where: +`TARGET` has the following syntax `[PATH/]NAME.SUFFIX[:TYPE]`, where: - `NAME`: name of the target from `meson.build` (e.g. `foo` from `executable('foo', ...)`). +- `SUFFIX`: name of the suffix of the target from `meson.build` (e.g. `exe` from `executable('foo', suffix: 'exe', ...)`). - `PATH`: path to the target relative to the root `meson.build` file. Note: relative path for a target specified in the root `meson.build` is `./`. - `TYPE`: type of the target. Can be one of the following: 'executable', 'static_library', 'shared_library', 'shared_module', 'custom', 'alias', 'run', 'jar'. -`PATH` and/or `TYPE` can be omitted if the resulting `TARGET` can be +`PATH`, `SUFFIX`, and `TYPE` can all be omitted if the resulting `TARGET` can be used to uniquely identify the target in `meson.build`. +Note that `SUFFIX` did not exist prior to 1.3.0. + #### Backend specific arguments *(since 0.55.0)* diff --git a/docs/markdown/snippets/meson_compile_suffixes.md b/docs/markdown/snippets/meson_compile_suffixes.md new file mode 100644 index 000000000000..481e8adf4b92 --- /dev/null +++ b/docs/markdown/snippets/meson_compile_suffixes.md @@ -0,0 +1,7 @@ +## Meson compile command now accepts suffixes for TARGET + +The syntax for specifying a target for meson compile is now +`[PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE]` where +`TARGET_SUFFIX` is the suffix argument given in the build target +within meson.build. It is optional and `TARGET_NAME` remains +sufficient if it uniquely resolves to one single target. diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 19875c22a9cd..6721beb0b008 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -61,9 +61,11 @@ def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]: class ParsedTargetName: full_name = '' + base_name = '' name = '' type = '' path = '' + suffix = '' def __init__(self, target: str): self.full_name = target @@ -80,6 +82,13 @@ def __init__(self, target: str): else: self.name = split[0] + split = self.name.rsplit('.', 1) + if len(split) > 1: + self.base_name = split[0] + self.suffix = split[1] + else: + self.base_name = split[0] + @staticmethod def _is_valid_type(type: str) -> bool: # Amend docs in Commands.md when editing this list @@ -96,19 +105,32 @@ def _is_valid_type(type: str) -> bool: return type in allowed_types def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introspect_data: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]: - if target.name not in introspect_data: + if target.name not in introspect_data and target.base_name not in introspect_data: raise MesonException(f'Can\'t invoke target `{target.full_name}`: target not found') intro_targets = introspect_data[target.name] + # if target.name doesn't find anything, try just the base name + if not intro_targets: + intro_targets = introspect_data[target.base_name] found_targets: T.List[T.Dict[str, T.Any]] = [] resolved_bdir = builddir.resolve() - if not target.type and not target.path: + if not target.type and not target.path and not target.suffix: found_targets = intro_targets else: for intro_target in intro_targets: + # Parse out the name from the id if needed + intro_target_name = intro_target['name'] + split = intro_target['id'].rsplit('@', 1) + if len(split) > 1: + split = split[0].split('@@', 1) + if len(split) > 1: + intro_target_name = split[1] + else: + intro_target_name = split[0] if ((target.type and target.type != intro_target['type'].replace(' ', '_')) or + (target.name != intro_target_name) or (target.path and intro_target['filename'] != 'no_name' and Path(target.path) != Path(intro_target['filename'][0]).relative_to(resolved_bdir).parent)): continue @@ -119,12 +141,20 @@ def get_target_from_intro_data(target: ParsedTargetName, builddir: Path, introsp elif len(found_targets) > 1: suggestions: T.List[str] = [] for i in found_targets: - p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i['name'] + i_name = i['name'] + split = i['id'].rsplit('@', 1) + if len(split) > 1: + split = split[0].split('@@', 1) + if len(split) > 1: + i_name = split[1] + else: + i_name = split[0] + p = Path(i['filename'][0]).relative_to(resolved_bdir).parent / i_name t = i['type'].replace(' ', '_') suggestions.append(f'- ./{p}:{t}') suggestions_str = '\n'.join(suggestions) raise MesonException(f'Can\'t invoke target `{target.full_name}`: ambiguous name.' - f'Add target type and/or path:\n{suggestions_str}') + f' Add target type and/or path:\n{suggestions_str}') return found_targets[0] @@ -278,7 +308,7 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None: metavar='TARGET', nargs='*', default=None, - help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME[:TARGET_TYPE].') + help='Targets to build. Target has the following format: [PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE].') parser.add_argument( '--clean', action='store_true', diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 030b216d7786..f5048837f77a 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2049,6 +2049,15 @@ def test_executable_names(self): self.assertPathExists(exe2) self.assertNotEqual(exe1, exe2) + # Wipe and run the compile command against the target names + self.init(testdir, extra_args=['--wipe']) + self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo']) + self._run([*self.meson_command, 'compile', '-C', self.builddir, './foo.bin']) + self.assertPathExists(exe1) + self.assertPathExists(exe2) + self.assertNotEqual(exe1, exe2) + + def opt_has(self, name, value): res = self.introspect('--buildoptions') found = False From 3cac6ea54572214d40234042f59de85618b0c131 Mon Sep 17 00:00:00 2001 From: Nomura Date: Mon, 2 Oct 2023 15:28:58 +0200 Subject: [PATCH 318/855] Add env kwarg in generator.process() --- .../snippets/env_kwarg_generator_process.md | 4 ++++ docs/yaml/objects/generator.yaml | 9 ++++++++ mesonbuild/backend/ninjabackend.py | 3 ++- mesonbuild/backend/vs2010backend.py | 3 ++- mesonbuild/build.py | 14 +++++++++++-- mesonbuild/interpreter/interpreterobjects.py | 5 +++-- mesonbuild/interpreter/kwargs.py | 1 + .../generate_main.py | 11 ++++++++++ .../main.template | 3 +++ .../272 env in generator.process/meson.build | 21 +++++++++++++++++++ 10 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 docs/markdown/snippets/env_kwarg_generator_process.md create mode 100644 test cases/common/272 env in generator.process/generate_main.py create mode 100644 test cases/common/272 env in generator.process/main.template create mode 100644 test cases/common/272 env in generator.process/meson.build diff --git a/docs/markdown/snippets/env_kwarg_generator_process.md b/docs/markdown/snippets/env_kwarg_generator_process.md new file mode 100644 index 000000000000..cdf73a302ae1 --- /dev/null +++ b/docs/markdown/snippets/env_kwarg_generator_process.md @@ -0,0 +1,4 @@ +## generator.process() gains 'env' keyword argument + +Like the kwarg of the same name in `custom_target()`, `env` allows +you to set the environment in which the generator will process inputs. diff --git a/docs/yaml/objects/generator.yaml b/docs/yaml/objects/generator.yaml index e7b866accfa5..fbef95fa4fc3 100644 --- a/docs/yaml/objects/generator.yaml +++ b/docs/yaml/objects/generator.yaml @@ -34,3 +34,12 @@ methods: `subdir/one.input` is processed it generates a file `{target private directory}/subdir/one.out` as opposed to `{target private directory}/one.out`. + + env: + type: env | list[str] | dict[str] + since: 1.3.0 + description: | + environment variables to set, such as + `{'NAME1': 'value1', 'NAME2': 'value2'}` or `['NAME1=value1', 'NAME2=value2']`, + or an [[@env]] object which allows more + sophisticated environment juggling. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2b9a64eb5492..a994d7388333 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2649,7 +2649,8 @@ def generate_genlist_for_target(self, genlist: build.GeneratedList, target: buil args = self.replace_paths(target, args, override_subdir=subdir) cmdlist, reason = self.as_meson_exe_cmdline(exe, self.replace_extra_args(args, genlist), - capture=outfiles[0] if generator.capture else None) + capture=outfiles[0] if generator.capture else None, + env=genlist.env) abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) os.makedirs(abs_pdir, exist_ok=True) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index fd19ff3d37cd..c9c21a13582e 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -211,7 +211,8 @@ def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, buil self.replace_extra_args(args, genlist), workdir=tdir_abs, capture=outfiles[0] if generator.capture else None, - force_serialize=True + force_serialize=True, + env=genlist.env ) deps = cmd[-1:] + deps abs_pdir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index d1888d7b2f27..8208fa0d9601 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1822,8 +1822,14 @@ def is_parent_path(parent: str, trial: str) -> bool: def process_files(self, files: T.Iterable[T.Union[str, File, 'CustomTarget', 'CustomTargetIndex', 'GeneratedList']], state: T.Union['Interpreter', 'ModuleState'], preserve_path_from: T.Optional[str] = None, - extra_args: T.Optional[T.List[str]] = None) -> 'GeneratedList': - output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else []) + extra_args: T.Optional[T.List[str]] = None, + env: T.Optional[EnvironmentVariables] = None) -> 'GeneratedList': + output = GeneratedList( + self, + state.subdir, + preserve_path_from, + extra_args=extra_args if extra_args is not None else [], + env=env if env is not None else EnvironmentVariables()) for e in files: if isinstance(e, CustomTarget): @@ -1862,6 +1868,7 @@ class GeneratedList(HoldableObject): subdir: str preserve_path_from: T.Optional[str] extra_args: T.List[str] + env: T.Optional[EnvironmentVariables] def __post_init__(self) -> None: self.name = self.generator.exe @@ -1875,6 +1882,9 @@ def __post_init__(self) -> None: if self.extra_args is None: self.extra_args: T.List[str] = [] + if self.env is None: + self.env: EnvironmentVariables = EnvironmentVariables() + if isinstance(self.generator.exe, programs.ExternalProgram): if not self.generator.exe.found(): raise InvalidArguments('Tried to use not-found external program as generator') diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 46b4cc1e51c1..effeebb2019e 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -21,7 +21,7 @@ typed_pos_args, typed_kwargs, typed_operator, noArgsFlattening, noPosargs, noKwargs, unholder_return, flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode) -from ..interpreter.type_checking import NoneType, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW +from ..interpreter.type_checking import NoneType, ENV_KW, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW from ..dependencies import Dependency, ExternalLibrary, InternalDependency from ..programs import ExternalProgram from ..mesonlib import HoldableObject, OptionKey, listify, Popen_safe @@ -1043,6 +1043,7 @@ def __init__(self, gen: build.Generator, interpreter: 'Interpreter'): 'generator.process', KwargInfo('preserve_path_from', (str, NoneType), since='0.45.0'), KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), + ENV_KW.evolve(since='1.3.0') ) def process_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File, 'build.GeneratedTypes']]], @@ -1060,7 +1061,7 @@ def process_method(self, '0.57.0', self.interpreter.subproject) gl = self.held_object.process_files(args[0], self.interpreter, - preserve_path_from, extra_args=kwargs['extra_args']) + preserve_path_from, extra_args=kwargs['extra_args'], env=kwargs['env']) return gl diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 7396229db708..241a08b766ae 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -103,6 +103,7 @@ class GeneratorProcess(TypedDict): preserve_path_from: T.Optional[str] extra_args: T.List[str] + env: EnvironmentVariables class DependencyMethodPartialDependency(TypedDict): diff --git a/test cases/common/272 env in generator.process/generate_main.py b/test cases/common/272 env in generator.process/generate_main.py new file mode 100644 index 000000000000..993c5ac034e1 --- /dev/null +++ b/test cases/common/272 env in generator.process/generate_main.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import os +import sys + +ENV_VAR_VALUE = os.environ.get('ENV_VAR_VALUE') +assert ENV_VAR_VALUE is not None + +with open(sys.argv[1], 'r') as infile, \ + open(sys.argv[2], 'w') as outfile: + + outfile.write(infile.read().replace('ENV_VAR_VALUE', ENV_VAR_VALUE)) diff --git a/test cases/common/272 env in generator.process/main.template b/test cases/common/272 env in generator.process/main.template new file mode 100644 index 000000000000..3c3340efcc58 --- /dev/null +++ b/test cases/common/272 env in generator.process/main.template @@ -0,0 +1,3 @@ +int main(void) { + return ENV_VAR_VALUE; +} \ No newline at end of file diff --git a/test cases/common/272 env in generator.process/meson.build b/test cases/common/272 env in generator.process/meson.build new file mode 100644 index 000000000000..5d7404024b7a --- /dev/null +++ b/test cases/common/272 env in generator.process/meson.build @@ -0,0 +1,21 @@ +project('test_env_in_generator_process', 'c') + +generate_main_py = find_program('generate_main.py') + +main_generator = generator(generate_main_py, + arguments: ['@INPUT@', '@OUTPUT@'], + output: '@BASENAME@' + '.c' +) + +main_template = files('main.template') + +# With explicit values +my_executable = executable('myexecutable', main_generator.process(main_template, env: {'ENV_VAR_VALUE': '0'})) +test('explicit_value', my_executable) + +# With env object +env = environment() +env.set('ENV_VAR_VALUE', '0') + +my_executable2 = executable('myexecutable2', main_generator.process(main_template, env: env)) +test('env_object', my_executable2) From 583d2815d1a130227f0f4db47e4ab2e80ebb6a61 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 5 Oct 2023 16:26:44 +0300 Subject: [PATCH 319/855] Document the color used in the logo. --- graphics/meson_logo.svg | 53 ++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/graphics/meson_logo.svg b/graphics/meson_logo.svg index d5b47bcf4ead..2b0f024bf63e 100644 --- a/graphics/meson_logo.svg +++ b/graphics/meson_logo.svg @@ -2,20 +2,20 @@ + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" + sodipodi:docname="meson_logo.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:window-width="2504" + inkscape:window-height="1650" + inkscape:window-x="546" + inkscape:window-y="110" + inkscape:window-maximized="0" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" /> @@ -87,7 +90,7 @@ image/svg+xml - + @@ -336,5 +339,21 @@ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26416996;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="m 96.975039,102.57831 c -3.04835,1.72126 -4.94049,4.94629 -4.95784,8.44909 3.18944,1.73892 6.93427,1.67939 9.836611,0.0181 2.6e-4,-0.008 7.9e-4,-0.0165 0.001,-0.0248 -0.004,-3.484 -1.863431,-6.70217 -4.879301,-8.44238 z m 1.64176,3.72948 c 0.45198,0.30715 0.38492,1.04655 0.31212,1.55288 -0.0926,0.55776 -0.62713,1.47487 -1.32188,2.07326 0.0899,0.12885 0.14181,0.28753 0.14108,0.45682 -0.43052,0.21761 -0.85742,-0.0278 -1.37408,-0.47026 -0.51665,-0.44244 -1.07391,-1.32905 -1.25884,-2.24017 -0.16403,0.0174 -0.33188,-0.0192 -0.47594,-0.11007 0.0376,-0.51089 0.57985,-0.8146 1.0604,-0.99374 0.48056,-0.17913 1.71868,-0.2395 2.59158,0.0708 0.0681,-0.1429 0.18071,-0.26288 0.32556,-0.339 z" id="path817-6-2-9-7-9-93-9-8-1-2-4-6" /> + The official color of the logo is PANTONE 2105 C.The sRGB substitute is (57, 32, 124). From 2c4a1b6324b1c069f713f089d22d1a0ea70cf222 Mon Sep 17 00:00:00 2001 From: Nigel Kukard Date: Mon, 9 Oct 2023 00:00:39 +0000 Subject: [PATCH 320/855] Add support for lcov 2.0 lcov 2.0 deprecates `--rc lcov_branch_coverage=1` for `--rc branch_coverage=1` and gives an error when an exclude is used on a non existing directory. I added a version check for lcov and removed the subprojects directory from the exclusion list if it does not exist. Fixes #11995 --- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/environment.py | 22 +++++++++++++++++----- mesonbuild/scripts/coverage.py | 20 ++++++++++++++------ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a994d7388333..29883bac737b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -640,7 +640,7 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional key = OptionKey('b_coverage') if (key in self.environment.coredata.options and self.environment.coredata.options[key].value): - gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, _ = environment.find_coverage_tools() + gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, _ = environment.find_coverage_tools() if gcovr_exe or (lcov_exe and genhtml_exe): self.add_build_comment(NinjaComment('Coverage rules')) self.generate_coverage_rules(gcovr_exe, gcovr_version) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7bd8c2ca60af..2ba20548f481 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -96,6 +96,20 @@ def detect_gcovr(min_version: str = '3.3', log: bool = False): return gcovr_exe, found return None, None +def detect_lcov(log: bool = False): + lcov_exe = 'lcov' + try: + p, found = Popen_safe([lcov_exe, '--version'])[0:2] + except (FileNotFoundError, PermissionError): + # Doesn't exist in PATH or isn't executable + return None, None + found = search_version(found) + if p.returncode == 0 and found: + if log: + mlog.log('Found lcov-{} at {}'.format(found, quote_arg(shutil.which(lcov_exe)))) + return lcov_exe, found + return None, None + def detect_llvm_cov(): tools = get_llvm_tool_names('llvm-cov') for tool in tools: @@ -103,20 +117,18 @@ def detect_llvm_cov(): return tool return None -def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: +def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: gcovr_exe, gcovr_version = detect_gcovr() llvm_cov_exe = detect_llvm_cov() - lcov_exe = 'lcov' + lcov_exe, lcov_version = detect_lcov() genhtml_exe = 'genhtml' - if not mesonlib.exe_exists([lcov_exe, '--version']): - lcov_exe = None if not mesonlib.exe_exists([genhtml_exe, '--version']): genhtml_exe = None - return gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe + return gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe def detect_ninja(version: str = '1.8.2', log: bool = False) -> T.List[str]: r = detect_ninja_command_and_version(version, log) diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index cb865d08d258..4c0f81e8a026 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -22,7 +22,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build outfiles = [] exitcode = 0 - (gcovr_exe, gcovr_version, lcov_exe, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() + (gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() # load config files for tools if available in the source tree # - lcov requires manually specifying a per-project config @@ -35,6 +35,11 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build else: lcov_config = [] + if lcov_exe and mesonlib.version_compare(lcov_version, '>=2.0'): + lcov_exe_rc_branch_coverage = ['--rc', 'branch_coverage=1'] + else: + lcov_exe_rc_branch_coverage = ['--rc', 'lcov_branch_coverage=1'] + gcovr_config = ['-e', re.escape(subproject_root)] # gcovr >= 4.2 requires a different syntax for out of source builds @@ -90,6 +95,9 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build initial_tracefile = covinfo + '.initial' run_tracefile = covinfo + '.run' raw_tracefile = covinfo + '.raw' + lcov_subpoject_exclude = [] + if os.path.exists(subproject_root): + lcov_subpoject_exclude.append(os.path.join(subproject_root, '*')) if use_llvm_cov: # Create a shim to allow using llvm-cov as a gcov tool. if mesonlib.is_windows(): @@ -117,26 +125,26 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build '--capture', '--output-file', run_tracefile, '--no-checksum', - '--rc', 'lcov_branch_coverage=1'] + + *lcov_exe_rc_branch_coverage] + lcov_config + gcov_tool_args) # Join initial and test results. subprocess.check_call([lcov_exe, '-a', initial_tracefile, '-a', run_tracefile, - '--rc', 'lcov_branch_coverage=1', + *lcov_exe_rc_branch_coverage, '-o', raw_tracefile] + lcov_config) # Remove all directories outside the source_root from the covinfo subprocess.check_call([lcov_exe, '--extract', raw_tracefile, os.path.join(source_root, '*'), - '--rc', 'lcov_branch_coverage=1', + *lcov_exe_rc_branch_coverage, '--output-file', covinfo] + lcov_config) # Remove all directories inside subproject dir subprocess.check_call([lcov_exe, '--remove', covinfo, - os.path.join(subproject_root, '*'), - '--rc', 'lcov_branch_coverage=1', + *lcov_subpoject_exclude, + *lcov_exe_rc_branch_coverage, '--output-file', covinfo] + lcov_config) subprocess.check_call([genhtml_exe, '--prefix', build_root, From 49a6a99c7fe85c66ff3e1f71e6c0fccb969acd2b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 8 Oct 2023 22:51:06 -0400 Subject: [PATCH 321/855] wrap: catch failure to extract tarball and raise WrapException This most likely happens when the source archive has files which take advantage of case sensitivity, and someone is unfortunate enough to have to work with broken operating systems that do not have the capacity to use modern technology, like the 1970s invention of case sensitive filesystems. For example, Windows and macOS both have retrocomputing environments, where case sensitive abilities were carefully removed from modern filesystems in order to share the delights of classical computing with the masses. On such systems, innocent tarballs fail to extract with: ``` OSError: [Errno 22] Invalid argument: 'C:\path\to\file' ``` thereby demonstrating Microsoft's unbounded and enthusiastic love for users (who are, universally, retrocomputing fans). n.b. there is, begrudgingly, a secret option for crazy people who hate retrocomputing to enable modern 1970s computing on Windows systems. Naturally, no one with any sense would ever use this, and it is rightly left in its sensible default in for example Github Actions. Fixes #12344 --- mesonbuild/wrap/wrap.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index a1bf72511363..21a5c5d227e3 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -569,7 +569,10 @@ def get_file(self) -> None: if 'lead_directory_missing' in self.wrap.values: os.mkdir(self.dirname) extract_dir = self.dirname - shutil.unpack_archive(path, extract_dir) + try: + shutil.unpack_archive(path, extract_dir) + except OSError as e: + raise WrapException(f'failed to unpack archive with error: {str(e)}') from e def get_git(self) -> None: if not GIT: From 84b8d257e490a29dbc2d439971fa0aa3669c8bbb Mon Sep 17 00:00:00 2001 From: Benjamin Redelings Date: Sat, 7 Oct 2023 10:37:49 -0400 Subject: [PATCH 322/855] Allow c++23 in gcc-11. --- mesonbuild/compilers/cpp.py | 2 +- unittests/linuxliketests.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index ba7539c6f858..dc733dd9ed38 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -426,7 +426,7 @@ def get_options(self) -> 'MutableKeyedOptionDictType': 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20', ] - if version_compare(self.version, '>=12.2.0'): + if version_compare(self.version, '>=11.0.0'): cppstd_choices.append('c++23') if version_compare(self.version, '>=14.0.0'): cppstd_choices.append('c++26') diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 7d99d8bf5fea..024d4338a861 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -520,10 +520,10 @@ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None: compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=10.0.0')) has_cpp2b = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=12.0.0', None) or - compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0')) + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=11.0.0')) has_cpp23 = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or - compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=12.2.0')) + compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=11.0.0')) has_cpp26 = (compiler.get_id() not in {'clang', 'gcc'} or compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=17.0.0', None) or compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=14.0.0')) From a3d287c553b9598f010fe0755c5528ef62055e44 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 17 Aug 2023 17:20:31 -0500 Subject: [PATCH 323/855] Port simd.check() to typed_pos_args/typed_kwargs --- mesonbuild/modules/simd.py | 77 +++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index 3ee0858b3287..b1429775d99a 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -13,53 +13,78 @@ # limitations under the License. from __future__ import annotations -from .. import mesonlib, compilers, mlog +import typing as T + +from .. import mesonlib, mlog from .. import build +from ..compilers import Compiler +from ..interpreter.type_checking import BT_SOURCES_KW, STATIC_LIB_KWS +from ..interpreterbase.decorators import KwargInfo, typed_pos_args, typed_kwargs from . import ExtensionModule, ModuleInfo +if T.TYPE_CHECKING: + from ..interpreter import kwargs as kwtypes + from ..interpreter.type_checking import SourcesVarargsType + + class CheckKw(kwtypes.StaticLibrary): + + compiler: Compiler + mmx: SourcesVarargsType + sse: SourcesVarargsType + sse2: SourcesVarargsType + sse3: SourcesVarargsType + ssse3: SourcesVarargsType + sse41: SourcesVarargsType + sse42: SourcesVarargsType + avx: SourcesVarargsType + avx2: SourcesVarargsType + neon: SourcesVarargsType + + +# FIXME add Altivec and AVX512. +ISETS = ( + 'mmx', + 'sse', + 'sse2', + 'sse3', + 'ssse3', + 'sse41', + 'sse42', + 'avx', + 'avx2', + 'neon', +) + + class SimdModule(ExtensionModule): INFO = ModuleInfo('SIMD', '0.42.0', unstable=True) def __init__(self, interpreter): super().__init__(interpreter) - # FIXME add Altivec and AVX512. - self.isets = ('mmx', - 'sse', - 'sse2', - 'sse3', - 'ssse3', - 'sse41', - 'sse42', - 'avx', - 'avx2', - 'neon', - ) self.methods.update({ 'check': self.check, }) - def check(self, state, args, kwargs): - result = [] - if len(args) != 1: - raise mesonlib.MesonException('Check requires one argument, a name prefix for checks.') - prefix = args[0] - if not isinstance(prefix, str): - raise mesonlib.MesonException('Argument must be a string.') - if 'compiler' not in kwargs: - raise mesonlib.MesonException('Must specify compiler keyword') + @typed_pos_args('simd.check', str) + @typed_kwargs('simd.check', + KwargInfo('compiler', Compiler, required=True), + *[BT_SOURCES_KW.evolve(name=iset) for iset in ISETS], + *[a for a in STATIC_LIB_KWS if a.name != 'sources'], + allow_unknown=True) # Because we also accept STATIC_LIB_KWS, but build targets have not been completely ported to typed_pos_args/typed_kwargs. + def check(self, state, args: T.Tuple[str], kwargs: CheckKw): + result: T.List[build.StaticLibrary] = [] if 'sources' in kwargs: raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') + prefix = args[0] basic_kwargs = {} for key, value in kwargs.items(): - if key not in self.isets and key != 'compiler': + if key not in ISETS and key != 'compiler': basic_kwargs[key] = value compiler = kwargs['compiler'] - if not isinstance(compiler, compilers.compilers.Compiler): - raise mesonlib.MesonException('Compiler argument must be a compiler object.') conf = build.ConfigurationData() - for iset in self.isets: + for iset in ISETS: if iset not in kwargs: continue iset_fname = kwargs[iset] # Might also be an array or Files. static_library will validate. From a5f323b6cf5d94da6884f0bd202521381b72712a Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 17 Aug 2023 17:02:25 -0500 Subject: [PATCH 324/855] Finish typing the simd module --- mesonbuild/modules/simd.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index b1429775d99a..afd3a2af0fda 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -24,7 +24,8 @@ from . import ExtensionModule, ModuleInfo if T.TYPE_CHECKING: - from ..interpreter import kwargs as kwtypes + from . import ModuleState + from ..interpreter import Interpreter, kwargs as kwtypes from ..interpreter.type_checking import SourcesVarargsType class CheckKw(kwtypes.StaticLibrary): @@ -61,7 +62,7 @@ class SimdModule(ExtensionModule): INFO = ModuleInfo('SIMD', '0.42.0', unstable=True) - def __init__(self, interpreter): + def __init__(self, interpreter: Interpreter): super().__init__(interpreter) self.methods.update({ 'check': self.check, @@ -73,7 +74,7 @@ def __init__(self, interpreter): *[BT_SOURCES_KW.evolve(name=iset) for iset in ISETS], *[a for a in STATIC_LIB_KWS if a.name != 'sources'], allow_unknown=True) # Because we also accept STATIC_LIB_KWS, but build targets have not been completely ported to typed_pos_args/typed_kwargs. - def check(self, state, args: T.Tuple[str], kwargs: CheckKw): + def check(self, state: ModuleState, args: T.Tuple[str], kwargs: CheckKw) -> T.List[T.Union[T.List[build.StaticLibrary], build.ConfigurationData]]: result: T.List[build.StaticLibrary] = [] if 'sources' in kwargs: raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') @@ -109,5 +110,5 @@ def check(self, state, args: T.Tuple[str], kwargs: CheckKw): result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs)) return [result, conf] -def initialize(*args, **kwargs): - return SimdModule(*args, **kwargs) +def initialize(interp: Interpreter) -> SimdModule: + return SimdModule(interp) From 101d783d666d3170b15da97bbde938d6fce2cf8b Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 17 Aug 2023 17:42:15 -0500 Subject: [PATCH 325/855] Clean up some of the code in simd.check() --- mesonbuild/modules/simd.py | 50 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index afd3a2af0fda..bce89dd2d976 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -19,7 +19,7 @@ from .. import build from ..compilers import Compiler from ..interpreter.type_checking import BT_SOURCES_KW, STATIC_LIB_KWS -from ..interpreterbase.decorators import KwargInfo, typed_pos_args, typed_kwargs +from ..interpreterbase.decorators import KwargInfo, permittedKwargs, typed_pos_args, typed_kwargs from . import ExtensionModule, ModuleInfo @@ -74,40 +74,48 @@ def __init__(self, interpreter: Interpreter): *[BT_SOURCES_KW.evolve(name=iset) for iset in ISETS], *[a for a in STATIC_LIB_KWS if a.name != 'sources'], allow_unknown=True) # Because we also accept STATIC_LIB_KWS, but build targets have not been completely ported to typed_pos_args/typed_kwargs. + @permittedKwargs({'compiler', *ISETS, *build.known_stlib_kwargs}) # Also remove this, per above comment def check(self, state: ModuleState, args: T.Tuple[str], kwargs: CheckKw) -> T.List[T.Union[T.List[build.StaticLibrary], build.ConfigurationData]]: result: T.List[build.StaticLibrary] = [] + if 'sources' in kwargs: raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') + + local_kwargs = set((*ISETS, 'compiler')) + static_lib_kwargs = T.cast('kwtypes.StaticLibrary', {k: v for k, v in kwargs.items() if k not in local_kwargs}) + prefix = args[0] - basic_kwargs = {} - for key, value in kwargs.items(): - if key not in ISETS and key != 'compiler': - basic_kwargs[key] = value compiler = kwargs['compiler'] conf = build.ConfigurationData() + for iset in ISETS: - if iset not in kwargs: + sources = kwargs[iset] + + compile_args = compiler.get_instruction_set_args(iset) + if compile_args is None: + mlog.log(f'Compiler supports {iset}:', mlog.red('NO')) continue - iset_fname = kwargs[iset] # Might also be an array or Files. static_library will validate. - args = compiler.get_instruction_set_args(iset) - if args is None: - mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) + + if not compiler.has_multi_arguments(compile_args, state.environment)[0]: + mlog.log(f'Compiler supports {iset}:', mlog.red('NO')) continue - if args: - if not compiler.has_multi_arguments(args, state.environment)[0]: - mlog.log('Compiler supports %s:' % iset, mlog.red('NO')) - continue - mlog.log('Compiler supports %s:' % iset, mlog.green('YES')) - conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset) + mlog.log(f'Compiler supports {iset}:', mlog.green('YES')) + conf.values['HAVE_' + iset.upper()] = ('1', f'Compiler supports {iset}.') + libname = prefix + '_' + iset - lib_kwargs = {'sources': iset_fname, - } - lib_kwargs.update(basic_kwargs) + lib_kwargs = static_lib_kwargs.copy() + lib_kwargs['sources'] = sources + + # Add compile args we derived above to those the user provided us langarg_key = compiler.get_language() + '_args' old_lang_args = mesonlib.extract_as_list(lib_kwargs, langarg_key) - all_lang_args = old_lang_args + args + all_lang_args = old_lang_args + compile_args lib_kwargs[langarg_key] = all_lang_args - result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs)) + + lib = self.interpreter.build_target(state.current_node, (libname, []), lib_kwargs, build.StaticLibrary) + + result.append(lib) + return [result, conf] def initialize(interp: Interpreter) -> SimdModule: From 8490eaa29dd9b5a7fd36bf9c2f871008139ede7a Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 17 Aug 2023 17:24:03 -0500 Subject: [PATCH 326/855] Add simd.py to run_mypy.py --- run_mypy.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_mypy.py b/run_mypy.py index cf0e0e3de253..16ff318e8442 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -60,6 +60,7 @@ 'mesonbuild/modules/qt5.py', 'mesonbuild/modules/qt6.py', 'mesonbuild/modules/rust.py', + 'mesonbuild/modules/simd.py', 'mesonbuild/modules/sourceset.py', 'mesonbuild/modules/wayland.py', 'mesonbuild/modules/windows.py', From cbca1919481902efbd5dadda3cc80db84fd75f0c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 21 Sep 2023 11:21:11 -0700 Subject: [PATCH 327/855] interpreter: Handle BuildTarget.vala_args as Files in the interpreter Way back in Meson 0.25, support was added to `vala_args` for Files. Strangely, this was never added to any other language, though it's been discussed before. For type safety, it makes more sense to handle this in the interpreter level, and pass only strings into the build IR. This is accomplished by adding a `depend_files` field to the `BuildTarget` class (which is not exposed to the user), and adding the depend files into that field, while converting the arguments to relative string paths. This ensures both the proper build dependencies happen, as well as that the arguments are always strings. --- docs/yaml/functions/_build_target_base.yaml | 5 +++ mesonbuild/backend/backends.py | 2 +- mesonbuild/backend/ninjabackend.py | 18 +++----- mesonbuild/backend/vs2010backend.py | 6 +-- mesonbuild/build.py | 5 ++- mesonbuild/interpreter/interpreter.py | 41 +++++++++++++++++++ mesonbuild/interpreter/kwargs.py | 3 +- .../meson.build | 0 .../my-resources.xml | 0 .../mywidget.ui | 0 .../mywidget.vala | 0 11 files changed, 60 insertions(+), 20 deletions(-) rename {manual tests/7 vala composite widgets => test cases/vala/27 file as command line argument}/meson.build (100%) rename {manual tests/7 vala composite widgets => test cases/vala/27 file as command line argument}/my-resources.xml (100%) rename {manual tests/7 vala composite widgets => test cases/vala/27 file as command line argument}/mywidget.ui (100%) rename {manual tests/7 vala composite widgets => test cases/vala/27 file as command line argument}/mywidget.vala (100%) diff --git a/docs/yaml/functions/_build_target_base.yaml b/docs/yaml/functions/_build_target_base.yaml index 3f0e88158c36..1db49a5315a6 100644 --- a/docs/yaml/functions/_build_target_base.yaml +++ b/docs/yaml/functions/_build_target_base.yaml @@ -48,6 +48,11 @@ kwargs: compiler flags to use for the given language; eg: `cpp_args` for C++ + vala_args: + type: list[str | file] + description: | + Compiler flags for Vala. Unlike other languages this may contain Files + sources: type: str | file | custom_tgt | custom_idx | generated_list | structured_src description: Additional source files. Same as the source varargs. diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index a8bf387f91e5..dd9e6ee6cf28 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1475,7 +1475,7 @@ def get_custom_target_sources(self, target: build.CustomTarget) -> T.List[str]: srcs += fname return srcs - def get_custom_target_depend_files(self, target: build.CustomTarget, absolute_paths: bool = False) -> T.List[str]: + def get_target_depend_files(self, target: T.Union[build.CustomTarget, build.BuildTarget], absolute_paths: bool = False) -> T.List[str]: deps: T.List[str] = [] for i in target.depend_files: if isinstance(i, mesonlib.File): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 29883bac737b..d4d4e2ff698c 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1151,7 +1151,7 @@ def generate_custom_target(self, target: build.CustomTarget): self.custom_target_generator_inputs(target) (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) - deps += self.get_custom_target_depend_files(target) + deps += self.get_target_depend_files(target) if target.build_always_stale: deps.append('PHONY') if target.depfile is None: @@ -1214,7 +1214,7 @@ def generate_run_target(self, target: build.RunTarget): elem.add_item('description', f'Running external command {target.name}{cmd_type}') elem.add_item('pool', 'console') deps = self.unwrap_dep_list(target) - deps += self.get_custom_target_depend_files(target) + deps += self.get_target_depend_files(target) elem.add_dep(deps) self.add_build(elem) self.processed_targets.add(target.get_id()) @@ -1712,18 +1712,10 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ if isinstance(gensrc, modules.GResourceTarget): gres_xml, = self.get_custom_target_sources(gensrc) args += ['--gresources=' + gres_xml] - extra_args = [] - - for a in target.extra_args.get('vala', []): - if isinstance(a, File): - relname = a.rel_to_builddir(self.build_to_src) - extra_dep_files.append(relname) - extra_args.append(relname) - else: - extra_args.append(a) dependency_vapis = self.determine_dep_vapis(target) extra_dep_files += dependency_vapis - args += extra_args + extra_dep_files.extend(self.get_target_depend_files(target)) + args += target.get_extra_args('vala') element = NinjaBuildElement(self.all_outputs, valac_outputs, self.compiler_to_rule_name(valac), all_files + dependency_vapis) @@ -2622,7 +2614,7 @@ def generate_genlist_for_target(self, genlist: build.GeneratedList, target: buil exe = generator.get_exe() infilelist = genlist.get_inputs() outfilelist = genlist.get_outputs() - extra_dependencies = self.get_custom_target_depend_files(genlist) + extra_dependencies = self.get_target_depend_files(genlist) for i, curfile in enumerate(infilelist): if len(generator.outputs) == 1: sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c9c21a13582e..b9ada532bcd8 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -187,7 +187,7 @@ def generate_genlist_for_target(self, genlist: T.Union[build.GeneratedList, buil else: sole_output = '' infilename = os.path.join(down, curfile.rel_to_builddir(self.build_to_src, target_private_dir)) - deps = self.get_custom_target_depend_files(genlist, True) + deps = self.get_target_depend_files(genlist, True) base_args = generator.get_arglist(infilename) outfiles_rel = genlist.get_outputs_for(curfile) outfiles = [os.path.join(target_private_dir, of) for of in outfiles_rel] @@ -699,7 +699,7 @@ def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), guid=guid) - depend_files = self.get_custom_target_depend_files(target) + depend_files = self.get_target_depend_files(target) if not target.command: # This is an alias target and thus doesn't run any command. It's @@ -738,7 +738,7 @@ def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, gui # from the target dir, not the build root. target.absolute_paths = True (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True) - depend_files = self.get_custom_target_depend_files(target, True) + depend_files = self.get_target_depend_files(target, True) # Always use a wrapper because MSBuild eats random characters when # there are many arguments. tdir_abs = os.path.join(self.environment.get_build_dir(), self.get_target_dir(target)) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8208fa0d9601..9f0abf539b54 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -735,6 +735,7 @@ def __init__( self.link_language = kwargs.get('link_language') self.link_targets: T.List[LibTypes] = [] self.link_whole_targets: T.List[T.Union[StaticLibrary, CustomTarget, CustomTargetIndex]] = [] + self.depend_files: T.List[File] = [] self.link_depends = [] self.added_deps = set() self.name_prefix_set = False @@ -746,7 +747,7 @@ def __init__( # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] self.pch: T.Dict[str, T.List[str]] = {} - self.extra_args: T.Dict[str, T.List['FileOrString']] = {} + self.extra_args: T.Dict[str, T.List[str]] = {} self.sources: T.List[File] = [] self.generated: T.List['GeneratedTypes'] = [] self.extra_files: T.List[File] = [] @@ -1278,7 +1279,7 @@ def get_debug_filename(self) -> T.Optional[str]: def get_outputs(self) -> T.List[str]: return self.outputs - def get_extra_args(self, language): + def get_extra_args(self, language) -> T.List[str]: return self.extra_args.get(language, []) @lru_cache(maxsize=None) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 0b6ccef22044..29eaed202434 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3230,6 +3230,46 @@ def build_library(self, node, args, kwargs): else: raise InterpreterException(f'Unknown default_library value: {default_library}.') + def __convert_file_args(self, raw: T.List[mesonlib.FileOrString], allow_file: bool) -> T.Tuple[T.List[mesonlib.File], T.List[str]]: + """Convert raw target arguments from File | str to File. + + This removes files from the command line and replaces them with string + values, but adds the files to depends list + + :param raw: the raw arguments + :return: A tuple of file dependencies and raw arguments + """ + depend_files: T.List[mesonlib.File] = [] + args: T.List[str] = [] + build_to_source = mesonlib.relpath(self.environment.get_source_dir(), + self.environment.get_build_dir()) + + for a in raw: + if isinstance(a, mesonlib.File): + if not allow_file: + raise InvalidArguments('File type arguments are only allowed for vala') + depend_files.append(a) + args.append(a.rel_to_builddir(build_to_source)) + else: + args.append(a) + + return depend_files, args + + def __process_language_args(self, kwargs: T.Dict[str, T.List[mesonlib.FileOrString]]) -> None: + """Convert split language args into a combined dictionary. + + The Meson DSL takes arguments in the form `_args : args`, but in the + build layer we store these in a single dictionary as `{: args}`. + This function extracts the arguments from the DSL format and prepares + them for the IR. + """ + d = kwargs.setdefault('depend_files', []) + + for l in compilers.all_languages: + deps, args = self.__convert_file_args(kwargs[f'{l}_args'], l == 'vala') + kwargs[f'{l}_args'] = args + d.extend(deps) + @T.overload def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Executable, targetclass: T.Type[build.Executable]) -> build.Executable: ... @@ -3295,6 +3335,7 @@ def build_target_decorator_caller(self, node, args, kwargs): mlog.debug('Unknown target type:', str(targetclass)) raise RuntimeError('Unreachable code') self.kwarg_strings_to_includedirs(kwargs) + self.__process_language_args(kwargs) # Filter out kwargs from other target types. For example 'soversion' # passed to library() when default_library == 'static'. diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 241a08b766ae..26ecb4ef92e4 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -7,7 +7,7 @@ import typing as T -from typing_extensions import TypedDict, Literal, Protocol +from typing_extensions import TypedDict, Literal, Protocol, NotRequired from .. import build from .. import coredata @@ -326,6 +326,7 @@ class _BaseBuildTarget(TypedDict): """ override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] + depend_files: NotRequired[T.List[File]] class _BuildTarget(_BaseBuildTarget): diff --git a/manual tests/7 vala composite widgets/meson.build b/test cases/vala/27 file as command line argument/meson.build similarity index 100% rename from manual tests/7 vala composite widgets/meson.build rename to test cases/vala/27 file as command line argument/meson.build diff --git a/manual tests/7 vala composite widgets/my-resources.xml b/test cases/vala/27 file as command line argument/my-resources.xml similarity index 100% rename from manual tests/7 vala composite widgets/my-resources.xml rename to test cases/vala/27 file as command line argument/my-resources.xml diff --git a/manual tests/7 vala composite widgets/mywidget.ui b/test cases/vala/27 file as command line argument/mywidget.ui similarity index 100% rename from manual tests/7 vala composite widgets/mywidget.ui rename to test cases/vala/27 file as command line argument/mywidget.ui diff --git a/manual tests/7 vala composite widgets/mywidget.vala b/test cases/vala/27 file as command line argument/mywidget.vala similarity index 100% rename from manual tests/7 vala composite widgets/mywidget.vala rename to test cases/vala/27 file as command line argument/mywidget.vala From 523a27c6f0b40c7ed1cc04d4d5c2d74cc9f6b30e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 3 Feb 2023 15:22:57 -0800 Subject: [PATCH 328/855] build: Use typed_kwargs for language args This also moves the repacking into the interpreter, making the build implementation simpler and removing a layering violation. This also makes use a defaultdict to remove the need to call `.get()` --- mesonbuild/backend/ninjabackend.py | 4 ++-- mesonbuild/build.py | 26 +++++++------------------ mesonbuild/interpreter/interpreter.py | 13 ++++++------- mesonbuild/interpreter/kwargs.py | 16 +++++++++++++++ mesonbuild/interpreter/type_checking.py | 17 ++++++++++++++++ mesonbuild/modules/rust.py | 7 ++++--- 6 files changed, 52 insertions(+), 31 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d4d4e2ff698c..3375b699e97d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1068,7 +1068,7 @@ def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: return True if 'cpp' not in target.compilers: return False - if '-fmodules-ts' in target.extra_args.get('cpp', []): + if '-fmodules-ts' in target.extra_args['cpp']: return True # Currently only the preview version of Visual Studio is supported. cpp = target.compilers['cpp'] @@ -1462,7 +1462,7 @@ def generate_cs_target(self, target: build.BuildTarget): compiler = target.compilers['cs'] rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] deps = [] - commands = compiler.compiler_args(target.extra_args.get('cs', [])) + commands = compiler.compiler_args(target.extra_args['cs']) commands += compiler.get_buildtype_args(buildtype) commands += compiler.get_optimization_args(target.get_option(OptionKey('optimization'))) commands += compiler.get_debug_args(target.get_option(OptionKey('debug'))) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 9f0abf539b54..ac2993fec487 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -724,7 +724,7 @@ def __init__( objects: T.List[ObjectTypes], environment: environment.Environment, compilers: T.Dict[str, 'Compiler'], - kwargs): + kwargs: T.Dict[str, T.Any]): super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False)) self.all_compilers = compilers self.compilers: OrderedDict[str, Compiler] = OrderedDict() @@ -747,7 +747,7 @@ def __init__( # as Vala which generates .vapi and .h besides the compiled output. self.outputs = [self.filename] self.pch: T.Dict[str, T.List[str]] = {} - self.extra_args: T.Dict[str, T.List[str]] = {} + self.extra_args: T.DefaultDict[str, T.List[str]] = kwargs.get('language_args', defaultdict(list)) self.sources: T.List[File] = [] self.generated: T.List['GeneratedTypes'] = [] self.extra_files: T.List[File] = [] @@ -831,6 +831,8 @@ def check_unknown_kwargs(self, kwargs): def check_unknown_kwargs_int(self, kwargs, known_kwargs): unknowns = [] for k in kwargs: + if k == 'language_args': + continue if k not in known_kwargs: unknowns.append(k) if len(unknowns) > 0: @@ -1104,10 +1106,6 @@ def process_kwargs(self, kwargs): self.process_kwargs_base(kwargs) self.original_kwargs = kwargs - for lang in all_languages: - lang_args = extract_as_list(kwargs, f'{lang}_args') - self.add_compiler_args(lang, lang_args) - self.add_pch('c', extract_as_list(kwargs, 'c_pch')) self.add_pch('cpp', extract_as_list(kwargs, 'cpp_pch')) @@ -1279,8 +1277,8 @@ def get_debug_filename(self) -> T.Optional[str]: def get_outputs(self) -> T.List[str]: return self.outputs - def get_extra_args(self, language) -> T.List[str]: - return self.extra_args.get(language, []) + def get_extra_args(self, language: str) -> T.List[str]: + return self.extra_args[language] @lru_cache(maxsize=None) def get_dependencies(self) -> OrderedSet[Target]: @@ -1539,16 +1537,6 @@ def add_include_dirs(self, args: T.Sequence['IncludeDirs'], set_is_system: T.Opt ids = [IncludeDirs(x.get_curdir(), x.get_incdirs(), is_system, x.get_extra_build_dirs()) for x in ids] self.include_dirs += ids - def add_compiler_args(self, language: str, args: T.List['FileOrString']) -> None: - args = listify(args) - for a in args: - if not isinstance(a, (str, File)): - raise InvalidArguments('A non-string passed to compiler args.') - if language in self.extra_args: - self.extra_args[language] += args - else: - self.extra_args[language] = args - def get_aliases(self) -> T.List[T.Tuple[str, str, str]]: return [] @@ -2876,7 +2864,7 @@ def __init__(self, name: str, subdir: str, subproject: str, for_machine: Machine raise InvalidArguments('structured sources are not supported in Java targets.') self.filename = self.name + '.jar' self.outputs = [self.filename] - self.java_args = kwargs.get('java_args', []) + self.java_args = self.extra_args['java'] self.main_class = kwargs.get('main_class', '') self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 29eaed202434..c7dc92d5d70f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3230,7 +3230,7 @@ def build_library(self, node, args, kwargs): else: raise InterpreterException(f'Unknown default_library value: {default_library}.') - def __convert_file_args(self, raw: T.List[mesonlib.FileOrString], allow_file: bool) -> T.Tuple[T.List[mesonlib.File], T.List[str]]: + def __convert_file_args(self, raw: T.List[mesonlib.FileOrString]) -> T.Tuple[T.List[mesonlib.File], T.List[str]]: """Convert raw target arguments from File | str to File. This removes files from the command line and replaces them with string @@ -3246,8 +3246,6 @@ def __convert_file_args(self, raw: T.List[mesonlib.FileOrString], allow_file: bo for a in raw: if isinstance(a, mesonlib.File): - if not allow_file: - raise InvalidArguments('File type arguments are only allowed for vala') depend_files.append(a) args.append(a.rel_to_builddir(build_to_source)) else: @@ -3264,11 +3262,13 @@ def __process_language_args(self, kwargs: T.Dict[str, T.List[mesonlib.FileOrStri them for the IR. """ d = kwargs.setdefault('depend_files', []) + new_args: T.DefaultDict[str, T.List[str]] = collections.defaultdict(list) for l in compilers.all_languages: - deps, args = self.__convert_file_args(kwargs[f'{l}_args'], l == 'vala') - kwargs[f'{l}_args'] = args + deps, args = self.__convert_file_args(kwargs[f'{l}_args']) + new_args[l] = args d.extend(deps) + kwargs['language_args'] = new_args @T.overload def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], @@ -3295,7 +3295,6 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: @FeatureNewKwargs('build target', '0.42.0', ['build_rpath', 'implicit_include_directories']) - @FeatureNewKwargs('build target', '0.41.0', ['rust_args']) @FeatureNewKwargs('build target', '0.38.0', ['build_by_default']) @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) def build_target_decorator_caller(self, node, args, kwargs): @@ -3339,7 +3338,7 @@ def build_target_decorator_caller(self, node, args, kwargs): # Filter out kwargs from other target types. For example 'soversion' # passed to library() when default_library == 'static'. - kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs} + kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs | {'language_args'}} srcs: T.List['SourceInputs'] = [] struct: T.Optional[build.StructuredSources] = build.StructuredSources() diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 26ecb4ef92e4..45cb07b3d495 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -335,12 +335,27 @@ class _BuildTarget(_BaseBuildTarget): rust_dependency_map: T.Dict[str, str] sources: SourcesVarargsType + c_args: T.List[str] + cpp_args: T.List[str] + cuda_args: T.List[str] + fortran_args: T.List[str] + d_args: T.List[str] + objc_args: T.List[str] + objcpp_args: T.List[str] + rust_args: T.List[str] + vala_args: T.List[T.Union[str, File]] # Yes, Vala is really special + cs_args: T.List[str] + swift_args: T.List[str] + cython_args: T.List[str] + nasm_args: T.List[str] + masm_args: T.List[str] class _LibraryMixin(TypedDict): rust_abi: T.Optional[Literal['c', 'rust']] + class Executable(_BuildTarget): export_dynamic: T.Optional[bool] @@ -394,6 +409,7 @@ class Jar(_BaseBuildTarget): main_class: str java_resources: T.Optional[build.StructuredSources] sources: T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget] + java_args: T.List[str] class FuncDeclareDependency(TypedDict): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 27a05523f953..cfd45b1bf167 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -526,8 +526,25 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since_values={CustomTargetIndex: '1.3.0'} ) +_BASE_LANG_KW: KwargInfo[T.List[str]] = KwargInfo( + 'UNKNOWN', + ContainerTypeInfo(list, (str)), + listify=True, + default=[], +) + +_LANGUAGE_KWS: T.List[KwargInfo[T.List[str]]] = [ + _BASE_LANG_KW.evolve(name=f'{lang}_args') + for lang in compilers.all_languages - {'rust', 'vala'} +] +# Cannot use _BASE_LANG_KW here because Vala is special for types +_LANGUAGE_KWS.append(KwargInfo( + 'vala_args', ContainerTypeInfo(list, (str, File)), listify=True, default=[])) +_LANGUAGE_KWS.append(_BASE_LANG_KW.evolve(name='rust_args', since='0.41.0')) + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ + *_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, ] diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 08aee16c8453..98bf05312cf0 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations - import os import typing as T from mesonbuild.interpreterbase.decorators import FeatureNew @@ -160,12 +159,14 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func new_target_kwargs = base_target.original_kwargs.copy() # Don't mutate the shallow copied list, instead replace it with a new # one - new_target_kwargs['rust_args'] = \ - new_target_kwargs.get('rust_args', []) + kwargs['rust_args'] + ['--test'] new_target_kwargs['install'] = False new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies'] new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with'] + lang_args = base_target.extra_args.copy() + lang_args['rust'] = base_target.extra_args['rust'] + kwargs['rust_args'] + ['--test'] + new_target_kwargs['language_args'] = lang_args + sources = T.cast('T.List[SourceOutputs]', base_target.sources.copy()) sources.extend(base_target.generated) From 835b23efb46998f49020b31012d3c5dc8ac437fc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 20 Jul 2023 10:55:58 -0700 Subject: [PATCH 329/855] interpreter: deprecated language args that don't apply to targets `java_args` is only valid for `jar()` (and `build_target()`, but that's deprecated), while all other language args are invalid for `jar()`. This deprecates all of those arguments, that shouldn't be allowed, and provides useful error messages. As an advantage, this avoids generating useless `java_static_args` and `java_shared_args`. In order to get useful error messages for both build_target and executable + *library, we need to separate LIBRARY and BUILD_TARGET a bit. --- mesonbuild/interpreter/type_checking.py | 26 +++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index cfd45b1bf167..4b3a8a422a34 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -535,22 +535,29 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus _LANGUAGE_KWS: T.List[KwargInfo[T.List[str]]] = [ _BASE_LANG_KW.evolve(name=f'{lang}_args') - for lang in compilers.all_languages - {'rust', 'vala'} + for lang in compilers.all_languages - {'rust', 'vala', 'java'} ] # Cannot use _BASE_LANG_KW here because Vala is special for types _LANGUAGE_KWS.append(KwargInfo( 'vala_args', ContainerTypeInfo(list, (str, File)), listify=True, default=[])) _LANGUAGE_KWS.append(_BASE_LANG_KW.evolve(name='rust_args', since='0.41.0')) +# We need this deprecated values more than the non-deprecated values. So we'll evolve them out elsewhere. +_JAVA_LANG_KW: KwargInfo[T.List[str]] = _BASE_LANG_KW.evolve( + name='java_args', + deprecated='1.3.0', + deprecated_message='This does not, and never has, done anything. It should be removed' +) + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ - *_LANGUAGE_KWS, OVERRIDE_OPTIONS_KW, ] # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, + *_LANGUAGE_KWS, BT_SOURCES_KW, RUST_CRATE_TYPE_KW, KwargInfo( @@ -630,6 +637,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_BUILD_TARGET_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, _VS_MODULE_DEFS_KW.evolve(since='1.3.0', since_values=None), + _JAVA_LANG_KW, ] # Arguments exclusive to library types @@ -649,6 +657,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_BUILD_TARGET_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, *_EXCLUSIVE_LIB_KWS, + _JAVA_LANG_KW, ] # Arguments exclusive to SharedLibrary. These are separated to make integrating @@ -665,6 +674,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_LIB_KWS, _VS_MODULE_DEFS_KW, + _JAVA_LANG_KW, ] # Arguments exclusive to SharedModule. These are separated to make integrating @@ -677,6 +687,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_LIB_KWS, _VS_MODULE_DEFS_KW, + _JAVA_LANG_KW, ] # Arguments exclusive to JAR. These are separated to make integrating @@ -684,6 +695,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup _EXCLUSIVE_JAR_KWS: T.List[KwargInfo] = [ KwargInfo('main_class', str, default=''), KwargInfo('java_resources', (StructuredSources, NoneType), since='0.62.0'), + _JAVA_LANG_KW.evolve(deprecated=None, deprecated_message=None), ] # The total list of arguments used by JAR @@ -695,7 +707,9 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, GeneratedList, ExtractedObjects, BuildTarget)), listify=True, default=[], - ) + ), + *[a.evolve(deprecated='1.3.0', deprecated_message='This argument has never done anything in jar(), and should be removed') + for a in _LANGUAGE_KWS], ] # Arguments used by both_library and library @@ -706,11 +720,15 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, _VS_MODULE_DEFS_KW, + _JAVA_LANG_KW, ] # Arguments used by build_Target BUILD_TARGET_KWS = [ - *LIBRARY_KWS, + *_BUILD_TARGET_KWS, + *_EXCLUSIVE_SHARED_LIB_KWS, + *_EXCLUSIVE_SHARED_MOD_KWS, + *_EXCLUSIVE_STATIC_LIB_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, *[a.evolve(deprecated='1.3.0', deprecated_message='The use of "jar" in "build_target()" is deprecated, and this argument is only used by jar()') for a in _EXCLUSIVE_JAR_KWS], From e24f43051255d3978002f39d08149c3088cb67f9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 9 Oct 2023 11:20:48 -0700 Subject: [PATCH 330/855] interpreter: extend annotations around build_both_libraries This allows for even more accurate type information --- mesonbuild/interpreter/interpreter.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c7dc92d5d70f..5ff5c0b5001d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3186,7 +3186,7 @@ def add_target(self, name: str, tobj: build.Target) -> None: self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() @FeatureNew('both_libraries', '0.46.0') - def build_both_libraries(self, node, args, kwargs): + def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary) static_lib = self.build_target(node, args, kwargs, build.StaticLibrary) @@ -3219,12 +3219,13 @@ def build_both_libraries(self, node, args, kwargs): return build.BothLibraries(shared_lib, static_lib) - def build_library(self, node, args, kwargs): + def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library): default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject)) + assert isinstance(default_library, str), 'for mypy' if default_library == 'shared': - return self.build_target(node, args, kwargs, build.SharedLibrary) + return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.SharedLibrary) elif default_library == 'static': - return self.build_target(node, args, kwargs, build.StaticLibrary) + return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.StaticLibrary) elif default_library == 'both': return self.build_both_libraries(node, args, kwargs) else: From 013536fcb45dc40c4f592f5c5821ee6d38d331ed Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 13 Jul 2023 10:26:14 -0700 Subject: [PATCH 331/855] interpreter: add _(static|shared)_args Which allow passing arguments specifically to the static or shared libraries. For design, this is all handled in the interpreter, by the build layer the arguments are combined into the existing fields. This limits changes required in the mid and backend layers --- .../snippets/shared_static_only_args.md | 9 +++++ docs/yaml/functions/library.yaml | 34 +++++++++++++++++++ mesonbuild/interpreter/interpreter.py | 17 +++++++++- mesonbuild/interpreter/kwargs.py | 29 ++++++++++++++++ mesonbuild/interpreter/type_checking.py | 11 +++++- .../common/178 bothlibraries/meson.build | 10 +++++- test cases/common/3 static/lib3.c | 11 ++++++ test cases/common/3 static/meson.build | 7 +++- test cases/common/4 shared/libfile2.c | 22 ++++++++++++ test cases/common/4 shared/meson.build | 7 +++- unittests/allplatformstests.py | 2 +- 11 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 docs/markdown/snippets/shared_static_only_args.md create mode 100644 test cases/common/3 static/lib3.c create mode 100644 test cases/common/4 shared/libfile2.c diff --git a/docs/markdown/snippets/shared_static_only_args.md b/docs/markdown/snippets/shared_static_only_args.md new file mode 100644 index 000000000000..0963c714bdf3 --- /dev/null +++ b/docs/markdown/snippets/shared_static_only_args.md @@ -0,0 +1,9 @@ +## `_(shared|static)_args` for both_library, library, and build_target + +We now allow passing arguments like `c_static_args` and `c_shared_args`. This +allows a [[both_libraries]] to have arguments specific to either the shared or +static library, as well as common arguments to both. + +There is a drawback to this, since Meson now cannot re-use object files between +the static and shared targets. This could lead to much higher compilation time +when using a [[both_libraries]] if there are many sources. diff --git a/docs/yaml/functions/library.yaml b/docs/yaml/functions/library.yaml index f9e336b9b808..1d406f13c039 100644 --- a/docs/yaml/functions/library.yaml +++ b/docs/yaml/functions/library.yaml @@ -16,6 +16,12 @@ description: | The keyword arguments for this are the same as for [[build_target]] +warnings: + - using _shared_args and/or _static_args may lead to much higher + compilation times with both_library, as object files cannot be shared between + the static and shared targets. It is guaranteed to not duplicate the build if + these arguments are empty arrays + posargs_inherit: _build_target_base varargs_inherit: _build_target_base kwargs_inherit: @@ -32,3 +38,31 @@ kwargs: type being build. - 'c': Create a "cdylib" or "staticlib" crate depending on the library type being build. + + _static_args: + type: list[str] + since: 1.3.0 + description: + Arguments that are only passed to a static library + + vala_static_args: + type: list[str | file] + since: 1.3.0 + description: + Arguments that are only passed to a static library + + Like `vala_args`, [[files]] is allowed in addition to string + + _shared_args: + type: list[str] + since: 1.3.0 + description: + Arguments that are only passed to a shared library + + vala_shared_args: + type: list[str | file] + since: 1.3.0 + description: + Arguments that are only passed to a shared library + + Like `vala_args`, [[files]] is allowed in addition to string diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 5ff5c0b5001d..23ce14620a64 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -216,7 +216,9 @@ def dump_value(self, arr, list_sep, indent): known_library_kwargs = ( build.known_shlib_kwargs | - build.known_stlib_kwargs + build.known_stlib_kwargs | + {f'{l}_shared_args' for l in compilers.all_languages - {'java'}} | + {f'{l}_static_args' for l in compilers.all_languages - {'java'}} ) known_build_target_kwargs = ( @@ -3202,6 +3204,9 @@ def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, Source # FIXME: rustc supports generating both libraries in a single invocation, # but for now compile twice. reuse_object_files = False + elif any(k.endswith(('static_args', 'shared_args')) and v for k, v in kwargs.items()): + # Ensure not just the keyword arguments exist, but that they are non-empty. + reuse_object_files = False else: reuse_object_files = static_lib.pic @@ -3336,6 +3341,16 @@ def build_target_decorator_caller(self, node, args, kwargs): raise RuntimeError('Unreachable code') self.kwarg_strings_to_includedirs(kwargs) self.__process_language_args(kwargs) + if targetclass is build.StaticLibrary: + for lang in compilers.all_languages - {'java'}: + deps, args = self.__convert_file_args(kwargs.get(f'{lang}_static_args', [])) + kwargs['language_args'][lang].extend(args) + kwargs['depend_files'].extend(deps) + elif targetclass is build.SharedLibrary: + for lang in compilers.all_languages - {'java'}: + deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', [])) + kwargs['language_args'][lang].extend(args) + kwargs['depend_files'].extend(deps) # Filter out kwargs from other target types. For example 'soversion' # passed to library() when default_library == 'static'. diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 45cb07b3d495..2f3f37f67908 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -397,6 +397,35 @@ class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): """For library, both_library, and as a base for build_target""" + c_static_args: NotRequired[T.List[str]] + c_shared_args: NotRequired[T.List[str]] + cpp_static_args: NotRequired[T.List[str]] + cpp_shared_args: NotRequired[T.List[str]] + cuda_static_args: NotRequired[T.List[str]] + cuda_shared_args: NotRequired[T.List[str]] + fortran_static_args: NotRequired[T.List[str]] + fortran_shared_args: NotRequired[T.List[str]] + d_static_args: NotRequired[T.List[str]] + d_shared_args: NotRequired[T.List[str]] + objc_static_args: NotRequired[T.List[str]] + objc_shared_args: NotRequired[T.List[str]] + objcpp_static_args: NotRequired[T.List[str]] + objcpp_shared_args: NotRequired[T.List[str]] + rust_static_args: NotRequired[T.List[str]] + rust_shared_args: NotRequired[T.List[str]] + vala_static_args: NotRequired[T.List[T.Union[str, File]]] # Yes, Vala is really special + vala_shared_args: NotRequired[T.List[T.Union[str, File]]] # Yes, Vala is really special + cs_static_args: NotRequired[T.List[str]] + cs_shared_args: NotRequired[T.List[str]] + swift_static_args: NotRequired[T.List[str]] + swift_shared_args: NotRequired[T.List[str]] + cython_static_args: NotRequired[T.List[str]] + cython_shared_args: NotRequired[T.List[str]] + nasm_static_args: NotRequired[T.List[str]] + nasm_shared_args: NotRequired[T.List[str]] + masm_static_args: NotRequired[T.List[str]] + masm_shared_args: NotRequired[T.List[str]] + class BuildTarget(Library): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 4b3a8a422a34..153a0d9e92bc 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -665,7 +665,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup _EXCLUSIVE_SHARED_LIB_KWS: T.List[KwargInfo] = [ _DARWIN_VERSIONS_KW, KwargInfo('soversion', (str, int, NoneType), convertor=lambda x: str(x) if x is not None else None), - KwargInfo('version', (str, NoneType), validator=_validate_shlib_version) + KwargInfo('version', (str, NoneType), validator=_validate_shlib_version), ] # The total list of arguments used by SharedLibrary @@ -712,6 +712,13 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup for a in _LANGUAGE_KWS], ] +_SHARED_STATIC_ARGS: T.List[KwargInfo[T.List[str]]] = [ + *[l.evolve(name=l.name.replace('_', '_static_'), since='1.3.0') + for l in _LANGUAGE_KWS], + *[l.evolve(name=l.name.replace('_', '_shared_'), since='1.3.0') + for l in _LANGUAGE_KWS], +] + # Arguments used by both_library and library LIBRARY_KWS = [ *_BUILD_TARGET_KWS, @@ -719,6 +726,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, + *_SHARED_STATIC_ARGS, _VS_MODULE_DEFS_KW, _JAVA_LANG_KW, ] @@ -730,6 +738,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, *_EXCLUSIVE_EXECUTABLE_KWS, + *_SHARED_STATIC_ARGS, *[a.evolve(deprecated='1.3.0', deprecated_message='The use of "jar" in "build_target()" is deprecated, and this argument is only used by jar()') for a in _EXCLUSIVE_JAR_KWS], KwargInfo( diff --git a/test cases/common/178 bothlibraries/meson.build b/test cases/common/178 bothlibraries/meson.build index 843a607a1e89..62f2061f8d67 100644 --- a/test cases/common/178 bothlibraries/meson.build +++ b/test cases/common/178 bothlibraries/meson.build @@ -55,9 +55,17 @@ test('runtest-both-2', exe_both2) # the executable linking using the C compiler. # https://github.com/Netflix/vmaf/issues/1107 libccpp = both_libraries('ccpp', 'foo.cpp', 'libfile.c', - cpp_args : ['-std=c++11']) + cpp_args : ['-std=c++11'], + c_static_args : ['-DSTATIC_COMPILATION'], + cpp_static_args : ['-DSTATIC_COMPILATION'], +) exe = executable('prog-ccpp', 'main2.c', link_with: libccpp.get_static_lib(), c_args : ['-DSTATIC_COMPILATION'], ) test('runtest-ccpp', exe) + +exe = executable('prog-ccpp-shared', 'main2.c', + link_with: libccpp.get_shared_lib(), +) +test('runtest-ccpp-shared', exe) diff --git a/test cases/common/3 static/lib3.c b/test cases/common/3 static/lib3.c new file mode 100644 index 000000000000..f834cf8b8422 --- /dev/null +++ b/test cases/common/3 static/lib3.c @@ -0,0 +1,11 @@ +int func3(const int x) { + return x + 1; +} + +#ifndef WORK +# error "did not get static only C args" +#endif + +#ifdef BREAK +# error "got shared only C args, but shouldn't have" +#endif diff --git a/test cases/common/3 static/meson.build b/test cases/common/3 static/meson.build index 04ff2f6f301e..1127ecb447f7 100644 --- a/test cases/common/3 static/meson.build +++ b/test cases/common/3 static/meson.build @@ -1,4 +1,4 @@ -project('static library test', 'c') +project('static library test', 'c', default_options : ['default_library=static']) lib = static_library('mylib', get_option('source'), link_args : '-THISMUSTNOBEUSED') # Static linker needs to ignore all link args. @@ -12,3 +12,8 @@ endif assert(has_not_changed, 'Static library has changed.') assert(not is_disabler(lib), 'Static library is a disabler.') + +if get_option('default_library') == 'static' + library('lib2', 'lib3.c', c_static_args : ['-DWORK'], c_shared_args : ['-DBREAK']) +endif +build_target('lib4', 'lib3.c', c_static_args : ['-DWORK'], target_type : 'static_library') diff --git a/test cases/common/4 shared/libfile2.c b/test cases/common/4 shared/libfile2.c new file mode 100644 index 000000000000..fee1d1efd872 --- /dev/null +++ b/test cases/common/4 shared/libfile2.c @@ -0,0 +1,22 @@ +#if defined _WIN32 || defined __CYGWIN__ + #define DLL_PUBLIC __declspec(dllexport) +#else + #if defined __GNUC__ + #define DLL_PUBLIC __attribute__ ((visibility("default"))) + #else + #pragma message ("Compiler does not support symbol visibility.") + #define DLL_PUBLIC + #endif +#endif + +#ifndef WORK +# error "Did not get shared only arguments" +#endif + +#ifdef BREAK +# error "got static only C args, but shouldn't have" +#endif + +int DLL_PUBLIC libfunc(void) { + return 3; +} diff --git a/test cases/common/4 shared/meson.build b/test cases/common/4 shared/meson.build index 1c88bc5877d6..7f79ad6302f4 100644 --- a/test cases/common/4 shared/meson.build +++ b/test cases/common/4 shared/meson.build @@ -1,4 +1,4 @@ -project('shared library test', 'c') +project('shared library test', 'c', default_options : ['default_library=shared']) lib = shared_library('mylib', 'libfile.c') build_target('mylib2', 'libfile.c', target_type: 'shared_library') @@ -11,3 +11,8 @@ endif assert(has_not_changed, 'Shared library has changed.') assert(not is_disabler(lib), 'Shared library is a disabler.') + +if get_option('default_library') == 'shared' + library('mylib5', 'libfile2.c', c_shared_args : ['-DWORK']) +endif +build_target('mylib4', 'libfile2.c', target_type: 'shared_library', c_shared_args : ['-DWORK'], c_static_args : ['-DBREAK']) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index f5048837f77a..18ed3bf5c193 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -394,7 +394,7 @@ def test_static_library_overwrite(self): self.init(testdir) # Get name of static library targets = self.introspect('--targets') - self.assertEqual(len(targets), 1) + self.assertGreaterEqual(len(targets), 1) libname = targets[0]['filename'][0] # Build and get contents of static library self.build() From b5b952688f03d69e947c144f4d928145e6e47a5f Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 9 Jun 2023 23:20:48 -0400 Subject: [PATCH 332/855] cargo: builder: Remove all duplicated functions Keep only the Builder class, there is no point in duplicating everything. --- mesonbuild/cargo/builder.py | 218 +++++++------------------------- mesonbuild/cargo/cfg.py | 58 ++++----- mesonbuild/cargo/interpreter.py | 5 +- unittests/cargotests.py | 102 +++++++-------- 4 files changed, 123 insertions(+), 260 deletions(-) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 3f7f6885e3d6..66fd00c27d4d 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -17,175 +17,26 @@ import builtins -def _token(tid: str, filename: str, value: mparser.TV_TokenTypes) -> mparser.Token[mparser.TV_TokenTypes]: - """Create a Token object, but with the line numbers stubbed out. - - :param tid: the token id (such as string, number, etc) - :param filename: the filename that the token was generated from - :param value: the value of the token - :return: A Token object - """ - return mparser.Token(tid, filename, -1, -1, -1, (-1, -1), value) - - -def _symbol(filename: str, val: str) -> mparser.SymbolNode: - return mparser.SymbolNode(_token('', filename, val)) - - -def string(value: str, filename: str) -> mparser.StringNode: - """Build A StringNode - - :param value: the value of the string - :param filename: the file that the value came from - :return: A StringNode - """ - return mparser.StringNode(_token('string', filename, value)) - - -def number(value: int, filename: str) -> mparser.NumberNode: - """Build A NumberNode - - :param value: the value of the number - :param filename: the file that the value came from - :return: A NumberNode - """ - return mparser.NumberNode(_token('number', filename, str(value))) - - -def bool(value: builtins.bool, filename: str) -> mparser.BooleanNode: - """Build A BooleanNode - - :param value: the value of the boolean - :param filename: the file that the value came from - :return: A BooleanNode - """ - return mparser.BooleanNode(_token('bool', filename, value)) - - -def array(value: T.List[mparser.BaseNode], filename: str) -> mparser.ArrayNode: - """Build an Array Node - - :param value: A list of nodes to insert into the array - :param filename: The file the array is from - :return: An ArrayNode built from the arguments - """ - args = mparser.ArgumentNode(_token('array', filename, 'unused')) - args.arguments = value - return mparser.ArrayNode(_symbol(filename, '['), args, _symbol(filename, ']')) - - -def identifier(value: str, filename: str) -> mparser.IdNode: - """Build A IdNode - - :param value: the value of the boolean - :param filename: the file that the value came from - :return: A BooleanNode - """ - return mparser.IdNode(_token('id', filename, value)) - - -def method(name: str, id_: mparser.IdNode, - pos: T.Optional[T.List[mparser.BaseNode]] = None, - kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, - ) -> mparser.MethodNode: - """Create a method call. - - :param name: the name of the method - :param id_: the object to call the method of - :param pos: a list of positional arguments, defaults to None - :param kw: a dictionary of keyword arguments, defaults to None - :return: a method call object - """ - args = mparser.ArgumentNode(_token('array', id_.filename, 'unused')) - if pos is not None: - args.arguments = pos - if kw is not None: - args.kwargs = {identifier(k, id_.filename): v for k, v in kw.items()} - return mparser.MethodNode(id_, _symbol(id_.filename, '.'), identifier(name, id_.filename), _symbol(id_.filename, '('), args, _symbol(id_.filename, ')')) - - -def function(name: str, filename: str, - pos: T.Optional[T.List[mparser.BaseNode]] = None, - kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, - ) -> mparser.FunctionNode: - """Create a function call. - - :param name: the name of the function - :param filename: The name of the current file being evaluated - :param pos: a list of positional arguments, defaults to None - :param kw: a dictionary of keyword arguments, defaults to None - :return: a method call object - """ - args = mparser.ArgumentNode(_token('array', filename, 'unused')) - if pos is not None: - args.arguments = pos - if kw is not None: - args.kwargs = {identifier(k, filename): v for k, v in kw.items()} - return mparser.FunctionNode(identifier(name, filename), _symbol(filename, '('), args, _symbol(filename, ')')) - - -def equal(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: - """Create an equality operation - - :param lhs: The left hand side of the equal - :param rhs: the right hand side of the equal - :return: A compraison node - """ - return mparser.ComparisonNode('==', lhs, _symbol(lhs.filename, '=='), rhs) - - -def or_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: - """Create and OrNode - - :param lhs: The Left of the Node - :param rhs: The Right of the Node - :return: The OrNode - """ - return mparser.OrNode(lhs, _symbol(lhs.filename, 'or'), rhs) - - -def and_(lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: - """Create an AndNode - - :param lhs: The left of the And - :param rhs: The right of the And - :return: The AndNode - """ - return mparser.AndNode(lhs, _symbol(lhs.filename, 'and'), rhs) - - -def not_(value: mparser.BaseNode, filename: str) -> mparser.NotNode: - """Create a not node - - :param value: The value to negate - :param filename: the string filename - :return: The NotNode - """ - return mparser.NotNode(_token('not', filename, ''), _symbol(filename, 'not'), value) - - -def assign(value: mparser.BaseNode, varname: str, filename: str) -> mparser.AssignmentNode: - """Create an AssignmentNode - - :param value: The rvalue - :param varname: The lvalue - :param filename: The filename - :return: An AssignmentNode - """ - return mparser.AssignmentNode(identifier(varname, filename), _symbol(filename, '='), value) - - -def block(filename: str) -> mparser.CodeBlockNode: - return mparser.CodeBlockNode(_token('node', filename, '')) - - @dataclasses.dataclass class Builder: filename: str + def _token(self, tid: str, value: mparser.TV_TokenTypes) -> mparser.Token[mparser.TV_TokenTypes]: + """Create a Token object, but with the line numbers stubbed out. + + :param tid: the token id (such as string, number, etc) + :param filename: the filename that the token was generated from + :param value: the value of the token + :return: A Token object + """ + return mparser.Token(tid, self.filename, -1, -1, -1, (-1, -1), value) + + def _symbol(self, val: str) -> mparser.SymbolNode: + return mparser.SymbolNode(self._token('', val)) + def assign(self, value: mparser.BaseNode, varname: str) -> mparser.AssignmentNode: - return assign(value, varname, self.filename) + return mparser.AssignmentNode(self.identifier(varname), self._symbol('='), value) def string(self, value: str) -> mparser.StringNode: """Build A StringNode @@ -193,7 +44,7 @@ def string(self, value: str) -> mparser.StringNode: :param value: the value of the string :return: A StringNode """ - return string(value, self.filename) + return mparser.StringNode(self._token('string', value)) def number(self, value: int) -> mparser.NumberNode: """Build A NumberNode @@ -201,7 +52,7 @@ def number(self, value: int) -> mparser.NumberNode: :param value: the value of the number :return: A NumberNode """ - return number(value, self.filename) + return mparser.NumberNode(self._token('number', str(value))) def bool(self, value: builtins.bool) -> mparser.BooleanNode: """Build A BooleanNode @@ -209,7 +60,7 @@ def bool(self, value: builtins.bool) -> mparser.BooleanNode: :param value: the value of the boolean :return: A BooleanNode """ - return bool(value, self.filename) + return mparser.BooleanNode(self._token('bool', value)) def array(self, value: T.List[mparser.BaseNode]) -> mparser.ArrayNode: """Build an Array Node @@ -217,7 +68,9 @@ def array(self, value: T.List[mparser.BaseNode]) -> mparser.ArrayNode: :param value: A list of nodes to insert into the array :return: An ArrayNode built from the arguments """ - return array(value, self.filename) + args = mparser.ArgumentNode(self._token('array', 'unused')) + args.arguments = value + return mparser.ArrayNode(self._symbol('['), args, self._symbol(']')) def identifier(self, value: str) -> mparser.IdNode: """Build A IdNode @@ -225,7 +78,7 @@ def identifier(self, value: str) -> mparser.IdNode: :param value: the value of the boolean :return: A BooleanNode """ - return identifier(value, self.filename) + return mparser.IdNode(self._token('id', value)) def method(self, name: str, id_: mparser.IdNode, pos: T.Optional[T.List[mparser.BaseNode]] = None, @@ -239,7 +92,12 @@ def method(self, name: str, id_: mparser.IdNode, :param kw: a dictionary of keyword arguments, defaults to None :return: a method call object """ - return method(name, id_, pos or [], kw or {}) + args = mparser.ArgumentNode(self._token('array', 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {self.identifier(k): v for k, v in kw.items()} + return mparser.MethodNode(id_, self._symbol('.'), self.identifier(name), self._symbol('('), args, self._symbol(')')) def function(self, name: str, pos: T.Optional[T.List[mparser.BaseNode]] = None, @@ -252,7 +110,12 @@ def function(self, name: str, :param kw: a dictionary of keyword arguments, defaults to None :return: a method call object """ - return function(name, self.filename, pos or [], kw or {}) + args = mparser.ArgumentNode(self._token('array', 'unused')) + if pos is not None: + args.arguments = pos + if kw is not None: + args.kwargs = {self.identifier(k): v for k, v in kw.items()} + return mparser.FunctionNode(self.identifier(name), self._symbol('('), args, self._symbol(')')) def equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: """Create an equality operation @@ -261,7 +124,7 @@ def equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.Compari :param rhs: the right hand side of the equal :return: A compraison node """ - return equal(lhs, rhs) + return mparser.ComparisonNode('==', lhs, self._symbol('=='), rhs) def or_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: """Create and OrNode @@ -270,7 +133,7 @@ def or_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: :param rhs: The Right of the Node :return: The OrNode """ - return or_(lhs, rhs) + return mparser.OrNode(lhs, self._symbol('or'), rhs) def and_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: """Create an AndNode @@ -279,12 +142,17 @@ def and_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.AndNode: :param rhs: The right of the And :return: The AndNode """ - return and_(lhs, rhs) + return mparser.AndNode(lhs, self._symbol('and'), rhs) - def not_(self, value: mparser.BaseNode, filename: str) -> mparser.NotNode: + def not_(self, value: mparser.BaseNode) -> mparser.NotNode: """Create a not node :param value: The value to negate :return: The NotNode """ - return not_(value, self.filename) + return mparser.NotNode(self._token('not', ''), self._symbol('not'), value) + + def block(self, lines: T.List[mparser.BaseNode]) -> mparser.CodeBlockNode: + block = mparser.CodeBlockNode(self._token('node', '')) + block.lines = lines + return block diff --git a/mesonbuild/cargo/cfg.py b/mesonbuild/cargo/cfg.py index ed6fd53d6843..0d49527cc2a0 100644 --- a/mesonbuild/cargo/cfg.py +++ b/mesonbuild/cargo/cfg.py @@ -130,7 +130,6 @@ class IR: """Base IR node for Cargo CFG.""" - filename: str @dataclasses.dataclass class String(IR): @@ -169,7 +168,7 @@ class Not(IR): value: IR -def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: +def _parse(ast: _LEX_STREAM_AH) -> IR: (token, value), n_stream = next(ast) if n_stream is not None: ntoken, _ = n_stream @@ -179,12 +178,12 @@ def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: stream: T.List[_LEX_TOKEN] if token is TokenType.IDENTIFIER: if ntoken is TokenType.EQUAL: - return Equal(filename, Identifier(filename, value), _parse(ast, filename)) + return Equal(Identifier(value), _parse(ast)) if token is TokenType.STRING: - return String(filename, value) + return String(value) if token is TokenType.EQUAL: # In this case the previous caller already has handled the equal - return _parse(ast, filename) + return _parse(ast) if token in {TokenType.ANY, TokenType.ALL}: type_ = All if token is TokenType.ALL else Any assert ntoken is TokenType.LPAREN @@ -194,13 +193,13 @@ def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: while token is not TokenType.RPAREN: (token, value), _ = next(ast) if token is TokenType.COMMA: - args.append(_parse(lookahead(iter(stream)), filename)) + args.append(_parse(lookahead(iter(stream)))) stream.clear() else: stream.append((token, value)) if stream: - args.append(_parse(lookahead(iter(stream)), filename)) - return type_(filename, args) + args.append(_parse(lookahead(iter(stream)))) + return type_(args) if token is TokenType.NOT: next(ast) # advance the iterator to get rid of the LPAREN stream = [] @@ -208,69 +207,68 @@ def _parse(ast: _LEX_STREAM_AH, filename: str) -> IR: while token is not TokenType.RPAREN: # type: ignore (token, value), _ = next(ast) stream.append((token, value)) - return Not(filename, _parse(lookahead(iter(stream)), filename)) + return Not(_parse(lookahead(iter(stream)))) raise MesonBugException(f'Unhandled Cargo token: {token}') -def parse(ast: _LEX_STREAM, filename: str) -> IR: +def parse(ast: _LEX_STREAM) -> IR: """Parse the tokenized list into Meson AST. :param ast: An iterable of Tokens - :param filename: The name of the file being parsed :return: An mparser Node to be used as a conditional """ ast_i: _LEX_STREAM_AH = lookahead(iter(ast)) - return _parse(ast_i, filename) + return _parse(ast_i) @functools.singledispatch -def ir_to_meson(ir: T.Any) -> mparser.BaseNode: +def ir_to_meson(ir: T.Any, build: builder.Builder) -> mparser.BaseNode: raise NotImplementedError @ir_to_meson.register -def _(ir: String) -> mparser.BaseNode: - return builder.string(ir.value, ir.filename) +def _(ir: String, build: builder.Builder) -> mparser.BaseNode: + return build.string(ir.value) @ir_to_meson.register -def _(ir: Identifier) -> mparser.BaseNode: - host_machine = builder.identifier('host_machine', ir.filename) +def _(ir: Identifier, build: builder.Builder) -> mparser.BaseNode: + host_machine = build.identifier('host_machine') if ir.value == "target_arch": - return builder.method('cpu_family', host_machine) + return build.method('cpu_family', host_machine) elif ir.value in {"target_os", "target_family"}: - return builder.method('system', host_machine) + return build.method('system', host_machine) elif ir.value == "target_endian": - return builder.method('endian', host_machine) + return build.method('endian', host_machine) raise MesonBugException(f"Unhandled Cargo identifier: {ir.value}") @ir_to_meson.register -def _(ir: Equal) -> mparser.BaseNode: - return builder.equal(ir_to_meson(ir.lhs), ir_to_meson(ir.rhs)) +def _(ir: Equal, build: builder.Builder) -> mparser.BaseNode: + return build.equal(ir_to_meson(ir.lhs, build), ir_to_meson(ir.rhs, build)) @ir_to_meson.register -def _(ir: Not) -> mparser.BaseNode: - return builder.not_(ir_to_meson(ir.value), ir.filename) +def _(ir: Not, build: builder.Builder) -> mparser.BaseNode: + return build.not_(ir_to_meson(ir.value, build)) @ir_to_meson.register -def _(ir: Any) -> mparser.BaseNode: +def _(ir: Any, build: builder.Builder) -> mparser.BaseNode: args = iter(reversed(ir.args)) last = next(args) - cur = builder.or_(ir_to_meson(next(args)), ir_to_meson(last)) + cur = build.or_(ir_to_meson(next(args), build), ir_to_meson(last, build)) for a in args: - cur = builder.or_(ir_to_meson(a), cur) + cur = build.or_(ir_to_meson(a, build), cur) return cur @ir_to_meson.register -def _(ir: All) -> mparser.BaseNode: +def _(ir: All, build: builder.Builder) -> mparser.BaseNode: args = iter(reversed(ir.args)) last = next(args) - cur = builder.and_(ir_to_meson(next(args)), ir_to_meson(last)) + cur = build.and_(ir_to_meson(next(args), build), ir_to_meson(last, build)) for a in args: - cur = builder.and_(ir_to_meson(a), cur) + cur = build.and_(ir_to_meson(a, build), cur) return cur diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 8848a46a8d63..d0cdbaac56ed 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -445,7 +445,4 @@ def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, 'src', 'lib.rs')): ast.extend(_create_lib(cargo, build)) - # XXX: make this not awful - block = builder.block(filename) - block.lines = ast - return block + return build.block(ast) diff --git a/unittests/cargotests.py b/unittests/cargotests.py index 61b64b1700de..e1bce1c898f3 100644 --- a/unittests/cargotests.py +++ b/unittests/cargotests.py @@ -104,83 +104,83 @@ def test_lex(self) -> None: def test_parse(self) -> None: cases = [ - ('target_os = "windows"', cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "windows"))), - ('target_arch = "x86"', cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86"))), - ('target_family = "unix"', cfg.Equal('', cfg.Identifier('', "target_family"), cfg.String('', "unix"))), + ('target_os = "windows"', cfg.Equal(cfg.Identifier("target_os"), cfg.String("windows"))), + ('target_arch = "x86"', cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86"))), + ('target_family = "unix"', cfg.Equal(cfg.Identifier("target_family"), cfg.String("unix"))), ('any(target_arch = "x86", target_arch = "x86_64")', cfg.Any( - '', [ - cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), - cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86_64")), + [ + cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), + cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86_64")), ])), ('all(target_arch = "x86", target_os = "linux")', cfg.All( - '', [ - cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), - cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + [ + cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), + cfg.Equal(cfg.Identifier("target_os"), cfg.String("linux")), ])), ('not(all(target_arch = "x86", target_os = "linux"))', cfg.Not( - '', cfg.All( - '', [ - cfg.Equal('', cfg.Identifier('', "target_arch"), cfg.String('', "x86")), - cfg.Equal('', cfg.Identifier('', "target_os"), cfg.String('', "linux")), + [ + cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), + cfg.Equal(cfg.Identifier("target_os"), cfg.String("linux")), ]))), ] for data, expected in cases: with self.subTest(): - self.assertEqual(cfg.parse(iter(cfg.lexer(data)), ''), expected) + self.assertEqual(cfg.parse(iter(cfg.lexer(data))), expected) def test_ir_to_meson(self) -> None: - HOST_MACHINE = builder.identifier('host_machine', '') + build = builder.Builder('') + HOST_MACHINE = build.identifier('host_machine') cases = [ ('target_os = "windows"', - builder.equal(builder.method('system', HOST_MACHINE), - builder.string('windows', ''))), + build.equal(build.method('system', HOST_MACHINE), + build.string('windows'))), ('target_arch = "x86"', - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', ''))), + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86'))), ('target_family = "unix"', - builder.equal(builder.method('system', HOST_MACHINE), - builder.string('unix', ''))), + build.equal(build.method('system', HOST_MACHINE), + build.string('unix'))), ('not(target_arch = "x86")', - builder.not_(builder.equal( - builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', '')), '')), + build.not_(build.equal( + build.method('cpu_family', HOST_MACHINE), + build.string('x86')))), ('any(target_arch = "x86", target_arch = "x86_64")', - builder.or_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', '')), - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86_64', '')))), + build.or_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86')), + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86_64')))), ('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', - builder.or_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', '')), - builder.or_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86_64', '')), - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('aarch64', ''))))), + build.or_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86')), + build.or_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86_64')), + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('aarch64'))))), ('all(target_arch = "x86", target_arch = "x86_64")', - builder.and_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', '')), - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86_64', '')))), + build.and_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86')), + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86_64')))), ('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', - builder.and_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86', '')), - builder.and_( - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('x86_64', '')), - builder.equal(builder.method('cpu_family', HOST_MACHINE), - builder.string('aarch64', ''))))), + build.and_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86')), + build.and_( + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('x86_64')), + build.equal(build.method('cpu_family', HOST_MACHINE), + build.string('aarch64'))))), ] for data, expected in cases: with self.subTest(): - value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data)), '')) + value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data))), build) self.assertEqual(value, expected) From 3334addbbd70122fc02174312299353ecf1a5bcc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 12:48:21 -0400 Subject: [PATCH 333/855] cargo: Builder: Add dict support --- mesonbuild/cargo/builder.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 66fd00c27d4d..17b4ca52c9a6 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -72,6 +72,17 @@ def array(self, value: T.List[mparser.BaseNode]) -> mparser.ArrayNode: args.arguments = value return mparser.ArrayNode(self._symbol('['), args, self._symbol(']')) + def dict(self, value: T.Dict[mparser.BaseNode, mparser.BaseNode]) -> mparser.DictNode: + """Build an Dictionary Node + + :param value: A dict of nodes to insert into the dictionary + :return: An DictNode built from the arguments + """ + args = mparser.ArgumentNode(self._token('dict', 'unused')) + for key, val in value.items(): + args.set_kwarg_no_check(key, val) + return mparser.DictNode(self._symbol('{'), args, self._symbol('}')) + def identifier(self, value: str) -> mparser.IdNode: """Build A IdNode From 05d5055d85344958809f3bcbfa222ae1a891af6b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 11:37:21 -0400 Subject: [PATCH 334/855] cargo: Remove unused function --- mesonbuild/cargo/interpreter.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index d0cdbaac56ed..16b709bc95b7 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -21,7 +21,6 @@ from . import builder from . import version -from .._pathlib import Path from ..mesonlib import MesonException, Popen_safe if T.TYPE_CHECKING: @@ -369,19 +368,6 @@ def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: return manifests -def load_all_manifests(subproject_dir: str) -> T.Dict[str, Manifest]: - """Find all cargo subprojects, and load them - - :param subproject_dir: Directory to look for subprojects in - :return: A dictionary of rust project names to Manifests - """ - manifests: T.Dict[str, Manifest] = {} - for p in Path(subproject_dir).iterdir(): - if p.is_dir() and (p / 'Cargo.toml').exists(): - manifests.update(_load_manifests(str(p))) - return manifests - - def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: kw: T.Dict[str, mparser.BaseNode] = {} if cargo.dependencies: From f752efdd88c251dfb070f444719cde13085f8884 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 10 Jun 2023 09:53:28 -0400 Subject: [PATCH 335/855] cargo: interpreter: Reorganize functions order Keep _create_foo() functions together and with a common signature. That's cleaner especially since we are going to add more of them. --- mesonbuild/cargo/interpreter.py | 105 ++++++++++++++++---------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 16b709bc95b7..0c4f52416dc5 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -77,6 +77,7 @@ def fixup_meson_varname(name: str) -> str: """ return name.replace('-', '_') + # Pylance can figure out that these do not, in fact, overlap, but mypy can't @T.overload def _fixup_raw_mappings(d: manifest.BuildTarget) -> manifest.FixedBuildTarget: ... # type: ignore @@ -269,35 +270,6 @@ class Manifest: path: str = '' -def _create_project(package: Package, build: builder.Builder, env: Environment) -> mparser.FunctionNode: - """Create a function call - - :param package: The Cargo package to generate from - :param filename: The full path to the file - :param meson_version: The generating meson version - :return: a FunctionNode - """ - args: T.List[mparser.BaseNode] = [] - args.extend([ - build.string(package.name), - build.string('rust'), - ]) - kwargs: T.Dict[str, mparser.BaseNode] = { - 'version': build.string(package.version), - # Always assume that the generated meson is using the latest features - # This will warn when when we generate deprecated code, which is helpful - # for the upkeep of the module - 'meson_version': build.string(f'>= {env.coredata.version}'), - 'default_options': build.array([build.string(f'rust_std={package.edition}')]), - } - if package.license: - kwargs['license'] = build.string(package.license) - elif package.license_file: - kwargs['license_files'] = build.string(package.license_file) - - return build.function('project', args, kwargs) - - def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = '') -> Manifest: # This cast is a bit of a hack to deal with proc-macro lib = _fixup_raw_mappings(raw_manifest.get('lib', {})) @@ -368,6 +340,57 @@ def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: return manifests +def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) -> T.List[mparser.BaseNode]: + """Create a function call + + :param cargo: The Manifest to generate from + :param build: The AST builder + :param env: Meson environment + :return: a list nodes + """ + args: T.List[mparser.BaseNode] = [] + args.extend([ + build.string(cargo.package.name), + build.string('rust'), + ]) + kwargs: T.Dict[str, mparser.BaseNode] = { + 'version': build.string(cargo.package.version), + # Always assume that the generated meson is using the latest features + # This will warn when when we generate deprecated code, which is helpful + # for the upkeep of the module + 'meson_version': build.string(f'>= {env.coredata.version}'), + 'default_options': build.array([build.string(f'rust_std={cargo.package.edition}')]), + } + if cargo.package.license: + kwargs['license'] = build.string(cargo.package.license) + elif cargo.package.license_file: + kwargs['license_files'] = build.string(cargo.package.license_file) + + return [build.function('project', args, kwargs)] + + +def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: + ast: T.List[mparser.BaseNode] = [ + build.assign(build.function('import', [build.string('rust')]), 'rust') + ] + for name, dep in cargo.dependencies.items(): + kw = { + 'version': build.array([build.string(s) for s in dep.version]), + } + ast.extend([ + build.assign( + build.method( + 'cargo', + build.identifier('rust'), + [build.string(name)], + kw, + ), + f'dep_{fixup_meson_varname(name)}', + ), + ]) + return ast + + def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: kw: T.Dict[str, mparser.BaseNode] = {} if cargo.dependencies: @@ -389,7 +412,6 @@ def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN ), 'lib' ), - build.assign( build.function( 'declare_dependency', @@ -404,27 +426,8 @@ def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') build = builder.Builder(filename) - ast: T.List[mparser.BaseNode] = [ - _create_project(cargo.package, build, env), - build.assign(build.function('import', [build.string('rust')]), 'rust'), - ] - - if cargo.dependencies: - for name, dep in cargo.dependencies.items(): - kw = { - 'version': build.array([build.string(s) for s in dep.version]), - } - ast.extend([ - build.assign( - build.method( - 'cargo', - build.identifier('rust'), - [build.string(name)], - kw, - ), - f'dep_{fixup_meson_varname(name)}', - ), - ]) + ast = _create_project(cargo, build, env) + ast += _create_dependencies(cargo, build) # Libs are always auto-discovered and there's no other way to handle them, # which is unfortunate for reproducability From 3abe52133df7911d400445a5006f29002bd1fc2c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 11:52:26 -0400 Subject: [PATCH 336/855] cargo: Use "-rs" suffix convention to lookup for Rust dependencies --- mesonbuild/cargo/interpreter.py | 36 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 0c4f52416dc5..e8390c610ec5 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -340,6 +340,14 @@ def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: return manifests +def _dependency_name(package_name: str) -> str: + return package_name if package_name.endswith('-rs') else f'{package_name}-rs' + + +def _dependency_varname(package_name: str) -> str: + return f'{fixup_meson_varname(package_name)}_dep' + + def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) -> T.List[mparser.BaseNode]: """Create a function call @@ -370,22 +378,19 @@ def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) - def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: - ast: T.List[mparser.BaseNode] = [ - build.assign(build.function('import', [build.string('rust')]), 'rust') - ] + ast: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): kw = { 'version': build.array([build.string(s) for s in dep.version]), } ast.extend([ build.assign( - build.method( - 'cargo', - build.identifier('rust'), - [build.string(name)], + build.function( + 'dependency', + [build.string(_dependency_name(name))], kw, ), - f'dep_{fixup_meson_varname(name)}', + _dependency_varname(name), ), ]) return ast @@ -394,9 +399,8 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: kw: T.Dict[str, mparser.BaseNode] = {} if cargo.dependencies: - ids = [build.identifier(f'dep_{n}') for n in cargo.dependencies] - kw['dependencies'] = build.array( - [build.method('get_variable', i, [build.string('dep')]) for i in ids]) + ids = [build.identifier(_dependency_varname(n)) for n in cargo.dependencies] + kw['dependencies'] = build.array(ids) # FIXME: currently assuming that an rlib is being generated, which is # the most common. @@ -418,7 +422,15 @@ def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN kw={'link_with': build.identifier('lib'), **kw}, ), 'dep' - ) + ), + build.method( + 'override_dependency', + build.identifier('meson'), + [ + build.string(_dependency_name(cargo.package.name)), + build.identifier('dep'), + ], + ), ] From 3a16da39adafb2349ba15d170c4b3cba078edd84 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 12:20:17 -0400 Subject: [PATCH 337/855] cargo: Add support for rust_dependency_map --- mesonbuild/cargo/interpreter.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index e8390c610ec5..f8419f7cf0ba 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -380,6 +380,7 @@ def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) - def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: ast: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): + package_name = dep.package or name kw = { 'version': build.array([build.string(s) for s in dep.version]), } @@ -387,20 +388,23 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.assign( build.function( 'dependency', - [build.string(_dependency_name(name))], + [build.string(_dependency_name(package_name))], kw, ), - _dependency_varname(name), + _dependency_varname(package_name), ), ]) return ast def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: - kw: T.Dict[str, mparser.BaseNode] = {} - if cargo.dependencies: - ids = [build.identifier(_dependency_varname(n)) for n in cargo.dependencies] - kw['dependencies'] = build.array(ids) + dependencies: T.List[mparser.BaseNode] = [] + dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {} + for name, dep in cargo.dependencies.items(): + package_name = dep.package or name + dependencies.append(build.identifier(_dependency_varname(package_name))) + if name != package_name: + dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) # FIXME: currently assuming that an rlib is being generated, which is # the most common. @@ -412,14 +416,19 @@ def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN build.string(fixup_meson_varname(cargo.package.name)), build.string(os.path.join('src', 'lib.rs')), ], - kw, + { + 'dependencies': build.array(dependencies), + 'rust_dependency_map': build.dict(dependency_map), + }, ), 'lib' ), build.assign( build.function( 'declare_dependency', - kw={'link_with': build.identifier('lib'), **kw}, + kw={ + 'link_with': build.identifier('lib'), + }, ), 'dep' ), From d6bf48cd7e8a4633f5f84428394bb4d44e5a462b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 8 Jun 2023 09:42:14 -0400 Subject: [PATCH 338/855] cargo: Package description is optional --- mesonbuild/cargo/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index f8419f7cf0ba..32c3705f7a66 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -116,7 +116,7 @@ class Package: name: str version: str - description: str + description: T.Optional[str] = None resolver: T.Optional[str] = None authors: T.List[str] = dataclasses.field(default_factory=list) edition: manifest.EDITION = '2015' From 019a0c38c6fc97fb3d3d595b3f0fd2c40a8af76f Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 8 Jun 2023 09:42:35 -0400 Subject: [PATCH 339/855] cargo: Support all crate library types --- mesonbuild/cargo/interpreter.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 32c3705f7a66..68517ba459d7 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -397,21 +397,33 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar return ast -def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: +def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CRATE_TYPE) -> T.List[mparser.BaseNode]: dependencies: T.List[mparser.BaseNode] = [] dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {} + rust_args: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): package_name = dep.package or name dependencies.append(build.identifier(_dependency_varname(package_name))) if name != package_name: dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) - # FIXME: currently assuming that an rlib is being generated, which is - # the most common. + if cargo.lib.proc_macro: + crate_type = 'proc-macro' + + if crate_type == 'proc-macro': + rust_args += [build.string('--extern'), build.string('proc_macro')] + + if crate_type in {'lib', 'rlib', 'staticlib'}: + target_type = 'static_library' + elif crate_type in {'dylib', 'cdylib', 'proc-macro'}: + target_type = 'shared_library' + else: + raise MesonException(f'Unsupported crate type {crate_type}') + return [ build.assign( build.function( - 'static_library', + target_type, [ build.string(fixup_meson_varname(cargo.package.name)), build.string(os.path.join('src', 'lib.rs')), @@ -419,6 +431,8 @@ def _create_lib(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN { 'dependencies': build.array(dependencies), 'rust_dependency_map': build.dict(dependency_map), + 'rust_crate_type': build.string(crate_type), + 'rust_args': build.array(rust_args) }, ), 'lib' @@ -453,6 +467,7 @@ def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: # Libs are always auto-discovered and there's no other way to handle them, # which is unfortunate for reproducability if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, 'src', 'lib.rs')): - ast.extend(_create_lib(cargo, build)) + for crate_type in cargo.lib.crate_type: + ast.extend(_create_lib(cargo, build, crate_type)) return build.block(ast) From ea42d2d01999c00c7fe7846de38416b8693bfb79 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 8 Jun 2023 16:51:19 -0400 Subject: [PATCH 340/855] cargo: Fix '1.0.45' version conversion The middle 0 was wrongly dropped. --- mesonbuild/cargo/version.py | 3 +-- unittests/cargotests.py | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/cargo/version.py b/mesonbuild/cargo/version.py index cb09a004b8d7..cde7a83a3d51 100644 --- a/mesonbuild/cargo/version.py +++ b/mesonbuild/cargo/version.py @@ -80,8 +80,7 @@ def convert(cargo_ver: str) -> T.List[str]: max_.append(str(int(v_) + 1)) bumped = True else: - if not (bumped and v_ == '0'): - min_.append(v_) + min_.append(v_) if not bumped: max_.append('0') diff --git a/unittests/cargotests.py b/unittests/cargotests.py index e1bce1c898f3..f0aedd0caec0 100644 --- a/unittests/cargotests.py +++ b/unittests/cargotests.py @@ -39,8 +39,9 @@ def test_cargo_to_meson(self) -> None: ('0.0', ['< 1']), ('0', ['< 1']), ('0.0.5', ['>= 0.0.5', '< 0.0.6']), - ('0.5.0', ['>= 0.5', '< 0.6']), + ('0.5.0', ['>= 0.5.0', '< 0.6']), ('0.5', ['>= 0.5', '< 0.6']), + ('1.0.45', ['>= 1.0.45', '< 2']), # Caret (Which is the same as unqualified) ('^2', ['>= 2', '< 3']), @@ -50,7 +51,7 @@ def test_cargo_to_meson(self) -> None: ('^0.0', ['< 1']), ('^0', ['< 1']), ('^0.0.5', ['>= 0.0.5', '< 0.0.6']), - ('^0.5.0', ['>= 0.5', '< 0.6']), + ('^0.5.0', ['>= 0.5.0', '< 0.6']), ('^0.5', ['>= 0.5', '< 0.6']), # Multiple requirements From dc329f0f04d917da5bf295e013f393caed4a85fc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 2 Jun 2023 12:11:45 -0400 Subject: [PATCH 341/855] interpreter: Add support for cargo subproject --- .../markdown/Wrap-dependency-system-manual.md | 21 ++++++++++++++++ docs/markdown/snippets/wrap.md | 3 ++- mesonbuild/cargo/__init__.py | 5 ++++ mesonbuild/cargo/interpreter.py | 8 +++++- mesonbuild/interpreter/interpreter.py | 25 ++++++++++++++----- mesonbuild/wrap/wrap.py | 3 ++- .../cmake/26 dependency fallback/meson.build | 2 +- test cases/rust/21 cargo subproject/main.c | 5 ++++ .../rust/21 cargo subproject/meson.build | 7 ++++++ .../subprojects/bar-rs.wrap | 2 ++ .../subprojects/bar-rs/Cargo.toml | 3 +++ .../subprojects/bar-rs/src/lib.rs | 1 + .../subprojects/foo-rs.wrap | 2 ++ .../subprojects/foo-rs/Cargo.toml | 10 ++++++++ .../subprojects/foo-rs/src/lib.rs | 4 +++ 15 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 test cases/rust/21 cargo subproject/main.c create mode 100644 test cases/rust/21 cargo subproject/meson.build create mode 100644 test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap create mode 100644 test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml create mode 100644 test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs create mode 100644 test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap create mode 100644 test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml create mode 100644 test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index 9000c40c7c16..e1e9474790cb 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -91,6 +91,7 @@ previously reserved to `wrap-file`: Supported methods: - `meson` requires `meson.build` file. - `cmake` requires `CMakeLists.txt` file. [See details](#cmake-wraps). + - `cargo` requires `Cargo.toml` file. [See details](#cargo-wraps). ### Specific to wrap-file - `source_url` - download url to retrieve the wrap-file source archive @@ -313,6 +314,26 @@ method = cmake [provide] foo-bar-1.0 = foo_bar_dep ``` +### Cargo wraps + +Cargo subprojects automatically override the `-rs` dependency name. +`package_name` is defined in `[package] name = ...` section of the `Cargo.toml` +and `-rs` suffix is added. That means the `.wrap` file should have +`dependency_names = foo-rs` in their `[provide]` section when `Cargo.toml` has +package name `foo`. + +Cargo subprojects require a toml parser. Python >= 3.11 have one built-in, older +Python versions require either the external `tomli` module or `toml2json` program. + +For example, a Cargo project with the package name `foo-bar` would have a wrap +file like that: +```ini +[wrap-file] +... +method = cargo +[provide] +dependency_names = foo-bar-rs +``` ## Using wrapped projects diff --git a/docs/markdown/snippets/wrap.md b/docs/markdown/snippets/wrap.md index 6e03c2e13ffa..3a5521efcdb1 100644 --- a/docs/markdown/snippets/wrap.md +++ b/docs/markdown/snippets/wrap.md @@ -1,4 +1,4 @@ -## Automatic fallback to `cmake` subproject +## Automatic fallback to `cmake` and `cargo` subproject CMake subprojects have been supported for a while using the `cmake.subproject()` module method. However until now it was not possible to use a CMake subproject @@ -10,3 +10,4 @@ key in the wrap file's first section. The method defaults to `meson`. Supported methods: - `meson` requires `meson.build` file. - `cmake` requires `CMakeLists.txt` file. [See details](Wrap-dependency-system-manual.md#cmake-wraps). +- `cargo` requires `Cargo.toml` file. [See details](Wrap-dependency-system-manual.md#cargo-wraps). diff --git a/mesonbuild/cargo/__init__.py b/mesonbuild/cargo/__init__.py index e69de29bb2d1..0007b9d6469b 100644 --- a/mesonbuild/cargo/__init__.py +++ b/mesonbuild/cargo/__init__.py @@ -0,0 +1,5 @@ +__all__ = [ + 'interpret' +] + +from .interpreter import interpret diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 68517ba459d7..12365bb1d614 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -457,7 +457,13 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR ] -def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode: +def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBlockNode: + package_name = subp_name[:-3] if subp_name.endswith('-rs') else subp_name + manifests = _load_manifests(os.path.join(env.source_dir, subdir)) + cargo = manifests.get(package_name) + if not cargo: + raise MesonException(f'Cargo package {package_name!r} not found in {subdir}') + filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') build = builder.Builder(filename) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 23ce14620a64..cc83cbd47bb3 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -930,13 +930,14 @@ def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_meth m += ['method', mlog.bold(method)] mlog.log(*m, '\n', nested=False) + methods_map: T.Dict[wrap.Method, T.Callable[[str, str, T.Dict[OptionKey, str, kwtypes.DoSubproject]], SubprojectHolder]] = { + 'meson': self._do_subproject_meson, + 'cmake': self._do_subproject_cmake, + 'cargo': self._do_subproject_cargo, + } + try: - if method == 'meson': - return self._do_subproject_meson(subp_name, subdir, default_options, kwargs) - elif method == 'cmake': - return self._do_subproject_cmake(subp_name, subdir, default_options, kwargs) - else: - raise mesonlib.MesonBugException(f'The method {method} is invalid for the subproject {subp_name}') + return methods_map[method](subp_name, subdir, default_options, kwargs) # Invalid code is always an error except InvalidCode: raise @@ -1038,6 +1039,18 @@ def _do_subproject_cmake(self, subp_name: str, subdir: str, result.cm_interpreter = cm_int return result + def _do_subproject_cargo(self, subp_name: str, subdir: str, + default_options: T.Dict[OptionKey, str], + kwargs: kwtypes.DoSubproject) -> SubprojectHolder: + from .. import cargo + FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node) + with mlog.nested(subp_name): + ast = cargo.interpret(subp_name, subdir, self.environment) + return self._do_subproject_meson( + subp_name, subdir, default_options, kwargs, ast, + # FIXME: Are there other files used by cargo interpreter? + [os.path.join(subdir, 'Cargo.toml')]) + def get_option_internal(self, optname: str) -> coredata.UserOption: key = OptionKey.from_string(optname).evolve(subproject=self.subproject) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 21a5c5d227e3..a5b4dc8ec6fe 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -47,7 +47,7 @@ import http.client from typing_extensions import Literal - Method = Literal['meson', 'cmake'] + Method = Literal['meson', 'cmake', 'cargo'] try: # Importing is just done to check if SSL exists, so all warnings @@ -450,6 +450,7 @@ def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> methods_map: T.Dict[Method, str] = { 'meson': 'meson.build', 'cmake': 'CMakeLists.txt', + 'cargo': 'Cargo.toml', } # Check if this wrap forces a specific method, use meson otherwise. diff --git a/test cases/cmake/26 dependency fallback/meson.build b/test cases/cmake/26 dependency fallback/meson.build index b36aaac58e37..871d70c9f8ea 100644 --- a/test cases/cmake/26 dependency fallback/meson.build +++ b/test cases/cmake/26 dependency fallback/meson.build @@ -9,7 +9,7 @@ test('test1', exe1) # to meson but wrap force cmake. subproject('force_cmake') -testcase expect_error('Wrap method \'notfound\' is not supported, must be one of: meson, cmake') +testcase expect_error('Wrap method \'notfound\' is not supported, must be one of: meson, cmake, cargo') subproject('broken_method') endtestcase diff --git a/test cases/rust/21 cargo subproject/main.c b/test cases/rust/21 cargo subproject/main.c new file mode 100644 index 000000000000..5daec64e3167 --- /dev/null +++ b/test cases/rust/21 cargo subproject/main.c @@ -0,0 +1,5 @@ +int rust_func(void); + +int main(int argc, char *argv[]) { + return rust_func(); +} diff --git a/test cases/rust/21 cargo subproject/meson.build b/test cases/rust/21 cargo subproject/meson.build new file mode 100644 index 000000000000..420e6e3b9ccf --- /dev/null +++ b/test cases/rust/21 cargo subproject/meson.build @@ -0,0 +1,7 @@ +project('cargo subproject', 'c') + +foo_dep = dependency('foo-rs') +exe = executable('app', 'main.c', + dependencies: foo_dep, +) +test('cargo-test', exe) diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap b/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap new file mode 100644 index 000000000000..99686e90e78e --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap @@ -0,0 +1,2 @@ +[wrap-file] +method = cargo diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml b/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml new file mode 100644 index 000000000000..232b4d7d445d --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "bar" +version = "0.1" diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs b/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs new file mode 100644 index 000000000000..5b64db8cc42f --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs @@ -0,0 +1 @@ +pub const VALUE: i32 = 0; diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap b/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap new file mode 100644 index 000000000000..99686e90e78e --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap @@ -0,0 +1,2 @@ +[wrap-file] +method = cargo diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml new file mode 100644 index 000000000000..214c3279c72e --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "foo" +version = "0.0.1" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +mybar = { version = "0.1", package = "bar" } diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs new file mode 100644 index 000000000000..732d7d20b10f --- /dev/null +++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn rust_func() -> i32 { + mybar::VALUE +} From 3af0632c3d02c552982737580cfac56adb72c8ad Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 9 Oct 2023 17:51:21 -0400 Subject: [PATCH 342/855] cargo: Use rust_abi and rust.proc_macro() instead of rust_crate_type --- mesonbuild/cargo/interpreter.py | 49 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 12365bb1d614..9e5910c093e4 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -400,43 +400,39 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CRATE_TYPE) -> T.List[mparser.BaseNode]: dependencies: T.List[mparser.BaseNode] = [] dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {} - rust_args: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): package_name = dep.package or name dependencies.append(build.identifier(_dependency_varname(package_name))) if name != package_name: dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) - if cargo.lib.proc_macro: - crate_type = 'proc-macro' + posargs: T.List[mparser.BaseNode] = [ + build.string(fixup_meson_varname(cargo.package.name)), + build.string(os.path.join('src', 'lib.rs')), + ] - if crate_type == 'proc-macro': - rust_args += [build.string('--extern'), build.string('proc_macro')] + kwargs: T.Dict[str, mparser.BaseNode] = { + 'dependencies': build.array(dependencies), + 'rust_dependency_map': build.dict(dependency_map), + } - if crate_type in {'lib', 'rlib', 'staticlib'}: - target_type = 'static_library' - elif crate_type in {'dylib', 'cdylib', 'proc-macro'}: - target_type = 'shared_library' + lib: mparser.BaseNode + if cargo.lib.proc_macro or crate_type == 'proc-macro': + kwargs['rust_args'] = build.array([build.string('--extern'), build.string('proc_macro')]) + lib = build.method('proc_macro', build.identifier('rust'), posargs, kwargs) else: - raise MesonException(f'Unsupported crate type {crate_type}') + if crate_type in {'lib', 'rlib', 'staticlib'}: + target_type = 'static_library' + elif crate_type in {'dylib', 'cdylib'}: + target_type = 'shared_library' + else: + raise MesonException(f'Unsupported crate type {crate_type}') + if crate_type in {'staticlib', 'cdylib'}: + kwargs['rust_abi'] = build.string('c') + lib = build.function(target_type, posargs, kwargs) return [ - build.assign( - build.function( - target_type, - [ - build.string(fixup_meson_varname(cargo.package.name)), - build.string(os.path.join('src', 'lib.rs')), - ], - { - 'dependencies': build.array(dependencies), - 'rust_dependency_map': build.dict(dependency_map), - 'rust_crate_type': build.string(crate_type), - 'rust_args': build.array(rust_args) - }, - ), - 'lib' - ), + build.assign(lib, 'lib'), build.assign( build.function( 'declare_dependency', @@ -468,6 +464,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBloc build = builder.Builder(filename) ast = _create_project(cargo, build, env) + ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')] ast += _create_dependencies(cargo, build) # Libs are always auto-discovered and there's no other way to handle them, From b78aa8f9e98c01d7be87fcb1cbcbea2ba33fb84a Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 7 Oct 2023 03:09:44 +0530 Subject: [PATCH 343/855] msubprojects: Abort the rebase if there's conflicts Don't leave the subproject tree in a broken / conflicting state. The user is most likely not a git expert who will know what magic command to run to fix their source tree. --- mesonbuild/msubprojects.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 45b711d13140..87905deb43cb 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -231,7 +231,9 @@ def git_rebase(self, revision: str) -> bool: try: self.git_output(['-c', 'rebase.autoStash=true', 'rebase', 'FETCH_HEAD']) except GitException as e: - self.log(' -> Could not rebase', mlog.bold(self.repo_dir), 'onto', mlog.bold(revision)) + self.git_output(['-c', 'rebase.autoStash=true', 'rebase', '--abort']) + self.log(' -> Could not rebase', mlog.bold(self.repo_dir), 'onto', mlog.bold(revision), + '-- aborted') self.log(mlog.red(e.output)) self.log(mlog.red(str(e))) return False From 3c6f04b29442ba1a06c572bf533b34fb91ef27ed Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 7 Oct 2023 03:10:41 +0530 Subject: [PATCH 344/855] msubprojects: Checkout if the branch is tracking upstream A rebase of the current branch is the wrong thing to do if the revision (branch) specified in the wrap changed, which is the case in the majority of cases, such as when switching from one release branch to another. --- mesonbuild/msubprojects.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 87905deb43cb..874364e18771 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -287,6 +287,19 @@ def git_checkout_and_rebase(self, revision: str) -> bool: success = self.git_rebase(revision) return success + def git_branch_has_upstream(self, urls: set) -> bool: + cmd = ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'] + ret, upstream = quiet_git(cmd, self.repo_dir) + if not ret: + return False + try: + remote = upstream.split('/', maxsplit=1)[0] + except IndexError: + return False + cmd = ['remote', 'get-url', remote] + ret, remote_url = quiet_git(cmd, self.repo_dir) + return remote_url.strip() in urls + def update_git(self) -> bool: options = T.cast('UpdateArguments', self.options) if not os.path.exists(os.path.join(self.repo_dir, '.git')): @@ -378,12 +391,16 @@ def update_git(self) -> bool: success = self.git_rebase(revision) else: # We are in another branch, either the user created their own branch and - # we should rebase it, or revision changed in the wrap file and we need - # to checkout the new branch. + # we should rebase it, or revision changed in the wrap file (we + # know this when the current branch has an upstream) and we need to + # checkout the new branch. if options.reset: success = self.git_checkout_and_reset(revision) else: - success = self.git_rebase(revision) + if self.git_branch_has_upstream({url, push_url}): + success = self.git_checkout_and_rebase(revision) + else: + success = self.git_rebase(revision) if success: self.update_git_done() return success From 208b31faf14ad1cfb0c1de10b02e668c36bdf1f5 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 20 Sep 2023 09:08:00 -0400 Subject: [PATCH 345/855] MSVCDynamicLinker: prevent duplicated /nologo argument --- mesonbuild/linkers/linkers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 5911a9fa34ef..dbb5e57aa585 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1315,7 +1315,7 @@ def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str] prefix, always_args, machine=machine, version=version, direct=direct) def get_always_args(self) -> T.List[str]: - return self._apply_prefix(['/nologo', '/release']) + super().get_always_args() + return self._apply_prefix(['/release']) + super().get_always_args() def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) From 4c9927e8b700a27ba300b9b6561f6ea223d35585 Mon Sep 17 00:00:00 2001 From: Ada Date: Tue, 10 Oct 2023 14:59:32 +0100 Subject: [PATCH 346/855] Fix MSVC linker error LNK1170 with long rspfiles The MSVC linker errors out if a line in the rspfile is too long. The resolution is to use the built-in ninja keyword $in_newline instead of $in, which splits each input into separate lines. --- mesonbuild/backend/ninjabackend.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3375b699e97d..3477b0a14b54 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -237,8 +237,10 @@ def _quoter(x, qf = quote_func): return ninja_quote(qf(str(x))) def write(self, outfile: T.TextIO) -> None: + rspfile_args = self.args if self.rspfile_quote_style is RSPFileSyntax.MSVC: rspfile_quote_func = cmd_quote + rspfile_args = [NinjaCommandArg('$in_newline', arg.quoting) if arg.s == '$in' else arg for arg in rspfile_args] else: rspfile_quote_func = gcc_rsp_quote @@ -253,7 +255,7 @@ def rule_iter(): if rsp == '_RSP': outfile.write(' command = {} @$out.rsp\n'.format(' '.join([self._quoter(x) for x in self.command]))) outfile.write(' rspfile = $out.rsp\n') - outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in self.args]))) + outfile.write(' rspfile_content = {}\n'.format(' '.join([self._quoter(x, rspfile_quote_func) for x in rspfile_args]))) else: outfile.write(' command = {}\n'.format(' '.join([self._quoter(x) for x in self.command + self.args]))) if self.deps: From c0a5da86494a00b3c242190f720c05b4cfb27740 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 29 Sep 2023 13:18:16 -0500 Subject: [PATCH 347/855] Use -idirafter when adding Apple framework include paths System headers will continue to "preempt" the framework headers. This should allow both and --- mesonbuild/dependencies/framework.py | 2 +- test cases/osx/5 extra frameworks/meson.build | 10 +++++++--- test cases/osx/5 extra frameworks/stat.c | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mesonbuild/dependencies/framework.py b/mesonbuild/dependencies/framework.py index b02b3ceb7d5b..6c0b1f14fae3 100644 --- a/mesonbuild/dependencies/framework.py +++ b/mesonbuild/dependencies/framework.py @@ -76,7 +76,7 @@ def detect(self, name: str, paths: T.List[str]) -> None: # https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Tasks/IncludingFrameworks.html incdir = self._get_framework_include_path(framework_path) if incdir: - self.compile_args += ['-I' + incdir] + self.compile_args += ['-idirafter' + incdir] self.is_found = True return diff --git a/test cases/osx/5 extra frameworks/meson.build b/test cases/osx/5 extra frameworks/meson.build index 0bd2c17fe6a6..f6c01e63a1bd 100644 --- a/test cases/osx/5 extra frameworks/meson.build +++ b/test cases/osx/5 extra frameworks/meson.build @@ -1,10 +1,14 @@ project('xcode extra framework test', 'c') -dep_libs = dependency('OpenGL', method : 'extraframework') -assert(dep_libs.type_name() == 'extraframeworks', 'type_name is ' + dep_libs.type_name()) +opengl_dep = dependency('OpenGL', method : 'extraframework') +assert(opengl_dep.type_name() == 'extraframeworks', 'type_name is ' + opengl_dep.type_name()) dep_main = dependency('Foundation') assert(dep_main.type_name() == 'extraframeworks', 'type_name is ' + dep_main.type_name()) -stlib = static_library('stat', 'stat.c', install : true, dependencies: dep_libs) +# https://github.com/mesonbuild/meson/issues/10002 +ldap_dep = dependency('ldap', method : 'extraframework') +assert(ldap_dep.type_name() == 'extraframeworks', 'type_name is ' + ldap_dep.type_name()) + +stlib = static_library('stat', 'stat.c', install : true, dependencies: [opengl_dep, ldap_dep]) exe = executable('prog', 'prog.c', install : true, dependencies: dep_main) diff --git a/test cases/osx/5 extra frameworks/stat.c b/test cases/osx/5 extra frameworks/stat.c index 4825cefd245c..79a3974dafc8 100644 --- a/test cases/osx/5 extra frameworks/stat.c +++ b/test cases/osx/5 extra frameworks/stat.c @@ -1 +1,4 @@ +// https://github.com/mesonbuild/meson/issues/10002 +#include + int func(void) { return 933; } From 4ae75eef16ce821e8d551fd8f0eb70ab6e194553 Mon Sep 17 00:00:00 2001 From: Mattijs Korpershoek Date: Wed, 11 Oct 2023 15:04:38 +0200 Subject: [PATCH 348/855] cpp: use -nostlib++ instead of -nostlib for custom cpp_stdlib The _stdlib can be used in cross files to use a custom standard library for a given language. When cpp_stdlib is used in a cross file, meson passes * -nostdinc++ to the compiler * -nostlib to the linker According to [1] (gcc) and [2] (clang), we should pass -nostlib++ to the linker when we don't want to link to the standard C++ library. Currently, we pass -nostlib. Fix this by implementing a C++ specific get_no_stdlib_link_args() function. [1] https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#index-nostdlib_002b_002b [2] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-nostdlib Signed-off-by: Mattijs Korpershoek --- mesonbuild/compilers/cpp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index dc733dd9ed38..43a5492f0560 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -93,6 +93,9 @@ def get_display_language(cls) -> str: def get_no_stdinc_args(self) -> T.List[str]: return ['-nostdinc++'] + def get_no_stdlib_link_args(self) -> T.List[str]: + return ['-nostdlib++'] + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: code = 'class breakCCompiler;int main(void) { return 0; }\n' return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) From 4ebe03713dd5bd240efe0198907f4662bb730c8c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 12 Oct 2023 05:40:07 +0530 Subject: [PATCH 349/855] ninjabackend: Use the right ranlib for static linker rules Fixes https://github.com/mesonbuild/meson/issues/12349 --- mesonbuild/backend/ninjabackend.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3477b0a14b54..b0fec89b352e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2355,7 +2355,12 @@ def generate_static_link_rules(self): # ranlib, not to ar cmdlist.extend(args) args = [] - cmdlist.extend(['&&', 'ranlib', '-c', '$out']) + # Ensure that we use the user-specified ranlib if any, and + # fallback to just picking up some ranlib otherwise + ranlib = self.environment.lookup_binary_entry(for_machine, 'ranlib') + if ranlib is None: + ranlib = ['ranlib'] + cmdlist.extend(['&&'] + ranlib + ['-c', '$out']) description = 'Linking static target $out' if num_pools > 0: pool = 'pool = link_pool' From 19beb070e8d3f130df6301e43a6fc940c7268ace Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 4 Oct 2023 11:07:56 -0700 Subject: [PATCH 350/855] interpreter: use typed_kwargs for build_target.d_debug --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 2f3f37f67908..daa5d4dfe706 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -333,6 +333,7 @@ class _BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" + d_debug: T.List[T.Union[str, int]] rust_dependency_map: T.Dict[str, str] sources: SourcesVarargsType c_args: T.List[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 153a0d9e92bc..08e9b3878b5c 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -560,6 +560,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus *_LANGUAGE_KWS, BT_SOURCES_KW, RUST_CRATE_TYPE_KW, + KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), KwargInfo( 'rust_dependency_map', ContainerTypeInfo(dict, str), From 9b1efa37fd10b8c160c6a9ec58714edc6d899336 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 4 Oct 2023 12:52:18 -0700 Subject: [PATCH 351/855] interpreter: use typed_kwargs for build_target.d_import_dirs --- mesonbuild/build.py | 8 ++------ mesonbuild/interpreter/interpreter.py | 11 ++++++----- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index ac2993fec487..0f6f8e3cf695 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1124,12 +1124,8 @@ def process_kwargs(self, kwargs): dfeature_debug = kwargs.get('d_debug', []) if dfeature_debug: dfeatures['debug'] = dfeature_debug - if 'd_import_dirs' in kwargs: - dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs') - for d in dfeature_import_dirs: - if not isinstance(d, IncludeDirs): - raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') - dfeatures['import_dirs'] = dfeature_import_dirs + if kwargs.get('d_import_dirs') is not None: + dfeatures['import_dirs'] = kwargs['d_import_dirs'] if dfeatures: self.d_features = dfeatures diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index cc83cbd47bb3..1bfcda0fb49e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3352,7 +3352,6 @@ def build_target_decorator_caller(self, node, args, kwargs): if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}: mlog.debug('Unknown target type:', str(targetclass)) raise RuntimeError('Unreachable code') - self.kwarg_strings_to_includedirs(kwargs) self.__process_language_args(kwargs) if targetclass is build.StaticLibrary: for lang in compilers.all_languages - {'java'}: @@ -3364,6 +3363,8 @@ def build_target_decorator_caller(self, node, args, kwargs): deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', [])) kwargs['language_args'][lang].extend(args) kwargs['depend_files'].extend(deps) + if targetclass is not build.Jar: + self.kwarg_strings_to_includedirs(kwargs) # Filter out kwargs from other target types. For example 'soversion' # passed to library() when default_library == 'static'. @@ -3436,10 +3437,10 @@ def build_target_decorator_caller(self, node, args, kwargs): self.project_args_frozen = True return target - def kwarg_strings_to_includedirs(self, kwargs): - if 'd_import_dirs' in kwargs: - items = mesonlib.extract_as_list(kwargs, 'd_import_dirs') - cleaned_items = [] + def kwarg_strings_to_includedirs(self, kwargs: kwtypes._BuildTarget) -> None: + if kwargs['d_import_dirs']: + items = kwargs['d_import_dirs'] + cleaned_items: T.List[build.IncludeDirs] = [] for i in items: if isinstance(i, str): # BW compatibility. This was permitted so we must support it diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index daa5d4dfe706..af5593d07a77 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -334,6 +334,7 @@ class _BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" d_debug: T.List[T.Union[str, int]] + d_import_dirs: T.List[T.Union[str, build.IncludeDirs]] rust_dependency_map: T.Dict[str, str] sources: SourcesVarargsType c_args: T.List[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 08e9b3878b5c..ee69ab7db1f1 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -559,6 +559,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus *_ALL_TARGET_KWS, *_LANGUAGE_KWS, BT_SOURCES_KW, + INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'), RUST_CRATE_TYPE_KW, KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), KwargInfo( From 2048d1333e2db36686a45444f58cf5c96c44e6e4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 4 Oct 2023 12:55:17 -0700 Subject: [PATCH 352/855] interpreter: use typed_kwargs for build_target.d_module_versions --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index af5593d07a77..41d7a753a504 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -335,6 +335,7 @@ class _BuildTarget(_BaseBuildTarget): d_debug: T.List[T.Union[str, int]] d_import_dirs: T.List[T.Union[str, build.IncludeDirs]] + d_module_versions: T.List[T.Union[str, int]] rust_dependency_map: T.Dict[str, str] sources: SourcesVarargsType c_args: T.List[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index ee69ab7db1f1..df17a43ef721 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -562,6 +562,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'), RUST_CRATE_TYPE_KW, KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), + D_MODULE_VERSIONS_KW, KwargInfo( 'rust_dependency_map', ContainerTypeInfo(dict, str), From 7c101413d026ee50d950db1c5fcff48c20c757da Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 4 Oct 2023 12:57:13 -0700 Subject: [PATCH 353/855] interpreter: use typed_kwargs for build_target.d_unittest --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 41d7a753a504..b4a389be3628 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -336,6 +336,7 @@ class _BuildTarget(_BaseBuildTarget): d_debug: T.List[T.Union[str, int]] d_import_dirs: T.List[T.Union[str, build.IncludeDirs]] d_module_versions: T.List[T.Union[str, int]] + d_unittest: bool rust_dependency_map: T.Dict[str, str] sources: SourcesVarargsType c_args: T.List[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index df17a43ef721..82f770fa9d5d 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -563,6 +563,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus RUST_CRATE_TYPE_KW, KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), D_MODULE_VERSIONS_KW, + KwargInfo('d_unittest', bool, default=False), KwargInfo( 'rust_dependency_map', ContainerTypeInfo(dict, str), From b2f681c92a3efb0bb77cf75ba5146c13cf54b2b5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 7 Mar 2023 15:05:37 -0800 Subject: [PATCH 354/855] build: use a TypedDict for d_features This allows for better type checking. --- mesonbuild/build.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 0f6f8e3cf695..8185ef4cf0bc 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -44,7 +44,7 @@ from .interpreterbase import FeatureNew, FeatureDeprecated if T.TYPE_CHECKING: - from typing_extensions import Literal + from typing_extensions import Literal, TypedDict from . import environment from ._typing import ImmutableListProtocol @@ -64,6 +64,13 @@ BuildTargetTypes = T.Union['BuildTarget', 'CustomTarget', 'CustomTargetIndex'] ObjectTypes = T.Union[str, 'File', 'ExtractedObjects', 'GeneratedTypes'] + class DFeatures(TypedDict): + + unittest: bool + debug: T.List[T.Union[str, int]] + import_dirs: T.List[IncludeDirs] + versions: T.List[T.Union[str, int]] + pch_kwargs = {'c_pch', 'cpp_pch'} lang_arg_kwargs = {f'{lang}_args' for lang in all_languages} @@ -751,7 +758,12 @@ def __init__( self.sources: T.List[File] = [] self.generated: T.List['GeneratedTypes'] = [] self.extra_files: T.List[File] = [] - self.d_features = defaultdict(list) + self.d_features: DFeatures = { + 'debug': kwargs.get('d_debug', []), + 'import_dirs': kwargs.get('d_import_dirs', []), + 'versions': kwargs.get('d_module_versions', []), + 'unittest': kwargs.get('d_unittest', False), + } self.pic = False self.pie = False # Track build_rpath entries so we can remove them at install time @@ -1114,21 +1126,6 @@ def process_kwargs(self, kwargs): self.vala_vapi = kwargs.get('vala_vapi', self.name + '.vapi') self.vala_gir = kwargs.get('vala_gir', None) - dfeatures = defaultdict(list) - dfeature_unittest = kwargs.get('d_unittest', False) - if dfeature_unittest: - dfeatures['unittest'] = dfeature_unittest - dfeature_versions = kwargs.get('d_module_versions', []) - if dfeature_versions: - dfeatures['versions'] = dfeature_versions - dfeature_debug = kwargs.get('d_debug', []) - if dfeature_debug: - dfeatures['debug'] = dfeature_debug - if kwargs.get('d_import_dirs') is not None: - dfeatures['import_dirs'] = kwargs['d_import_dirs'] - if dfeatures: - self.d_features = dfeatures - self.link_args = extract_as_list(kwargs, 'link_args') for i in self.link_args: if not isinstance(i, str): From 6599c32fd3f1128bb0dfdc7acb3162510791c61b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 4 Oct 2023 13:07:25 -0700 Subject: [PATCH 355/855] compilers/d: remove duplicate method from subclass The DCompiler and DmDLikeCompiler classes both implement the exact same `get_feature_args()` method. The DmdLikeCompiler inherits the DCompiler. As such, removing it doesn't change the behavior of anything, but decreases the chances of bugs being introduced, as well as LoC. --- mesonbuild/compilers/d.py | 88 --------------------------------------- 1 file changed, 88 deletions(-) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 08ebb7583e06..8b35f022b63b 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -170,94 +170,6 @@ def get_pic_args(self) -> T.List[str]: return [] return ['-fPIC'] - def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: - # TODO: using a TypeDict here would improve this - res: T.List[str] = [] - # get_feature_args can be called multiple times for the same target when there is generated source - # so we have to copy the kwargs (target.d_features) dict before popping from it - kwargs = kwargs.copy() - if 'unittest' in kwargs: - unittest = kwargs.pop('unittest') - unittest_arg = d_feature_args[self.id]['unittest'] - if not unittest_arg: - raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) - if unittest: - res.append(unittest_arg) - - if 'debug' in kwargs: - debug_level = -1 - debugs = kwargs.pop('debug') - if not isinstance(debugs, list): - debugs = [debugs] - - debug_arg = d_feature_args[self.id]['debug'] - if not debug_arg: - raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string()) - - # Parse all debug identifiers and the largest debug level identifier - for d in debugs: - if isinstance(d, int): - if d > debug_level: - debug_level = d - elif isinstance(d, str) and d.isdigit(): - if int(d) > debug_level: - debug_level = int(d) - else: - res.append(f'{debug_arg}={d}') - - if debug_level >= 0: - res.append(f'{debug_arg}={debug_level}') - - if 'versions' in kwargs: - version_level = -1 - versions = kwargs.pop('versions') - if not isinstance(versions, list): - versions = [versions] - - version_arg = d_feature_args[self.id]['version'] - if not version_arg: - raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string()) - - # Parse all version identifiers and the largest version level identifier - for v in versions: - if isinstance(v, int): - if v > version_level: - version_level = v - elif isinstance(v, str) and v.isdigit(): - if int(v) > version_level: - version_level = int(v) - else: - res.append(f'{version_arg}={v}') - - if version_level >= 0: - res.append(f'{version_arg}={version_level}') - - if 'import_dirs' in kwargs: - import_dirs = kwargs.pop('import_dirs') - if not isinstance(import_dirs, list): - import_dirs = [import_dirs] - - import_dir_arg = d_feature_args[self.id]['import_dir'] - if not import_dir_arg: - raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) - for idir_obj in import_dirs: - basedir = idir_obj.get_curdir() - for idir in idir_obj.get_incdirs(): - bldtreedir = os.path.join(basedir, idir) - # Avoid superfluous '/.' at the end of paths when d is '.' - if idir not in ('', '.'): - expdir = bldtreedir - else: - expdir = basedir - srctreedir = os.path.join(build_to_src, expdir) - res.append(f'{import_dir_arg}{srctreedir}') - res.append(f'{import_dir_arg}{bldtreedir}') - - if kwargs: - raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) - - return res - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: if buildtype != 'plain': return self._get_target_arch_args() From 74771d211946eb1d966051af1f310e0934bacd3d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 18 Jan 2023 13:24:43 -0800 Subject: [PATCH 356/855] compilers/d: use DFeatures for get_features_args --- mesonbuild/compilers/compilers.py | 4 +- mesonbuild/compilers/d.py | 145 +++++++++++++----------------- mesonbuild/modules/pkgconfig.py | 3 +- 3 files changed, 66 insertions(+), 86 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index c7af1cac6841..5f2e304dd997 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -32,7 +32,7 @@ from ..arglist import CompilerArgs if T.TYPE_CHECKING: - from ..build import BuildTarget + from ..build import BuildTarget, DFeatures from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment @@ -1331,7 +1331,7 @@ def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, return self.compiles(code, env, extra_args=extra_args, dependencies=dependencies, mode=CompileCheckMode.LINK, disable_cache=disable_cache) - def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: + def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]: """Used by D for extra language features.""" # TODO: using a TypeDict here would improve this raise EnvironmentException(f'{self.id} does not implement get_feature_args') diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 8b35f022b63b..05f3b7d8d6e8 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -39,6 +39,7 @@ from .mixins.gnu import gnu_common_warning_args if T.TYPE_CHECKING: + from ..build import DFeatures from ..dependencies import Dependency from ..programs import ExternalProgram from ..envconfig import MachineInfo @@ -498,91 +499,69 @@ def get_pic_args(self) -> T.List[str]: return [] return ['-fPIC'] - def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: - # TODO: using a TypeDict here would improve this + def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]: res: T.List[str] = [] - # get_feature_args can be called multiple times for the same target when there is generated source - # so we have to copy the kwargs (target.d_features) dict before popping from it - kwargs = kwargs.copy() - if 'unittest' in kwargs: - unittest = kwargs.pop('unittest') - unittest_arg = d_feature_args[self.id]['unittest'] - if not unittest_arg: - raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) - if unittest: - res.append(unittest_arg) - - if 'debug' in kwargs: - debug_level = -1 - debugs = kwargs.pop('debug') - if not isinstance(debugs, list): - debugs = [debugs] - - debug_arg = d_feature_args[self.id]['debug'] - if not debug_arg: - raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string()) - - # Parse all debug identifiers and the largest debug level identifier - for d in debugs: - if isinstance(d, int): - if d > debug_level: - debug_level = d - elif isinstance(d, str) and d.isdigit(): - if int(d) > debug_level: - debug_level = int(d) - else: - res.append(f'{debug_arg}={d}') - - if debug_level >= 0: - res.append(f'{debug_arg}={debug_level}') - - if 'versions' in kwargs: - version_level = -1 - versions = kwargs.pop('versions') - if not isinstance(versions, list): - versions = [versions] - - version_arg = d_feature_args[self.id]['version'] - if not version_arg: - raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string()) - - # Parse all version identifiers and the largest version level identifier - for v in versions: - if isinstance(v, int): - if v > version_level: - version_level = v - elif isinstance(v, str) and v.isdigit(): - if int(v) > version_level: - version_level = int(v) + unittest_arg = d_feature_args[self.id]['unittest'] + if not unittest_arg: + raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string()) + if kwargs['unittest']: + res.append(unittest_arg) + + debug_level = -1 + debug_arg = d_feature_args[self.id]['debug'] + if not debug_arg: + raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string()) + + # Parse all debug identifiers and the largest debug level identifier + for d in kwargs['debug']: + if isinstance(d, int): + if d > debug_level: + debug_level = d + elif isinstance(d, str) and d.isdigit(): + if int(d) > debug_level: + debug_level = int(d) + else: + res.append(f'{debug_arg}={d}') + + if debug_level >= 0: + res.append(f'{debug_arg}={debug_level}') + + version_level = -1 + version_arg = d_feature_args[self.id]['version'] + if not version_arg: + raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string()) + + # Parse all version identifiers and the largest version level identifier + for v in kwargs['versions']: + if isinstance(v, int): + if v > version_level: + version_level = v + elif isinstance(v, str) and v.isdigit(): + if int(v) > version_level: + version_level = int(v) + else: + res.append(f'{version_arg}={v}') + + if version_level >= 0: + res.append(f'{version_arg}={version_level}') + + import_dir_arg = d_feature_args[self.id]['import_dir'] + if not import_dir_arg: + raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) + # TODO: ImportDirs.to_string_list(), but we need both the project source + # root and project build root for that. + for idir_obj in kwargs['import_dirs']: + basedir = idir_obj.get_curdir() + for idir in idir_obj.get_incdirs(): + bldtreedir = os.path.join(basedir, idir) + # Avoid superfluous '/.' at the end of paths when d is '.' + if idir not in ('', '.'): + expdir = bldtreedir else: - res.append(f'{version_arg}={v}') - - if version_level >= 0: - res.append(f'{version_arg}={version_level}') - - if 'import_dirs' in kwargs: - import_dirs = kwargs.pop('import_dirs') - if not isinstance(import_dirs, list): - import_dirs = [import_dirs] - - import_dir_arg = d_feature_args[self.id]['import_dir'] - if not import_dir_arg: - raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string()) - for idir_obj in import_dirs: - basedir = idir_obj.get_curdir() - for idir in idir_obj.get_incdirs(): - bldtreedir = os.path.join(basedir, idir) - # Avoid superfluous '/.' at the end of paths when d is '.' - if idir not in ('', '.'): - expdir = bldtreedir - else: - expdir = basedir - srctreedir = os.path.join(build_to_src, expdir) - res.append(f'{import_dir_arg}{srctreedir}') - res.append(f'{import_dir_arg}{bldtreedir}') - - if kwargs: - raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys())) + expdir = basedir + srctreedir = os.path.join(build_to_src, expdir) + res.append(f'{import_dir_arg}{srctreedir}') + res.append(f'{import_dir_arg}{bldtreedir}') return res diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 75521b886869..ee12293cdb3b 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -682,7 +682,8 @@ def generate(self, state: ModuleState, if dversions: compiler = state.environment.coredata.compilers.host.get('d') if compiler: - deps.add_cflags(compiler.get_feature_args({'versions': dversions}, None)) + deps.add_cflags(compiler.get_feature_args( + {'versions': dversions, 'import_dirs': [], 'debug': [], 'unittest': False}, None)) deps.remove_dups() From 658fe7243b1415bd4d2d1ae36d9beb3ed33c5e67 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 15:17:31 -0700 Subject: [PATCH 357/855] modules/rust: remove rust_crate_type for test() method This is required to test non-executable targets when they set an explicit type. --- mesonbuild/modules/rust.py | 1 + test cases/rust/9 unit tests/meson.build | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 98bf05312cf0..0781b32001ac 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -162,6 +162,7 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func new_target_kwargs['install'] = False new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies'] new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with'] + del new_target_kwargs['rust_crate_type'] lang_args = base_target.extra_args.copy() lang_args['rust'] = base_target.extra_args['rust'] + kwargs['rust_args'] + ['--test'] diff --git a/test cases/rust/9 unit tests/meson.build b/test cases/rust/9 unit tests/meson.build index 94cc400d42d8..b444271ae18c 100644 --- a/test cases/rust/9 unit tests/meson.build +++ b/test cases/rust/9 unit tests/meson.build @@ -36,7 +36,7 @@ exe = executable('rust_exe', ['test2.rs', 'test.rs'], build_by_default : false) rust = import('unstable-rust') rust.test('rust_test_from_exe', exe, should_fail : true) -lib = static_library('rust_static', ['test.rs'], build_by_default : false) +lib = static_library('rust_static', ['test.rs'], build_by_default : false, rust_crate_type : 'lib') rust.test('rust_test_from_static', lib, args: ['--skip', 'test_add_intentional_fail']) lib = shared_library('rust_shared', ['test.rs'], build_by_default : false) From 5fcf3476614a971079b43866c1ba8830ac15ba8c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 09:50:34 -0700 Subject: [PATCH 358/855] modules/rust: only use include and define args from global/project args --- mesonbuild/modules/rust.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 0781b32001ac..3d0bdd59a81b 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -12,8 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations +import itertools import os import typing as T + from mesonbuild.interpreterbase.decorators import FeatureNew from . import ExtensionModule, ModuleReturnValue, ModuleInfo @@ -238,11 +240,13 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu elif isinstance(s, CustomTarget): depends.append(s) - clang_args.extend(state.global_args.get('c', [])) - clang_args.extend(state.project_args.get('c', [])) + # We only want include directories and defines, other things may not be valid cargs = state.get_option('args', state.subproject, lang='c') assert isinstance(cargs, list), 'for mypy' clang_args.extend(cargs) + for a in itertools.chain(state.global_args.get('c', []), state.project_args.get('c', []), cargs): + if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): + clang_args.append(a) if self._bindgen_bin is None: self._bindgen_bin = state.find_program('bindgen') From 746c4eff48a2256faf428918198dc83d75b58206 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 16 Oct 2023 17:34:59 -0400 Subject: [PATCH 359/855] msubprojects: Fix crash if wrapdb_version is in bad format Fixes: #12378 --- mesonbuild/msubprojects.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 874364e18771..6b107c063984 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -155,6 +155,11 @@ def update_wrapdb(self) -> bool: try: wrapdb_version = self.wrap.get('wrapdb_version') branch, revision = wrapdb_version.split('-', 1) + except ValueError: + if not options.force: + self.log(' ->', mlog.red('Malformed wrapdb_version field, use --force to update any way')) + return False + branch = revision = None except WrapException: # Fallback to parsing the patch URL to determine current version. # This won't work for projects that have upstream Meson support. From bd0ab92bba0a1b149fd190170db78745698c862c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 17 Oct 2023 13:01:23 +0530 Subject: [PATCH 360/855] msubprojects: Fix typo 'any way' -> 'anyway' --- mesonbuild/msubprojects.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 6b107c063984..599d0b797c1f 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -157,7 +157,7 @@ def update_wrapdb(self) -> bool: branch, revision = wrapdb_version.split('-', 1) except ValueError: if not options.force: - self.log(' ->', mlog.red('Malformed wrapdb_version field, use --force to update any way')) + self.log(' ->', mlog.red('Malformed wrapdb_version field, use --force to update anyway')) return False branch = revision = None except WrapException: @@ -168,7 +168,7 @@ def update_wrapdb(self) -> bool: branch, revision = parse_patch_url(patch_url) except WrapException: if not options.force: - self.log(' ->', mlog.red('Could not determine current version, use --force to update any way')) + self.log(' ->', mlog.red('Could not determine current version, use --force to update anyway')) return False branch = revision = None From 507d8bf4d7da7c1dd80e2a6e777862dac179f59e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 12:14:48 -0700 Subject: [PATCH 361/855] interpreter: use typed_kwargs for build_target.build_by_default This allows a little bit of cleanup in the build layer, since there is code now that would always be true and we shouldn't do that. --- mesonbuild/build.py | 3 ++- mesonbuild/interpreter/interpreter.py | 1 - mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8185ef4cf0bc..dbfbea81b7f5 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -652,7 +652,8 @@ def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None: self.build_by_default = kwargs['build_by_default'] if not isinstance(self.build_by_default, bool): raise InvalidArguments('build_by_default must be a boolean value.') - elif kwargs.get('install', False): + + if not self.build_by_default and kwargs.get('install', False): # For backward compatibility, if build_by_default is not explicitly # set, use the value of 'install' if it's enabled. self.build_by_default = True diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 1bfcda0fb49e..85f599e3521e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3314,7 +3314,6 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: @FeatureNewKwargs('build target', '0.42.0', ['build_rpath', 'implicit_include_directories']) - @FeatureNewKwargs('build target', '0.38.0', ['build_by_default']) @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) def build_target_decorator_caller(self, node, args, kwargs): return True diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index b4a389be3628..3bfba6e85060 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -325,6 +325,7 @@ class _BaseBuildTarget(TypedDict): BuildTarget functions. """ + build_by_default: bool override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 82f770fa9d5d..4887214cd5df 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -552,6 +552,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, + KwargInfo('build_by_default', bool, default=True, since='0.38.0'), ] # Applies to all build_target classes except jar From bae2e13b392aba48d3b89e9a0bb06fc72af8c805 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 12:17:02 -0700 Subject: [PATCH 362/855] interpreter: use typed_kwargs for build_target.install --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 3bfba6e85060..57d2bbc01e4e 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -326,6 +326,7 @@ class _BaseBuildTarget(TypedDict): """ build_by_default: bool + install: bool override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 4887214cd5df..bb984ef1d09e 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -553,6 +553,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, KwargInfo('build_by_default', bool, default=True, since='0.38.0'), + INSTALL_KW, ] # Applies to all build_target classes except jar From 2fc872907813fa58a13f029bcf2a85924decf067 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 12:20:14 -0700 Subject: [PATCH 363/855] interpreter: use typed_kwargs for build_target.install_mode --- mesonbuild/interpreter/interpreter.py | 22 ---------------------- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 85f599e3521e..166e990852e4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2425,27 +2425,6 @@ def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtyp pass self.subdir = prev_subdir - def _get_kwarg_install_mode(self, kwargs: T.Dict[str, T.Any]) -> T.Optional[FileMode]: - if kwargs.get('install_mode', None) is None: - return None - if isinstance(kwargs['install_mode'], FileMode): - return kwargs['install_mode'] - install_mode: T.List[str] = [] - mode = mesonlib.typeslistify(kwargs.get('install_mode', []), (str, int)) - for m in mode: - # We skip any arguments that are set to `false` - if m is False: - m = None - install_mode.append(m) - if len(install_mode) > 3: - raise InvalidArguments('Keyword argument install_mode takes at ' - 'most 3 arguments.') - if len(install_mode) > 0 and install_mode[0] is not None and \ - not isinstance(install_mode[0], str): - raise InvalidArguments('Keyword argument install_mode requires the ' - 'permissions arg to be a string or false') - return FileMode(*install_mode) - # This is either ignored on basically any OS nowadays, or silently gets # ignored (Solaris) or triggers an "illegal operation" error (FreeBSD). # It was likely added "because it exists", but should never be used. In @@ -3343,7 +3322,6 @@ def build_target_decorator_caller(self, node, args, kwargs): sources = self.source_strings_to_files(sources) objs = extract_as_list(kwargs, 'objects') kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') - kwargs['install_mode'] = self._get_kwarg_install_mode(kwargs) if 'extra_files' in kwargs: ef = extract_as_list(kwargs, 'extra_files') kwargs['extra_files'] = self.source_strings_to_files(ef) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 57d2bbc01e4e..546523adf9a8 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -327,6 +327,7 @@ class _BaseBuildTarget(TypedDict): build_by_default: bool install: bool + install_mode: FileMode override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index bb984ef1d09e..dc055f1089bc 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -554,6 +554,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus OVERRIDE_OPTIONS_KW, KwargInfo('build_by_default', bool, default=True, since='0.38.0'), INSTALL_KW, + INSTALL_MODE_KW, ] # Applies to all build_target classes except jar From 357abf51c5a07efd1dabe916aa80790618dd5403 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 13:13:09 -0700 Subject: [PATCH 364/855] interpreter: use typed_kwargs for build_target.native --- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + mesonbuild/modules/python.py | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 166e990852e4..1ff852b607f5 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3300,7 +3300,7 @@ def build_target_decorator_caller(self, node, args, kwargs): build_target_decorator_caller(self, node, args, kwargs) name, sources = args - for_machine = self.machine_from_native_kwarg(kwargs) + for_machine = kwargs['native'] if kwargs.get('rust_crate_type') == 'proc-macro': # Silently force to native because that's the only sensible value # and rust_crate_type is deprecated any way. diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 546523adf9a8..7af146a78f41 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -328,6 +328,7 @@ class _BaseBuildTarget(TypedDict): build_by_default: bool install: bool install_mode: FileMode + native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index dc055f1089bc..87e6562732d4 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -555,6 +555,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('build_by_default', bool, default=True, since='0.38.0'), INSTALL_KW, INSTALL_MODE_KW, + NATIVE_KW, ] # Applies to all build_target classes except jar diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index c8af224f8976..432962cee454 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -197,7 +197,7 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], # into the linker path when not running in debug mode via a series #pragma comment(lib, "") # directives. We manually override these here as this interferes with the intended # use of the 'limited_api' kwarg - for_machine = self.interpreter.machine_from_native_kwarg(kwargs) + for_machine = kwargs['native'] compilers = self.interpreter.environment.coredata.compilers[for_machine] if any(compiler.get_id() == 'msvc' for compiler in compilers.values()): pydep_copy = copy.copy(pydep) From ca32ffc1579bd27539daa3ba41ba1099d9c476df Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 13:16:16 -0700 Subject: [PATCH 365/855] interpreter: use typed_kwargs for build_target.extra_files --- mesonbuild/interpreter/interpreter.py | 4 +--- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 1ff852b607f5..d28b292b520f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3322,9 +3322,7 @@ def build_target_decorator_caller(self, node, args, kwargs): sources = self.source_strings_to_files(sources) objs = extract_as_list(kwargs, 'objects') kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') - if 'extra_files' in kwargs: - ef = extract_as_list(kwargs, 'extra_files') - kwargs['extra_files'] = self.source_strings_to_files(ef) + kwargs['extra_files'] = self.source_strings_to_files(kwargs['extra_files']) self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}: mlog.debug('Unknown target type:', str(targetclass)) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 7af146a78f41..5fc2e3e8cdf0 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -326,6 +326,7 @@ class _BaseBuildTarget(TypedDict): """ build_by_default: bool + extra_files: T.List[FileOrString] install: bool install_mode: FileMode native: MachineChoice diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 87e6562732d4..9ade652c0299 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -553,6 +553,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, KwargInfo('build_by_default', bool, default=True, since='0.38.0'), + KwargInfo('extra_files', ContainerTypeInfo(list, (str, File)), default=[], listify=True), INSTALL_KW, INSTALL_MODE_KW, NATIVE_KW, From a3444d31dbf38ea6165096b897f6b94c92aa8b5b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 13:19:11 -0700 Subject: [PATCH 366/855] interpreter: use typed_kwargs for build_target.implicit_include_directories --- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d28b292b520f..0ceb00fe746f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3292,7 +3292,7 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: - @FeatureNewKwargs('build target', '0.42.0', ['build_rpath', 'implicit_include_directories']) + @FeatureNewKwargs('build target', '0.42.0', ['build_rpath']) @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) def build_target_decorator_caller(self, node, args, kwargs): return True diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 5fc2e3e8cdf0..6ab0d1836c97 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -329,6 +329,7 @@ class _BaseBuildTarget(TypedDict): extra_files: T.List[FileOrString] install: bool install_mode: FileMode + implicit_include_directories: bool native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 9ade652c0299..e22bd401f3ca 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -556,6 +556,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('extra_files', ContainerTypeInfo(list, (str, File)), default=[], listify=True), INSTALL_KW, INSTALL_MODE_KW, + KwargInfo('implicit_include_directories', bool, default=True, since='0.42.0'), NATIVE_KW, ] From b02d23206a659898f4165a7ee7c07b064b7c079b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:33:52 -0700 Subject: [PATCH 367/855] interpreter: use typed_kwargs for build_target.build_rpath --- mesonbuild/interpreter/interpreter.py | 1 - mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 0ceb00fe746f..25e096b22a62 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3292,7 +3292,6 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: - @FeatureNewKwargs('build target', '0.42.0', ['build_rpath']) @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) def build_target_decorator_caller(self, node, args, kwargs): return True diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 6ab0d1836c97..046838ec79c3 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -326,6 +326,7 @@ class _BaseBuildTarget(TypedDict): """ build_by_default: bool + build_rpath: str extra_files: T.List[FileOrString] install: bool install_mode: FileMode diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index e22bd401f3ca..87d862290fe9 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -576,6 +576,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus default={}, since='1.2.0', ), + KwargInfo('build_rpath', str, default='', since='0.42.0'), ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: From e06ae906779c00417f8003cc7171c1516353317b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:35:03 -0700 Subject: [PATCH 368/855] interpreter: use typed_kwargs for build_target.install_rpath --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 046838ec79c3..e5afa962bd70 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -330,6 +330,7 @@ class _BaseBuildTarget(TypedDict): extra_files: T.List[FileOrString] install: bool install_mode: FileMode + install_rpath: str implicit_include_directories: bool native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 87d862290fe9..cc3dbbb6860d 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -577,6 +577,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since='1.2.0', ), KwargInfo('build_rpath', str, default='', since='0.42.0'), + KwargInfo('install_rpath', str, default=''), ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: From 0f23dc5b03fda2e8958903eb25587a7e4e2daa67 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:42:30 -0700 Subject: [PATCH 369/855] interpreter: use typed_kwargs for build_target.link_language --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index e5afa962bd70..d6d6220fd973 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -332,6 +332,7 @@ class _BaseBuildTarget(TypedDict): install_mode: FileMode install_rpath: str implicit_include_directories: bool + link_language: T.Optional[str] native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index cc3dbbb6860d..c2ea63299db2 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -578,6 +578,12 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus ), KwargInfo('build_rpath', str, default='', since='0.42.0'), KwargInfo('install_rpath', str, default=''), + KwargInfo( + 'link_language', + (str, NoneType), + validator=in_set_validator(set(compilers.all_languages)), + since='0.51.0', + ), ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: From d38bf5fbb0b21e1f33ee81d52a361d4c8f8847a5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:46:44 -0700 Subject: [PATCH 370/855] interpreter: use typed_kwargs for build_target.gnu_symbol_visibility --- mesonbuild/interpreter/interpreter.py | 6 ------ mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 7 +++++++ mesonbuild/modules/python.py | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 25e096b22a62..223ebddba19d 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3292,12 +3292,6 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs kwargs: T.Union[kwtypes.Executable, kwtypes.StaticLibrary, kwtypes.SharedLibrary, kwtypes.SharedModule, kwtypes.Jar], targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]] ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]: - @FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility']) - def build_target_decorator_caller(self, node, args, kwargs): - return True - - build_target_decorator_caller(self, node, args, kwargs) - name, sources = args for_machine = kwargs['native'] if kwargs.get('rust_crate_type') == 'proc-macro': diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index d6d6220fd973..31730e64582d 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -328,6 +328,7 @@ class _BaseBuildTarget(TypedDict): build_by_default: bool build_rpath: str extra_files: T.List[FileOrString] + gnu_symbol_visibility: str install: bool install_mode: FileMode install_rpath: str diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index c2ea63299db2..b67a4006a5e8 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -577,6 +577,13 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since='1.2.0', ), KwargInfo('build_rpath', str, default='', since='0.42.0'), + KwargInfo( + 'gnu_symbol_visibility', + str, + default='', + validator=in_set_validator({'', 'default', 'internal', 'hidden', 'protected', 'inlineshidden'}), + since='0.48.0', + ), KwargInfo('install_rpath', str, default=''), KwargInfo( 'link_language', diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 432962cee454..ec95374d38ab 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -232,7 +232,7 @@ def extension_module_method(self, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs['name_prefix'] = '' kwargs['name_suffix'] = target_suffix - if 'gnu_symbol_visibility' not in kwargs and \ + if kwargs['gnu_symbol_visibility'] == '' and \ (self.is_pypy or mesonlib.version_compare(self.version, '>=3.9')): kwargs['gnu_symbol_visibility'] = 'inlineshidden' From 4386419a861240e8719b86e4a125902b7ff77644 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:52:21 -0700 Subject: [PATCH 371/855] interpreter: use typed_kwargs for build_target.link_depends --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 31730e64582d..477bc232ebac 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -333,6 +333,7 @@ class _BaseBuildTarget(TypedDict): install_mode: FileMode install_rpath: str implicit_include_directories: bool + link_depends: T.List[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget]] link_language: T.Optional[str] native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index b67a4006a5e8..8286b97e1e3d 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -585,6 +585,12 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus since='0.48.0', ), KwargInfo('install_rpath', str, default=''), + KwargInfo( + 'link_depends', + ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, BuildTarget)), + default=[], + listify=True, + ), KwargInfo( 'link_language', (str, NoneType), From 9f80a069ec215f41b289f11ca8dd1f24c88fed97 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 14:59:29 -0700 Subject: [PATCH 372/855] interpreter: use typed_kwargs for build_target.name_prefix --- mesonbuild/build.py | 2 +- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index dbfbea81b7f5..086527df1be9 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1181,7 +1181,7 @@ def process_kwargs(self, kwargs): if not os.path.isfile(trial): raise InvalidArguments(f'Tried to add non-existing resource {r}.') self.resources = resources - if 'name_prefix' in kwargs: + if kwargs.get('name_prefix') is not None: name_prefix = kwargs['name_prefix'] if isinstance(name_prefix, list): if name_prefix: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 477bc232ebac..b4af9abc2725 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -335,6 +335,7 @@ class _BaseBuildTarget(TypedDict): implicit_include_directories: bool link_depends: T.List[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget]] link_language: T.Optional[str] + name_prefix: T.Optional[str] native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 8286b97e1e3d..6cae9cd814b6 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -560,12 +560,27 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus NATIVE_KW, ] + +def _name_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: + if isinstance(arg, list) and arg: + return 'must be empty when passed as an array to signify the default value.' + return None + + +_NAME_PREFIX_KW: KwargInfo[T.Optional[T.Union[str, T.List]]] = KwargInfo( + 'name_prefix', + (str, NoneType, list), + validator=_name_validator, + convertor=lambda x: None if isinstance(x, list) else x, +) + # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, *_LANGUAGE_KWS, BT_SOURCES_KW, INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'), + _NAME_PREFIX_KW, RUST_CRATE_TYPE_KW, KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), D_MODULE_VERSIONS_KW, From 1abdd9dd61d152e70e36fba0a2575bcc7370fb01 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 15:00:29 -0700 Subject: [PATCH 373/855] interpreter: use typed_kwargs for build_target.name_suffix --- mesonbuild/build.py | 2 +- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 086527df1be9..05ec9deb718d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1191,7 +1191,7 @@ def process_kwargs(self, kwargs): raise InvalidArguments('name_prefix must be a string.') self.prefix = name_prefix self.name_prefix_set = True - if 'name_suffix' in kwargs: + if kwargs.get('name_suffix') is not None: name_suffix = kwargs['name_suffix'] if isinstance(name_suffix, list): if name_suffix: diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index b4af9abc2725..afd8ece1a08a 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -336,6 +336,7 @@ class _BaseBuildTarget(TypedDict): link_depends: T.List[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.BuildTarget]] link_language: T.Optional[str] name_prefix: T.Optional[str] + name_suffix: T.Optional[str] native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 6cae9cd814b6..f24268c01d92 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -567,6 +567,12 @@ def _name_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: return None +def _name_suffix_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: + if arg == '': + return 'must nt be a empty string. An empty array may be passed if you want Meson to use the default behavior.' + return _name_validator(arg) + + _NAME_PREFIX_KW: KwargInfo[T.Optional[T.Union[str, T.List]]] = KwargInfo( 'name_prefix', (str, NoneType, list), @@ -581,6 +587,7 @@ def _name_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: BT_SOURCES_KW, INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'), _NAME_PREFIX_KW, + _NAME_PREFIX_KW.evolve(name='name_suffix', validator=_name_suffix_validator), RUST_CRATE_TYPE_KW, KwargInfo('d_debug', ContainerTypeInfo(list, (str, int)), default=[], listify=True), D_MODULE_VERSIONS_KW, From d5bdcf1145065282dbd8b076e09d68330e1ddf2d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 15:32:00 -0700 Subject: [PATCH 374/855] interpreter: use typed_kwargs for build_target.resources --- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 1 + 2 files changed, 2 insertions(+) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index afd8ece1a08a..a4ebe98ebb00 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -340,6 +340,7 @@ class _BaseBuildTarget(TypedDict): native: MachineChoice override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] + resources: T.List[str] class _BuildTarget(_BaseBuildTarget): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index f24268c01d92..6a4dda5614d4 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -558,6 +558,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus INSTALL_MODE_KW, KwargInfo('implicit_include_directories', bool, default=True, since='0.42.0'), NATIVE_KW, + KwargInfo('resources', ContainerTypeInfo(list, str), default=[], listify=True), ] From e419184a9b2698983e3115e6552e67ac026a3ce1 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 29 Sep 2023 15:49:40 -0700 Subject: [PATCH 375/855] interpreter: use typed_kwargs for build_target.objects --- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreter/kwargs.py | 1 + mesonbuild/interpreter/type_checking.py | 31 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 223ebddba19d..7fb3c923407b 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3313,7 +3313,7 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs sources = [s for s in sources if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))] sources = self.source_strings_to_files(sources) - objs = extract_as_list(kwargs, 'objects') + objs = kwargs['objects'] kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') kwargs['extra_files'] = self.source_strings_to_files(kwargs['extra_files']) self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index a4ebe98ebb00..17f7876a04d0 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -338,6 +338,7 @@ class _BaseBuildTarget(TypedDict): name_prefix: T.Optional[str] name_suffix: T.Optional[str] native: MachineChoice + objects: T.List[build.ObjectTypes] override_options: T.Dict[OptionKey, T.Union[str, int, bool, T.List[str]]] depend_files: NotRequired[T.List[File]] resources: T.List[str] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 6a4dda5614d4..296baca31bae 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -25,6 +25,7 @@ if T.TYPE_CHECKING: from typing_extensions import Literal + from ..build import ObjectTypes from ..interpreterbase import TYPE_var from ..mesonlib import EnvInitValueType @@ -549,6 +550,24 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus deprecated_message='This does not, and never has, done anything. It should be removed' ) +def _objects_validator(vals: T.List[ObjectTypes]) -> T.Optional[str]: + non_objects: T.List[str] = [] + + for val in vals: + if isinstance(val, ExtractedObjects): + continue + elif isinstance(val, (str, File)): + if not compilers.is_object(val): + non_objects.append(str(val)) + else: + non_objects.extend(o for o in val.get_outputs() if not compilers.is_object(o)) + + if non_objects: + return f'File{"s" if len(non_objects) > 1 else ""}: "{", ".join(non_objects)}" are not objects' + + return None + + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, @@ -559,6 +578,17 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('implicit_include_directories', bool, default=True, since='0.42.0'), NATIVE_KW, KwargInfo('resources', ContainerTypeInfo(list, str), default=[], listify=True), + KwargInfo( + 'objects', + ContainerTypeInfo(list, (str, File, CustomTarget, CustomTargetIndex, GeneratedList, ExtractedObjects)), + listify=True, + default=[], + validator=_objects_validator, + since_values={ + ContainerTypeInfo(list, (GeneratedList, CustomTarget, CustomTargetIndex)): + ('1.1.0', 'generated sources as positional "objects" arguments') + }, + ), ] @@ -581,6 +611,7 @@ def _name_suffix_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[ convertor=lambda x: None if isinstance(x, list) else x, ) + # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, From 0781eab48123aadab1ca7973aff024b0d4789bd7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Oct 2023 16:18:31 +0200 Subject: [PATCH 376/855] release notes: fix snippet for "fill:" argument The release notes were using the older spelling "length". Signed-off-by: Paolo Bonzini --- docs/markdown/snippets/int_to_string_fill.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/markdown/snippets/int_to_string_fill.md b/docs/markdown/snippets/int_to_string_fill.md index 2b0d250858f9..44885ff66d1d 100644 --- a/docs/markdown/snippets/int_to_string_fill.md +++ b/docs/markdown/snippets/int_to_string_fill.md @@ -6,10 +6,10 @@ string representation of the integer with leading zeroes: ```meson n = 4 message(n.to_string()) -message(n.to_string(length: 3)) +message(n.to_string(fill: 3)) n = -4 -message(n.to_string(length: 3)) +message(n.to_string(fill: 3)) ``` OUTPUT: @@ -17,4 +17,4 @@ OUTPUT: 4 004 -04 -``` \ No newline at end of file +``` From 890dd31cb0cdfaca6ddf483c8d8ba3b4c1bcb753 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 18 Oct 2023 10:08:16 +0530 Subject: [PATCH 377/855] test cases/15 llvm: Skip cmake when llvm == 17.0 There's a bug in the zstd find_package module: https://github.com/llvm/llvm-project/commit/e7fc7540daa9333f0be4f380fc9c619236d17f57#r130257253 --- test cases/frameworks/15 llvm/meson.build | 5 +++++ test cases/frameworks/15 llvm/test.json | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build index aac037fe6cd7..9c39e45b6a43 100644 --- a/test cases/frameworks/15 llvm/meson.build +++ b/test cases/frameworks/15 llvm/meson.build @@ -8,6 +8,11 @@ if not d.found() error('MESON_SKIP_TEST llvm not found.') endif +if method != 'config-tool' and d.version().startswith('17.0') and host_machine.system() == 'windows' + # https://github.com/llvm/llvm-project/commit/e7fc7540daa9333f0be4f380fc9c619236d17f57#r130257253 + error('MESON_SKIP_TEST broken llvm cmake files on MSYS2') +endif + modules_to_find = [ 'bitwriter', 'asmprinter', 'executionengine', 'mcjit', 'target', 'nativecodegen', 'amdgpu', 'engine' diff --git a/test cases/frameworks/15 llvm/test.json b/test cases/frameworks/15 llvm/test.json index 66ecd43552f6..f9d730514220 100644 --- a/test cases/frameworks/15 llvm/test.json +++ b/test cases/frameworks/15 llvm/test.json @@ -2,9 +2,9 @@ "matrix": { "options": { "method": [ - { "val": "config-tool", "skip_on_jobname": ["msys2-gcc"]}, - { "val": "cmake", "skip_on_jobname": ["msys2-gcc"] }, - { "val": "combination", "skip_on_jobname": ["msys2-gcc"]} + { "val": "config-tool", "skip_on_jobname": ["msys2-gcc"] }, + { "val": "cmake", "skip_on_jobname": ["msys2"] }, + { "val": "combination", "skip_on_jobname": ["msys2"] } ], "link-static": [ { "val": true, "skip_on_jobname": ["opensuse"] }, From 361f7484d2fe9d1cf03b66a66d785618694aa62c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 16 Oct 2023 14:22:12 -0400 Subject: [PATCH 378/855] Remove duplicated code to canonicalize b_vscrt option value Add a common function that infers vscrt from buildtype in Compiler base class. --- mesonbuild/backend/ninjabackend.py | 9 +------ mesonbuild/backend/vs2010backend.py | 21 ++++------------- mesonbuild/compilers/asm.py | 23 +----------------- mesonbuild/compilers/compilers.py | 26 ++++++++++++++++++++- mesonbuild/compilers/d.py | 26 +-------------------- mesonbuild/compilers/mixins/visualstudio.py | 24 ++----------------- 6 files changed, 34 insertions(+), 95 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b0fec89b352e..e332971d98fa 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1973,13 +1973,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: try: buildtype = target.get_option(OptionKey('buildtype')) crt = target.get_option(OptionKey('b_vscrt')) - is_debug = buildtype == 'debug' - - if crt == 'from_buildtype': - crt = 'mdd' if is_debug else 'md' - elif crt == 'static_from_buildtype': - crt = 'mtd' if is_debug else 'mt' - + crt = rustc.get_crt_val(crt, buildtype) if crt == 'mdd': crt_link_args = ['-l', 'static=msvcrtd'] elif crt == 'md': @@ -1989,7 +1983,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: crt_link_args = ['-l', 'static=libcmtd'] elif crt == 'mt': crt_link_args = ['-l', 'static=libcmt'] - except KeyError: crt_args_injected = True diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index b9ada532bcd8..cb1ea78337e1 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1311,28 +1311,15 @@ def add_non_makefile_vcxproj_elements( ET.SubElement(clconf, 'OpenMPSupport').text = 'true' # CRT type; debug or release vscrt_type = target.get_option(OptionKey('b_vscrt')) - if vscrt_type == 'from_buildtype': - if self.buildtype == 'debug': - ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' - else: - ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' - elif vscrt_type == 'static_from_buildtype': - if self.buildtype == 'debug': - ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug' - else: - ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' - ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' - elif vscrt_type == 'mdd': + vscrt_val = compiler.get_crt_val(vscrt_type, self.buildtype) + if vscrt_val == 'mdd': ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebugDLL' - elif vscrt_type == 'mt': + elif vscrt_val == 'mt': # FIXME, wrong ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreaded' - elif vscrt_type == 'mtd': + elif vscrt_val == 'mtd': # FIXME, wrong ET.SubElement(type_config, 'UseDebugLibraries').text = 'true' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDebug' diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index 19f7b643b698..392a082969d3 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -124,28 +124,7 @@ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: if not self.info.is_windows(): return [] - if crt_val in self.crt_args: - return self.crt_args[crt_val] - assert crt_val in {'from_buildtype', 'static_from_buildtype'} - dbg = 'mdd' - rel = 'md' - if crt_val == 'static_from_buildtype': - dbg = 'mtd' - rel = 'mt' - # Match what build type flags used to do. - if buildtype == 'plain': - return [] - elif buildtype == 'debug': - return self.crt_args[dbg] - elif buildtype == 'debugoptimized': - return self.crt_args[rel] - elif buildtype == 'release': - return self.crt_args[rel] - elif buildtype == 'minsize': - return self.crt_args[rel] - else: - assert buildtype == 'custom' - raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + return self.crt_args[self.get_crt_val(crt_val, buildtype)] class YasmCompiler(NasmCompiler): id = 'yasm' diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 5f2e304dd997..abf4ef430cca 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -299,6 +299,8 @@ class CompileCheckMode(enum.Enum): True: ['-g'] } +MSCRT_VALS = ['none', 'md', 'mdd', 'mt', 'mtd'] + base_options: 'KeyedOptionDictType' = { OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), @@ -325,7 +327,7 @@ class CompileCheckMode(enum.Enum): OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False), OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False), OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.', - ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'], + MSCRT_VALS + ['from_buildtype', 'static_from_buildtype'], 'from_buildtype'), } @@ -1105,6 +1107,28 @@ def get_assert_args(self, disable: bool) -> T.List[str]: """ return [] + def get_crt_val(self, crt_val: str, buildtype: str) -> str: + if crt_val in MSCRT_VALS: + return crt_val + assert crt_val in {'from_buildtype', 'static_from_buildtype'} + + dbg = 'mdd' + rel = 'md' + if crt_val == 'static_from_buildtype': + dbg = 'mtd' + rel = 'mt' + + # Match what build type flags used to do. + if buildtype == 'plain': + return 'none' + elif buildtype == 'debug': + return dbg + elif buildtype in {'debugoptimized', 'release', 'minsize'}: + return rel + else: + assert buildtype == 'custom' + raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: raise EnvironmentException('This compiler does not support Windows CRT selection') diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 05f3b7d8d6e8..d8a72fdf3408 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -379,31 +379,7 @@ def get_debug_args(self, is_debug: bool) -> T.List[str]: def _get_crt_args(self, crt_val: str, buildtype: str) -> T.List[str]: if not self.info.is_windows(): return [] - - if crt_val in self.mscrt_args: - return self.mscrt_args[crt_val] - assert crt_val in {'from_buildtype', 'static_from_buildtype'} - - dbg = 'mdd' - rel = 'md' - if crt_val == 'static_from_buildtype': - dbg = 'mtd' - rel = 'mt' - - # Match what build type flags used to do. - if buildtype == 'plain': - return [] - elif buildtype == 'debug': - return self.mscrt_args[dbg] - elif buildtype == 'debugoptimized': - return self.mscrt_args[rel] - elif buildtype == 'release': - return self.mscrt_args[rel] - elif buildtype == 'minsize': - return self.mscrt_args[rel] - else: - assert buildtype == 'custom' - raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + return self.mscrt_args[self.get_crt_val(crt_val, buildtype)] def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, suffix: str, soversion: str, diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 24f11329d42e..3dd75754ed18 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -366,28 +366,8 @@ def get_default_include_dirs(self) -> T.List[str]: return os.environ['INCLUDE'].split(os.pathsep) def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: - if crt_val in self.crt_args: - return self.crt_args[crt_val] - assert crt_val in {'from_buildtype', 'static_from_buildtype'} - dbg = 'mdd' - rel = 'md' - if crt_val == 'static_from_buildtype': - dbg = 'mtd' - rel = 'mt' - # Match what build type flags used to do. - if buildtype == 'plain': - return [] - elif buildtype == 'debug': - return self.crt_args[dbg] - elif buildtype == 'debugoptimized': - return self.crt_args[rel] - elif buildtype == 'release': - return self.crt_args[rel] - elif buildtype == 'minsize': - return self.crt_args[rel] - else: - assert buildtype == 'custom' - raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + crt_val = self.get_crt_val(crt_val, buildtype) + return self.crt_args[crt_val] def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: # MSVC doesn't have __attribute__ like Clang and GCC do, so just return From e2a87afa52612c9ec6fd825e115838323ba13936 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 16 Oct 2023 14:35:25 -0400 Subject: [PATCH 379/855] rust: Always link dll and exe with the correct vscrt This fixes missing flags in the link_whole case and link failure for static libraries. --- mesonbuild/backend/ninjabackend.py | 50 ++++++------------------------ mesonbuild/compilers/rust.py | 16 ++++++++++ 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index e332971d98fa..0c984eadf5c3 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1951,40 +1951,16 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() - # Have we already injected msvc-crt args? - # - # If we don't have A C, C++, or Fortran compiler that is - # VisualStudioLike treat this as if we've already injected them - # - # We handle this here rather than in the rust compiler because in - # general we don't want to link rust targets to a non-default crt. - # However, because of the way that MSCRTs work you can only link to one - # per target, so if A links to the debug one, and B links to the normal - # one you can't link A and B. Rust is hardcoded to the default one, - # so if we compile C/C++ code and link against a non-default MSCRT then - # linking will fail. We can work around this by injecting MSCRT link - # arguments early in the rustc command line + # Rustc always use non-debug Windows runtime. Inject the one selected + # by Meson options instead. # https://github.com/rust-lang/rust/issues/39016 - crt_args_injected = not any(x is not None and x.get_argument_syntax() == 'msvc' for x in - (self.environment.coredata.compilers[target.for_machine].get(l) - for l in ['c', 'cpp', 'fortran'])) - - crt_link_args: T.List[str] = [] - try: - buildtype = target.get_option(OptionKey('buildtype')) - crt = target.get_option(OptionKey('b_vscrt')) - crt = rustc.get_crt_val(crt, buildtype) - if crt == 'mdd': - crt_link_args = ['-l', 'static=msvcrtd'] - elif crt == 'md': - # this is the default, no need to inject anything - crt_args_injected = True - elif crt == 'mtd': - crt_link_args = ['-l', 'static=libcmtd'] - elif crt == 'mt': - crt_link_args = ['-l', 'static=libcmt'] - except KeyError: - crt_args_injected = True + if not isinstance(target, build.StaticLibrary): + try: + buildtype = target.get_option(OptionKey('buildtype')) + crt = target.get_option(OptionKey('b_vscrt')) + args += rustc.get_crt_link_args(crt, buildtype) + except KeyError: + pass # TODO: we likely need to use verbatim to handle name_prefix and name_suffix for d in target.link_targets: @@ -2001,10 +1977,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) continue - if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): - args += crt_link_args - crt_args_injected = True - if isinstance(d, build.StaticLibrary): # Rustc doesn't follow Meson's convention that static libraries # are called .a, and import libraries are .lib, so we have to @@ -2045,10 +2017,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) else: - if not crt_args_injected and not {'c', 'cpp', 'fortran'}.isdisjoint(d.compilers): - crt_args_injected = True - crt_args_injected = True - if rustc.linker.id in {'link', 'lld-link'}: if verbatim: # If we can use the verbatim modifier, then everything is great diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index b5e6a6a0c5a7..1fb94aa4447a 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -55,6 +55,17 @@ class RustCompiler(Compiler): '3': ['-W', 'warnings'], } + # Those are static libraries, but we use dylib= here as workaround to avoid + # rust --tests to use /WHOLEARCHIVE. + # https://github.com/rust-lang/rust/issues/116910 + MSVCRT_ARGS: T.Mapping[str, T.List[str]] = { + 'none': [], + 'md': [], # this is the default, no need to inject anything + 'mdd': ['-l', 'dylib=msvcrtd'], + 'mt': ['-l', 'dylib=libcmt'], + 'mtd': ['-l', 'dylib=libcmtd'], + } + def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, @@ -177,6 +188,11 @@ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: # Rust handles this for us, we don't need to do anything return [] + def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: + if self.linker.id not in {'link', 'lld-link'}: + return [] + return self.MSVCRT_ARGS[self.get_crt_val(crt_val, buildtype)] + def get_colorout_args(self, colortype: str) -> T.List[str]: if colortype in {'always', 'never', 'auto'}: return [f'--color={colortype}'] From 7b7d2e060b447de9c2642848847370a58711ac1c Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 19 Oct 2023 15:06:11 +0100 Subject: [PATCH 380/855] mtest: set ASAN_OPTIONS and UBSAN_OPTIONS to abort by default Do as we do for MALLOC_PERTURB and set a sensible value for both ASAN_OPTIONS and UBSAN_OPTIONS to abort on failure and give more helpful output at the same time. We do not set these options if the user has exported a value themselves to allow override. In the last week alone, I've observed two cases where people were expecting sanitizers to abort on failure and were surprised when it didn't: 1) https://github.com/git/git/commit/252d693797912ddb2684733160170f0408b73274 2) https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/c47df433f7bc9936fc59b323ca5e53ea4a04f40e Correct this - which is in-line with meson's DWIM/DTRT philosophy. Signed-off-by: Sam James --- docs/markdown/Unit-tests.md | 6 ++++++ docs/markdown/snippets/sanitizers_test.md | 5 +++++ docs/yaml/functions/test.yaml | 4 ++++ mesonbuild/mtest.py | 9 +++++++++ 4 files changed, 24 insertions(+) create mode 100644 docs/markdown/snippets/sanitizers_test.md diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 030eb19c4dc8..7ad95d2649c1 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -38,6 +38,12 @@ set to a random value between 1..255. This can help find memory leaks on configurations using glibc, including with non-GCC compilers. This feature can be disabled as discussed in [[test]]. +### ASAN_OPTIONS and UBSAN_OPTIONS + +By default, the environment variables `ASAN_OPTIONS` and `UBSAN_OPTIONS` are +set to enable aborting on detected violations and to give a backtrace. This +feature can be disabled as discussed in [[test]]. + ## Coverage If you enable coverage measurements by giving Meson the command line diff --git a/docs/markdown/snippets/sanitizers_test.md b/docs/markdown/snippets/sanitizers_test.md new file mode 100644 index 000000000000..24929114beab --- /dev/null +++ b/docs/markdown/snippets/sanitizers_test.md @@ -0,0 +1,5 @@ +## Tests now abort on errors by default under sanitizers + +Sanitizers like AddressSanitizer and UndefinedBehaviorSanitizer do not abort +by default on detected violations. Meson now exports `ASAN_OPTIONS` and `UBSAN_OPTIONS` +when unset in the environment to provide sensible abort-by-default behavior. diff --git a/docs/yaml/functions/test.yaml b/docs/yaml/functions/test.yaml index 4e791671c19e..622b7c3b0ba0 100644 --- a/docs/yaml/functions/test.yaml +++ b/docs/yaml/functions/test.yaml @@ -33,6 +33,10 @@ description: | test(..., env: nomalloc, ...) ``` + By default, the environment variables `ASAN_OPTIONS` and `UBSAN_OPTIONS` are + set to enable aborting on detected violations and to give a backtrace. To suppress + this, `ASAN_OPTIONS` and `UBSAN_OPTIONS` can be set in the environment. + In addition to running individual executables as test cases, `test()` can also be used to invoke an external test harness. In this case, it is best to use `verbose: true` *(since 0.62.0)* and, if supported diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 1298cc031975..291b1e2fec15 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1418,6 +1418,15 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, if ('MALLOC_PERTURB_' not in env or not env['MALLOC_PERTURB_']) and not options.benchmark: env['MALLOC_PERTURB_'] = str(random.randint(1, 255)) + # Sanitizers do not default to aborting on error. This is counter to + # expectations when using -Db_sanitize and has led to confusion in the wild + # in CI. Set our own values of {ASAN,UBSAN}_OPTOINS to rectify this, but + # only if the user has not defined them. + if ('ASAN_OPTIONS' not in env or not env['ASAN_OPTIONS']): + env['ASAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1' + if ('UBSAN_OPTIONS' not in env or not env['UBSAN_OPTIONS']): + env['UBSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' + if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0: timeout = None elif self.options.timeout_multiplier is None: From bf9314e00dde4160b1022168cff91e09c868935c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 17 Oct 2023 10:36:19 -0400 Subject: [PATCH 381/855] pkgconfig: Allow setting both pkgconfig and pkg-config This was previously allowed for different usage. Keep allowing it, but with non fatal deprecation notice, and ignore the value from legacy pkgconfig. --- .../pkgconfig_deprecated_machine_file.md | 10 ++++++++++ mesonbuild/envconfig.py | 19 ++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/pkgconfig_deprecated_machine_file.md diff --git a/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md b/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md new file mode 100644 index 000000000000..36647e90e844 --- /dev/null +++ b/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md @@ -0,0 +1,10 @@ +## Machine files: `pkgconfig` field deprecated and replaced by `pkg-config` + +Meson used to allow both `pkgconfig` and `pkg-config` entries in machine files, +the former was used for `dependency()` lookup and the latter was used as return +value for `find_program('pkg-config')`. + +This inconsistency is now fixed by deprecating `pkgconfig` in favor of +`pkg-config` which matches the name of the binary. For backward compatibility +it is still allowed to define both with the same value, in that case no +deprecation warning is printed. diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 5621b99feff8..07f1229e3065 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -404,12 +404,21 @@ def __init__( if not isinstance(command, (list, str)): raise mesonlib.MesonException( f'Invalid type {command!r} for entry {name!r} in cross file') - if name == 'pkgconfig': - if 'pkg-config' in binaries: - raise mesonlib.MesonException('Both pkgconfig and pkg-config entries in machine file.') - mlog.deprecation('"pkgconfig" entry is deprecated and should be replaced by "pkg-config"') - name = 'pkg-config' self.binaries[name] = mesonlib.listify(command) + if 'pkgconfig' in self.binaries: + if 'pkg-config' not in self.binaries: + mlog.deprecation('"pkgconfig" entry is deprecated and should be replaced by "pkg-config"', fatal=False) + self.binaries['pkg-config'] = self.binaries['pkgconfig'] + elif self.binaries['pkgconfig'] != self.binaries['pkg-config']: + raise mesonlib.MesonException('Mismatched pkgconfig and pkg-config binaries in the machine file.') + else: + # Both are defined with the same value, this is allowed + # for backward compatibility. + # FIXME: We should still print deprecation warning if the + # project targets Meson >= 1.3.0, but we have no way to know + # that here. + pass + del self.binaries['pkgconfig'] @staticmethod def detect_ccache() -> T.List[str]: From e6e07f46ea64aead8fecb6f623c795ea3d8e62a2 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 17 Oct 2023 10:17:00 -0700 Subject: [PATCH 382/855] modules/rust: remove missed cargs.extend() --- mesonbuild/modules/rust.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 3d0bdd59a81b..8e55ad4f811b 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -243,7 +243,6 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu # We only want include directories and defines, other things may not be valid cargs = state.get_option('args', state.subproject, lang='c') assert isinstance(cargs, list), 'for mypy' - clang_args.extend(cargs) for a in itertools.chain(state.global_args.get('c', []), state.project_args.get('c', []), cargs): if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): clang_args.append(a) From 450b3db37810c99854f670cb70a59e0bee5b8777 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 17 Oct 2023 10:39:10 -0700 Subject: [PATCH 383/855] modules/rust: Add a test that bindgen drops arguments it shouldn't use This does require hacking up the test pretty badly, since we need to not ever pass GCC these invalid values. But it's preferable to writing another project test I think. Co-Authored-by: Nirbheek Chauhan --- test cases/rust/12 bindgen/meson.build | 12 +++++++++-- test cases/rust/12 bindgen/test.json | 2 +- unittests/allplatformstests.py | 28 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index e7cb5f3db2c0..e36e9e2d1a7b 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -8,8 +8,16 @@ if not prog_bindgen.found() error('MESON_SKIP_TEST bindgen not found') endif -add_project_arguments('-DPROJECT_ARG', language : 'c') -add_global_arguments('-DGLOBAL_ARG', language : 'c') +cc_id = meson.get_compiler('c').get_id() +compiler_specific_args = [] +if cc_id == 'gcc' + compiler_specific_args = ['-mtls-dialect=gnu2'] +elif cc_id == 'msvc' + compiler_specific_args = ['/fp:fast'] +endif + +add_project_arguments(['-DPROJECT_ARG', compiler_specific_args], language : 'c') +add_global_arguments(['-DGLOBAL_ARG', compiler_specific_args], language : 'c') # This seems to happen on windows when libclang.dll is not in path or is not # valid. We must try to process a header file for this to work. diff --git a/test cases/rust/12 bindgen/test.json b/test cases/rust/12 bindgen/test.json index b3a758562969..d45543b13223 100644 --- a/test cases/rust/12 bindgen/test.json +++ b/test cases/rust/12 bindgen/test.json @@ -4,7 +4,7 @@ }, "stdout": [ { - "line": "test cases/rust/12 bindgen/meson.build:30: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." + "line": "test cases/rust/12 bindgen/meson.build:38: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." } ] } diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 18ed3bf5c193..059be2d4f225 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -4810,6 +4810,34 @@ def test_rust_rlib_linkage(self) -> None: self.assertEqual(cm.exception.returncode, 1) self.assertIn('exit status 39', cm.exception.stdout) + @skip_if_not_language('rust') + def test_bindgen_drops_invalid(self) -> None: + if self.backend is not Backend.ninja: + raise unittest.SkipTest('Rust is only supported with ninja currently') + testdir = os.path.join(self.rust_test_dir, '12 bindgen') + env = get_fake_env(testdir, self.builddir, self.prefix) + cc = detect_c_compiler(env, MachineChoice.HOST) + # bindgen understands compiler args that clang understands, but not + # flags by other compilers + if cc.get_id() == 'gcc': + bad_arg = '-fdse' + elif cc.get_id() == 'msvc': + bad_arg = '/fastfail' + else: + raise unittest.SkipTest('Test only supports GCC and MSVC') + self.init(testdir, extra_args=[f"-Dc_args=['-DCMD_ARG', '{bad_arg}']"]) + intro = self.introspect(['--targets']) + for i in intro: + if i['type'] == 'custom' and i['id'].startswith('rustmod-bindgen'): + args = i['target_sources'][0]['compiler'] + self.assertIn('-DCMD_ARG', args) + self.assertIn('-DPROJECT_ARG', args) + self.assertIn('-DGLOBAL_ARG', args) + self.assertNotIn(bad_arg, args) + self.assertNotIn('-mtls-dialect=gnu2', args) + self.assertNotIn('/fp:fast', args) + return + def test_custom_target_name(self): testdir = os.path.join(self.unit_test_dir, '100 custom target name') self.init(testdir) From 46cedeb431a67cde1c26c6d936bdd84ea8392d6f Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 20 Oct 2023 10:48:30 -0500 Subject: [PATCH 384/855] Support -j as a shorthand for --num-processes We already use -j to support parallelism in meson compile. So let's add the same for meson test and meson subprojects. --- .../snippets/shorthand_argument_for_mtest_num_processes.md | 4 ++++ mesonbuild/msubprojects.py | 2 +- mesonbuild/mtest.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md diff --git a/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md b/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md new file mode 100644 index 000000000000..7ff661b1363b --- /dev/null +++ b/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md @@ -0,0 +1,4 @@ +## `-j` shorthand for `--num-processes` + +`-j` now means the same thing as `--num-processes`. It was inconsistently +supported only in some subcommands. Now you may use it everywhere diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index 599d0b797c1f..fb9a847139c9 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -638,7 +638,7 @@ def add_common_arguments(p: argparse.ArgumentParser) -> None: help='Path to source directory') p.add_argument('--types', default='', help=f'Comma-separated list of subproject types. Supported types are: {ALL_TYPES_STRING} (default: all)') - p.add_argument('--num-processes', default=None, type=int, + p.add_argument('-j', '--num-processes', default=None, type=int, help='How many parallel processes to use (Since 0.59.0).') p.add_argument('--allow-insecure', default=False, action='store_true', help='Allow insecure server connections.') diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 291b1e2fec15..57bf28fb6fcd 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -157,7 +157,7 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: help="Run benchmarks instead of tests.") parser.add_argument('--logbase', default='testlog', help="Base name for log file.") - parser.add_argument('--num-processes', default=determine_worker_count(), type=int, + parser.add_argument('-j', '--num-processes', default=determine_worker_count(), type=int, help='How many parallel processes to use.') parser.add_argument('-v', '--verbose', default=False, action='store_true', help='Do not redirect stdout and stderr') From 1cf0ed0997de355d15d9418448423ecf06a62467 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 15 Aug 2023 23:00:10 -0400 Subject: [PATCH 385/855] add missing imports for future annotations --- mesonbuild/_pathlib.py | 1 + mesonbuild/compilers/asm.py | 2 ++ mesonbuild/scripts/test_loaded_modules.py | 3 +++ mesonbuild/scripts/yasm.py | 2 ++ 4 files changed, 8 insertions(+) diff --git a/mesonbuild/_pathlib.py b/mesonbuild/_pathlib.py index 640b5ed21dd2..561a135db1dd 100644 --- a/mesonbuild/_pathlib.py +++ b/mesonbuild/_pathlib.py @@ -29,6 +29,7 @@ python bugs are fixed and it is OK to tell our users to "just upgrade python". ''' +from __future__ import annotations import pathlib import os diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index 392a082969d3..09cf9e11eed0 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import typing as T diff --git a/mesonbuild/scripts/test_loaded_modules.py b/mesonbuild/scripts/test_loaded_modules.py index b3547beafe9d..f824134f2863 100644 --- a/mesonbuild/scripts/test_loaded_modules.py +++ b/mesonbuild/scripts/test_loaded_modules.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import sys import json import typing as T + from . import meson_exe # This script is used by run_unittests.py to verify we don't load too many diff --git a/mesonbuild/scripts/yasm.py b/mesonbuild/scripts/yasm.py index 730ff3e1657c..1d25e6f008bf 100644 --- a/mesonbuild/scripts/yasm.py +++ b/mesonbuild/scripts/yasm.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import argparse import subprocess import typing as T From 34ac2e4af6e5b4c86e8fcfef86042621d55dd141 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 17 Jul 2023 23:02:56 -0400 Subject: [PATCH 386/855] fix ninja backend rules containing internal enum reprs Partially reverts commit 1624354f33bf0a33f0e715ba1ca391ae0154ad19 which moved a bunch of stuff from strings to enums. The issue here is that Compiler.mode is not just, or primarily, something we compare, but is instead written in as e.g. `rule c_{compiler.mode}` to build.ninja, so this identifier needs to be a string. Ultimately, the issue is that the commit tried to rewrite a bunch of things called "mode" that had a couple of TODOs saying to use enums... but it rewrote everything called "mode" regardless of whether it was a function kwarg or a compiler property, even though the TODO only applied to one of them. --- mesonbuild/compilers/compilers.py | 2 +- mesonbuild/compilers/mixins/clike.py | 4 ++-- mesonbuild/compilers/mixins/visualstudio.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index abf4ef430cca..fb399b11422f 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -527,7 +527,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): language: str id: str warn_args: T.Dict[str, T.List[str]] - mode = CompileCheckMode.COMPILE + mode = 'COMPILER' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index b3c80d44060c..ca909998bffd 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1359,7 +1359,7 @@ def get_assert_args(self, disable: bool) -> T.List[str]: @functools.lru_cache(maxsize=None) def can_compile(self, src: 'mesonlib.FileOrString') -> bool: # Files we preprocess can be anything, e.g. .in - if self.mode == CompileCheckMode.PREPROCESS: + if self.mode == 'PREPROCESSOR': return True return super().can_compile(src) @@ -1367,6 +1367,6 @@ def get_preprocessor(self) -> Compiler: if not self.preprocessor: self.preprocessor = copy.copy(self) self.preprocessor.exelist = self.exelist + self.get_preprocess_to_file_args() - self.preprocessor.mode = CompileCheckMode.PREPROCESS + self.preprocessor.mode = 'PREPROCESSOR' self.modes.append(self.preprocessor) return self.preprocessor diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 3dd75754ed18..810dddd9d2f3 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -182,7 +182,7 @@ def sanitizer_compile_args(self, value: str) -> T.List[str]: return ['/fsanitize=address'] def get_output_args(self, outputname: str) -> T.List[str]: - if self.mode == CompileCheckMode.PREPROCESS: + if self.mode == 'PREPROCESSOR': return ['/Fi' + outputname] if outputname.endswith('.exe'): return ['/Fe' + outputname] From ae7a9b0f4430a055ac419c6f1157cbd0e6eed45c Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 9 Apr 2023 19:04:47 -0400 Subject: [PATCH 387/855] fix the repr for OrderedSet to actually execute correctly Old: ``` OrderedSet("'foo'", "'bar'", "'baz'") ``` New: ``` OrderedSet(['foo', 'bar', 'baz']) ``` The old one looked nasty *and* was totally non-functional. --- mesonbuild/utils/universal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 8216e780420c..26194628c46c 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1886,8 +1886,8 @@ def __len__(self) -> int: def __repr__(self) -> str: # Don't print 'OrderedSet("")' for an empty set. if self.__container: - return 'OrderedSet("{}")'.format( - '", "'.join(repr(e) for e in self.__container.keys())) + return 'OrderedSet([{}])'.format( + ', '.join(repr(e) for e in self.__container.keys())) return 'OrderedSet()' def __reversed__(self) -> T.Iterator[_T]: From e9e098b73e116c865ae0e52bb29001740b23ba22 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Fri, 20 Oct 2023 16:50:43 -0500 Subject: [PATCH 388/855] build: improve the warning for executables with the same name adb1a360b9f9edb26eda233326b1d539baeccd5b added the feature and also the usual meson-style warning to users that might be using the feature but were not targeting a new enough meson version. Well unfortunately the warning both doesn't actually work (it didn't take different directories into account) and is also really slow because it creates an O(N^2) loop for checking this. Instead, rework this by adding an additional set that stores a tuple containing the target name and its subdirectory. We only add this tuple if the target is an executable since it is the only time it will be relevant. After that, simply check if the name + subdir combination already exists in the set along with the target being executable. If so, then we execute FeatureNew which may possibly warn. This is a simply O(1) lookup which is way faster. Fixes #12404. --- mesonbuild/build.py | 1 + mesonbuild/interpreter/interpreter.py | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 05ec9deb718d..4fc409a8de9d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -252,6 +252,7 @@ def __init__(self, environment: environment.Environment): self.environment = environment self.projects = {} self.targets: 'T.OrderedDict[str, T.Union[CustomTarget, BuildTarget]]' = OrderedDict() + self.targetnames: T.Set[T.Tuple[str, str]] = set() # Set of executable names and their subdir self.global_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) self.global_link_args: PerMachine[T.Dict[str, T.List[str]]] = PerMachine({}, {}) self.projects_args: PerMachine[T.Dict[str, T.Dict[str, T.List[str]]]] = PerMachine({}, {}) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 7fb3c923407b..2fba33486aff 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3163,12 +3163,15 @@ def add_target(self, name: str, tobj: build.Target) -> None: # To permit an executable and a shared library to have the # same name, such as "foo.exe" and "libfoo.a". idname = tobj.get_id() - for t in self.build.targets.values(): - if t.get_id() == idname: - raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') - if isinstance(tobj, build.Executable) and isinstance(t, build.Executable) and t.name == tobj.name: - FeatureNew.single_use('multiple executables with the same name but different suffixes', - '1.3.0', self.subproject, location=self.current_node) + subdir = tobj.get_subdir() + namedir = (name, subdir) + + if idname in self.build.targets: + raise InvalidCode(f'Tried to create target "{name}", but a target of that name already exists.') + + if isinstance(tobj, build.Executable) and namedir in self.build.targetnames: + FeatureNew.single_use(f'multiple executables with the same name, "{tobj.name}", but different suffixes in the same directory', + '1.3.0', self.subproject, location=self.current_node) if isinstance(tobj, build.BuildTarget): self.add_languages(tobj.missing_languages, True, tobj.for_machine) @@ -3176,6 +3179,9 @@ def add_target(self, name: str, tobj: build.Target) -> None: self.add_stdlib_info(tobj) self.build.targets[idname] = tobj + # Only need to add executables to this set + if isinstance(tobj, build.Executable): + self.build.targetnames.update([namedir]) if idname not in self.coredata.target_guids: self.coredata.target_guids[idname] = str(uuid.uuid4()).upper() From ada6236f76f4fbce4313b48eeaf9d8485516fde8 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Fri, 20 Oct 2023 11:24:11 +0800 Subject: [PATCH 389/855] i18n module: Invoke itstool with the full command line Certain envs may not support invoking itstool by itself directly as a script as shebang lines are not supported, such as under cmd.exe shells on Windows, that are normally used for Visual Studio (and the like, such as clang-cl) builds. This will call the corresponding interpreter to invoke itstool when needed, so that itstool can be properly run, even if shebang lines are not supported by the env. This will fix building appstream on Windows using clang-cl, for instance. --- mesonbuild/modules/i18n.py | 6 +++++- mesonbuild/scripts/itstool.py | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index c82e580a2a1b..e375674d98e3 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -14,6 +14,7 @@ from __future__ import annotations from os import path +import shlex import typing as T from . import ExtensionModule, ModuleReturnValue, ModuleInfo @@ -360,11 +361,14 @@ def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: ' command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, 'ExternalProgram', mesonlib.File]] = [] command.extend(state.environment.get_build_command()) + + itstool_cmd = self.tools['itstool'].get_command() + # TODO: python 3.8 can use shlex.join() command.extend([ '--internal', 'itstool', 'join', '-i', '@INPUT@', '-o', '@OUTPUT@', - '--itstool=' + self.tools['itstool'].get_path(), + '--itstool=' + ' '.join(shlex.quote(c) for c in itstool_cmd), ]) if its_files: for fname in its_files: diff --git a/mesonbuild/scripts/itstool.py b/mesonbuild/scripts/itstool.py index 0bfcaf9b5292..16af1c23528b 100644 --- a/mesonbuild/scripts/itstool.py +++ b/mesonbuild/scripts/itstool.py @@ -17,6 +17,7 @@ import argparse import subprocess import tempfile +import shlex import shutil import typing as T @@ -56,7 +57,7 @@ def run_join(build_dir: str, itstool: str, its_files: T.List[str], mo_files: T.L shutil.copy(mo_file, tmp_mo_fname) locale_mo_files.append(tmp_mo_fname) - cmd = [itstool] + cmd = shlex.split(itstool) if its_files: for fname in its_files: cmd.extend(['-i', fname]) From 3bbe66e971dfe84dcffa702c2673fb136da0a508 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 26 Oct 2023 19:23:20 +0300 Subject: [PATCH 390/855] Condense test directories for RC1. --- run_format_tests.py | 2 +- .../main.cpp | 0 .../meson.build | 0 .../subprojects/broken_method.wrap | 0 .../subprojects/cmMod.wrap | 0 .../subprojects/cmMod/CMakeLists.txt | 0 .../subprojects/cmMod/cmMod.cpp | 0 .../subprojects/cmMod/cmMod.hpp | 0 .../subprojects/cmMod/cpp_pch.hpp | 0 .../subprojects/cmake_subp/CMakeLists.txt | 0 .../subprojects/force_cmake.wrap | 0 .../subprojects/force_cmake/CMakeLists.txt | 0 .../subprojects/force_cmake/meson.build | 0 .../subprojects/meson_method.wrap | 0 .../subprojects/meson_subp/meson.build | 0 .../include/test_262_header.h | 0 .../meson.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../lib.c | 0 .../meson.build | 0 .../meson_options.txt | 0 .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 0 .../meson.build | 0 .../subprojects/dummy.wrap | 0 .../subprojects/dummy/dummy.c | 0 .../subprojects/dummy/meson.build | 0 .../subprojects/dummy/meson_options.txt | 0 .../foo/file1 | 0 .../foo/link1 | 0 .../foo/link2.h | 0 .../meson.build | 0 .../test.json | 0 .../generate_main.py | 0 .../main.template | 0 .../meson.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../nativefile.ini | 0 .../test.json | 2 +- .../100 no glib-compile-resources/test.json | 7 ---- .../meson.build | 0 .../test.json | 2 +- .../failing/101 number in combo/test.json | 5 --- .../meson.build | 0 .../subprojects/foob/meson.build | 0 .../test.json | 0 .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 0 .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../sub/meson.build | 0 .../test.json | 2 +- .../109 invalid fstring/meson.build | 0 .../109 invalid fstring/test.json | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/foo/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/cmlib/CMakeLists.txt | 0 .../subprojects/cmlib/main.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../src/header.h | 0 .../src/source.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../trivial.c | 0 .../meson.build | 0 .../test.json | 2 +- .../trivial.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/A/meson.build | 0 .../subprojects/B/meson.build | 0 .../test.json | 2 +- .../main.rs | 0 .../meson.build | 0 .../test.json | 2 +- .../main.rs | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/sub/main.c | 0 .../subprojects/sub/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/cmlib/CMakeLists.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../subprojects/subproj1/file.txt | 0 .../subprojects/subproj1/meson.build | 0 .../subprojects/subproj1/nested/meson.build | 0 .../subprojects/subproj2/file.txt | 0 .../subprojects/subproj2/meson.build | 0 .../subprojects/subproj2/nested/meson.build | 0 .../subprojects/subproj3/file.txt | 0 .../subprojects/subproj3/meson.build | 0 .../test.json | 2 +- .../inc/lib.h | 0 .../lib.c | 0 .../meson.build | 0 .../subprojects/a/meson.build | 0 .../subprojects/a/prog.c | 0 .../test.json | 2 +- .../inc/lib.h | 0 .../lib.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../src1.c | 0 .../src2.c | 0 .../test.json | 2 +- .../main.c | 0 .../meson.build | 0 .../subprojects/sub/meson.build | 0 .../test.json | 2 +- .../exe.c | 0 .../lib.in | 0 .../meson.build | 0 .../test.json | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../module.c | 0 .../prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/abc/meson.build | 0 .../subprojects/abc/meson_options.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../prog.c | 0 .../subprojects/a/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/foo/meson.build | 0 .../subprojects/foo/sub.c | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/a/meson.build | 0 .../subprojects/b/meson.build | 0 .../subprojects/b/sneaky.c | 0 .../test.json | 2 +- .../meson.build | 0 .../prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../main.c | 0 .../meson.build | 0 .../subprojects/a/a.c | 0 .../subprojects/a/a.h | 0 .../subprojects/a/meson.build | 0 .../subprojects/b/b.c | 0 .../subprojects/b/b.h | 0 .../subprojects/b/meson.build | 0 .../subprojects/c/c.h | 0 .../subprojects/c/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../file1.txt | 0 .../file2.txt | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subdir/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../overrides.py | 0 .../test.json | 2 +- .../meson.build | 0 .../other.py | 0 .../something.py | 0 .../test.json | 2 +- .../meson.build | 0 .../returncode.py | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../input | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../module.c | 0 .../prog.c | 0 .../test.json | 2 +- .../config9.h.in | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../foo.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/somesubproj/meson.build | 0 .../test.json | 2 +- .../input | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../{88 kwarg dupe => 86 kwarg dupe}/prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../prog.c | 0 .../test.json | 2 +- .../include/pch.h | 0 .../meson.build | 0 .../prog.c | 0 .../src/pch.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../Info.plist.cpp | 0 .../meson.build | 0 .../preproc.py | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../main.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subdir/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 2 +- .../failing/{99 no lang => 97 no lang}/main.c | 0 .../{99 no lang => 97 no lang}/meson.build | 0 .../{99 no lang => 97 no lang}/test.json | 2 +- .../meson.build | 0 .../98 no glib-compile-resources/test.json | 7 ++++ .../trivial.gresource.xml | 0 .../meson.build | 0 .../nativefile.ini | 0 .../failing/99 number in combo/test.json | 5 +++ .../foo.py | 0 .../meson.build | 0 .../subdir/meson.build | 0 .../lib2.rs | 0 .../main.rs | 0 .../meson.build | 0 .../meson.build | 0 .../unit/{104 strip => 103 strip}/lib.c | 0 .../unit/{104 strip => 103 strip}/meson.build | 0 .../meson.build | 0 .../meson.build | 0 .../meson.build | 0 .../script.py | 0 .../com/mesonbuild/Simple.java | 0 .../meson.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../main.c | 0 .../meson.build | 0 .../s1.c | 0 .../s2.c | 0 .../s3.c | 0 .../meson.build | 0 .../expected_mods.json | 0 .../meson.build | 0 .../{115 genvslite => 117 genvslite}/main.cpp | 0 .../meson.build | 0 .../cache_dir/bar/meson.build | 0 .../cache_dir/foo.zip | Bin .../meson.build | 0 .../subprojects/bar.wrap | 0 .../subprojects/foo.wrap | 0 .../meson.build | 0 .../nativefile.ini | 0 .../{118 rewrite => 120 rewrite}/meson.build | 0 .../main.c | 0 .../meson.build | 0 .../foo.c | 0 .../foo.dat | 0 .../foo.h | 0 .../foo/foofile | 0 .../meson.build | 0 .../subprojects/bar/bar.c | 0 .../subprojects/bar/bar.dat | 0 .../subprojects/bar/bar.h | 0 .../subprojects/bar/bar/barfile | 0 .../subprojects/bar/meson.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../subprojects/sub/foo.c | 0 .../subprojects/sub/meson.build | 0 .../.clang-format | 0 .../.clang-format-ignore | 0 .../.clang-format-include | 0 .../meson.build | 0 .../not-included/badformat.cpp | 0 .../src/badformat.c | 0 .../src/badformat.cpp | 0 .../easytogrepfor/genh.py | 0 .../easytogrepfor/meson.build | 0 .../{95 custominc => 94 custominc}/helper.c | 0 .../meson.build | 0 .../{95 custominc => 94 custominc}/prog.c | 0 .../{95 custominc => 94 custominc}/prog2.c | 0 .../meson.build | 0 .../subprojects/something/meson.build | 0 .../meson.build | 0 .../test.c | 0 .../.gitignore | 0 .../libtestprovider/meson.build | 0 .../libtestprovider/provider.c | 0 .../proguser/meson.build | 0 .../proguser/receiver.c | 0 .../bar-custom.txt | 0 .../bar-devel.h | 0 .../bar-notag.txt | 0 .../custom_files/data.txt | 0 .../excludes/excluded.txt | 0 .../excludes/excluded/placeholder.txt | 0 .../excludes/installed.txt | 0 .../foo.in | 0 .../foo1-devel.h | 0 .../lib.c | 0 .../main.c | 0 .../meson.build | 0 .../script.py | 0 .../subdir/bar2-devel.h | 0 .../subdir/foo2.in | 0 .../subdir/foo3-devel.h | 0 .../subdir/lib.c | 0 .../subdir/main.c | 0 .../subdir/meson.build | 0 .../subdir/script.py | 0 .../subprojects/subproject/aaa.txt | 0 .../subprojects/subproject/bbb.txt | 0 .../subprojects/subproject/meson.build | 0 .../file.txt.in | 0 .../meson.build | 0 .../subdir/meson.build | 0 unittests/allplatformstests.py | 36 +++++++++--------- unittests/linuxliketests.py | 8 ++-- unittests/machinefiletests.py | 2 +- unittests/platformagnostictests.py | 12 +++--- unittests/rewritetests.py | 2 +- unittests/windowstests.py | 2 +- 392 files changed, 115 insertions(+), 115 deletions(-) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/main.cpp (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/meson.build (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/broken_method.wrap (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmMod.wrap (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmMod/CMakeLists.txt (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmMod/cmMod.cpp (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmMod/cmMod.hpp (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmMod/cpp_pch.hpp (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/cmake_subp/CMakeLists.txt (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/force_cmake.wrap (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/force_cmake/CMakeLists.txt (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/force_cmake/meson.build (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/meson_method.wrap (100%) rename test cases/cmake/{26 dependency fallback => 27 dependency fallback}/subprojects/meson_subp/meson.build (100%) rename test cases/common/{262 internal dependency includes in checks => 263 internal dependency includes in checks}/include/test_262_header.h (100%) rename test cases/common/{262 internal dependency includes in checks => 263 internal dependency includes in checks}/meson.build (100%) rename test cases/common/{262 required keyword in has functions => 264 required keyword in has functions}/meson.build (100%) rename test cases/common/{262 required keyword in has functions => 264 required keyword in has functions}/meson_options.txt (100%) rename test cases/common/{263 default_options dict => 265 default_options dict}/lib.c (100%) rename test cases/common/{263 default_options dict => 265 default_options dict}/meson.build (100%) rename test cases/common/{263 default_options dict => 265 default_options dict}/meson_options.txt (100%) rename test cases/common/{264 format string => 266 format string}/meson.build (100%) rename test cases/common/{264 format string => 266 format string}/meson_options.txt (100%) rename test cases/common/{264 format string => 266 format string}/test.json (100%) rename test cases/common/{265 default_options in find_program => 267 default_options in find_program}/meson.build (100%) rename test cases/common/{265 default_options in find_program => 267 default_options in find_program}/subprojects/dummy.wrap (100%) rename test cases/common/{265 default_options in find_program => 267 default_options in find_program}/subprojects/dummy/dummy.c (100%) rename test cases/common/{265 default_options in find_program => 267 default_options in find_program}/subprojects/dummy/meson.build (100%) rename test cases/common/{265 default_options in find_program => 267 default_options in find_program}/subprojects/dummy/meson_options.txt (100%) rename test cases/common/{266 install functions and follow_symlinks => 268 install functions and follow_symlinks}/foo/file1 (100%) rename test cases/common/{266 install functions and follow_symlinks => 268 install functions and follow_symlinks}/foo/link1 (100%) rename test cases/common/{266 install functions and follow_symlinks => 268 install functions and follow_symlinks}/foo/link2.h (100%) rename test cases/common/{266 install functions and follow_symlinks => 268 install functions and follow_symlinks}/meson.build (100%) rename test cases/common/{266 install functions and follow_symlinks => 268 install functions and follow_symlinks}/test.json (100%) rename test cases/common/{272 env in generator.process => 271 env in generator.process}/generate_main.py (100%) rename test cases/common/{272 env in generator.process => 271 env in generator.process}/main.template (100%) rename test cases/common/{272 env in generator.process => 271 env in generator.process}/meson.build (100%) rename test cases/failing/{102 bool in combo => 100 bool in combo}/meson.build (100%) rename test cases/failing/{102 bool in combo => 100 bool in combo}/meson_options.txt (100%) rename test cases/failing/{102 bool in combo => 100 bool in combo}/nativefile.ini (100%) rename test cases/failing/{102 bool in combo => 100 bool in combo}/test.json (73%) delete mode 100644 test cases/failing/100 no glib-compile-resources/test.json rename test cases/failing/{103 compiler no lang => 101 compiler no lang}/meson.build (100%) rename test cases/failing/{103 compiler no lang => 101 compiler no lang}/test.json (66%) delete mode 100644 test cases/failing/101 number in combo/test.json rename test cases/failing/{104 no fallback => 102 no fallback}/meson.build (100%) rename test cases/failing/{104 no fallback => 102 no fallback}/subprojects/foob/meson.build (100%) rename test cases/failing/{104 no fallback => 102 no fallback}/test.json (100%) rename test cases/failing/{105 feature require => 103 feature require}/meson.build (100%) rename test cases/failing/{105 feature require => 103 feature require}/meson_options.txt (100%) rename test cases/failing/{105 feature require => 103 feature require}/test.json (100%) rename test cases/failing/{106 feature require.bis => 104 feature require.bis}/meson.build (100%) rename test cases/failing/{106 feature require.bis => 104 feature require.bis}/meson_options.txt (100%) rename test cases/failing/{106 feature require.bis => 104 feature require.bis}/test.json (100%) rename test cases/failing/{107 no build get_external_property => 105 no build get_external_property}/meson.build (100%) rename test cases/failing/{107 no build get_external_property => 105 no build get_external_property}/test.json (63%) rename test cases/failing/{108 enter subdir twice => 106 enter subdir twice}/meson.build (100%) rename test cases/failing/{108 enter subdir twice => 106 enter subdir twice}/sub/meson.build (100%) rename test cases/failing/{108 enter subdir twice => 106 enter subdir twice}/test.json (64%) rename test cases/failing/{109 invalid fstring => 107 invalid fstring}/109 invalid fstring/meson.build (100%) rename test cases/failing/{109 invalid fstring => 107 invalid fstring}/109 invalid fstring/test.json (100%) rename test cases/failing/{109 invalid fstring => 107 invalid fstring}/meson.build (100%) rename test cases/failing/{109 invalid fstring => 107 invalid fstring}/test.json (63%) rename test cases/failing/{110 compiler argument checking => 108 compiler argument checking}/meson.build (100%) rename test cases/failing/{110 compiler argument checking => 108 compiler argument checking}/test.json (66%) rename test cases/failing/{111 empty fallback => 109 empty fallback}/meson.build (100%) rename test cases/failing/{111 empty fallback => 109 empty fallback}/subprojects/foo/meson.build (100%) rename test cases/failing/{111 empty fallback => 109 empty fallback}/test.json (65%) rename test cases/failing/{112 cmake executable dependency => 110 cmake executable dependency}/meson.build (100%) rename test cases/failing/{112 cmake executable dependency => 110 cmake executable dependency}/subprojects/cmlib/CMakeLists.txt (100%) rename test cases/failing/{112 cmake executable dependency => 110 cmake executable dependency}/subprojects/cmlib/main.c (100%) rename test cases/failing/{112 cmake executable dependency => 110 cmake executable dependency}/test.json (77%) rename test cases/failing/{113 allow_fallback with fallback => 111 allow_fallback with fallback}/meson.build (100%) rename test cases/failing/{113 allow_fallback with fallback => 111 allow_fallback with fallback}/test.json (70%) rename test cases/failing/{114 nonsensical bindgen => 112 nonsensical bindgen}/meson.build (100%) rename test cases/failing/{114 nonsensical bindgen => 112 nonsensical bindgen}/src/header.h (100%) rename test cases/failing/{114 nonsensical bindgen => 112 nonsensical bindgen}/src/source.c (100%) rename test cases/failing/{114 nonsensical bindgen => 112 nonsensical bindgen}/test.json (69%) rename test cases/failing/{115 run_target in test => 113 run_target in test}/meson.build (100%) rename test cases/failing/{115 run_target in test => 113 run_target in test}/test.json (77%) rename test cases/failing/{115 run_target in test => 113 run_target in test}/trivial.c (100%) rename test cases/failing/{116 run_target in add_install_script => 114 run_target in add_install_script}/meson.build (100%) rename test cases/failing/{116 run_target in add_install_script => 114 run_target in add_install_script}/test.json (81%) rename test cases/failing/{116 run_target in add_install_script => 114 run_target in add_install_script}/trivial.c (100%) rename test cases/failing/{117 pathsep in install_symlink => 115 pathsep in install_symlink}/meson.build (100%) rename test cases/failing/{117 pathsep in install_symlink => 115 pathsep in install_symlink}/test.json (74%) rename test cases/failing/{118 subproject version conflict => 116 subproject version conflict}/meson.build (100%) rename test cases/failing/{118 subproject version conflict => 116 subproject version conflict}/subprojects/A/meson.build (100%) rename test cases/failing/{118 subproject version conflict => 116 subproject version conflict}/subprojects/B/meson.build (100%) rename test cases/failing/{118 subproject version conflict => 116 subproject version conflict}/test.json (66%) rename test cases/failing/{119 structured source empty string => 117 structured source empty string}/main.rs (100%) rename test cases/failing/{119 structured source empty string => 117 structured source empty string}/meson.build (100%) rename test cases/failing/{119 structured source empty string => 117 structured source empty string}/test.json (71%) rename test cases/failing/{120 structured_sources conflicts => 118 structured_sources conflicts}/main.rs (100%) rename test cases/failing/{120 structured_sources conflicts => 118 structured_sources conflicts}/meson.build (100%) rename test cases/failing/{120 structured_sources conflicts => 118 structured_sources conflicts}/test.json (67%) rename test cases/failing/{121 missing compiler => 119 missing compiler}/meson.build (100%) rename test cases/failing/{121 missing compiler => 119 missing compiler}/subprojects/sub/main.c (100%) rename test cases/failing/{121 missing compiler => 119 missing compiler}/subprojects/sub/meson.build (100%) rename test cases/failing/{121 missing compiler => 119 missing compiler}/test.json (68%) rename test cases/failing/{122 cmake subproject error => 120 cmake subproject error}/meson.build (100%) rename test cases/failing/{122 cmake subproject error => 120 cmake subproject error}/subprojects/cmlib/CMakeLists.txt (100%) rename test cases/failing/{122 cmake subproject error => 120 cmake subproject error}/test.json (74%) rename test cases/failing/{123 pkgconfig not relocatable outside prefix => 121 pkgconfig not relocatable outside prefix}/meson.build (100%) rename test cases/failing/{123 pkgconfig not relocatable outside prefix => 121 pkgconfig not relocatable outside prefix}/test.json (78%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/meson_options.txt (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj1/file.txt (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj1/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj1/nested/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj2/file.txt (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj2/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj2/nested/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj3/file.txt (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/subprojects/subproj3/meson.build (100%) rename test cases/failing/{124 subproject sandbox violation => 122 subproject sandbox violation}/test.json (82%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/inc/lib.h (100%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/lib.c (100%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/meson.build (100%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/subprojects/a/meson.build (100%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/subprojects/a/prog.c (100%) rename test cases/failing/{125 override and add_project_dependency => 123 override and add_project_dependency}/test.json (66%) rename test cases/failing/{126 targets before add_project_dependency => 124 targets before add_project_dependency}/inc/lib.h (100%) rename test cases/failing/{126 targets before add_project_dependency => 124 targets before add_project_dependency}/lib.c (100%) rename test cases/failing/{126 targets before add_project_dependency => 124 targets before add_project_dependency}/meson.build (100%) rename test cases/failing/{126 targets before add_project_dependency => 124 targets before add_project_dependency}/test.json (70%) rename test cases/failing/{127 extract from unity => 125 extract from unity}/meson.build (100%) rename test cases/failing/{127 extract from unity => 125 extract from unity}/src1.c (100%) rename test cases/failing/{127 extract from unity => 125 extract from unity}/src2.c (100%) rename test cases/failing/{127 extract from unity => 125 extract from unity}/test.json (73%) rename test cases/failing/{128 subproject object as a dependency => 126 subproject object as a dependency}/main.c (100%) rename test cases/failing/{128 subproject object as a dependency => 126 subproject object as a dependency}/meson.build (100%) rename test cases/failing/{128 subproject object as a dependency => 126 subproject object as a dependency}/subprojects/sub/meson.build (100%) rename test cases/failing/{128 subproject object as a dependency => 126 subproject object as a dependency}/test.json (64%) rename test cases/failing/{129 generator host binary => 127 generator host binary}/exe.c (100%) rename test cases/failing/{129 generator host binary => 127 generator host binary}/lib.in (100%) rename test cases/failing/{129 generator host binary => 127 generator host binary}/meson.build (100%) rename test cases/failing/{129 generator host binary => 127 generator host binary}/test.json (100%) rename test cases/failing/{130 invalid ast => 128 invalid ast}/meson.build (100%) rename test cases/failing/{130 invalid ast => 128 invalid ast}/test.json (67%) rename test cases/failing/{131 invalid project function => 129 invalid project function}/meson.build (100%) rename test cases/failing/{131 invalid project function => 129 invalid project function}/test.json (69%) rename test cases/failing/{55 or on new line => 53 or on new line}/meson.build (100%) rename test cases/failing/{55 or on new line => 53 or on new line}/meson_options.txt (100%) rename test cases/failing/{55 or on new line => 53 or on new line}/test.json (50%) rename test cases/failing/{56 link with executable => 54 link with executable}/meson.build (100%) rename test cases/failing/{56 link with executable => 54 link with executable}/module.c (100%) rename test cases/failing/{56 link with executable => 54 link with executable}/prog.c (100%) rename test cases/failing/{56 link with executable => 54 link with executable}/test.json (58%) rename test cases/failing/{57 assign custom target index => 55 assign custom target index}/meson.build (100%) rename test cases/failing/{57 assign custom target index => 55 assign custom target index}/test.json (59%) rename test cases/failing/{58 getoption prefix => 56 getoption prefix}/meson.build (100%) rename test cases/failing/{58 getoption prefix => 56 getoption prefix}/subprojects/abc/meson.build (100%) rename test cases/failing/{58 getoption prefix => 56 getoption prefix}/subprojects/abc/meson_options.txt (100%) rename test cases/failing/{58 getoption prefix => 56 getoption prefix}/test.json (72%) rename test cases/failing/{59 bad option argument => 57 bad option argument}/meson.build (100%) rename test cases/failing/{59 bad option argument => 57 bad option argument}/meson_options.txt (100%) rename test cases/failing/{59 bad option argument => 57 bad option argument}/test.json (63%) rename test cases/failing/{60 subproj filegrab => 58 subproj filegrab}/meson.build (100%) rename test cases/failing/{60 subproj filegrab => 58 subproj filegrab}/prog.c (100%) rename test cases/failing/{60 subproj filegrab => 58 subproj filegrab}/subprojects/a/meson.build (100%) rename test cases/failing/{60 subproj filegrab => 58 subproj filegrab}/test.json (68%) rename test cases/failing/{61 grab subproj => 59 grab subproj}/meson.build (100%) rename test cases/failing/{61 grab subproj => 59 grab subproj}/subprojects/foo/meson.build (100%) rename test cases/failing/{61 grab subproj => 59 grab subproj}/subprojects/foo/sub.c (100%) rename test cases/failing/{61 grab subproj => 59 grab subproj}/test.json (64%) rename test cases/failing/{62 grab sibling => 60 grab sibling}/meson.build (100%) rename test cases/failing/{62 grab sibling => 60 grab sibling}/subprojects/a/meson.build (100%) rename test cases/failing/{62 grab sibling => 60 grab sibling}/subprojects/b/meson.build (100%) rename test cases/failing/{62 grab sibling => 60 grab sibling}/subprojects/b/sneaky.c (100%) rename test cases/failing/{62 grab sibling => 60 grab sibling}/test.json (68%) rename test cases/failing/{63 string as link target => 61 string as link target}/meson.build (100%) rename test cases/failing/{63 string as link target => 61 string as link target}/prog.c (100%) rename test cases/failing/{63 string as link target => 61 string as link target}/test.json (53%) rename test cases/failing/{64 dependency not-found and required => 62 dependency not-found and required}/meson.build (100%) rename test cases/failing/{64 dependency not-found and required => 62 dependency not-found and required}/test.json (63%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/main.c (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/meson.build (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/a/a.c (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/a/a.h (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/a/meson.build (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/b/b.c (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/b/b.h (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/b/meson.build (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/c/c.h (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/subprojects/c/meson.build (100%) rename test cases/failing/{65 subproj different versions => 63 subproj different versions}/test.json (64%) rename test cases/failing/{66 wrong boost module => 64 wrong boost module}/meson.build (100%) rename test cases/failing/{66 wrong boost module => 64 wrong boost module}/test.json (60%) rename test cases/failing/{67 install_data rename bad size => 65 install_data rename bad size}/file1.txt (100%) rename test cases/failing/{67 install_data rename bad size => 65 install_data rename bad size}/file2.txt (100%) rename test cases/failing/{67 install_data rename bad size => 65 install_data rename bad size}/meson.build (100%) rename test cases/failing/{67 install_data rename bad size => 65 install_data rename bad size}/test.json (75%) rename test cases/failing/{68 skip only subdir => 66 skip only subdir}/meson.build (100%) rename test cases/failing/{68 skip only subdir => 66 skip only subdir}/subdir/meson.build (100%) rename test cases/failing/{68 skip only subdir => 66 skip only subdir}/test.json (55%) rename test cases/failing/{69 dual override => 67 dual override}/meson.build (100%) rename test cases/failing/{69 dual override => 67 dual override}/overrides.py (100%) rename test cases/failing/{69 dual override => 67 dual override}/test.json (65%) rename test cases/failing/{70 override used => 68 override used}/meson.build (100%) rename test cases/failing/{70 override used => 68 override used}/other.py (100%) rename test cases/failing/{70 override used => 68 override used}/something.py (100%) rename test cases/failing/{70 override used => 68 override used}/test.json (67%) rename test cases/failing/{71 run_command unclean exit => 69 run_command unclean exit}/meson.build (100%) rename test cases/failing/{71 run_command unclean exit => 69 run_command unclean exit}/returncode.py (100%) rename test cases/failing/{71 run_command unclean exit => 69 run_command unclean exit}/test.json (56%) rename test cases/failing/{72 int literal leading zero => 70 int literal leading zero}/meson.build (100%) rename test cases/failing/{72 int literal leading zero => 70 int literal leading zero}/test.json (69%) rename test cases/failing/{73 configuration immutable => 71 configuration immutable}/input (100%) rename test cases/failing/{73 configuration immutable => 71 configuration immutable}/meson.build (100%) rename test cases/failing/{73 configuration immutable => 71 configuration immutable}/test.json (65%) rename test cases/failing/{74 link with shared module on osx => 72 link with shared module on osx}/meson.build (100%) rename test cases/failing/{74 link with shared module on osx => 72 link with shared module on osx}/module.c (100%) rename test cases/failing/{74 link with shared module on osx => 72 link with shared module on osx}/prog.c (100%) rename test cases/failing/{74 link with shared module on osx => 72 link with shared module on osx}/test.json (68%) rename test cases/failing/{75 non-ascii in ascii encoded configure file => 73 non-ascii in ascii encoded configure file}/config9.h.in (100%) rename test cases/failing/{75 non-ascii in ascii encoded configure file => 73 non-ascii in ascii encoded configure file}/meson.build (100%) rename test cases/failing/{75 non-ascii in ascii encoded configure file => 73 non-ascii in ascii encoded configure file}/test.json (79%) rename test cases/failing/{76 subproj dependency not-found and required => 74 subproj dependency not-found and required}/meson.build (100%) rename test cases/failing/{76 subproj dependency not-found and required => 74 subproj dependency not-found and required}/test.json (68%) rename test cases/failing/{77 unfound run => 75 unfound run}/meson.build (100%) rename test cases/failing/{77 unfound run => 75 unfound run}/test.json (60%) rename test cases/failing/{78 framework dependency with version => 76 framework dependency with version}/meson.build (100%) rename test cases/failing/{78 framework dependency with version => 76 framework dependency with version}/test.json (72%) rename test cases/failing/{79 override exe config => 77 override exe config}/foo.c (100%) rename test cases/failing/{79 override exe config => 77 override exe config}/meson.build (100%) rename test cases/failing/{79 override exe config => 77 override exe config}/test.json (72%) rename test cases/failing/{80 gl dependency with version => 78 gl dependency with version}/meson.build (100%) rename test cases/failing/{80 gl dependency with version => 78 gl dependency with version}/test.json (69%) rename test cases/failing/{81 threads dependency with version => 79 threads dependency with version}/meson.build (100%) rename test cases/failing/{81 threads dependency with version => 79 threads dependency with version}/test.json (71%) rename test cases/failing/{82 gtest dependency with version => 80 gtest dependency with version}/meson.build (100%) rename test cases/failing/{82 gtest dependency with version => 80 gtest dependency with version}/test.json (62%) rename test cases/failing/{83 dub library => 81 dub library}/meson.build (100%) rename test cases/failing/{83 dub library => 81 dub library}/test.json (57%) rename test cases/failing/{84 dub executable => 82 dub executable}/meson.build (100%) rename test cases/failing/{84 dub executable => 82 dub executable}/test.json (59%) rename test cases/failing/{85 dub compiler => 83 dub compiler}/meson.build (100%) rename test cases/failing/{85 dub compiler => 83 dub compiler}/test.json (81%) rename test cases/failing/{86 subproj not-found dep => 84 subproj not-found dep}/meson.build (100%) rename test cases/failing/{86 subproj not-found dep => 84 subproj not-found dep}/subprojects/somesubproj/meson.build (100%) rename test cases/failing/{86 subproj not-found dep => 84 subproj not-found dep}/test.json (62%) rename test cases/failing/{87 invalid configure file => 85 invalid configure file}/input (100%) rename test cases/failing/{87 invalid configure file => 85 invalid configure file}/meson.build (100%) rename test cases/failing/{87 invalid configure file => 85 invalid configure file}/test.json (67%) rename test cases/failing/{88 kwarg dupe => 86 kwarg dupe}/meson.build (100%) rename test cases/failing/{88 kwarg dupe => 86 kwarg dupe}/prog.c (100%) rename test cases/failing/{88 kwarg dupe => 86 kwarg dupe}/test.json (65%) rename test cases/failing/{89 missing pch file => 87 missing pch file}/meson.build (100%) rename test cases/failing/{89 missing pch file => 87 missing pch file}/prog.c (100%) rename test cases/failing/{89 missing pch file => 87 missing pch file}/test.json (74%) rename test cases/failing/{90 pch source different folder => 88 pch source different folder}/include/pch.h (100%) rename test cases/failing/{90 pch source different folder => 88 pch source different folder}/meson.build (100%) rename test cases/failing/{90 pch source different folder => 88 pch source different folder}/prog.c (100%) rename test cases/failing/{90 pch source different folder => 88 pch source different folder}/src/pch.c (100%) rename test cases/failing/{90 pch source different folder => 88 pch source different folder}/test.json (62%) rename test cases/failing/{91 unknown config tool => 89 unknown config tool}/meson.build (100%) rename test cases/failing/{91 unknown config tool => 89 unknown config tool}/test.json (60%) rename test cases/failing/{92 custom target install data => 90 custom target install data}/Info.plist.cpp (100%) rename test cases/failing/{92 custom target install data => 90 custom target install data}/meson.build (100%) rename test cases/failing/{92 custom target install data => 90 custom target install data}/preproc.py (100%) rename test cases/failing/{92 custom target install data => 90 custom target install data}/test.json (71%) rename test cases/failing/{93 add dict non string key => 91 add dict non string key}/meson.build (100%) rename test cases/failing/{93 add dict non string key => 91 add dict non string key}/test.json (54%) rename test cases/failing/{94 add dict duplicate keys => 92 add dict duplicate keys}/meson.build (100%) rename test cases/failing/{94 add dict duplicate keys => 92 add dict duplicate keys}/test.json (58%) rename test cases/failing/{95 no host get_external_property => 93 no host get_external_property}/meson.build (100%) rename test cases/failing/{95 no host get_external_property => 93 no host get_external_property}/test.json (63%) rename test cases/failing/{96 no native compiler => 94 no native compiler}/main.c (100%) rename test cases/failing/{96 no native compiler => 94 no native compiler}/meson.build (100%) rename test cases/failing/{96 no native compiler => 94 no native compiler}/test.json (58%) rename test cases/failing/{97 subdir parse error => 95 subdir parse error}/meson.build (100%) rename test cases/failing/{97 subdir parse error => 95 subdir parse error}/subdir/meson.build (100%) rename test cases/failing/{97 subdir parse error => 95 subdir parse error}/test.json (59%) rename test cases/failing/{98 invalid option file => 96 invalid option file}/meson.build (100%) rename test cases/failing/{98 invalid option file => 96 invalid option file}/meson_options.txt (100%) rename test cases/failing/{98 invalid option file => 96 invalid option file}/test.json (50%) rename test cases/failing/{99 no lang => 97 no lang}/main.c (100%) rename test cases/failing/{99 no lang => 97 no lang}/meson.build (100%) rename test cases/failing/{99 no lang => 97 no lang}/test.json (54%) rename test cases/failing/{100 no glib-compile-resources => 98 no glib-compile-resources}/meson.build (100%) create mode 100644 test cases/failing/98 no glib-compile-resources/test.json rename test cases/failing/{100 no glib-compile-resources => 98 no glib-compile-resources}/trivial.gresource.xml (100%) rename test cases/failing/{101 number in combo => 99 number in combo}/meson.build (100%) rename test cases/failing/{101 number in combo => 99 number in combo}/nativefile.ini (100%) create mode 100644 test cases/failing/99 number in combo/test.json rename test cases/unit/{101 relative find program => 100 relative find program}/foo.py (100%) rename test cases/unit/{101 relative find program => 100 relative find program}/meson.build (100%) rename test cases/unit/{101 relative find program => 100 relative find program}/subdir/meson.build (100%) rename test cases/unit/{102 rlib linkage => 101 rlib linkage}/lib2.rs (100%) rename test cases/unit/{102 rlib linkage => 101 rlib linkage}/main.rs (100%) rename test cases/unit/{102 rlib linkage => 101 rlib linkage}/meson.build (100%) rename test cases/unit/{103 python without pkgconfig => 102 python without pkgconfig}/meson.build (100%) rename test cases/unit/{104 strip => 103 strip}/lib.c (100%) rename test cases/unit/{104 strip => 103 strip}/meson.build (100%) rename test cases/unit/{105 debug function => 104 debug function}/meson.build (100%) rename test cases/unit/{106 pkgconfig relocatable with absolute path => 105 pkgconfig relocatable with absolute path}/meson.build (100%) rename test cases/unit/{110 replace unencodable xml chars => 111 replace unencodable xml chars}/meson.build (100%) rename test cases/unit/{110 replace unencodable xml chars => 111 replace unencodable xml chars}/script.py (100%) rename test cases/unit/{111 classpath => 112 classpath}/com/mesonbuild/Simple.java (100%) rename test cases/unit/{111 classpath => 112 classpath}/meson.build (100%) rename test cases/unit/{112 list build options => 113 list build options}/meson.build (100%) rename test cases/unit/{112 list build options => 113 list build options}/meson_options.txt (100%) rename test cases/unit/{113 complex link cases => 114 complex link cases}/main.c (100%) rename test cases/unit/{113 complex link cases => 114 complex link cases}/meson.build (100%) rename test cases/unit/{113 complex link cases => 114 complex link cases}/s1.c (100%) rename test cases/unit/{113 complex link cases => 114 complex link cases}/s2.c (100%) rename test cases/unit/{113 complex link cases => 114 complex link cases}/s3.c (100%) rename test cases/unit/{114 c cpp stds => 115 c cpp stds}/meson.build (100%) rename test cases/unit/{114 empty project => 116 empty project}/expected_mods.json (100%) rename test cases/unit/{114 empty project => 116 empty project}/meson.build (100%) rename test cases/unit/{115 genvslite => 117 genvslite}/main.cpp (100%) rename test cases/unit/{115 genvslite => 117 genvslite}/meson.build (100%) rename test cases/unit/{116 meson package cache dir => 118 meson package cache dir}/cache_dir/bar/meson.build (100%) rename test cases/unit/{116 meson package cache dir => 118 meson package cache dir}/cache_dir/foo.zip (100%) rename test cases/unit/{116 meson package cache dir => 118 meson package cache dir}/meson.build (100%) rename test cases/unit/{116 meson package cache dir => 118 meson package cache dir}/subprojects/bar.wrap (100%) rename test cases/unit/{116 meson package cache dir => 118 meson package cache dir}/subprojects/foo.wrap (100%) rename test cases/unit/{117 openssl cmake bug => 119 openssl cmake bug}/meson.build (100%) rename test cases/unit/{117 openssl cmake bug => 119 openssl cmake bug}/nativefile.ini (100%) rename test cases/unit/{118 rewrite => 120 rewrite}/meson.build (100%) rename test cases/unit/{119 executable suffix => 121 executable suffix}/main.c (100%) rename test cases/unit/{119 executable suffix => 121 executable suffix}/meson.build (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/foo.c (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/foo.dat (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/foo.h (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/foo/foofile (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/meson.build (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/subprojects/bar/bar.c (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/subprojects/bar/bar.dat (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/subprojects/bar/bar.h (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/subprojects/bar/bar/barfile (100%) rename test cases/unit/{92 install skip subprojects => 91 install skip subprojects}/subprojects/bar/meson.build (100%) rename test cases/unit/{93 new subproject in configured project => 92 new subproject in configured project}/meson.build (100%) rename test cases/unit/{93 new subproject in configured project => 92 new subproject in configured project}/meson_options.txt (100%) rename test cases/unit/{93 new subproject in configured project => 92 new subproject in configured project}/subprojects/sub/foo.c (100%) rename test cases/unit/{93 new subproject in configured project => 92 new subproject in configured project}/subprojects/sub/meson.build (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/.clang-format (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/.clang-format-ignore (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/.clang-format-include (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/meson.build (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/not-included/badformat.cpp (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/src/badformat.c (100%) rename test cases/unit/{94 clangformat => 93 clangformat}/src/badformat.cpp (100%) rename test cases/unit/{95 custominc => 94 custominc}/easytogrepfor/genh.py (100%) rename test cases/unit/{95 custominc => 94 custominc}/easytogrepfor/meson.build (100%) rename test cases/unit/{95 custominc => 94 custominc}/helper.c (100%) rename test cases/unit/{95 custominc => 94 custominc}/meson.build (100%) rename test cases/unit/{95 custominc => 94 custominc}/prog.c (100%) rename test cases/unit/{95 custominc => 94 custominc}/prog2.c (100%) rename test cases/unit/{96 implicit force fallback => 95 implicit force fallback}/meson.build (100%) rename test cases/unit/{96 implicit force fallback => 95 implicit force fallback}/subprojects/something/meson.build (100%) rename test cases/unit/{97 compiler.links file arg => 96 compiler.links file arg}/meson.build (100%) rename test cases/unit/{97 compiler.links file arg => 96 compiler.links file arg}/test.c (100%) rename test cases/unit/{98 link full name => 97 link full name}/.gitignore (100%) rename test cases/unit/{98 link full name => 97 link full name}/libtestprovider/meson.build (100%) rename test cases/unit/{98 link full name => 97 link full name}/libtestprovider/provider.c (100%) rename test cases/unit/{98 link full name => 97 link full name}/proguser/meson.build (100%) rename test cases/unit/{98 link full name => 97 link full name}/proguser/receiver.c (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/bar-custom.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/bar-devel.h (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/bar-notag.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/custom_files/data.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/excludes/excluded.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/excludes/excluded/placeholder.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/excludes/installed.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/foo.in (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/foo1-devel.h (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/lib.c (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/main.c (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/meson.build (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/script.py (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/bar2-devel.h (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/foo2.in (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/foo3-devel.h (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/lib.c (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/main.c (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/meson.build (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subdir/script.py (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subprojects/subproject/aaa.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subprojects/subproject/bbb.txt (100%) rename test cases/unit/{99 install all targets => 98 install all targets}/subprojects/subproject/meson.build (100%) rename test cases/unit/{100 custom target name => 99 custom target name}/file.txt.in (100%) rename test cases/unit/{100 custom target name => 99 custom target name}/meson.build (100%) rename test cases/unit/{100 custom target name => 99 custom target name}/subdir/meson.build (100%) diff --git a/run_format_tests.py b/run_format_tests.py index 1bf997ccc179..70fa1212e129 100644 --- a/run_format_tests.py +++ b/run_format_tests.py @@ -63,7 +63,7 @@ def check_format() -> None: 'work area', '.eggs', '_cache', # e.g. .mypy_cache 'venv', # virtualenvs have DOS line endings - '118 rewrite', # we explicitly test for tab in meson.build file + '120 rewrite', # we explicitly test for tab in meson.build file } for (root, _, filenames) in os.walk('.'): if any([x in root for x in skip_dirs]): diff --git a/test cases/cmake/26 dependency fallback/main.cpp b/test cases/cmake/27 dependency fallback/main.cpp similarity index 100% rename from test cases/cmake/26 dependency fallback/main.cpp rename to test cases/cmake/27 dependency fallback/main.cpp diff --git a/test cases/cmake/26 dependency fallback/meson.build b/test cases/cmake/27 dependency fallback/meson.build similarity index 100% rename from test cases/cmake/26 dependency fallback/meson.build rename to test cases/cmake/27 dependency fallback/meson.build diff --git a/test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap b/test cases/cmake/27 dependency fallback/subprojects/broken_method.wrap similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/broken_method.wrap rename to test cases/cmake/27 dependency fallback/subprojects/broken_method.wrap diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap b/test cases/cmake/27 dependency fallback/subprojects/cmMod.wrap similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmMod.wrap rename to test cases/cmake/27 dependency fallback/subprojects/cmMod.wrap diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmMod/CMakeLists.txt rename to test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp b/test cases/cmake/27 dependency fallback/subprojects/cmMod/cmMod.cpp similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.cpp rename to test cases/cmake/27 dependency fallback/subprojects/cmMod/cmMod.cpp diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp b/test cases/cmake/27 dependency fallback/subprojects/cmMod/cmMod.hpp similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmMod/cmMod.hpp rename to test cases/cmake/27 dependency fallback/subprojects/cmMod/cmMod.hpp diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp b/test cases/cmake/27 dependency fallback/subprojects/cmMod/cpp_pch.hpp similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmMod/cpp_pch.hpp rename to test cases/cmake/27 dependency fallback/subprojects/cmMod/cpp_pch.hpp diff --git a/test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt b/test cases/cmake/27 dependency fallback/subprojects/cmake_subp/CMakeLists.txt similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/cmake_subp/CMakeLists.txt rename to test cases/cmake/27 dependency fallback/subprojects/cmake_subp/CMakeLists.txt diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap b/test cases/cmake/27 dependency fallback/subprojects/force_cmake.wrap similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/force_cmake.wrap rename to test cases/cmake/27 dependency fallback/subprojects/force_cmake.wrap diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt b/test cases/cmake/27 dependency fallback/subprojects/force_cmake/CMakeLists.txt similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/force_cmake/CMakeLists.txt rename to test cases/cmake/27 dependency fallback/subprojects/force_cmake/CMakeLists.txt diff --git a/test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build b/test cases/cmake/27 dependency fallback/subprojects/force_cmake/meson.build similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/force_cmake/meson.build rename to test cases/cmake/27 dependency fallback/subprojects/force_cmake/meson.build diff --git a/test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap b/test cases/cmake/27 dependency fallback/subprojects/meson_method.wrap similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/meson_method.wrap rename to test cases/cmake/27 dependency fallback/subprojects/meson_method.wrap diff --git a/test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build b/test cases/cmake/27 dependency fallback/subprojects/meson_subp/meson.build similarity index 100% rename from test cases/cmake/26 dependency fallback/subprojects/meson_subp/meson.build rename to test cases/cmake/27 dependency fallback/subprojects/meson_subp/meson.build diff --git a/test cases/common/262 internal dependency includes in checks/include/test_262_header.h b/test cases/common/263 internal dependency includes in checks/include/test_262_header.h similarity index 100% rename from test cases/common/262 internal dependency includes in checks/include/test_262_header.h rename to test cases/common/263 internal dependency includes in checks/include/test_262_header.h diff --git a/test cases/common/262 internal dependency includes in checks/meson.build b/test cases/common/263 internal dependency includes in checks/meson.build similarity index 100% rename from test cases/common/262 internal dependency includes in checks/meson.build rename to test cases/common/263 internal dependency includes in checks/meson.build diff --git a/test cases/common/262 required keyword in has functions/meson.build b/test cases/common/264 required keyword in has functions/meson.build similarity index 100% rename from test cases/common/262 required keyword in has functions/meson.build rename to test cases/common/264 required keyword in has functions/meson.build diff --git a/test cases/common/262 required keyword in has functions/meson_options.txt b/test cases/common/264 required keyword in has functions/meson_options.txt similarity index 100% rename from test cases/common/262 required keyword in has functions/meson_options.txt rename to test cases/common/264 required keyword in has functions/meson_options.txt diff --git a/test cases/common/263 default_options dict/lib.c b/test cases/common/265 default_options dict/lib.c similarity index 100% rename from test cases/common/263 default_options dict/lib.c rename to test cases/common/265 default_options dict/lib.c diff --git a/test cases/common/263 default_options dict/meson.build b/test cases/common/265 default_options dict/meson.build similarity index 100% rename from test cases/common/263 default_options dict/meson.build rename to test cases/common/265 default_options dict/meson.build diff --git a/test cases/common/263 default_options dict/meson_options.txt b/test cases/common/265 default_options dict/meson_options.txt similarity index 100% rename from test cases/common/263 default_options dict/meson_options.txt rename to test cases/common/265 default_options dict/meson_options.txt diff --git a/test cases/common/264 format string/meson.build b/test cases/common/266 format string/meson.build similarity index 100% rename from test cases/common/264 format string/meson.build rename to test cases/common/266 format string/meson.build diff --git a/test cases/common/264 format string/meson_options.txt b/test cases/common/266 format string/meson_options.txt similarity index 100% rename from test cases/common/264 format string/meson_options.txt rename to test cases/common/266 format string/meson_options.txt diff --git a/test cases/common/264 format string/test.json b/test cases/common/266 format string/test.json similarity index 100% rename from test cases/common/264 format string/test.json rename to test cases/common/266 format string/test.json diff --git a/test cases/common/265 default_options in find_program/meson.build b/test cases/common/267 default_options in find_program/meson.build similarity index 100% rename from test cases/common/265 default_options in find_program/meson.build rename to test cases/common/267 default_options in find_program/meson.build diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy.wrap b/test cases/common/267 default_options in find_program/subprojects/dummy.wrap similarity index 100% rename from test cases/common/265 default_options in find_program/subprojects/dummy.wrap rename to test cases/common/267 default_options in find_program/subprojects/dummy.wrap diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c b/test cases/common/267 default_options in find_program/subprojects/dummy/dummy.c similarity index 100% rename from test cases/common/265 default_options in find_program/subprojects/dummy/dummy.c rename to test cases/common/267 default_options in find_program/subprojects/dummy/dummy.c diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/meson.build b/test cases/common/267 default_options in find_program/subprojects/dummy/meson.build similarity index 100% rename from test cases/common/265 default_options in find_program/subprojects/dummy/meson.build rename to test cases/common/267 default_options in find_program/subprojects/dummy/meson.build diff --git a/test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt b/test cases/common/267 default_options in find_program/subprojects/dummy/meson_options.txt similarity index 100% rename from test cases/common/265 default_options in find_program/subprojects/dummy/meson_options.txt rename to test cases/common/267 default_options in find_program/subprojects/dummy/meson_options.txt diff --git a/test cases/common/266 install functions and follow_symlinks/foo/file1 b/test cases/common/268 install functions and follow_symlinks/foo/file1 similarity index 100% rename from test cases/common/266 install functions and follow_symlinks/foo/file1 rename to test cases/common/268 install functions and follow_symlinks/foo/file1 diff --git a/test cases/common/266 install functions and follow_symlinks/foo/link1 b/test cases/common/268 install functions and follow_symlinks/foo/link1 similarity index 100% rename from test cases/common/266 install functions and follow_symlinks/foo/link1 rename to test cases/common/268 install functions and follow_symlinks/foo/link1 diff --git a/test cases/common/266 install functions and follow_symlinks/foo/link2.h b/test cases/common/268 install functions and follow_symlinks/foo/link2.h similarity index 100% rename from test cases/common/266 install functions and follow_symlinks/foo/link2.h rename to test cases/common/268 install functions and follow_symlinks/foo/link2.h diff --git a/test cases/common/266 install functions and follow_symlinks/meson.build b/test cases/common/268 install functions and follow_symlinks/meson.build similarity index 100% rename from test cases/common/266 install functions and follow_symlinks/meson.build rename to test cases/common/268 install functions and follow_symlinks/meson.build diff --git a/test cases/common/266 install functions and follow_symlinks/test.json b/test cases/common/268 install functions and follow_symlinks/test.json similarity index 100% rename from test cases/common/266 install functions and follow_symlinks/test.json rename to test cases/common/268 install functions and follow_symlinks/test.json diff --git a/test cases/common/272 env in generator.process/generate_main.py b/test cases/common/271 env in generator.process/generate_main.py similarity index 100% rename from test cases/common/272 env in generator.process/generate_main.py rename to test cases/common/271 env in generator.process/generate_main.py diff --git a/test cases/common/272 env in generator.process/main.template b/test cases/common/271 env in generator.process/main.template similarity index 100% rename from test cases/common/272 env in generator.process/main.template rename to test cases/common/271 env in generator.process/main.template diff --git a/test cases/common/272 env in generator.process/meson.build b/test cases/common/271 env in generator.process/meson.build similarity index 100% rename from test cases/common/272 env in generator.process/meson.build rename to test cases/common/271 env in generator.process/meson.build diff --git a/test cases/failing/102 bool in combo/meson.build b/test cases/failing/100 bool in combo/meson.build similarity index 100% rename from test cases/failing/102 bool in combo/meson.build rename to test cases/failing/100 bool in combo/meson.build diff --git a/test cases/failing/102 bool in combo/meson_options.txt b/test cases/failing/100 bool in combo/meson_options.txt similarity index 100% rename from test cases/failing/102 bool in combo/meson_options.txt rename to test cases/failing/100 bool in combo/meson_options.txt diff --git a/test cases/failing/102 bool in combo/nativefile.ini b/test cases/failing/100 bool in combo/nativefile.ini similarity index 100% rename from test cases/failing/102 bool in combo/nativefile.ini rename to test cases/failing/100 bool in combo/nativefile.ini diff --git a/test cases/failing/102 bool in combo/test.json b/test cases/failing/100 bool in combo/test.json similarity index 73% rename from test cases/failing/102 bool in combo/test.json rename to test cases/failing/100 bool in combo/test.json index c0041afec402..357d7a875534 100644 --- a/test cases/failing/102 bool in combo/test.json +++ b/test cases/failing/100 bool in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/102 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + { "line": "test cases/failing/100 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } ] } diff --git a/test cases/failing/100 no glib-compile-resources/test.json b/test cases/failing/100 no glib-compile-resources/test.json deleted file mode 100644 index b9f5fdcf8d37..000000000000 --- a/test cases/failing/100 no glib-compile-resources/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/100 no glib-compile-resources/meson.build:8:12: ERROR: Program 'glib-compile-resources' not found or not executable" - } - ] -} diff --git a/test cases/failing/103 compiler no lang/meson.build b/test cases/failing/101 compiler no lang/meson.build similarity index 100% rename from test cases/failing/103 compiler no lang/meson.build rename to test cases/failing/101 compiler no lang/meson.build diff --git a/test cases/failing/103 compiler no lang/test.json b/test cases/failing/101 compiler no lang/test.json similarity index 66% rename from test cases/failing/103 compiler no lang/test.json rename to test cases/failing/101 compiler no lang/test.json index 123dcb9c38f3..364efa9e8912 100644 --- a/test cases/failing/103 compiler no lang/test.json +++ b/test cases/failing/101 compiler no lang/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/103 compiler no lang/meson.build:2:6: ERROR: Tried to access compiler for language \"c\", not specified for host machine." + "line": "test cases/failing/101 compiler no lang/meson.build:2:6: ERROR: Tried to access compiler for language \"c\", not specified for host machine." } ] } diff --git a/test cases/failing/101 number in combo/test.json b/test cases/failing/101 number in combo/test.json deleted file mode 100644 index 4c30f98002ed..000000000000 --- a/test cases/failing/101 number in combo/test.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "stdout": [ - { "line": "test cases/failing/101 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } - ] -} diff --git a/test cases/failing/104 no fallback/meson.build b/test cases/failing/102 no fallback/meson.build similarity index 100% rename from test cases/failing/104 no fallback/meson.build rename to test cases/failing/102 no fallback/meson.build diff --git a/test cases/failing/104 no fallback/subprojects/foob/meson.build b/test cases/failing/102 no fallback/subprojects/foob/meson.build similarity index 100% rename from test cases/failing/104 no fallback/subprojects/foob/meson.build rename to test cases/failing/102 no fallback/subprojects/foob/meson.build diff --git a/test cases/failing/104 no fallback/test.json b/test cases/failing/102 no fallback/test.json similarity index 100% rename from test cases/failing/104 no fallback/test.json rename to test cases/failing/102 no fallback/test.json diff --git a/test cases/failing/105 feature require/meson.build b/test cases/failing/103 feature require/meson.build similarity index 100% rename from test cases/failing/105 feature require/meson.build rename to test cases/failing/103 feature require/meson.build diff --git a/test cases/failing/105 feature require/meson_options.txt b/test cases/failing/103 feature require/meson_options.txt similarity index 100% rename from test cases/failing/105 feature require/meson_options.txt rename to test cases/failing/103 feature require/meson_options.txt diff --git a/test cases/failing/105 feature require/test.json b/test cases/failing/103 feature require/test.json similarity index 100% rename from test cases/failing/105 feature require/test.json rename to test cases/failing/103 feature require/test.json diff --git a/test cases/failing/106 feature require.bis/meson.build b/test cases/failing/104 feature require.bis/meson.build similarity index 100% rename from test cases/failing/106 feature require.bis/meson.build rename to test cases/failing/104 feature require.bis/meson.build diff --git a/test cases/failing/106 feature require.bis/meson_options.txt b/test cases/failing/104 feature require.bis/meson_options.txt similarity index 100% rename from test cases/failing/106 feature require.bis/meson_options.txt rename to test cases/failing/104 feature require.bis/meson_options.txt diff --git a/test cases/failing/106 feature require.bis/test.json b/test cases/failing/104 feature require.bis/test.json similarity index 100% rename from test cases/failing/106 feature require.bis/test.json rename to test cases/failing/104 feature require.bis/test.json diff --git a/test cases/failing/107 no build get_external_property/meson.build b/test cases/failing/105 no build get_external_property/meson.build similarity index 100% rename from test cases/failing/107 no build get_external_property/meson.build rename to test cases/failing/105 no build get_external_property/meson.build diff --git a/test cases/failing/107 no build get_external_property/test.json b/test cases/failing/105 no build get_external_property/test.json similarity index 63% rename from test cases/failing/107 no build get_external_property/test.json rename to test cases/failing/105 no build get_external_property/test.json index ff7438669838..e8b282c6fd9f 100644 --- a/test cases/failing/107 no build get_external_property/test.json +++ b/test cases/failing/105 no build get_external_property/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/107 no build get_external_property/meson.build:3:14: ERROR: Unknown property for build machine: nonexisting" + "line": "test cases/failing/105 no build get_external_property/meson.build:3:14: ERROR: Unknown property for build machine: nonexisting" } ] } diff --git a/test cases/failing/108 enter subdir twice/meson.build b/test cases/failing/106 enter subdir twice/meson.build similarity index 100% rename from test cases/failing/108 enter subdir twice/meson.build rename to test cases/failing/106 enter subdir twice/meson.build diff --git a/test cases/failing/108 enter subdir twice/sub/meson.build b/test cases/failing/106 enter subdir twice/sub/meson.build similarity index 100% rename from test cases/failing/108 enter subdir twice/sub/meson.build rename to test cases/failing/106 enter subdir twice/sub/meson.build diff --git a/test cases/failing/108 enter subdir twice/test.json b/test cases/failing/106 enter subdir twice/test.json similarity index 64% rename from test cases/failing/108 enter subdir twice/test.json rename to test cases/failing/106 enter subdir twice/test.json index 0a8e127692eb..9a8b11d060ed 100644 --- a/test cases/failing/108 enter subdir twice/test.json +++ b/test cases/failing/106 enter subdir twice/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/108 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited." + "line": "test cases/failing/106 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited." } ] } diff --git a/test cases/failing/109 invalid fstring/109 invalid fstring/meson.build b/test cases/failing/107 invalid fstring/109 invalid fstring/meson.build similarity index 100% rename from test cases/failing/109 invalid fstring/109 invalid fstring/meson.build rename to test cases/failing/107 invalid fstring/109 invalid fstring/meson.build diff --git a/test cases/failing/109 invalid fstring/109 invalid fstring/test.json b/test cases/failing/107 invalid fstring/109 invalid fstring/test.json similarity index 100% rename from test cases/failing/109 invalid fstring/109 invalid fstring/test.json rename to test cases/failing/107 invalid fstring/109 invalid fstring/test.json diff --git a/test cases/failing/109 invalid fstring/meson.build b/test cases/failing/107 invalid fstring/meson.build similarity index 100% rename from test cases/failing/109 invalid fstring/meson.build rename to test cases/failing/107 invalid fstring/meson.build diff --git a/test cases/failing/109 invalid fstring/test.json b/test cases/failing/107 invalid fstring/test.json similarity index 63% rename from test cases/failing/109 invalid fstring/test.json rename to test cases/failing/107 invalid fstring/test.json index 580d087211c6..ccd82b574c32 100644 --- a/test cases/failing/109 invalid fstring/test.json +++ b/test cases/failing/107 invalid fstring/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/109 invalid fstring/meson.build:3:4: ERROR: Identifier \"foo\" does not name a variable." + "line": "test cases/failing/107 invalid fstring/meson.build:3:4: ERROR: Identifier \"foo\" does not name a variable." } ] } diff --git a/test cases/failing/110 compiler argument checking/meson.build b/test cases/failing/108 compiler argument checking/meson.build similarity index 100% rename from test cases/failing/110 compiler argument checking/meson.build rename to test cases/failing/108 compiler argument checking/meson.build diff --git a/test cases/failing/110 compiler argument checking/test.json b/test cases/failing/108 compiler argument checking/test.json similarity index 66% rename from test cases/failing/110 compiler argument checking/test.json rename to test cases/failing/108 compiler argument checking/test.json index f60c014cea12..e9e27af574fe 100644 --- a/test cases/failing/110 compiler argument checking/test.json +++ b/test cases/failing/108 compiler argument checking/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/110 compiler argument checking/meson.build:4:25: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" + "line": "test cases/failing/108 compiler argument checking/meson.build:4:25: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" } ] } diff --git a/test cases/failing/111 empty fallback/meson.build b/test cases/failing/109 empty fallback/meson.build similarity index 100% rename from test cases/failing/111 empty fallback/meson.build rename to test cases/failing/109 empty fallback/meson.build diff --git a/test cases/failing/111 empty fallback/subprojects/foo/meson.build b/test cases/failing/109 empty fallback/subprojects/foo/meson.build similarity index 100% rename from test cases/failing/111 empty fallback/subprojects/foo/meson.build rename to test cases/failing/109 empty fallback/subprojects/foo/meson.build diff --git a/test cases/failing/111 empty fallback/test.json b/test cases/failing/109 empty fallback/test.json similarity index 65% rename from test cases/failing/111 empty fallback/test.json rename to test cases/failing/109 empty fallback/test.json index 022e747ff107..46a4ec51495d 100644 --- a/test cases/failing/111 empty fallback/test.json +++ b/test cases/failing/109 empty fallback/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/111 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found.*" + "line": "test cases/failing/109 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found.*" } ] } diff --git a/test cases/failing/112 cmake executable dependency/meson.build b/test cases/failing/110 cmake executable dependency/meson.build similarity index 100% rename from test cases/failing/112 cmake executable dependency/meson.build rename to test cases/failing/110 cmake executable dependency/meson.build diff --git a/test cases/failing/112 cmake executable dependency/subprojects/cmlib/CMakeLists.txt b/test cases/failing/110 cmake executable dependency/subprojects/cmlib/CMakeLists.txt similarity index 100% rename from test cases/failing/112 cmake executable dependency/subprojects/cmlib/CMakeLists.txt rename to test cases/failing/110 cmake executable dependency/subprojects/cmlib/CMakeLists.txt diff --git a/test cases/failing/112 cmake executable dependency/subprojects/cmlib/main.c b/test cases/failing/110 cmake executable dependency/subprojects/cmlib/main.c similarity index 100% rename from test cases/failing/112 cmake executable dependency/subprojects/cmlib/main.c rename to test cases/failing/110 cmake executable dependency/subprojects/cmlib/main.c diff --git a/test cases/failing/112 cmake executable dependency/test.json b/test cases/failing/110 cmake executable dependency/test.json similarity index 77% rename from test cases/failing/112 cmake executable dependency/test.json rename to test cases/failing/110 cmake executable dependency/test.json index d425fa292340..80d01fe0d3ec 100644 --- a/test cases/failing/112 cmake executable dependency/test.json +++ b/test cases/failing/110 cmake executable dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/112 cmake executable dependency/meson.build:9:14: ERROR: main is an executable and does not support the dependency() method. Use target() instead." + "line": "test cases/failing/110 cmake executable dependency/meson.build:9:14: ERROR: main is an executable and does not support the dependency() method. Use target() instead." } ], "tools": { diff --git a/test cases/failing/113 allow_fallback with fallback/meson.build b/test cases/failing/111 allow_fallback with fallback/meson.build similarity index 100% rename from test cases/failing/113 allow_fallback with fallback/meson.build rename to test cases/failing/111 allow_fallback with fallback/meson.build diff --git a/test cases/failing/113 allow_fallback with fallback/test.json b/test cases/failing/111 allow_fallback with fallback/test.json similarity index 70% rename from test cases/failing/113 allow_fallback with fallback/test.json rename to test cases/failing/111 allow_fallback with fallback/test.json index 58ed475c06ff..92aa19af306c 100644 --- a/test cases/failing/113 allow_fallback with fallback/test.json +++ b/test cases/failing/111 allow_fallback with fallback/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/113 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive" + "line": "test cases/failing/111 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive" } ] } diff --git a/test cases/failing/114 nonsensical bindgen/meson.build b/test cases/failing/112 nonsensical bindgen/meson.build similarity index 100% rename from test cases/failing/114 nonsensical bindgen/meson.build rename to test cases/failing/112 nonsensical bindgen/meson.build diff --git a/test cases/failing/114 nonsensical bindgen/src/header.h b/test cases/failing/112 nonsensical bindgen/src/header.h similarity index 100% rename from test cases/failing/114 nonsensical bindgen/src/header.h rename to test cases/failing/112 nonsensical bindgen/src/header.h diff --git a/test cases/failing/114 nonsensical bindgen/src/source.c b/test cases/failing/112 nonsensical bindgen/src/source.c similarity index 100% rename from test cases/failing/114 nonsensical bindgen/src/source.c rename to test cases/failing/112 nonsensical bindgen/src/source.c diff --git a/test cases/failing/114 nonsensical bindgen/test.json b/test cases/failing/112 nonsensical bindgen/test.json similarity index 69% rename from test cases/failing/114 nonsensical bindgen/test.json rename to test cases/failing/112 nonsensical bindgen/test.json index bc85311ab3c2..a2b4b719602d 100644 --- a/test cases/failing/114 nonsensical bindgen/test.json +++ b/test cases/failing/112 nonsensical bindgen/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/114 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target" + "line": "test cases/failing/112 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target" } ] } diff --git a/test cases/failing/115 run_target in test/meson.build b/test cases/failing/113 run_target in test/meson.build similarity index 100% rename from test cases/failing/115 run_target in test/meson.build rename to test cases/failing/113 run_target in test/meson.build diff --git a/test cases/failing/115 run_target in test/test.json b/test cases/failing/113 run_target in test/test.json similarity index 77% rename from test cases/failing/115 run_target in test/test.json rename to test cases/failing/113 run_target in test/test.json index 6eddb7c6894c..0e1ded4ea354 100644 --- a/test cases/failing/115 run_target in test/test.json +++ b/test cases/failing/113 run_target in test/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/115 run_target in test/meson.build:7:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]" + "line": "test cases/failing/113 run_target in test/meson.build:7:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]" } ] } diff --git a/test cases/failing/115 run_target in test/trivial.c b/test cases/failing/113 run_target in test/trivial.c similarity index 100% rename from test cases/failing/115 run_target in test/trivial.c rename to test cases/failing/113 run_target in test/trivial.c diff --git a/test cases/failing/116 run_target in add_install_script/meson.build b/test cases/failing/114 run_target in add_install_script/meson.build similarity index 100% rename from test cases/failing/116 run_target in add_install_script/meson.build rename to test cases/failing/114 run_target in add_install_script/meson.build diff --git a/test cases/failing/116 run_target in add_install_script/test.json b/test cases/failing/114 run_target in add_install_script/test.json similarity index 81% rename from test cases/failing/116 run_target in add_install_script/test.json rename to test cases/failing/114 run_target in add_install_script/test.json index 03027e4487b1..0b28f9b15ff1 100644 --- a/test cases/failing/116 run_target in add_install_script/test.json +++ b/test cases/failing/114 run_target in add_install_script/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/116 run_target in add_install_script/meson.build:7:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\"" + "line": "test cases/failing/114 run_target in add_install_script/meson.build:7:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\"" } ] } diff --git a/test cases/failing/116 run_target in add_install_script/trivial.c b/test cases/failing/114 run_target in add_install_script/trivial.c similarity index 100% rename from test cases/failing/116 run_target in add_install_script/trivial.c rename to test cases/failing/114 run_target in add_install_script/trivial.c diff --git a/test cases/failing/117 pathsep in install_symlink/meson.build b/test cases/failing/115 pathsep in install_symlink/meson.build similarity index 100% rename from test cases/failing/117 pathsep in install_symlink/meson.build rename to test cases/failing/115 pathsep in install_symlink/meson.build diff --git a/test cases/failing/117 pathsep in install_symlink/test.json b/test cases/failing/115 pathsep in install_symlink/test.json similarity index 74% rename from test cases/failing/117 pathsep in install_symlink/test.json rename to test cases/failing/115 pathsep in install_symlink/test.json index aa356194af3c..fee661f4ed63 100644 --- a/test cases/failing/117 pathsep in install_symlink/test.json +++ b/test cases/failing/115 pathsep in install_symlink/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/117 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir." + "line": "test cases/failing/115 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir." } ] } diff --git a/test cases/failing/118 subproject version conflict/meson.build b/test cases/failing/116 subproject version conflict/meson.build similarity index 100% rename from test cases/failing/118 subproject version conflict/meson.build rename to test cases/failing/116 subproject version conflict/meson.build diff --git a/test cases/failing/118 subproject version conflict/subprojects/A/meson.build b/test cases/failing/116 subproject version conflict/subprojects/A/meson.build similarity index 100% rename from test cases/failing/118 subproject version conflict/subprojects/A/meson.build rename to test cases/failing/116 subproject version conflict/subprojects/A/meson.build diff --git a/test cases/failing/118 subproject version conflict/subprojects/B/meson.build b/test cases/failing/116 subproject version conflict/subprojects/B/meson.build similarity index 100% rename from test cases/failing/118 subproject version conflict/subprojects/B/meson.build rename to test cases/failing/116 subproject version conflict/subprojects/B/meson.build diff --git a/test cases/failing/118 subproject version conflict/test.json b/test cases/failing/116 subproject version conflict/test.json similarity index 66% rename from test cases/failing/118 subproject version conflict/test.json rename to test cases/failing/116 subproject version conflict/test.json index 81ef85580e36..c827744968f8 100644 --- a/test cases/failing/118 subproject version conflict/test.json +++ b/test cases/failing/116 subproject version conflict/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/118 subproject version conflict/meson.build:4:8: ERROR: Subproject B version is 100 but ['1'] required." + "line": "test cases/failing/116 subproject version conflict/meson.build:4:8: ERROR: Subproject B version is 100 but ['1'] required." } ] } diff --git a/test cases/failing/119 structured source empty string/main.rs b/test cases/failing/117 structured source empty string/main.rs similarity index 100% rename from test cases/failing/119 structured source empty string/main.rs rename to test cases/failing/117 structured source empty string/main.rs diff --git a/test cases/failing/119 structured source empty string/meson.build b/test cases/failing/117 structured source empty string/meson.build similarity index 100% rename from test cases/failing/119 structured source empty string/meson.build rename to test cases/failing/117 structured source empty string/meson.build diff --git a/test cases/failing/119 structured source empty string/test.json b/test cases/failing/117 structured source empty string/test.json similarity index 71% rename from test cases/failing/119 structured source empty string/test.json rename to test cases/failing/117 structured source empty string/test.json index d1d463e1a621..7c90b0325355 100644 --- a/test cases/failing/119 structured source empty string/test.json +++ b/test cases/failing/117 structured source empty string/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/119 structured source empty string/meson.build:9:2: ERROR: structured_sources: keys to dictionary argument may not be an empty string." + "line": "test cases/failing/117 structured source empty string/meson.build:9:2: ERROR: structured_sources: keys to dictionary argument may not be an empty string." } ] } diff --git a/test cases/failing/120 structured_sources conflicts/main.rs b/test cases/failing/118 structured_sources conflicts/main.rs similarity index 100% rename from test cases/failing/120 structured_sources conflicts/main.rs rename to test cases/failing/118 structured_sources conflicts/main.rs diff --git a/test cases/failing/120 structured_sources conflicts/meson.build b/test cases/failing/118 structured_sources conflicts/meson.build similarity index 100% rename from test cases/failing/120 structured_sources conflicts/meson.build rename to test cases/failing/118 structured_sources conflicts/meson.build diff --git a/test cases/failing/120 structured_sources conflicts/test.json b/test cases/failing/118 structured_sources conflicts/test.json similarity index 67% rename from test cases/failing/120 structured_sources conflicts/test.json rename to test cases/failing/118 structured_sources conflicts/test.json index 2f3d1ef0d4ed..55b1228906e1 100644 --- a/test cases/failing/120 structured_sources conflicts/test.json +++ b/test cases/failing/118 structured_sources conflicts/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/120 structured_sources conflicts/meson.build:7:0: ERROR: Conflicting sources in structured sources: main.rs" + "line": "test cases/failing/118 structured_sources conflicts/meson.build:7:0: ERROR: Conflicting sources in structured sources: main.rs" } ] } diff --git a/test cases/failing/121 missing compiler/meson.build b/test cases/failing/119 missing compiler/meson.build similarity index 100% rename from test cases/failing/121 missing compiler/meson.build rename to test cases/failing/119 missing compiler/meson.build diff --git a/test cases/failing/121 missing compiler/subprojects/sub/main.c b/test cases/failing/119 missing compiler/subprojects/sub/main.c similarity index 100% rename from test cases/failing/121 missing compiler/subprojects/sub/main.c rename to test cases/failing/119 missing compiler/subprojects/sub/main.c diff --git a/test cases/failing/121 missing compiler/subprojects/sub/meson.build b/test cases/failing/119 missing compiler/subprojects/sub/meson.build similarity index 100% rename from test cases/failing/121 missing compiler/subprojects/sub/meson.build rename to test cases/failing/119 missing compiler/subprojects/sub/meson.build diff --git a/test cases/failing/121 missing compiler/test.json b/test cases/failing/119 missing compiler/test.json similarity index 68% rename from test cases/failing/121 missing compiler/test.json rename to test cases/failing/119 missing compiler/test.json index 442e3312d19b..c5f3fb1caaee 100644 --- a/test cases/failing/121 missing compiler/test.json +++ b/test cases/failing/119 missing compiler/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/121 missing compiler/subprojects/sub/meson.build:4:0: ERROR: No host machine compiler for 'subprojects/sub/main.c'" + "line": "test cases/failing/119 missing compiler/subprojects/sub/meson.build:4:0: ERROR: No host machine compiler for 'subprojects/sub/main.c'" } ] } diff --git a/test cases/failing/122 cmake subproject error/meson.build b/test cases/failing/120 cmake subproject error/meson.build similarity index 100% rename from test cases/failing/122 cmake subproject error/meson.build rename to test cases/failing/120 cmake subproject error/meson.build diff --git a/test cases/failing/122 cmake subproject error/subprojects/cmlib/CMakeLists.txt b/test cases/failing/120 cmake subproject error/subprojects/cmlib/CMakeLists.txt similarity index 100% rename from test cases/failing/122 cmake subproject error/subprojects/cmlib/CMakeLists.txt rename to test cases/failing/120 cmake subproject error/subprojects/cmlib/CMakeLists.txt diff --git a/test cases/failing/122 cmake subproject error/test.json b/test cases/failing/120 cmake subproject error/test.json similarity index 74% rename from test cases/failing/122 cmake subproject error/test.json rename to test cases/failing/120 cmake subproject error/test.json index 57430ebd2f09..d88e708bfd35 100644 --- a/test cases/failing/122 cmake subproject error/test.json +++ b/test cases/failing/120 cmake subproject error/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/122 cmake subproject error/meson.build:8:14: ERROR: Failed to configure the CMake subproject: Fancy error message" + "line": "test cases/failing/120 cmake subproject error/meson.build:8:14: ERROR: Failed to configure the CMake subproject: Fancy error message" } ], "tools": { diff --git a/test cases/failing/123 pkgconfig not relocatable outside prefix/meson.build b/test cases/failing/121 pkgconfig not relocatable outside prefix/meson.build similarity index 100% rename from test cases/failing/123 pkgconfig not relocatable outside prefix/meson.build rename to test cases/failing/121 pkgconfig not relocatable outside prefix/meson.build diff --git a/test cases/failing/123 pkgconfig not relocatable outside prefix/test.json b/test cases/failing/121 pkgconfig not relocatable outside prefix/test.json similarity index 78% rename from test cases/failing/123 pkgconfig not relocatable outside prefix/test.json rename to test cases/failing/121 pkgconfig not relocatable outside prefix/test.json index 2ca1320d6453..c0dfb87e2354 100644 --- a/test cases/failing/123 pkgconfig not relocatable outside prefix/test.json +++ b/test cases/failing/121 pkgconfig not relocatable outside prefix/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/123 pkgconfig not relocatable outside prefix/meson\\.build:17:5: ERROR: Pkgconfig prefix cannot be outside of the prefix when pkgconfig\\.relocatable=true. Pkgconfig prefix is (C:)?/opt/lib/pkgconfig.", + "line": "test cases/failing/121 pkgconfig not relocatable outside prefix/meson\\.build:17:5: ERROR: Pkgconfig prefix cannot be outside of the prefix when pkgconfig\\.relocatable=true. Pkgconfig prefix is (C:)?/opt/lib/pkgconfig.", "match": "re" } ] diff --git a/test cases/failing/124 subproject sandbox violation/meson.build b/test cases/failing/122 subproject sandbox violation/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/meson.build rename to test cases/failing/122 subproject sandbox violation/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/meson_options.txt b/test cases/failing/122 subproject sandbox violation/meson_options.txt similarity index 100% rename from test cases/failing/124 subproject sandbox violation/meson_options.txt rename to test cases/failing/122 subproject sandbox violation/meson_options.txt diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj1/file.txt b/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/file.txt similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj1/file.txt rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj1/file.txt diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj1/meson.build b/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj1/meson.build rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj1/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj1/nested/meson.build b/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/nested/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj1/nested/meson.build rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj1/nested/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj2/file.txt b/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/file.txt similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj2/file.txt rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj2/file.txt diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj2/meson.build b/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj2/meson.build rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj2/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj2/nested/meson.build b/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/nested/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj2/nested/meson.build rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj2/nested/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj3/file.txt b/test cases/failing/122 subproject sandbox violation/subprojects/subproj3/file.txt similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj3/file.txt rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj3/file.txt diff --git a/test cases/failing/124 subproject sandbox violation/subprojects/subproj3/meson.build b/test cases/failing/122 subproject sandbox violation/subprojects/subproj3/meson.build similarity index 100% rename from test cases/failing/124 subproject sandbox violation/subprojects/subproj3/meson.build rename to test cases/failing/122 subproject sandbox violation/subprojects/subproj3/meson.build diff --git a/test cases/failing/124 subproject sandbox violation/test.json b/test cases/failing/122 subproject sandbox violation/test.json similarity index 82% rename from test cases/failing/124 subproject sandbox violation/test.json rename to test cases/failing/122 subproject sandbox violation/test.json index ca3d142ec003..4bd40288403a 100644 --- a/test cases/failing/124 subproject sandbox violation/test.json +++ b/test cases/failing/122 subproject sandbox violation/test.json @@ -10,7 +10,7 @@ }, "stdout": [ { - "line": "test cases/failing/124 subproject sandbox violation/meson.build:24:0: ERROR: Sandbox violation: Tried to grab file file.txt from a nested subproject." + "line": "test cases/failing/122 subproject sandbox violation/meson.build:24:0: ERROR: Sandbox violation: Tried to grab file file.txt from a nested subproject." } ] } diff --git a/test cases/failing/125 override and add_project_dependency/inc/lib.h b/test cases/failing/123 override and add_project_dependency/inc/lib.h similarity index 100% rename from test cases/failing/125 override and add_project_dependency/inc/lib.h rename to test cases/failing/123 override and add_project_dependency/inc/lib.h diff --git a/test cases/failing/125 override and add_project_dependency/lib.c b/test cases/failing/123 override and add_project_dependency/lib.c similarity index 100% rename from test cases/failing/125 override and add_project_dependency/lib.c rename to test cases/failing/123 override and add_project_dependency/lib.c diff --git a/test cases/failing/125 override and add_project_dependency/meson.build b/test cases/failing/123 override and add_project_dependency/meson.build similarity index 100% rename from test cases/failing/125 override and add_project_dependency/meson.build rename to test cases/failing/123 override and add_project_dependency/meson.build diff --git a/test cases/failing/125 override and add_project_dependency/subprojects/a/meson.build b/test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build similarity index 100% rename from test cases/failing/125 override and add_project_dependency/subprojects/a/meson.build rename to test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build diff --git a/test cases/failing/125 override and add_project_dependency/subprojects/a/prog.c b/test cases/failing/123 override and add_project_dependency/subprojects/a/prog.c similarity index 100% rename from test cases/failing/125 override and add_project_dependency/subprojects/a/prog.c rename to test cases/failing/123 override and add_project_dependency/subprojects/a/prog.c diff --git a/test cases/failing/125 override and add_project_dependency/test.json b/test cases/failing/123 override and add_project_dependency/test.json similarity index 66% rename from test cases/failing/125 override and add_project_dependency/test.json rename to test cases/failing/123 override and add_project_dependency/test.json index df749ec7ed4b..e0a4433cb172 100644 --- a/test cases/failing/125 override and add_project_dependency/test.json +++ b/test cases/failing/123 override and add_project_dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/125 override and add_project_dependency/subprojects/a/meson.build:6:0: ERROR: Dependencies must be external dependencies" + "line": "test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build:6:0: ERROR: Dependencies must be external dependencies" } ] } diff --git a/test cases/failing/126 targets before add_project_dependency/inc/lib.h b/test cases/failing/124 targets before add_project_dependency/inc/lib.h similarity index 100% rename from test cases/failing/126 targets before add_project_dependency/inc/lib.h rename to test cases/failing/124 targets before add_project_dependency/inc/lib.h diff --git a/test cases/failing/126 targets before add_project_dependency/lib.c b/test cases/failing/124 targets before add_project_dependency/lib.c similarity index 100% rename from test cases/failing/126 targets before add_project_dependency/lib.c rename to test cases/failing/124 targets before add_project_dependency/lib.c diff --git a/test cases/failing/126 targets before add_project_dependency/meson.build b/test cases/failing/124 targets before add_project_dependency/meson.build similarity index 100% rename from test cases/failing/126 targets before add_project_dependency/meson.build rename to test cases/failing/124 targets before add_project_dependency/meson.build diff --git a/test cases/failing/126 targets before add_project_dependency/test.json b/test cases/failing/124 targets before add_project_dependency/test.json similarity index 70% rename from test cases/failing/126 targets before add_project_dependency/test.json rename to test cases/failing/124 targets before add_project_dependency/test.json index d467914ccf97..d856ba4fdab2 100644 --- a/test cases/failing/126 targets before add_project_dependency/test.json +++ b/test cases/failing/124 targets before add_project_dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/126 targets before add_project_dependency/meson.build:5:0: ERROR: Tried to use 'add_project_dependencies' after a build target has been declared." + "line": "test cases/failing/124 targets before add_project_dependency/meson.build:5:0: ERROR: Tried to use 'add_project_dependencies' after a build target has been declared." } ] } diff --git a/test cases/failing/127 extract from unity/meson.build b/test cases/failing/125 extract from unity/meson.build similarity index 100% rename from test cases/failing/127 extract from unity/meson.build rename to test cases/failing/125 extract from unity/meson.build diff --git a/test cases/failing/127 extract from unity/src1.c b/test cases/failing/125 extract from unity/src1.c similarity index 100% rename from test cases/failing/127 extract from unity/src1.c rename to test cases/failing/125 extract from unity/src1.c diff --git a/test cases/failing/127 extract from unity/src2.c b/test cases/failing/125 extract from unity/src2.c similarity index 100% rename from test cases/failing/127 extract from unity/src2.c rename to test cases/failing/125 extract from unity/src2.c diff --git a/test cases/failing/127 extract from unity/test.json b/test cases/failing/125 extract from unity/test.json similarity index 73% rename from test cases/failing/127 extract from unity/test.json rename to test cases/failing/125 extract from unity/test.json index 9403481f8b7f..2f6468d36493 100644 --- a/test cases/failing/127 extract from unity/test.json +++ b/test cases/failing/125 extract from unity/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/127 extract from unity/meson.build:4:37: ERROR: Single object files cannot be extracted in Unity builds. You can only extract all the object files for each compiler at once." + "line": "test cases/failing/125 extract from unity/meson.build:4:37: ERROR: Single object files cannot be extracted in Unity builds. You can only extract all the object files for each compiler at once." } ] } diff --git a/test cases/failing/128 subproject object as a dependency/main.c b/test cases/failing/126 subproject object as a dependency/main.c similarity index 100% rename from test cases/failing/128 subproject object as a dependency/main.c rename to test cases/failing/126 subproject object as a dependency/main.c diff --git a/test cases/failing/128 subproject object as a dependency/meson.build b/test cases/failing/126 subproject object as a dependency/meson.build similarity index 100% rename from test cases/failing/128 subproject object as a dependency/meson.build rename to test cases/failing/126 subproject object as a dependency/meson.build diff --git a/test cases/failing/128 subproject object as a dependency/subprojects/sub/meson.build b/test cases/failing/126 subproject object as a dependency/subprojects/sub/meson.build similarity index 100% rename from test cases/failing/128 subproject object as a dependency/subprojects/sub/meson.build rename to test cases/failing/126 subproject object as a dependency/subprojects/sub/meson.build diff --git a/test cases/failing/128 subproject object as a dependency/test.json b/test cases/failing/126 subproject object as a dependency/test.json similarity index 64% rename from test cases/failing/128 subproject object as a dependency/test.json rename to test cases/failing/126 subproject object as a dependency/test.json index b04bf3766cd2..4bf7f5b8bffe 100644 --- a/test cases/failing/128 subproject object as a dependency/test.json +++ b/test cases/failing/126 subproject object as a dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/128 subproject object as a dependency/meson.build:3:0: ERROR: Tried to use subproject object as a dependency." + "line": "test cases/failing/126 subproject object as a dependency/meson.build:3:0: ERROR: Tried to use subproject object as a dependency." } ] } diff --git a/test cases/failing/129 generator host binary/exe.c b/test cases/failing/127 generator host binary/exe.c similarity index 100% rename from test cases/failing/129 generator host binary/exe.c rename to test cases/failing/127 generator host binary/exe.c diff --git a/test cases/failing/129 generator host binary/lib.in b/test cases/failing/127 generator host binary/lib.in similarity index 100% rename from test cases/failing/129 generator host binary/lib.in rename to test cases/failing/127 generator host binary/lib.in diff --git a/test cases/failing/129 generator host binary/meson.build b/test cases/failing/127 generator host binary/meson.build similarity index 100% rename from test cases/failing/129 generator host binary/meson.build rename to test cases/failing/127 generator host binary/meson.build diff --git a/test cases/failing/129 generator host binary/test.json b/test cases/failing/127 generator host binary/test.json similarity index 100% rename from test cases/failing/129 generator host binary/test.json rename to test cases/failing/127 generator host binary/test.json diff --git a/test cases/failing/130 invalid ast/meson.build b/test cases/failing/128 invalid ast/meson.build similarity index 100% rename from test cases/failing/130 invalid ast/meson.build rename to test cases/failing/128 invalid ast/meson.build diff --git a/test cases/failing/130 invalid ast/test.json b/test cases/failing/128 invalid ast/test.json similarity index 67% rename from test cases/failing/130 invalid ast/test.json rename to test cases/failing/128 invalid ast/test.json index 285d078ad3c3..e5c3873dc5c1 100644 --- a/test cases/failing/130 invalid ast/test.json +++ b/test cases/failing/128 invalid ast/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/130 invalid ast/meson.build:1:44: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + "line": "test cases/failing/128 invalid ast/meson.build:1:44: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" } ] } diff --git a/test cases/failing/131 invalid project function/meson.build b/test cases/failing/129 invalid project function/meson.build similarity index 100% rename from test cases/failing/131 invalid project function/meson.build rename to test cases/failing/129 invalid project function/meson.build diff --git a/test cases/failing/131 invalid project function/test.json b/test cases/failing/129 invalid project function/test.json similarity index 69% rename from test cases/failing/131 invalid project function/test.json rename to test cases/failing/129 invalid project function/test.json index e6814c665e2d..b28266cb166e 100644 --- a/test cases/failing/131 invalid project function/test.json +++ b/test cases/failing/129 invalid project function/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/131 invalid project function/meson.build:1:67: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + "line": "test cases/failing/129 invalid project function/meson.build:1:67: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" } ] } diff --git a/test cases/failing/55 or on new line/meson.build b/test cases/failing/53 or on new line/meson.build similarity index 100% rename from test cases/failing/55 or on new line/meson.build rename to test cases/failing/53 or on new line/meson.build diff --git a/test cases/failing/55 or on new line/meson_options.txt b/test cases/failing/53 or on new line/meson_options.txt similarity index 100% rename from test cases/failing/55 or on new line/meson_options.txt rename to test cases/failing/53 or on new line/meson_options.txt diff --git a/test cases/failing/55 or on new line/test.json b/test cases/failing/53 or on new line/test.json similarity index 50% rename from test cases/failing/55 or on new line/test.json rename to test cases/failing/53 or on new line/test.json index f1b8a673cbe4..33900255503e 100644 --- a/test cases/failing/55 or on new line/test.json +++ b/test cases/failing/53 or on new line/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/55 or on new line/meson.build:4:8: ERROR: Invalid or clause." + "line": "test cases/failing/53 or on new line/meson.build:4:8: ERROR: Invalid or clause." } ] } diff --git a/test cases/failing/56 link with executable/meson.build b/test cases/failing/54 link with executable/meson.build similarity index 100% rename from test cases/failing/56 link with executable/meson.build rename to test cases/failing/54 link with executable/meson.build diff --git a/test cases/failing/56 link with executable/module.c b/test cases/failing/54 link with executable/module.c similarity index 100% rename from test cases/failing/56 link with executable/module.c rename to test cases/failing/54 link with executable/module.c diff --git a/test cases/failing/56 link with executable/prog.c b/test cases/failing/54 link with executable/prog.c similarity index 100% rename from test cases/failing/56 link with executable/prog.c rename to test cases/failing/54 link with executable/prog.c diff --git a/test cases/failing/56 link with executable/test.json b/test cases/failing/54 link with executable/test.json similarity index 58% rename from test cases/failing/56 link with executable/test.json rename to test cases/failing/54 link with executable/test.json index b137f4f29b02..2b51bdd5af9c 100644 --- a/test cases/failing/56 link with executable/test.json +++ b/test cases/failing/54 link with executable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/56 link with executable/meson.build:4:4: ERROR: Link target 'prog' is not linkable." + "line": "test cases/failing/54 link with executable/meson.build:4:4: ERROR: Link target 'prog' is not linkable." } ] } diff --git a/test cases/failing/57 assign custom target index/meson.build b/test cases/failing/55 assign custom target index/meson.build similarity index 100% rename from test cases/failing/57 assign custom target index/meson.build rename to test cases/failing/55 assign custom target index/meson.build diff --git a/test cases/failing/57 assign custom target index/test.json b/test cases/failing/55 assign custom target index/test.json similarity index 59% rename from test cases/failing/57 assign custom target index/test.json rename to test cases/failing/55 assign custom target index/test.json index 392137ac17ab..39983fb678cc 100644 --- a/test cases/failing/57 assign custom target index/test.json +++ b/test cases/failing/55 assign custom target index/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/57 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id." + "line": "test cases/failing/55 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id." } ] } diff --git a/test cases/failing/58 getoption prefix/meson.build b/test cases/failing/56 getoption prefix/meson.build similarity index 100% rename from test cases/failing/58 getoption prefix/meson.build rename to test cases/failing/56 getoption prefix/meson.build diff --git a/test cases/failing/58 getoption prefix/subprojects/abc/meson.build b/test cases/failing/56 getoption prefix/subprojects/abc/meson.build similarity index 100% rename from test cases/failing/58 getoption prefix/subprojects/abc/meson.build rename to test cases/failing/56 getoption prefix/subprojects/abc/meson.build diff --git a/test cases/failing/58 getoption prefix/subprojects/abc/meson_options.txt b/test cases/failing/56 getoption prefix/subprojects/abc/meson_options.txt similarity index 100% rename from test cases/failing/58 getoption prefix/subprojects/abc/meson_options.txt rename to test cases/failing/56 getoption prefix/subprojects/abc/meson_options.txt diff --git a/test cases/failing/58 getoption prefix/test.json b/test cases/failing/56 getoption prefix/test.json similarity index 72% rename from test cases/failing/58 getoption prefix/test.json rename to test cases/failing/56 getoption prefix/test.json index 630dcd99b572..c52dffc71c99 100644 --- a/test cases/failing/58 getoption prefix/test.json +++ b/test cases/failing/56 getoption prefix/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/58 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects." + "line": "test cases/failing/56 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects." } ] } diff --git a/test cases/failing/59 bad option argument/meson.build b/test cases/failing/57 bad option argument/meson.build similarity index 100% rename from test cases/failing/59 bad option argument/meson.build rename to test cases/failing/57 bad option argument/meson.build diff --git a/test cases/failing/59 bad option argument/meson_options.txt b/test cases/failing/57 bad option argument/meson_options.txt similarity index 100% rename from test cases/failing/59 bad option argument/meson_options.txt rename to test cases/failing/57 bad option argument/meson_options.txt diff --git a/test cases/failing/59 bad option argument/test.json b/test cases/failing/57 bad option argument/test.json similarity index 63% rename from test cases/failing/59 bad option argument/test.json rename to test cases/failing/57 bad option argument/test.json index 9d22a9a228fb..622acdffc186 100644 --- a/test cases/failing/59 bad option argument/test.json +++ b/test cases/failing/57 bad option argument/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/59 bad option argument/meson_options.txt:1:0: ERROR: string option got unknown keyword arguments \"value_\"" + "line": "test cases/failing/57 bad option argument/meson_options.txt:1:0: ERROR: string option got unknown keyword arguments \"value_\"" } ] } diff --git a/test cases/failing/60 subproj filegrab/meson.build b/test cases/failing/58 subproj filegrab/meson.build similarity index 100% rename from test cases/failing/60 subproj filegrab/meson.build rename to test cases/failing/58 subproj filegrab/meson.build diff --git a/test cases/failing/60 subproj filegrab/prog.c b/test cases/failing/58 subproj filegrab/prog.c similarity index 100% rename from test cases/failing/60 subproj filegrab/prog.c rename to test cases/failing/58 subproj filegrab/prog.c diff --git a/test cases/failing/60 subproj filegrab/subprojects/a/meson.build b/test cases/failing/58 subproj filegrab/subprojects/a/meson.build similarity index 100% rename from test cases/failing/60 subproj filegrab/subprojects/a/meson.build rename to test cases/failing/58 subproj filegrab/subprojects/a/meson.build diff --git a/test cases/failing/60 subproj filegrab/test.json b/test cases/failing/58 subproj filegrab/test.json similarity index 68% rename from test cases/failing/60 subproj filegrab/test.json rename to test cases/failing/58 subproj filegrab/test.json index 04a6dbbddb37..950e109c9d1d 100644 --- a/test cases/failing/60 subproj filegrab/test.json +++ b/test cases/failing/58 subproj filegrab/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/60 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project." + "line": "test cases/failing/58 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project." } ] } diff --git a/test cases/failing/61 grab subproj/meson.build b/test cases/failing/59 grab subproj/meson.build similarity index 100% rename from test cases/failing/61 grab subproj/meson.build rename to test cases/failing/59 grab subproj/meson.build diff --git a/test cases/failing/61 grab subproj/subprojects/foo/meson.build b/test cases/failing/59 grab subproj/subprojects/foo/meson.build similarity index 100% rename from test cases/failing/61 grab subproj/subprojects/foo/meson.build rename to test cases/failing/59 grab subproj/subprojects/foo/meson.build diff --git a/test cases/failing/61 grab subproj/subprojects/foo/sub.c b/test cases/failing/59 grab subproj/subprojects/foo/sub.c similarity index 100% rename from test cases/failing/61 grab subproj/subprojects/foo/sub.c rename to test cases/failing/59 grab subproj/subprojects/foo/sub.c diff --git a/test cases/failing/61 grab subproj/test.json b/test cases/failing/59 grab subproj/test.json similarity index 64% rename from test cases/failing/61 grab subproj/test.json rename to test cases/failing/59 grab subproj/test.json index 873ec6c06473..7c9020280b0b 100644 --- a/test cases/failing/61 grab subproj/test.json +++ b/test cases/failing/59 grab subproj/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/61 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject." + "line": "test cases/failing/59 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject." } ] } diff --git a/test cases/failing/62 grab sibling/meson.build b/test cases/failing/60 grab sibling/meson.build similarity index 100% rename from test cases/failing/62 grab sibling/meson.build rename to test cases/failing/60 grab sibling/meson.build diff --git a/test cases/failing/62 grab sibling/subprojects/a/meson.build b/test cases/failing/60 grab sibling/subprojects/a/meson.build similarity index 100% rename from test cases/failing/62 grab sibling/subprojects/a/meson.build rename to test cases/failing/60 grab sibling/subprojects/a/meson.build diff --git a/test cases/failing/62 grab sibling/subprojects/b/meson.build b/test cases/failing/60 grab sibling/subprojects/b/meson.build similarity index 100% rename from test cases/failing/62 grab sibling/subprojects/b/meson.build rename to test cases/failing/60 grab sibling/subprojects/b/meson.build diff --git a/test cases/failing/62 grab sibling/subprojects/b/sneaky.c b/test cases/failing/60 grab sibling/subprojects/b/sneaky.c similarity index 100% rename from test cases/failing/62 grab sibling/subprojects/b/sneaky.c rename to test cases/failing/60 grab sibling/subprojects/b/sneaky.c diff --git a/test cases/failing/62 grab sibling/test.json b/test cases/failing/60 grab sibling/test.json similarity index 68% rename from test cases/failing/62 grab sibling/test.json rename to test cases/failing/60 grab sibling/test.json index 9e7c4bbf1053..8f42badb3fb8 100644 --- a/test cases/failing/62 grab sibling/test.json +++ b/test cases/failing/60 grab sibling/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/62 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project." + "line": "test cases/failing/60 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project." } ] } diff --git a/test cases/failing/63 string as link target/meson.build b/test cases/failing/61 string as link target/meson.build similarity index 100% rename from test cases/failing/63 string as link target/meson.build rename to test cases/failing/61 string as link target/meson.build diff --git a/test cases/failing/63 string as link target/prog.c b/test cases/failing/61 string as link target/prog.c similarity index 100% rename from test cases/failing/63 string as link target/prog.c rename to test cases/failing/61 string as link target/prog.c diff --git a/test cases/failing/63 string as link target/test.json b/test cases/failing/61 string as link target/test.json similarity index 53% rename from test cases/failing/63 string as link target/test.json rename to test cases/failing/61 string as link target/test.json index a531d647e5e4..b7f6bd784b30 100644 --- a/test cases/failing/63 string as link target/test.json +++ b/test cases/failing/61 string as link target/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/63 string as link target/meson.build:2:0: ERROR: '' is not a target." + "line": "test cases/failing/61 string as link target/meson.build:2:0: ERROR: '' is not a target." } ] } diff --git a/test cases/failing/64 dependency not-found and required/meson.build b/test cases/failing/62 dependency not-found and required/meson.build similarity index 100% rename from test cases/failing/64 dependency not-found and required/meson.build rename to test cases/failing/62 dependency not-found and required/meson.build diff --git a/test cases/failing/64 dependency not-found and required/test.json b/test cases/failing/62 dependency not-found and required/test.json similarity index 63% rename from test cases/failing/64 dependency not-found and required/test.json rename to test cases/failing/62 dependency not-found and required/test.json index ceb521e49295..69a67ffbb52e 100644 --- a/test cases/failing/64 dependency not-found and required/test.json +++ b/test cases/failing/62 dependency not-found and required/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/64 dependency not-found and required/meson.build:2:6: ERROR: Dependency is required but has no candidates." + "line": "test cases/failing/62 dependency not-found and required/meson.build:2:6: ERROR: Dependency is required but has no candidates." } ] } diff --git a/test cases/failing/65 subproj different versions/main.c b/test cases/failing/63 subproj different versions/main.c similarity index 100% rename from test cases/failing/65 subproj different versions/main.c rename to test cases/failing/63 subproj different versions/main.c diff --git a/test cases/failing/65 subproj different versions/meson.build b/test cases/failing/63 subproj different versions/meson.build similarity index 100% rename from test cases/failing/65 subproj different versions/meson.build rename to test cases/failing/63 subproj different versions/meson.build diff --git a/test cases/failing/65 subproj different versions/subprojects/a/a.c b/test cases/failing/63 subproj different versions/subprojects/a/a.c similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/a/a.c rename to test cases/failing/63 subproj different versions/subprojects/a/a.c diff --git a/test cases/failing/65 subproj different versions/subprojects/a/a.h b/test cases/failing/63 subproj different versions/subprojects/a/a.h similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/a/a.h rename to test cases/failing/63 subproj different versions/subprojects/a/a.h diff --git a/test cases/failing/65 subproj different versions/subprojects/a/meson.build b/test cases/failing/63 subproj different versions/subprojects/a/meson.build similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/a/meson.build rename to test cases/failing/63 subproj different versions/subprojects/a/meson.build diff --git a/test cases/failing/65 subproj different versions/subprojects/b/b.c b/test cases/failing/63 subproj different versions/subprojects/b/b.c similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/b/b.c rename to test cases/failing/63 subproj different versions/subprojects/b/b.c diff --git a/test cases/failing/65 subproj different versions/subprojects/b/b.h b/test cases/failing/63 subproj different versions/subprojects/b/b.h similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/b/b.h rename to test cases/failing/63 subproj different versions/subprojects/b/b.h diff --git a/test cases/failing/65 subproj different versions/subprojects/b/meson.build b/test cases/failing/63 subproj different versions/subprojects/b/meson.build similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/b/meson.build rename to test cases/failing/63 subproj different versions/subprojects/b/meson.build diff --git a/test cases/failing/65 subproj different versions/subprojects/c/c.h b/test cases/failing/63 subproj different versions/subprojects/c/c.h similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/c/c.h rename to test cases/failing/63 subproj different versions/subprojects/c/c.h diff --git a/test cases/failing/65 subproj different versions/subprojects/c/meson.build b/test cases/failing/63 subproj different versions/subprojects/c/meson.build similarity index 100% rename from test cases/failing/65 subproj different versions/subprojects/c/meson.build rename to test cases/failing/63 subproj different versions/subprojects/c/meson.build diff --git a/test cases/failing/65 subproj different versions/test.json b/test cases/failing/63 subproj different versions/test.json similarity index 64% rename from test cases/failing/65 subproj different versions/test.json rename to test cases/failing/63 subproj different versions/test.json index d18a823d1555..f2535fafd587 100644 --- a/test cases/failing/65 subproj different versions/test.json +++ b/test cases/failing/63 subproj different versions/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/65 subproj different versions/subprojects/b/meson.build:3:8: ERROR: Dependency 'c' is required but not found." + "line": "test cases/failing/63 subproj different versions/subprojects/b/meson.build:3:8: ERROR: Dependency 'c' is required but not found." } ] } diff --git a/test cases/failing/66 wrong boost module/meson.build b/test cases/failing/64 wrong boost module/meson.build similarity index 100% rename from test cases/failing/66 wrong boost module/meson.build rename to test cases/failing/64 wrong boost module/meson.build diff --git a/test cases/failing/66 wrong boost module/test.json b/test cases/failing/64 wrong boost module/test.json similarity index 60% rename from test cases/failing/66 wrong boost module/test.json rename to test cases/failing/64 wrong boost module/test.json index 7d646d4b408d..78e206999120 100644 --- a/test cases/failing/66 wrong boost module/test.json +++ b/test cases/failing/64 wrong boost module/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/66 wrong boost module/meson.build:9:10: ERROR: Dependency \"boost\" not found, tried system" + "line": "test cases/failing/64 wrong boost module/meson.build:9:10: ERROR: Dependency \"boost\" not found, tried system" } ] } diff --git a/test cases/failing/67 install_data rename bad size/file1.txt b/test cases/failing/65 install_data rename bad size/file1.txt similarity index 100% rename from test cases/failing/67 install_data rename bad size/file1.txt rename to test cases/failing/65 install_data rename bad size/file1.txt diff --git a/test cases/failing/67 install_data rename bad size/file2.txt b/test cases/failing/65 install_data rename bad size/file2.txt similarity index 100% rename from test cases/failing/67 install_data rename bad size/file2.txt rename to test cases/failing/65 install_data rename bad size/file2.txt diff --git a/test cases/failing/67 install_data rename bad size/meson.build b/test cases/failing/65 install_data rename bad size/meson.build similarity index 100% rename from test cases/failing/67 install_data rename bad size/meson.build rename to test cases/failing/65 install_data rename bad size/meson.build diff --git a/test cases/failing/67 install_data rename bad size/test.json b/test cases/failing/65 install_data rename bad size/test.json similarity index 75% rename from test cases/failing/67 install_data rename bad size/test.json rename to test cases/failing/65 install_data rename bad size/test.json index af1f0d97734d..efc62907db4e 100644 --- a/test cases/failing/67 install_data rename bad size/test.json +++ b/test cases/failing/65 install_data rename bad size/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/67 install_data rename bad size/meson.build:3:0: ERROR: \"rename\" and \"sources\" argument lists must be the same length if \"rename\" is given. Rename has 1 elements and sources has 2." + "line": "test cases/failing/65 install_data rename bad size/meson.build:3:0: ERROR: \"rename\" and \"sources\" argument lists must be the same length if \"rename\" is given. Rename has 1 elements and sources has 2." } ] } diff --git a/test cases/failing/68 skip only subdir/meson.build b/test cases/failing/66 skip only subdir/meson.build similarity index 100% rename from test cases/failing/68 skip only subdir/meson.build rename to test cases/failing/66 skip only subdir/meson.build diff --git a/test cases/failing/68 skip only subdir/subdir/meson.build b/test cases/failing/66 skip only subdir/subdir/meson.build similarity index 100% rename from test cases/failing/68 skip only subdir/subdir/meson.build rename to test cases/failing/66 skip only subdir/subdir/meson.build diff --git a/test cases/failing/68 skip only subdir/test.json b/test cases/failing/66 skip only subdir/test.json similarity index 55% rename from test cases/failing/68 skip only subdir/test.json rename to test cases/failing/66 skip only subdir/test.json index 4558847dd4fe..de21e006c6fb 100644 --- a/test cases/failing/68 skip only subdir/test.json +++ b/test cases/failing/66 skip only subdir/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/68 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist." + "line": "test cases/failing/66 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist." } ] } diff --git a/test cases/failing/69 dual override/meson.build b/test cases/failing/67 dual override/meson.build similarity index 100% rename from test cases/failing/69 dual override/meson.build rename to test cases/failing/67 dual override/meson.build diff --git a/test cases/failing/69 dual override/overrides.py b/test cases/failing/67 dual override/overrides.py similarity index 100% rename from test cases/failing/69 dual override/overrides.py rename to test cases/failing/67 dual override/overrides.py diff --git a/test cases/failing/69 dual override/test.json b/test cases/failing/67 dual override/test.json similarity index 65% rename from test cases/failing/69 dual override/test.json rename to test cases/failing/67 dual override/test.json index 784d6b275cbc..b50f3aca8959 100644 --- a/test cases/failing/69 dual override/test.json +++ b/test cases/failing/67 dual override/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/69 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden." + "line": "test cases/failing/67 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden." } ] } diff --git a/test cases/failing/70 override used/meson.build b/test cases/failing/68 override used/meson.build similarity index 100% rename from test cases/failing/70 override used/meson.build rename to test cases/failing/68 override used/meson.build diff --git a/test cases/failing/70 override used/other.py b/test cases/failing/68 override used/other.py similarity index 100% rename from test cases/failing/70 override used/other.py rename to test cases/failing/68 override used/other.py diff --git a/test cases/failing/70 override used/something.py b/test cases/failing/68 override used/something.py similarity index 100% rename from test cases/failing/70 override used/something.py rename to test cases/failing/68 override used/something.py diff --git a/test cases/failing/70 override used/test.json b/test cases/failing/68 override used/test.json similarity index 67% rename from test cases/failing/70 override used/test.json rename to test cases/failing/68 override used/test.json index adb60aa92066..f11aac61983c 100644 --- a/test cases/failing/70 override used/test.json +++ b/test cases/failing/68 override used/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/70 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found." + "line": "test cases/failing/68 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found." } ] } diff --git a/test cases/failing/71 run_command unclean exit/meson.build b/test cases/failing/69 run_command unclean exit/meson.build similarity index 100% rename from test cases/failing/71 run_command unclean exit/meson.build rename to test cases/failing/69 run_command unclean exit/meson.build diff --git a/test cases/failing/71 run_command unclean exit/returncode.py b/test cases/failing/69 run_command unclean exit/returncode.py similarity index 100% rename from test cases/failing/71 run_command unclean exit/returncode.py rename to test cases/failing/69 run_command unclean exit/returncode.py diff --git a/test cases/failing/71 run_command unclean exit/test.json b/test cases/failing/69 run_command unclean exit/test.json similarity index 56% rename from test cases/failing/71 run_command unclean exit/test.json rename to test cases/failing/69 run_command unclean exit/test.json index ca5fcbad1a31..96c2141fc9fa 100644 --- a/test cases/failing/71 run_command unclean exit/test.json +++ b/test cases/failing/69 run_command unclean exit/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/71 run_command unclean exit/meson\\.build:4:0: ERROR: Command `.*['\"].*[\\\\/]test cases[\\\\/]failing[\\\\/]71 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py['\"] 1` failed with status 1\\." + "line": "test cases/failing/69 run_command unclean exit/meson\\.build:4:0: ERROR: Command `.*['\"].*[\\\\/]test cases[\\\\/]failing[\\\\/]69 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py['\"] 1` failed with status 1\\." } ] } diff --git a/test cases/failing/72 int literal leading zero/meson.build b/test cases/failing/70 int literal leading zero/meson.build similarity index 100% rename from test cases/failing/72 int literal leading zero/meson.build rename to test cases/failing/70 int literal leading zero/meson.build diff --git a/test cases/failing/72 int literal leading zero/test.json b/test cases/failing/70 int literal leading zero/test.json similarity index 69% rename from test cases/failing/72 int literal leading zero/test.json rename to test cases/failing/70 int literal leading zero/test.json index 556e4921058e..fafbf0d044e2 100644 --- a/test cases/failing/72 int literal leading zero/test.json +++ b/test cases/failing/70 int literal leading zero/test.json @@ -2,7 +2,7 @@ "stdout": [ { "comment": "this error message is not very informative", - "line": "test cases/failing/72 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number." + "line": "test cases/failing/70 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number." } ] } diff --git a/test cases/failing/73 configuration immutable/input b/test cases/failing/71 configuration immutable/input similarity index 100% rename from test cases/failing/73 configuration immutable/input rename to test cases/failing/71 configuration immutable/input diff --git a/test cases/failing/73 configuration immutable/meson.build b/test cases/failing/71 configuration immutable/meson.build similarity index 100% rename from test cases/failing/73 configuration immutable/meson.build rename to test cases/failing/71 configuration immutable/meson.build diff --git a/test cases/failing/73 configuration immutable/test.json b/test cases/failing/71 configuration immutable/test.json similarity index 65% rename from test cases/failing/73 configuration immutable/test.json rename to test cases/failing/71 configuration immutable/test.json index 32d942781114..af1a65ddd184 100644 --- a/test cases/failing/73 configuration immutable/test.json +++ b/test cases/failing/71 configuration immutable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/73 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." + "line": "test cases/failing/71 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." } ] } diff --git a/test cases/failing/74 link with shared module on osx/meson.build b/test cases/failing/72 link with shared module on osx/meson.build similarity index 100% rename from test cases/failing/74 link with shared module on osx/meson.build rename to test cases/failing/72 link with shared module on osx/meson.build diff --git a/test cases/failing/74 link with shared module on osx/module.c b/test cases/failing/72 link with shared module on osx/module.c similarity index 100% rename from test cases/failing/74 link with shared module on osx/module.c rename to test cases/failing/72 link with shared module on osx/module.c diff --git a/test cases/failing/74 link with shared module on osx/prog.c b/test cases/failing/72 link with shared module on osx/prog.c similarity index 100% rename from test cases/failing/74 link with shared module on osx/prog.c rename to test cases/failing/72 link with shared module on osx/prog.c diff --git a/test cases/failing/74 link with shared module on osx/test.json b/test cases/failing/72 link with shared module on osx/test.json similarity index 68% rename from test cases/failing/74 link with shared module on osx/test.json rename to test cases/failing/72 link with shared module on osx/test.json index 09e990616ccb..1a2d78cd7e16 100644 --- a/test cases/failing/74 link with shared module on osx/test.json +++ b/test cases/failing/72 link with shared module on osx/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/74 link with shared module on osx/meson.build:8:4: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" + "line": "test cases/failing/72 link with shared module on osx/meson.build:8:4: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" } ] } diff --git a/test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in b/test cases/failing/73 non-ascii in ascii encoded configure file/config9.h.in similarity index 100% rename from test cases/failing/75 non-ascii in ascii encoded configure file/config9.h.in rename to test cases/failing/73 non-ascii in ascii encoded configure file/config9.h.in diff --git a/test cases/failing/75 non-ascii in ascii encoded configure file/meson.build b/test cases/failing/73 non-ascii in ascii encoded configure file/meson.build similarity index 100% rename from test cases/failing/75 non-ascii in ascii encoded configure file/meson.build rename to test cases/failing/73 non-ascii in ascii encoded configure file/meson.build diff --git a/test cases/failing/75 non-ascii in ascii encoded configure file/test.json b/test cases/failing/73 non-ascii in ascii encoded configure file/test.json similarity index 79% rename from test cases/failing/75 non-ascii in ascii encoded configure file/test.json rename to test cases/failing/73 non-ascii in ascii encoded configure file/test.json index 3d797f9239da..63f5bef8530d 100644 --- a/test cases/failing/75 non-ascii in ascii encoded configure file/test.json +++ b/test cases/failing/73 non-ascii in ascii encoded configure file/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/75 non-ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)" + "line": "test cases/failing/73 non-ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)" } ] } diff --git a/test cases/failing/76 subproj dependency not-found and required/meson.build b/test cases/failing/74 subproj dependency not-found and required/meson.build similarity index 100% rename from test cases/failing/76 subproj dependency not-found and required/meson.build rename to test cases/failing/74 subproj dependency not-found and required/meson.build diff --git a/test cases/failing/76 subproj dependency not-found and required/test.json b/test cases/failing/74 subproj dependency not-found and required/test.json similarity index 68% rename from test cases/failing/76 subproj dependency not-found and required/test.json rename to test cases/failing/74 subproj dependency not-found and required/test.json index 52d3a0fefba5..997bc56b2cc8 100644 --- a/test cases/failing/76 subproj dependency not-found and required/test.json +++ b/test cases/failing/74 subproj dependency not-found and required/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/76 subproj dependency not-found and required/meson.build:2:10: ERROR: Neither a subproject directory nor a missing.wrap file was found." + "line": "test cases/failing/74 subproj dependency not-found and required/meson.build:2:10: ERROR: Neither a subproject directory nor a missing.wrap file was found." } ] } diff --git a/test cases/failing/77 unfound run/meson.build b/test cases/failing/75 unfound run/meson.build similarity index 100% rename from test cases/failing/77 unfound run/meson.build rename to test cases/failing/75 unfound run/meson.build diff --git a/test cases/failing/77 unfound run/test.json b/test cases/failing/75 unfound run/test.json similarity index 60% rename from test cases/failing/77 unfound run/test.json rename to test cases/failing/75 unfound run/test.json index 99464bd7b789..855c2a477d0d 100644 --- a/test cases/failing/77 unfound run/test.json +++ b/test cases/failing/75 unfound run/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/77 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'" + "line": "test cases/failing/75 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'" } ] } diff --git a/test cases/failing/78 framework dependency with version/meson.build b/test cases/failing/76 framework dependency with version/meson.build similarity index 100% rename from test cases/failing/78 framework dependency with version/meson.build rename to test cases/failing/76 framework dependency with version/meson.build diff --git a/test cases/failing/78 framework dependency with version/test.json b/test cases/failing/76 framework dependency with version/test.json similarity index 72% rename from test cases/failing/78 framework dependency with version/test.json rename to test cases/failing/76 framework dependency with version/test.json index 8a708316bd9f..07b4a6eba4e8 100644 --- a/test cases/failing/78 framework dependency with version/test.json +++ b/test cases/failing/76 framework dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/78 framework dependency with version/meson.build:8:6: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/76 framework dependency with version/meson.build:8:6: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/79 override exe config/foo.c b/test cases/failing/77 override exe config/foo.c similarity index 100% rename from test cases/failing/79 override exe config/foo.c rename to test cases/failing/77 override exe config/foo.c diff --git a/test cases/failing/79 override exe config/meson.build b/test cases/failing/77 override exe config/meson.build similarity index 100% rename from test cases/failing/79 override exe config/meson.build rename to test cases/failing/77 override exe config/meson.build diff --git a/test cases/failing/79 override exe config/test.json b/test cases/failing/77 override exe config/test.json similarity index 72% rename from test cases/failing/79 override exe config/test.json rename to test cases/failing/77 override exe config/test.json index 1a671a37efcf..a0dd7ae6e6ed 100644 --- a/test cases/failing/79 override exe config/test.json +++ b/test cases/failing/77 override exe config/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/79 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration" + "line": "test cases/failing/77 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration" } ] } diff --git a/test cases/failing/80 gl dependency with version/meson.build b/test cases/failing/78 gl dependency with version/meson.build similarity index 100% rename from test cases/failing/80 gl dependency with version/meson.build rename to test cases/failing/78 gl dependency with version/meson.build diff --git a/test cases/failing/80 gl dependency with version/test.json b/test cases/failing/78 gl dependency with version/test.json similarity index 69% rename from test cases/failing/80 gl dependency with version/test.json rename to test cases/failing/78 gl dependency with version/test.json index 73d470a70e1a..fbd9ff9ee478 100644 --- a/test cases/failing/80 gl dependency with version/test.json +++ b/test cases/failing/78 gl dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/80 gl dependency with version/meson.build:9:6: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/78 gl dependency with version/meson.build:9:6: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/81 threads dependency with version/meson.build b/test cases/failing/79 threads dependency with version/meson.build similarity index 100% rename from test cases/failing/81 threads dependency with version/meson.build rename to test cases/failing/79 threads dependency with version/meson.build diff --git a/test cases/failing/81 threads dependency with version/test.json b/test cases/failing/79 threads dependency with version/test.json similarity index 71% rename from test cases/failing/81 threads dependency with version/test.json rename to test cases/failing/79 threads dependency with version/test.json index 2c12d69126c7..890695b64b00 100644 --- a/test cases/failing/81 threads dependency with version/test.json +++ b/test cases/failing/79 threads dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/81 threads dependency with version/meson.build:3:6: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/79 threads dependency with version/meson.build:3:6: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/82 gtest dependency with version/meson.build b/test cases/failing/80 gtest dependency with version/meson.build similarity index 100% rename from test cases/failing/82 gtest dependency with version/meson.build rename to test cases/failing/80 gtest dependency with version/meson.build diff --git a/test cases/failing/82 gtest dependency with version/test.json b/test cases/failing/80 gtest dependency with version/test.json similarity index 62% rename from test cases/failing/82 gtest dependency with version/test.json rename to test cases/failing/80 gtest dependency with version/test.json index 4eb816eff976..3f9934d49e60 100644 --- a/test cases/failing/82 gtest dependency with version/test.json +++ b/test cases/failing/80 gtest dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/82 gtest dependency with version/meson.build:8:6: ERROR: Dependency 'gtest' is required but not found." + "line": "test cases/failing/80 gtest dependency with version/meson.build:8:6: ERROR: Dependency 'gtest' is required but not found." } ] } diff --git a/test cases/failing/83 dub library/meson.build b/test cases/failing/81 dub library/meson.build similarity index 100% rename from test cases/failing/83 dub library/meson.build rename to test cases/failing/81 dub library/meson.build diff --git a/test cases/failing/83 dub library/test.json b/test cases/failing/81 dub library/test.json similarity index 57% rename from test cases/failing/83 dub library/test.json rename to test cases/failing/81 dub library/test.json index e4248f4f0342..2db91eed594d 100644 --- a/test cases/failing/83 dub library/test.json +++ b/test cases/failing/81 dub library/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/83 dub library/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" + "line": "test cases/failing/81 dub library/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" } ] } diff --git a/test cases/failing/84 dub executable/meson.build b/test cases/failing/82 dub executable/meson.build similarity index 100% rename from test cases/failing/84 dub executable/meson.build rename to test cases/failing/82 dub executable/meson.build diff --git a/test cases/failing/84 dub executable/test.json b/test cases/failing/82 dub executable/test.json similarity index 59% rename from test cases/failing/84 dub executable/test.json rename to test cases/failing/82 dub executable/test.json index 6dfff62d0ac9..8ae46b84864f 100644 --- a/test cases/failing/84 dub executable/test.json +++ b/test cases/failing/82 dub executable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/84 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found" + "line": "test cases/failing/82 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found" } ] } diff --git a/test cases/failing/85 dub compiler/meson.build b/test cases/failing/83 dub compiler/meson.build similarity index 100% rename from test cases/failing/85 dub compiler/meson.build rename to test cases/failing/83 dub compiler/meson.build diff --git a/test cases/failing/85 dub compiler/test.json b/test cases/failing/83 dub compiler/test.json similarity index 81% rename from test cases/failing/85 dub compiler/test.json rename to test cases/failing/83 dub compiler/test.json index 50ee39b31c58..07241d21ed47 100644 --- a/test cases/failing/85 dub compiler/test.json +++ b/test cases/failing/83 dub compiler/test.json @@ -13,7 +13,7 @@ }, "stdout": [ { - "line": "test cases/failing/85 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found" + "line": "test cases/failing/83 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found" } ] } diff --git a/test cases/failing/86 subproj not-found dep/meson.build b/test cases/failing/84 subproj not-found dep/meson.build similarity index 100% rename from test cases/failing/86 subproj not-found dep/meson.build rename to test cases/failing/84 subproj not-found dep/meson.build diff --git a/test cases/failing/86 subproj not-found dep/subprojects/somesubproj/meson.build b/test cases/failing/84 subproj not-found dep/subprojects/somesubproj/meson.build similarity index 100% rename from test cases/failing/86 subproj not-found dep/subprojects/somesubproj/meson.build rename to test cases/failing/84 subproj not-found dep/subprojects/somesubproj/meson.build diff --git a/test cases/failing/86 subproj not-found dep/test.json b/test cases/failing/84 subproj not-found dep/test.json similarity index 62% rename from test cases/failing/86 subproj not-found dep/test.json rename to test cases/failing/84 subproj not-found dep/test.json index c1acb9a62ccc..bea1ed0e3614 100644 --- a/test cases/failing/86 subproj not-found dep/test.json +++ b/test cases/failing/84 subproj not-found dep/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/86 subproj not-found dep/meson.build:2:10: ERROR: Dependency '(anonymous)' is required but not found." + "line": "test cases/failing/84 subproj not-found dep/meson.build:2:10: ERROR: Dependency '(anonymous)' is required but not found." } ] } diff --git a/test cases/failing/87 invalid configure file/input b/test cases/failing/85 invalid configure file/input similarity index 100% rename from test cases/failing/87 invalid configure file/input rename to test cases/failing/85 invalid configure file/input diff --git a/test cases/failing/87 invalid configure file/meson.build b/test cases/failing/85 invalid configure file/meson.build similarity index 100% rename from test cases/failing/87 invalid configure file/meson.build rename to test cases/failing/85 invalid configure file/meson.build diff --git a/test cases/failing/87 invalid configure file/test.json b/test cases/failing/85 invalid configure file/test.json similarity index 67% rename from test cases/failing/87 invalid configure file/test.json rename to test cases/failing/85 invalid configure file/test.json index d8ea73d5f001..1cee20880a4d 100644 --- a/test cases/failing/87 invalid configure file/test.json +++ b/test cases/failing/85 invalid configure file/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/87 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true" + "line": "test cases/failing/85 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true" } ] } diff --git a/test cases/failing/88 kwarg dupe/meson.build b/test cases/failing/86 kwarg dupe/meson.build similarity index 100% rename from test cases/failing/88 kwarg dupe/meson.build rename to test cases/failing/86 kwarg dupe/meson.build diff --git a/test cases/failing/88 kwarg dupe/prog.c b/test cases/failing/86 kwarg dupe/prog.c similarity index 100% rename from test cases/failing/88 kwarg dupe/prog.c rename to test cases/failing/86 kwarg dupe/prog.c diff --git a/test cases/failing/88 kwarg dupe/test.json b/test cases/failing/86 kwarg dupe/test.json similarity index 65% rename from test cases/failing/88 kwarg dupe/test.json rename to test cases/failing/86 kwarg dupe/test.json index d152725c9b7e..229debbea812 100644 --- a/test cases/failing/88 kwarg dupe/test.json +++ b/test cases/failing/86 kwarg dupe/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/88 kwarg dupe/meson.build:6:2: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." + "line": "test cases/failing/86 kwarg dupe/meson.build:6:2: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." } ] } diff --git a/test cases/failing/89 missing pch file/meson.build b/test cases/failing/87 missing pch file/meson.build similarity index 100% rename from test cases/failing/89 missing pch file/meson.build rename to test cases/failing/87 missing pch file/meson.build diff --git a/test cases/failing/89 missing pch file/prog.c b/test cases/failing/87 missing pch file/prog.c similarity index 100% rename from test cases/failing/89 missing pch file/prog.c rename to test cases/failing/87 missing pch file/prog.c diff --git a/test cases/failing/89 missing pch file/test.json b/test cases/failing/87 missing pch file/test.json similarity index 74% rename from test cases/failing/89 missing pch file/test.json rename to test cases/failing/87 missing pch file/test.json index 1924bbf3d5c8..a54acb7a7562 100644 --- a/test cases/failing/89 missing pch file/test.json +++ b/test cases/failing/87 missing pch file/test.json @@ -2,7 +2,7 @@ "stdout": [ { "comment": "literal 'pch/prog.h' from meson.build appears in output, irrespective of os.path.sep", - "line": "test cases/failing/89 missing pch file/meson.build:2:6: ERROR: File pch/prog.h does not exist." + "line": "test cases/failing/87 missing pch file/meson.build:2:6: ERROR: File pch/prog.h does not exist." } ] } diff --git a/test cases/failing/90 pch source different folder/include/pch.h b/test cases/failing/88 pch source different folder/include/pch.h similarity index 100% rename from test cases/failing/90 pch source different folder/include/pch.h rename to test cases/failing/88 pch source different folder/include/pch.h diff --git a/test cases/failing/90 pch source different folder/meson.build b/test cases/failing/88 pch source different folder/meson.build similarity index 100% rename from test cases/failing/90 pch source different folder/meson.build rename to test cases/failing/88 pch source different folder/meson.build diff --git a/test cases/failing/90 pch source different folder/prog.c b/test cases/failing/88 pch source different folder/prog.c similarity index 100% rename from test cases/failing/90 pch source different folder/prog.c rename to test cases/failing/88 pch source different folder/prog.c diff --git a/test cases/failing/90 pch source different folder/src/pch.c b/test cases/failing/88 pch source different folder/src/pch.c similarity index 100% rename from test cases/failing/90 pch source different folder/src/pch.c rename to test cases/failing/88 pch source different folder/src/pch.c diff --git a/test cases/failing/90 pch source different folder/test.json b/test cases/failing/88 pch source different folder/test.json similarity index 62% rename from test cases/failing/90 pch source different folder/test.json rename to test cases/failing/88 pch source different folder/test.json index 49cdcb0f7e7b..60fa4e0a6f07 100644 --- a/test cases/failing/90 pch source different folder/test.json +++ b/test cases/failing/88 pch source different folder/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/90 pch source different folder/meson.build:4:6: ERROR: PCH files must be stored in the same folder." + "line": "test cases/failing/88 pch source different folder/meson.build:4:6: ERROR: PCH files must be stored in the same folder." } ] } diff --git a/test cases/failing/91 unknown config tool/meson.build b/test cases/failing/89 unknown config tool/meson.build similarity index 100% rename from test cases/failing/91 unknown config tool/meson.build rename to test cases/failing/89 unknown config tool/meson.build diff --git a/test cases/failing/91 unknown config tool/test.json b/test cases/failing/89 unknown config tool/test.json similarity index 60% rename from test cases/failing/91 unknown config tool/test.json rename to test cases/failing/89 unknown config tool/test.json index e225167d57fe..f5c0d96abb13 100644 --- a/test cases/failing/91 unknown config tool/test.json +++ b/test cases/failing/89 unknown config tool/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/91 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found" + "line": "test cases/failing/89 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found" } ] } diff --git a/test cases/failing/92 custom target install data/Info.plist.cpp b/test cases/failing/90 custom target install data/Info.plist.cpp similarity index 100% rename from test cases/failing/92 custom target install data/Info.plist.cpp rename to test cases/failing/90 custom target install data/Info.plist.cpp diff --git a/test cases/failing/92 custom target install data/meson.build b/test cases/failing/90 custom target install data/meson.build similarity index 100% rename from test cases/failing/92 custom target install data/meson.build rename to test cases/failing/90 custom target install data/meson.build diff --git a/test cases/failing/92 custom target install data/preproc.py b/test cases/failing/90 custom target install data/preproc.py similarity index 100% rename from test cases/failing/92 custom target install data/preproc.py rename to test cases/failing/90 custom target install data/preproc.py diff --git a/test cases/failing/92 custom target install data/test.json b/test cases/failing/90 custom target install data/test.json similarity index 71% rename from test cases/failing/92 custom target install data/test.json rename to test cases/failing/90 custom target install data/test.json index 46ab01362bd9..d495163f2a2b 100644 --- a/test cases/failing/92 custom target install data/test.json +++ b/test cases/failing/90 custom target install data/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/92 custom target install data/meson.build:11:0: ERROR: install_data argument 1 was of type \"CustomTarget\" but should have been one of: \"str\", \"File\"" + "line": "test cases/failing/90 custom target install data/meson.build:11:0: ERROR: install_data argument 1 was of type \"CustomTarget\" but should have been one of: \"str\", \"File\"" } ] } diff --git a/test cases/failing/93 add dict non string key/meson.build b/test cases/failing/91 add dict non string key/meson.build similarity index 100% rename from test cases/failing/93 add dict non string key/meson.build rename to test cases/failing/91 add dict non string key/meson.build diff --git a/test cases/failing/93 add dict non string key/test.json b/test cases/failing/91 add dict non string key/test.json similarity index 54% rename from test cases/failing/93 add dict non string key/test.json rename to test cases/failing/91 add dict non string key/test.json index 0ca2f532afd2..db506b2e021e 100644 --- a/test cases/failing/93 add dict non string key/test.json +++ b/test cases/failing/91 add dict non string key/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/93 add dict non string key/meson.build:9:9: ERROR: Key must be a string" + "line": "test cases/failing/91 add dict non string key/meson.build:9:9: ERROR: Key must be a string" } ] } diff --git a/test cases/failing/94 add dict duplicate keys/meson.build b/test cases/failing/92 add dict duplicate keys/meson.build similarity index 100% rename from test cases/failing/94 add dict duplicate keys/meson.build rename to test cases/failing/92 add dict duplicate keys/meson.build diff --git a/test cases/failing/94 add dict duplicate keys/test.json b/test cases/failing/92 add dict duplicate keys/test.json similarity index 58% rename from test cases/failing/94 add dict duplicate keys/test.json rename to test cases/failing/92 add dict duplicate keys/test.json index 23a557374d27..b428a5387348 100644 --- a/test cases/failing/94 add dict duplicate keys/test.json +++ b/test cases/failing/92 add dict duplicate keys/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/94 add dict duplicate keys/meson.build:9:27: ERROR: Duplicate dictionary key: myKey" + "line": "test cases/failing/92 add dict duplicate keys/meson.build:9:27: ERROR: Duplicate dictionary key: myKey" } ] } diff --git a/test cases/failing/95 no host get_external_property/meson.build b/test cases/failing/93 no host get_external_property/meson.build similarity index 100% rename from test cases/failing/95 no host get_external_property/meson.build rename to test cases/failing/93 no host get_external_property/meson.build diff --git a/test cases/failing/95 no host get_external_property/test.json b/test cases/failing/93 no host get_external_property/test.json similarity index 63% rename from test cases/failing/95 no host get_external_property/test.json rename to test cases/failing/93 no host get_external_property/test.json index 18507e715bfe..b26f3c9b6b59 100644 --- a/test cases/failing/95 no host get_external_property/test.json +++ b/test cases/failing/93 no host get_external_property/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/95 no host get_external_property/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" + "line": "test cases/failing/93 no host get_external_property/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" } ] } diff --git a/test cases/failing/96 no native compiler/main.c b/test cases/failing/94 no native compiler/main.c similarity index 100% rename from test cases/failing/96 no native compiler/main.c rename to test cases/failing/94 no native compiler/main.c diff --git a/test cases/failing/96 no native compiler/meson.build b/test cases/failing/94 no native compiler/meson.build similarity index 100% rename from test cases/failing/96 no native compiler/meson.build rename to test cases/failing/94 no native compiler/meson.build diff --git a/test cases/failing/96 no native compiler/test.json b/test cases/failing/94 no native compiler/test.json similarity index 58% rename from test cases/failing/96 no native compiler/test.json rename to test cases/failing/94 no native compiler/test.json index 01077275c2ef..7181c6b7ee5d 100644 --- a/test cases/failing/96 no native compiler/test.json +++ b/test cases/failing/94 no native compiler/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/96 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\"" + "line": "test cases/failing/94 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\"" } ] } diff --git a/test cases/failing/97 subdir parse error/meson.build b/test cases/failing/95 subdir parse error/meson.build similarity index 100% rename from test cases/failing/97 subdir parse error/meson.build rename to test cases/failing/95 subdir parse error/meson.build diff --git a/test cases/failing/97 subdir parse error/subdir/meson.build b/test cases/failing/95 subdir parse error/subdir/meson.build similarity index 100% rename from test cases/failing/97 subdir parse error/subdir/meson.build rename to test cases/failing/95 subdir parse error/subdir/meson.build diff --git a/test cases/failing/97 subdir parse error/test.json b/test cases/failing/95 subdir parse error/test.json similarity index 59% rename from test cases/failing/97 subdir parse error/test.json rename to test cases/failing/95 subdir parse error/test.json index 414789ee03dc..c94ed58d47d5 100644 --- a/test cases/failing/97 subdir parse error/test.json +++ b/test cases/failing/95 subdir parse error/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/97 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id." + "line": "test cases/failing/95 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id." } ] } diff --git a/test cases/failing/98 invalid option file/meson.build b/test cases/failing/96 invalid option file/meson.build similarity index 100% rename from test cases/failing/98 invalid option file/meson.build rename to test cases/failing/96 invalid option file/meson.build diff --git a/test cases/failing/98 invalid option file/meson_options.txt b/test cases/failing/96 invalid option file/meson_options.txt similarity index 100% rename from test cases/failing/98 invalid option file/meson_options.txt rename to test cases/failing/96 invalid option file/meson_options.txt diff --git a/test cases/failing/98 invalid option file/test.json b/test cases/failing/96 invalid option file/test.json similarity index 50% rename from test cases/failing/98 invalid option file/test.json rename to test cases/failing/96 invalid option file/test.json index 6ab53931a5de..5f1a89f7ced1 100644 --- a/test cases/failing/98 invalid option file/test.json +++ b/test cases/failing/96 invalid option file/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/98 invalid option file/meson_options.txt:1:0: ERROR: lexer" + "line": "test cases/failing/96 invalid option file/meson_options.txt:1:0: ERROR: lexer" } ] } diff --git a/test cases/failing/99 no lang/main.c b/test cases/failing/97 no lang/main.c similarity index 100% rename from test cases/failing/99 no lang/main.c rename to test cases/failing/97 no lang/main.c diff --git a/test cases/failing/99 no lang/meson.build b/test cases/failing/97 no lang/meson.build similarity index 100% rename from test cases/failing/99 no lang/meson.build rename to test cases/failing/97 no lang/meson.build diff --git a/test cases/failing/99 no lang/test.json b/test cases/failing/97 no lang/test.json similarity index 54% rename from test cases/failing/99 no lang/test.json rename to test cases/failing/97 no lang/test.json index 48c6dd70e698..a2af0a1970b9 100644 --- a/test cases/failing/99 no lang/test.json +++ b/test cases/failing/97 no lang/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/99 no lang/meson.build:2:0: ERROR: No host machine compiler for 'main.c'" + "line": "test cases/failing/97 no lang/meson.build:2:0: ERROR: No host machine compiler for 'main.c'" } ] } diff --git a/test cases/failing/100 no glib-compile-resources/meson.build b/test cases/failing/98 no glib-compile-resources/meson.build similarity index 100% rename from test cases/failing/100 no glib-compile-resources/meson.build rename to test cases/failing/98 no glib-compile-resources/meson.build diff --git a/test cases/failing/98 no glib-compile-resources/test.json b/test cases/failing/98 no glib-compile-resources/test.json new file mode 100644 index 000000000000..d5edd7692da2 --- /dev/null +++ b/test cases/failing/98 no glib-compile-resources/test.json @@ -0,0 +1,7 @@ +{ + "stdout": [ + { + "line": "test cases/failing/98 no glib-compile-resources/meson.build:8:12: ERROR: Program 'glib-compile-resources' not found or not executable" + } + ] +} diff --git a/test cases/failing/100 no glib-compile-resources/trivial.gresource.xml b/test cases/failing/98 no glib-compile-resources/trivial.gresource.xml similarity index 100% rename from test cases/failing/100 no glib-compile-resources/trivial.gresource.xml rename to test cases/failing/98 no glib-compile-resources/trivial.gresource.xml diff --git a/test cases/failing/101 number in combo/meson.build b/test cases/failing/99 number in combo/meson.build similarity index 100% rename from test cases/failing/101 number in combo/meson.build rename to test cases/failing/99 number in combo/meson.build diff --git a/test cases/failing/101 number in combo/nativefile.ini b/test cases/failing/99 number in combo/nativefile.ini similarity index 100% rename from test cases/failing/101 number in combo/nativefile.ini rename to test cases/failing/99 number in combo/nativefile.ini diff --git a/test cases/failing/99 number in combo/test.json b/test cases/failing/99 number in combo/test.json new file mode 100644 index 000000000000..f59812e3bcda --- /dev/null +++ b/test cases/failing/99 number in combo/test.json @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/99 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + ] +} diff --git a/test cases/unit/101 relative find program/foo.py b/test cases/unit/100 relative find program/foo.py similarity index 100% rename from test cases/unit/101 relative find program/foo.py rename to test cases/unit/100 relative find program/foo.py diff --git a/test cases/unit/101 relative find program/meson.build b/test cases/unit/100 relative find program/meson.build similarity index 100% rename from test cases/unit/101 relative find program/meson.build rename to test cases/unit/100 relative find program/meson.build diff --git a/test cases/unit/101 relative find program/subdir/meson.build b/test cases/unit/100 relative find program/subdir/meson.build similarity index 100% rename from test cases/unit/101 relative find program/subdir/meson.build rename to test cases/unit/100 relative find program/subdir/meson.build diff --git a/test cases/unit/102 rlib linkage/lib2.rs b/test cases/unit/101 rlib linkage/lib2.rs similarity index 100% rename from test cases/unit/102 rlib linkage/lib2.rs rename to test cases/unit/101 rlib linkage/lib2.rs diff --git a/test cases/unit/102 rlib linkage/main.rs b/test cases/unit/101 rlib linkage/main.rs similarity index 100% rename from test cases/unit/102 rlib linkage/main.rs rename to test cases/unit/101 rlib linkage/main.rs diff --git a/test cases/unit/102 rlib linkage/meson.build b/test cases/unit/101 rlib linkage/meson.build similarity index 100% rename from test cases/unit/102 rlib linkage/meson.build rename to test cases/unit/101 rlib linkage/meson.build diff --git a/test cases/unit/103 python without pkgconfig/meson.build b/test cases/unit/102 python without pkgconfig/meson.build similarity index 100% rename from test cases/unit/103 python without pkgconfig/meson.build rename to test cases/unit/102 python without pkgconfig/meson.build diff --git a/test cases/unit/104 strip/lib.c b/test cases/unit/103 strip/lib.c similarity index 100% rename from test cases/unit/104 strip/lib.c rename to test cases/unit/103 strip/lib.c diff --git a/test cases/unit/104 strip/meson.build b/test cases/unit/103 strip/meson.build similarity index 100% rename from test cases/unit/104 strip/meson.build rename to test cases/unit/103 strip/meson.build diff --git a/test cases/unit/105 debug function/meson.build b/test cases/unit/104 debug function/meson.build similarity index 100% rename from test cases/unit/105 debug function/meson.build rename to test cases/unit/104 debug function/meson.build diff --git a/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build b/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build similarity index 100% rename from test cases/unit/106 pkgconfig relocatable with absolute path/meson.build rename to test cases/unit/105 pkgconfig relocatable with absolute path/meson.build diff --git a/test cases/unit/110 replace unencodable xml chars/meson.build b/test cases/unit/111 replace unencodable xml chars/meson.build similarity index 100% rename from test cases/unit/110 replace unencodable xml chars/meson.build rename to test cases/unit/111 replace unencodable xml chars/meson.build diff --git a/test cases/unit/110 replace unencodable xml chars/script.py b/test cases/unit/111 replace unencodable xml chars/script.py similarity index 100% rename from test cases/unit/110 replace unencodable xml chars/script.py rename to test cases/unit/111 replace unencodable xml chars/script.py diff --git a/test cases/unit/111 classpath/com/mesonbuild/Simple.java b/test cases/unit/112 classpath/com/mesonbuild/Simple.java similarity index 100% rename from test cases/unit/111 classpath/com/mesonbuild/Simple.java rename to test cases/unit/112 classpath/com/mesonbuild/Simple.java diff --git a/test cases/unit/111 classpath/meson.build b/test cases/unit/112 classpath/meson.build similarity index 100% rename from test cases/unit/111 classpath/meson.build rename to test cases/unit/112 classpath/meson.build diff --git a/test cases/unit/112 list build options/meson.build b/test cases/unit/113 list build options/meson.build similarity index 100% rename from test cases/unit/112 list build options/meson.build rename to test cases/unit/113 list build options/meson.build diff --git a/test cases/unit/112 list build options/meson_options.txt b/test cases/unit/113 list build options/meson_options.txt similarity index 100% rename from test cases/unit/112 list build options/meson_options.txt rename to test cases/unit/113 list build options/meson_options.txt diff --git a/test cases/unit/113 complex link cases/main.c b/test cases/unit/114 complex link cases/main.c similarity index 100% rename from test cases/unit/113 complex link cases/main.c rename to test cases/unit/114 complex link cases/main.c diff --git a/test cases/unit/113 complex link cases/meson.build b/test cases/unit/114 complex link cases/meson.build similarity index 100% rename from test cases/unit/113 complex link cases/meson.build rename to test cases/unit/114 complex link cases/meson.build diff --git a/test cases/unit/113 complex link cases/s1.c b/test cases/unit/114 complex link cases/s1.c similarity index 100% rename from test cases/unit/113 complex link cases/s1.c rename to test cases/unit/114 complex link cases/s1.c diff --git a/test cases/unit/113 complex link cases/s2.c b/test cases/unit/114 complex link cases/s2.c similarity index 100% rename from test cases/unit/113 complex link cases/s2.c rename to test cases/unit/114 complex link cases/s2.c diff --git a/test cases/unit/113 complex link cases/s3.c b/test cases/unit/114 complex link cases/s3.c similarity index 100% rename from test cases/unit/113 complex link cases/s3.c rename to test cases/unit/114 complex link cases/s3.c diff --git a/test cases/unit/114 c cpp stds/meson.build b/test cases/unit/115 c cpp stds/meson.build similarity index 100% rename from test cases/unit/114 c cpp stds/meson.build rename to test cases/unit/115 c cpp stds/meson.build diff --git a/test cases/unit/114 empty project/expected_mods.json b/test cases/unit/116 empty project/expected_mods.json similarity index 100% rename from test cases/unit/114 empty project/expected_mods.json rename to test cases/unit/116 empty project/expected_mods.json diff --git a/test cases/unit/114 empty project/meson.build b/test cases/unit/116 empty project/meson.build similarity index 100% rename from test cases/unit/114 empty project/meson.build rename to test cases/unit/116 empty project/meson.build diff --git a/test cases/unit/115 genvslite/main.cpp b/test cases/unit/117 genvslite/main.cpp similarity index 100% rename from test cases/unit/115 genvslite/main.cpp rename to test cases/unit/117 genvslite/main.cpp diff --git a/test cases/unit/115 genvslite/meson.build b/test cases/unit/117 genvslite/meson.build similarity index 100% rename from test cases/unit/115 genvslite/meson.build rename to test cases/unit/117 genvslite/meson.build diff --git a/test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build b/test cases/unit/118 meson package cache dir/cache_dir/bar/meson.build similarity index 100% rename from test cases/unit/116 meson package cache dir/cache_dir/bar/meson.build rename to test cases/unit/118 meson package cache dir/cache_dir/bar/meson.build diff --git a/test cases/unit/116 meson package cache dir/cache_dir/foo.zip b/test cases/unit/118 meson package cache dir/cache_dir/foo.zip similarity index 100% rename from test cases/unit/116 meson package cache dir/cache_dir/foo.zip rename to test cases/unit/118 meson package cache dir/cache_dir/foo.zip diff --git a/test cases/unit/116 meson package cache dir/meson.build b/test cases/unit/118 meson package cache dir/meson.build similarity index 100% rename from test cases/unit/116 meson package cache dir/meson.build rename to test cases/unit/118 meson package cache dir/meson.build diff --git a/test cases/unit/116 meson package cache dir/subprojects/bar.wrap b/test cases/unit/118 meson package cache dir/subprojects/bar.wrap similarity index 100% rename from test cases/unit/116 meson package cache dir/subprojects/bar.wrap rename to test cases/unit/118 meson package cache dir/subprojects/bar.wrap diff --git a/test cases/unit/116 meson package cache dir/subprojects/foo.wrap b/test cases/unit/118 meson package cache dir/subprojects/foo.wrap similarity index 100% rename from test cases/unit/116 meson package cache dir/subprojects/foo.wrap rename to test cases/unit/118 meson package cache dir/subprojects/foo.wrap diff --git a/test cases/unit/117 openssl cmake bug/meson.build b/test cases/unit/119 openssl cmake bug/meson.build similarity index 100% rename from test cases/unit/117 openssl cmake bug/meson.build rename to test cases/unit/119 openssl cmake bug/meson.build diff --git a/test cases/unit/117 openssl cmake bug/nativefile.ini b/test cases/unit/119 openssl cmake bug/nativefile.ini similarity index 100% rename from test cases/unit/117 openssl cmake bug/nativefile.ini rename to test cases/unit/119 openssl cmake bug/nativefile.ini diff --git a/test cases/unit/118 rewrite/meson.build b/test cases/unit/120 rewrite/meson.build similarity index 100% rename from test cases/unit/118 rewrite/meson.build rename to test cases/unit/120 rewrite/meson.build diff --git a/test cases/unit/119 executable suffix/main.c b/test cases/unit/121 executable suffix/main.c similarity index 100% rename from test cases/unit/119 executable suffix/main.c rename to test cases/unit/121 executable suffix/main.c diff --git a/test cases/unit/119 executable suffix/meson.build b/test cases/unit/121 executable suffix/meson.build similarity index 100% rename from test cases/unit/119 executable suffix/meson.build rename to test cases/unit/121 executable suffix/meson.build diff --git a/test cases/unit/92 install skip subprojects/foo.c b/test cases/unit/91 install skip subprojects/foo.c similarity index 100% rename from test cases/unit/92 install skip subprojects/foo.c rename to test cases/unit/91 install skip subprojects/foo.c diff --git a/test cases/unit/92 install skip subprojects/foo.dat b/test cases/unit/91 install skip subprojects/foo.dat similarity index 100% rename from test cases/unit/92 install skip subprojects/foo.dat rename to test cases/unit/91 install skip subprojects/foo.dat diff --git a/test cases/unit/92 install skip subprojects/foo.h b/test cases/unit/91 install skip subprojects/foo.h similarity index 100% rename from test cases/unit/92 install skip subprojects/foo.h rename to test cases/unit/91 install skip subprojects/foo.h diff --git a/test cases/unit/92 install skip subprojects/foo/foofile b/test cases/unit/91 install skip subprojects/foo/foofile similarity index 100% rename from test cases/unit/92 install skip subprojects/foo/foofile rename to test cases/unit/91 install skip subprojects/foo/foofile diff --git a/test cases/unit/92 install skip subprojects/meson.build b/test cases/unit/91 install skip subprojects/meson.build similarity index 100% rename from test cases/unit/92 install skip subprojects/meson.build rename to test cases/unit/91 install skip subprojects/meson.build diff --git a/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c b/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c similarity index 100% rename from test cases/unit/92 install skip subprojects/subprojects/bar/bar.c rename to test cases/unit/91 install skip subprojects/subprojects/bar/bar.c diff --git a/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat b/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat similarity index 100% rename from test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat rename to test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat diff --git a/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h b/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h similarity index 100% rename from test cases/unit/92 install skip subprojects/subprojects/bar/bar.h rename to test cases/unit/91 install skip subprojects/subprojects/bar/bar.h diff --git a/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile b/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile similarity index 100% rename from test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile rename to test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile diff --git a/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build b/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build similarity index 100% rename from test cases/unit/92 install skip subprojects/subprojects/bar/meson.build rename to test cases/unit/91 install skip subprojects/subprojects/bar/meson.build diff --git a/test cases/unit/93 new subproject in configured project/meson.build b/test cases/unit/92 new subproject in configured project/meson.build similarity index 100% rename from test cases/unit/93 new subproject in configured project/meson.build rename to test cases/unit/92 new subproject in configured project/meson.build diff --git a/test cases/unit/93 new subproject in configured project/meson_options.txt b/test cases/unit/92 new subproject in configured project/meson_options.txt similarity index 100% rename from test cases/unit/93 new subproject in configured project/meson_options.txt rename to test cases/unit/92 new subproject in configured project/meson_options.txt diff --git a/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c b/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c similarity index 100% rename from test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c rename to test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c diff --git a/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build b/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build similarity index 100% rename from test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build rename to test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build diff --git a/test cases/unit/94 clangformat/.clang-format b/test cases/unit/93 clangformat/.clang-format similarity index 100% rename from test cases/unit/94 clangformat/.clang-format rename to test cases/unit/93 clangformat/.clang-format diff --git a/test cases/unit/94 clangformat/.clang-format-ignore b/test cases/unit/93 clangformat/.clang-format-ignore similarity index 100% rename from test cases/unit/94 clangformat/.clang-format-ignore rename to test cases/unit/93 clangformat/.clang-format-ignore diff --git a/test cases/unit/94 clangformat/.clang-format-include b/test cases/unit/93 clangformat/.clang-format-include similarity index 100% rename from test cases/unit/94 clangformat/.clang-format-include rename to test cases/unit/93 clangformat/.clang-format-include diff --git a/test cases/unit/94 clangformat/meson.build b/test cases/unit/93 clangformat/meson.build similarity index 100% rename from test cases/unit/94 clangformat/meson.build rename to test cases/unit/93 clangformat/meson.build diff --git a/test cases/unit/94 clangformat/not-included/badformat.cpp b/test cases/unit/93 clangformat/not-included/badformat.cpp similarity index 100% rename from test cases/unit/94 clangformat/not-included/badformat.cpp rename to test cases/unit/93 clangformat/not-included/badformat.cpp diff --git a/test cases/unit/94 clangformat/src/badformat.c b/test cases/unit/93 clangformat/src/badformat.c similarity index 100% rename from test cases/unit/94 clangformat/src/badformat.c rename to test cases/unit/93 clangformat/src/badformat.c diff --git a/test cases/unit/94 clangformat/src/badformat.cpp b/test cases/unit/93 clangformat/src/badformat.cpp similarity index 100% rename from test cases/unit/94 clangformat/src/badformat.cpp rename to test cases/unit/93 clangformat/src/badformat.cpp diff --git a/test cases/unit/95 custominc/easytogrepfor/genh.py b/test cases/unit/94 custominc/easytogrepfor/genh.py similarity index 100% rename from test cases/unit/95 custominc/easytogrepfor/genh.py rename to test cases/unit/94 custominc/easytogrepfor/genh.py diff --git a/test cases/unit/95 custominc/easytogrepfor/meson.build b/test cases/unit/94 custominc/easytogrepfor/meson.build similarity index 100% rename from test cases/unit/95 custominc/easytogrepfor/meson.build rename to test cases/unit/94 custominc/easytogrepfor/meson.build diff --git a/test cases/unit/95 custominc/helper.c b/test cases/unit/94 custominc/helper.c similarity index 100% rename from test cases/unit/95 custominc/helper.c rename to test cases/unit/94 custominc/helper.c diff --git a/test cases/unit/95 custominc/meson.build b/test cases/unit/94 custominc/meson.build similarity index 100% rename from test cases/unit/95 custominc/meson.build rename to test cases/unit/94 custominc/meson.build diff --git a/test cases/unit/95 custominc/prog.c b/test cases/unit/94 custominc/prog.c similarity index 100% rename from test cases/unit/95 custominc/prog.c rename to test cases/unit/94 custominc/prog.c diff --git a/test cases/unit/95 custominc/prog2.c b/test cases/unit/94 custominc/prog2.c similarity index 100% rename from test cases/unit/95 custominc/prog2.c rename to test cases/unit/94 custominc/prog2.c diff --git a/test cases/unit/96 implicit force fallback/meson.build b/test cases/unit/95 implicit force fallback/meson.build similarity index 100% rename from test cases/unit/96 implicit force fallback/meson.build rename to test cases/unit/95 implicit force fallback/meson.build diff --git a/test cases/unit/96 implicit force fallback/subprojects/something/meson.build b/test cases/unit/95 implicit force fallback/subprojects/something/meson.build similarity index 100% rename from test cases/unit/96 implicit force fallback/subprojects/something/meson.build rename to test cases/unit/95 implicit force fallback/subprojects/something/meson.build diff --git a/test cases/unit/97 compiler.links file arg/meson.build b/test cases/unit/96 compiler.links file arg/meson.build similarity index 100% rename from test cases/unit/97 compiler.links file arg/meson.build rename to test cases/unit/96 compiler.links file arg/meson.build diff --git a/test cases/unit/97 compiler.links file arg/test.c b/test cases/unit/96 compiler.links file arg/test.c similarity index 100% rename from test cases/unit/97 compiler.links file arg/test.c rename to test cases/unit/96 compiler.links file arg/test.c diff --git a/test cases/unit/98 link full name/.gitignore b/test cases/unit/97 link full name/.gitignore similarity index 100% rename from test cases/unit/98 link full name/.gitignore rename to test cases/unit/97 link full name/.gitignore diff --git a/test cases/unit/98 link full name/libtestprovider/meson.build b/test cases/unit/97 link full name/libtestprovider/meson.build similarity index 100% rename from test cases/unit/98 link full name/libtestprovider/meson.build rename to test cases/unit/97 link full name/libtestprovider/meson.build diff --git a/test cases/unit/98 link full name/libtestprovider/provider.c b/test cases/unit/97 link full name/libtestprovider/provider.c similarity index 100% rename from test cases/unit/98 link full name/libtestprovider/provider.c rename to test cases/unit/97 link full name/libtestprovider/provider.c diff --git a/test cases/unit/98 link full name/proguser/meson.build b/test cases/unit/97 link full name/proguser/meson.build similarity index 100% rename from test cases/unit/98 link full name/proguser/meson.build rename to test cases/unit/97 link full name/proguser/meson.build diff --git a/test cases/unit/98 link full name/proguser/receiver.c b/test cases/unit/97 link full name/proguser/receiver.c similarity index 100% rename from test cases/unit/98 link full name/proguser/receiver.c rename to test cases/unit/97 link full name/proguser/receiver.c diff --git a/test cases/unit/99 install all targets/bar-custom.txt b/test cases/unit/98 install all targets/bar-custom.txt similarity index 100% rename from test cases/unit/99 install all targets/bar-custom.txt rename to test cases/unit/98 install all targets/bar-custom.txt diff --git a/test cases/unit/99 install all targets/bar-devel.h b/test cases/unit/98 install all targets/bar-devel.h similarity index 100% rename from test cases/unit/99 install all targets/bar-devel.h rename to test cases/unit/98 install all targets/bar-devel.h diff --git a/test cases/unit/99 install all targets/bar-notag.txt b/test cases/unit/98 install all targets/bar-notag.txt similarity index 100% rename from test cases/unit/99 install all targets/bar-notag.txt rename to test cases/unit/98 install all targets/bar-notag.txt diff --git a/test cases/unit/99 install all targets/custom_files/data.txt b/test cases/unit/98 install all targets/custom_files/data.txt similarity index 100% rename from test cases/unit/99 install all targets/custom_files/data.txt rename to test cases/unit/98 install all targets/custom_files/data.txt diff --git a/test cases/unit/99 install all targets/excludes/excluded.txt b/test cases/unit/98 install all targets/excludes/excluded.txt similarity index 100% rename from test cases/unit/99 install all targets/excludes/excluded.txt rename to test cases/unit/98 install all targets/excludes/excluded.txt diff --git a/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt b/test cases/unit/98 install all targets/excludes/excluded/placeholder.txt similarity index 100% rename from test cases/unit/99 install all targets/excludes/excluded/placeholder.txt rename to test cases/unit/98 install all targets/excludes/excluded/placeholder.txt diff --git a/test cases/unit/99 install all targets/excludes/installed.txt b/test cases/unit/98 install all targets/excludes/installed.txt similarity index 100% rename from test cases/unit/99 install all targets/excludes/installed.txt rename to test cases/unit/98 install all targets/excludes/installed.txt diff --git a/test cases/unit/99 install all targets/foo.in b/test cases/unit/98 install all targets/foo.in similarity index 100% rename from test cases/unit/99 install all targets/foo.in rename to test cases/unit/98 install all targets/foo.in diff --git a/test cases/unit/99 install all targets/foo1-devel.h b/test cases/unit/98 install all targets/foo1-devel.h similarity index 100% rename from test cases/unit/99 install all targets/foo1-devel.h rename to test cases/unit/98 install all targets/foo1-devel.h diff --git a/test cases/unit/99 install all targets/lib.c b/test cases/unit/98 install all targets/lib.c similarity index 100% rename from test cases/unit/99 install all targets/lib.c rename to test cases/unit/98 install all targets/lib.c diff --git a/test cases/unit/99 install all targets/main.c b/test cases/unit/98 install all targets/main.c similarity index 100% rename from test cases/unit/99 install all targets/main.c rename to test cases/unit/98 install all targets/main.c diff --git a/test cases/unit/99 install all targets/meson.build b/test cases/unit/98 install all targets/meson.build similarity index 100% rename from test cases/unit/99 install all targets/meson.build rename to test cases/unit/98 install all targets/meson.build diff --git a/test cases/unit/99 install all targets/script.py b/test cases/unit/98 install all targets/script.py similarity index 100% rename from test cases/unit/99 install all targets/script.py rename to test cases/unit/98 install all targets/script.py diff --git a/test cases/unit/99 install all targets/subdir/bar2-devel.h b/test cases/unit/98 install all targets/subdir/bar2-devel.h similarity index 100% rename from test cases/unit/99 install all targets/subdir/bar2-devel.h rename to test cases/unit/98 install all targets/subdir/bar2-devel.h diff --git a/test cases/unit/99 install all targets/subdir/foo2.in b/test cases/unit/98 install all targets/subdir/foo2.in similarity index 100% rename from test cases/unit/99 install all targets/subdir/foo2.in rename to test cases/unit/98 install all targets/subdir/foo2.in diff --git a/test cases/unit/99 install all targets/subdir/foo3-devel.h b/test cases/unit/98 install all targets/subdir/foo3-devel.h similarity index 100% rename from test cases/unit/99 install all targets/subdir/foo3-devel.h rename to test cases/unit/98 install all targets/subdir/foo3-devel.h diff --git a/test cases/unit/99 install all targets/subdir/lib.c b/test cases/unit/98 install all targets/subdir/lib.c similarity index 100% rename from test cases/unit/99 install all targets/subdir/lib.c rename to test cases/unit/98 install all targets/subdir/lib.c diff --git a/test cases/unit/99 install all targets/subdir/main.c b/test cases/unit/98 install all targets/subdir/main.c similarity index 100% rename from test cases/unit/99 install all targets/subdir/main.c rename to test cases/unit/98 install all targets/subdir/main.c diff --git a/test cases/unit/99 install all targets/subdir/meson.build b/test cases/unit/98 install all targets/subdir/meson.build similarity index 100% rename from test cases/unit/99 install all targets/subdir/meson.build rename to test cases/unit/98 install all targets/subdir/meson.build diff --git a/test cases/unit/99 install all targets/subdir/script.py b/test cases/unit/98 install all targets/subdir/script.py similarity index 100% rename from test cases/unit/99 install all targets/subdir/script.py rename to test cases/unit/98 install all targets/subdir/script.py diff --git a/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt b/test cases/unit/98 install all targets/subprojects/subproject/aaa.txt similarity index 100% rename from test cases/unit/99 install all targets/subprojects/subproject/aaa.txt rename to test cases/unit/98 install all targets/subprojects/subproject/aaa.txt diff --git a/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt b/test cases/unit/98 install all targets/subprojects/subproject/bbb.txt similarity index 100% rename from test cases/unit/99 install all targets/subprojects/subproject/bbb.txt rename to test cases/unit/98 install all targets/subprojects/subproject/bbb.txt diff --git a/test cases/unit/99 install all targets/subprojects/subproject/meson.build b/test cases/unit/98 install all targets/subprojects/subproject/meson.build similarity index 100% rename from test cases/unit/99 install all targets/subprojects/subproject/meson.build rename to test cases/unit/98 install all targets/subprojects/subproject/meson.build diff --git a/test cases/unit/100 custom target name/file.txt.in b/test cases/unit/99 custom target name/file.txt.in similarity index 100% rename from test cases/unit/100 custom target name/file.txt.in rename to test cases/unit/99 custom target name/file.txt.in diff --git a/test cases/unit/100 custom target name/meson.build b/test cases/unit/99 custom target name/meson.build similarity index 100% rename from test cases/unit/100 custom target name/meson.build rename to test cases/unit/99 custom target name/meson.build diff --git a/test cases/unit/100 custom target name/subdir/meson.build b/test cases/unit/99 custom target name/subdir/meson.build similarity index 100% rename from test cases/unit/100 custom target name/subdir/meson.build rename to test cases/unit/99 custom target name/subdir/meson.build diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 059be2d4f225..53a0042c27e6 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -474,7 +474,7 @@ def test_replace_unencodable_xml_chars_unit(self): ''' if not shutil.which('xmllint'): raise SkipTest('xmllint not installed') - testdir = os.path.join(self.unit_test_dir, '110 replace unencodable xml chars') + testdir = os.path.join(self.unit_test_dir, '111 replace unencodable xml chars') self.init(testdir) tests_command_output = self.run_tests() junit_xml_logs = Path(self.logdir, 'testlog.junit.xml') @@ -634,7 +634,7 @@ def test_forcefallback(self): self.run_tests() def test_implicit_forcefallback(self): - testdir = os.path.join(self.unit_test_dir, '96 implicit force fallback') + testdir = os.path.join(self.unit_test_dir, '95 implicit force fallback') with self.assertRaises(subprocess.CalledProcessError): self.init(testdir) self.init(testdir, extra_args=['--wrap-mode=forcefallback']) @@ -1958,7 +1958,7 @@ def check_pcfile(name, *, relocatable, levels=2): check_pcfile('libvartest2.pc', relocatable=False) self.wipe() - testdir_abs = os.path.join(self.unit_test_dir, '106 pkgconfig relocatable with absolute path') + testdir_abs = os.path.join(self.unit_test_dir, '105 pkgconfig relocatable with absolute path') self.init(testdir_abs) check_pcfile('libsimple.pc', relocatable=True, levels=3) @@ -2040,7 +2040,7 @@ def get_opt(): self.assertDictEqual(original, expected) def test_executable_names(self): - testdir = os.path.join(self.unit_test_dir, '119 executable suffix') + testdir = os.path.join(self.unit_test_dir, '121 executable suffix') self.init(testdir) self.build() exe1 = os.path.join(self.builddir, 'foo' + exe_suffix) @@ -2131,7 +2131,7 @@ def test_options_with_choices_changing(self) -> None: def test_options_listed_in_build_options(self) -> None: """Detect when changed options become listed in build options.""" - testdir = os.path.join(self.unit_test_dir, '112 list build options') + testdir = os.path.join(self.unit_test_dir, '113 list build options') out = self.init(testdir) for line in out.splitlines(): @@ -2236,9 +2236,9 @@ def test_error_location_path(self): for (t, f) in [ ('10 out of bounds', 'meson.build'), ('18 wrong plusassign', 'meson.build'), - ('59 bad option argument', 'meson_options.txt'), - ('97 subdir parse error', os.path.join('subdir', 'meson.build')), - ('98 invalid option file', 'meson_options.txt'), + ('57 bad option argument', 'meson_options.txt'), + ('95 subdir parse error', os.path.join('subdir', 'meson.build')), + ('96 invalid option file', 'meson_options.txt'), ]: tdir = os.path.join(self.src_root, 'test cases', 'failing', t) @@ -2369,7 +2369,7 @@ def test_check_module_linking(self): self.assertIn(msg, out) def test_mixed_language_linker_check(self): - testdir = os.path.join(self.unit_test_dir, '97 compiler.links file arg') + testdir = os.path.join(self.unit_test_dir, '96 compiler.links file arg') self.init(testdir) cmds = self.get_meson_log_compiler_checks() self.assertEqual(len(cmds), 5) @@ -4206,7 +4206,7 @@ def test_build_b_options(self) -> None: self.init(srcdir, extra_args=['-Dbuild.b_lto=true']) def test_install_skip_subprojects(self): - testdir = os.path.join(self.unit_test_dir, '92 install skip subprojects') + testdir = os.path.join(self.unit_test_dir, '91 install skip subprojects') self.init(testdir) self.build() @@ -4253,7 +4253,7 @@ def check_installed_files(extra_args, expected): check_installed_files(['--skip-subprojects', 'another'], all_expected) def test_adding_subproject_to_configure_project(self) -> None: - srcdir = os.path.join(self.unit_test_dir, '93 new subproject in configured project') + srcdir = os.path.join(self.unit_test_dir, '92 new subproject in configured project') self.init(srcdir) self.build() self.setconf('-Duse-sub=true') @@ -4303,7 +4303,7 @@ def test_clang_format_check(self): if not shutil.which('clang-format'): raise SkipTest('clang-format not found') - testdir = os.path.join(self.unit_test_dir, '94 clangformat') + testdir = os.path.join(self.unit_test_dir, '93 clangformat') newdir = os.path.join(self.builddir, 'testdir') shutil.copytree(testdir, newdir) self.new_builddir() @@ -4328,7 +4328,7 @@ def test_clang_format_check(self): self.build('clang-format-check') def test_custom_target_implicit_include(self): - testdir = os.path.join(self.unit_test_dir, '95 custominc') + testdir = os.path.join(self.unit_test_dir, '94 custominc') self.init(testdir) self.build() compdb = self.get_compdb() @@ -4368,7 +4368,7 @@ def test_env_flags_to_linker(self) -> None: self.assertEqual(sorted(link_args), sorted(['-flto'])) def test_install_tag(self) -> None: - testdir = os.path.join(self.unit_test_dir, '99 install all targets') + testdir = os.path.join(self.unit_test_dir, '98 install all targets') self.init(testdir) self.build() @@ -4539,7 +4539,7 @@ def test_install_script_dry_run(self): def test_introspect_install_plan(self): - testdir = os.path.join(self.unit_test_dir, '99 install all targets') + testdir = os.path.join(self.unit_test_dir, '98 install all targets') introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json') self.init(testdir) self.assertPathExists(introfile) @@ -4791,7 +4791,7 @@ def test_rust_rlib_linkage(self) -> None: }} ''') - testdir = os.path.join(self.unit_test_dir, '102 rlib linkage') + testdir = os.path.join(self.unit_test_dir, '101 rlib linkage') gen_file = os.path.join(testdir, 'lib.rs') with open(gen_file, 'w', encoding='utf-8') as f: f.write(template.format(0)) @@ -4839,7 +4839,7 @@ def test_bindgen_drops_invalid(self) -> None: return def test_custom_target_name(self): - testdir = os.path.join(self.unit_test_dir, '100 custom target name') + testdir = os.path.join(self.unit_test_dir, '99 custom target name') self.init(testdir) out = self.build() if self.backend is Backend.ninja: @@ -4900,7 +4900,7 @@ def test_configure_same_noop(self): oldmtime = newmtime def test_c_cpp_stds(self): - testdir = os.path.join(self.unit_test_dir, '114 c cpp stds') + testdir = os.path.join(self.unit_test_dir, '115 c cpp stds') self.init(testdir) # Invalid values should fail whatever compiler we have with self.assertRaises(subprocess.CalledProcessError): diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 024d4338a861..de86fa7fa3e3 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -1366,7 +1366,7 @@ def test_link_arg_fullname(self): see: https://github.com/mesonbuild/meson/issues/9000 https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a ''' - testdir = os.path.join(self.unit_test_dir, '98 link full name','libtestprovider') + testdir = os.path.join(self.unit_test_dir, '97 link full name','libtestprovider') oldprefix = self.prefix # install into installdir without using DESTDIR installdir = self.installdir @@ -1379,7 +1379,7 @@ def test_link_arg_fullname(self): self.new_builddir() env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), 'PKG_CONFIG_PATH': _prepend_pkg_config_path(os.path.join(installdir, self.libdir, 'pkgconfig'))} - testdir = os.path.join(self.unit_test_dir, '98 link full name','proguser') + testdir = os.path.join(self.unit_test_dir, '97 link full name','proguser') self.init(testdir,override_envvars=env) # test for link with full path @@ -1791,7 +1791,7 @@ def test_cmake_multilib(self): @skipUnless(is_linux() or is_osx(), 'Test only applicable to Linux and macOS') def test_install_strip(self): - testdir = os.path.join(self.unit_test_dir, '104 strip') + testdir = os.path.join(self.unit_test_dir, '103 strip') self.init(testdir) self.build() @@ -1847,7 +1847,7 @@ def test_freezing(self): @skipUnless(is_linux(), "Ninja file differs on different platforms") def test_complex_link_cases(self): - testdir = os.path.join(self.unit_test_dir, '113 complex link cases') + testdir = os.path.join(self.unit_test_dir, '114 complex link cases') self.init(testdir) self.build() with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as f: diff --git a/unittests/machinefiletests.py b/unittests/machinefiletests.py index 9e71810c9d2d..d2309f802322 100644 --- a/unittests/machinefiletests.py +++ b/unittests/machinefiletests.py @@ -375,7 +375,7 @@ def test_java_compiler(self): def test_java_classpath(self): if self.backend is not Backend.ninja: raise SkipTest('Jar is only supported with Ninja') - testdir = os.path.join(self.unit_test_dir, '111 classpath') + testdir = os.path.join(self.unit_test_dir, '112 classpath') self.init(testdir) self.build() one_build_path = get_classpath(os.path.join(self.builddir, 'one.jar')) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 204a22ba5302..f094e988a83d 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -39,7 +39,7 @@ def test_relative_find_program(self): Tests that find_program() with a relative path does not find the program in current workdir. ''' - testdir = os.path.join(self.unit_test_dir, '101 relative find program') + testdir = os.path.join(self.unit_test_dir, '100 relative find program') self.init(testdir, workdir=testdir) def test_invalid_option_names(self): @@ -75,11 +75,11 @@ def write_file(code: str): interp.process(fname) def test_python_dependency_without_pkgconfig(self): - testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') + testdir = os.path.join(self.unit_test_dir, '102 python without pkgconfig') self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) def test_debug_function_outputs_to_meson_log(self): - testdir = os.path.join(self.unit_test_dir, '105 debug function') + testdir = os.path.join(self.unit_test_dir, '104 debug function') log_msg = 'This is an example debug output, should only end up in debug log' output = self.init(testdir) @@ -250,7 +250,7 @@ def test_setup_loaded_modules(self): thing to do as new features are added, but keeping track of them is good. ''' - testdir = os.path.join(self.unit_test_dir, '114 empty project') + testdir = os.path.join(self.unit_test_dir, '116 empty project') self.init(testdir) self._run(self.meson_command + ['--internal', 'regenerate', '--profile-self', testdir, self.builddir]) @@ -265,7 +265,7 @@ def test_setup_loaded_modules(self): def test_meson_package_cache_dir(self): # Copy testdir into temporary directory to not pollute meson source tree. - testdir = os.path.join(self.unit_test_dir, '116 meson package cache dir') + testdir = os.path.join(self.unit_test_dir, '118 meson package cache dir') srcdir = os.path.join(self.builddir, 'srctree') shutil.copytree(testdir, srcdir) builddir = os.path.join(srcdir, '_build') @@ -274,7 +274,7 @@ def test_meson_package_cache_dir(self): def test_cmake_openssl_not_found_bug(self): """Issue #12098""" - testdir = os.path.join(self.unit_test_dir, '117 openssl cmake bug') + testdir = os.path.join(self.unit_test_dir, '119 openssl cmake bug') self.meson_native_files.append(os.path.join(testdir, 'nativefile.ini')) out = self.init(testdir, allow_fail=True) self.assertNotIn('Unhandled python exception', out) diff --git a/unittests/rewritetests.py b/unittests/rewritetests.py index c33884442675..7932fecae26a 100644 --- a/unittests/rewritetests.py +++ b/unittests/rewritetests.py @@ -402,7 +402,7 @@ def test_target_remove_extra_files(self): self.assertDictEqual(out, expected) def test_raw_printer_is_idempotent(self): - test_path = Path(self.unit_test_dir, '118 rewrite') + test_path = Path(self.unit_test_dir, '120 rewrite') meson_build_file = test_path / 'meson.build' # original_contents = meson_build_file.read_bytes() original_contents = meson_build_file.read_text(encoding='utf-8') diff --git a/unittests/windowstests.py b/unittests/windowstests.py index 37e92996d97a..be53d65a0d5d 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -195,7 +195,7 @@ def test_genvslite(self): if self.backend is not Backend.ninja: raise SkipTest('Test only applies when using the Ninja backend') - testdir = os.path.join(self.unit_test_dir, '115 genvslite') + testdir = os.path.join(self.unit_test_dir, '117 genvslite') env = get_fake_env(testdir, self.builddir, self.prefix) cc = detect_c_compiler(env, MachineChoice.HOST) From 20bcca39726803aba56fcc388332622d70605e1a Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 26 Oct 2023 22:09:30 +0300 Subject: [PATCH 391/855] Handle path behaviour change in Python 3.12. --- test cases/common/220 fs module/meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index 7f113d66eb48..80019631f6bc 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -39,7 +39,9 @@ assert(fs.expanduser('~/foo').endswith('foo'), 'expanduser with tail failed') # -- as_posix assert(fs.as_posix('/') == '/', 'as_posix idempotent') assert(fs.as_posix('\\') == '/', 'as_posix simple') -assert(fs.as_posix('\\\\') == '/', 'as_posix simple') +# Python 3.12 changed how these paths are handled, so deal with both. +drivepath = fs.as_posix('\\\\') +assert(drivepath == '/' or drivepath == '//', 'as_posix simple') assert(fs.as_posix('foo\\bar/baz') == 'foo/bar/baz', 'as_posix mixed slash') # -- is_absolute From bca31cffc2eec44fdb34d206df30753b276390c5 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 27 Oct 2023 00:07:15 +0300 Subject: [PATCH 392/855] Bump version number for RC1. --- 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 c2c49cfbda40..7e9d7d8be17a 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "July 2023" "meson 1.2.0" "User Commands" +.TH MESON "1" "October 2023" "meson 1.3.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index f91c5837fdf0..29a3d0eec165 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -61,7 +61,7 @@ # # 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.2.99' +version = '1.3.0.rc1' # 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 01368ffb293da009f3df139ebcdc5f9ac7557809 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 28 Oct 2023 21:53:49 -0400 Subject: [PATCH 393/855] simd module: fix regression that broke using only some simd variants Regression in commit a3d287c553b9598f010fe0755c5528ef62055e44. When a given kwarg is not specified, we want to not generate it as a simd variant. Since the default for buildtarget sources is `[]` it resulted in building a static library with no sources, and a warning stating that this was buggy and will eventually be removed. Fix this by teaching buildtarget sources to allow None, and defaulting to it specifically for the simd module. We can check this and then skip processing entirely. Fixes #12438 --- mesonbuild/interpreter/type_checking.py | 2 +- mesonbuild/modules/simd.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 296baca31bae..e7edc1939b18 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -470,7 +470,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus BT_SOURCES_KW: KwargInfo[SourcesVarargsType] = KwargInfo( 'sources', - ContainerTypeInfo(list, SOURCES_VARARGS), + (NoneType, ContainerTypeInfo(list, SOURCES_VARARGS)), listify=True, default=[], ) diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index bce89dd2d976..b8baf39ef34a 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -71,7 +71,7 @@ def __init__(self, interpreter: Interpreter): @typed_pos_args('simd.check', str) @typed_kwargs('simd.check', KwargInfo('compiler', Compiler, required=True), - *[BT_SOURCES_KW.evolve(name=iset) for iset in ISETS], + *[BT_SOURCES_KW.evolve(name=iset, default=None) for iset in ISETS], *[a for a in STATIC_LIB_KWS if a.name != 'sources'], allow_unknown=True) # Because we also accept STATIC_LIB_KWS, but build targets have not been completely ported to typed_pos_args/typed_kwargs. @permittedKwargs({'compiler', *ISETS, *build.known_stlib_kwargs}) # Also remove this, per above comment @@ -90,6 +90,8 @@ def check(self, state: ModuleState, args: T.Tuple[str], kwargs: CheckKw) -> T.Li for iset in ISETS: sources = kwargs[iset] + if sources is None: + continue compile_args = compiler.get_instruction_set_args(iset) if compile_args is None: From b2000620f42ee730c47fcd7b4e510928b635e724 Mon Sep 17 00:00:00 2001 From: Alaska Date: Sun, 29 Oct 2023 00:06:28 +0200 Subject: [PATCH 394/855] cargo subprojects: don't assume each target has dependencies Previously, creating a meson wrap with "method=cargo" for https://github.com/sunfishcode/is-terminal would fail, because its Cargo.toml contains a [target] section without dependencies. Instead, we now fall back to an empty list in case of no specified dependencies (like everywhere else in "_convert_manifest") --- mesonbuild/cargo/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 9e5910c093e4..a6634ac1b2a8 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -292,7 +292,7 @@ def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = [Benchmark(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bench', {})], [Example(**_fixup_raw_mappings(b)) for b in raw_manifest.get('example', {})], raw_manifest.get('features', {}), - {k: {k2: Dependency.from_raw(v2) for k2, v2 in v['dependencies'].items()} + {k: {k2: Dependency.from_raw(v2) for k2, v2 in v.get('dependencies', {}).items()} for k, v in raw_manifest.get('target', {}).items()}, subdir, path, From 99fadccd29c709e652f0fab5b5738fadfc4a2ebe Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Mon, 11 Sep 2023 07:38:01 +0100 Subject: [PATCH 395/855] completions: bash: add a bunch of missing completion options --- data/shell-completions/bash/meson | 138 +++++++++++------------------- 1 file changed, 51 insertions(+), 87 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index 3dd16cc49167..595b5b5a5ad7 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -168,6 +168,55 @@ _meson_compgen_options() { return 0 } +_meson_common_setup_configure_longopts=( + help + prefix + bindir + datadir + includedir + infodir + libdir + licensedir + libexecdir + localedir + localstatedir + mandir + sbindir + sharedstatedir + sysconfdir + auto-features + backend + genvslite + buildtype + debug + default-library + errorlogs + install-umask + layout + optimization + prefer-static + stdsplit + strip + unity + unity-size + warnlevel + werror + wrap-mode + force-fallback-for + vsenv + pkgconfig.relocatable + python.bytecompile + python.install-env + python.platlibdir + python.purelibdir + python.allow-limited-api + pkg-config-path + build.pkg-config-path + cmake-prefix-path + build.cmake-prefix-path + clearcache +) + _meson-setup() { shortopts=( h @@ -175,53 +224,10 @@ _meson-setup() { v ) - # backend-startup-project is currently VS backend only. - longopts=( - help - prefix - bindir - datadir - includedir - infodir - libdir - libexecdir - licensedir - localedir - localstatedir - mandir - sbindir - sharedstatedir - sysconfdir - auto-features - backend - buildtype - debug - default-library - errorlogs - install-umask - layout - optimization - prefer-static - stdsplit - strip - unity - unity-size - warnlevel - werror - wrap-mode - force-fallback-for - pkgconfig.relocatable - python.install-env - python.platlibdir - python.purelibdir - pkg-config-path - build.pkg-config-path - cmake-prefix-path - build.cmake-prefix-path + ${_meson_common_setup_configure_longopts[@]} native-file cross-file - vsenv version fatal-meson-warnings reconfigure @@ -266,49 +272,7 @@ _meson-configure() { ) longopts=( - help - prefix - bindir - datadir - includedir - infodir - libdir - libexecdir - licensedir - localedir - localstatedir - mandir - sbindir - sharedstatedir - sysconfdir - auto-features - backend - buildtype - debug - default-library - errorlogs - install-umask - layout - optimization - prefer-static - stdsplit - strip - unity - unity-size - warnlevel - werror - wrap-mode - force-fallback-for - backend-startup-project - pkgconfig.relocatable - python.install-env - python.platlibdir - python.purelibdir - pkg-config-path - build.pkg-config-path - cmake-prefix-path - build.cmake-prefix-path - clearcache + ${_meson_common_setup_configure_longopts[@]} no-pager ) From ce691f8c98aeb72a246c4d6e9d60ed9ec88a6afd Mon Sep 17 00:00:00 2001 From: Luke Elliott Date: Mon, 11 Sep 2023 07:37:51 +0100 Subject: [PATCH 396/855] Add comments suggesting to keep shell completion scripts up-to-date near cmd line argument code --- mesonbuild/coredata.py | 1 + mesonbuild/mcompile.py | 2 ++ mesonbuild/mconf.py | 2 ++ mesonbuild/mdevenv.py | 2 ++ mesonbuild/mdist.py | 2 ++ mesonbuild/minit.py | 2 ++ mesonbuild/minstall.py | 2 ++ mesonbuild/mintro.py | 2 ++ mesonbuild/msetup.py | 2 ++ mesonbuild/msubprojects.py | 2 ++ mesonbuild/mtest.py | 2 ++ mesonbuild/munstable_coredata.py | 2 ++ mesonbuild/rewriter.py | 2 ++ mesonbuild/scripts/env2mfile.py | 2 ++ mesonbuild/wrap/wraptool.py | 2 ++ 15 files changed, 29 insertions(+) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 29a3d0eec165..4fd82833e0d6 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1332,6 +1332,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi # Update `docs/markdown/Builtin-options.md` after changing the options below # Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required. +# Please also update completion scripts in $MESONSRC/data/shell-completions/ BUILTIN_DIR_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([ (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')), diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 6721beb0b008..60d71333b08d 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -301,6 +301,8 @@ def get_parsed_args_xcode(options: 'argparse.Namespace', builddir: Path) -> T.Tu cmd += options.xcode_args return cmd, None +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: 'argparse.ArgumentParser') -> None: """Add compile specific arguments.""" parser.add_argument( diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 9f6c6856f5fc..04f6d5bcbd5b 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -35,6 +35,8 @@ # cannot be TV_Loggable, because non-ansidecorators do direct string concat LOGLINE = T.Union[str, mlog.AnsiDecorator] +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: 'argparse.ArgumentParser') -> None: coredata.register_builtin_arguments(parser) parser.add_argument('builddir', nargs='?', default='.') diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index aea5da2e00dd..b60d7a5729d8 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -18,6 +18,8 @@ POWERSHELL_EXES = {'pwsh.exe', 'powershell.exe'} +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('-C', dest='builddir', type=Path, default='.', help='Path to build directory') diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 089056b35a79..c46670e0c411 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -48,6 +48,8 @@ 'xztar': '.tar.xz', 'zip': '.zip'} +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('-C', dest='wd', action=RealPathAction, help='directory to cd into before running') diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index abe8104d022d..39027fd11497 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -153,6 +153,8 @@ def autodetect_options(options: Arguments, sample: bool = False) -> None: raise SystemExit("Can't autodetect language, please specify it with -l.") print("Detected language: " + options.language) +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: 'argparse.ArgumentParser') -> None: ''' Here we add args for that the user can passed when making a new diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 5f8629b7fe47..bf6f7a1204c1 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -72,6 +72,8 @@ class ArgumentType(Protocol): selinux_updates: T.List[str] = [] +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('-C', dest='wd', action=RealPathAction, help='directory to cd into before running') diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index e3f2e51b17f0..a980c7c55e3d 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -90,6 +90,8 @@ def get_meson_introspection_types(coredata: T.Optional[cdata.CoreData] = None, ('tests', IntroCommand('List all unit tests', func=lambda: list_tests(testdata))), ]) +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: intro_types = get_meson_introspection_types() for key, val in intro_types.items(): diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 4ff60000ff06..f8e242ae2bf2 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -31,6 +31,8 @@ ''' +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: coredata.register_builtin_arguments(parser) parser.add_argument('--native-file', diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index fb9a847139c9..ea2eb2cc39bb 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -657,6 +657,8 @@ def add_wrap_update_parser(subparsers: 'SubParsers') -> argparse.ArgumentParser: p.set_defaults(pre_func=Runner.pre_update_wrapdb) return p +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: subparsers = parser.add_subparsers(title='Commands', dest='command') subparsers.required = True diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 57bf28fb6fcd..c1ce1e09efc0 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -124,6 +124,8 @@ def determine_worker_count() -> int: num_workers = 1 return num_workers +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('--maxfail', default=0, type=int, help='Number of failing tests before aborting the ' diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py index e6c543b81bb8..ba6ffb3ebe7c 100644 --- a/mesonbuild/munstable_coredata.py +++ b/mesonbuild/munstable_coredata.py @@ -21,6 +21,8 @@ import pprint import textwrap +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser): parser.add_argument('--all', action='store_true', dest='all', default=False, help='Show data not used by current backend.') diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index a86b97eccabb..d6509fc971ff 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -38,6 +38,8 @@ class RewriterException(MesonException): pass +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser, formatter=None): parser.add_argument('-s', '--sourcedir', type=str, default='.', metavar='SRCDIR', help='Path to source directory.') parser.add_argument('-V', '--verbose', action='store_true', default=False, help='Enable verbose output') diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index 1a6d0ce97ba4..8811b6cf813d 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -31,6 +31,8 @@ def has_for_build() -> bool: return True return False +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: 'argparse.ArgumentParser') -> None: parser.add_argument('--debarch', default=None, help='The dpkg architecture to generate.') diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index c009aa1c6e01..c4ff9dbbb8c4 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -28,6 +28,8 @@ if T.TYPE_CHECKING: import argparse +# Note: when adding arguments, please also add them to the completion +# scripts in $MESONSRC/data/shell-completions/ def add_arguments(parser: 'argparse.ArgumentParser') -> None: subparsers = parser.add_subparsers(title='Commands', dest='command') subparsers.required = True From f4d19db25e3183833a5e2d77ef5ab40b9b523144 Mon Sep 17 00:00:00 2001 From: Aditya Vidyadhar Kamath Date: Tue, 10 Oct 2023 08:13:14 -0500 Subject: [PATCH 397/855] Use target.aix_so_archive to decide to archive shared library in AIX Previously, AIX support was updated to archive shared libraries per AIX platform conventions, which expect .a files that contain .so files. This is usually correct, but an edge case occurs for loadable plugins, e.g. what meson creates for `shared_module()`. A notable example is python extensions (SciPy, for example). These should *not* be archived, because the .so file itself needs to be loaded as a plugin. For example, SciPy fails to import in the python interpreter. Handle this by differentiating between plugins and regular libraries, and only archiving when safe to do so. Fixes #12219 --- mesonbuild/backend/backends.py | 3 +++ mesonbuild/backend/ninjabackend.py | 12 ++++-------- mesonbuild/build.py | 6 ++++++ mesonbuild/minstall.py | 3 ++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index dd9e6ee6cf28..8cf738dbf436 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -355,6 +355,9 @@ def get_target_filename_for_linking(self, target: T.Union[build.Target, build.Cu # On all other platforms, we link to the library directly. if isinstance(target, build.SharedLibrary): link_lib = target.get_import_filename() or target.get_filename() + # In AIX, if we archive .so, the blibpath must link to archived shared library otherwise to the .so file. + if mesonlib.is_aix() and target.aix_so_archive: + link_lib = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', link_lib.replace('.so', '.a')) return os.path.join(self.get_target_dir(target), link_lib) elif isinstance(target, build.StaticLibrary): return os.path.join(self.get_target_dir(target), target.get_filename()) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0c984eadf5c3..0c126006c7a5 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1060,8 +1060,9 @@ def generate_target(self, target): #In AIX, we archive shared libraries. If the instance is a shared library, we add a command to archive the shared library #object and create the build element. if isinstance(target, build.SharedLibrary) and self.environment.machines[target.for_machine].is_aix(): - elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname]) - self.add_build(elem) + if target.aix_so_archive: + elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname]) + self.add_build(elem) def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: if mesonlib.version_compare(self.ninja_version, '<1.10.0'): @@ -3457,11 +3458,6 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. else: dependencies = target.get_dependencies() internal = self.build_target_link_arguments(linker, dependencies) - #In AIX since shared libraries are archived the dependencies must - #depend on .a file with the .so and not directly on the .so file. - if self.environment.machines[target.for_machine].is_aix(): - for i, val in enumerate(internal): - internal[i] = linker.get_archive_name(val) commands += internal # Only non-static built targets need link args and link dependencies if not isinstance(target, build.StaticLibrary): @@ -3667,7 +3663,7 @@ def generate_ending(self) -> None: # Add the first output of each target to the 'all' target so that # they are all built #Add archive file if shared library in AIX for build all. - if isinstance(t, build.SharedLibrary): + if isinstance(t, build.SharedLibrary) and t.aix_so_archive: if self.environment.machines[t.for_machine].is_aix(): linker, stdlib_args = self.determine_linker_and_stdlib_args(t) t.get_outputs()[0] = linker.get_archive_name(t.get_outputs()[0]) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 4fc409a8de9d..8ae54754b639 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2171,6 +2171,9 @@ class SharedLibrary(BuildTarget): typename = 'shared library' + # Used by AIX to decide whether to archive shared library or not. + aix_so_archive = True + def __init__( self, name: str, @@ -2436,6 +2439,9 @@ class SharedModule(SharedLibrary): typename = 'shared module' + # Used by AIX to not archive shared library for dlopen mechanism + aix_so_archive = False + def __init__( self, name: str, diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index bf6f7a1204c1..297afb4e23d5 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -722,8 +722,9 @@ def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix # In AIX, we archive our shared libraries. When we install any package in AIX we need to # install the archive in which the shared library exists. The below code does the same. # We change the .so files having lt_version or so_version to archive file install. + # If .so does not exist then it means it is in the archive. Otherwise it is a .so that exists. if is_aix(): - if '.so' in t.fname: + if not os.path.exists(t.fname) and '.so' in t.fname: t.fname = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', t.fname.replace('.so', '.a')) if not self.should_install(t): continue From cfec255027ca7c928defcc665a12e91b439c7c3f Mon Sep 17 00:00:00 2001 From: Aditya Vidyadhar Kamath Date: Sun, 29 Oct 2023 23:02:24 -0500 Subject: [PATCH 398/855] Fix traceback on AIX in shlib archiving code A compiler may not have a linker: ``` 'NoneType' object has no attribute 'get_command_to_archive_shlib' ``` --- mesonbuild/compilers/compilers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index fb399b11422f..a7bb6c417932 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -962,6 +962,8 @@ def get_archive_name(self, filename: str) -> str: return self.linker.get_archive_name(filename) def get_command_to_archive_shlib(self) -> T.List[str]: + if not self.linker: + return [] return self.linker.get_command_to_archive_shlib() def thread_flags(self, env: 'Environment') -> T.List[str]: From 3500349df16908daed8788687af59a0521c074d4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 12 Oct 2023 12:54:24 -0400 Subject: [PATCH 399/855] rust: Fix link arguments Reduce code duplication by iterating target.get_dependencies() instead of iterating target.link_targets and target.link_whole_targets separately. This has the extra benefit of taking into account transitive dependencies. - For indirect C ABI static libraries, this adds missing "-l static=" arguments. - For indirect Rust ABI dependencies, this adds missing "-L" arguments. - Verbatim modifier was used only for link_whole_targets, it's now always used when available. Fixes: #11694 --- mesonbuild/backend/ninjabackend.py | 89 +++++++++++++++--------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0c126006c7a5..faf3acfc0671 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1949,8 +1949,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: args += ['--emit', f'dep-info={depfile}', '--emit', f'link={target_name}'] args += ['--out-dir', self.get_target_private_dir(target)] args += target.get_extra_args('rust') - linkdirs = mesonlib.OrderedSet() - external_deps = target.external_deps.copy() # Rustc always use non-debug Windows runtime. Inject the one selected # by Meson options instead. @@ -1963,35 +1961,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: except KeyError: pass - # TODO: we likely need to use verbatim to handle name_prefix and name_suffix - for d in target.link_targets: - linkdirs.add(d.subdir) - # staticlib and cdylib provide a plain C ABI, i.e. contain no Rust - # metadata. As such they should be treated like any other external - # link target - if d.uses_rust() and d.rust_crate_type not in ['staticlib', 'cdylib']: - # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust - # dependency, so that collisions with libraries in rustc's - # sysroot don't cause ambiguity - d_name = self._get_rust_dependency_name(target, d) - args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] - project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) - continue - - if isinstance(d, build.StaticLibrary): - # Rustc doesn't follow Meson's convention that static libraries - # are called .a, and import libraries are .lib, so we have to - # manually handle that. - if rustc.linker.id in {'link', 'lld-link'}: - args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}'] - else: - args += ['-l', f'static={d.name}'] - external_deps.extend(d.external_deps) - else: - # Rust uses -l for non rust dependencies, but we still need to - # add dylib=foo - args += ['-l', f'dylib={d.name}'] - # Since 1.61.0 Rust has a special modifier for whole-archive linking, # before that it would treat linking two static libraries as # whole-archive linking. However, to make this work we have to disable @@ -1999,48 +1968,77 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # have to hope that the default cases of +whole-archive are sufficient. # See: https://github.com/rust-lang/rust/issues/99429 if mesonlib.version_compare(rustc.version, '>= 1.63.0'): - whole_archive = ':+whole-archive,-bundle' + whole_archive = '+whole-archive,-bundle' else: whole_archive = '' if mesonlib.version_compare(rustc.version, '>= 1.67.0'): - verbatim = ',+verbatim' + verbatim = '+verbatim' else: verbatim = '' - for d in target.link_whole_targets: + linkdirs = mesonlib.OrderedSet() + external_deps = target.external_deps.copy() + target_deps = target.get_dependencies() + for d in target_deps: linkdirs.add(d.subdir) - if d.uses_rust(): + if d.uses_rust_abi(): + if d not in itertools.chain(target.link_targets, target.link_whole_targets): + # Indirect Rust ABI dependency, we only need its path in linkdirs. + continue # specify `extern CRATE_NAME=OUTPUT_FILE` for each Rust # dependency, so that collisions with libraries in rustc's # sysroot don't cause ambiguity d_name = self._get_rust_dependency_name(target, d) args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) - else: - if rustc.linker.id in {'link', 'lld-link'}: - if verbatim: - # If we can use the verbatim modifier, then everything is great - args += ['-l', f'static{whole_archive}{verbatim}={d.get_outputs()[0]}'] - elif isinstance(target, build.StaticLibrary): + continue + + # Link a C ABI library + + if isinstance(d, build.StaticLibrary): + external_deps.extend(d.external_deps) + + lib = None + modifiers = [] + link_whole = d in target.link_whole_targets + if link_whole and whole_archive: + modifiers.append(whole_archive) + if verbatim: + modifiers.append(verbatim) + lib = self.get_target_filename_for_linking(d) + elif rustc.linker.id in {'link', 'lld-link'} and isinstance(d, build.StaticLibrary): + # Rustc doesn't follow Meson's convention that static libraries + # are called .a, and import libraries are .lib, so we have to + # manually handle that. + if link_whole: + if isinstance(target, build.StaticLibrary): # If we don't, for static libraries the only option is # to make a copy, since we can't pass objects in, or # directly affect the archiver. but we're not going to # do that given how quickly rustc versions go out of # support unless there's a compelling reason to do so. # This only affects 1.61–1.66 - mlog.warning('Due to limitations in Rustc versions 1.61–1.66 and meson library naming', + mlog.warning('Due to limitations in Rustc versions 1.61–1.66 and meson library naming,', 'whole-archive linking with MSVC may or may not work. Upgrade rustc to', '>= 1.67. A best effort is being made, but likely won\'t work') - args += ['-l', f'static={d.name}'] + lib = d.name else: # When doing dynamic linking (binaries and [c]dylibs), # we can instead just proxy the correct arguments to the linker for link_whole_arg in rustc.linker.get_link_whole_for([self.get_target_filename_for_linking(d)]): args += ['-C', f'link-arg={link_whole_arg}'] else: - args += ['-l', f'static{whole_archive}={d.name}'] - external_deps.extend(d.external_deps) + args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}'] + else: + lib = d.name + + if lib: + _type = 'static' if isinstance(d, build.StaticLibrary) else 'dylib' + if modifiers: + _type += ':' + ','.join(modifiers) + args += ['-l', f'{_type}={lib}'] + for e in external_deps: for a in e.get_link_args(): if a in rustc.native_static_libs: @@ -2068,7 +2066,6 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # library need to link with their stdlibs (C++ and Fortran, for example) args.extend(target.get_used_stdlib_args('rust')) - target_deps = target.get_dependencies() has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps) has_rust_shared_deps = any(dep.uses_rust() and dep.rust_crate_type == 'dylib' From 204563751ed907cd507d3a1a2f48bd8c22b5bb97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 23 Apr 2023 19:35:58 +0300 Subject: [PATCH 400/855] rust: Add unit test for transitive rust dependencies --- .../rust/20 transitive dependencies/liba/lib.rs | 3 +++ .../rust/20 transitive dependencies/liba/meson.build | 5 +++++ .../rust/20 transitive dependencies/libb/lib.rs | 3 +++ .../rust/20 transitive dependencies/libb/meson.build | 6 ++++++ test cases/rust/20 transitive dependencies/main.rs | 3 +++ .../rust/20 transitive dependencies/meson.build | 12 ++++++++++++ 6 files changed, 32 insertions(+) create mode 100644 test cases/rust/20 transitive dependencies/liba/lib.rs create mode 100644 test cases/rust/20 transitive dependencies/liba/meson.build create mode 100644 test cases/rust/20 transitive dependencies/libb/lib.rs create mode 100644 test cases/rust/20 transitive dependencies/libb/meson.build create mode 100644 test cases/rust/20 transitive dependencies/main.rs create mode 100644 test cases/rust/20 transitive dependencies/meson.build diff --git a/test cases/rust/20 transitive dependencies/liba/lib.rs b/test cases/rust/20 transitive dependencies/liba/lib.rs new file mode 100644 index 000000000000..0fc8ce55f90a --- /dev/null +++ b/test cases/rust/20 transitive dependencies/liba/lib.rs @@ -0,0 +1,3 @@ +pub fn foo() -> i32 { + 123 +} diff --git a/test cases/rust/20 transitive dependencies/liba/meson.build b/test cases/rust/20 transitive dependencies/liba/meson.build new file mode 100644 index 000000000000..b32822db995f --- /dev/null +++ b/test cases/rust/20 transitive dependencies/liba/meson.build @@ -0,0 +1,5 @@ +liba = static_library('liba', 'lib.rs', + rust_crate_type : 'rlib', +) + +liba_dep = declare_dependency(link_with : liba) diff --git a/test cases/rust/20 transitive dependencies/libb/lib.rs b/test cases/rust/20 transitive dependencies/libb/lib.rs new file mode 100644 index 000000000000..e97463b92eb9 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/libb/lib.rs @@ -0,0 +1,3 @@ +pub fn bar() -> i32 { + 2 * liba::foo() +} diff --git a/test cases/rust/20 transitive dependencies/libb/meson.build b/test cases/rust/20 transitive dependencies/libb/meson.build new file mode 100644 index 000000000000..67947e73afa2 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/libb/meson.build @@ -0,0 +1,6 @@ +libb = static_library('libb', 'lib.rs', + rust_crate_type : 'rlib', + dependencies : [liba_dep], +) + +libb_dep = declare_dependency(link_with : libb) diff --git a/test cases/rust/20 transitive dependencies/main.rs b/test cases/rust/20 transitive dependencies/main.rs new file mode 100644 index 000000000000..4b248456c148 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", libb::bar()); +} diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/20 transitive dependencies/meson.build new file mode 100644 index 000000000000..2f378f88fecd --- /dev/null +++ b/test cases/rust/20 transitive dependencies/meson.build @@ -0,0 +1,12 @@ +project('transitive dependencies', 'rust', + version : '1.0.0', + meson_version : '>= 1.0.0', + default_options : ['rust_std=2018'], +) + +subdir('liba') +subdir('libb') + +main = executable('main', 'main.rs', + dependencies : [libb_dep], +) From de03bf51d8fc704728d4bf0e8feb90e545f964c5 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 12 Oct 2023 18:02:13 -0400 Subject: [PATCH 401/855] rust: Do not use +verbatim on MacOS It seems broken and fails on our CI: https://github.com/rust-lang/rust/issues/116674 --- mesonbuild/backend/ninjabackend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index faf3acfc0671..41bdf4cc688e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1972,7 +1972,8 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: else: whole_archive = '' - if mesonlib.version_compare(rustc.version, '>= 1.67.0'): + # FIXME: Seems broken on MacOS: https://github.com/rust-lang/rust/issues/116674 + if mesonlib.version_compare(rustc.version, '>= 1.67.0') and not mesonlib.is_osx(): verbatim = '+verbatim' else: verbatim = '' From 06b9d1e75a142bb54282042a993bef5f9aa57138 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 2 Nov 2023 11:28:57 -0400 Subject: [PATCH 402/855] rust: proc-macro should be ignored in transitive dependencies Fixes: #12459 --- mesonbuild/build.py | 2 ++ .../rust/20 transitive dependencies/foo.c | 8 ++++++++ .../rust/20 transitive dependencies/foo.rs | 9 +++++++++ .../rust/20 transitive dependencies/meson.build | 17 ++++++++++++++++- .../rust/20 transitive dependencies/proc.rs | 7 +++++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test cases/rust/20 transitive dependencies/foo.c create mode 100644 test cases/rust/20 transitive dependencies/foo.rs create mode 100644 test cases/rust/20 transitive dependencies/proc.rs diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8ae54754b639..9283bca97f96 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1299,6 +1299,8 @@ def get_dependencies_recurse(self, result: OrderedSet[Target], include_internals for t in self.link_targets: if t in result: continue + if isinstance(t, SharedLibrary) and t.rust_crate_type == 'proc-macro': + continue if include_internals or not t.is_internal(): result.add(t) if isinstance(t, StaticLibrary): diff --git a/test cases/rust/20 transitive dependencies/foo.c b/test cases/rust/20 transitive dependencies/foo.c new file mode 100644 index 000000000000..e40878a87709 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/foo.c @@ -0,0 +1,8 @@ +#include + +uint32_t foo_rs(void); + +int main(void) +{ + return foo_rs() == 42 ? 0 : 1; +} diff --git a/test cases/rust/20 transitive dependencies/foo.rs b/test cases/rust/20 transitive dependencies/foo.rs new file mode 100644 index 000000000000..8e3863853f9d --- /dev/null +++ b/test cases/rust/20 transitive dependencies/foo.rs @@ -0,0 +1,9 @@ +extern crate pm; +use pm::make_answer; + +make_answer!(); + +#[no_mangle] +pub fn foo_rs() -> u32 { + answer() +} diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/20 transitive dependencies/meson.build index 2f378f88fecd..e5354b8f6f13 100644 --- a/test cases/rust/20 transitive dependencies/meson.build +++ b/test cases/rust/20 transitive dependencies/meson.build @@ -1,4 +1,4 @@ -project('transitive dependencies', 'rust', +project('transitive dependencies', 'rust', 'c', version : '1.0.0', meson_version : '>= 1.0.0', default_options : ['rust_std=2018'], @@ -10,3 +10,18 @@ subdir('libb') main = executable('main', 'main.rs', dependencies : [libb_dep], ) + +# Since foo-rs is a static library, its dependencies are normally added to +# footest link command. However, since pm is a proc-macro, footest should not +# link with it. In native build this is an harmless overlinking, but in cross +# building foo and pm are for different arch and it would fail to link. +rust = import('rust') +pm = rust.proc_macro('pm', 'proc.rs') +foo = static_library('foo-rs', 'foo.rs', + rust_abi: 'c', + link_with: pm, +) +exe = executable('footest', 'foo.c', + link_with: foo, +) +test('footest', exe) diff --git a/test cases/rust/20 transitive dependencies/proc.rs b/test cases/rust/20 transitive dependencies/proc.rs new file mode 100644 index 000000000000..53935e45d17f --- /dev/null +++ b/test cases/rust/20 transitive dependencies/proc.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} From 74712f2dbc3e0f04e6458c6ffe129187dd4726bf Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Tue, 31 Oct 2023 16:42:30 +0100 Subject: [PATCH 403/855] scan-build: Exclude subprojects from scan-build report When a user invokes the scan-build target that Meson generates all subprojects are included in the resulting report. This commit modifies the invocation of scan-build to exclude all bugs that scan-build finds in the subprojects from the final report. A release note has also been added describing the changed behaviour. --- .../snippets/subprojects_excluded_from_scanbuild.md | 4 ++++ mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/scripts/scanbuild.py | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/subprojects_excluded_from_scanbuild.md diff --git a/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md b/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md new file mode 100644 index 000000000000..d740006be248 --- /dev/null +++ b/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md @@ -0,0 +1,4 @@ +## Subprojects excluded from scan-build reports + +The `scan-build` target, created when using the `ninja` backend with `scan-build` +present, now excludes bugs found in subprojects from its final report. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 41bdf4cc688e..0f630a6b6d2d 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3581,7 +3581,7 @@ def generate_scanbuild(self) -> None: if 'scan-build' in self.all_outputs: return cmd = self.environment.get_build_command() + \ - ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \ + ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir, self.build.get_subproject_dir()] + \ self.environment.get_build_command() + self.get_user_option_args() elem = self.create_phony_target('scan-build', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py index 9cfc75dc388d..be60024da329 100644 --- a/mesonbuild/scripts/scanbuild.py +++ b/mesonbuild/scripts/scanbuild.py @@ -24,12 +24,12 @@ from ast import literal_eval import os -def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, logdir: Path, args: T.List[str]) -> int: +def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, logdir: Path, subprojdir: Path, args: T.List[str]) -> int: # In case of problems leave the temp directory around # so it can be debugged. scandir = tempfile.mkdtemp(dir=str(privdir)) meson_cmd = exelist + args - build_cmd = exelist + ['-o', str(logdir)] + detect_ninja() + ['-C', scandir] + build_cmd = exelist + ['--exclude', str(subprojdir), '-o', str(logdir)] + detect_ninja() + ['-C', scandir] rc = subprocess.call(meson_cmd + [str(srcdir), scandir]) if rc != 0: return rc @@ -41,8 +41,9 @@ def scanbuild(exelist: T.List[str], srcdir: Path, blddir: Path, privdir: Path, l def run(args: T.List[str]) -> int: srcdir = Path(args[0]) bldpath = Path(args[1]) + subprojdir = srcdir / Path(args[2]) blddir = args[1] - meson_cmd = args[2:] + meson_cmd = args[3:] privdir = bldpath / 'meson-private' logdir = bldpath / 'meson-logs' / 'scanbuild' shutil.rmtree(str(logdir), ignore_errors=True) @@ -63,4 +64,4 @@ def run(args: T.List[str]) -> int: print('Could not execute scan-build "%s"' % ' '.join(exelist)) return 1 - return scanbuild(exelist, srcdir, bldpath, privdir, logdir, meson_cmd) + return scanbuild(exelist, srcdir, bldpath, privdir, logdir, subprojdir, meson_cmd) From fb1c6e32f41277540b8ab51b1b4223ec68d18821 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 29 Oct 2023 22:04:53 -0400 Subject: [PATCH 404/855] Fine-tune the error message when trying to build outside the project root We try to backtrack through the filesystem to find the correct directory to build in, and suggest this as a possible diagnostic. However, our current heuristic relies on parsing the raw file with string matching to see if it starts with `project(`, and this may or may not actually work. Instead, do a bit of recursion and parse each candidate with mparser, then check if the first node of *that* file is a project() function. This makes us resilient to a common case: where the root meson.build is entirely valid, but, the first line is a comment containing e.g. SPDX license headers and a simple string comparison simply does not cut it. Fixes the bad error message from #12441, which was supposed to provide more guidance but did not. --- mesonbuild/interpreterbase/interpreterbase.py | 28 +++++++++++++------ unittests/platformagnostictests.py | 8 ++++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index ea6e37ca67ae..315bdf4031c6 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -132,20 +132,30 @@ def parse_project(self) -> None: self.evaluate_codeblock(self.ast, end=1) def sanity_check_ast(self) -> None: - if not isinstance(self.ast, mparser.CodeBlockNode): - raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.') - if not self.ast.lines: - raise InvalidCode('No statements in code.') - first = self.ast.lines[0] - if not isinstance(first, mparser.FunctionNode) or first.func_name.value != 'project': + def _is_project(ast: mparser.CodeBlockNode) -> object: + if not isinstance(ast, mparser.CodeBlockNode): + raise InvalidCode('AST is of invalid type. Possibly a bug in the parser.') + if not ast.lines: + raise InvalidCode('No statements in code.') + first = ast.lines[0] + return isinstance(first, mparser.FunctionNode) and first.func_name.value == 'project' + + if not _is_project(self.ast): p = pathlib.Path(self.source_root).resolve() found = p for parent in p.parents: if (parent / 'meson.build').is_file(): with open(parent / 'meson.build', encoding='utf-8') as f: - if f.readline().startswith('project('): - found = parent - break + code = f.read() + + try: + ast = mparser.Parser(code, 'empty').parse() + except mparser.ParseException: + continue + + if _is_project(ast): + found = parent + break else: break diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index f094e988a83d..1f4ea7ea07e0 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -278,3 +278,11 @@ def test_cmake_openssl_not_found_bug(self): self.meson_native_files.append(os.path.join(testdir, 'nativefile.ini')) out = self.init(testdir, allow_fail=True) self.assertNotIn('Unhandled python exception', out) + + 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) + + self.assertIn('first statement must be a call to project()', out) + # provide guidance diagnostics by finding a file whose first AST statement is project() + self.assertIn(f'Did you mean to run meson from the directory: "{testdir}"?', out) From 2d538c58cb7626cf3d799761dd9444f1aed9ba40 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 4 Nov 2023 13:12:07 +0100 Subject: [PATCH 405/855] Fix visibility attribute support check for GCC on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit has_function_attribute() depends on -Wattributes being emitted when an attribute is not supported by the compiler. In case of GCC on Window (at least) there is no warning in case the attribute is used on a declaration. Only once there is also a function definition does it emit a warning like: a.c: In function ‘foo’: a.c:8:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes] 8 | } To fix this add a dummy function definition to all visibility compiler checks in meson. The tests in "197 function attributes" only checked for positive return result on on-msvc compilers, except one special case for dllexport/dllimport. Refactor the tests a bit so one can specify also a negative expected result, and add tests for all visibility attribute variants. --- mesonbuild/compilers/c_function_attributes.py | 14 +++--- .../197 function attributes/meson.build | 43 +++++++++++++------ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/mesonbuild/compilers/c_function_attributes.py b/mesonbuild/compilers/c_function_attributes.py index 71ee9b22a75d..eec872b5f0b1 100644 --- a/mesonbuild/compilers/c_function_attributes.py +++ b/mesonbuild/compilers/c_function_attributes.py @@ -103,17 +103,17 @@ 'vector_size': '__attribute__((vector_size(32))); int foo(void) { return 0; }', 'visibility': ''' - int foo_def(void) __attribute__((visibility("default"))); - int foo_hid(void) __attribute__((visibility("hidden"))); - int foo_int(void) __attribute__((visibility("internal")));''', + int foo_def(void) __attribute__((visibility("default"))); int foo_def(void) { return 0; } + int foo_hid(void) __attribute__((visibility("hidden"))); int foo_hid(void) { return 0; } + int foo_int(void) __attribute__((visibility("internal"))); int foo_int(void) { return 0; }''', 'visibility:default': - 'int foo(void) __attribute__((visibility("default")));', + 'int foo(void) __attribute__((visibility("default"))); int foo(void) { return 0; }', 'visibility:hidden': - 'int foo(void) __attribute__((visibility("hidden")));', + 'int foo(void) __attribute__((visibility("hidden"))); int foo(void) { return 0; }', 'visibility:internal': - 'int foo(void) __attribute__((visibility("internal")));', + 'int foo(void) __attribute__((visibility("internal"))); int foo(void) { return 0; }', 'visibility:protected': - 'int foo(void) __attribute__((visibility("protected")));', + 'int foo(void) __attribute__((visibility("protected"))); int foo(void) { return 0; }', 'warning': 'int foo(void) __attribute__((warning("")));', 'warn_unused_result': diff --git a/test cases/common/197 function attributes/meson.build b/test cases/common/197 function attributes/meson.build index 0d5c04ed1199..8ef6b741d655 100644 --- a/test cases/common/197 function attributes/meson.build +++ b/test cases/common/197 function attributes/meson.build @@ -23,7 +23,8 @@ if c.get_id() == 'pgi' error('MESON_SKIP_TEST: PGI supports its own set of features, will need a separate list for PGI to test it.') endif -expected_result = not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) +expected = {} +expected_default = not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) # Q: Why is ifunc not in this list or any of the below lists? # A: It's too damn hard to figure out if you actually support it, since it @@ -56,8 +57,24 @@ attributes = [ 'vector_size', 'warn_unused_result', 'weak', + 'dllexport', + 'dllimport', ] +expected += { + 'dllexport': ['windows', 'cygwin'].contains(host_machine.system()), + 'dllimport': ['windows', 'cygwin'].contains(host_machine.system()), +} + +if c.get_id() == 'gcc' and ['windows', 'cygwin'].contains(host_machine.system()) + expected += { + 'visibility': false, + 'visibility:hidden': false, + 'visibility:internal': false, + 'visibility:protected': false, + } +endif + if c.get_id() != 'intel' # not supported by icc as of 19.0.0 attributes += 'weakref' @@ -67,6 +84,10 @@ endif if host_machine.system() != 'darwin' attributes += 'alias' attributes += 'visibility' + attributes += 'visibility:default' + attributes += 'visibility:hidden' + attributes += 'visibility:internal' + attributes += 'visibility:protected' attributes += 'alloc_size' endif @@ -94,24 +115,18 @@ endif if get_option('mode') == 'single' foreach a : attributes x = c.has_function_attribute(a) + expected_result = expected.get(a, expected_default) assert(x == expected_result, '@0@: @1@'.format(c.get_id(), a)) x = cpp.has_function_attribute(a) assert(x == expected_result, '@0@: @1@'.format(cpp.get_id(), a)) endforeach - - win_expect = ['windows', 'cygwin'].contains(host_machine.system()) - foreach a : ['dllexport', 'dllimport'] - assert(c.has_function_attribute(a) == win_expect, - '@0@: @1@'.format(c.get_id(), a)) - assert(cpp.has_function_attribute(a) == win_expect, - '@0@: @1@'.format(cpp.get_id(), a)) - endforeach else - if not ['msvc', 'clang-cl', 'intel-cl'].contains(c.get_id()) - multi_expected = attributes - else - multi_expected = [] - endif + multi_expected = [] + foreach a : attributes + if expected.get(a, expected_default) + multi_expected += a + endif + endforeach multi_check = c.get_supported_function_attributes(attributes) assert(multi_check == multi_expected, 'get_supported_function_arguments works (C)') From bf7d617b8c9c38df9b0a164365897090c95589d5 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Fri, 3 Nov 2023 23:41:33 -0600 Subject: [PATCH 406/855] Adding Trilobite Data to Users.md --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 7aef3221995b..0fd781a011aa 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -162,6 +162,7 @@ format files - [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 - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code - [Trilobite XCore](https://github.com/trilobite-stdlib/trilo-xcore-c), a core essential library for C code + - [Trilobite XData](https://github.com/trilobite-stdlib/trilo-xdata-c), a data structures and algorithms for C code - [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 9aa14eb013df80ab68d1b63c039e599b558ea6e6 Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Sat, 4 Nov 2023 19:52:37 -0600 Subject: [PATCH 407/855] Update Users.md --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 0fd781a011aa..6e8897714136 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -161,6 +161,7 @@ format files - [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 - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code + - [Trilobite XType](https://github.com/trilobite-stdlib/trilo-xtype-c), a data type library for C code - [Trilobite XCore](https://github.com/trilobite-stdlib/trilo-xcore-c), a core essential library for C code - [Trilobite XData](https://github.com/trilobite-stdlib/trilo-xdata-c), a data structures and algorithms for C code - [UFJF-MLTK](https://github.com/mateus558/UFJF-Machine-Learning-Toolkit), A C++ cross-platform framework for machine learning algorithms development and testing From 87480bc497bc18587563556e49e1956f8f512e49 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 29 Oct 2023 00:35:35 -0400 Subject: [PATCH 408/855] gnome module: fix invalid find_tool variable contents causing crash If a tool that is looked up in a .pc file is supposed to be there and has a pkg-config variable entry, but the value is incorrect, we can't actually use it. Since commit ab3d02066c91974922948f8b8b0fc944875d1a90 we actually do run the ExternalProgram search procedure on it though -- which caused it to go wonky and return a None if it doesn't exist, instead of containing a path to a program that does not exist and fails at build time. This is better in the case where searching helps resolve .exe file extensions -- and worse in the case where patches to the dependency means nothing we do is ever enough to actually find what is expected, since now we crash. Raise an explicit error in such a case, pointing out that the dependency itself is broken and needs a distributor-side resolution. Fixes #12412 --- mesonbuild/modules/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index a1aa2334495a..bbfb5bdbd40f 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -112,7 +112,12 @@ def find_tool(self, name: str, depname: str, varname: str, required: bool = True if dep.found() and dep.type_name == 'pkgconfig': value = dep.get_variable(pkgconfig=varname) if value: - return ExternalProgram(value) + progobj = ExternalProgram(value) + if not progobj.found(): + msg = (f'Dependency {depname!r} tool variable {varname!r} contains erroneous value: {value!r}\n\n' + 'This is a distributor issue -- please report it to your {depname} provider.') + raise mesonlib.MesonException(msg) + return progobj # Normal program lookup return self.find_program(name, required=required, wanted=wanted) From 61a760a39cd774cca9593cf531bd783e55ed36ee Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 5 Nov 2023 23:14:42 +0200 Subject: [PATCH 409/855] Increment 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 7e9d7d8be17a..b98401312b8b 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "October 2023" "meson 1.3.0" "User Commands" +.TH MESON "1" "November 2023" "meson 1.3.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 4fd82833e0d6..0522257337ed 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -61,7 +61,7 @@ # # 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.3.0.rc1' +version = '1.3.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 4c5e976a75a49245286bfafc2304f1193c888e4d Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 3 Nov 2023 08:05:53 -0400 Subject: [PATCH 410/855] msubprojects: Fix --sourcedir argument not working This is a regression caused by https://github.com/mesonbuild/meson/pull/11951. Fixes: #12466 --- mesonbuild/msubprojects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index ea2eb2cc39bb..d8afd92ddec6 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -746,7 +746,7 @@ def run(options: 'Arguments') -> int: pre_func(options) logger = Logger(len(wraps)) for wrap in wraps: - dirname = Path(subproject_dir, wrap.directory).as_posix() + dirname = Path(source_dir, subproject_dir, wrap.directory).as_posix() runner = Runner(logger, r, wrap, dirname, options) task = loop.run_in_executor(executor, runner.run) tasks.append(task) From 91f2050813b81575db61d5aafff6aa3a2fa61a06 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 6 Nov 2023 07:48:55 -0500 Subject: [PATCH 411/855] rust: Add unique metadata id This solves StableCrateId collision when using multiple versions of the same crate. --- mesonbuild/backend/ninjabackend.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0f630a6b6d2d..339952400903 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1948,6 +1948,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: depfile = os.path.join(target.subdir, target.name + '.d') args += ['--emit', f'dep-info={depfile}', '--emit', f'link={target_name}'] args += ['--out-dir', self.get_target_private_dir(target)] + args += ['-C', 'metadata=' + target.get_id()] args += target.get_extra_args('rust') # Rustc always use non-debug Windows runtime. Inject the one selected From ccff0f43b2e8bdd749ec2d3ea893d0c23eb5c3c7 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 5 Nov 2023 13:58:37 -0500 Subject: [PATCH 412/855] tests: skip llvm modules test more thoroughly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bug that is referenced in the SKIP message was merged in time for the most recent llvm 16.x release. However, due to the graciousness of the LLVM developers, a very reasonable response was taken: LLVM will not merge ("the average"?) bugfixes during the final point release of a release series, as judged by their willingness to continue maintaining a major release of LLVM (????????) because merging a bugfix could theoretically cause a new bug instead and that Simply Is Not Done™. It could result in truly tragic outcomes, like having to release another bugfix. This innovative approach to bug solving has advanced the science of computing forward by decades. Sadly, it comes at a downside: software doesn't work. At this point it becomes obvious that llvm 16 in general will simply not work with Meson, and this is "expected", so bump the version checking for our SKIP to match reality. --- test cases/frameworks/15 llvm/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/15 llvm/meson.build b/test cases/frameworks/15 llvm/meson.build index 9c39e45b6a43..bb945cc44659 100644 --- a/test cases/frameworks/15 llvm/meson.build +++ b/test cases/frameworks/15 llvm/meson.build @@ -86,7 +86,7 @@ else dep_tinfo = cpp.find_library('tinfo', required: false) endif - if static and method == 'cmake' and d.version().startswith('16.0') and d.version()[5].to_int() <= 5 + if static and method == 'cmake' and d.version().startswith('16.0') message('Skipping modules with cmake due to an LLVM bug, see https://github.com/mesonbuild/meson/issues/11642') llvm_dep = dependency( 'llvm', From 686963f1c247442e01787a276879391aa64e41c2 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 2 Nov 2023 13:12:20 -0400 Subject: [PATCH 413/855] ci: Add arm rust toolchain in ubuntu-rolling image --- ci/ciimage/ubuntu-rolling/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/ciimage/ubuntu-rolling/install.sh b/ci/ciimage/ubuntu-rolling/install.sh index a02eb8f5d3bb..35a0b0ea286c 100755 --- a/ci/ciimage/ubuntu-rolling/install.sh +++ b/ci/ciimage/ubuntu-rolling/install.sh @@ -56,6 +56,7 @@ apt-get -y remove rustc || true wget -O - https://sh.rustup.rs | sh -s -- -y --profile minimal --component clippy source "$HOME/.cargo/env" rustup target add x86_64-pc-windows-gnu +rustup target add arm-unknown-linux-gnueabihf # cleanup apt-get -y clean From 2ea284bac1dce5ac659aaaa68f4c36f6278ed340 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 6 Nov 2023 18:30:00 +0200 Subject: [PATCH 414/855] Prohibit symlinks in test data dir because they get mangled by setup.py. --- run_format_tests.py | 8 +++++++ run_project_tests.py | 21 +++++++++++++++++++ .../foo/file1 | 0 .../meson.build | 0 .../test.json | 0 .../foo/link1 | 1 - .../foo/link2.h | 1 - .../subprojects/no-warn/meson_options.txt | 2 +- 8 files changed, 30 insertions(+), 3 deletions(-) mode change 100644 => 100755 run_format_tests.py rename test cases/common/{268 install functions and follow_symlinks => 268 install functions and follow symlinks}/foo/file1 (100%) rename test cases/common/{268 install functions and follow_symlinks => 268 install functions and follow symlinks}/meson.build (100%) rename test cases/common/{268 install functions and follow_symlinks => 268 install functions and follow symlinks}/test.json (100%) delete mode 120000 test cases/common/268 install functions and follow_symlinks/foo/link1 delete mode 120000 test cases/common/268 install functions and follow_symlinks/foo/link2.h mode change 120000 => 100644 test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt diff --git a/run_format_tests.py b/run_format_tests.py old mode 100644 new mode 100755 index 70fa1212e129..ca3e715f2c28 --- a/run_format_tests.py +++ b/run_format_tests.py @@ -75,9 +75,17 @@ def check_format() -> None: continue check_file(root / file) +def check_symlinks(): + for f in Path('test cases').glob('**/*'): + if f.is_symlink(): + if 'boost symlinks' in str(f): + continue + raise SystemExit(f'Test data dir contains symlink: {f}.') + if __name__ == '__main__': script_dir = os.path.split(__file__)[0] if script_dir != '': os.chdir(script_dir) check_format() + check_symlinks() diff --git a/run_project_tests.py b/run_project_tests.py index 7ff164086678..39bf1628f4aa 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1561,6 +1561,14 @@ def get_version(t: ToolInfo) -> str: print('{0:<{2}}: {1}'.format(tool.tool, get_version(tool), max_width)) print() +tmpdir = list(Path('.').glob('**/*install functions and follow symlinks')) +print(tmpdir) +assert(len(tmpdir) == 1) +symlink_test_dir = tmpdir[0] +symlink_file1 = symlink_test_dir / 'foo/link1' +symlink_file2 = symlink_test_dir / 'foo/link2.h' +del tmpdir + def clear_transitive_files() -> None: a = Path('test cases/common') for d in a.glob('*subproject subdir/subprojects/subsubsub*'): @@ -1568,6 +1576,18 @@ def clear_transitive_files() -> None: mesonlib.windows_proof_rmtree(str(d)) else: mesonlib.windows_proof_rm(str(d)) + try: + symlink_file1.unlink() + except FileNotFoundError: + pass + try: + symlink_file2.unlink() + except FileNotFoundError: + pass + +def setup_symlinks() -> None: + symlink_file1.symlink_to('file1') + symlink_file2.symlink_to('file1') if __name__ == '__main__': if under_ci and not raw_ci_jobname: @@ -1611,6 +1631,7 @@ def clear_transitive_files() -> None: options.extra_args += ['--native-file', options.native_file] clear_transitive_files() + setup_symlinks() print('Meson build system', meson_version, 'Project Tests') print('Using python', sys.version.split('\n')[0], f'({sys.executable!r})') diff --git a/test cases/common/268 install functions and follow_symlinks/foo/file1 b/test cases/common/268 install functions and follow symlinks/foo/file1 similarity index 100% rename from test cases/common/268 install functions and follow_symlinks/foo/file1 rename to test cases/common/268 install functions and follow symlinks/foo/file1 diff --git a/test cases/common/268 install functions and follow_symlinks/meson.build b/test cases/common/268 install functions and follow symlinks/meson.build similarity index 100% rename from test cases/common/268 install functions and follow_symlinks/meson.build rename to test cases/common/268 install functions and follow symlinks/meson.build diff --git a/test cases/common/268 install functions and follow_symlinks/test.json b/test cases/common/268 install functions and follow symlinks/test.json similarity index 100% rename from test cases/common/268 install functions and follow_symlinks/test.json rename to test cases/common/268 install functions and follow symlinks/test.json diff --git a/test cases/common/268 install functions and follow_symlinks/foo/link1 b/test cases/common/268 install functions and follow_symlinks/foo/link1 deleted file mode 120000 index 08219db9b096..000000000000 --- a/test cases/common/268 install functions and follow_symlinks/foo/link1 +++ /dev/null @@ -1 +0,0 @@ -file1 \ No newline at end of file diff --git a/test cases/common/268 install functions and follow_symlinks/foo/link2.h b/test cases/common/268 install functions and follow_symlinks/foo/link2.h deleted file mode 120000 index 08219db9b096..000000000000 --- a/test cases/common/268 install functions and follow_symlinks/foo/link2.h +++ /dev/null @@ -1 +0,0 @@ -file1 \ No newline at end of file diff --git a/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt b/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt deleted file mode 120000 index 7b28df279f07..000000000000 --- a/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt +++ /dev/null @@ -1 +0,0 @@ -meson.options \ No newline at end of file diff --git a/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt b/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt new file mode 100644 index 000000000000..b84ee83fcccc --- /dev/null +++ b/test cases/warning/9 meson.options/subprojects/no-warn/meson_options.txt @@ -0,0 +1 @@ +option('foo', type : 'string') From 21bf18afa159bbfae8f4e5c88e174f4fbc5ffc2b Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 8 Nov 2023 09:59:59 -0500 Subject: [PATCH 415/855] build: Simplify recursive function that extracts objects in link_whole --- mesonbuild/build.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 9283bca97f96..0cb21cfeb0d7 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1276,13 +1276,13 @@ def get_extra_args(self, language: str) -> T.List[str]: return self.extra_args[language] @lru_cache(maxsize=None) - def get_dependencies(self) -> OrderedSet[Target]: + def get_dependencies(self) -> OrderedSet[BuildTargetTypes]: # Get all targets needed for linking. This includes all link_with and # link_whole targets, and also all dependencies of static libraries # recursively. The algorithm here is closely related to what we do in # get_internal_static_libraries(): Installed static libraries include # objects from all their dependencies already. - result: OrderedSet[Target] = OrderedSet() + result: OrderedSet[BuildTargetTypes] = OrderedSet() for t in itertools.chain(self.link_targets, self.link_whole_targets): if t not in result: result.add(t) @@ -1290,7 +1290,7 @@ def get_dependencies(self) -> OrderedSet[Target]: t.get_dependencies_recurse(result) return result - def get_dependencies_recurse(self, result: OrderedSet[Target], include_internals: bool = True) -> None: + def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True) -> 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 @@ -1394,7 +1394,7 @@ def get_external_deps(self) -> T.List[dependencies.Dependency]: def is_internal(self) -> bool: return False - def link(self, targets): + def link(self, targets: T.List[BuildTargetTypes]) -> None: for t in targets: if not isinstance(t, (Target, CustomTargetIndex)): if isinstance(t, dependencies.ExternalLibrary): @@ -1420,7 +1420,7 @@ def link(self, targets): self.check_can_link_together(t) self.link_targets.append(t) - def link_whole(self, targets, promoted: bool = False): + def link_whole(self, targets: T.List[BuildTargetTypes], promoted: bool = False) -> None: for t in targets: if isinstance(t, (CustomTarget, CustomTargetIndex)): if not t.is_linkable_target(): @@ -1437,32 +1437,30 @@ def link_whole(self, targets, promoted: bool = False): if isinstance(self, StaticLibrary) and not self.uses_rust(): # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. - self.check_can_extract_objects(t, origin=self, promoted=promoted) - self.objects += [t.extract_all_objects()] + self._bundle_static_library(t, promoted) # If we install this static library we also need to include objects # from all uninstalled static libraries it depends on. if self.install: - for lib in t.get_internal_static_libraries(origin=self): - self.objects += [lib.extract_all_objects()] + for lib in t.get_internal_static_libraries(): + self._bundle_static_library(lib, True) self.link_whole_targets.append(t) @lru_cache(maxsize=None) - def get_internal_static_libraries(self, origin: StaticLibrary) -> OrderedSet[Target]: - result: OrderedSet[Target] = OrderedSet() - self.get_internal_static_libraries_recurse(result, origin) + def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]: + result: OrderedSet[BuildTargetTypes] = OrderedSet() + self.get_internal_static_libraries_recurse(result) return result - def get_internal_static_libraries_recurse(self, result: OrderedSet[Target], origin: StaticLibrary) -> None: + def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None: for t in self.link_targets: if t.is_internal() and t not in result: - self.check_can_extract_objects(t, origin, promoted=True) result.add(t) - t.get_internal_static_libraries_recurse(result, origin) + t.get_internal_static_libraries_recurse(result) for t in self.link_whole_targets: if t.is_internal(): - t.get_internal_static_libraries_recurse(result, origin) + t.get_internal_static_libraries_recurse(result) - def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origin: StaticLibrary, promoted: bool = False) -> None: + def _bundle_static_library(self, t: T.Union[BuildTargetTypes], promoted: bool = False) -> None: if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): # To extract objects from a custom target we would have to extract # the archive, WIP implementation can be found in @@ -1472,12 +1470,13 @@ def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origi # https://github.com/mesonbuild/meson/issues/10722 # https://github.com/mesonbuild/meson/issues/10723 # https://github.com/mesonbuild/meson/issues/10724 - m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {origin.name!r}. ' + m = (f'Cannot link_whole a custom or Rust target {t.name!r} into a static library {self.name!r}. ' 'Instead, pass individual object files with the "objects:" keyword argument if possible.') if promoted: - m += (f' Meson had to promote link to link_whole because {origin.name!r} is installed but not {t.name!r},' + m += (f' Meson had to promote link to link_whole because {self.name!r} is installed but not {t.name!r},' f' and thus has to include objects from {t.name!r} to be usable.') raise InvalidArguments(m) + self.objects.append(t.extract_all_objects()) def check_can_link_together(self, t: BuildTargetTypes) -> None: links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() From d0a7a203a6edb570c36a9fb5f04a3541df2be687 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 8 Nov 2023 14:30:11 -0500 Subject: [PATCH 416/855] build: Add dummy base class for CustomTarget and CustomTargetIndex CustomTarget and CustomTargetIndex often have to be special cased because they are not subclass of BuildTarget. It's easier to introduce a dummy base class. This fix recursive functions over link targets that might encouters libraries built as CustomTarget. --- mesonbuild/build.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 0cb21cfeb0d7..651f614ba709 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1299,7 +1299,7 @@ def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include for t in self.link_targets: if t in result: continue - if isinstance(t, SharedLibrary) and t.rust_crate_type == 'proc-macro': + if t.rust_crate_type == 'proc-macro': continue if include_internals or not t.is_internal(): result.add(t) @@ -2523,7 +2523,26 @@ def flatten_command(self, cmd: T.Sequence[T.Union[str, File, programs.ExternalPr raise InvalidArguments(f'Argument {c!r} in "command" is invalid') return final_cmd -class CustomTarget(Target, CommandBase): +class CustomTargetBase: + ''' Base class for CustomTarget and CustomTargetIndex + + This base class can be used to provide a dummy implementation of some + private methods to avoid repeating `isinstance(t, BuildTarget)` when dealing + with custom targets. + ''' + + rust_crate_type = '' + + def get_dependencies_recurse(self, result: OrderedSet[BuildTargetTypes], include_internals: bool = True) -> None: + pass + + def get_internal_static_libraries(self) -> OrderedSet[BuildTargetTypes]: + return OrderedSet() + + def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTypes]) -> None: + pass + +class CustomTarget(Target, CustomTargetBase, CommandBase): typename = 'custom' @@ -2900,7 +2919,7 @@ def get_default_install_dir(self) -> T.Tuple[str, str]: return self.environment.get_jar_dir(), '{jardir}' @dataclass(eq=False) -class CustomTargetIndex(HoldableObject): +class CustomTargetIndex(CustomTargetBase, HoldableObject): """A special opaque object returned by indexing a CustomTarget. This object exists in Meson, but acts as a proxy in the backends, making targets depend From d25d8e2772b92838299b4f4056fe3888c10c0ee7 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 6 Nov 2023 13:52:51 -0500 Subject: [PATCH 417/855] rust: Fix linking with C libraries (again) Pass link arguments directly down to linker by using `-C link-args=` instead of letting rustc/linker resolve `-l` arguments. This solves problems with e.g. +verbatim not being portable. Note that we also pass `-l` args as `-Clink-args=-l` because rustc would otherwise reorder arguments and put `-lstdc++` before `-Clink-args=libfoo++.a`. However, when building a rlib/staticlib we should still use `-l` arguments because that allows rustc to bundle static libraries we link-whole. In that case, since there is no platform specific dynamic linker, +verbatim works. This also fix installed staticlib that now bundle uninstalled static libraries it links to (recursively). This is done by putting them all into self.link_whole_targets instead of putting their objects into self.objects, and let rustc do the bundling. This has the extra advantage that rustc can bundle static libries built with CustomTarget. Disable bundling in all other cases, otherwise we could end up with duplicated objects in static libraries, in diamond dependency graph case. Fixes: #12484 --- mesonbuild/backend/ninjabackend.py | 108 ++++++++---------- mesonbuild/build.py | 10 +- test cases/rust/15 polyglot sharedlib/adder.c | 8 +- .../rust/15 polyglot sharedlib/adder.rs | 11 +- .../rust/15 polyglot sharedlib/meson.build | 23 ++-- .../15 polyglot sharedlib/zero/meson.build | 6 + .../rust/15 polyglot sharedlib/zero/zero.c | 11 ++ .../15 polyglot sharedlib/zero/zero_static.c | 6 + .../20 transitive dependencies/diamond/func.c | 4 + .../20 transitive dependencies/diamond/main.c | 5 + .../diamond/meson.build | 25 ++++ .../20 transitive dependencies/diamond/r1.rs | 9 ++ .../20 transitive dependencies/diamond/r2.rs | 9 ++ .../20 transitive dependencies/diamond/r3.rs | 4 + .../20 transitive dependencies/meson.build | 2 + .../rust/20 transitive dependencies/test.json | 5 + 16 files changed, 163 insertions(+), 83 deletions(-) create mode 100644 test cases/rust/15 polyglot sharedlib/zero/meson.build create mode 100644 test cases/rust/15 polyglot sharedlib/zero/zero.c create mode 100644 test cases/rust/15 polyglot sharedlib/zero/zero_static.c create mode 100644 test cases/rust/20 transitive dependencies/diamond/func.c create mode 100644 test cases/rust/20 transitive dependencies/diamond/main.c create mode 100644 test cases/rust/20 transitive dependencies/diamond/meson.build create mode 100644 test cases/rust/20 transitive dependencies/diamond/r1.rs create mode 100644 test cases/rust/20 transitive dependencies/diamond/r2.rs create mode 100644 test cases/rust/20 transitive dependencies/diamond/r3.rs create mode 100644 test cases/rust/20 transitive dependencies/test.json diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 339952400903..22af2500e87c 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1962,23 +1962,22 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: except KeyError: pass - # Since 1.61.0 Rust has a special modifier for whole-archive linking, - # before that it would treat linking two static libraries as - # whole-archive linking. However, to make this work we have to disable - # bundling, which can't be done until 1.63.0… So for 1.61–1.62 we just - # have to hope that the default cases of +whole-archive are sufficient. - # See: https://github.com/rust-lang/rust/issues/99429 - if mesonlib.version_compare(rustc.version, '>= 1.63.0'): - whole_archive = '+whole-archive,-bundle' - else: - whole_archive = '' - - # FIXME: Seems broken on MacOS: https://github.com/rust-lang/rust/issues/116674 - if mesonlib.version_compare(rustc.version, '>= 1.67.0') and not mesonlib.is_osx(): + if mesonlib.version_compare(rustc.version, '>= 1.67.0'): verbatim = '+verbatim' else: verbatim = '' + def _link_library(libname: str, static: bool, bundle: bool = False): + type_ = 'static' if static else 'dylib' + modifiers = [] + if not bundle and static: + modifiers.append('-bundle') + if verbatim: + modifiers.append(verbatim) + if modifiers: + type_ += ':' + ','.join(modifiers) + args.extend(['-l', f'{type_}={libname}']) + linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() target_deps = target.get_dependencies() @@ -2001,64 +2000,47 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: if isinstance(d, build.StaticLibrary): external_deps.extend(d.external_deps) - lib = None - modifiers = [] + # Pass native libraries directly to the linker with "-C link-arg" + # because rustc's "-l:+verbatim=" is not portable and we cannot rely + # on linker to find the right library without using verbatim filename. + # For example "-lfoo" won't find "foo.so" in the case name_prefix set + # to "", or would always pick the shared library when both "libfoo.so" + # and "libfoo.a" are available. + # See https://doc.rust-lang.org/rustc/command-line-arguments.html#linking-modifiers-verbatim. + # + # However, rustc static linker (rlib and staticlib) requires using + # "-l" argument and does not rely on platform specific dynamic linker. + lib = self.get_target_filename_for_linking(d) link_whole = d in target.link_whole_targets - if link_whole and whole_archive: - modifiers.append(whole_archive) - if verbatim: - modifiers.append(verbatim) - lib = self.get_target_filename_for_linking(d) - elif rustc.linker.id in {'link', 'lld-link'} and isinstance(d, build.StaticLibrary): - # Rustc doesn't follow Meson's convention that static libraries - # are called .a, and import libraries are .lib, so we have to - # manually handle that. - if link_whole: - if isinstance(target, build.StaticLibrary): - # If we don't, for static libraries the only option is - # to make a copy, since we can't pass objects in, or - # directly affect the archiver. but we're not going to - # do that given how quickly rustc versions go out of - # support unless there's a compelling reason to do so. - # This only affects 1.61–1.66 - mlog.warning('Due to limitations in Rustc versions 1.61–1.66 and meson library naming,', - 'whole-archive linking with MSVC may or may not work. Upgrade rustc to', - '>= 1.67. A best effort is being made, but likely won\'t work') - lib = d.name - else: - # When doing dynamic linking (binaries and [c]dylibs), - # we can instead just proxy the correct arguments to the linker - for link_whole_arg in rustc.linker.get_link_whole_for([self.get_target_filename_for_linking(d)]): - args += ['-C', f'link-arg={link_whole_arg}'] - else: - args += ['-C', f'link-arg={self.get_target_filename_for_linking(d)}'] + if isinstance(target, build.StaticLibrary): + static = isinstance(d, build.StaticLibrary) + libname = os.path.basename(lib) if verbatim else d.name + _link_library(libname, static, bundle=link_whole) + elif link_whole: + link_whole_args = rustc.linker.get_link_whole_for([lib]) + args += [f'-Clink-arg={a}' for a in link_whole_args] else: - lib = d.name - - if lib: - _type = 'static' if isinstance(d, build.StaticLibrary) else 'dylib' - if modifiers: - _type += ':' + ','.join(modifiers) - args += ['-l', f'{_type}={lib}'] + args.append(f'-Clink-arg={lib}') for e in external_deps: for a in e.get_link_args(): if a in rustc.native_static_libs: # Exclude link args that rustc already add by default - continue - if a.endswith(('.dll', '.so', '.dylib', '.a', '.lib')): - dir_, lib = os.path.split(a) - linkdirs.add(dir_) - lib, ext = os.path.splitext(lib) - if lib.startswith('lib'): - lib = lib[3:] - _type = 'static' if a.endswith(('.a', '.lib')) else 'dylib' - args.extend(['-l', f'{_type}={lib}']) + pass elif a.startswith('-L'): args.append(a) - elif a.startswith('-l'): - _type = 'static' if e.static else 'dylib' - args.extend(['-l', f'{_type}={a[2:]}']) + elif a.endswith(('.dll', '.so', '.dylib', '.a', '.lib')) and isinstance(target, build.StaticLibrary): + dir_, lib = os.path.split(a) + linkdirs.add(dir_) + if not verbatim: + lib, ext = os.path.splitext(lib) + if lib.startswith('lib'): + lib = lib[3:] + static = a.endswith(('.a', '.lib')) + _link_library(lib, static) + else: + args.append(f'-Clink-arg={a}') + for d in linkdirs: if d == '': d = '.' @@ -2066,7 +2048,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # Because of the way rustc links, this must come after any potential # library need to link with their stdlibs (C++ and Fortran, for example) - args.extend(target.get_used_stdlib_args('rust')) + args.extend(f'-Clink-arg={a}' for a in target.get_used_stdlib_args('rust')) has_shared_deps = any(isinstance(dep, build.SharedLibrary) for dep in target_deps) has_rust_shared_deps = any(dep.uses_rust() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 651f614ba709..9c27b2361542 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1434,7 +1434,7 @@ def link_whole(self, targets: T.List[BuildTargetTypes], promoted: bool = False) msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) self.check_can_link_together(t) - if isinstance(self, StaticLibrary) and not self.uses_rust(): + if isinstance(self, StaticLibrary): # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. self._bundle_static_library(t, promoted) @@ -1461,7 +1461,10 @@ def get_internal_static_libraries_recurse(self, result: OrderedSet[BuildTargetTy t.get_internal_static_libraries_recurse(result) def _bundle_static_library(self, t: T.Union[BuildTargetTypes], promoted: bool = False) -> None: - if isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): + if self.uses_rust(): + # Rustc can bundle static libraries, no need to extract objects. + self.link_whole_targets.append(t) + elif isinstance(t, (CustomTarget, CustomTargetIndex)) or t.uses_rust(): # To extract objects from a custom target we would have to extract # the archive, WIP implementation can be found in # https://github.com/mesonbuild/meson/pull/9218. @@ -1476,7 +1479,8 @@ def _bundle_static_library(self, t: T.Union[BuildTargetTypes], promoted: bool = m += (f' Meson had to promote link to link_whole because {self.name!r} is installed but not {t.name!r},' f' and thus has to include objects from {t.name!r} to be usable.') raise InvalidArguments(m) - self.objects.append(t.extract_all_objects()) + else: + self.objects.append(t.extract_all_objects()) def check_can_link_together(self, t: BuildTargetTypes) -> None: links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() diff --git a/test cases/rust/15 polyglot sharedlib/adder.c b/test cases/rust/15 polyglot sharedlib/adder.c index 66613edf57d7..1b5faa67e7b2 100644 --- a/test cases/rust/15 polyglot sharedlib/adder.c +++ b/test cases/rust/15 polyglot sharedlib/adder.c @@ -11,7 +11,13 @@ adder* adder_create(int number) { return a; } -// adder_add is implemented in the Rust file. +// adder_add_r is implemented in the Rust file. +int adder_add_r(adder *a, int number); + +int adder_add(adder *a, int number) +{ + return adder_add_r(a, number); +} void adder_destroy(adder *a) { free(a); diff --git a/test cases/rust/15 polyglot sharedlib/adder.rs b/test cases/rust/15 polyglot sharedlib/adder.rs index 9095350355bd..ec4d1cc138b6 100644 --- a/test cases/rust/15 polyglot sharedlib/adder.rs +++ b/test cases/rust/15 polyglot sharedlib/adder.rs @@ -3,7 +3,14 @@ pub struct Adder { pub number: i32 } +extern "C" { + pub fn zero() -> i32; + pub fn zero_static() -> i32; +} + #[no_mangle] -pub extern fn adder_add(a: &Adder, number: i32) -> i32 { - return a.number + number; +pub extern fn adder_add_r(a: &Adder, number: i32) -> i32 { + unsafe { + return a.number + number + zero() + zero_static(); + } } diff --git a/test cases/rust/15 polyglot sharedlib/meson.build b/test cases/rust/15 polyglot sharedlib/meson.build index 13fc8fd47c5e..fc3d53b679ea 100644 --- a/test cases/rust/15 polyglot sharedlib/meson.build +++ b/test cases/rust/15 polyglot sharedlib/meson.build @@ -1,20 +1,15 @@ project('adder', 'c', 'rust', version: '1.0.0') -if build_machine.system() != 'linux' - error('MESON_SKIP_TEST, this test only works on Linux. Patches welcome.') -endif +subdir('zero') -thread_dep = dependency('threads') -dl_dep = meson.get_compiler('c').find_library('dl', required: false) -m_dep = meson.get_compiler('c').find_library('m', required: false) - -rl = static_library('radder', 'adder.rs', rust_crate_type: 'staticlib') +rl = shared_library('radder', 'adder.rs', + rust_abi: 'c', + link_with: [zero_shared, zero_static]) l = shared_library('adder', 'adder.c', - c_args: '-DBUILDING_ADDER', - link_with: rl, - version: '1.0.0', - soversion: '1', - link_args: '-Wl,-u,adder_add', # Ensure that Rust code is not removed as unused. - dependencies: [thread_dep, dl_dep, m_dep]) + c_args: '-DBUILDING_ADDER', + link_with: rl, + version: '1.0.0', + soversion: '1', +) test('adder', executable('addertest', 'addertest.c', link_with: l)) diff --git a/test cases/rust/15 polyglot sharedlib/zero/meson.build b/test cases/rust/15 polyglot sharedlib/zero/meson.build new file mode 100644 index 000000000000..ec7ecf7bb397 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/meson.build @@ -0,0 +1,6 @@ +# They both have the same name, this tests we use +verbatim to distinguish them +# using their filename. It also ensures we pass the importlib on Windows. +# Those libs are in a subdir as regression test: +# https://github.com/mesonbuild/meson/issues/12484 +zero_shared = shared_library('zero', 'zero.c') +zero_static = static_library('zero', 'zero_static.c') diff --git a/test cases/rust/15 polyglot sharedlib/zero/zero.c b/test cases/rust/15 polyglot sharedlib/zero/zero.c new file mode 100644 index 000000000000..02672f3946d4 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/zero.c @@ -0,0 +1,11 @@ +#if defined _WIN32 || defined __CYGWIN__ +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT int zero(void); + +int zero(void) { + return 0; +} diff --git a/test cases/rust/15 polyglot sharedlib/zero/zero_static.c b/test cases/rust/15 polyglot sharedlib/zero/zero_static.c new file mode 100644 index 000000000000..7f14fb4d65d1 --- /dev/null +++ b/test cases/rust/15 polyglot sharedlib/zero/zero_static.c @@ -0,0 +1,6 @@ +int zero_static(void); + +int zero_static(void) +{ + return 0; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/func.c b/test cases/rust/20 transitive dependencies/diamond/func.c new file mode 100644 index 000000000000..c07ab728df15 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/func.c @@ -0,0 +1,4 @@ +int c_func(void); +int c_func(void) { + return 123; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/main.c b/test cases/rust/20 transitive dependencies/diamond/main.c new file mode 100644 index 000000000000..c633e9ae5482 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/main.c @@ -0,0 +1,5 @@ +int r3(void); + +int main_func(void) { + return r3() == 246 ? 0 : 1; +} diff --git a/test cases/rust/20 transitive dependencies/diamond/meson.build b/test cases/rust/20 transitive dependencies/diamond/meson.build new file mode 100644 index 000000000000..dc48d4523e92 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/meson.build @@ -0,0 +1,25 @@ +# Regression test for a diamond dependency graph: +# ┌►R1┐ +# main-►R3─┤ ├─►C1 +# └►R2┘ +# Both libr1.rlib and libr2.rlib used to contain func.c.o. That was causing +# libr3.rlib to have duplicated func.c.o and then libmain.so failed to link: +# multiple definition of `c_func'. + +libc1 = static_library('c1', 'func.c') +libr1 = static_library('r1', 'r1.rs', link_with: libc1) +libr2 = static_library('r2', 'r2.rs', link_with: libc1) +libr3 = static_library('r3', 'r3.rs', + link_with: [libr1, libr2], + rust_abi: 'c', +) +shared_library('main', 'main.c', link_whole: [libr3]) + +# Same dependency graph, but r3 is now installed. Since c1, r1 and r2 are +# not installed, r3 must contain them. +libr3 = static_library('r3-installed', 'r3.rs', + link_with: [libr1, libr2], + rust_abi: 'c', + install: true, +) +shared_library('main-installed', 'main.c', link_with: [libr3]) diff --git a/test cases/rust/20 transitive dependencies/diamond/r1.rs b/test cases/rust/20 transitive dependencies/diamond/r1.rs new file mode 100644 index 000000000000..7afb71109d11 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r1.rs @@ -0,0 +1,9 @@ +extern "C" { + fn c_func() -> i32; +} + +pub fn r1() -> i32 { + unsafe { + c_func() + } +} diff --git a/test cases/rust/20 transitive dependencies/diamond/r2.rs b/test cases/rust/20 transitive dependencies/diamond/r2.rs new file mode 100644 index 000000000000..ee73ee2e2280 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r2.rs @@ -0,0 +1,9 @@ +extern "C" { + fn c_func() -> i32; +} + +pub fn r2() -> i32 { + unsafe { + c_func() + } +} diff --git a/test cases/rust/20 transitive dependencies/diamond/r3.rs b/test cases/rust/20 transitive dependencies/diamond/r3.rs new file mode 100644 index 000000000000..9794b7eda2d0 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/diamond/r3.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub fn r3() -> i32 { + r1::r1() + r2::r2() +} diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/20 transitive dependencies/meson.build index e5354b8f6f13..b786e64949f5 100644 --- a/test cases/rust/20 transitive dependencies/meson.build +++ b/test cases/rust/20 transitive dependencies/meson.build @@ -25,3 +25,5 @@ exe = executable('footest', 'foo.c', link_with: foo, ) test('footest', exe) + +subdir('diamond') diff --git a/test cases/rust/20 transitive dependencies/test.json b/test cases/rust/20 transitive dependencies/test.json new file mode 100644 index 000000000000..0d98c230ad37 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/test.json @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libr3-installed.a"} + ] +} From bd99f0bf1cd3e591a174aa985153f3ec9819d235 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 9 Nov 2023 14:55:06 -0500 Subject: [PATCH 418/855] rust: Make sure -l and -L are a single arg CompilerArgs would otherwise dedup and reorder them. --- mesonbuild/backend/ninjabackend.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 22af2500e87c..7ed6b443f140 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1976,7 +1976,7 @@ def _link_library(libname: str, static: bool, bundle: bool = False): modifiers.append(verbatim) if modifiers: type_ += ':' + ','.join(modifiers) - args.extend(['-l', f'{type_}={libname}']) + args.append(f'-l{type_}={libname}') linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() @@ -2042,9 +2042,8 @@ def _link_library(libname: str, static: bool, bundle: bool = False): args.append(f'-Clink-arg={a}') for d in linkdirs: - if d == '': - d = '.' - args += ['-L', d] + d = d or '.' + args.append(f'-L{d}') # Because of the way rustc links, this must come after any potential # library need to link with their stdlibs (C++ and Fortran, for example) From 42898bb455bda962ee6ecf0eb21c5090005b3906 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 10 Nov 2023 13:03:49 -0500 Subject: [PATCH 419/855] msvc: Do not include pch obj when b_pch=false Fixes: #12494 --- mesonbuild/backend/backends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 8cf738dbf436..b8b958883d67 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -896,7 +896,7 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_buil result.append(s.relative_name()) # MSVC generate an object file for PCH - if extobj.pch: + if extobj.pch and self.target_uses_pch(extobj.target): for lang, pch in extobj.target.pch.items(): compiler = extobj.target.compilers[lang] if compiler.get_argument_syntax() == 'msvc': From 11dec13a1933159be6bee160f899b39970b64d06 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 10 Nov 2023 14:01:28 -0500 Subject: [PATCH 420/855] mtest: -C argument does not need type convertor It is already done by RealPathAction and mypy started complaining about it. --- mesonbuild/mtest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index c1ce1e09efc0..b7d2bc6cf4f9 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -143,9 +143,6 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('--wrapper', default=None, dest='wrapper', type=split_args, help='wrapper to run tests with (e.g. Valgrind)') parser.add_argument('-C', dest='wd', action=RealPathAction, - # https://github.com/python/typeshed/issues/3107 - # https://github.com/python/mypy/issues/7177 - type=os.path.abspath, # type: ignore help='directory to cd into before running') parser.add_argument('--suite', default=[], dest='include_suites', action='append', metavar='SUITE', help='Only run tests belonging to the given suite.') From 422550036ea20061a60b29f695b2d1865667f012 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 12 Nov 2023 17:14:58 +0200 Subject: [PATCH 421/855] Handle dupe number in test renumberer. --- tools/dircondenser.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/dircondenser.py b/tools/dircondenser.py index fa299e9783c9..1b262f98083b 100755 --- a/tools/dircondenser.py +++ b/tools/dircondenser.py @@ -49,6 +49,8 @@ def get_entries() -> T.List[T.Tuple[int, str]]: numstr = int(number) except ValueError: raise SystemExit(f'Dir name {e} does not start with a number.') + if 'includedirxyz' in e: + continue entries.append((numstr, rest)) entries.sort() return entries From 97dc8801a691b0712b59d283416727c3f84b1115 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 12 Nov 2023 17:23:28 +0200 Subject: [PATCH 422/855] Renumber test dirs for rc3. --- .../diamond/func.c | 0 .../diamond/main.c | 0 .../diamond/meson.build | 0 .../diamond/r1.rs | 0 .../diamond/r2.rs | 0 .../diamond/r3.rs | 0 .../foo.c | 0 .../foo.rs | 0 .../liba/lib.rs | 0 .../liba/meson.build | 0 .../libb/lib.rs | 0 .../libb/meson.build | 0 .../main.rs | 0 .../meson.build | 0 .../proc.rs | 0 .../test.json | 0 .../main.c | 0 .../meson.build | 0 .../subprojects/bar-rs.wrap | 0 .../subprojects/bar-rs/Cargo.toml | 0 .../subprojects/bar-rs/src/lib.rs | 0 .../subprojects/foo-rs.wrap | 0 .../subprojects/foo-rs/Cargo.toml | 0 .../subprojects/foo-rs/src/lib.rs | 0 .../file.txt.in | 0 .../meson.build | 0 .../subdir/meson.build | 0 .../foo.py | 0 .../meson.build | 0 .../subdir/meson.build | 0 .../lib2.rs | 0 .../main.rs | 0 .../meson.build | 0 .../meson.build | 0 .../unit/{103 strip => 104 strip}/lib.c | 0 .../unit/{103 strip => 104 strip}/meson.build | 0 .../meson.build | 0 .../meson.build | 0 .../foo.c | 0 .../foo.dat | 0 .../foo.h | 0 .../foo/foofile | 0 .../meson.build | 0 .../subprojects/bar/bar.c | 0 .../subprojects/bar/bar.dat | 0 .../subprojects/bar/bar.h | 0 .../subprojects/bar/bar/barfile | 0 .../subprojects/bar/meson.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../subprojects/sub/foo.c | 0 .../subprojects/sub/meson.build | 0 .../.clang-format | 0 .../.clang-format-ignore | 0 .../.clang-format-include | 0 .../meson.build | 0 .../not-included/badformat.cpp | 0 .../src/badformat.c | 0 .../src/badformat.cpp | 0 .../easytogrepfor/genh.py | 0 .../easytogrepfor/meson.build | 0 .../{94 custominc => 95 custominc}/helper.c | 0 .../meson.build | 0 .../{94 custominc => 95 custominc}/prog.c | 0 .../{94 custominc => 95 custominc}/prog2.c | 0 .../meson.build | 0 .../subprojects/something/meson.build | 0 .../meson.build | 0 .../test.c | 0 .../.gitignore | 0 .../libtestprovider/meson.build | 0 .../libtestprovider/provider.c | 0 .../proguser/meson.build | 0 .../proguser/receiver.c | 0 .../bar-custom.txt | 0 .../bar-devel.h | 0 .../bar-notag.txt | 0 .../custom_files/data.txt | 0 .../excludes/excluded.txt | 0 .../excludes/excluded/placeholder.txt | 0 .../excludes/installed.txt | 0 .../foo.in | 0 .../foo1-devel.h | 0 .../lib.c | 0 .../main.c | 0 .../meson.build | 0 .../script.py | 0 .../subdir/bar2-devel.h | 0 .../subdir/foo2.in | 0 .../subdir/foo3-devel.h | 0 .../subdir/lib.c | 0 .../subdir/main.c | 0 .../subdir/meson.build | 0 .../subdir/script.py | 0 .../subprojects/subproject/aaa.txt | 0 .../subprojects/subproject/bbb.txt | 0 .../subprojects/subproject/meson.build | 0 unittests/allplatformstests.py | 22 +++++++++---------- unittests/linuxliketests.py | 6 ++--- unittests/platformagnostictests.py | 6 ++--- 100 files changed, 17 insertions(+), 17 deletions(-) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/func.c (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/main.c (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/meson.build (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/r1.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/r2.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/diamond/r3.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/foo.c (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/foo.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/liba/lib.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/liba/meson.build (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/libb/lib.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/libb/meson.build (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/main.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/meson.build (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/proc.rs (100%) rename test cases/rust/{20 transitive dependencies => 21 transitive dependencies}/test.json (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/main.c (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/meson.build (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/bar-rs.wrap (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/bar-rs/Cargo.toml (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/bar-rs/src/lib.rs (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/foo-rs.wrap (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/foo-rs/Cargo.toml (100%) rename test cases/rust/{21 cargo subproject => 22 cargo subproject}/subprojects/foo-rs/src/lib.rs (100%) rename test cases/unit/{99 custom target name => 100 custom target name}/file.txt.in (100%) rename test cases/unit/{99 custom target name => 100 custom target name}/meson.build (100%) rename test cases/unit/{99 custom target name => 100 custom target name}/subdir/meson.build (100%) rename test cases/unit/{100 relative find program => 101 relative find program}/foo.py (100%) rename test cases/unit/{100 relative find program => 101 relative find program}/meson.build (100%) rename test cases/unit/{100 relative find program => 101 relative find program}/subdir/meson.build (100%) rename test cases/unit/{101 rlib linkage => 102 rlib linkage}/lib2.rs (100%) rename test cases/unit/{101 rlib linkage => 102 rlib linkage}/main.rs (100%) rename test cases/unit/{101 rlib linkage => 102 rlib linkage}/meson.build (100%) rename test cases/unit/{102 python without pkgconfig => 103 python without pkgconfig}/meson.build (100%) rename test cases/unit/{103 strip => 104 strip}/lib.c (100%) rename test cases/unit/{103 strip => 104 strip}/meson.build (100%) rename test cases/unit/{104 debug function => 105 debug function}/meson.build (100%) rename test cases/unit/{105 pkgconfig relocatable with absolute path => 106 pkgconfig relocatable with absolute path}/meson.build (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/foo.c (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/foo.dat (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/foo.h (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/foo/foofile (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/meson.build (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/subprojects/bar/bar.c (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/subprojects/bar/bar.dat (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/subprojects/bar/bar.h (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/subprojects/bar/bar/barfile (100%) rename test cases/unit/{91 install skip subprojects => 92 install skip subprojects}/subprojects/bar/meson.build (100%) rename test cases/unit/{92 new subproject in configured project => 93 new subproject in configured project}/meson.build (100%) rename test cases/unit/{92 new subproject in configured project => 93 new subproject in configured project}/meson_options.txt (100%) rename test cases/unit/{92 new subproject in configured project => 93 new subproject in configured project}/subprojects/sub/foo.c (100%) rename test cases/unit/{92 new subproject in configured project => 93 new subproject in configured project}/subprojects/sub/meson.build (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/.clang-format (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/.clang-format-ignore (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/.clang-format-include (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/meson.build (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/not-included/badformat.cpp (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/src/badformat.c (100%) rename test cases/unit/{93 clangformat => 94 clangformat}/src/badformat.cpp (100%) rename test cases/unit/{94 custominc => 95 custominc}/easytogrepfor/genh.py (100%) rename test cases/unit/{94 custominc => 95 custominc}/easytogrepfor/meson.build (100%) rename test cases/unit/{94 custominc => 95 custominc}/helper.c (100%) rename test cases/unit/{94 custominc => 95 custominc}/meson.build (100%) rename test cases/unit/{94 custominc => 95 custominc}/prog.c (100%) rename test cases/unit/{94 custominc => 95 custominc}/prog2.c (100%) rename test cases/unit/{95 implicit force fallback => 96 implicit force fallback}/meson.build (100%) rename test cases/unit/{95 implicit force fallback => 96 implicit force fallback}/subprojects/something/meson.build (100%) rename test cases/unit/{96 compiler.links file arg => 97 compiler.links file arg}/meson.build (100%) rename test cases/unit/{96 compiler.links file arg => 97 compiler.links file arg}/test.c (100%) rename test cases/unit/{97 link full name => 98 link full name}/.gitignore (100%) rename test cases/unit/{97 link full name => 98 link full name}/libtestprovider/meson.build (100%) rename test cases/unit/{97 link full name => 98 link full name}/libtestprovider/provider.c (100%) rename test cases/unit/{97 link full name => 98 link full name}/proguser/meson.build (100%) rename test cases/unit/{97 link full name => 98 link full name}/proguser/receiver.c (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/bar-custom.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/bar-devel.h (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/bar-notag.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/custom_files/data.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/excludes/excluded.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/excludes/excluded/placeholder.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/excludes/installed.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/foo.in (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/foo1-devel.h (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/lib.c (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/main.c (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/meson.build (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/script.py (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/bar2-devel.h (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/foo2.in (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/foo3-devel.h (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/lib.c (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/main.c (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/meson.build (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subdir/script.py (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subprojects/subproject/aaa.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subprojects/subproject/bbb.txt (100%) rename test cases/unit/{98 install all targets => 99 install all targets}/subprojects/subproject/meson.build (100%) diff --git a/test cases/rust/20 transitive dependencies/diamond/func.c b/test cases/rust/21 transitive dependencies/diamond/func.c similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/func.c rename to test cases/rust/21 transitive dependencies/diamond/func.c diff --git a/test cases/rust/20 transitive dependencies/diamond/main.c b/test cases/rust/21 transitive dependencies/diamond/main.c similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/main.c rename to test cases/rust/21 transitive dependencies/diamond/main.c diff --git a/test cases/rust/20 transitive dependencies/diamond/meson.build b/test cases/rust/21 transitive dependencies/diamond/meson.build similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/meson.build rename to test cases/rust/21 transitive dependencies/diamond/meson.build diff --git a/test cases/rust/20 transitive dependencies/diamond/r1.rs b/test cases/rust/21 transitive dependencies/diamond/r1.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/r1.rs rename to test cases/rust/21 transitive dependencies/diamond/r1.rs diff --git a/test cases/rust/20 transitive dependencies/diamond/r2.rs b/test cases/rust/21 transitive dependencies/diamond/r2.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/r2.rs rename to test cases/rust/21 transitive dependencies/diamond/r2.rs diff --git a/test cases/rust/20 transitive dependencies/diamond/r3.rs b/test cases/rust/21 transitive dependencies/diamond/r3.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/diamond/r3.rs rename to test cases/rust/21 transitive dependencies/diamond/r3.rs diff --git a/test cases/rust/20 transitive dependencies/foo.c b/test cases/rust/21 transitive dependencies/foo.c similarity index 100% rename from test cases/rust/20 transitive dependencies/foo.c rename to test cases/rust/21 transitive dependencies/foo.c diff --git a/test cases/rust/20 transitive dependencies/foo.rs b/test cases/rust/21 transitive dependencies/foo.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/foo.rs rename to test cases/rust/21 transitive dependencies/foo.rs diff --git a/test cases/rust/20 transitive dependencies/liba/lib.rs b/test cases/rust/21 transitive dependencies/liba/lib.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/liba/lib.rs rename to test cases/rust/21 transitive dependencies/liba/lib.rs diff --git a/test cases/rust/20 transitive dependencies/liba/meson.build b/test cases/rust/21 transitive dependencies/liba/meson.build similarity index 100% rename from test cases/rust/20 transitive dependencies/liba/meson.build rename to test cases/rust/21 transitive dependencies/liba/meson.build diff --git a/test cases/rust/20 transitive dependencies/libb/lib.rs b/test cases/rust/21 transitive dependencies/libb/lib.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/libb/lib.rs rename to test cases/rust/21 transitive dependencies/libb/lib.rs diff --git a/test cases/rust/20 transitive dependencies/libb/meson.build b/test cases/rust/21 transitive dependencies/libb/meson.build similarity index 100% rename from test cases/rust/20 transitive dependencies/libb/meson.build rename to test cases/rust/21 transitive dependencies/libb/meson.build diff --git a/test cases/rust/20 transitive dependencies/main.rs b/test cases/rust/21 transitive dependencies/main.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/main.rs rename to test cases/rust/21 transitive dependencies/main.rs diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/21 transitive dependencies/meson.build similarity index 100% rename from test cases/rust/20 transitive dependencies/meson.build rename to test cases/rust/21 transitive dependencies/meson.build diff --git a/test cases/rust/20 transitive dependencies/proc.rs b/test cases/rust/21 transitive dependencies/proc.rs similarity index 100% rename from test cases/rust/20 transitive dependencies/proc.rs rename to test cases/rust/21 transitive dependencies/proc.rs diff --git a/test cases/rust/20 transitive dependencies/test.json b/test cases/rust/21 transitive dependencies/test.json similarity index 100% rename from test cases/rust/20 transitive dependencies/test.json rename to test cases/rust/21 transitive dependencies/test.json diff --git a/test cases/rust/21 cargo subproject/main.c b/test cases/rust/22 cargo subproject/main.c similarity index 100% rename from test cases/rust/21 cargo subproject/main.c rename to test cases/rust/22 cargo subproject/main.c diff --git a/test cases/rust/21 cargo subproject/meson.build b/test cases/rust/22 cargo subproject/meson.build similarity index 100% rename from test cases/rust/21 cargo subproject/meson.build rename to test cases/rust/22 cargo subproject/meson.build diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap b/test cases/rust/22 cargo subproject/subprojects/bar-rs.wrap similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap rename to test cases/rust/22 cargo subproject/subprojects/bar-rs.wrap diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml rename to test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/bar-rs/src/lib.rs similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs rename to test cases/rust/22 cargo subproject/subprojects/bar-rs/src/lib.rs diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap b/test cases/rust/22 cargo subproject/subprojects/foo-rs.wrap similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap rename to test cases/rust/22 cargo subproject/subprojects/foo-rs.wrap diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml rename to test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs similarity index 100% rename from test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs rename to test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs diff --git a/test cases/unit/99 custom target name/file.txt.in b/test cases/unit/100 custom target name/file.txt.in similarity index 100% rename from test cases/unit/99 custom target name/file.txt.in rename to test cases/unit/100 custom target name/file.txt.in diff --git a/test cases/unit/99 custom target name/meson.build b/test cases/unit/100 custom target name/meson.build similarity index 100% rename from test cases/unit/99 custom target name/meson.build rename to test cases/unit/100 custom target name/meson.build diff --git a/test cases/unit/99 custom target name/subdir/meson.build b/test cases/unit/100 custom target name/subdir/meson.build similarity index 100% rename from test cases/unit/99 custom target name/subdir/meson.build rename to test cases/unit/100 custom target name/subdir/meson.build diff --git a/test cases/unit/100 relative find program/foo.py b/test cases/unit/101 relative find program/foo.py similarity index 100% rename from test cases/unit/100 relative find program/foo.py rename to test cases/unit/101 relative find program/foo.py diff --git a/test cases/unit/100 relative find program/meson.build b/test cases/unit/101 relative find program/meson.build similarity index 100% rename from test cases/unit/100 relative find program/meson.build rename to test cases/unit/101 relative find program/meson.build diff --git a/test cases/unit/100 relative find program/subdir/meson.build b/test cases/unit/101 relative find program/subdir/meson.build similarity index 100% rename from test cases/unit/100 relative find program/subdir/meson.build rename to test cases/unit/101 relative find program/subdir/meson.build diff --git a/test cases/unit/101 rlib linkage/lib2.rs b/test cases/unit/102 rlib linkage/lib2.rs similarity index 100% rename from test cases/unit/101 rlib linkage/lib2.rs rename to test cases/unit/102 rlib linkage/lib2.rs diff --git a/test cases/unit/101 rlib linkage/main.rs b/test cases/unit/102 rlib linkage/main.rs similarity index 100% rename from test cases/unit/101 rlib linkage/main.rs rename to test cases/unit/102 rlib linkage/main.rs diff --git a/test cases/unit/101 rlib linkage/meson.build b/test cases/unit/102 rlib linkage/meson.build similarity index 100% rename from test cases/unit/101 rlib linkage/meson.build rename to test cases/unit/102 rlib linkage/meson.build diff --git a/test cases/unit/102 python without pkgconfig/meson.build b/test cases/unit/103 python without pkgconfig/meson.build similarity index 100% rename from test cases/unit/102 python without pkgconfig/meson.build rename to test cases/unit/103 python without pkgconfig/meson.build diff --git a/test cases/unit/103 strip/lib.c b/test cases/unit/104 strip/lib.c similarity index 100% rename from test cases/unit/103 strip/lib.c rename to test cases/unit/104 strip/lib.c diff --git a/test cases/unit/103 strip/meson.build b/test cases/unit/104 strip/meson.build similarity index 100% rename from test cases/unit/103 strip/meson.build rename to test cases/unit/104 strip/meson.build diff --git a/test cases/unit/104 debug function/meson.build b/test cases/unit/105 debug function/meson.build similarity index 100% rename from test cases/unit/104 debug function/meson.build rename to test cases/unit/105 debug function/meson.build diff --git a/test cases/unit/105 pkgconfig relocatable with absolute path/meson.build b/test cases/unit/106 pkgconfig relocatable with absolute path/meson.build similarity index 100% rename from test cases/unit/105 pkgconfig relocatable with absolute path/meson.build rename to test cases/unit/106 pkgconfig relocatable with absolute path/meson.build diff --git a/test cases/unit/91 install skip subprojects/foo.c b/test cases/unit/92 install skip subprojects/foo.c similarity index 100% rename from test cases/unit/91 install skip subprojects/foo.c rename to test cases/unit/92 install skip subprojects/foo.c diff --git a/test cases/unit/91 install skip subprojects/foo.dat b/test cases/unit/92 install skip subprojects/foo.dat similarity index 100% rename from test cases/unit/91 install skip subprojects/foo.dat rename to test cases/unit/92 install skip subprojects/foo.dat diff --git a/test cases/unit/91 install skip subprojects/foo.h b/test cases/unit/92 install skip subprojects/foo.h similarity index 100% rename from test cases/unit/91 install skip subprojects/foo.h rename to test cases/unit/92 install skip subprojects/foo.h diff --git a/test cases/unit/91 install skip subprojects/foo/foofile b/test cases/unit/92 install skip subprojects/foo/foofile similarity index 100% rename from test cases/unit/91 install skip subprojects/foo/foofile rename to test cases/unit/92 install skip subprojects/foo/foofile diff --git a/test cases/unit/91 install skip subprojects/meson.build b/test cases/unit/92 install skip subprojects/meson.build similarity index 100% rename from test cases/unit/91 install skip subprojects/meson.build rename to test cases/unit/92 install skip subprojects/meson.build diff --git a/test cases/unit/91 install skip subprojects/subprojects/bar/bar.c b/test cases/unit/92 install skip subprojects/subprojects/bar/bar.c similarity index 100% rename from test cases/unit/91 install skip subprojects/subprojects/bar/bar.c rename to test cases/unit/92 install skip subprojects/subprojects/bar/bar.c diff --git a/test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat b/test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat similarity index 100% rename from test cases/unit/91 install skip subprojects/subprojects/bar/bar.dat rename to test cases/unit/92 install skip subprojects/subprojects/bar/bar.dat diff --git a/test cases/unit/91 install skip subprojects/subprojects/bar/bar.h b/test cases/unit/92 install skip subprojects/subprojects/bar/bar.h similarity index 100% rename from test cases/unit/91 install skip subprojects/subprojects/bar/bar.h rename to test cases/unit/92 install skip subprojects/subprojects/bar/bar.h diff --git a/test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile b/test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile similarity index 100% rename from test cases/unit/91 install skip subprojects/subprojects/bar/bar/barfile rename to test cases/unit/92 install skip subprojects/subprojects/bar/bar/barfile diff --git a/test cases/unit/91 install skip subprojects/subprojects/bar/meson.build b/test cases/unit/92 install skip subprojects/subprojects/bar/meson.build similarity index 100% rename from test cases/unit/91 install skip subprojects/subprojects/bar/meson.build rename to test cases/unit/92 install skip subprojects/subprojects/bar/meson.build diff --git a/test cases/unit/92 new subproject in configured project/meson.build b/test cases/unit/93 new subproject in configured project/meson.build similarity index 100% rename from test cases/unit/92 new subproject in configured project/meson.build rename to test cases/unit/93 new subproject in configured project/meson.build diff --git a/test cases/unit/92 new subproject in configured project/meson_options.txt b/test cases/unit/93 new subproject in configured project/meson_options.txt similarity index 100% rename from test cases/unit/92 new subproject in configured project/meson_options.txt rename to test cases/unit/93 new subproject in configured project/meson_options.txt diff --git a/test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c b/test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c similarity index 100% rename from test cases/unit/92 new subproject in configured project/subprojects/sub/foo.c rename to test cases/unit/93 new subproject in configured project/subprojects/sub/foo.c diff --git a/test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build b/test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build similarity index 100% rename from test cases/unit/92 new subproject in configured project/subprojects/sub/meson.build rename to test cases/unit/93 new subproject in configured project/subprojects/sub/meson.build diff --git a/test cases/unit/93 clangformat/.clang-format b/test cases/unit/94 clangformat/.clang-format similarity index 100% rename from test cases/unit/93 clangformat/.clang-format rename to test cases/unit/94 clangformat/.clang-format diff --git a/test cases/unit/93 clangformat/.clang-format-ignore b/test cases/unit/94 clangformat/.clang-format-ignore similarity index 100% rename from test cases/unit/93 clangformat/.clang-format-ignore rename to test cases/unit/94 clangformat/.clang-format-ignore diff --git a/test cases/unit/93 clangformat/.clang-format-include b/test cases/unit/94 clangformat/.clang-format-include similarity index 100% rename from test cases/unit/93 clangformat/.clang-format-include rename to test cases/unit/94 clangformat/.clang-format-include diff --git a/test cases/unit/93 clangformat/meson.build b/test cases/unit/94 clangformat/meson.build similarity index 100% rename from test cases/unit/93 clangformat/meson.build rename to test cases/unit/94 clangformat/meson.build diff --git a/test cases/unit/93 clangformat/not-included/badformat.cpp b/test cases/unit/94 clangformat/not-included/badformat.cpp similarity index 100% rename from test cases/unit/93 clangformat/not-included/badformat.cpp rename to test cases/unit/94 clangformat/not-included/badformat.cpp diff --git a/test cases/unit/93 clangformat/src/badformat.c b/test cases/unit/94 clangformat/src/badformat.c similarity index 100% rename from test cases/unit/93 clangformat/src/badformat.c rename to test cases/unit/94 clangformat/src/badformat.c diff --git a/test cases/unit/93 clangformat/src/badformat.cpp b/test cases/unit/94 clangformat/src/badformat.cpp similarity index 100% rename from test cases/unit/93 clangformat/src/badformat.cpp rename to test cases/unit/94 clangformat/src/badformat.cpp diff --git a/test cases/unit/94 custominc/easytogrepfor/genh.py b/test cases/unit/95 custominc/easytogrepfor/genh.py similarity index 100% rename from test cases/unit/94 custominc/easytogrepfor/genh.py rename to test cases/unit/95 custominc/easytogrepfor/genh.py diff --git a/test cases/unit/94 custominc/easytogrepfor/meson.build b/test cases/unit/95 custominc/easytogrepfor/meson.build similarity index 100% rename from test cases/unit/94 custominc/easytogrepfor/meson.build rename to test cases/unit/95 custominc/easytogrepfor/meson.build diff --git a/test cases/unit/94 custominc/helper.c b/test cases/unit/95 custominc/helper.c similarity index 100% rename from test cases/unit/94 custominc/helper.c rename to test cases/unit/95 custominc/helper.c diff --git a/test cases/unit/94 custominc/meson.build b/test cases/unit/95 custominc/meson.build similarity index 100% rename from test cases/unit/94 custominc/meson.build rename to test cases/unit/95 custominc/meson.build diff --git a/test cases/unit/94 custominc/prog.c b/test cases/unit/95 custominc/prog.c similarity index 100% rename from test cases/unit/94 custominc/prog.c rename to test cases/unit/95 custominc/prog.c diff --git a/test cases/unit/94 custominc/prog2.c b/test cases/unit/95 custominc/prog2.c similarity index 100% rename from test cases/unit/94 custominc/prog2.c rename to test cases/unit/95 custominc/prog2.c diff --git a/test cases/unit/95 implicit force fallback/meson.build b/test cases/unit/96 implicit force fallback/meson.build similarity index 100% rename from test cases/unit/95 implicit force fallback/meson.build rename to test cases/unit/96 implicit force fallback/meson.build diff --git a/test cases/unit/95 implicit force fallback/subprojects/something/meson.build b/test cases/unit/96 implicit force fallback/subprojects/something/meson.build similarity index 100% rename from test cases/unit/95 implicit force fallback/subprojects/something/meson.build rename to test cases/unit/96 implicit force fallback/subprojects/something/meson.build diff --git a/test cases/unit/96 compiler.links file arg/meson.build b/test cases/unit/97 compiler.links file arg/meson.build similarity index 100% rename from test cases/unit/96 compiler.links file arg/meson.build rename to test cases/unit/97 compiler.links file arg/meson.build diff --git a/test cases/unit/96 compiler.links file arg/test.c b/test cases/unit/97 compiler.links file arg/test.c similarity index 100% rename from test cases/unit/96 compiler.links file arg/test.c rename to test cases/unit/97 compiler.links file arg/test.c diff --git a/test cases/unit/97 link full name/.gitignore b/test cases/unit/98 link full name/.gitignore similarity index 100% rename from test cases/unit/97 link full name/.gitignore rename to test cases/unit/98 link full name/.gitignore diff --git a/test cases/unit/97 link full name/libtestprovider/meson.build b/test cases/unit/98 link full name/libtestprovider/meson.build similarity index 100% rename from test cases/unit/97 link full name/libtestprovider/meson.build rename to test cases/unit/98 link full name/libtestprovider/meson.build diff --git a/test cases/unit/97 link full name/libtestprovider/provider.c b/test cases/unit/98 link full name/libtestprovider/provider.c similarity index 100% rename from test cases/unit/97 link full name/libtestprovider/provider.c rename to test cases/unit/98 link full name/libtestprovider/provider.c diff --git a/test cases/unit/97 link full name/proguser/meson.build b/test cases/unit/98 link full name/proguser/meson.build similarity index 100% rename from test cases/unit/97 link full name/proguser/meson.build rename to test cases/unit/98 link full name/proguser/meson.build diff --git a/test cases/unit/97 link full name/proguser/receiver.c b/test cases/unit/98 link full name/proguser/receiver.c similarity index 100% rename from test cases/unit/97 link full name/proguser/receiver.c rename to test cases/unit/98 link full name/proguser/receiver.c diff --git a/test cases/unit/98 install all targets/bar-custom.txt b/test cases/unit/99 install all targets/bar-custom.txt similarity index 100% rename from test cases/unit/98 install all targets/bar-custom.txt rename to test cases/unit/99 install all targets/bar-custom.txt diff --git a/test cases/unit/98 install all targets/bar-devel.h b/test cases/unit/99 install all targets/bar-devel.h similarity index 100% rename from test cases/unit/98 install all targets/bar-devel.h rename to test cases/unit/99 install all targets/bar-devel.h diff --git a/test cases/unit/98 install all targets/bar-notag.txt b/test cases/unit/99 install all targets/bar-notag.txt similarity index 100% rename from test cases/unit/98 install all targets/bar-notag.txt rename to test cases/unit/99 install all targets/bar-notag.txt diff --git a/test cases/unit/98 install all targets/custom_files/data.txt b/test cases/unit/99 install all targets/custom_files/data.txt similarity index 100% rename from test cases/unit/98 install all targets/custom_files/data.txt rename to test cases/unit/99 install all targets/custom_files/data.txt diff --git a/test cases/unit/98 install all targets/excludes/excluded.txt b/test cases/unit/99 install all targets/excludes/excluded.txt similarity index 100% rename from test cases/unit/98 install all targets/excludes/excluded.txt rename to test cases/unit/99 install all targets/excludes/excluded.txt diff --git a/test cases/unit/98 install all targets/excludes/excluded/placeholder.txt b/test cases/unit/99 install all targets/excludes/excluded/placeholder.txt similarity index 100% rename from test cases/unit/98 install all targets/excludes/excluded/placeholder.txt rename to test cases/unit/99 install all targets/excludes/excluded/placeholder.txt diff --git a/test cases/unit/98 install all targets/excludes/installed.txt b/test cases/unit/99 install all targets/excludes/installed.txt similarity index 100% rename from test cases/unit/98 install all targets/excludes/installed.txt rename to test cases/unit/99 install all targets/excludes/installed.txt diff --git a/test cases/unit/98 install all targets/foo.in b/test cases/unit/99 install all targets/foo.in similarity index 100% rename from test cases/unit/98 install all targets/foo.in rename to test cases/unit/99 install all targets/foo.in diff --git a/test cases/unit/98 install all targets/foo1-devel.h b/test cases/unit/99 install all targets/foo1-devel.h similarity index 100% rename from test cases/unit/98 install all targets/foo1-devel.h rename to test cases/unit/99 install all targets/foo1-devel.h diff --git a/test cases/unit/98 install all targets/lib.c b/test cases/unit/99 install all targets/lib.c similarity index 100% rename from test cases/unit/98 install all targets/lib.c rename to test cases/unit/99 install all targets/lib.c diff --git a/test cases/unit/98 install all targets/main.c b/test cases/unit/99 install all targets/main.c similarity index 100% rename from test cases/unit/98 install all targets/main.c rename to test cases/unit/99 install all targets/main.c diff --git a/test cases/unit/98 install all targets/meson.build b/test cases/unit/99 install all targets/meson.build similarity index 100% rename from test cases/unit/98 install all targets/meson.build rename to test cases/unit/99 install all targets/meson.build diff --git a/test cases/unit/98 install all targets/script.py b/test cases/unit/99 install all targets/script.py similarity index 100% rename from test cases/unit/98 install all targets/script.py rename to test cases/unit/99 install all targets/script.py diff --git a/test cases/unit/98 install all targets/subdir/bar2-devel.h b/test cases/unit/99 install all targets/subdir/bar2-devel.h similarity index 100% rename from test cases/unit/98 install all targets/subdir/bar2-devel.h rename to test cases/unit/99 install all targets/subdir/bar2-devel.h diff --git a/test cases/unit/98 install all targets/subdir/foo2.in b/test cases/unit/99 install all targets/subdir/foo2.in similarity index 100% rename from test cases/unit/98 install all targets/subdir/foo2.in rename to test cases/unit/99 install all targets/subdir/foo2.in diff --git a/test cases/unit/98 install all targets/subdir/foo3-devel.h b/test cases/unit/99 install all targets/subdir/foo3-devel.h similarity index 100% rename from test cases/unit/98 install all targets/subdir/foo3-devel.h rename to test cases/unit/99 install all targets/subdir/foo3-devel.h diff --git a/test cases/unit/98 install all targets/subdir/lib.c b/test cases/unit/99 install all targets/subdir/lib.c similarity index 100% rename from test cases/unit/98 install all targets/subdir/lib.c rename to test cases/unit/99 install all targets/subdir/lib.c diff --git a/test cases/unit/98 install all targets/subdir/main.c b/test cases/unit/99 install all targets/subdir/main.c similarity index 100% rename from test cases/unit/98 install all targets/subdir/main.c rename to test cases/unit/99 install all targets/subdir/main.c diff --git a/test cases/unit/98 install all targets/subdir/meson.build b/test cases/unit/99 install all targets/subdir/meson.build similarity index 100% rename from test cases/unit/98 install all targets/subdir/meson.build rename to test cases/unit/99 install all targets/subdir/meson.build diff --git a/test cases/unit/98 install all targets/subdir/script.py b/test cases/unit/99 install all targets/subdir/script.py similarity index 100% rename from test cases/unit/98 install all targets/subdir/script.py rename to test cases/unit/99 install all targets/subdir/script.py diff --git a/test cases/unit/98 install all targets/subprojects/subproject/aaa.txt b/test cases/unit/99 install all targets/subprojects/subproject/aaa.txt similarity index 100% rename from test cases/unit/98 install all targets/subprojects/subproject/aaa.txt rename to test cases/unit/99 install all targets/subprojects/subproject/aaa.txt diff --git a/test cases/unit/98 install all targets/subprojects/subproject/bbb.txt b/test cases/unit/99 install all targets/subprojects/subproject/bbb.txt similarity index 100% rename from test cases/unit/98 install all targets/subprojects/subproject/bbb.txt rename to test cases/unit/99 install all targets/subprojects/subproject/bbb.txt diff --git a/test cases/unit/98 install all targets/subprojects/subproject/meson.build b/test cases/unit/99 install all targets/subprojects/subproject/meson.build similarity index 100% rename from test cases/unit/98 install all targets/subprojects/subproject/meson.build rename to test cases/unit/99 install all targets/subprojects/subproject/meson.build diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 53a0042c27e6..86a6b61c9a8f 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -634,7 +634,7 @@ def test_forcefallback(self): self.run_tests() def test_implicit_forcefallback(self): - testdir = os.path.join(self.unit_test_dir, '95 implicit force fallback') + testdir = os.path.join(self.unit_test_dir, '96 implicit force fallback') with self.assertRaises(subprocess.CalledProcessError): self.init(testdir) self.init(testdir, extra_args=['--wrap-mode=forcefallback']) @@ -1958,7 +1958,7 @@ def check_pcfile(name, *, relocatable, levels=2): check_pcfile('libvartest2.pc', relocatable=False) self.wipe() - testdir_abs = os.path.join(self.unit_test_dir, '105 pkgconfig relocatable with absolute path') + testdir_abs = os.path.join(self.unit_test_dir, '106 pkgconfig relocatable with absolute path') self.init(testdir_abs) check_pcfile('libsimple.pc', relocatable=True, levels=3) @@ -2369,7 +2369,7 @@ def test_check_module_linking(self): self.assertIn(msg, out) def test_mixed_language_linker_check(self): - testdir = os.path.join(self.unit_test_dir, '96 compiler.links file arg') + testdir = os.path.join(self.unit_test_dir, '97 compiler.links file arg') self.init(testdir) cmds = self.get_meson_log_compiler_checks() self.assertEqual(len(cmds), 5) @@ -4206,7 +4206,7 @@ def test_build_b_options(self) -> None: self.init(srcdir, extra_args=['-Dbuild.b_lto=true']) def test_install_skip_subprojects(self): - testdir = os.path.join(self.unit_test_dir, '91 install skip subprojects') + testdir = os.path.join(self.unit_test_dir, '92 install skip subprojects') self.init(testdir) self.build() @@ -4253,7 +4253,7 @@ def check_installed_files(extra_args, expected): check_installed_files(['--skip-subprojects', 'another'], all_expected) def test_adding_subproject_to_configure_project(self) -> None: - srcdir = os.path.join(self.unit_test_dir, '92 new subproject in configured project') + srcdir = os.path.join(self.unit_test_dir, '93 new subproject in configured project') self.init(srcdir) self.build() self.setconf('-Duse-sub=true') @@ -4303,7 +4303,7 @@ def test_clang_format_check(self): if not shutil.which('clang-format'): raise SkipTest('clang-format not found') - testdir = os.path.join(self.unit_test_dir, '93 clangformat') + testdir = os.path.join(self.unit_test_dir, '94 clangformat') newdir = os.path.join(self.builddir, 'testdir') shutil.copytree(testdir, newdir) self.new_builddir() @@ -4328,7 +4328,7 @@ def test_clang_format_check(self): self.build('clang-format-check') def test_custom_target_implicit_include(self): - testdir = os.path.join(self.unit_test_dir, '94 custominc') + testdir = os.path.join(self.unit_test_dir, '95 custominc') self.init(testdir) self.build() compdb = self.get_compdb() @@ -4368,7 +4368,7 @@ def test_env_flags_to_linker(self) -> None: self.assertEqual(sorted(link_args), sorted(['-flto'])) def test_install_tag(self) -> None: - testdir = os.path.join(self.unit_test_dir, '98 install all targets') + testdir = os.path.join(self.unit_test_dir, '99 install all targets') self.init(testdir) self.build() @@ -4539,7 +4539,7 @@ def test_install_script_dry_run(self): def test_introspect_install_plan(self): - testdir = os.path.join(self.unit_test_dir, '98 install all targets') + testdir = os.path.join(self.unit_test_dir, '99 install all targets') introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json') self.init(testdir) self.assertPathExists(introfile) @@ -4791,7 +4791,7 @@ def test_rust_rlib_linkage(self) -> None: }} ''') - testdir = os.path.join(self.unit_test_dir, '101 rlib linkage') + testdir = os.path.join(self.unit_test_dir, '102 rlib linkage') gen_file = os.path.join(testdir, 'lib.rs') with open(gen_file, 'w', encoding='utf-8') as f: f.write(template.format(0)) @@ -4839,7 +4839,7 @@ def test_bindgen_drops_invalid(self) -> None: return def test_custom_target_name(self): - testdir = os.path.join(self.unit_test_dir, '99 custom target name') + testdir = os.path.join(self.unit_test_dir, '100 custom target name') self.init(testdir) out = self.build() if self.backend is Backend.ninja: diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index de86fa7fa3e3..4fcf52e09f2c 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -1366,7 +1366,7 @@ def test_link_arg_fullname(self): see: https://github.com/mesonbuild/meson/issues/9000 https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a ''' - testdir = os.path.join(self.unit_test_dir, '97 link full name','libtestprovider') + testdir = os.path.join(self.unit_test_dir, '98 link full name','libtestprovider') oldprefix = self.prefix # install into installdir without using DESTDIR installdir = self.installdir @@ -1379,7 +1379,7 @@ def test_link_arg_fullname(self): self.new_builddir() env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir), 'PKG_CONFIG_PATH': _prepend_pkg_config_path(os.path.join(installdir, self.libdir, 'pkgconfig'))} - testdir = os.path.join(self.unit_test_dir, '97 link full name','proguser') + testdir = os.path.join(self.unit_test_dir, '98 link full name','proguser') self.init(testdir,override_envvars=env) # test for link with full path @@ -1791,7 +1791,7 @@ def test_cmake_multilib(self): @skipUnless(is_linux() or is_osx(), 'Test only applicable to Linux and macOS') def test_install_strip(self): - testdir = os.path.join(self.unit_test_dir, '103 strip') + testdir = os.path.join(self.unit_test_dir, '104 strip') self.init(testdir) self.build() diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 1f4ea7ea07e0..31dea0ffe8ec 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -39,7 +39,7 @@ def test_relative_find_program(self): Tests that find_program() with a relative path does not find the program in current workdir. ''' - testdir = os.path.join(self.unit_test_dir, '100 relative find program') + testdir = os.path.join(self.unit_test_dir, '101 relative find program') self.init(testdir, workdir=testdir) def test_invalid_option_names(self): @@ -75,11 +75,11 @@ def write_file(code: str): interp.process(fname) def test_python_dependency_without_pkgconfig(self): - testdir = os.path.join(self.unit_test_dir, '102 python without pkgconfig') + testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) def test_debug_function_outputs_to_meson_log(self): - testdir = os.path.join(self.unit_test_dir, '104 debug function') + testdir = os.path.join(self.unit_test_dir, '105 debug function') log_msg = 'This is an example debug output, should only end up in debug log' output = self.init(testdir) From 76e6340f4bd5ee0d3dffaa84c5cdd10fbee61f7f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 12 Nov 2023 12:19:58 -0500 Subject: [PATCH 423/855] fix regression in converting build_target kwargs to typed_kwargs We haven't actually verified that these kwargs are equal to what we had before, and should probably revert the entire series. But I have multiple reports in the wild of projects that no longer build because of `install: [true, false, get_option('foobar')]` which was always incorrect and always equal to just dropping values all over the floor and treating it the same as "bool(value) == True". Special case this particular typed kwarg and allow it with a sternly worded warning that it was always wrong and should never ever ever be done. Fixes: https://bugs.gentoo.org/917118 Fixes: http://qa-logs.debian.net/2023/11/11/rhythmbox_3.4.7-1_unstable_meson-exp.log Thanks to the Gentoo Tinderbox project, and Lucas Nussbaum of the Debian project. --- mesonbuild/interpreter/interpreter.py | 7 +++++++ mesonbuild/interpreter/type_checking.py | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 2fba33486aff..e885010b23a1 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -3318,6 +3318,13 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs # backwards compatibility anyway sources = [s for s in sources if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))] + + # due to lack of type checking, these are "allowed" for legacy reasons + if not isinstance(kwargs['install'], bool): + FeatureBroken.single_use('install kwarg with non-boolean value', '1.3.0', self.subproject, + 'This was never intended to work, and is essentially the same as using `install: true` regardless of value.', + node) + sources = self.source_strings_to_files(sources) objs = kwargs['objects'] kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index e7edc1939b18..06ded7298d07 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -573,7 +573,8 @@ def _objects_validator(vals: T.List[ObjectTypes]) -> T.Optional[str]: OVERRIDE_OPTIONS_KW, KwargInfo('build_by_default', bool, default=True, since='0.38.0'), KwargInfo('extra_files', ContainerTypeInfo(list, (str, File)), default=[], listify=True), - INSTALL_KW, + # Accursed. We allow this for backwards compat and warn in the interpreter. + KwargInfo('install', object, default=False), INSTALL_MODE_KW, KwargInfo('implicit_include_directories', bool, default=True, since='0.42.0'), NATIVE_KW, From 0bc01e87d9a82c59ae77ba62a9b3fe26922afee8 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 12 Nov 2023 19:57:21 -0500 Subject: [PATCH 424/855] CI: adapt to renamed fedora package when building updated images --- ci/ciimage/fedora/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/fedora/install.sh b/ci/ciimage/fedora/install.sh index 2f1ae7dfd2fd..dc9c20af3e74 100755 --- a/ci/ciimage/fedora/install.sh +++ b/ci/ciimage/fedora/install.sh @@ -8,7 +8,7 @@ pkgs=( python python-pip python3-devel ninja-build make git autoconf automake patch elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-objc++ vala rust bison flex ldc libasan libasan-static - mono-core boost-devel gtkmm30 gtest-devel gmock-devel protobuf-devel wxGTK3-devel gobject-introspection + mono-core boost-devel gtkmm30 gtest-devel gmock-devel protobuf-devel wxGTK-devel gobject-introspection boost-python3-devel itstool gtk3-devel java-latest-openjdk-devel gtk-doc llvm-devel clang-devel SDL2-devel graphviz-devel zlib zlib-devel zlib-static #hdf5-openmpi-devel hdf5-devel netcdf-openmpi-devel netcdf-devel netcdf-fortran-openmpi-devel netcdf-fortran-devel scalapack-openmpi-devel From 2da53e943ad9d44c4416ec4cca8ef549bf40d7b3 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 13 Nov 2023 14:31:21 -0500 Subject: [PATCH 425/855] rust: Add transitive dependencies to ninja rules In the case r1 -> s1 -> s2 where s1 and s2 are uninstalled C static libraries, the libs1.a rule does not depend on libs2.a. That means that r1 rule must depend on both s1 and s2. --- mesonbuild/backend/ninjabackend.py | 6 ++---- test cases/rust/21 transitive dependencies/app.rs | 9 +++++++++ test cases/rust/21 transitive dependencies/meson.build | 8 ++++++++ test cases/rust/21 transitive dependencies/static1.c | 5 +++++ test cases/rust/21 transitive dependencies/static2.c | 7 +++++++ 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 test cases/rust/21 transitive dependencies/app.rs create mode 100644 test cases/rust/21 transitive dependencies/static1.c create mode 100644 test cases/rust/21 transitive dependencies/static2.c diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 7ed6b443f140..049ae253fe34 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1877,10 +1877,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: self.generate_generator_list_rules(target) # dependencies need to cause a relink, they're not just for ordering - deps = [ - os.path.join(t.subdir, t.get_filename()) - for t in itertools.chain(target.link_targets, target.link_whole_targets) - ] + deps: T.List[str] = [] # Dependencies for rust-project.json project_deps: T.List[RustDep] = [] @@ -1983,6 +1980,7 @@ def _link_library(libname: str, static: bool, bundle: bool = False): target_deps = target.get_dependencies() for d in target_deps: linkdirs.add(d.subdir) + deps.append(self.get_dependency_filename(d)) if d.uses_rust_abi(): if d not in itertools.chain(target.link_targets, target.link_whole_targets): # Indirect Rust ABI dependency, we only need its path in linkdirs. diff --git a/test cases/rust/21 transitive dependencies/app.rs b/test cases/rust/21 transitive dependencies/app.rs new file mode 100644 index 000000000000..a9802b311815 --- /dev/null +++ b/test cases/rust/21 transitive dependencies/app.rs @@ -0,0 +1,9 @@ +extern "C" { + fn static2() -> i32; +} + +fn main() { + unsafe { + static2(); + } +} diff --git a/test cases/rust/21 transitive dependencies/meson.build b/test cases/rust/21 transitive dependencies/meson.build index b786e64949f5..37687fd4db2f 100644 --- a/test cases/rust/21 transitive dependencies/meson.build +++ b/test cases/rust/21 transitive dependencies/meson.build @@ -27,3 +27,11 @@ exe = executable('footest', 'foo.c', test('footest', exe) subdir('diamond') + +# The ninja rule for libstatic2.a does not depend on libstatic1.a because it +# only need static2.c.o to create the archive. That means that the ninja rule +# for app must depend on both, otherwise libstatic1.a won't be built and linking +# will fail. +static1 = static_library('static1', 'static1.c', build_by_default: false) +static2 = static_library('static2', 'static2.c', link_with: static1) +exe = executable('app', 'app.rs', link_with: static2) diff --git a/test cases/rust/21 transitive dependencies/static1.c b/test cases/rust/21 transitive dependencies/static1.c new file mode 100644 index 000000000000..104618a6f734 --- /dev/null +++ b/test cases/rust/21 transitive dependencies/static1.c @@ -0,0 +1,5 @@ +int static1(void); + +int static1(void){ + return 1; +} diff --git a/test cases/rust/21 transitive dependencies/static2.c b/test cases/rust/21 transitive dependencies/static2.c new file mode 100644 index 000000000000..6877c04c65cf --- /dev/null +++ b/test cases/rust/21 transitive dependencies/static2.c @@ -0,0 +1,7 @@ +int static1(void); +int static2(void); + +int static2(void) +{ + return 1 + static1(); +} From cddf2e9d872ebbc673d2595bc176a0572d258222 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 13 Nov 2023 14:32:13 -0500 Subject: [PATCH 426/855] fix another regression in converting build_target kwargs to typed_kwargs This time we have a case where people are passing non-objects by using them as str | File, which we never warned about and silently accepted. If it was passed via custom_target outputs we *would* error out, interestingly enough. At the backend layer, we just pass them directly to the linker... which is valid, if we misdetected what's a valid linker input or people just used funny names. In particular, the mingw toolchain allows passing a *.def file directly, and some people are doing that. If we do want to allow this, we should do it consistently. For now, just follow the current theme of what's expected, but do so by warning instead of fatally erroring, for cases where users were able to do it in the past. --- mesonbuild/build.py | 6 ++++++ mesonbuild/interpreter/type_checking.py | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 9c27b2361542..12e7cb5ef64b 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -854,9 +854,12 @@ def check_unknown_kwargs_int(self, kwargs, known_kwargs): def process_objectlist(self, objects): assert isinstance(objects, list) + deprecated_non_objects = [] for s in objects: if isinstance(s, (str, File, ExtractedObjects)): self.objects.append(s) + if not isinstance(s, ExtractedObjects) and not is_object(s): + deprecated_non_objects.append(s) elif isinstance(s, (CustomTarget, CustomTargetIndex, GeneratedList)): non_objects = [o for o in s.get_outputs() if not is_object(o)] if non_objects: @@ -864,6 +867,9 @@ def process_objectlist(self, objects): self.generated.append(s) else: raise InvalidArguments(f'Bad object of type {type(s).__name__!r} in target {self.name!r}.') + if deprecated_non_objects: + FeatureDeprecated.single_use(f'Source file {deprecated_non_objects[0]} in the \'objects\' kwarg is not an object.', + '1.3.0', self.subproject) def process_sourcelist(self, sources: T.List['SourceOutputs']) -> None: """Split sources into generated and static sources. diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 06ded7298d07..2fa62524bb95 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -554,11 +554,8 @@ def _objects_validator(vals: T.List[ObjectTypes]) -> T.Optional[str]: non_objects: T.List[str] = [] for val in vals: - if isinstance(val, ExtractedObjects): + if isinstance(val, (str, File, ExtractedObjects)): continue - elif isinstance(val, (str, File)): - if not compilers.is_object(val): - non_objects.append(str(val)) else: non_objects.extend(o for o in val.get_outputs() if not compilers.is_object(o)) From 7e1aed0abcf41c62f2ae0a02372f3ba9afff15fc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 13 Nov 2023 12:21:20 -0800 Subject: [PATCH 427/855] type_checking: fix typo --- mesonbuild/interpreter/type_checking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 2fa62524bb95..3b6542025477 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -598,7 +598,7 @@ def _name_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: def _name_suffix_validator(arg: T.Optional[T.Union[str, T.List]]) -> T.Optional[str]: if arg == '': - return 'must nt be a empty string. An empty array may be passed if you want Meson to use the default behavior.' + return 'must not be a empty string. An empty array may be passed if you want Meson to use the default behavior.' return _name_validator(arg) From f8e87134a4e851b760d0032b9a850cdcb654bad1 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 13 Nov 2023 12:28:13 -0800 Subject: [PATCH 428/855] type_checking: simplify error message for object validation --- mesonbuild/interpreter/type_checking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 3b6542025477..5212a85ba754 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -560,7 +560,7 @@ def _objects_validator(vals: T.List[ObjectTypes]) -> T.Optional[str]: non_objects.extend(o for o in val.get_outputs() if not compilers.is_object(o)) if non_objects: - return f'File{"s" if len(non_objects) > 1 else ""}: "{", ".join(non_objects)}" are not objects' + return f'{", ".join(non_objects)!r} are not objects' return None From dac3f26ee5e8bd841023ecdd3d83c6b2e1ca60b5 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 13 Nov 2023 21:19:24 +0200 Subject: [PATCH 429/855] 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 0522257337ed..b4d3158e4ddc 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -61,7 +61,7 @@ # # 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.3.0.rc2' +version = '1.3.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 398c4b22874c2f67eb2eca6371e5a94d21ab8eed Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 13 Nov 2023 18:45:54 -0500 Subject: [PATCH 430/855] dependencies: allow get_variable to define multiple pkgconfig defines It was previously impossible to do this: ``` dep.get_pkgconfig_variable( 'foo', define_variable: ['prefix', '/usr', 'datadir', '/usr/share'], ) ``` since get_pkgconfig_variable mandated exactly two (if any) arguments. However, you could do this: ``` dep.get_variable( 'foo', pkgconfig_define: ['prefix', '/usr', 'datadir', '/usr/share'], ) ``` It would silently do the wrong thing, by defining "prefix" as `/usr=datadir=/usr/share`, which might not "matter" if only datadir was used in the "foo" variable as the unmodified value might be adequate. The actual intention of anyone writing such a meson.build is that they aren't sure whether the .pc file uses ${prefix} or ${datadir} (or which one gets used, might have changed between versions of that .pc file, even). A recent refactor made this into a hard error, which broke some projects that were doing this and inadvertently depending on some .pc file that only used the second variable. (This was "fine" since the result was essentially meaningful, and even resulted in behavior identical to the intended behavior if both projects were installed into the same prefix -- in which case there's nothing to remap.) Re-allow this. There are two ways we could re-allow this: - ignore it with a warning - add a new feature to allow actually doing this Since the use case which triggered this bug actually has a pretty good reason to want to do this, it makes sense to add the new feature. Fixes https://bugs.gentoo.org/916576 Fixes https://github.com/containers/bubblewrap/issues/609 --- .../snippets/pkgconfig_define_variable.md | 10 ++++++++++ docs/yaml/objects/dep.yaml | 8 ++++++++ mesonbuild/dependencies/pkgconfig.py | 6 ++++-- mesonbuild/dependencies/scalapack.py | 2 +- mesonbuild/interpreter/interpreterobjects.py | 7 +++++++ mesonbuild/interpreter/type_checking.py | 15 ++++++++++----- mesonbuild/mdevenv.py | 2 +- test cases/linuxlike/1 pkg-config/meson.build | 7 +++++++ 8 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 docs/markdown/snippets/pkgconfig_define_variable.md diff --git a/docs/markdown/snippets/pkgconfig_define_variable.md b/docs/markdown/snippets/pkgconfig_define_variable.md new file mode 100644 index 000000000000..0f7082b0d094 --- /dev/null +++ b/docs/markdown/snippets/pkgconfig_define_variable.md @@ -0,0 +1,10 @@ +## pkg-config dependencies can now get a variable with multiple replacements + +When using [[dep.get_variable]] and defining a `pkgconfig_define`, it is +sometimes useful to remap multiple dependency variables. For example, if the +upstream project changed the variable name that is interpolated and it is +desirable to support both versions. + +It is now possible to pass multiple pairs of variable/value. + +The same applies to the compatibility [[dep.get_pkgconfig_variable]] method. diff --git a/docs/yaml/objects/dep.yaml b/docs/yaml/objects/dep.yaml index d847690f0dd5..52e28faca2d2 100644 --- a/docs/yaml/objects/dep.yaml +++ b/docs/yaml/objects/dep.yaml @@ -38,6 +38,8 @@ methods: variable by passing a list to this kwarg that can affect the retrieved variable: `['prefix', '/'])`. + *(Since 1.3.0)* Multiple variables can be specified in pairs. + default: type: str since: 0.45.0 @@ -174,6 +176,12 @@ methods: from the object then `default_value` is returned, if it is not set then an error is raised. + warnings: + - Before 1.3.0, specifying multiple pkgconfig_define pairs would silently + malform the results. Only the first variable would be redefined, but + its value would contain both the second variable name, as well as its + value. + optargs: varname: type: str diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 93422defd67f..e86206b88c2e 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -139,9 +139,11 @@ def version(self, name: str) -> T.Optional[str]: @staticmethod def _define_variable_args(define_variable: PkgConfigDefineType) -> T.List[str]: + ret = [] if define_variable: - return ['--define-variable=' + '='.join(define_variable)] - return [] + for pair in define_variable: + ret.append('--define-variable=' + '='.join(pair)) + return ret @lru_cache(maxsize=None) def cflags(self, name: str, allow_system: bool = False, diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index 158056fa0311..a8e20f405e92 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -148,5 +148,5 @@ def _set_cargs(self) -> None: # gfortran doesn't appear to look in system paths for INCLUDE files, # so don't allow pkg-config to suppress -I flags for system paths allow_system = True - cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=('prefix', self.__mklroot.as_posix())) + cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=(('prefix', self.__mklroot.as_posix()),)) self.compile_args = self._convert_mingw_paths(cflags) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index effeebb2019e..f13e3ff4ad17 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -494,6 +494,9 @@ def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConf from ..dependencies.pkgconfig import PkgConfigDependency if not isinstance(self.held_object, PkgConfigDependency): raise InvalidArguments(f'{self.held_object.get_name()!r} is not a pkgconfig dependency') + if kwargs['define_variable'] and len(kwargs['define_variable']) > 1: + FeatureNew.single_use('dependency.get_pkgconfig_variable keyword argument "define_variable" with more than one pair', + '1.3.0', self.subproject, location=self.current_node) return self.held_object.get_variable( pkgconfig=args[0], default_value=kwargs['default'], @@ -536,6 +539,10 @@ def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.Depend default_varname = args[0] if default_varname is not None: FeatureNew('Positional argument to dependency.get_variable()', '0.58.0').use(self.subproject, self.current_node) + if kwargs['pkgconfig_define'] and len(kwargs['pkgconfig_define']) > 1: + FeatureNew.single_use('dependency.get_variable keyword argument "pkgconfig_define" with more than one pair', + '1.3.0', self.subproject, 'In previous versions, this silently returned a malformed value.', + self.current_node) return self.held_object.get_variable( cmake=kwargs['cmake'] or default_varname, pkgconfig=kwargs['pkgconfig'] or default_varname, diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 5212a85ba754..616f4efbb58e 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -4,8 +4,7 @@ """Helpers for strict type checking.""" from __future__ import annotations -import os -import re +import itertools, os, re import typing as T from .. import compilers @@ -30,7 +29,7 @@ from ..mesonlib import EnvInitValueType _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] - PkgConfigDefineType = T.Optional[T.Tuple[str, str]] + PkgConfigDefineType = T.Optional[T.Tuple[T.Tuple[str, str], ...]] SourcesVarargsType = T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget]] @@ -841,10 +840,16 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup ) ] +def _pkgconfig_define_convertor(x: T.List[str]) -> PkgConfigDefineType: + if x: + keys = itertools.islice(x, 0, None, 2) + vals = itertools.islice(x, 1, None, 2) + return tuple(zip(keys, vals)) + return None + PKGCONFIG_DEFINE_KW: KwargInfo = KwargInfo( 'pkgconfig_define', ContainerTypeInfo(list, str, pairs=True), default=[], - validator=lambda x: 'must be of length 2 or empty' if len(x) not in {0, 2} else None, - convertor=lambda x: tuple(x) if x else None + convertor=_pkgconfig_define_convertor, ) diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index b60d7a5729d8..9f3d1b973d28 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -87,7 +87,7 @@ def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List datadir = b.environment.coredata.get_option(OptionKey('datadir')) assert isinstance(datadir, str), 'for mypy' datadir_abs = os.path.join(prefix, datadir) - completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=('datadir', datadir_abs)) + completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=(('datadir', datadir_abs),)) assert isinstance(completionsdir, str), 'for mypy' completionsdir_path = Path(completionsdir) for f in install_data.data: diff --git a/test cases/linuxlike/1 pkg-config/meson.build b/test cases/linuxlike/1 pkg-config/meson.build index ca48e9bd098f..b09630a16db4 100644 --- a/test cases/linuxlike/1 pkg-config/meson.build +++ b/test cases/linuxlike/1 pkg-config/meson.build @@ -22,6 +22,13 @@ assert(dep.get_pkgconfig_variable('nonexisting') == '', 'Value of unknown variab assert(dep.get_pkgconfig_variable('nonexisting', default: 'foo') == 'foo', 'Value of unknown variable is not defaulted.') # pkg-config is able to replace variables assert(dep.get_pkgconfig_variable('prefix', define_variable: ['prefix', '/tmp']) == '/tmp', 'prefix variable has not been replaced.') +assert(dep.get_variable('prefix', pkgconfig_define: ['prefix', '/tmp']) == '/tmp', 'prefix variable has not been replaced.') +# pkg-config can replace multiple variables at once +assert(dep.get_variable('prefix', pkgconfig_define: ['prefix', '/tmp', 'libdir', '/bad/libdir']) == '/tmp', 'first variable has not been replaced.') +assert(dep.get_variable('prefix', pkgconfig_define: ['libdir', '/bad/libdir', 'prefix', '/tmp']) == '/tmp', 'second variable has not been replaced.') +assert(dep.get_pkgconfig_variable('prefix', define_variable: ['prefix', '/tmp', 'libdir', '/bad/libdir']) == '/tmp', 'first variable has not been replaced.') +assert(dep.get_pkgconfig_variable('prefix', define_variable: ['libdir', '/bad/libdir', 'prefix', '/tmp']) == '/tmp', 'second variable has not been replaced.') + # Test that dependencies of dependencies work. dep2 = declare_dependency(dependencies : dep) From 6901ec394fb38b0f959713a96c8cc409620ed5c5 Mon Sep 17 00:00:00 2001 From: Marcel Telka Date: Thu, 16 Nov 2023 09:59:05 +0100 Subject: [PATCH 431/855] Remove shebang from rewriter.py --- mesonbuild/rewriter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index d6509fc971ff..88a99e543b89 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # Copyright 2016 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); From 2b494083956d46f7935f40a92b2c283b7fad6b7a Mon Sep 17 00:00:00 2001 From: albert <92109627+Albkat@users.noreply.github.com> Date: Fri, 17 Nov 2023 18:12:48 +0100 Subject: [PATCH 432/855] note on glib library --- docs/markdown/Tutorial.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/markdown/Tutorial.md b/docs/markdown/Tutorial.md index 34e65fc1c05a..4a2725503bea 100644 --- a/docs/markdown/Tutorial.md +++ b/docs/markdown/Tutorial.md @@ -18,6 +18,8 @@ following command: sudo apt install libgtk-3-dev ``` +In addition, it is recommended to have the glib library with version 2.74 or higher. + It is possible to build the GUI application on other platforms, such as Windows and macOS, but you need to install the needed dependencies. From 8928669a69f63311d9c6db59b3f7b3c83a85ca24 Mon Sep 17 00:00:00 2001 From: David Seifert <16636962+SoapGentoo@users.noreply.github.com> Date: Sat, 18 Nov 2023 01:08:41 -0800 Subject: [PATCH 433/855] Fix unity builds (#12452) * unity builds: correct integer ceiling division * edge case failure with unity builds: - static archive bar that gets installed, that links with another static archive foo that does not get installed - the number of files in static archive foo is divisible by unity_size would yield an error with ninja: ninja: error: 'subprojects/foo/src/libfoo.a.p/meson-generated_foo-unity1.cpp.o', needed by 'src/libbar.a', missing and no known rule to make it * unity builds: test for build failure when #files is divisible by unity_size --- mesonbuild/backend/backends.py | 2 +- test cases/common/272 unity/meson.build | 13 +++++++++++++ test cases/common/272 unity/slib.c | 6 ++++++ test cases/common/272 unity/slib1.c | 3 +++ test cases/common/272 unity/slib2.c | 3 +++ test cases/common/272 unity/test.json | 5 +++++ 6 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 test cases/common/272 unity/meson.build create mode 100644 test cases/common/272 unity/slib.c create mode 100644 test cases/common/272 unity/slib1.c create mode 100644 test cases/common/272 unity/slib2.c create mode 100644 test cases/common/272 unity/test.json diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index b8b958883d67..2c24e4c314a7 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -920,7 +920,7 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_buil if comp.language in LANGS_CANT_UNITY: sources += srcs continue - for i in range(len(srcs) // unity_size + 1): + for i in range((len(srcs) + unity_size - 1) // unity_size): _src = self.get_unity_source_file(extobj.target, comp.get_default_suffix(), i) sources.append(_src) diff --git a/test cases/common/272 unity/meson.build b/test cases/common/272 unity/meson.build new file mode 100644 index 000000000000..9acb9b8fe6ff --- /dev/null +++ b/test cases/common/272 unity/meson.build @@ -0,0 +1,13 @@ +project('unity', 'c', + default_options : [ + 'unity_size=2']) + +if get_option('unity') != 'on' + error('MESON_SKIP_TEST: unity builds not enabled') +endif + +slib_notinstalled = static_library('slib_notinstalled', + # test depends on the number of files being divisible by unity_size + ['slib1.c', 'slib2.c']) + +slib_installed = static_library('slib_installed', ['slib1.c', 'slib2.c'], link_with : slib_notinstalled, install : true) diff --git a/test cases/common/272 unity/slib.c b/test cases/common/272 unity/slib.c new file mode 100644 index 000000000000..d7053366a47f --- /dev/null +++ b/test cases/common/272 unity/slib.c @@ -0,0 +1,6 @@ +int func1(void); +int func2(void); + +int static_lib_func(void) { + return func1() + func2(); +} diff --git a/test cases/common/272 unity/slib1.c b/test cases/common/272 unity/slib1.c new file mode 100644 index 000000000000..35304eed65f1 --- /dev/null +++ b/test cases/common/272 unity/slib1.c @@ -0,0 +1,3 @@ +int func1(void) { + return 1; +} diff --git a/test cases/common/272 unity/slib2.c b/test cases/common/272 unity/slib2.c new file mode 100644 index 000000000000..5badf23bcb72 --- /dev/null +++ b/test cases/common/272 unity/slib2.c @@ -0,0 +1,3 @@ +int func2(void) { + return 2; +} diff --git a/test cases/common/272 unity/test.json b/test cases/common/272 unity/test.json new file mode 100644 index 000000000000..0a10fddb5989 --- /dev/null +++ b/test cases/common/272 unity/test.json @@ -0,0 +1,5 @@ +{ + "installed": [ + {"type": "file", "file": "usr/lib/libslib_installed.a"} + ] +} From 1c0c89d30f2b02068eef2b9a64ea824b2cd5d09b Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 19 Nov 2023 21:44:41 +0200 Subject: [PATCH 434/855] Bump version number for release. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index b4d3158e4ddc..ff5e7956a8a5 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -61,7 +61,7 @@ # # 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.3.0.rc3' +version = '1.3.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 7368795d13081d4928a9ba04d48498ca2442624b Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 19 Nov 2023 21:58:19 +0200 Subject: [PATCH 435/855] Generate release notes for 1.3.0. --- docs/markdown/Release-notes-for-1.3.0.md | 338 ++++++++++++++++++ .../clike_compilers_implicit_includes.md | 13 - docs/markdown/snippets/compile_werror.md | 5 - docs/markdown/snippets/compiler_has_define.md | 10 - .../snippets/configure_file_macro_guard.md | 6 - docs/markdown/snippets/cstd.md | 18 - .../snippets/custom_target_description.md | 6 - .../snippets/deprecate_build_target_jar.md | 8 - .../snippets/env_kwarg_generator_process.md | 4 - docs/markdown/snippets/executable-suffixes.md | 14 - .../snippets/executable_vs_module_defs.md | 4 - .../snippets/find_program_default_options.md | 4 - docs/markdown/snippets/fs_relative_to.md | 17 - .../snippets/install_follow_symlink_arg.md | 7 - docs/markdown/snippets/int_to_string_fill.md | 20 -- docs/markdown/snippets/json_output_format.md | 5 - .../snippets/machine_file_source_dir.md | 13 - .../markdown/snippets/meson_clang_tidy_fix.md | 9 - .../snippets/meson_compile_suffixes.md | 7 - docs/markdown/snippets/meson_home.md | 7 - docs/markdown/snippets/msetup.md | 13 - .../snippets/pkgconfig_define_variable.md | 10 - .../pkgconfig_deprecated_machine_file.md | 10 - .../python_extension_module_limited_api.md | 5 - .../required_keyword_for_has_functions.md | 19 - docs/markdown/snippets/rust_crate_type.md | 11 - docs/markdown/snippets/sanitizers_test.md | 5 - .../snippets/shared_static_only_args.md | 9 - ...rthand_argument_for_mtest_num_processes.md | 4 - docs/markdown/snippets/string_format.md | 10 - .../subprojects_excluded_from_scanbuild.md | 4 - .../vs_module_defs_customtargetindex.md | 8 - docs/markdown/snippets/wrap.md | 13 - docs/sitemap.txt | 1 + 34 files changed, 339 insertions(+), 298 deletions(-) create mode 100644 docs/markdown/Release-notes-for-1.3.0.md delete mode 100644 docs/markdown/snippets/clike_compilers_implicit_includes.md delete mode 100644 docs/markdown/snippets/compile_werror.md delete mode 100644 docs/markdown/snippets/compiler_has_define.md delete mode 100644 docs/markdown/snippets/configure_file_macro_guard.md delete mode 100644 docs/markdown/snippets/cstd.md delete mode 100644 docs/markdown/snippets/custom_target_description.md delete mode 100644 docs/markdown/snippets/deprecate_build_target_jar.md delete mode 100644 docs/markdown/snippets/env_kwarg_generator_process.md delete mode 100644 docs/markdown/snippets/executable-suffixes.md delete mode 100644 docs/markdown/snippets/executable_vs_module_defs.md delete mode 100644 docs/markdown/snippets/find_program_default_options.md delete mode 100644 docs/markdown/snippets/fs_relative_to.md delete mode 100644 docs/markdown/snippets/install_follow_symlink_arg.md delete mode 100644 docs/markdown/snippets/int_to_string_fill.md delete mode 100644 docs/markdown/snippets/json_output_format.md delete mode 100644 docs/markdown/snippets/machine_file_source_dir.md delete mode 100644 docs/markdown/snippets/meson_clang_tidy_fix.md delete mode 100644 docs/markdown/snippets/meson_compile_suffixes.md delete mode 100644 docs/markdown/snippets/meson_home.md delete mode 100644 docs/markdown/snippets/msetup.md delete mode 100644 docs/markdown/snippets/pkgconfig_define_variable.md delete mode 100644 docs/markdown/snippets/pkgconfig_deprecated_machine_file.md delete mode 100644 docs/markdown/snippets/python_extension_module_limited_api.md delete mode 100644 docs/markdown/snippets/required_keyword_for_has_functions.md delete mode 100644 docs/markdown/snippets/rust_crate_type.md delete mode 100644 docs/markdown/snippets/sanitizers_test.md delete mode 100644 docs/markdown/snippets/shared_static_only_args.md delete mode 100644 docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md delete mode 100644 docs/markdown/snippets/string_format.md delete mode 100644 docs/markdown/snippets/subprojects_excluded_from_scanbuild.md delete mode 100644 docs/markdown/snippets/vs_module_defs_customtargetindex.md delete mode 100644 docs/markdown/snippets/wrap.md diff --git a/docs/markdown/Release-notes-for-1.3.0.md b/docs/markdown/Release-notes-for-1.3.0.md new file mode 100644 index 000000000000..cf6ad46ae064 --- /dev/null +++ b/docs/markdown/Release-notes-for-1.3.0.md @@ -0,0 +1,338 @@ +--- +title: Release 1.3.0 +short-description: Release notes for 1.3.0 +... + +# New features + +Meson 1.3.0 was released on 19 November 2023 +## Clarify of implicitly-included headers in C-like compiler checks + +Compiler check methods `compiler.compute_int()`, `compiler.alignment()` +and `compiler.sizeof()` now have their implicitly-included headers +corrected and documented. + +`` was included unintentionally when cross-compiling, which +is less than ideal because there is no guarantee that a standard library +is available for the target platform. Only `` is included instead. + +For projects that depend on the old behavior, the compiler check methods +have an optional argument `prefix`, which can be used to specify additional +`#include` directives. + +## Treat warnings as error in compiler checks + +Compiler check methods `compiler.compiles()`, `compiler.links()` and `compiler.run()` +now have a new `werror: true` keyword argument to treat compiler warnings as error. +This can be used to check if code compiles without warnings. + +## Compilers now have a `has_define` method + +This method returns true if the given preprocessor symbol is +defined, else false is returned. This is useful is cases where +an empty define has to be distinguished from a non-set one, which +is not possible using `get_define`. + +Additionally it makes intent clearer for code that only needs +to check if a specific define is set at all and does not care +about its value. + +## [[configure_file]] now has a `macro_name` parameter. + +This new paramater, `macro_name` allows C macro-style include guards to be added +to [[configure_file]]'s output when a template file is not given. This change +simplifies the creation of configure files that define macros with dynamic names +and want the C-style include guards. + +## `c_std` and `cpp_std` options now accepts a list of values + +Projects that prefer GNU C, but can fallback to ISO C, can now set, for +example, `default_options: 'c_std=gnu11,c11'`, and it will use `gnu11` when +available, but fallback to `c11` otherwise. It is an error only if none of the +values are supported by the current compiler. + +Likewise, a project that can take benefit of `c++17` but can still build with +`c++11` can set `default_options: 'cpp_std=c++17,c++11'`. + +This allows us to deprecate `gnuXX` values from the MSVC compiler. That means +that `default_options: 'c_std=gnu11'` will now print a warning with MSVC +but fallback to `c11`. No warning is printed if at least one +of the values is valid, i.e. `default_options: 'c_std=gnu11,c11'`. + +In the future that deprecation warning will become an hard error because +`c_std=gnu11` should mean GNU is required, for projects that cannot be +built with MSVC for example. + +## More meaningful description of many generative tasks + +When a module uses a `CustomTarget` to process files, it now has the possibility +to customize the message displayed by ninja. + +Many modules were updated to take advantage of this new feature. + +## Deprecate 'jar' as a build_target type + +The point of `build_target()` is that what is produced can be conditionally +changed. However, `jar()` has a significant number of non-overlapping arguments +from other build_targets, including the kinds of sources it can include. Because +of this crafting a `build_target` that can be used as a Jar and as something +else is incredibly hard to do. As such, it has been deprecated, and using +`jar()` directly is recommended. + +## generator.process() gains 'env' keyword argument + +Like the kwarg of the same name in `custom_target()`, `env` allows +you to set the environment in which the generator will process inputs. + +## Target names for executables now take into account suffixes. + +In previous versions of meson, a `meson.build` file like this: + +``` +exectuable('foo', 'main.c') +exectuable('foo', 'main.c', name_suffix: 'bar') +``` + +would result in a configure error because meson internally used +the same id for both executables. This build file is now allowed +since meson takes into account the `bar` suffix when generating the +second executable. This allows for executables with the same basename +but different suffixes to be built in the same subdirectory. + +## Executable gains vs_module_defs keyword + +This allows using a .def file to control which functions an [[executable]] will +expose to a [[shared_module]]. + +## find_program() now supports the 'default_options' argument + +In a similar fashion as dependency(), find_program() now also allows you to set default +options for the subproject that gets built in case of a fallback. + +## `fs.relative_to()` + +The `fs` module now has a `relative_to` method. The method will return the +relative path from argument one to argument two, if one exists. Otherwise, the +absolute path to argument one is returned. + +```meson +assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') +assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') +assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') + +assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') +assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') +``` + +In addition to strings, it can handle files, custom targets, custom target +indices, and build targets. + +## Added follow_symlinks arg to install_data, install_header, and install_subdir + +The [[install_data]], [[install_headers]], [[install_subdir]] functions now +have an optional argument `follow_symlinks` that, if set to `true`, makes it so +symbolic links in the source are followed, rather than copied into the +destination tree, to match the old behavior. The default, which is currently +to follow links, is subject to change in the future. + +## Added 'fill' kwarg to int.to_string() + +int.to_string() now accepts a `fill` argument. This allows you to pad the +string representation of the integer with leading zeroes: + +```meson +n = 4 +message(n.to_string()) +message(n.to_string(fill: 3)) + +n = -4 +message(n.to_string(fill: 3)) +``` + +OUTPUT: +```meson +4 +004 +-04 +``` + +## Added 'json' output_format to configure_file() + +When no input file is specified, [[configure_file]] can now +generate a `json` file from given [[@cfg_data]]. +Field descriptions are not preserved in the json file. + +## `@GLOBAL_SOURCE_ROOT@` and `@DIRNAME@` in machine files + +Some tokens are now replaced in the machine file before parsing it: +- `@GLOBAL_SOURCE_ROOT@`: the absolute path to the project's source tree +- `@DIRNAME@`: the absolute path to the machine file's parent directory. + +It can be used, for example, to have paths relative to the source directory, or +relative to toolchain's installation directory. +```ini +[binaries] +c = '@DIRNAME@/toolchain/gcc' +exe_wrapper = '@GLOBAL_SOURCE_ROOT@' / 'build-aux' / 'my-exe-wrapper.sh' +``` + +## clang-tidy-fix target + +If `clang-tidy` is installed and the project's source root contains a +`.clang-tidy` (or `_clang-tidy`) file, Meson will automatically define +a `clang-tidy-fix` target that runs `run-clang-tidy` tool with `-fix` +option to apply the changes found by clang-tidy to the source code. + +If you have defined your own `clang-tidy-fix` target, Meson will not +generate its own target. + +## Meson compile command now accepts suffixes for TARGET + +The syntax for specifying a target for meson compile is now +`[PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE]` where +`TARGET_SUFFIX` is the suffix argument given in the build target +within meson.build. It is optional and `TARGET_NAME` remains +sufficient if it uniquely resolves to one single target. + +## New environment variable `MESON_PACKAGE_CACHE_DIR` + +If the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of the +project's `subprojects/packagecache`. This allows sharing the cache across multiple +projects. In addition it can contain an already extracted source tree as long as it +has the same directory name as the `directory` field in the wrap file. In that +case, the directory will be copied into `subprojects/` before applying patches. + +## Update options with `meson setup -Dopt=value` + +If the build directory already exists, options are updated with their new value +given on the command line (`-Dopt=value`). Unless `--reconfigure` is also specified, +this won't reconfigure immediately. This has the same behaviour as +`meson configure -Dopt=value`. + +Previous Meson versions were simply a no-op. + +## Clear persistent cache with `meson setup --clearcache` + +Just like `meson configure --clearcache`, it is now possible to clear the cache +and reconfigure in a single command with `meson setup --clearcache --reconfigure `. + +## pkg-config dependencies can now get a variable with multiple replacements + +When using [[dep.get_variable]] and defining a `pkgconfig_define`, it is +sometimes useful to remap multiple dependency variables. For example, if the +upstream project changed the variable name that is interpolated and it is +desirable to support both versions. + +It is now possible to pass multiple pairs of variable/value. + +The same applies to the compatibility [[dep.get_pkgconfig_variable]] method. + +## Machine files: `pkgconfig` field deprecated and replaced by `pkg-config` + +Meson used to allow both `pkgconfig` and `pkg-config` entries in machine files, +the former was used for `dependency()` lookup and the latter was used as return +value for `find_program('pkg-config')`. + +This inconsistency is now fixed by deprecating `pkgconfig` in favor of +`pkg-config` which matches the name of the binary. For backward compatibility +it is still allowed to define both with the same value, in that case no +deprecation warning is printed. + +## Support targeting Python's limited C API + +The Python module's `extension_module` function has gained the ability +to build extensions which target Python's limited C API via a new keyword +argument: `limited_api`. + +## All compiler `has_*` methods support the `required` keyword + +Now instead of + +```meson +assert(cc.has_function('some_function')) +assert(cc.has_type('some_type')) +assert(cc.has_member('struct some_type', 'x')) +assert(cc.has_members('struct some_type', ['x', 'y'])) +``` + +we can use + +```meson +cc.has_function('some_function', required: true) +cc.has_type('some_type', required: true) +cc.has_member('struct some_type', 'x', required: true) +cc.has_members('struct some_type', ['x', 'y'], required: true) +``` + +## Deprecated `rust_crate_type` and replaced by `rust_abi` + +The new `rust_abi` keyword argument is accepted by [[shared_library]], +[[static_library]], [[library]] and [[shared_module]] functions. It can be either +`'rust'` (the default) or `'c'` strings. + +`rust_crate_type` is now deprecated because Meson already knows if it's a shared +or static library, user only need to specify the ABI (Rust or C). + +`proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) +method. + +## Tests now abort on errors by default under sanitizers + +Sanitizers like AddressSanitizer and UndefinedBehaviorSanitizer do not abort +by default on detected violations. Meson now exports `ASAN_OPTIONS` and `UBSAN_OPTIONS` +when unset in the environment to provide sensible abort-by-default behavior. + +## `_(shared|static)_args` for both_library, library, and build_target + +We now allow passing arguments like `c_static_args` and `c_shared_args`. This +allows a [[both_libraries]] to have arguments specific to either the shared or +static library, as well as common arguments to both. + +There is a drawback to this, since Meson now cannot re-use object files between +the static and shared targets. This could lead to much higher compilation time +when using a [[both_libraries]] if there are many sources. + +## `-j` shorthand for `--num-processes` + +`-j` now means the same thing as `--num-processes`. It was inconsistently +supported only in some subcommands. Now you may use it everywhere + +## Unified message(), str.format() and f-string formatting + +They now all support the same set of values: strings, integers, bools, options, +dictionaries and lists thereof. + +- Feature options (i.e. enabled, disabled, auto) were not previously supported + by any of those functions. +- Lists and dictionaries were not previously supported by f-string. +- str.format() allowed any type and often resulted in printing the internal + representation which is now deprecated. + +## Subprojects excluded from scan-build reports + +The `scan-build` target, created when using the `ninja` backend with `scan-build` +present, now excludes bugs found in subprojects from its final report. + +## vs_module_defs keyword now supports indexes of custom_target + +This means you can do something like: +```meson +defs = custom_target('generate_module_defs', ...) +shared_library('lib1', vs_module_defs : defs[0]) +shared_library('lib2', vs_module_defs : defs[2]) +``` + +## Automatic fallback to `cmake` and `cargo` subproject + +CMake subprojects have been supported for a while using the `cmake.subproject()` +module method. However until now it was not possible to use a CMake subproject +as fallback in a `dependency()` call. + +A wrap file can now specify the method used to build it by setting the `method` +key in the wrap file's first section. The method defaults to `meson`. + +Supported methods: +- `meson` requires `meson.build` file. +- `cmake` requires `CMakeLists.txt` file. [See details](Wrap-dependency-system-manual.md#cmake-wraps). +- `cargo` requires `Cargo.toml` file. [See details](Wrap-dependency-system-manual.md#cargo-wraps). + diff --git a/docs/markdown/snippets/clike_compilers_implicit_includes.md b/docs/markdown/snippets/clike_compilers_implicit_includes.md deleted file mode 100644 index a26ec0312a7c..000000000000 --- a/docs/markdown/snippets/clike_compilers_implicit_includes.md +++ /dev/null @@ -1,13 +0,0 @@ -## Clarify of implicitly-included headers in C-like compiler checks - -Compiler check methods `compiler.compute_int()`, `compiler.alignment()` -and `compiler.sizeof()` now have their implicitly-included headers -corrected and documented. - -`` was included unintentionally when cross-compiling, which -is less than ideal because there is no guarantee that a standard library -is available for the target platform. Only `` is included instead. - -For projects that depend on the old behavior, the compiler check methods -have an optional argument `prefix`, which can be used to specify additional -`#include` directives. diff --git a/docs/markdown/snippets/compile_werror.md b/docs/markdown/snippets/compile_werror.md deleted file mode 100644 index e81abb8558c9..000000000000 --- a/docs/markdown/snippets/compile_werror.md +++ /dev/null @@ -1,5 +0,0 @@ -## Treat warnings as error in compiler checks - -Compiler check methods `compiler.compiles()`, `compiler.links()` and `compiler.run()` -now have a new `werror: true` keyword argument to treat compiler warnings as error. -This can be used to check if code compiles without warnings. diff --git a/docs/markdown/snippets/compiler_has_define.md b/docs/markdown/snippets/compiler_has_define.md deleted file mode 100644 index 64de26b391ae..000000000000 --- a/docs/markdown/snippets/compiler_has_define.md +++ /dev/null @@ -1,10 +0,0 @@ -## Compilers now have a `has_define` method - -This method returns true if the given preprocessor symbol is -defined, else false is returned. This is useful is cases where -an empty define has to be distinguished from a non-set one, which -is not possible using `get_define`. - -Additionally it makes intent clearer for code that only needs -to check if a specific define is set at all and does not care -about its value. \ No newline at end of file diff --git a/docs/markdown/snippets/configure_file_macro_guard.md b/docs/markdown/snippets/configure_file_macro_guard.md deleted file mode 100644 index ebb4fc554936..000000000000 --- a/docs/markdown/snippets/configure_file_macro_guard.md +++ /dev/null @@ -1,6 +0,0 @@ -## [[configure_file]] now has a `macro_name` parameter. - -This new paramater, `macro_name` allows C macro-style include guards to be added -to [[configure_file]]'s output when a template file is not given. This change -simplifies the creation of configure files that define macros with dynamic names -and want the C-style include guards. diff --git a/docs/markdown/snippets/cstd.md b/docs/markdown/snippets/cstd.md deleted file mode 100644 index cc1f08318745..000000000000 --- a/docs/markdown/snippets/cstd.md +++ /dev/null @@ -1,18 +0,0 @@ -## `c_std` and `cpp_std` options now accepts a list of values - -Projects that prefer GNU C, but can fallback to ISO C, can now set, for -example, `default_options: 'c_std=gnu11,c11'`, and it will use `gnu11` when -available, but fallback to `c11` otherwise. It is an error only if none of the -values are supported by the current compiler. - -Likewise, a project that can take benefit of `c++17` but can still build with -`c++11` can set `default_options: 'cpp_std=c++17,c++11'`. - -This allows us to deprecate `gnuXX` values from the MSVC compiler. That means -that `default_options: 'c_std=gnu11'` will now print a warning with MSVC -but fallback to `c11`. No warning is printed if at least one -of the values is valid, i.e. `default_options: 'c_std=gnu11,c11'`. - -In the future that deprecation warning will become an hard error because -`c_std=gnu11` should mean GNU is required, for projects that cannot be -built with MSVC for example. diff --git a/docs/markdown/snippets/custom_target_description.md b/docs/markdown/snippets/custom_target_description.md deleted file mode 100644 index fd8820eb23a3..000000000000 --- a/docs/markdown/snippets/custom_target_description.md +++ /dev/null @@ -1,6 +0,0 @@ -## More meaningful description of many generative tasks - -When a module uses a `CustomTarget` to process files, it now has the possibility -to customize the message displayed by ninja. - -Many modules were updated to take advantage of this new feature. diff --git a/docs/markdown/snippets/deprecate_build_target_jar.md b/docs/markdown/snippets/deprecate_build_target_jar.md deleted file mode 100644 index 1aa5a81dd2cb..000000000000 --- a/docs/markdown/snippets/deprecate_build_target_jar.md +++ /dev/null @@ -1,8 +0,0 @@ -## Deprecate 'jar' as a build_target type - -The point of `build_target()` is that what is produced can be conditionally -changed. However, `jar()` has a significant number of non-overlapping arguments -from other build_targets, including the kinds of sources it can include. Because -of this crafting a `build_target` that can be used as a Jar and as something -else is incredibly hard to do. As such, it has been deprecated, and using -`jar()` directly is recommended. diff --git a/docs/markdown/snippets/env_kwarg_generator_process.md b/docs/markdown/snippets/env_kwarg_generator_process.md deleted file mode 100644 index cdf73a302ae1..000000000000 --- a/docs/markdown/snippets/env_kwarg_generator_process.md +++ /dev/null @@ -1,4 +0,0 @@ -## generator.process() gains 'env' keyword argument - -Like the kwarg of the same name in `custom_target()`, `env` allows -you to set the environment in which the generator will process inputs. diff --git a/docs/markdown/snippets/executable-suffixes.md b/docs/markdown/snippets/executable-suffixes.md deleted file mode 100644 index 44471e9dd4c6..000000000000 --- a/docs/markdown/snippets/executable-suffixes.md +++ /dev/null @@ -1,14 +0,0 @@ -## Target names for executables now take into account suffixes. - -In previous versions of meson, a `meson.build` file like this: - -``` -exectuable('foo', 'main.c') -exectuable('foo', 'main.c', name_suffix: 'bar') -``` - -would result in a configure error because meson internally used -the same id for both executables. This build file is now allowed -since meson takes into account the `bar` suffix when generating the -second executable. This allows for executables with the same basename -but different suffixes to be built in the same subdirectory. diff --git a/docs/markdown/snippets/executable_vs_module_defs.md b/docs/markdown/snippets/executable_vs_module_defs.md deleted file mode 100644 index 79017488d09f..000000000000 --- a/docs/markdown/snippets/executable_vs_module_defs.md +++ /dev/null @@ -1,4 +0,0 @@ -## Executable gains vs_module_defs keyword - -This allows using a .def file to control which functions an [[executable]] will -expose to a [[shared_module]]. diff --git a/docs/markdown/snippets/find_program_default_options.md b/docs/markdown/snippets/find_program_default_options.md deleted file mode 100644 index 2cf9822d2f87..000000000000 --- a/docs/markdown/snippets/find_program_default_options.md +++ /dev/null @@ -1,4 +0,0 @@ -## find_program() now supports the 'default_options' argument - -In a similar fashion as dependency(), find_program() now also allows you to set default -options for the subproject that gets built in case of a fallback. diff --git a/docs/markdown/snippets/fs_relative_to.md b/docs/markdown/snippets/fs_relative_to.md deleted file mode 100644 index 82e6a4268bb8..000000000000 --- a/docs/markdown/snippets/fs_relative_to.md +++ /dev/null @@ -1,17 +0,0 @@ -## `fs.relative_to()` - -The `fs` module now has a `relative_to` method. The method will return the -relative path from argument one to argument two, if one exists. Otherwise, the -absolute path to argument one is returned. - -```meson -assert(fs.relative_to('c:\\prefix\\lib', 'c:\\prefix\\bin') == '..\\lib') -assert(fs.relative_to('c:\\proj1\\foo', 'd:\\proj1\\bar') == 'c:\\proj1\\foo') -assert(fs.relative_to('prefix\\lib\\foo', 'prefix') == 'lib\\foo') - -assert(fs.relative_to('/prefix/lib', '/prefix/bin') == '../lib') -assert(fs.relative_to('prefix/lib/foo', 'prefix') == 'lib/foo') -``` - -In addition to strings, it can handle files, custom targets, custom target -indices, and build targets. diff --git a/docs/markdown/snippets/install_follow_symlink_arg.md b/docs/markdown/snippets/install_follow_symlink_arg.md deleted file mode 100644 index ce971d7ff722..000000000000 --- a/docs/markdown/snippets/install_follow_symlink_arg.md +++ /dev/null @@ -1,7 +0,0 @@ -## Added follow_symlinks arg to install_data, install_header, and install_subdir - -The [[install_data]], [[install_headers]], [[install_subdir]] functions now -have an optional argument `follow_symlinks` that, if set to `true`, makes it so -symbolic links in the source are followed, rather than copied into the -destination tree, to match the old behavior. The default, which is currently -to follow links, is subject to change in the future. diff --git a/docs/markdown/snippets/int_to_string_fill.md b/docs/markdown/snippets/int_to_string_fill.md deleted file mode 100644 index 44885ff66d1d..000000000000 --- a/docs/markdown/snippets/int_to_string_fill.md +++ /dev/null @@ -1,20 +0,0 @@ -## Added 'fill' kwarg to int.to_string() - -int.to_string() now accepts a `fill` argument. This allows you to pad the -string representation of the integer with leading zeroes: - -```meson -n = 4 -message(n.to_string()) -message(n.to_string(fill: 3)) - -n = -4 -message(n.to_string(fill: 3)) -``` - -OUTPUT: -```meson -4 -004 --04 -``` diff --git a/docs/markdown/snippets/json_output_format.md b/docs/markdown/snippets/json_output_format.md deleted file mode 100644 index 626840f76b52..000000000000 --- a/docs/markdown/snippets/json_output_format.md +++ /dev/null @@ -1,5 +0,0 @@ -## Added 'json' output_format to configure_file() - -When no input file is specified, [[configure_file]] can now -generate a `json` file from given [[@cfg_data]]. -Field descriptions are not preserved in the json file. diff --git a/docs/markdown/snippets/machine_file_source_dir.md b/docs/markdown/snippets/machine_file_source_dir.md deleted file mode 100644 index 5af344e40ca9..000000000000 --- a/docs/markdown/snippets/machine_file_source_dir.md +++ /dev/null @@ -1,13 +0,0 @@ -## `@GLOBAL_SOURCE_ROOT@` and `@DIRNAME@` in machine files - -Some tokens are now replaced in the machine file before parsing it: -- `@GLOBAL_SOURCE_ROOT@`: the absolute path to the project's source tree -- `@DIRNAME@`: the absolute path to the machine file's parent directory. - -It can be used, for example, to have paths relative to the source directory, or -relative to toolchain's installation directory. -```ini -[binaries] -c = '@DIRNAME@/toolchain/gcc' -exe_wrapper = '@GLOBAL_SOURCE_ROOT@' / 'build-aux' / 'my-exe-wrapper.sh' -``` diff --git a/docs/markdown/snippets/meson_clang_tidy_fix.md b/docs/markdown/snippets/meson_clang_tidy_fix.md deleted file mode 100644 index 3a8c772f3f63..000000000000 --- a/docs/markdown/snippets/meson_clang_tidy_fix.md +++ /dev/null @@ -1,9 +0,0 @@ -## clang-tidy-fix target - -If `clang-tidy` is installed and the project's source root contains a -`.clang-tidy` (or `_clang-tidy`) file, Meson will automatically define -a `clang-tidy-fix` target that runs `run-clang-tidy` tool with `-fix` -option to apply the changes found by clang-tidy to the source code. - -If you have defined your own `clang-tidy-fix` target, Meson will not -generate its own target. diff --git a/docs/markdown/snippets/meson_compile_suffixes.md b/docs/markdown/snippets/meson_compile_suffixes.md deleted file mode 100644 index 481e8adf4b92..000000000000 --- a/docs/markdown/snippets/meson_compile_suffixes.md +++ /dev/null @@ -1,7 +0,0 @@ -## Meson compile command now accepts suffixes for TARGET - -The syntax for specifying a target for meson compile is now -`[PATH_TO_TARGET/]TARGET_NAME.TARGET_SUFFIX[:TARGET_TYPE]` where -`TARGET_SUFFIX` is the suffix argument given in the build target -within meson.build. It is optional and `TARGET_NAME` remains -sufficient if it uniquely resolves to one single target. diff --git a/docs/markdown/snippets/meson_home.md b/docs/markdown/snippets/meson_home.md deleted file mode 100644 index 2d656fc1e28b..000000000000 --- a/docs/markdown/snippets/meson_home.md +++ /dev/null @@ -1,7 +0,0 @@ -## New environment variable `MESON_PACKAGE_CACHE_DIR` - -If the `MESON_PACKAGE_CACHE_DIR` environment variable is set, it is used instead of the -project's `subprojects/packagecache`. This allows sharing the cache across multiple -projects. In addition it can contain an already extracted source tree as long as it -has the same directory name as the `directory` field in the wrap file. In that -case, the directory will be copied into `subprojects/` before applying patches. diff --git a/docs/markdown/snippets/msetup.md b/docs/markdown/snippets/msetup.md deleted file mode 100644 index f68313d67477..000000000000 --- a/docs/markdown/snippets/msetup.md +++ /dev/null @@ -1,13 +0,0 @@ -## Update options with `meson setup -Dopt=value` - -If the build directory already exists, options are updated with their new value -given on the command line (`-Dopt=value`). Unless `--reconfigure` is also specified, -this won't reconfigure immediately. This has the same behaviour as -`meson configure -Dopt=value`. - -Previous Meson versions were simply a no-op. - -## Clear persistent cache with `meson setup --clearcache` - -Just like `meson configure --clearcache`, it is now possible to clear the cache -and reconfigure in a single command with `meson setup --clearcache --reconfigure `. diff --git a/docs/markdown/snippets/pkgconfig_define_variable.md b/docs/markdown/snippets/pkgconfig_define_variable.md deleted file mode 100644 index 0f7082b0d094..000000000000 --- a/docs/markdown/snippets/pkgconfig_define_variable.md +++ /dev/null @@ -1,10 +0,0 @@ -## pkg-config dependencies can now get a variable with multiple replacements - -When using [[dep.get_variable]] and defining a `pkgconfig_define`, it is -sometimes useful to remap multiple dependency variables. For example, if the -upstream project changed the variable name that is interpolated and it is -desirable to support both versions. - -It is now possible to pass multiple pairs of variable/value. - -The same applies to the compatibility [[dep.get_pkgconfig_variable]] method. diff --git a/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md b/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md deleted file mode 100644 index 36647e90e844..000000000000 --- a/docs/markdown/snippets/pkgconfig_deprecated_machine_file.md +++ /dev/null @@ -1,10 +0,0 @@ -## Machine files: `pkgconfig` field deprecated and replaced by `pkg-config` - -Meson used to allow both `pkgconfig` and `pkg-config` entries in machine files, -the former was used for `dependency()` lookup and the latter was used as return -value for `find_program('pkg-config')`. - -This inconsistency is now fixed by deprecating `pkgconfig` in favor of -`pkg-config` which matches the name of the binary. For backward compatibility -it is still allowed to define both with the same value, in that case no -deprecation warning is printed. diff --git a/docs/markdown/snippets/python_extension_module_limited_api.md b/docs/markdown/snippets/python_extension_module_limited_api.md deleted file mode 100644 index f5da9699d9ce..000000000000 --- a/docs/markdown/snippets/python_extension_module_limited_api.md +++ /dev/null @@ -1,5 +0,0 @@ -## Support targeting Python's limited C API - -The Python module's `extension_module` function has gained the ability -to build extensions which target Python's limited C API via a new keyword -argument: `limited_api`. diff --git a/docs/markdown/snippets/required_keyword_for_has_functions.md b/docs/markdown/snippets/required_keyword_for_has_functions.md deleted file mode 100644 index 0752ac7fe11b..000000000000 --- a/docs/markdown/snippets/required_keyword_for_has_functions.md +++ /dev/null @@ -1,19 +0,0 @@ -## All compiler `has_*` methods support the `required` keyword - -Now instead of - -```meson -assert(cc.has_function('some_function')) -assert(cc.has_type('some_type')) -assert(cc.has_member('struct some_type', 'x')) -assert(cc.has_members('struct some_type', ['x', 'y'])) -``` - -we can use - -```meson -cc.has_function('some_function', required: true) -cc.has_type('some_type', required: true) -cc.has_member('struct some_type', 'x', required: true) -cc.has_members('struct some_type', ['x', 'y'], required: true) -``` diff --git a/docs/markdown/snippets/rust_crate_type.md b/docs/markdown/snippets/rust_crate_type.md deleted file mode 100644 index 9b32f0ee86f2..000000000000 --- a/docs/markdown/snippets/rust_crate_type.md +++ /dev/null @@ -1,11 +0,0 @@ -## Deprecated `rust_crate_type` and replaced by `rust_abi` - -The new `rust_abi` keyword argument is accepted by [[shared_library]], -[[static_library]], [[library]] and [[shared_module]] functions. It can be either -`'rust'` (the default) or `'c'` strings. - -`rust_crate_type` is now deprecated because Meson already knows if it's a shared -or static library, user only need to specify the ABI (Rust or C). - -`proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) -method. diff --git a/docs/markdown/snippets/sanitizers_test.md b/docs/markdown/snippets/sanitizers_test.md deleted file mode 100644 index 24929114beab..000000000000 --- a/docs/markdown/snippets/sanitizers_test.md +++ /dev/null @@ -1,5 +0,0 @@ -## Tests now abort on errors by default under sanitizers - -Sanitizers like AddressSanitizer and UndefinedBehaviorSanitizer do not abort -by default on detected violations. Meson now exports `ASAN_OPTIONS` and `UBSAN_OPTIONS` -when unset in the environment to provide sensible abort-by-default behavior. diff --git a/docs/markdown/snippets/shared_static_only_args.md b/docs/markdown/snippets/shared_static_only_args.md deleted file mode 100644 index 0963c714bdf3..000000000000 --- a/docs/markdown/snippets/shared_static_only_args.md +++ /dev/null @@ -1,9 +0,0 @@ -## `_(shared|static)_args` for both_library, library, and build_target - -We now allow passing arguments like `c_static_args` and `c_shared_args`. This -allows a [[both_libraries]] to have arguments specific to either the shared or -static library, as well as common arguments to both. - -There is a drawback to this, since Meson now cannot re-use object files between -the static and shared targets. This could lead to much higher compilation time -when using a [[both_libraries]] if there are many sources. diff --git a/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md b/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md deleted file mode 100644 index 7ff661b1363b..000000000000 --- a/docs/markdown/snippets/shorthand_argument_for_mtest_num_processes.md +++ /dev/null @@ -1,4 +0,0 @@ -## `-j` shorthand for `--num-processes` - -`-j` now means the same thing as `--num-processes`. It was inconsistently -supported only in some subcommands. Now you may use it everywhere diff --git a/docs/markdown/snippets/string_format.md b/docs/markdown/snippets/string_format.md deleted file mode 100644 index fa3361750e8e..000000000000 --- a/docs/markdown/snippets/string_format.md +++ /dev/null @@ -1,10 +0,0 @@ -## Unified message(), str.format() and f-string formatting - -They now all support the same set of values: strings, integers, bools, options, -dictionaries and lists thereof. - -- Feature options (i.e. enabled, disabled, auto) were not previously supported - by any of those functions. -- Lists and dictionaries were not previously supported by f-string. -- str.format() allowed any type and often resulted in printing the internal - representation which is now deprecated. diff --git a/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md b/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md deleted file mode 100644 index d740006be248..000000000000 --- a/docs/markdown/snippets/subprojects_excluded_from_scanbuild.md +++ /dev/null @@ -1,4 +0,0 @@ -## Subprojects excluded from scan-build reports - -The `scan-build` target, created when using the `ninja` backend with `scan-build` -present, now excludes bugs found in subprojects from its final report. diff --git a/docs/markdown/snippets/vs_module_defs_customtargetindex.md b/docs/markdown/snippets/vs_module_defs_customtargetindex.md deleted file mode 100644 index d50d04ecb516..000000000000 --- a/docs/markdown/snippets/vs_module_defs_customtargetindex.md +++ /dev/null @@ -1,8 +0,0 @@ -## vs_module_defs keyword now supports indexes of custom_target - -This means you can do something like: -```meson -defs = custom_target('generate_module_defs', ...) -shared_library('lib1', vs_module_defs : defs[0]) -shared_library('lib2', vs_module_defs : defs[2]) -``` diff --git a/docs/markdown/snippets/wrap.md b/docs/markdown/snippets/wrap.md deleted file mode 100644 index 3a5521efcdb1..000000000000 --- a/docs/markdown/snippets/wrap.md +++ /dev/null @@ -1,13 +0,0 @@ -## Automatic fallback to `cmake` and `cargo` subproject - -CMake subprojects have been supported for a while using the `cmake.subproject()` -module method. However until now it was not possible to use a CMake subproject -as fallback in a `dependency()` call. - -A wrap file can now specify the method used to build it by setting the `method` -key in the wrap file's first section. The method defaults to `meson`. - -Supported methods: -- `meson` requires `meson.build` file. -- `cmake` requires `CMakeLists.txt` file. [See details](Wrap-dependency-system-manual.md#cmake-wraps). -- `cargo` requires `Cargo.toml` file. [See details](Wrap-dependency-system-manual.md#cargo-wraps). diff --git a/docs/sitemap.txt b/docs/sitemap.txt index b6d57a493acc..5eb2284eb3ce 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.3.0.md Release-notes-for-1.2.0.md Release-notes-for-1.1.0.md Release-notes-for-1.0.0.md From dea72e42bfcd25ac6e3ae55bf99e063cf5b77101 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 19 Nov 2023 22:39:16 +0200 Subject: [PATCH 436/855] Bump version number for new development. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index ff5e7956a8a5..20bba09e5402 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -61,7 +61,7 @@ # # 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.3.0' +version = '1.3.99' # 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 dfd8cfbd8d9ce03473cb17a722400cb4a8d1b67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Sat, 4 Nov 2023 12:59:01 +0100 Subject: [PATCH 437/855] vs2010backend: fix incompatibility with custom manifests EmbedManifest seems to default to true, which creates a default manifest based on other parameters (likewise defaults) and makes it impossible to supply your own with CREATEPROCESS_MANIFEST_RESOURCE_ID. There is value to being able to do this and no value to the default one, so this should be disabled. --- mesonbuild/backend/vs2010backend.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index cb1ea78337e1..f4de6582360c 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -693,6 +693,8 @@ def create_basic_project(self, target_name, *, if target_ext: ET.SubElement(direlem, 'TargetExt').text = target_ext + ET.SubElement(direlem, 'EmbedManifest').text = 'false' + return (root, type_config) def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str) -> None: From 2ed94ccb47b597990b63207b272a5b3dea4a4877 Mon Sep 17 00:00:00 2001 From: Chris Lamb Date: Mon, 20 Nov 2023 09:53:01 +0000 Subject: [PATCH 438/855] Make the Requires.private line in generated .pkgconfig files reproducible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whilst working on the Reproducible Builds effort, we noticed that meson was generates .pkgconfig files that are not reproducible. For example, here is neatvnc's pkgconfig file when built with HEAD^1: Name: neatvnc Description: A Neat VNC server library Version: 0.7.0 -Requires.private: pixman-1, aml < 0.4.0, aml >= 0.3.0, zlib, libdrm, libturbojpeg, gnutls, nettle, hogweed, gmp, gbm, libavcodec, libavfilter, libavutil +Requires.private: pixman-1, aml >= 0.3.0, aml < 0.4.0, zlib, libdrm, libturbojpeg, gnutls, nettle, hogweed, gmp, gbm, libavcodec, libavfilter, libavutil Libs: -L${libdir} -lneatvnc Libs.private: -lm Cflags: -I${includedir} This is, ultimately, due to iterating over the contents of a set within a DefaultDict and can thus be fixed by sorting the output immediately prior to generating the Requires.private string. An alternative solution would be to place the sorted(…) call a few lines down: return ', '.join(sorted(result)) However, this changes the expected ordering of the entire line, and many users may be unhappy with that (alternative) change as a result. By contrast, this commit will only enforce an ordering when there are multiple version requirements (eg. a lower and a higher version requirement, ie. a version range). It will, additionally, order them with the lower part of the range first. This was originally filed (with a slightly different patch) by myself in the the Debian bug tracker . Signed-off-by: Chris Lamb --- mesonbuild/modules/pkgconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index ee12293cdb3b..fa543fdb5fda 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -307,7 +307,7 @@ def format_reqs(self, reqs: T.List[str]) -> str: for name in reqs: vreqs = self.version_reqs.get(name, None) if vreqs: - result += [name + ' ' + self.format_vreq(vreq) for vreq in vreqs] + result += [name + ' ' + self.format_vreq(vreq) for vreq in sorted(vreqs)] else: result += [name] return ', '.join(result) From 5e06eb9b899f902eeb56935c166d58b2c5727faf Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 10 Nov 2023 16:32:36 -0500 Subject: [PATCH 439/855] wraptool: Remove dead code Update command is implemented in msubprojects.py, because it can update all wraps in parallel. --- mesonbuild/wrap/wraptool.py | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index c4ff9dbbb8c4..187bfaa79c6b 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -20,7 +20,7 @@ from glob import glob from .wrap import (open_wrapdburl, WrapException, get_releases, get_releases_data, - update_wrap_file, parse_patch_url) + parse_patch_url) from pathlib import Path from .. import mesonlib, msubprojects @@ -134,31 +134,6 @@ def get_current_version(wrapfile: str) -> T.Tuple[str, str, str, str, T.Optional patch_filename = wrap_data['patch_filename'] return branch, revision, wrap_data['directory'], wrap_data['source_filename'], patch_filename -def update(options: 'argparse.Namespace') -> None: - name = options.name - if not os.path.isdir('subprojects'): - raise SystemExit('Subprojects dir not found. Run this command in your source root directory.') - wrapfile = os.path.join('subprojects', name + '.wrap') - if not os.path.exists(wrapfile): - raise SystemExit('Project ' + name + ' is not in use.') - (branch, revision, subdir, src_file, patch_file) = get_current_version(wrapfile) - (new_branch, new_revision) = get_latest_version(name, options.allow_insecure) - if new_branch == branch and new_revision == revision: - print('Project ' + name + ' is already up to date.') - raise SystemExit - update_wrap_file(wrapfile, name, new_branch, new_revision, options.allow_insecure) - shutil.rmtree(os.path.join('subprojects', subdir), ignore_errors=True) - try: - os.unlink(os.path.join('subprojects/packagecache', src_file)) - except FileNotFoundError: - pass - if patch_file is not None: - try: - os.unlink(os.path.join('subprojects/packagecache', patch_file)) - except FileNotFoundError: - pass - print(f'Updated {name} version {new_branch} revision {new_revision}') - def info(options: 'argparse.Namespace') -> None: name = options.name releases = get_releases(options.allow_insecure) From 4a1e0235cc81442c312cb31a9ed5c639f0b1c8c5 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 10 Nov 2023 16:35:56 -0500 Subject: [PATCH 440/855] wrap: Cache get_releases() "meson wrap status" was calling it for each .wrap file. Better use lru_cache to ensure we don't make the same mistake elsewhere. --- mesonbuild/wrap/wrap.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index a5b4dc8ec6fe..ea8b4bf61e18 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -35,6 +35,7 @@ from base64 import b64encode from netrc import netrc from pathlib import Path, PurePath +from functools import lru_cache from . import WrapMode from .. import coredata @@ -111,6 +112,7 @@ def get_releases_data(allow_insecure: bool) -> bytes: url = open_wrapdburl('https://wrapdb.mesonbuild.com/v2/releases.json', allow_insecure, True) return url.read() +@lru_cache(maxsize=None) def get_releases(allow_insecure: bool) -> T.Dict[str, T.Any]: data = get_releases_data(allow_insecure) return T.cast('T.Dict[str, T.Any]', json.loads(data.decode())) From 30ab9747ae03364ac2ccd4a8f508286c57ed54a5 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 9 Nov 2023 20:18:19 +0100 Subject: [PATCH 441/855] clike: Deduplicate rpath linker flags [why] On Apple clang 15.0.0 linker (i.e. ld64 1015.7) giving the same rpath multiple times raises a warning: ld: warning: duplicate -rpath '/local/lib' ignored This can frequently happen when linking several dependencies that all have that rpath in e.g. pkgconfig. [how] Deduplicate all rpath arguments. [note] I'm not sure how the code handles --start/end-group, but for rpath that should not make any difference as that is not bound to a group. Signed-off-by: Fini Jastrow --- mesonbuild/compilers/mixins/clike.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index ca909998bffd..ad8fa2747495 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1,4 +1,4 @@ -# Copyright 2012-2022 The Meson development team +# Copyright 2012-2023 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ class CLikeCompilerArgs(arglist.CompilerArgs): # NOTE: not thorough. A list of potential corner cases can be found in # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 - dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic') + dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic', '-Wl,-rpath') dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') From 9aa1393fdb6b757d82d82941e9a7cd3fc21e725f Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Wed, 18 Oct 2023 11:37:23 +0000 Subject: [PATCH 442/855] docs: fix bindgen_clang_arguments example > error: unsupported option '--target'; did you mean '-target'? --- docs/markdown/Rust-module.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 0fb9edef748b..8ef8c433ee81 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -103,7 +103,7 @@ were never turned on by Meson. ```ini [properties] -bindgen_clang_arguments = ['--target', 'x86_64-linux-gnu'] +bindgen_clang_arguments = ['-target', 'x86_64-linux-gnu'] ``` ### proc_macro() From 96f0b3ca38fa3518187429aaec62a6dae9f25500 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Wed, 25 Oct 2023 12:04:39 -0400 Subject: [PATCH 443/855] Update release frequency to match reality Releases have been happening an average of once every 90 days for the past two years (since 0.60.0). If we just look at releases since 1.0.0, the average is over 100 days. --- docs/markdown/Release-procedure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/Release-procedure.md b/docs/markdown/Release-procedure.md index 4a6e7f8a7b31..1f0ec0894472 100644 --- a/docs/markdown/Release-procedure.md +++ b/docs/markdown/Release-procedure.md @@ -16,8 +16,8 @@ choose. # Major releases Major releases are currently in the form 0.X.0, where X is an -increasing number. We aim to do a major release roughly once a month, -though the schedule is not set in stone. +increasing number. We aim to do a major release roughly once every 3 to 4 +months, though the schedule is not set in stone. Before a major release is made a stable branch will be made, and 0.X.0-rc1 release candidate will be made. A new milestone for 0.X.0 From 63453564ee697ebf4741f082b8d678ed15455a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Fri, 13 Oct 2023 07:59:09 +0100 Subject: [PATCH 444/855] docs: document out of bounds behavior in str.substring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe Laíns --- docs/yaml/elementary/str.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/yaml/elementary/str.yml b/docs/yaml/elementary/str.yml index 83ab3dd64478..9d059cc092d3 100644 --- a/docs/yaml/elementary/str.yml +++ b/docs/yaml/elementary/str.yml @@ -164,6 +164,9 @@ methods: The method accepts negative values where negative `start` is relative to the end of string `len(string) - start` as well as negative `end`. + If `start` or `end` are out of bounds, the position of the closest character will be used. + If `start` is bigger than `end`, the result will be an empty substring. + example: | ```meson # Similar to the Python str[start:end] syntax @@ -180,6 +183,15 @@ methods: string.substring(1, -1) # => 'ooba' ``` + Example with out of bound values: + + ```meson + string = 'foobar' + string.substring(64) # => '' + string.substring(0, 64) # => 'foobar' + string.substring(64, 0) # => '' + ``` + optargs: start: type: int From 36059814661660eeca33c7553b50d35fb798b6f0 Mon Sep 17 00:00:00 2001 From: Gerion Entrup Date: Fri, 27 Oct 2023 01:05:13 +0200 Subject: [PATCH 445/855] docs/dependency: fix type of version kwarg --- docs/yaml/functions/dependency.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/yaml/functions/dependency.yaml b/docs/yaml/functions/dependency.yaml index 5ae1634bf3a1..74981b2d9f89 100644 --- a/docs/yaml/functions/dependency.yaml +++ b/docs/yaml/functions/dependency.yaml @@ -179,7 +179,7 @@ kwargs: subproject if it was not set explicitly in `default_options` keyword argument. version: - type: str + type: list[str] | str since: 0.37.0 description: | Specifies the required version, From 7f5f432ec98c1961b0b9712f36cec3ae3c5cd9f9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 25 Oct 2023 23:39:41 +0800 Subject: [PATCH 446/855] docs: Update Quick-guide.md Change the shell prompt to '#' to when installing as root. Signed-off-by: Bin Meng --- docs/markdown/Quick-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Quick-guide.md b/docs/markdown/Quick-guide.md index 3a869041e73b..534055aa750c 100644 --- a/docs/markdown/Quick-guide.md +++ b/docs/markdown/Quick-guide.md @@ -55,7 +55,7 @@ $ pip3 install --user meson ``` Install as root: ```console -$ pip3 install meson +# pip3 install meson ``` *If you are unsure whether to install as root or a local user, install From 85e4ee5b54c334d4104e6c3b2f3fda11cd9b2dd6 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 21 Oct 2023 09:47:39 -0400 Subject: [PATCH 447/855] File: Add full_path() method This is needed now that str.format() is not allowing it any more. It is also more consistent with other objects that have that method as well, such as build targets. Fixes: #12406 --- docs/markdown/snippets/file-full-path.md | 7 +++++++ docs/yaml/objects/file.yaml | 12 +++++++++++- mesonbuild/interpreter/interpreterobjects.py | 11 ++++++++++- test cases/common/74 file object/meson.build | 6 ++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/file-full-path.md diff --git a/docs/markdown/snippets/file-full-path.md b/docs/markdown/snippets/file-full-path.md new file mode 100644 index 000000000000..fbb8e548d80d --- /dev/null +++ b/docs/markdown/snippets/file-full-path.md @@ -0,0 +1,7 @@ +## File object now has `full_path()` method + +Returns a full path pointing to the file. This is useful for printing the path +with e.g [[message]] function for debugging purpose. + +**NOTE:** In most cases using the object itself will do the same job +as this and will also allow Meson to setup dependencies correctly. diff --git a/docs/yaml/objects/file.yaml b/docs/yaml/objects/file.yaml index 6aa0b85cea37..5d2ad3053729 100644 --- a/docs/yaml/objects/file.yaml +++ b/docs/yaml/objects/file.yaml @@ -1,3 +1,13 @@ name: file long_name: File -description: Opaque object that stores the path to an existing file +description: Object that stores the path to an existing file + +methods: +- name: full_path + returns: str + since: 1.4.0 + description: | + Returns a full path pointing to the file. This is useful for printing the + path with e.g [[message]] function for debugging purpose. + **NOTE:** In most cases using the object itself will do the same job + as this and will also allow Meson to setup dependencies correctly. diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index f13e3ff4ad17..4320cf52e924 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -701,7 +701,16 @@ class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]): pass class FileHolder(ObjectHolder[mesonlib.File]): - pass + def __init__(self, file: mesonlib.File, interpreter: 'Interpreter'): + super().__init__(file, interpreter) + self.methods.update({'full_path': self.full_path_method, + }) + + @noPosargs + @noKwargs + @FeatureNew('file.full_path', '1.4.0') + def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.absolute_path(self.env.source_dir, self.env.build_dir) class HeadersHolder(ObjectHolder[build.Headers]): pass diff --git a/test cases/common/74 file object/meson.build b/test cases/common/74 file object/meson.build index fc01bfec78a8..05c24aef8348 100644 --- a/test cases/common/74 file object/meson.build +++ b/test cases/common/74 file object/meson.build @@ -6,3 +6,9 @@ test('fobj', executable('fobj', prog0, lib0)) subdir('subdir1') subdir('subdir2') + +# Use fs.as_posix() because / operator replaces \ with / in the path, but +# full_path() method is not doing that. This is a pretty inconsistent across all +# Meson APIs. +fs = import('fs') +assert(fs.as_posix(prog0[0].full_path()) == fs.as_posix(meson.current_source_dir() / 'prog.c')) From 319b41b4c9c9d6d776828519b141fea1427fe89e Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 23 Nov 2023 09:11:54 -0500 Subject: [PATCH 448/855] mlog: Catch OSError when closing pager For some reasons, with msys2 it sometimes raises OSError instead of BrokenPipeError. Fixes: #12541 --- mesonbuild/mlog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index 0e62a57d4752..ca07f03f4428 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -190,7 +190,7 @@ def stop_pager(self) -> None: try: self.log_pager.stdin.flush() self.log_pager.stdin.close() - except BrokenPipeError: + except OSError: pass self.log_pager.wait() self.log_pager = None From caa38dad453905c968ecf1c021e2867f7f4a17e3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 26 Nov 2023 01:03:08 -0500 Subject: [PATCH 449/855] fix broken type annotation imports being ignored If an annotation could not be resolved, it's classified as a "missing import" and our configuration ignored it: ``` Skipping analyzing "mesonbuild.backends": module is installed, but missing library stubs or py.typed marker ``` As far as mypy is concerned, this library may or may not exist, but it doesn't have any typing information at all (may need to be installed first). We ignored this because of our docs/ and tools/ thirdparty dependencies, but we really should not. It is trivial to install them, and then enforce that this "just works". By enforcing it, we also make sure typos get caught. --- .github/workflows/lint.yml | 2 +- .mypy.ini | 2 +- docs/refman/loaderyaml.py | 2 +- mesonbuild/compilers/mixins/compcert.py | 2 +- mesonbuild/interpreter/compiler.py | 5 +++-- mesonbuild/mdevenv.py | 5 +++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 547a520cc3f9..ddedabf7ab80 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.x' - - run: python -m pip install mypy types-PyYAML + - run: python -m pip install mypy coverage types-PyYAML types-tqdm types-chevron - run: python run_mypy.py --allver env: PYTHONUNBUFFERED: 1 diff --git a/.mypy.ini b/.mypy.ini index 70fdcd9f3732..d00944bb2ec1 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -2,7 +2,7 @@ strict_optional = False show_error_context = False show_column_numbers = True -ignore_missing_imports = True +ignore_missing_imports = False implicit_reexport = False follow_imports = silent diff --git a/docs/refman/loaderyaml.py b/docs/refman/loaderyaml.py index fc06b0d67084..e7ec57a7e08d 100644 --- a/docs/refman/loaderyaml.py +++ b/docs/refman/loaderyaml.py @@ -41,7 +41,7 @@ class Template: class StrictTemplate(Template): def __init__(self) -> None: - from strictyaml import Map, MapPattern, Optional, Str, Seq, Int, Bool, EmptyList, OrValidator + from strictyaml import Map, MapPattern, Optional, Str, Seq, Int, Bool, EmptyList, OrValidator # type: ignore[import-untyped] d_named_object = { 'name': Str(), diff --git a/mesonbuild/compilers/mixins/compcert.py b/mesonbuild/compilers/mixins/compcert.py index ac4d5aaa07d5..a40f635fa65a 100644 --- a/mesonbuild/compilers/mixins/compcert.py +++ b/mesonbuild/compilers/mixins/compcert.py @@ -20,7 +20,7 @@ import typing as T if T.TYPE_CHECKING: - from envconfig import MachineInfo + from ...envconfig import MachineInfo from ...environment import Environment from ...compilers.compilers import Compiler else: diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 5528abe7ade5..ad6eb4b89c63 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -30,7 +30,7 @@ from ..compilers import Compiler, RunResult from ..interpreterbase import TYPE_var, TYPE_kwargs from .kwargs import ExtractRequired, ExtractSearchDirs - from .interpreter.interpreter import SourceOutputs + from .interpreter import SourceOutputs from ..mlog import TV_LoggableList from typing_extensions import TypedDict, Literal @@ -856,7 +856,8 @@ def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwa ) def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]: compiler = self.compiler.get_preprocessor() - sources: 'SourceOutputs' = self.interpreter.source_strings_to_files(args[0]) + _sources: T.List[mesonlib.File] = self.interpreter.source_strings_to_files(args[0]) + sources = T.cast('T.List[SourceOutputs]', _sources) if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in sources): FeatureNew.single_use('compiler.preprocess with generated sources', '1.1.0', self.subproject, location=self.current_node) diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 9f3d1b973d28..c8d0144c562f 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -5,6 +5,7 @@ import tempfile import shutil import itertools +import typing as T from pathlib import Path from . import build, minstall @@ -12,9 +13,9 @@ get_wine_shortpath, MachineChoice) from . import mlog -import typing as T + if T.TYPE_CHECKING: - from .backends import InstallData + from .backend.backends import InstallData POWERSHELL_EXES = {'pwsh.exe', 'powershell.exe'} From 739bdef431eca44ed12db882f3096c655725b87d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 26 Nov 2023 02:07:29 -0500 Subject: [PATCH 450/855] NOMERGE: do we need strictyaml too? --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ddedabf7ab80..58860bd8c300 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.x' - - run: python -m pip install mypy coverage types-PyYAML types-tqdm types-chevron + - run: python -m pip install mypy coverage strictyaml types-PyYAML types-tqdm types-chevron - run: python run_mypy.py --allver env: PYTHONUNBUFFERED: 1 From cf64e062bb6f8d95c73a6b292629a7776ff31864 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 26 Nov 2023 02:17:50 -0500 Subject: [PATCH 451/855] run_mypy: avoid type-checking tools against every possible python version --- run_mypy.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/run_mypy.py b/run_mypy.py index 16ff318e8442..25dc1d568faa 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -69,7 +69,8 @@ 'mesonbuild/mtest.py', 'mesonbuild/optinterpreter.py', 'mesonbuild/programs.py', - +] +additional = [ 'run_mypy.py', 'run_project_tests.py', 'run_single_test.py', @@ -115,23 +116,29 @@ def main() -> int: print('\x1bc', end='', flush=True) to_check = [] # type: T.List[str] + additional_to_check = [] # type: T.List[str] if opts.files: for f in opts.files: if f in modules: to_check.append(f) elif any(f.startswith(i) for i in modules): to_check.append(f) + elif f in additional: + additional_to_check.append(f) + elif any(f.startswith(i) for i in additional): + additional_to_check.append(f) else: if not opts.quiet: print(f'skipping {f!r} because it is not yet typed') else: to_check.extend(modules) + additional_to_check.extend(additional) if to_check: command = [opts.mypy] if opts.mypy else [sys.executable, '-m', 'mypy'] if not opts.quiet: print('Running mypy (this can take some time) ...') - retcode = subprocess.run(command + args + to_check, cwd=root).returncode + retcode = subprocess.run(command + args + to_check + additional_to_check, cwd=root).returncode if opts.allver and retcode == 0: for minor in range(7, sys.version_info[1]): if not opts.quiet: From 8c70ce466b9e323cb445f90044968e22d84b2888 Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Wed, 5 Jul 2023 11:39:19 +1000 Subject: [PATCH 452/855] More robust linker detection for armar (TI vs non-TI) --- mesonbuild/compilers/detect.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 0bfedd13921a..10bbf5f377c8 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -204,8 +204,6 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker if any(os.path.basename(x) in {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'} for x in linker): arg = '/?' - elif linker_name in {'ar2000', 'ar2000.exe', 'ar430', 'ar430.exe', 'armar', 'armar.exe'}: - arg = '?' else: arg = '--version' try: @@ -234,7 +232,7 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker return linkers.CcrxLinker(linker) if out.startswith('GNU ar') and 'xc16-ar' in linker_name: return linkers.Xc16Linker(linker) - if 'Texas Instruments Incorporated' in out: + if "--> error: bad option 'e'" in err: # TI if 'ar2000' in linker_name: return linkers.C2000Linker(linker) else: From 52638e8c65e15c9ea1523d7ba7a564ee91e6a59e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 27 Nov 2023 10:23:00 -0800 Subject: [PATCH 453/855] dependencies/base: Make MissingCompiler inherit Compiler for mypy This allows mypy and pyright to correctly determine the return types from methods, but makes 0 changes at runtime. --- mesonbuild/dependencies/base.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index c4861ff12116..6ab2bef7eac9 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -39,15 +39,34 @@ ) from ..interpreter.type_checking import PkgConfigDefineType + _MissingCompilerBase = Compiler +else: + _MissingCompilerBase = object + class DependencyException(MesonException): '''Exceptions raised while trying to find dependencies''' -class MissingCompiler: +class MissingCompiler(_MissingCompilerBase): """Represent a None Compiler - when no tool chain is found. replacing AttributeError with DependencyException""" + # These are needed in type checking mode to avoid errors, but we don't want + # the extra overhead at runtime + if T.TYPE_CHECKING: + def __init__(self) -> None: + pass + + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return [] + + def get_output_args(self, outputname: str) -> T.List[str]: + return [] + + def sanity_check(self, work_dir: str, environment: 'Environment') -> None: + return None + def __getattr__(self, item: str) -> T.Any: if item.startswith('__'): raise AttributeError() From a85353cd8326175e719b913ff9aa46e3daf20497 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 27 Nov 2023 10:26:23 -0800 Subject: [PATCH 454/855] cmake: Handle compiler.find_library returning None I'm not 100% sure that warning is the appropriate action, but it's better than failing with a backtrace. Fixes: #12555 --- mesonbuild/cmake/tracetargets.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py index bb5faa3959d1..20c7462d147a 100644 --- a/mesonbuild/cmake/tracetargets.py +++ b/mesonbuild/cmake/tracetargets.py @@ -55,7 +55,11 @@ def resolve_cmake_trace_targets(target_name: str, # CMake brute-forces a combination of prefix/suffix combinations to find the # right library. Assume any bare argument passed which is not also a CMake # target must be a system library we should try to link against. - res.libraries += clib_compiler.find_library(curr, env, []) + flib = clib_compiler.find_library(curr, env, []) + if flib is not None: + res.libraries += flib + else: + not_found_warning(curr) else: not_found_warning(curr) continue From 9016e6958bb83feb9a724f20d8badb116bf7c5f2 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Tue, 21 Nov 2023 08:42:56 +0100 Subject: [PATCH 455/855] Only convert boolean values for cmake formats This caused a regression with mesondefine where `conf_data.set("FOO", true)` turned into `#define FOO 1` instead of `#define FOO` --- mesonbuild/utils/universal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 26194628c46c..93e64c0a2e05 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1210,7 +1210,7 @@ def variable_replace(match: T.Match[str]) -> str: var, _ = confdata.get(varname) if isinstance(var, str): var_str = var - elif isinstance(var, bool): + elif variable_format.startswith("cmake") and isinstance(var, bool): var_str = str(int(var)) elif isinstance(var, int): var_str = str(var) From eb44957c1f4773ca4ff9759e7e75375b891dcd12 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 12:31:10 -0800 Subject: [PATCH 456/855] Handle macos linker reporting error message in pluring during detection Previously macos reported "ld: unknown option: --version" when being passed --version, but now sometimes it reports in plural, albeit without an obvious pattern when. To handle that, simply just check for the prefix without the : Fixes: https://github.com/mesonbuild/meson/issues/12552 --- mesonbuild/linkers/detect.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 4261144d0594..b86405a7673f 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -185,8 +185,9 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty v = search_version(o) linker = linkers.LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) - # first might be apple clang, second is for real gcc, the third is icc - elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e: + # First might be apple clang, second is for real gcc, the third is icc. + # Note that "ld: unknown option: " sometimes instead is "ld: unknown options:". + elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option' in e: if isinstance(comp_class.LINKER_PREFIX, str): cmd = compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args else: From c1f0897248fabad78877f124b431fd65bc8ba434 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 16:20:23 -0800 Subject: [PATCH 457/855] macos: Fix path in test to be Sonoma compatible The path tested prior does not exist anymore in Sonoma. It seems less likely that 'cat' will be removed, so use that. --- unittests/darwintests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/darwintests.py b/unittests/darwintests.py index 1f177602c9bc..91ccb42b5943 100644 --- a/unittests/darwintests.py +++ b/unittests/darwintests.py @@ -151,5 +151,5 @@ def test_objc_versions(self): def test_darwin_get_object_archs(self): from mesonbuild.mesonlib import darwin_get_object_archs - archs = darwin_get_object_archs('/System/Library/CoreServices/Encodings/libSymbolConverter.dylib') + archs = darwin_get_object_archs('/bin/cat') self.assertEqual(archs, ['x86_64', 'aarch64']) From 4ddaef813354f04b94f447d8881ece43db1c3108 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 16:27:02 -0800 Subject: [PATCH 458/855] macos: Fix test case for constructor_priority when using gcc GCC does not support constructor_priority on macos. It's possibly not the only platform for which that is the case, but... --- test cases/common/197 function attributes/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test cases/common/197 function attributes/meson.build b/test cases/common/197 function attributes/meson.build index 8ef6b741d655..530db9313329 100644 --- a/test cases/common/197 function attributes/meson.build +++ b/test cases/common/197 function attributes/meson.build @@ -91,6 +91,11 @@ if host_machine.system() != 'darwin' attributes += 'alloc_size' endif +# gcc doesn't support constructor_priority on darwin +if c.get_id() == 'gcc' and host_machine.system() == 'darwin' + expected += {'constructor_priority': false} +endif + if ['gcc', 'intel'].contains(c.get_id()) # not supported by clang as of 5.0.0 (at least up to 6.0.1) attributes += 'artificial' From 6eee9e7c0c91fecb26676c05898c54d010b5e1c4 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sat, 2 Dec 2023 19:44:34 +0100 Subject: [PATCH 459/855] python: fix mingw python detection code in case pkg-config isn't available The code assumed that sysconfig.get_platform() returns "mingw" for mingw Python, but that's no longer the case for 2.5 years now, as it now only starts with "mingw" and contains further information like the arch and other ABI relevant things to avoid conflicts. This updates the detection code to the current status quo. mingw Python only documents right now that it starts with "mingw", and none of that arch stuff, but it's unlikely that this will change, and this looks less error prone than looking at CC. Fixes #12547 --- mesonbuild/dependencies/python.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index fe778aff6c90..9aea6bda83fb 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -245,14 +245,15 @@ def find_libpy(self, environment: 'Environment') -> None: self.is_found = True def get_windows_python_arch(self) -> T.Optional[str]: - if self.platform == 'mingw': - pycc = self.variables.get('CC') - if pycc.startswith('x86_64'): + if self.platform.startswith('mingw'): + if 'x86_64' in self.platform: return 'x86_64' - elif pycc.startswith(('i686', 'i386')): + elif 'i686' in self.platform: return 'x86' + elif 'aarch64' in self.platform: + return 'aarch64' else: - mlog.log(f'MinGW Python built with unknown CC {pycc!r}, please file a bug') + mlog.log(f'MinGW Python built with unknown platform {self.platform!r}, please file a bug') return None elif self.platform == 'win32': return 'x86' @@ -309,7 +310,7 @@ def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: ''')) # base_prefix to allow for virtualenvs. lib = Path(self.variables.get('base_prefix')) / libpath - elif self.platform == 'mingw': + elif self.platform.startswith('mingw'): if self.static: libname = self.variables.get('LIBRARY') else: From dcff439df085b609cb24454598c9879931b942b8 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Sun, 3 Dec 2023 15:41:20 -0500 Subject: [PATCH 460/855] Fix test failure on Darwin on a case-sensitive fs This was encountered while looking into an issue with https://github.com/NixOS/nixpkgs/pull/268583. I run my Nix store on case-sensitive APFS, so the test fails due to trying to link `-framework ldap` instead of `-framework LDAP`. --- test cases/osx/5 extra frameworks/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/osx/5 extra frameworks/meson.build b/test cases/osx/5 extra frameworks/meson.build index f6c01e63a1bd..96532846c632 100644 --- a/test cases/osx/5 extra frameworks/meson.build +++ b/test cases/osx/5 extra frameworks/meson.build @@ -7,7 +7,7 @@ dep_main = dependency('Foundation') assert(dep_main.type_name() == 'extraframeworks', 'type_name is ' + dep_main.type_name()) # https://github.com/mesonbuild/meson/issues/10002 -ldap_dep = dependency('ldap', method : 'extraframework') +ldap_dep = dependency('LDAP', method : 'extraframework') assert(ldap_dep.type_name() == 'extraframeworks', 'type_name is ' + ldap_dep.type_name()) stlib = static_library('stat', 'stat.c', install : true, dependencies: [opengl_dep, ldap_dep]) From f1c748df87554aa5800fe4ecdea3ab1178e8f613 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 4 Dec 2023 11:24:26 -0800 Subject: [PATCH 461/855] run_project_tests: remove debug print --- run_project_tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/run_project_tests.py b/run_project_tests.py index 39bf1628f4aa..be3a3329811b 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1562,7 +1562,6 @@ def get_version(t: ToolInfo) -> str: print() tmpdir = list(Path('.').glob('**/*install functions and follow symlinks')) -print(tmpdir) assert(len(tmpdir) == 1) symlink_test_dir = tmpdir[0] symlink_file1 = symlink_test_dir / 'foo/link1' From 30184a48a032e6a2a6dbf0a76e437aa676c3e4aa Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 16:34:31 -0800 Subject: [PATCH 462/855] macos: Skip as-needed test, the linker is too smart The new linker in Sonoma / Xcode 15 considers the dependency via the initializer sufficient to pull in the library. The man page now notes: The linker never dead strips initialization and termination routines. They are considered "roots" of the dead strip graph. I could not find a good way to skip only if the linker version is new enough. Before long everyone will be using the new linker anyway... --- test cases/common/173 as-needed/meson.build | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test cases/common/173 as-needed/meson.build b/test cases/common/173 as-needed/meson.build index 3b54aaa02c17..1c2f632b4946 100644 --- a/test cases/common/173 as-needed/meson.build +++ b/test cases/common/173 as-needed/meson.build @@ -11,3 +11,10 @@ libB = library('B', 'libB.cpp', link_with : libA) main_exe = executable('C', 'main.cpp', link_with : [libA, libB]) test('main test', main_exe) + +# Since Sonoma / Xcode 15 the macos linker considers the dependency via the +# initializer sufficient to pull in the other other library. There's no good +# way to detect the linker version here, so just skip the on macos. +if host_machine.system() == 'darwin' + error('MESON_SKIP_TEST: the macos linker is too smart for this test') +endif From 5f659af870011e74299d1455a65c2cd5f5ace51f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 5 Dec 2023 14:26:54 -0500 Subject: [PATCH 463/855] ninja backend: don't hide all compiler warnings for transpiled languages This was originally added for vala only, with the rationale that vala generates bad code that has warnings. Unfortunately, the rationale was fatally flawed. The compiler warns about a number of things, which the user can control depending on their code (or their code generator's code), but some of those things are absolutely critical to warn about. In particular, GCC 14 and clang 17 are updating their defaults to warn -- and error by default for -- invalid C code that breaks the standard, but has been silently accepted for over 20 years "because lots of people do it". The code in question is UB, and compilers will generate faulty machine code that behaves erroneously and probably has a mass of CVEs waiting to happen. Compiler warnings are NOT safe to just... universally turn off. Compiler warnings could be either: - coding style lints - threatening statements that the code is factually and behaviorally wrong There is no magic bullet to ignore the former while respecting the latter. And the very last thing we should ever do is pass `-w`, since that causes ALL warnings to be disabled, even the manually added `-Werror=XXX`. If vala generated code creates warnings, then the vala compiler can decrease the log level by generating better code, or by adding warning suppression pragmas for *specific* issues, such as unused functions. --- mesonbuild/backend/backends.py | 13 ++----- mesonbuild/backend/ninjabackend.py | 19 ++++------ .../failing build/1 vala c werror/meson.build | 10 ----- .../failing build/1 vala c werror/prog.vala | 7 ---- .../1 vala c werror/unused-var.c | 8 ---- test cases/vala/5 target glib/meson.build | 4 -- unittests/linuxliketests.py | 37 ------------------- 7 files changed, 11 insertions(+), 87 deletions(-) delete mode 100644 test cases/failing build/1 vala c werror/meson.build delete mode 100644 test cases/failing build/1 vala c werror/prog.vala delete mode 100644 test cases/failing build/1 vala c werror/unused-var.c diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 2c24e4c314a7..639e07b2aac2 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -986,7 +986,7 @@ def get_no_stdlib_args(self, target: 'build.BuildTarget', compiler: 'Compiler') return compiler.get_no_stdinc_args() return [] - def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Compiler', no_warn_args: bool = False) -> 'CompilerArgs': + def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Compiler') -> 'CompilerArgs': # Create an empty commands list, and start adding arguments from # various sources in the order in which they must override each other # starting from hard-coded defaults followed by build options and so on. @@ -999,17 +999,12 @@ def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Com commands += self.get_no_stdlib_args(target, compiler) # Add things like /NOLOGO or -pipe; usually can't be overridden commands += compiler.get_always_args() - # Only add warning-flags by default if the buildtype enables it, and if - # we weren't explicitly asked to not emit warnings (for Vala, f.ex) - if no_warn_args: - commands += compiler.get_no_warn_args() - else: - # warning_level is a string, but mypy can't determine that - commands += compiler.get_warn_args(T.cast('str', target.get_option(OptionKey('warning_level')))) + # warning_level is a string, but mypy can't determine that + commands += compiler.get_warn_args(T.cast('str', target.get_option(OptionKey('warning_level')))) # Add -Werror if werror=true is set in the build options set on the # command-line or default_options inside project(). This only sets the # action to be done for warnings if/when they are emitted, so it's ok - # to set it after get_no_warn_args() or get_warn_args(). + # to set it after or get_warn_args(). if target.get_option(OptionKey('werror')): commands += compiler.get_werror_args() # Add compile args for c_* or cpp_* build options set on the diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 049ae253fe34..cdb747d73f27 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1939,7 +1939,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: if cratetype in {'bin', 'dylib'}: args.extend(rustc.get_linker_always_args()) - args += self.generate_basic_compiler_args(target, rustc, False) + args += self.generate_basic_compiler_args(target, rustc) # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] depfile = os.path.join(target.subdir, target.name + '.d') @@ -2804,10 +2804,9 @@ def generate_inc_dir(self, compiler: 'Compiler', d: str, basedir: str, is_system bargs = [] return (sargs, bargs) - def _generate_single_compile(self, target: build.BuildTarget, compiler: 'Compiler', - is_generated: bool = False) -> 'CompilerArgs': + def _generate_single_compile(self, target: build.BuildTarget, compiler: Compiler) -> CompilerArgs: commands = self._generate_single_compile_base_args(target, compiler) - commands += self._generate_single_compile_target_args(target, compiler, is_generated) + commands += self._generate_single_compile_target_args(target, compiler) return commands def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler: 'Compiler') -> 'CompilerArgs': @@ -2825,14 +2824,10 @@ def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler return commands @lru_cache(maxsize=None) - def _generate_single_compile_target_args(self, target: build.BuildTarget, compiler: 'Compiler', - is_generated: bool = False) -> 'ImmutableListProtocol[str]': - # The code generated by valac is usually crap and has tons of unused - # variables and such, so disable warnings for Vala C sources. - no_warn_args = is_generated == 'vala' + def _generate_single_compile_target_args(self, target: build.BuildTarget, compiler: Compiler) -> ImmutableListProtocol[str]: # Add compiler args and include paths from several sources; defaults, # build options, external dependencies, etc. - commands = self.generate_basic_compiler_args(target, compiler, no_warn_args) + commands = self.generate_basic_compiler_args(target, compiler) # Add custom target dirs as includes automatically, but before # target-specific include directories. if target.implicit_include_directories: @@ -2901,7 +2896,7 @@ def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) - if use_pch and 'mw' not in compiler.id: commands += self.get_pch_include_args(compiler, target) - commands += self._generate_single_compile_target_args(target, compiler, is_generated=False) + commands += self._generate_single_compile_target_args(target, compiler) # Metrowerks compilers require PCH include args to come after intraprocedural analysis args if use_pch and 'mw' in compiler.id: @@ -2935,7 +2930,7 @@ def generate_single_compile(self, target: build.BuildTarget, src, if use_pch and 'mw' not in compiler.id: commands += self.get_pch_include_args(compiler, target) - commands += self._generate_single_compile_target_args(target, compiler, is_generated) + commands += self._generate_single_compile_target_args(target, compiler) # Metrowerks compilers require PCH include args to come after intraprocedural analysis args if use_pch and 'mw' in compiler.id: diff --git a/test cases/failing build/1 vala c werror/meson.build b/test cases/failing build/1 vala c werror/meson.build deleted file mode 100644 index 736d7aa436d4..000000000000 --- a/test cases/failing build/1 vala c werror/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -project('valatest', 'c', default_options : 'werror=true') - -if find_program('valac', required : false).found() - add_languages('vala') - valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] - # Must fail due to -Werror and unused variable in C file - executable('valaprog', 'prog.vala', 'unused-var.c', dependencies : valadeps) -else - executable('failprog', 'unused-var.c') -endif diff --git a/test cases/failing build/1 vala c werror/prog.vala b/test cases/failing build/1 vala c werror/prog.vala deleted file mode 100644 index 638e776600bc..000000000000 --- a/test cases/failing build/1 vala c werror/prog.vala +++ /dev/null @@ -1,7 +0,0 @@ -class MainProg : GLib.Object { - - public static int main(string[] args) { - stdout.printf("Vala is working.\n"); - return 0; - } -} diff --git a/test cases/failing build/1 vala c werror/unused-var.c b/test cases/failing build/1 vala c werror/unused-var.c deleted file mode 100644 index 6b85078c91af..000000000000 --- a/test cases/failing build/1 vala c werror/unused-var.c +++ /dev/null @@ -1,8 +0,0 @@ -#warning "something" - -int -somelib(void) -{ - int unused_var; - return 33; -} diff --git a/test cases/vala/5 target glib/meson.build b/test cases/vala/5 target glib/meson.build index f285d9f16c4d..089bb3c97354 100644 --- a/test cases/vala/5 target glib/meson.build +++ b/test cases/vala/5 target glib/meson.build @@ -1,9 +1,5 @@ project('valatest', 'vala', 'c') -if not meson.is_unity() - add_global_arguments('-Werror', language : 'c') -endif - valadeps = [dependency('glib-2.0', version : '>=2.32'), dependency('gobject-2.0')] e = executable('valaprog', 'GLib.Thread.vala', 'retcode.c', dependencies : valadeps) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 4fcf52e09f2c..a02c99e8f447 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -298,43 +298,6 @@ def test_symlink_builddir(self) -> None: self.build() self._run(self.mtest_command) - def test_vala_c_warnings(self): - ''' - Test that no warnings are emitted for C code generated by Vala. This - can't be an ordinary test case because we need to inspect the compiler - database. - https://github.com/mesonbuild/meson/issues/864 - ''' - if not shutil.which('valac'): - raise SkipTest('valac not installed.') - testdir = os.path.join(self.vala_test_dir, '5 target glib') - self.init(testdir) - compdb = self.get_compdb() - vala_command = None - c_command = None - for each in compdb: - if each['file'].endswith('GLib.Thread.c'): - vala_command = each['command'] - elif each['file'].endswith('GLib.Thread.vala'): - continue - elif each['file'].endswith('retcode.c'): - c_command = each['command'] - else: - m = 'Unknown file {!r} in vala_c_warnings test'.format(each['file']) - raise AssertionError(m) - self.assertIsNotNone(vala_command) - self.assertIsNotNone(c_command) - # -w suppresses all warnings, should be there in Vala but not in C - self.assertIn(" -w ", vala_command) - self.assertNotIn(" -w ", c_command) - # -Wall enables all warnings, should be there in C but not in Vala - self.assertNotIn(" -Wall ", vala_command) - self.assertIn(" -Wall ", c_command) - # -Werror converts warnings to errors, should always be there since it's - # injected by an unrelated piece of code and the project has werror=true - self.assertIn(" -Werror ", vala_command) - self.assertIn(" -Werror ", c_command) - @skipIfNoPkgconfig def test_qtdependency_pkgconfig_detection(self): ''' From 39ecfc2d542ae7e248119b5dcb6f0a01493e2ae6 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 5 Dec 2023 14:48:39 -0500 Subject: [PATCH 464/855] compilers: drop dead code no_warn_args is unused. Its only purpose was to implement automatic hiding of UB in transpiled code, and it was not used at all in languages other than C/C++ -- specifically when the C/C++ source files were created by transpiling from vala or cython. --- mesonbuild/compilers/compilers.py | 4 ---- mesonbuild/compilers/fortran.py | 4 ---- mesonbuild/compilers/java.py | 3 --- mesonbuild/compilers/mixins/clike.py | 4 ---- mesonbuild/compilers/mixins/pgi.py | 3 --- mesonbuild/compilers/rust.py | 3 --- mesonbuild/compilers/vala.py | 3 --- 7 files changed, 24 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index a7bb6c417932..671e3f9cd1ac 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1377,10 +1377,6 @@ def get_debug_args(self, is_debug: bool) -> T.List[str]: """Arguments required for a debug build.""" return [] - def get_no_warn_args(self) -> T.List[str]: - """Arguments to completely disable warnings.""" - return [] - def needs_static_linker(self) -> bool: raise NotImplementedError(f'There is no static linker for {self.language}') diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index a80fdff5f44c..e2c0f80bdd33 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -253,10 +253,6 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic def get_module_outdir_args(self, path: str) -> T.List[str]: return ['-fmod=' + path] - def get_no_warn_args(self) -> T.List[str]: - # FIXME: Confirm that there's no compiler option to disable all warnings - return [] - class SunFortranCompiler(FortranCompiler): diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index 9f508d637313..fb81682edb9f 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -52,9 +52,6 @@ def get_warn_args(self, level: str) -> T.List[str]: def get_werror_args(self) -> T.List[str]: return ['-Werror'] - def get_no_warn_args(self) -> T.List[str]: - return ['-nowarn'] - def get_output_args(self, outputname: str) -> T.List[str]: if outputname == '': outputname = './' diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index ad8fa2747495..3cf79a66141f 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -177,10 +177,6 @@ def get_warn_args(self, level: str) -> T.List[str]: # TODO: this should be an enum return self.warn_args[level] - def get_no_warn_args(self) -> T.List[str]: - # Almost every compiler uses this for disabling warnings - return ['-w'] - def get_depfile_suffix(self) -> str: return 'd' diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 6362b46ac699..7a242839b3e1 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -61,9 +61,6 @@ def __init__(self) -> None: def get_module_incdir_args(self) -> T.Tuple[str]: return ('-module', ) - def get_no_warn_args(self) -> T.List[str]: - return ['-silent'] - def gen_import_library_args(self, implibname: str) -> T.List[str]: return [] diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 1fb94aa4447a..1eac1c064daa 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -213,9 +213,6 @@ def get_warn_args(self, level: str) -> T.List[str]: # TODO: I'm not really sure what to put here, Rustc doesn't have warning return self._WARNING_LEVELS[level] - def get_no_warn_args(self) -> T.List[str]: - return self._WARNING_LEVELS["0"] - def get_pic_args(self) -> T.List[str]: # relocation-model=pic is rustc's default already. return [] diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index ded158e8190e..c0d006a2eaa6 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -66,9 +66,6 @@ def get_always_args(self) -> T.List[str]: def get_warn_args(self, level: str) -> T.List[str]: return [] - def get_no_warn_args(self) -> T.List[str]: - return ['--disable-warnings'] - def get_werror_args(self) -> T.List[str]: return ['--fatal-warnings'] From 7148b4f207bd7a09d9191abe7ffee8d7996c4634 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 16:52:19 -0800 Subject: [PATCH 465/855] macos: Do not emit -undefined,error for Sonoma compatibility Emitting -undefined,error was correct,, but starting with Xcode 15 / Sonoma, doing so triggers "ld: warning: -undefined error is deprecated". Given that "-undefined error" is documented to be the linker's default behaviour, this warning seems ill advised. However, it does create a lot of noise. As "-undefined error" is the default behaviour, the least bad way to deal with this seems to be to just not emit anything. Of course that only works as long as nothing else injects -undefined dynamic_lookup, or such. Complain to Apple. Fixes: https://github.com/mesonbuild/meson/issues/12450 --- mesonbuild/linkers/linkers.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index dbb5e57aa585..ec8edba11934 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -792,7 +792,15 @@ def sanitizer_args(self, value: str) -> T.List[str]: return ['-fsanitize=' + value] def no_undefined_args(self) -> T.List[str]: - return self._apply_prefix('-undefined,error') + # We used to emit -undefined,error, but starting with Xcode 15 / + # Sonoma, doing so triggers "ld: warning: -undefined error is + # deprecated". Given that "-undefined error" is documented to be the + # linker's default behaviour, this warning seems ill advised. However, + # it does create a lot of noise. As "-undefined error" is the default + # behaviour, the least bad way to deal with this seems to be to just + # not emit anything here. Of course that only works as long as nothing + # else injects -undefined dynamic_lookup, or such. Complain to Apple. + return [] def headerpad_args(self) -> T.List[str]: return self._apply_prefix('-headerpad_max_install_names') From 254abb999fae0e29a20200472f016f2cd7236aef Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 30 Nov 2023 17:22:49 -0500 Subject: [PATCH 466/855] Fix coverage with lcov 2.0 and uncovered subprojects Version 2.0 of lcov triggers an error when an exclude pattern is unused. This can happen when the project has subprojects, but no code in them ends up covered: lcov: ERROR: 'exclude' pattern '/[...]/subprojects/*' is unused. (use "lcov --ignore-errors unused ..." to bypass this error) So, simply do as it says. Unused patterns doesn't seem problematic (or even interesting) here, so I don't think there's any risk in simply turning this off, which matches what happened with earlier versions of lcov anyway. --- mesonbuild/scripts/coverage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 4c0f81e8a026..54b00cbc4d92 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -145,6 +145,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build '--remove', covinfo, *lcov_subpoject_exclude, *lcov_exe_rc_branch_coverage, + '--ignore-errors', 'unused', '--output-file', covinfo] + lcov_config) subprocess.check_call([genhtml_exe, '--prefix', build_root, From 5de09cbe8838e8febf1ca3aa83b53cf06972bff3 Mon Sep 17 00:00:00 2001 From: Erwin Jansen Date: Tue, 28 Nov 2023 12:48:49 -0800 Subject: [PATCH 467/855] Always use posix paths when retrieving link name This commit modifies the get_target_filename_for_linking function to always return POSIX-style paths, even on Windows systems. This is necessary because the Ninja generator can have issues with Windows-style paths when using the `/WHOLEARCHIVE:` flag. This is consistent with the syntax accepted by the cl and clang-cl compilers, as documented in the Microsoft documentation: https: //learn.microsoft.com/en-us/cpp/build/reference/cl-filename-syntax?view=msvc-170 Fixes: 12534 --- mesonbuild/backend/backends.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 639e07b2aac2..f60c884fb2cc 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -358,16 +358,16 @@ def get_target_filename_for_linking(self, target: T.Union[build.Target, build.Cu # In AIX, if we archive .so, the blibpath must link to archived shared library otherwise to the .so file. if mesonlib.is_aix() and target.aix_so_archive: link_lib = re.sub('[.][a]([.]?([0-9]+))*([.]?([a-z]+))*', '.a', link_lib.replace('.so', '.a')) - return os.path.join(self.get_target_dir(target), link_lib) + return Path(self.get_target_dir(target), link_lib).as_posix() elif isinstance(target, build.StaticLibrary): - return os.path.join(self.get_target_dir(target), target.get_filename()) + return Path(self.get_target_dir(target), target.get_filename()).as_posix() elif isinstance(target, (build.CustomTarget, build.CustomTargetIndex)): if not target.is_linkable_target(): raise MesonException(f'Tried to link against custom target "{target.name}", which is not linkable.') - return os.path.join(self.get_target_dir(target), target.get_filename()) + return Path(self.get_target_dir(target), target.get_filename()).as_posix() elif isinstance(target, build.Executable): if target.import_filename: - return os.path.join(self.get_target_dir(target), target.get_import_filename()) + return Path(self.get_target_dir(target), target.get_import_filename()).as_posix() else: return None raise AssertionError(f'BUG: Tried to link to {target!r} which is not linkable') From be04234c852dc99d486f4199da26b272597bf0c7 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Fri, 8 Dec 2023 01:57:43 +0500 Subject: [PATCH 468/855] external_project.py: fix --host value Currently in cross-compilation mode the --host is set to x86-linux-linux, which results in an error. Change the code so that for x86 and x86_64 the second part is 'pc', and 'unknown' for the rest. Use cpu model instead of cpu family for the first part, as suggested by @dcbaker As the result, we get: i386-pc-linux on my setup. Fixes #12608 --- mesonbuild/modules/external_project.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index bd6eba494156..4247ba0cf656 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -136,8 +136,9 @@ def _configure(self, state: 'ModuleState') -> None: configure_cmd += self._format_options(self.configure_options, d) if self.env.is_cross_build(): - host = '{}-{}-{}'.format(self.host_machine.cpu_family, - self.build_machine.system, + host = '{}-{}-{}'.format(self.host_machine.cpu, + 'pc' if self.host_machine.cpu_family in {"x86", "x86_64"} + else 'unknown', self.host_machine.system) d = [('HOST', None, host)] configure_cmd += self._format_options(self.cross_configure_options, d) From 7fbadfdeabecbe01db7104697c76ebaf0fb218ae Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 9 Dec 2023 11:09:56 +0100 Subject: [PATCH 469/855] ninja backend: Remove always true check --- 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 cdb747d73f27..58d91103e3e0 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2926,7 +2926,7 @@ def generate_single_compile(self, target: build.BuildTarget, src, # Include PCH header as first thing as it must be the first one or it will be # ignored by gcc https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100462 - use_pch = self.target_uses_pch(target) and is_generated != 'pch' + use_pch = self.target_uses_pch(target) if use_pch and 'mw' not in compiler.id: commands += self.get_pch_include_args(compiler, target) From c2ea14fbd2af448136cc8af65a9a4da13a39d35c Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 9 Dec 2023 11:13:03 +0100 Subject: [PATCH 470/855] ninja backend: Make values passed to bool argument consistent --- mesonbuild/backend/ninjabackend.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 58d91103e3e0..c5c208661414 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -970,8 +970,7 @@ def generate_target(self, target): if self.environment.is_llvm_ir(src): o, s = self.generate_llvm_ir_compile(target, src) else: - o, s = self.generate_single_compile(target, src, True, - order_deps=header_deps) + o, s = self.generate_single_compile(target, src, True, order_deps=header_deps) compiled_sources.append(s) source2object[s] = o obj_list.append(o) @@ -1018,7 +1017,7 @@ def generate_target(self, target): # Passing 'vala' here signifies that we want the compile # arguments to be specialized for C code generated by # valac. For instance, no warnings should be emitted. - o, s = self.generate_single_compile(target, src, 'vala', [], header_deps) + o, s = self.generate_single_compile(target, src, True, [], header_deps) obj_list.append(o) # Generate compile targets for all the preexisting sources for this target @@ -2908,7 +2907,7 @@ def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) - return src_type_to_args def generate_single_compile(self, target: build.BuildTarget, src, - is_generated=False, header_deps=None, + is_generated: bool = False, header_deps=None, order_deps: T.Optional[T.List['mesonlib.FileOrString']] = None, extra_args: T.Optional[T.List[str]] = None, unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None) -> None: From 76ab2db0863d85eb92933067a034c33962091286 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 9 Dec 2023 11:21:55 +0100 Subject: [PATCH 471/855] ninja backend: Adjust naming and comments Meson supports other transpilers generating source code for which compilation rules need to be generated other than Vala. Reflect this in variable names and comments to avoid confusion. --- mesonbuild/backend/ninjabackend.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index c5c208661414..0e5697740bf0 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -993,13 +993,15 @@ def generate_target(self, target): fortran_inc_args = mesonlib.listify([target.compilers['fortran'].get_include_args( self.get_target_private_dir(t), is_system=False) for t in obj_targets]) - # Generate compilation targets for C sources generated from Vala - # sources. This can be extended to other $LANG->C compilers later if - # necessary. This needs to be separate for at least Vala + # Generate compilation targets for sources generated by transpilers. # - # Do not try to unity-build the generated c files from vala, as these - # often contain duplicate symbols and will fail to compile properly - vala_generated_source_files = [] + # Do not try to unity-build the generated source files, as these + # often contain duplicate symbols and will fail to compile properly. + # + # Gather all generated source files and header before generating the + # compilation rules, to be able to add correct dependencies on the + # generated headers. + transpiled_source_files = [] for src in transpiled_sources: raw_src = File.from_built_relative(src) # Generated targets are ordered deps because the must exist @@ -1010,13 +1012,8 @@ def generate_target(self, target): if self.environment.is_header(src): header_deps.append(raw_src) else: - # We gather all these and generate compile rules below - # after `header_deps` (above) is fully generated - vala_generated_source_files.append(raw_src) - for src in vala_generated_source_files: - # Passing 'vala' here signifies that we want the compile - # arguments to be specialized for C code generated by - # valac. For instance, no warnings should be emitted. + transpiled_source_files.append(raw_src) + for src in transpiled_source_files: o, s = self.generate_single_compile(target, src, True, [], header_deps) obj_list.append(o) From 5883089f6c7b39726dd06a48a23d8eb8754a75f7 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 9 Dec 2023 11:28:04 +0100 Subject: [PATCH 472/855] ninja backend: Remove outdated comment Generation of both C and C++ from Cython is supported via the cython_language option. --- mesonbuild/backend/ninjabackend.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0e5697740bf0..77df82297372 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1726,10 +1726,8 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ def generate_cython_transpile(self, target: build.BuildTarget) -> \ T.Tuple[T.MutableMapping[str, File], T.MutableMapping[str, File], T.List[str]]: - """Generate rules for transpiling Cython files to C or C++ + """Generate rules for transpiling Cython files to C or C++""" - XXX: Currently only C is handled. - """ static_sources: T.MutableMapping[str, File] = OrderedDict() generated_sources: T.MutableMapping[str, File] = OrderedDict() cython_sources: T.List[str] = [] From 17c6d5eb478386ad183fa7e11b688217645d8f4f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 5 Dec 2023 20:33:38 -0500 Subject: [PATCH 473/855] unittests: migrate from jsonschema to fastjsonschema The former has rust dependencies, which lead to max capping on Cygwin since there is no rust compiler there. But it turns out there are other disadvantages of jsonschema: - it involves installing 5 wheels, instead of just 1 - it is much slower To give some perspective to the latter issue, this is what it looks like when I test with jsonschema: ``` ===== 1 passed, 509 deselected in 3.07s ===== Total time: 3.341 seconds ``` And here's what it looks like when I test with fastjsonschema: ``` ===== 1 passed, 509 deselected, 1 warning in 0.28s ===== Total time: 0.550 seconds ``` I cannot think of a good reason to use the former. Although in order to work on old CI images, we'll support it as a fallback mechanism --- .github/workflows/cygwin.yml | 3 +-- .github/workflows/macos.yml | 2 +- .github/workflows/msys2.yml | 4 ++-- ci/ciimage/common.sh | 2 +- ci/run.ps1 | 2 +- unittests/internaltests.py | 27 +++++++++++++++++++-------- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index e62c745afea8..3b1b1851626e 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -76,8 +76,7 @@ jobs: - name: Run pip run: | export PATH=/usr/bin:/usr/local/bin:$(cygpath ${SYSTEMROOT})/system32 - # jsonschema is max capped because the new version depends on rust dependencies which are... hard to get on cygwin - python3 -m pip --disable-pip-version-check install gcovr 'jsonschema<4.18' pefile pytest pytest-subtests pytest-xdist coverage + python3 -m pip --disable-pip-version-check install gcovr fastjsonschema pefile pytest pytest-subtests pytest-xdist coverage shell: C:\cygwin\bin\bash.exe --noprofile --norc -o igncr -eo pipefail '{0}' - uses: actions/cache/save@v3 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6d6b43af7e42..0e5002a408c9 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -33,7 +33,7 @@ jobs: python-version: '3.x' - run: | python -m pip install --upgrade pip - python -m pip install pytest pytest-xdist pytest-subtests jsonschema coverage + python -m pip install pytest pytest-xdist pytest-subtests fastjsonschema coverage - run: brew install pkg-config ninja llvm qt@5 - env: CPPFLAGS: "-I/usr/local/include" diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 2bdcdd30e6f4..043f5ce2a462 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -80,7 +80,7 @@ jobs: mingw-w64-${{ matrix.MSYS2_ARCH }}-python-lxml mingw-w64-${{ matrix.MSYS2_ARCH }}-python-setuptools mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip - mingw-w64-${{ matrix.MSYS2_ARCH }}-python-jsonschema + mingw-w64-${{ matrix.MSYS2_ARCH }}-python-fastjsonschema mingw-w64-${{ matrix.MSYS2_ARCH }}-${{ matrix.TOOLCHAIN }} - name: Install dependencies @@ -100,7 +100,7 @@ jobs: - name: Run Tests run: | if [[ "${{ matrix.MSYS2_ARCH }}" == "x86_64" ]]; then - # There apparently is no clean way to add to the PATH in the + # There apparently is no clean way to add to the PATH in the # previous step? # See for instance https://github.com/msys2/setup-msys2/issues/171 export PATH=$PATH:$PWD/pypy3local diff --git a/ci/ciimage/common.sh b/ci/ciimage/common.sh index 67d59978f5a7..0169182408d5 100644 --- a/ci/ciimage/common.sh +++ b/ci/ciimage/common.sh @@ -15,7 +15,7 @@ base_python_pkgs=( pytest-xdist pytest-subtests coverage - jsonschema + fastjsonschema ) python_pkgs=( diff --git a/ci/run.ps1 b/ci/run.ps1 index badb4a74eae2..05bb6b69e216 100644 --- a/ci/run.ps1 +++ b/ci/run.ps1 @@ -92,7 +92,7 @@ python --version # Needed for running unit tests in parallel. echo "" -python -m pip --disable-pip-version-check install --upgrade pefile pytest-xdist pytest-subtests jsonschema coverage +python -m pip --disable-pip-version-check install --upgrade pefile pytest-xdist pytest-subtests fastjsonschema coverage # Needed for running the Cython tests python -m pip --disable-pip-version-check install cython diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 1c55b2976016..66bf4586c175 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1012,19 +1012,30 @@ def test_dependency_factory_order(self): def test_validate_json(self) -> None: """Validate the json schema for the test cases.""" try: - from jsonschema import validate, ValidationError + from fastjsonschema import compile, JsonSchemaValueException as JsonSchemaFailure + fast = True except ImportError: - if is_ci(): - raise - raise unittest.SkipTest('Python jsonschema module not found.') - - schema = json.loads(Path('data/test.schema.json').read_text(encoding='utf-8')) + try: + from jsonschema import validate, ValidationError as JsonSchemaFailure + fast = False + except: + if is_ci(): + raise + raise unittest.SkipTest('neither Python fastjsonschema nor jsonschema module not found.') + + with open('data/test.schema.json', 'r', encoding='utf-8') as f: + data = json.loads(f.read()) + + if fast: + schema_validator = compile(data) + else: + schema_validator = lambda x: validate(x, schema=data) errors: T.List[T.Tuple[Path, Exception]] = [] for p in Path('test cases').glob('**/test.json'): try: - validate(json.loads(p.read_text(encoding='utf-8')), schema=schema) - except ValidationError as e: + schema_validator(json.loads(p.read_text(encoding='utf-8'))) + except JsonSchemaFailure as e: errors.append((p.resolve(), e)) for f, e in errors: From af0464352aa46324a1a59f8a1e82b6cdd46ec891 Mon Sep 17 00:00:00 2001 From: arch1t3cht Date: Tue, 5 Dec 2023 00:53:59 +0100 Subject: [PATCH 474/855] vs: Manually link generated .o files Fixes #12550 . VS automatically links CustomBuild outputs ending in .obj or .res, but others need to be included explicitly. --- mesonbuild/backend/vs2010backend.py | 21 ++++++------------- .../common/52 object generator/meson.build | 10 ++++++++- test cases/common/52 object generator/prog.c | 3 ++- .../common/52 object generator/source4.c | 3 +++ 4 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 test cases/common/52 object generator/source4.c diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index f4de6582360c..f102fbe14140 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -894,18 +894,6 @@ def add_include_dirs(self, lang, parent_node, file_inc_dirs): dirs = file_inc_dirs[lang] ET.SubElement(parent_node, "AdditionalIncludeDirectories").text = ';'.join(dirs) - @staticmethod - def has_objects(objects, additional_objects, generated_objects): - # Ignore generated objects, those are automatically used by MSBuild because they are part of - # the CustomBuild Outputs. - return len(objects) + len(additional_objects) > 0 - - @staticmethod - def add_generated_objects(node, generated_objects): - # Do not add generated objects to project file. Those are automatically used by MSBuild, because - # they are part of the CustomBuild Outputs. - return - @staticmethod def escape_preprocessor_define(define: str) -> str: # See: https://msdn.microsoft.com/en-us/library/bb383819.aspx @@ -1779,17 +1767,20 @@ def path_normalize_add(path, lis): for o in custom_objs: additional_objects.append(o) + # VS automatically links CustomBuild outputs whose name ends in .obj or .res, + # but the others need to be included explicitly + explicit_link_gen_objs = [obj for obj in gen_objs if not obj.endswith(('.obj', '.res'))] + previous_objects = [] - if self.has_objects(objects, additional_objects, gen_objs): + if len(objects) + len(additional_objects) + len(explicit_link_gen_objs) > 0: inc_objs = ET.SubElement(root, 'ItemGroup') for s in objects: relpath = os.path.join(proj_to_build_root, s.rel_to_builddir(self.build_to_src)) if path_normalize_add(relpath, previous_objects): ET.SubElement(inc_objs, 'Object', Include=relpath) - for s in additional_objects: + for s in additional_objects + explicit_link_gen_objs: if path_normalize_add(s, previous_objects): ET.SubElement(inc_objs, 'Object', Include=s) - self.add_generated_objects(inc_objs, gen_objs) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') self.add_regen_dependency(root) diff --git a/test cases/common/52 object generator/meson.build b/test cases/common/52 object generator/meson.build index e20da6f466dd..49590d6d60f9 100644 --- a/test cases/common/52 object generator/meson.build +++ b/test cases/common/52 object generator/meson.build @@ -29,6 +29,14 @@ gen2 = generator(python, arguments : [comp, cc, '@INPUT@', '@OUTPUT0@']) generated2 = gen2.process(['source3.c']) -e = executable('prog', 'prog.c', generated, generated2) +# Generate an object file ending with .o even on Windows. +# The VS backend needs to handle .o objects differently from .obj objects. +gen3 = generator(python, + output : '@BASENAME@.o', + arguments : [comp, cc, '@INPUT@', '@OUTPUT@']) + +generated3 = gen3.process(['source4.c']) + +e = executable('prog', 'prog.c', generated, generated2, generated3) test('objgen', e) \ No newline at end of file diff --git a/test cases/common/52 object generator/prog.c b/test cases/common/52 object generator/prog.c index 9841180d0cfb..80056dc031a9 100644 --- a/test cases/common/52 object generator/prog.c +++ b/test cases/common/52 object generator/prog.c @@ -1,7 +1,8 @@ int func1_in_obj(void); int func2_in_obj(void); int func3_in_obj(void); +int func4_in_obj(void); int main(void) { - return func1_in_obj() + func2_in_obj() + func3_in_obj(); + return func1_in_obj() + func2_in_obj() + func3_in_obj() + func4_in_obj(); } diff --git a/test cases/common/52 object generator/source4.c b/test cases/common/52 object generator/source4.c new file mode 100644 index 000000000000..83f4fab81285 --- /dev/null +++ b/test cases/common/52 object generator/source4.c @@ -0,0 +1,3 @@ +int func4_in_obj(void) { + return 0; +} From 9d8f69a16fd6cdaea843cc605266c2a90e9eeaa8 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 29 Jul 2023 14:14:07 -0500 Subject: [PATCH 475/855] xcode: Add support for extra files Fixes #10903 --- mesonbuild/backend/xcodebackend.py | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index ec03627dd04b..2e18573e2b12 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -352,6 +352,13 @@ def generate_filemap(self) -> None: if isinstance(o, str): o = os.path.join(t.subdir, o) self.filemap[o] = self.gen_id() + for e in t.extra_files: + if isinstance(e, mesonlib.File): + e = os.path.join(e.subdir, e.fname) + self.filemap[e] = self.gen_id() + else: + e = os.path.join(t.subdir, e) + self.filemap[e] = self.gen_id() self.target_filemap[name] = self.gen_id() def generate_buildstylemap(self) -> None: @@ -523,6 +530,16 @@ def generate_target_file_maps_impl(self, targets): self.fileref_ids[k] = self.gen_id() else: raise RuntimeError('Unknown input type ' + str(o)) + for e in t.extra_files: + if isinstance(e, mesonlib.File): + e = os.path.join(e.subdir, e.fname) + if isinstance(e, str): + e = os.path.join(t.subdir, e) + k = (tname, e) + assert k not in self.buildfile_ids + self.buildfile_ids[k] = self.gen_id() + assert k not in self.fileref_ids + self.fileref_ids[k] = self.gen_id() def generate_build_file_maps(self) -> None: for buildfile in self.interpreter.get_build_def_files(): @@ -791,6 +808,24 @@ def generate_pbx_file_reference(self, objects_dict): o_dict.add_item('name', f'"{name}"') o_dict.add_item('path', f'"{rel_name}"') o_dict.add_item('sourceTree', 'SOURCE_ROOT') + + for e in t.extra_files: + if isinstance(e, mesonlib.File): + e = os.path.join(e.subdir, e.fname) + else: + e = os.path.join(t.subdir, e) + idval = self.fileref_ids[(tname, e)] + fullpath = os.path.join(self.environment.get_source_dir(), e) + e_dict = PbxDict() + xcodetype = self.get_xcodetype(e) + name = os.path.basename(e) + path = e + objects_dict.add_item(idval, e_dict, fullpath) + e_dict.add_item('isa', 'PBXFileReference') + e_dict.add_item('explicitFileType', '"' + xcodetype + '"') + e_dict.add_item('name', '"' + name + '"') + e_dict.add_item('path', '"' + path + '"') + e_dict.add_item('sourceTree', 'SOURCE_ROOT') for tname, idval in self.target_filemap.items(): target_dict = PbxDict() objects_dict.add_item(idval, target_dict, tname) @@ -989,6 +1024,14 @@ def write_group_target_entry(self, objects_dict, t): else: o = os.path.join(t.subdir, o) target_children.add_item(self.fileref_ids[(tid, o)], o) + for e in t.extra_files: + if isinstance(e, mesonlib.File): + e = os.path.join(e.subdir, e.fname) + elif isinstance(e, str): + e = os.path.join(t.subdir, e) + else: + continue + target_children.add_item(self.fileref_ids[(tid, e)], e) source_files_dict.add_item('name', '"Source files"') source_files_dict.add_item('sourceTree', '""') return group_id From 5bf99afe1abc8b08f8cf68b30817e86f223ec32d Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Thu, 27 Jul 2023 14:41:39 -0500 Subject: [PATCH 476/855] xcode: Set bridging header for mixed swift targets This must be explicitly set in Xcode or it will not be able to compile mixed targets successfully. This is not needed for pure Swift targets. Set a new variable "is_swift" so finding the bridging header does not take O(n^2) time. Fixes passing swift test case 5 (mixed) with Xcode backend. --- mesonbuild/backend/xcodebackend.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 2e18573e2b12..97b0ead2dc52 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1467,6 +1467,8 @@ def generate_single_build_target(self, objects_dict, target_name, target): dep_libs = [] links_dylib = False headerdirs = [] + bridging_header = "" + is_swift = self.is_swift_target(target) for d in target.include_dirs: for sd in d.incdirs: cd = os.path.join(d.curdir, sd) @@ -1474,6 +1476,13 @@ def generate_single_build_target(self, objects_dict, target_name, target): headerdirs.append(os.path.join(self.environment.get_build_dir(), cd)) for extra in d.extra_build_dirs: headerdirs.append(os.path.join(self.environment.get_build_dir(), extra)) + # Swift can import declarations from C-based code using bridging headers. + # There can only be one header, and it must be included as a source file. + for i in target.get_sources(): + if self.environment.is_header(i) and is_swift: + relh = i.rel_to_builddir(self.build_to_src) + bridging_header = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh)) + break (dep_libs, links_dylib) = self.determine_internal_dep_link_args(target, buildtype) if links_dylib: dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs @@ -1496,7 +1505,7 @@ def generate_single_build_target(self, objects_dict, target_name, target): ldargs += target.link_args # Swift is special. Again. You can't mix Swift with other languages # in the same target. Thus for Swift we only use - if self.is_swift_target(target): + if is_swift: linker, stdlib_args = target.compilers['swift'], [] else: linker, stdlib_args = self.determine_linker_and_stdlib_args(target) @@ -1651,6 +1660,8 @@ def generate_single_build_target(self, objects_dict, target_name, target): else: settings_dict.add_item('PRODUCT_NAME', product_name) settings_dict.add_item('SECTORDER_FLAGS', '""') + if is_swift and bridging_header: + settings_dict.add_item('SWIFT_OBJC_BRIDGING_HEADER', f'"{bridging_header}"') settings_dict.add_item('SYMROOT', f'"{symroot}"') sysheader_arr = PbxArray() # XCode will change every -I flag that points inside these directories From 3836deeed2fb4721f6e021be31de6a931a8374db Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Mon, 31 Jul 2023 10:13:06 -0500 Subject: [PATCH 477/855] xcode: Classify metal and glsl files correctly This fixes syntax highlighting on Xcode when viewing those files. --- mesonbuild/backend/xcodebackend.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 97b0ead2dc52..7f9f67ee7fd5 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -44,6 +44,8 @@ 'o': 'compiled.mach-o.objfile', 's': 'sourcecode.asm', 'asm': 'sourcecode.asm', + 'metal': 'sourcecode.metal', + 'glsl': 'sourcecode.glsl', } LANGNAMEMAP = {'c': 'C', 'cpp': 'CPLUSPLUS', From 1b09cac2523074def8d3a48b82768ae4afcf69eb Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Mon, 31 Jul 2023 12:28:25 -0500 Subject: [PATCH 478/855] xcode: Search for dependencies for custom targets When generating aggregated targets, custom targets were not being checked for dependencies when they should have. Fixes passing swift test case 4 (generate). --- mesonbuild/backend/xcodebackend.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 7f9f67ee7fd5..f8fa738935d8 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -581,6 +581,11 @@ def generate_pbx_aggregate_target(self, objects_dict): build_phases = [] dependencies = [self.regen_dependency_id] generator_id = 0 + for d in t.dependencies: + if isinstance(d, build.CustomTarget): + dependencies.append(self.pbx_custom_dep_map[d.get_id()]) + elif isinstance(d, build.BuildTarget): + dependencies.append(self.pbx_dep_map[d.get_id()]) for s in t.sources: if not isinstance(s, build.GeneratedList): continue From 0914f1739b6567551e95ee950dc3bcaa53c61120 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Mon, 31 Jul 2023 14:56:32 -0500 Subject: [PATCH 479/855] xcode: Fix generating single generator phase --- mesonbuild/backend/xcodebackend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index f8fa738935d8..5088fe05408d 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1274,6 +1274,7 @@ def generate_single_generator_phase(self, tname, t, genlist, generator_id, objec exe = generator.get_exe() exe_arr = self.build_target_to_cmd_array(exe) workdir = self.environment.get_build_dir() + target_private_dir = self.relpath(self.get_target_private_dir(t), self.get_target_dir(t)) gen_dict = PbxDict() objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, f'"Generator {generator_id}/{tname}"') infilelist = genlist.get_inputs() @@ -1295,7 +1296,7 @@ def generate_single_generator_phase(self, tname, t, genlist, generator_id, objec # unclear whether it is necessary, what actually happens when it is defined # and currently the build works without it. #infile_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) - infilename = i.rel_to_builddir(self.build_to_src) + infilename = i.rel_to_builddir(self.build_to_src, target_private_dir) base_args = generator.get_arglist(infilename) for o_base in genlist.get_outputs_for(i): o = os.path.join(self.get_target_private_dir(t), o_base) From 1de398a3775063f52b7f287b603a1e3ca9e8fab5 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 12 Aug 2023 13:24:05 -0500 Subject: [PATCH 480/855] xcode: Wrap custom target output paths in quotes Without this, any build directory with a space in it was enough to make Xcode fail to open the project due to parsing errors. --- mesonbuild/backend/xcodebackend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 5088fe05408d..e2b8b99851d2 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -883,7 +883,7 @@ def generate_pbx_file_reference(self, objects_dict): custom_dict.add_item('isa', 'PBXFileReference') custom_dict.add_item('explicitFileType', '"' + typestr + '"') custom_dict.add_item('name', o) - custom_dict.add_item('path', os.path.join(self.src_to_build, o)) + custom_dict.add_item('path', f'"{os.path.join(self.src_to_build, o)}"') custom_dict.add_item('refType', 0) custom_dict.add_item('sourceTree', 'SOURCE_ROOT') objects_dict.add_item(self.custom_target_output_fileref[o], custom_dict) @@ -1242,7 +1242,7 @@ def generate_custom_target_shell_build_phases(self, objects_dict): custom_dict.add_item('name', '"Generate {}."'.format(ofilenames[0])) custom_dict.add_item('outputPaths', outarray) for o in ofilenames: - outarray.add_item(os.path.join(self.environment.get_build_dir(), o)) + outarray.add_item(f'"{os.path.join(self.environment.get_build_dir(), o)}"') custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0) custom_dict.add_item('shellPath', '/bin/sh') workdir = self.environment.get_build_dir() @@ -1290,7 +1290,7 @@ def generate_single_generator_phase(self, tname, t, genlist, generator_id, objec outarray = PbxArray() gen_dict.add_item('outputPaths', outarray) for of in ofile_abs: - outarray.add_item(of) + outarray.add_item(f'"{of}"') for i in infilelist: # This might be needed to be added to inputPaths. It's not done yet as it is # unclear whether it is necessary, what actually happens when it is defined From 354843c4281f21ad30da06f3a6284e6d3752b1ed Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Thu, 17 Aug 2023 13:14:04 -0500 Subject: [PATCH 481/855] xcode: Enclose work directory in shell scripts --- mesonbuild/backend/xcodebackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index e2b8b99851d2..590b24f06c99 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1250,7 +1250,7 @@ def generate_custom_target_shell_build_phases(self, objects_dict): for c in fixed_cmd: quoted_cmd.append(c.replace('"', chr(92) + '"')) cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd]) - custom_dict.add_item('shellScript', f'"cd {workdir}; {cmdstr}"') + custom_dict.add_item('shellScript', f'"cd \'{workdir}\'; {cmdstr}"') custom_dict.add_item('showEnvVarsInLog', 0) def generate_generator_target_shell_build_phases(self, objects_dict): From 2915ab31af4863f50521e664824b100b47025c9d Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Thu, 17 Aug 2023 16:16:19 -0500 Subject: [PATCH 482/855] xcode: Override determine_swift_deps_dir() Xcode does not recognize our private directories, nor does it ever try to generate them. Instead, just import the build directories for each swift dependency. This fixes linking between swift targets when they are in their own subdirectories, as they will have different build directories in that case. --- mesonbuild/backend/xcodebackend.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 590b24f06c99..3bfadd7e7878 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -255,6 +255,13 @@ def object_filename_from_source(self, target, source): obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' return obj_path + def determine_swift_dep_dirs(self, target): + result: T.List[str] = [] + for l in target.link_targets: + # Xcode does not recognize our private directories, so we have to use its build directories instead. + result.append(os.path.join(self.environment.get_build_dir(), self.get_target_dir(l))) + return result + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: # Check for (currently) unexpected capture arg use cases - if capture: From b1d2282078127df0afed522e97b6c498ff5d80f9 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Thu, 17 Aug 2023 10:12:42 -0500 Subject: [PATCH 483/855] xcode: Filter out targets not built by default --- mesonbuild/backend/xcodebackend.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 3bfadd7e7878..4e0fa6b4bb6d 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -564,9 +564,13 @@ def generate_source_phase_map(self) -> None: def generate_pbx_aggregate_target(self, objects_dict): self.custom_aggregate_targets = {} self.build_all_tdep_id = self.gen_id() - # FIXME: filter out targets that are not built by default. - target_dependencies = [self.pbx_dep_map[t] for t in self.build_targets] - custom_target_dependencies = [self.pbx_custom_dep_map[t] for t in self.custom_targets] + target_dependencies = [] + custom_target_dependencies = [] + for tname, t in self.get_build_by_default_targets().items(): + if isinstance(t, build.CustomTarget): + custom_target_dependencies.append(self.pbx_custom_dep_map[t.get_id()]) + elif isinstance(t, build.BuildTarget): + target_dependencies.append(self.pbx_dep_map[t.get_id()]) aggregated_targets = [] aggregated_targets.append((self.all_id, 'ALL_BUILD', self.all_buildconf_id, From c341900d45e67b58de0682156021ddfafc4bf26f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 10 Dec 2023 21:39:04 -0500 Subject: [PATCH 484/855] coredata: add a few more type annotations 89 erros down to 34. Most of them are from getting the `BUILTIN_*` variables correct. --- mesonbuild/coredata.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 20bba09e5402..669e9f7ed953 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -197,7 +197,7 @@ class OctalInt(int): # NinjaBackend.get_user_option_args uses str() to converts it to a command line option # UserUmaskOption.toint() uses int(str, 8) to convert it to an integer # So we need to use oct instead of dec here if we do not want values to be misinterpreted. - def __str__(self): + def __str__(self) -> str: return oct(int(self)) class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]): @@ -653,7 +653,7 @@ def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: st raise MesonException(f'Cannot find specified {ftype} file: {f}') return real - def builtin_options_libdir_cross_fixup(self): + def builtin_options_libdir_cross_fixup(self) -> None: # By default set libdir to "lib" when cross compiling since # getting the "system default" is always wrong on multiarch # platforms as it gets a value like lib/x86_64-linux-gnu. @@ -882,10 +882,12 @@ def is_per_machine_option(optname: OptionKey) -> bool: return optname.lang is not None def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: - return self.options[OptionKey('args', machine=for_machine, lang=lang)].value + # mypy cannot analyze type of OptionKey + return T.cast('T.List[str]', self.options[OptionKey('args', machine=for_machine, lang=lang)].value) def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: - return self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value + # mypy cannot analyze type of OptionKey + return T.cast('T.List[str]', self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value) def update_project_options(self, options: 'MutableKeyedOptionDictType') -> None: for key, value in options.items(): @@ -1165,7 +1167,7 @@ def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: with open(filename, 'w', encoding='utf-8') as f: config.write(f) -def update_cmd_line_file(build_dir: str, options: argparse.Namespace): +def update_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: filename = get_cmd_line_file(build_dir) config = CmdLineFileParser() config.read(filename) @@ -1333,7 +1335,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi # Update `docs/markdown/Builtin-options.md` after changing the options below # Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required. # Please also update completion scripts in $MESONSRC/data/shell-completions/ -BUILTIN_DIR_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([ +BUILTIN_DIR_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')), (OptionKey('datadir'), BuiltinOption(UserStringOption, 'Data file directory', default_datadir())), @@ -1350,7 +1352,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi (OptionKey('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())), ]) -BUILTIN_CORE_OPTIONS: 'MutableKeyedOptionDictType' = OrderedDict([ +BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist, readonly=True)), @@ -1401,7 +1403,7 @@ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffi BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) -BUILTIN_OPTIONS_PER_MACHINE: 'MutableKeyedOptionDictType' = OrderedDict([ +BUILTIN_OPTIONS_PER_MACHINE: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])), (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])), ]) From 78e23e48f20067fb0c29106658fca8444ff92093 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 10 Dec 2023 21:48:54 -0500 Subject: [PATCH 485/855] backends: correct nonebackend return annotation and check in run_mypy The only backend that can return values in generate() is ninja, so this was useless cruft. --- mesonbuild/backend/nonebackend.py | 4 +--- mesonbuild/backend/xcodebackend.py | 2 +- run_mypy.py | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/nonebackend.py b/mesonbuild/backend/nonebackend.py index 35ec9582e593..a79f1b0df611 100644 --- a/mesonbuild/backend/nonebackend.py +++ b/mesonbuild/backend/nonebackend.py @@ -14,8 +14,6 @@ from __future__ import annotations -import typing as T - from .backends import Backend from .. import mlog from ..mesonlib import MesonBugException @@ -25,7 +23,7 @@ class NoneBackend(Backend): name = 'none' - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect the none backend to generate with \'capture = True\'') diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 4e0fa6b4bb6d..bd20e3af9d39 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -262,7 +262,7 @@ def determine_swift_dep_dirs(self, target): result.append(os.path.join(self.environment.get_build_dir(), self.get_target_dir(l))) return result - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'') diff --git a/run_mypy.py b/run_mypy.py index 25dc1d568faa..067080b9ad32 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -26,6 +26,7 @@ # specific files 'mesonbuild/arglist.py', 'mesonbuild/backend/backends.py', + 'mesonbuild/backend/nonebackend.py', # 'mesonbuild/coredata.py', 'mesonbuild/depfile.py', 'mesonbuild/envconfig.py', From d8a6bf9352ebc0be84be4337ee1cecfa840ab1f0 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 10 Dec 2023 23:04:10 -0500 Subject: [PATCH 486/855] xcode backend: delete unused code --- mesonbuild/backend/xcodebackend.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index bd20e3af9d39..104527a91953 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -236,12 +236,6 @@ def get_custom_target_output_dir(self, target): os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname - def target_to_build_root(self, target): - if self.get_target_dir(target) == '': - return '' - directories = os.path.normpath(self.get_target_dir(target)).split(os.sep) - return os.sep.join(['..'] * len(directories)) - def object_filename_from_source(self, target, source): # Xcode has the following naming scheme: # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o From ff7a997f484deda3e355e5697eea220d6001814b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 11 Dec 2023 12:49:43 -0500 Subject: [PATCH 487/855] xcode backend: make the type of get_target_dir align with parent class mypy will complain if backends.Backend has a lru_cache wrapped method, but it is overridden in XCodeBackend with a method that isn't cached. This is almost certainly a sign that we should be caching it here too anyway. The generic backend cache was added years ago via an intimidating commit f39d2cc3bfa1dd4983cbe5adfb6c6e87dd09d684 which claims that it reduced call time from 60s to 0.000435s and that this was specifically due to getting a coredata option every single time. This is probably workload dependent, but getting an option is *not* nearly as cheap as a throwaway function call. --- mesonbuild/backend/xcodebackend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 104527a91953..7d77b4fb08d0 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import annotations -import uuid, os, operator +import functools, uuid, os, operator import typing as T from . import backends @@ -226,6 +226,7 @@ def write_pbxfile(self, top_level_dict, ofilename): def gen_id(self) -> str: return str(uuid.uuid4()).upper().replace('-', '')[:24] + @functools.lru_cache(maxsize=None) def get_target_dir(self, target): dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))) #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) From fbb8030b277970f7edf293b3438f28a7317693b1 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 10 Dec 2023 23:40:38 -0500 Subject: [PATCH 488/855] xcode backend: sundry type annotations Down from 120 to 44 mypy errors. --- mesonbuild/backend/xcodebackend.py | 76 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 7d77b4fb08d0..3f1ba00c1fe2 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -67,12 +67,12 @@ class FileTreeEntry: def __init__(self) -> None: - self.subdirs = {} - self.targets = [] + self.subdirs: T.Dict[str, FileTreeEntry] = {} + self.targets: T.List[build.BuildTarget] = [] class PbxArray: def __init__(self) -> None: - self.items = [] + self.items: T.List[PbxArrayItem] = [] def add_item(self, item: T.Union[PbxArrayItem, str], comment: str = '') -> None: if isinstance(item, PbxArrayItem): @@ -127,8 +127,8 @@ class PbxDict: def __init__(self) -> None: # This class is a bit weird, because we want to write PBX dicts in # defined order _and_ we want to write intermediate comments also in order. - self.keys = set() - self.items = [] + self.keys: T.Set[str] = set() + self.items: T.List[T.Union[PbxDictItem, PbxComment]] = [] def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = '') -> None: assert key not in self.keys @@ -136,7 +136,7 @@ def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], commen self.keys.add(key) self.items.append(item) - def has_item(self, key): + def has_item(self, key: str) -> bool: return key in self.keys def add_comment(self, comment: PbxComment) -> None: @@ -216,7 +216,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter # that is used in two targets gets a total of four unique ID numbers. self.fileref_ids = {} - def write_pbxfile(self, top_level_dict, ofilename): + def write_pbxfile(self, top_level_dict, ofilename) -> None: tmpname = ofilename + '.tmp' with open(tmpname, 'w', encoding='utf-8') as ofile: ofile.write('// !$*UTF8*$!\n') @@ -227,17 +227,17 @@ def gen_id(self) -> str: return str(uuid.uuid4()).upper().replace('-', '')[:24] @functools.lru_cache(maxsize=None) - def get_target_dir(self, target): + def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: dirname = os.path.join(target.get_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))) #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname - def get_custom_target_output_dir(self, target): + def get_custom_target_output_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: dirname = target.get_subdir() os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname - def object_filename_from_source(self, target, source): + def object_filename_from_source(self, target: build.BuildTarget, source: mesonlib.FileOrString) -> str: # Xcode has the following naming scheme: # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o project = self.build.project_name @@ -250,7 +250,7 @@ def object_filename_from_source(self, target, source): obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' return obj_path - def determine_swift_dep_dirs(self, target): + def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: result: T.List[str] = [] for l in target.link_targets: # Xcode does not recognize our private directories, so we have to use its build directories instead. @@ -335,7 +335,7 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: self.write_pbxfile(self.top_level_dict, self.proj_file) self.generate_regen_info() - def get_xcodetype(self, fname): + def get_xcodetype(self, fname: str) -> str: extension = fname.split('.')[-1] if extension == 'C': extension = 'cpp' @@ -442,7 +442,7 @@ def generate_generator_target_map(self) -> None: self.gen_single_target_map(genlist, tname, t, generator_id) generator_id += 1 - def gen_single_target_map(self, genlist, tname, t, generator_id): + def gen_single_target_map(self, genlist, tname, t, generator_id) -> None: k = (tname, generator_id) assert k not in self.shell_targets self.shell_targets[k] = self.gen_id() @@ -505,7 +505,7 @@ def generate_target_file_maps(self) -> None: self.generate_target_file_maps_impl(self.build_targets) self.generate_target_file_maps_impl(self.custom_targets) - def generate_target_file_maps_impl(self, targets): + def generate_target_file_maps_impl(self, targets) -> None: for tname, t in targets.items(): for s in t.sources: if isinstance(s, mesonlib.File): @@ -556,7 +556,7 @@ def generate_source_phase_map(self) -> None: for t in self.build_targets: self.source_phase[t] = self.gen_id() - def generate_pbx_aggregate_target(self, objects_dict): + def generate_pbx_aggregate_target(self, objects_dict: PbxDict) -> None: self.custom_aggregate_targets = {} self.build_all_tdep_id = self.gen_id() target_dependencies = [] @@ -624,7 +624,7 @@ def generate_pbx_aggregate_target(self, objects_dict): agt_dict.add_item('productName', f'"{name}"') objects_dict.add_item(t[0], agt_dict, name) - def generate_pbx_build_file(self, objects_dict): + def generate_pbx_build_file(self, objects_dict: PbxDict) -> None: for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): if dep.name == 'appleframeworks': @@ -703,7 +703,7 @@ def generate_pbx_build_file(self, objects_dict): self.create_generator_shellphase(objects_dict, tname, generator_id) generator_id += 1 - def create_generator_shellphase(self, objects_dict, tname, generator_id): + def create_generator_shellphase(self, objects_dict, tname, generator_id) -> None: file_ids = self.generator_buildfile_ids[(tname, generator_id)] ref_ids = self.generator_fileref_ids[(tname, generator_id)] assert len(ref_ids) == len(file_ids) @@ -713,7 +713,7 @@ def create_generator_shellphase(self, objects_dict, tname, generator_id): odict.add_item('isa', 'PBXBuildFile') odict.add_item('fileRef', ref_id) - def generate_pbx_build_style(self, objects_dict): + def generate_pbx_build_style(self, objects_dict: PbxDict) -> None: # FIXME: Xcode 9 and later does not uses PBXBuildStyle and it gets removed. Maybe we can remove this part. for name, idval in self.buildstylemap.items(): styledict = PbxDict() @@ -724,7 +724,7 @@ def generate_pbx_build_style(self, objects_dict): settings_dict.add_item('COPY_PHASE_STRIP', 'NO') styledict.add_item('name', f'"{name}"') - def generate_pbx_container_item_proxy(self, objects_dict): + def generate_pbx_container_item_proxy(self, objects_dict: PbxDict) -> None: for t in self.build_targets: proxy_dict = PbxDict() objects_dict.add_item(self.containerproxy_map[t], proxy_dict, 'PBXContainerItemProxy') @@ -734,7 +734,7 @@ def generate_pbx_container_item_proxy(self, objects_dict): proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t]) proxy_dict.add_item('remoteInfo', '"' + t + '"') - def generate_pbx_file_reference(self, objects_dict): + def generate_pbx_file_reference(self, objects_dict: PbxDict) -> None: for tname, t in self.build_targets.items(): for dep in t.get_external_deps(): if dep.name == 'appleframeworks': @@ -906,7 +906,7 @@ def generate_pbx_file_reference(self, objects_dict): buildfile_dict.add_item('sourceTree', 'SOURCE_ROOT') objects_dict.add_item(self.fileref_ids[buildfile], buildfile_dict) - def generate_pbx_frameworks_buildphase(self, objects_dict): + def generate_pbx_frameworks_buildphase(self, objects_dict: PbxDict) -> None: for t in self.build_targets.values(): bt_dict = PbxDict() objects_dict.add_item(t.buildphasemap['Frameworks'], bt_dict, 'Frameworks') @@ -920,7 +920,7 @@ def generate_pbx_frameworks_buildphase(self, objects_dict): file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks') bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0) - def generate_pbx_group(self, objects_dict): + def generate_pbx_group(self, objects_dict: PbxDict) -> None: groupmap = {} target_src_map = {} for t in self.build_targets: @@ -1049,7 +1049,7 @@ def write_group_target_entry(self, objects_dict, t): source_files_dict.add_item('sourceTree', '""') return group_id - def add_projecttree(self, objects_dict, projecttree_id): + def add_projecttree(self, objects_dict, projecttree_id) -> None: root_dict = PbxDict() objects_dict.add_item(projecttree_id, root_dict, "Root of project tree") root_dict.add_item('isa', 'PBXGroup') @@ -1061,7 +1061,7 @@ def add_projecttree(self, objects_dict, projecttree_id): project_tree = self.generate_project_tree() self.write_tree(objects_dict, project_tree, target_children, '') - def write_tree(self, objects_dict, tree_node, children_array, current_subdir): + def write_tree(self, objects_dict, tree_node, children_array, current_subdir) -> None: for subdir_name, subdir_node in tree_node.subdirs.items(): subdir_dict = PbxDict() subdir_children = PbxArray() @@ -1084,13 +1084,13 @@ def write_tree(self, objects_dict, tree_node, children_array, current_subdir): if i: children_array.add_item(i) - def generate_project_tree(self): + def generate_project_tree(self) -> FileTreeEntry: tree_info = FileTreeEntry() for tname, t in self.build_targets.items(): self.add_target_to_tree(tree_info, t) return tree_info - def add_target_to_tree(self, tree_root, t): + def add_target_to_tree(self, tree_root: FileTreeEntry, t: build.BuildTarget) -> None: current_node = tree_root path_segments = t.subdir.split('/') for s in path_segments: @@ -1101,7 +1101,7 @@ def add_target_to_tree(self, tree_root, t): current_node = current_node.subdirs[s] current_node.targets.append(t) - def generate_pbx_native_target(self, objects_dict): + def generate_pbx_native_target(self, objects_dict: PbxDict) -> None: for tname, idval in self.native_targets.items(): ntarget_dict = PbxDict() t = self.build_targets[tname] @@ -1163,7 +1163,7 @@ def generate_pbx_native_target(self, objects_dict): raise MesonException('Unknown target type for %s' % tname) ntarget_dict.add_item('productType', f'"{typestr}"') - def generate_pbx_project(self, objects_dict): + def generate_pbx_project(self, objects_dict: PbxDict) -> None: project_dict = PbxDict() objects_dict.add_item(self.project_uid, project_dict, 'Project object') project_dict.add_item('isa', 'PBXProject') @@ -1191,13 +1191,13 @@ def generate_pbx_project(self, objects_dict): for t in self.custom_targets: targets_arr.add_item(self.custom_aggregate_targets[t], t) - def generate_pbx_shell_build_phase(self, objects_dict): + def generate_pbx_shell_build_phase(self, objects_dict: PbxDict) -> None: self.generate_test_shell_build_phase(objects_dict) self.generate_regen_shell_build_phase(objects_dict) self.generate_custom_target_shell_build_phases(objects_dict) self.generate_generator_target_shell_build_phases(objects_dict) - def generate_test_shell_build_phase(self, objects_dict): + def generate_test_shell_build_phase(self, objects_dict: PbxDict) -> None: shell_dict = PbxDict() objects_dict.add_item(self.test_command_id, shell_dict, 'ShellScript') shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') @@ -1212,7 +1212,7 @@ def generate_test_shell_build_phase(self, objects_dict): shell_dict.add_item('shellScript', f'"{cmdstr}"') shell_dict.add_item('showEnvVarsInLog', 0) - def generate_regen_shell_build_phase(self, objects_dict): + def generate_regen_shell_build_phase(self, objects_dict: PbxDict) -> None: shell_dict = PbxDict() objects_dict.add_item(self.regen_command_id, shell_dict, 'ShellScript') shell_dict.add_item('isa', 'PBXShellScriptBuildPhase') @@ -1227,7 +1227,7 @@ def generate_regen_shell_build_phase(self, objects_dict): shell_dict.add_item('shellScript', f'"{cmdstr}"') shell_dict.add_item('showEnvVarsInLog', 0) - def generate_custom_target_shell_build_phases(self, objects_dict): + def generate_custom_target_shell_build_phases(self, objects_dict: PbxDict) -> None: # Custom targets are shell build phases in Xcode terminology. for tname, t in self.custom_targets.items(): if not isinstance(t, build.CustomTarget): @@ -1259,7 +1259,7 @@ def generate_custom_target_shell_build_phases(self, objects_dict): custom_dict.add_item('shellScript', f'"cd \'{workdir}\'; {cmdstr}"') custom_dict.add_item('showEnvVarsInLog', 0) - def generate_generator_target_shell_build_phases(self, objects_dict): + def generate_generator_target_shell_build_phases(self, objects_dict: PbxDict) -> None: for tname, t in self.build_targets.items(): generator_id = 0 for genlist in t.generated: @@ -1273,7 +1273,7 @@ def generate_generator_target_shell_build_phases(self, objects_dict): self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict) generator_id += 1 - def generate_single_generator_phase(self, tname, t, genlist, generator_id, objects_dict): + def generate_single_generator_phase(self, tname, t, genlist, generator_id, objects_dict) -> None: # TODO: this should be rewritten to use the meson wrapper, like the other generators do # Currently it doesn't handle a host binary that requires an exe wrapper correctly. generator = genlist.get_generator() @@ -1335,7 +1335,7 @@ def generate_single_generator_phase(self, tname, t, genlist, generator_id, objec gen_dict.add_item('shellScript', cmdstr) gen_dict.add_item('showEnvVarsInLog', 0) - def generate_pbx_sources_build_phase(self, objects_dict): + def generate_pbx_sources_build_phase(self, objects_dict: PbxDict) -> None: for name in self.source_phase: phase_dict = PbxDict() t = self.build_targets[name] @@ -1368,7 +1368,7 @@ def generate_pbx_sources_build_phase(self, objects_dict): raise RuntimeError('Unknown input type: ' + str(gt)) phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0) - def generate_pbx_target_dependency(self, objects_dict): + def generate_pbx_target_dependency(self, objects_dict: PbxDict) -> None: all_dict = PbxDict() objects_dict.add_item(self.build_all_tdep_id, all_dict, 'ALL_BUILD') all_dict.add_item('isa', 'PBXTargetDependency') @@ -1393,7 +1393,7 @@ def generate_pbx_target_dependency(self, objects_dict): if t[3] is not None: t_dict.add_item('targetProxy', t[3], 'PBXContainerItemProxy') - def generate_xc_build_configuration(self, objects_dict): + def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: # First the setup for the toplevel project. for buildtype in self.buildtypes: bt_dict = PbxDict() @@ -1476,7 +1476,7 @@ def determine_internal_dep_link_args(self, target, buildtype): links_dylib = links_dylib or sub_links_dylib return (dep_libs, links_dylib) - def generate_single_build_target(self, objects_dict, target_name, target): + def generate_single_build_target(self, objects_dict, target_name, target) -> None: for buildtype in self.buildtypes: dep_libs = [] links_dylib = False From cc5a95a56ac0e12441361938c7c6b34ea1669621 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Fri, 29 Sep 2023 08:59:34 +1100 Subject: [PATCH 489/855] detect windows linkers for flang in detect_fortran_compiler --- mesonbuild/compilers/detect.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 10bbf5f377c8..6ff99c5556fb 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -779,8 +779,20 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C if 'flang' in out or 'clang' in out: cls = fortran.FlangFortranCompiler - linker = guess_nix_linker(env, - compiler, cls, version, for_machine) + if 'windows' in out or env.machines[for_machine].is_windows(): + # If we're in a MINGW context this actually will use a gnu + # style ld, but for flang on "real" windows we'll use + # either link.exe or lld-link.exe + try: + linker = guess_win_linker( + env, compiler, cls, version, + for_machine, invoked_directly=False + ) + except MesonException: + pass + if linker is None: + linker = guess_nix_linker(env, compiler, cls, + version, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) From c168687439170afdf767f27e032e71b76f4d4f37 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 28 Nov 2023 09:26:54 -0500 Subject: [PATCH 490/855] do not trigger workflows on dev branches --- .github/workflows/cygwin.yml | 4 ++++ .github/workflows/macos.yml | 4 ++++ .github/workflows/msys2.yml | 4 ++++ .github/workflows/nonnative.yml | 2 +- .github/workflows/os_comp.yml | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index 3b1b1851626e..c6f3dc416687 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -6,6 +6,10 @@ concurrency: on: push: + branches: + - master + # Stable branches such as 0.56 or 1.0 + - '[0-9]+.[0-9]+' paths: - "mesonbuild/**" - "test cases/**" diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0e5002a408c9..c195af96d4c4 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -6,6 +6,10 @@ concurrency: on: push: + branches: + - master + # Stable branches such as 0.56 or 1.0 + - '[0-9]+.[0-9]+' paths: - "mesonbuild/**" - "test cases/**" diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 043f5ce2a462..0a949e3af62b 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -6,6 +6,10 @@ concurrency: on: push: + branches: + - master + # Stable branches such as 0.56 or 1.0 + - '[0-9]+.[0-9]+' paths: - "mesonbuild/**" - "test cases/**" diff --git a/.github/workflows/nonnative.yml b/.github/workflows/nonnative.yml index b6066822c84b..1ad9e35bb0e0 100644 --- a/.github/workflows/nonnative.yml +++ b/.github/workflows/nonnative.yml @@ -8,7 +8,7 @@ on: push: branches: - master - # Stable branches such as 0.56 or the eventual 1.0 + # Stable branches such as 0.56 or 1.0 - '[0-9]+.[0-9]+' paths: - "mesonbuild/**" diff --git a/.github/workflows/os_comp.yml b/.github/workflows/os_comp.yml index d12e54ca2c6f..298963db1751 100644 --- a/.github/workflows/os_comp.yml +++ b/.github/workflows/os_comp.yml @@ -8,7 +8,7 @@ on: push: branches: - master - # Stable branches such as 0.56 or the eventual 1.0 + # Stable branches such as 0.56 or 1.0 - '[0-9]+.[0-9]+' paths: - "mesonbuild/**" From f6f46173c48196f99f1daaf21affba0f44aef962 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 Dec 2023 16:53:17 -0800 Subject: [PATCH 491/855] macos: Fix test_pkgconfig_parse_libs() test on arm The unit test infrastructure hardcodes the architecture as x86_64. On macos, the test_pkgconfig_parse_libs() test creates a few libraries for testing using clang. This leads to the test failing on arm based macs, as darwin_get_object_archs() will skip over these libraries, which then leads to the test failing because of using -l instead of referencing the libraries by their full path. I am not at all sure this is the best approach. I am also somewhat confused why nobody else has encountered this? CI apparently just runs on x86_64 macs? CC: @tristan957 --- unittests/internaltests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 66bf4586c175..3dc0fe7e64b9 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -618,7 +618,8 @@ def create_static_lib(name): out = name.with_suffix('.o') with src.open('w', encoding='utf-8') as f: f.write('int meson_foobar (void) { return 0; }') - subprocess.check_call(['clang', '-c', str(src), '-o', str(out)]) + # use of x86_64 is hardcoded in run_tests.py:get_fake_env() + subprocess.check_call(['clang', '-c', str(src), '-o', str(out), '-arch', 'x86_64']) subprocess.check_call(['ar', 'csr', str(name), str(out)]) with tempfile.TemporaryDirectory() as tmpdir: From ebf5757c59d9bceb953dc531c757e07dcf83c081 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 9 Dec 2023 23:13:01 +0100 Subject: [PATCH 492/855] cmake: parse project version This properly sets the project version in projects meson generates from cmake projects. This allows dependency fallbacks to properly check the version constraints in dependency calls when falling back to a cmake subproject. Before this would fail, because the project version was undefined. --- docs/markdown/snippets/cmake-project-version.md | 6 ++++++ mesonbuild/cmake/fileapi.py | 13 +++++++++++++ mesonbuild/cmake/interpreter.py | 7 +++++-- test cases/cmake/27 dependency fallback/meson.build | 2 +- .../subprojects/cmMod/CMakeLists.txt | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 docs/markdown/snippets/cmake-project-version.md diff --git a/docs/markdown/snippets/cmake-project-version.md b/docs/markdown/snippets/cmake-project-version.md new file mode 100644 index 000000000000..0bc120b9febe --- /dev/null +++ b/docs/markdown/snippets/cmake-project-version.md @@ -0,0 +1,6 @@ +## Meson now reads the project version of cmake subprojects + +CMake subprojects configured by meson will now have their project +version set to the project version in their CMakeLists.txt. This +allows version constraints to be properly checked when falling back to +a cmake subproject. diff --git a/mesonbuild/cmake/fileapi.py b/mesonbuild/cmake/fileapi.py index baf499fc0b1b..c82c51fc080e 100644 --- a/mesonbuild/cmake/fileapi.py +++ b/mesonbuild/cmake/fileapi.py @@ -30,8 +30,10 @@ def __init__(self, build_dir: Path): self.reply_dir = self.api_base_dir / 'reply' self.cmake_sources: T.List[CMakeBuildFile] = [] self.cmake_configurations: T.List[CMakeConfiguration] = [] + self.project_version = '' self.kind_resolver_map = { 'codemodel': self._parse_codemodel, + 'cache': self._parse_cache, 'cmakeFiles': self._parse_cmakeFiles, } @@ -41,12 +43,16 @@ def get_cmake_sources(self) -> T.List[CMakeBuildFile]: def get_cmake_configurations(self) -> T.List[CMakeConfiguration]: return self.cmake_configurations + def get_project_version(self) -> str: + return self.project_version + def setup_request(self) -> None: self.request_dir.mkdir(parents=True, exist_ok=True) query = { 'requests': [ {'kind': 'codemodel', 'version': {'major': 2, 'minor': 0}}, + {'kind': 'cache', 'version': {'major': 2, 'minor': 0}}, {'kind': 'cmakeFiles', 'version': {'major': 1, 'minor': 0}}, ] } @@ -279,6 +285,13 @@ def _parse_cmakeFiles(self, data: T.Dict[str, T.Any]) -> None: path = path if path.is_absolute() else src_dir / path self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))] + def _parse_cache(self, data: T.Dict[str, T.Any]) -> None: + assert 'entries' in data + + for e in data['entries']: + if e['name'] == 'CMAKE_PROJECT_VERSION': + self.project_version = e['value'] + def _strip_data(self, data: T.Any) -> T.Any: if isinstance(data, list): for idx, i in enumerate(data): diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 8e9ea187e239..20348b5f6bcf 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -784,6 +784,7 @@ def __init__(self, subdir: Path, install_prefix: Path, env: 'Environment', backe # Analysed data self.project_name = '' + self.project_version = '' self.languages: T.List[str] = [] self.targets: T.List[ConverterTarget] = [] self.custom_targets: T.List[ConverterCustomTarget] = [] @@ -875,6 +876,8 @@ def initialise(self, extra_cmake_options: T.List[str]) -> None: # Load the codemodel configurations self.codemodel_configs = self.fileapi.get_cmake_configurations() + self.project_version = self.fileapi.get_project_version() + def analyse(self) -> None: if self.codemodel_configs is None: raise CMakeException('CMakeInterpreter was not initialized') @@ -949,7 +952,7 @@ def analyse(self) -> None: for tgt in self.targets: tgt.cleanup_dependencies() - mlog.log('CMake project', mlog.bold(self.project_name), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.') + mlog.log('CMake project', mlog.bold(self.project_name), mlog.bold(self.project_version), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.') def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode: if not self.project_name: @@ -1023,7 +1026,7 @@ def assign(var_name: str, value: BaseNode) -> AssignmentNode: # Generate the root code block and the project function call root_cb = CodeBlockNode(token()) - root_cb.lines += [function('project', [self.project_name] + self.languages)] + root_cb.lines += [function('project', [self.project_name] + self.languages, {'version': self.project_version} if self.project_version else None)] # Add the run script for custom commands diff --git a/test cases/cmake/27 dependency fallback/meson.build b/test cases/cmake/27 dependency fallback/meson.build index 871d70c9f8ea..76230bbf6d1e 100644 --- a/test cases/cmake/27 dependency fallback/meson.build +++ b/test cases/cmake/27 dependency fallback/meson.build @@ -1,7 +1,7 @@ project('cmakeSubTest', ['c', 'cpp']) # Fallback to a CMake subproject -sub_dep = dependency('cmModLib++') +sub_dep = dependency('cmModLib++', version: '>=1.2.3') exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep]) test('test1', exe1) diff --git a/test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt index d08e55cdf4ac..f920576e27ea 100644 --- a/test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt +++ b/test cases/cmake/27 dependency fallback/subprojects/cmMod/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(cmMod) +project(cmMod VERSION 1.2.3) set(CMAKE_CXX_STANDARD 14) include_directories(${CMAKE_CURRENT_BINARY_DIR}) From 1f82afe8999e9b30403c57f9ac86ef2fc7ec1267 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Wed, 13 Dec 2023 13:21:31 +0100 Subject: [PATCH 493/855] add the EFL, Enlightenment, libdwarf and ThorVG as users of meson --- docs/markdown/Users.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 6e8897714136..86a50e500eef 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -37,6 +37,8 @@ topic](https://github.com/topics/meson). - [DOSBox Staging](https://github.com/dosbox-staging/dosbox-staging), DOS/x86 emulator - [DPDK](http://dpdk.org/browse/dpdk), Data Plane Development Kit, a set of libraries and drivers for fast packet processing - [DXVK](https://github.com/doitsujin/dxvk), a Vulkan-based Direct3D 11 implementation for Linux using Wine + - [EFL](https://www.enlightenment.org/about-efl), multiplatform set of libraries, used by the Enlightenment windows manager and other projects + - [Enlightenment](https://www.enlightenment.org/), windows manager, compositor and minimal desktop for Linux - [elementary OS](https://github.com/elementary/), Linux desktop oriented distribution - [Emeus](https://github.com/ebassi/emeus), constraint based layout manager for GTK+ - [Entangle](https://entangle-photo.org/), tethered camera control and capture desktop application @@ -86,6 +88,7 @@ topic](https://github.com/topics/meson). - [Le](https://github.com/kirushyk/le), machine learning framework - [libcamera](https://git.linuxtv.org/libcamera.git/), a library to handle complex cameras on Linux, ChromeOS and Android - [Libdrm](https://gitlab.freedesktop.org/mesa/drm), a library for abstracting DRM kernel interfaces + - [libdwarf](https://www.prevanders.net/dwarf.html), a multiplatform DWARF parser library - [libeconf](https://github.com/openSUSE/libeconf), Enhanced config file parsing library, which merges config files placed in several locations into one - [Libepoxy](https://github.com/anholt/libepoxy/), a library for handling OpenGL function pointer management - [libfuse](https://github.com/libfuse/libfuse), the reference implementation of the Linux FUSE (Filesystem in Userspace) interface @@ -158,6 +161,7 @@ format files - [szl](https://github.com/dimkr/szl), a lightweight, embeddable scripting language - [Taisei Project](https://taisei-project.org/), an open-source Touhou Project clone and fangame - [Terminology](https://github.com/billiob/terminology), a terminal emulator based on the Enlightenment Foundation Libraries + - [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 - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code From e991c4d45460c09e5eaee6cb1041edb95d1e990e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Dec 2023 11:38:41 -0800 Subject: [PATCH 494/855] Use SPDX-License-Identifier consistently This replaces all of the Apache blurbs at the start of each file with an `# SPDX-License-Identifier: Apache-2.0` string. It also fixes existing uses to be consistent in capitalization, and to be placed above any copyright notices. This removes nearly 3000 lines of boilerplate from the project (only python files), which no developer cares to look at. SPDX is in common use, particularly in the Linux kernel, and is the recommended format for Meson's own `project(license: )` field --- ci/usercustomize.py | 16 +--------------- docs/genrefman.py | 14 +------------- docs/genrelnotes.py | 15 ++------------- docs/jsonvalidator.py | 2 +- docs/refman/generatorbase.py | 12 +----------- docs/refman/generatorjson.py | 2 +- docs/refman/generatormd.py | 13 +------------ docs/refman/generatorpickle.py | 13 +------------ docs/refman/generatorprint.py | 13 +------------ docs/refman/generatorvim.py | 2 +- docs/refman/jsonschema.py | 2 +- docs/refman/loaderbase.py | 13 +------------ docs/refman/loaderpickle.py | 2 +- docs/refman/loaderyaml.py | 13 +------------ docs/refman/main.py | 13 +------------ docs/refman/model.py | 13 +------------ meson.py | 17 ++--------------- mesonbuild/_pathlib.py | 13 +------------ mesonbuild/_typing.py | 16 ++-------------- mesonbuild/arglist.py | 14 ++------------ mesonbuild/ast/__init__.py | 13 +------------ mesonbuild/ast/interpreter.py | 13 +------------ mesonbuild/ast/introspection.py | 13 +------------ mesonbuild/ast/postprocess.py | 13 +------------ mesonbuild/ast/printer.py | 13 +------------ mesonbuild/ast/visitor.py | 13 +------------ mesonbuild/backend/backends.py | 12 +----------- mesonbuild/backend/ninjabackend.py | 12 +----------- mesonbuild/backend/nonebackend.py | 13 +------------ mesonbuild/backend/vs2010backend.py | 13 +------------ mesonbuild/backend/vs2012backend.py | 12 +----------- mesonbuild/backend/vs2013backend.py | 12 +----------- mesonbuild/backend/vs2015backend.py | 12 +----------- mesonbuild/backend/vs2017backend.py | 12 +----------- mesonbuild/backend/vs2019backend.py | 12 +----------- mesonbuild/backend/vs2022backend.py | 12 +----------- mesonbuild/backend/xcodebackend.py | 12 +----------- mesonbuild/build.py | 13 +------------ mesonbuild/cmake/__init__.py | 13 +------------ mesonbuild/cmake/common.py | 15 +-------------- mesonbuild/cmake/executor.py | 15 +-------------- mesonbuild/cmake/fileapi.py | 12 +----------- mesonbuild/cmake/generator.py | 12 +----------- mesonbuild/cmake/interpreter.py | 13 +------------ mesonbuild/cmake/toolchain.py | 12 +----------- mesonbuild/cmake/traceparser.py | 13 +------------ mesonbuild/cmake/tracetargets.py | 2 +- mesonbuild/compilers/__init__.py | 13 +------------ mesonbuild/compilers/c.py | 12 +----------- mesonbuild/compilers/compilers.py | 12 +----------- mesonbuild/compilers/cpp.py | 12 +----------- mesonbuild/compilers/cs.py | 12 +----------- mesonbuild/compilers/cuda.py | 12 +----------- mesonbuild/compilers/d.py | 12 +----------- mesonbuild/compilers/detect.py | 12 +----------- mesonbuild/compilers/fortran.py | 12 +----------- mesonbuild/compilers/java.py | 12 +----------- mesonbuild/compilers/mixins/arm.py | 12 +----------- mesonbuild/compilers/mixins/ccrx.py | 12 +----------- mesonbuild/compilers/mixins/clang.py | 14 ++------------ mesonbuild/compilers/mixins/clike.py | 12 +----------- mesonbuild/compilers/mixins/compcert.py | 12 +----------- mesonbuild/compilers/mixins/elbrus.py | 16 +++------------- mesonbuild/compilers/mixins/emscripten.py | 14 ++------------ mesonbuild/compilers/mixins/gnu.py | 14 ++------------ mesonbuild/compilers/mixins/intel.py | 14 ++------------ mesonbuild/compilers/mixins/islinker.py | 14 ++------------ mesonbuild/compilers/mixins/metrowerks.py | 12 +----------- mesonbuild/compilers/mixins/pgi.py | 14 ++------------ mesonbuild/compilers/mixins/ti.py | 12 +----------- mesonbuild/compilers/mixins/visualstudio.py | 14 ++------------ mesonbuild/compilers/mixins/xc16.py | 12 +----------- mesonbuild/compilers/objc.py | 12 +----------- mesonbuild/compilers/objcpp.py | 12 +----------- mesonbuild/compilers/rust.py | 12 +----------- mesonbuild/compilers/swift.py | 12 +----------- mesonbuild/compilers/vala.py | 12 +----------- mesonbuild/coredata.py | 11 +---------- mesonbuild/dependencies/__init__.py | 12 +----------- mesonbuild/dependencies/base.py | 13 +------------ mesonbuild/dependencies/boost.py | 12 +----------- mesonbuild/dependencies/cmake.py | 12 +----------- mesonbuild/dependencies/coarrays.py | 12 +----------- mesonbuild/dependencies/configtool.py | 12 +----------- mesonbuild/dependencies/cuda.py | 12 +----------- mesonbuild/dependencies/detect.py | 12 +----------- mesonbuild/dependencies/dev.py | 16 +--------------- mesonbuild/dependencies/dub.py | 12 +----------- mesonbuild/dependencies/factory.py | 14 ++------------ mesonbuild/dependencies/framework.py | 12 +----------- mesonbuild/dependencies/hdf5.py | 13 +------------ mesonbuild/dependencies/misc.py | 13 +------------ mesonbuild/dependencies/mpi.py | 12 +----------- mesonbuild/dependencies/pkgconfig.py | 12 +----------- mesonbuild/dependencies/platform.py | 13 +------------ mesonbuild/dependencies/python.py | 12 +----------- mesonbuild/dependencies/qt.py | 15 ++------------- mesonbuild/dependencies/scalapack.py | 12 +----------- mesonbuild/dependencies/ui.py | 13 +------------ mesonbuild/depfile.py | 11 +---------- mesonbuild/envconfig.py | 12 +----------- mesonbuild/environment.py | 12 +----------- mesonbuild/interpreter/__init__.py | 14 +------------- mesonbuild/interpreter/interpreter.py | 11 +---------- mesonbuild/interpreter/primitives/__init__.py | 2 +- mesonbuild/interpreter/primitives/array.py | 2 +- mesonbuild/interpreter/primitives/dict.py | 2 +- mesonbuild/interpreter/primitives/integer.py | 2 +- mesonbuild/interpreter/primitives/range.py | 2 +- mesonbuild/interpreter/primitives/string.py | 2 +- mesonbuild/interpreterbase/__init__.py | 13 +------------ mesonbuild/interpreterbase/_unholder.py | 12 +----------- mesonbuild/interpreterbase/baseobjects.py | 12 +----------- mesonbuild/interpreterbase/decorators.py | 12 +----------- mesonbuild/interpreterbase/disabler.py | 12 +----------- mesonbuild/interpreterbase/exceptions.py | 13 +------------ mesonbuild/interpreterbase/helpers.py | 12 +----------- mesonbuild/interpreterbase/interpreterbase.py | 13 +------------ mesonbuild/interpreterbase/operator.py | 2 +- mesonbuild/linkers/__init__.py | 14 +------------- mesonbuild/linkers/base.py | 13 +------------ mesonbuild/linkers/detect.py | 13 +------------ mesonbuild/linkers/linkers.py | 12 +----------- mesonbuild/mcompile.py | 12 +----------- mesonbuild/mconf.py | 12 +----------- mesonbuild/mdist.py | 12 +----------- mesonbuild/mesondata.py | 12 +----------- mesonbuild/mesonlib.py | 14 +------------- mesonbuild/mesonmain.py | 12 +----------- mesonbuild/minit.py | 13 +------------ mesonbuild/minstall.py | 12 +----------- mesonbuild/mintro.py | 12 +----------- mesonbuild/mlog.py | 13 +------------ mesonbuild/modules/__init__.py | 13 +------------ mesonbuild/modules/cmake.py | 13 +------------ mesonbuild/modules/cuda.py | 12 +----------- mesonbuild/modules/dlang.py | 13 +------------ mesonbuild/modules/external_project.py | 12 +----------- mesonbuild/modules/fs.py | 13 +------------ mesonbuild/modules/gnome.py | 13 +------------ mesonbuild/modules/hotdoc.py | 12 +----------- mesonbuild/modules/i18n.py | 12 +----------- mesonbuild/modules/icestorm.py | 13 +------------ mesonbuild/modules/java.py | 12 +----------- mesonbuild/modules/keyval.py | 12 +----------- mesonbuild/modules/modtest.py | 13 +------------ mesonbuild/modules/pkgconfig.py | 13 +------------ mesonbuild/modules/python.py | 12 +----------- mesonbuild/modules/python3.py | 12 +----------- mesonbuild/modules/qt.py | 14 ++------------ mesonbuild/modules/qt4.py | 13 +------------ mesonbuild/modules/qt5.py | 13 +------------ mesonbuild/modules/qt6.py | 13 +------------ mesonbuild/modules/rust.py | 12 +----------- mesonbuild/modules/simd.py | 12 +----------- mesonbuild/modules/sourceset.py | 13 +------------ mesonbuild/modules/wayland.py | 13 +------------ mesonbuild/modules/windows.py | 12 +----------- mesonbuild/mparser.py | 12 +----------- mesonbuild/msetup.py | 12 +----------- mesonbuild/mtest.py | 13 +------------ mesonbuild/munstable_coredata.py | 12 +----------- mesonbuild/optinterpreter.py | 12 +----------- mesonbuild/programs.py | 12 +----------- mesonbuild/rewriter.py | 16 +--------------- mesonbuild/scripts/__init__.py | 13 +------------ mesonbuild/scripts/clangformat.py | 12 +----------- mesonbuild/scripts/clangtidy.py | 12 +----------- mesonbuild/scripts/cleantrees.py | 12 +----------- mesonbuild/scripts/copy.py | 4 ++-- mesonbuild/scripts/coverage.py | 12 +----------- mesonbuild/scripts/delwithsuffix.py | 12 +----------- mesonbuild/scripts/depfixer.py | 12 +----------- mesonbuild/scripts/depscan.py | 12 +----------- mesonbuild/scripts/dirchanger.py | 12 +----------- mesonbuild/scripts/env2mfile.py | 12 +----------- mesonbuild/scripts/externalproject.py | 12 +----------- mesonbuild/scripts/gettext.py | 12 +----------- mesonbuild/scripts/gtkdochelper.py | 12 +----------- mesonbuild/scripts/itstool.py | 12 +----------- mesonbuild/scripts/meson_exe.py | 12 +----------- mesonbuild/scripts/msgfmthelper.py | 12 +----------- mesonbuild/scripts/pycompile.py | 13 +------------ mesonbuild/scripts/regen_checker.py | 12 +----------- mesonbuild/scripts/run_tool.py | 12 +----------- mesonbuild/scripts/scanbuild.py | 12 +----------- mesonbuild/scripts/symbolextractor.py | 13 +------------ mesonbuild/scripts/tags.py | 12 +----------- mesonbuild/scripts/uninstall.py | 12 +----------- mesonbuild/scripts/vcstagger.py | 12 +----------- mesonbuild/templates/cpptemplates.py | 12 +----------- mesonbuild/templates/cstemplates.py | 12 +----------- mesonbuild/templates/ctemplates.py | 12 +----------- mesonbuild/templates/cudatemplates.py | 12 +----------- mesonbuild/templates/dlangtemplates.py | 12 +----------- mesonbuild/templates/fortrantemplates.py | 12 +----------- mesonbuild/templates/javatemplates.py | 12 +----------- mesonbuild/templates/mesontemplates.py | 12 +----------- mesonbuild/templates/objcpptemplates.py | 12 +----------- mesonbuild/templates/objctemplates.py | 12 +----------- mesonbuild/templates/rusttemplates.py | 12 +----------- mesonbuild/templates/samplefactory.py | 12 +----------- mesonbuild/templates/sampleimpl.py | 12 +----------- mesonbuild/templates/valatemplates.py | 12 +----------- mesonbuild/utils/core.py | 13 +------------ mesonbuild/utils/platform.py | 15 ++------------- mesonbuild/utils/posix.py | 15 ++------------- mesonbuild/utils/universal.py | 12 +----------- mesonbuild/utils/win32.py | 15 ++------------- mesonbuild/wrap/wrap.py | 12 +----------- mesonbuild/wrap/wraptool.py | 12 +----------- packaging/createmsi.py | 14 +------------- packaging/createpkg.py | 14 +------------- run_cross_test.py | 14 +------------- run_format_tests.py | 14 +------------- run_meson_command_tests.py | 14 +------------- run_project_tests.py | 13 +------------ run_single_test.py | 4 ++-- run_tests.py | 14 +------------- run_unittests.py | 13 +------------ setup.py | 13 +------------ skip_ci.py | 14 +------------- .../152 index customtarget/gen_sources.py | 15 ++------------- test cases/rust/12 bindgen/src/gen_header.py | 4 ++-- tools/ac_converter.py | 14 +------------- tools/boost_names.py | 14 +------------- tools/cmake2meson.py | 14 +------------- tools/copy_files.py | 14 -------------- tools/dircondenser.py | 15 +-------------- tools/regenerate_docs.py | 15 +-------------- tools/run_with_cov.py | 13 +------------ unittests/allplatformstests.py | 13 +------------ unittests/baseplatformtests.py | 13 +------------ unittests/darwintests.py | 13 +------------ unittests/datatests.py | 13 +------------ unittests/failuretests.py | 13 +------------ unittests/internaltests.py | 13 +------------ unittests/linuxcrosstests.py | 13 +------------ unittests/linuxliketests.py | 13 +------------ unittests/machinefiletests.py | 13 +------------ unittests/platformagnostictests.py | 13 +------------ unittests/pythontests.py | 13 +------------ unittests/rewritetests.py | 13 +------------ unittests/subprojectscommandtests.py | 13 +------------ unittests/taptests.py | 13 +------------ unittests/windowstests.py | 17 +++-------------- 246 files changed, 270 insertions(+), 2704 deletions(-) diff --git a/ci/usercustomize.py b/ci/usercustomize.py index 72421ba0d9ab..d72c6ad2d4c3 100644 --- a/ci/usercustomize.py +++ b/ci/usercustomize.py @@ -1,19 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script is used by coverage (see tools/run_with_cov.py) to enable coverage -# reports in python subprocesses - import coverage coverage.process_startup() diff --git a/docs/genrefman.py b/docs/genrefman.py index 2510ec590329..f3a4e3da76ce 100755 --- a/docs/genrefman.py +++ b/docs/genrefman.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Hack to make relative imports to mlog possible from pathlib import Path import sys diff --git a/docs/genrelnotes.py b/docs/genrelnotes.py index bad6597250f7..7cc9dcb1729a 100755 --- a/docs/genrelnotes.py +++ b/docs/genrelnotes.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + ''' Generates release notes for new releases of Meson build system ''' diff --git a/docs/jsonvalidator.py b/docs/jsonvalidator.py index 1b2c6377cc60..46d6167ba27f 100755 --- a/docs/jsonvalidator.py +++ b/docs/jsonvalidator.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team import argparse diff --git a/docs/refman/generatorbase.py b/docs/refman/generatorbase.py index 08ce4920d6f7..054180a1820b 100644 --- a/docs/refman/generatorbase.py +++ b/docs/refman/generatorbase.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from abc import ABCMeta, abstractmethod import typing as T diff --git a/docs/refman/generatorjson.py b/docs/refman/generatorjson.py index a2edc184aa36..4c980737012b 100644 --- a/docs/refman/generatorjson.py +++ b/docs/refman/generatorjson.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team from __future__ import annotations diff --git a/docs/refman/generatormd.py b/docs/refman/generatormd.py index 79029c1d57bf..2c80ab02308e 100644 --- a/docs/refman/generatormd.py +++ b/docs/refman/generatormd.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from .generatorbase import GeneratorBase import re import json diff --git a/docs/refman/generatorpickle.py b/docs/refman/generatorpickle.py index 364a9886dac5..19e416ef9737 100644 --- a/docs/refman/generatorpickle.py +++ b/docs/refman/generatorpickle.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import pickle from pathlib import Path from .generatorbase import GeneratorBase diff --git a/docs/refman/generatorprint.py b/docs/refman/generatorprint.py index d805296030bd..b1ed37558da2 100644 --- a/docs/refman/generatorprint.py +++ b/docs/refman/generatorprint.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from .generatorbase import GeneratorBase from .model import ReferenceManual, Object, Function, DataTypeInfo, Type, ObjectType diff --git a/docs/refman/generatorvim.py b/docs/refman/generatorvim.py index ea725740ffce..9cdb9b27bae7 100644 --- a/docs/refman/generatorvim.py +++ b/docs/refman/generatorvim.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2023 The Meson development team from __future__ import annotations diff --git a/docs/refman/jsonschema.py b/docs/refman/jsonschema.py index 283d3a2d9808..e8ace7891316 100644 --- a/docs/refman/jsonschema.py +++ b/docs/refman/jsonschema.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team import typing as T diff --git a/docs/refman/loaderbase.py b/docs/refman/loaderbase.py index e64134f5520c..39c92bf09ce4 100644 --- a/docs/refman/loaderbase.py +++ b/docs/refman/loaderbase.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from abc import ABCMeta, abstractmethod from pathlib import Path import re diff --git a/docs/refman/loaderpickle.py b/docs/refman/loaderpickle.py index 722fedf05eeb..8e7a25f56a59 100644 --- a/docs/refman/loaderpickle.py +++ b/docs/refman/loaderpickle.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team from pathlib import Path diff --git a/docs/refman/loaderyaml.py b/docs/refman/loaderyaml.py index e7ec57a7e08d..15ba5909dcfd 100644 --- a/docs/refman/loaderyaml.py +++ b/docs/refman/loaderyaml.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from .loaderbase import LoaderBase from .model import ( Type, diff --git a/docs/refman/main.py b/docs/refman/main.py index 9a3d16a610ec..f6cdf49e7898 100644 --- a/docs/refman/main.py +++ b/docs/refman/main.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from pathlib import Path import argparse import typing as T diff --git a/docs/refman/model.py b/docs/refman/model.py index 0c65c5835675..51d4ca24a8dd 100644 --- a/docs/refman/model.py +++ b/docs/refman/model.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from dataclasses import dataclass, field from enum import Enum import typing as T diff --git a/meson.py b/meson.py index 6f3ba2a9ee46..95d6c3a239bf 100755 --- a/meson.py +++ b/meson.py @@ -1,21 +1,8 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team +# Copyright © 2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file is an entry point for all commands, including scripts. Include the -# strict minimum python modules for performance reasons. import sys # Check python version before importing anything else, we might have an older diff --git a/mesonbuild/_pathlib.py b/mesonbuild/_pathlib.py index 561a135db1dd..b0ae2e7f3171 100644 --- a/mesonbuild/_pathlib.py +++ b/mesonbuild/_pathlib.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ''' This module soly exists to work around a pathlib.resolve bug on certain Windows systems: diff --git a/mesonbuild/_typing.py b/mesonbuild/_typing.py index d3cfa39d52a4..05ff2b3da948 100644 --- a/mesonbuild/_typing.py +++ b/mesonbuild/_typing.py @@ -1,18 +1,6 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Copyright © 2020-2021 Intel Corporation - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright © 2020-2023 Intel Corporation """Meson specific typing helpers. diff --git a/mesonbuild/arglist.py b/mesonbuild/arglist.py index f50d54eed822..54d7157e2ccf 100644 --- a/mesonbuild/arglist.py +++ b/mesonbuild/arglist.py @@ -1,17 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team -# Copyright © 2020 Intel Corporation +# Copyright © 2020-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from functools import lru_cache diff --git a/mesonbuild/ast/__init__.py b/mesonbuild/ast/__init__.py index d14620f71228..db4060047f70 100644 --- a/mesonbuild/ast/__init__.py +++ b/mesonbuild/ast/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 382fa41970e0..b6f7f9978467 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from __future__ import annotations diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 7d91a85d581c..9a39314ad56a 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool diff --git a/mesonbuild/ast/postprocess.py b/mesonbuild/ast/postprocess.py index 7d2036ed405d..e9f251345184 100644 --- a/mesonbuild/ast/postprocess.py +++ b/mesonbuild/ast/postprocess.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool from __future__ import annotations diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 155b5fc5e75d..bbaca35d9e1b 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool from __future__ import annotations diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index d05d3ffe519e..2b5cea6748d5 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool from __future__ import annotations diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index f60c884fb2cc..ac8fa9020198 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from collections import OrderedDict diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 77df82297372..b4a312bb2e07 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from collections import OrderedDict diff --git a/mesonbuild/backend/nonebackend.py b/mesonbuild/backend/nonebackend.py index a79f1b0df611..fa3f553f415f 100644 --- a/mesonbuild/backend/nonebackend.py +++ b/mesonbuild/backend/nonebackend.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations from .backends import Backend diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index f102fbe14140..d5e1b3d74285 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import copy import itertools diff --git a/mesonbuild/backend/vs2012backend.py b/mesonbuild/backend/vs2012backend.py index 76e5c40b0824..307964bdd1c2 100644 --- a/mesonbuild/backend/vs2012backend.py +++ b/mesonbuild/backend/vs2012backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/backend/vs2013backend.py b/mesonbuild/backend/vs2013backend.py index 1fbde46ce4db..ae0b68bbef2f 100644 --- a/mesonbuild/backend/vs2013backend.py +++ b/mesonbuild/backend/vs2013backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .vs2010backend import Vs2010Backend diff --git a/mesonbuild/backend/vs2015backend.py b/mesonbuild/backend/vs2015backend.py index 8e4da363149a..4c515cca6f1e 100644 --- a/mesonbuild/backend/vs2015backend.py +++ b/mesonbuild/backend/vs2015backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/backend/vs2017backend.py b/mesonbuild/backend/vs2017backend.py index 375d660e35d4..393544febb60 100644 --- a/mesonbuild/backend/vs2017backend.py +++ b/mesonbuild/backend/vs2017backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/backend/vs2019backend.py b/mesonbuild/backend/vs2019backend.py index f01f7eceb8ca..4d6e226d16ff 100644 --- a/mesonbuild/backend/vs2019backend.py +++ b/mesonbuild/backend/vs2019backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/backend/vs2022backend.py b/mesonbuild/backend/vs2022backend.py index ea715d87d8e8..27e0438c7075 100644 --- a/mesonbuild/backend/vs2022backend.py +++ b/mesonbuild/backend/vs2022backend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 3f1ba00c1fe2..6cb7f3ff0f88 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import functools, uuid, os, operator diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 12e7cb5ef64b..68513bb63614 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations from collections import defaultdict, OrderedDict from dataclasses import dataclass, field, InitVar diff --git a/mesonbuild/cmake/__init__.py b/mesonbuild/cmake/__init__.py index e9d7f2a8b7d4..607df8977cf6 100644 --- a/mesonbuild/cmake/__init__.py +++ b/mesonbuild/cmake/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. diff --git a/mesonbuild/cmake/common.py b/mesonbuild/cmake/common.py index aa0bbbf0b4b0..f117a9f6b562 100644 --- a/mesonbuild/cmake/common.py +++ b/mesonbuild/cmake/common.py @@ -1,19 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This class contains the basic functionality needed to run any interpreter -# or an interpreter-based tool. from __future__ import annotations from ..mesonlib import MesonException, OptionKey diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py index 7958baf0c62b..dd43cc04ac17 100644 --- a/mesonbuild/cmake/executor.py +++ b/mesonbuild/cmake/executor.py @@ -1,19 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This class contains the basic functionality needed to run any interpreter -# or an interpreter-based tool. from __future__ import annotations import subprocess as S diff --git a/mesonbuild/cmake/fileapi.py b/mesonbuild/cmake/fileapi.py index c82c51fc080e..ad371fc8c998 100644 --- a/mesonbuild/cmake/fileapi.py +++ b/mesonbuild/cmake/fileapi.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .common import CMakeException, CMakeBuildFile, CMakeConfiguration diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py index 750e4c28296c..b78860564c34 100644 --- a/mesonbuild/cmake/generator.py +++ b/mesonbuild/cmake/generator.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mesonlib diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 20348b5f6bcf..eb65f25402f8 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from __future__ import annotations diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py index be5bd66fd9bb..1aad0bc3b5bc 100644 --- a/mesonbuild/cmake/toolchain.py +++ b/mesonbuild/cmake/toolchain.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from pathlib import Path diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py index dd0dfb57f90f..69e4131823fa 100644 --- a/mesonbuild/cmake/traceparser.py +++ b/mesonbuild/cmake/traceparser.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from __future__ import annotations diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py index 20c7462d147a..69d88a88cc39 100644 --- a/mesonbuild/cmake/tracetargets.py +++ b/mesonbuild/cmake/tracetargets.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifer: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team from __future__ import annotations diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index c516aab576a5..1d2d34c47fe3 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Public symbols for compilers sub-package when using 'from . import compilers' __all__ = [ 'Compiler', diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 7f9e5844c09a..951ec8e38690 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os.path diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 671e3f9cd1ac..69e9f93867b2 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import abc diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 43a5492f0560..226605390356 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import copy diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index cd99c817580a..15672f709066 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os.path, subprocess diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 09a7d6af0614..0d79947bba27 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import enum diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index d8a72fdf3408..a44ab5db693e 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os.path diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 6ff99c5556fb..9d4852bf1524 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from ..mesonlib import ( diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index e2c0f80bdd33..4b4136e2f609 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index fb81682edb9f..d063554eb8da 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index 3abc0c8175ad..06ca8d416fb9 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the arm family of compilers.""" diff --git a/mesonbuild/compilers/mixins/ccrx.py b/mesonbuild/compilers/mixins/ccrx.py index 71c103338e25..45992bf75f03 100644 --- a/mesonbuild/compilers/mixins/ccrx.py +++ b/mesonbuild/compilers/mixins/ccrx.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the Renesas CC-RX compiler family.""" diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index 6a9c79bc77c5..a57b9a9af9c1 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019-2022 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Abstractions for the LLVM/Clang compiler family.""" diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 3cf79a66141f..b3fc96cec47c 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2023 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/mesonbuild/compilers/mixins/compcert.py b/mesonbuild/compilers/mixins/compcert.py index a40f635fa65a..8b2ee1e7c22d 100644 --- a/mesonbuild/compilers/mixins/compcert.py +++ b/mesonbuild/compilers/mixins/compcert.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the CompCert C compiler family.""" diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py index ad6b7ca05511..b4c3f3511734 100644 --- a/mesonbuild/compilers/mixins/elbrus.py +++ b/mesonbuild/compilers/mixins/elbrus.py @@ -1,16 +1,6 @@ -# Copyright 2019 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2023 Intel Corporation + from __future__ import annotations """Abstractions for the Elbrus family of compilers.""" diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py index fef22b9073ba..d10c49987392 100644 --- a/mesonbuild/compilers/mixins/emscripten.py +++ b/mesonbuild/compilers/mixins/emscripten.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Provides a mixin for shared code between C and C++ Emscripten compilers.""" diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index b62435b1931b..95c6cecb1402 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019-2022 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Provides mixins for GNU compilers and GNU-like compilers.""" diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index 9af05e01cdf9..da0ab21335a9 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Abstractions for the Intel Compiler families. diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py index cfdd746b037f..05a74fab2b10 100644 --- a/mesonbuild/compilers/mixins/islinker.py +++ b/mesonbuild/compilers/mixins/islinker.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Mixins for compilers that *are* linkers. diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py index 8c3eca586b8a..1d72afb45f49 100644 --- a/mesonbuild/compilers/mixins/metrowerks.py +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the Metrowerks/Freescale Embedded C/C++ compiler family.""" diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 7a242839b3e1..9f474f117e9a 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Abstractions for the PGI family of compilers.""" diff --git a/mesonbuild/compilers/mixins/ti.py b/mesonbuild/compilers/mixins/ti.py index ae23c8416bd1..6d15b6bd2684 100644 --- a/mesonbuild/compilers/mixins/ti.py +++ b/mesonbuild/compilers/mixins/ti.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the Texas Instruments compiler family.""" diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 810dddd9d2f3..20af8ceef63c 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. + from __future__ import annotations """Abstractions to simplify compilers that implement an MSVC compatible diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py index 2b3904628417..c1b3dba20c3a 100644 --- a/mesonbuild/compilers/mixins/xc16.py +++ b/mesonbuild/compilers/mixins/xc16.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations specific to the Microchip XC16 C compiler family.""" diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index cb8eb9e1fb88..23008e62cae8 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 2297196f8f53..a5664dab4a01 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 1eac1c064daa..f9929088f8cb 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import subprocess, os.path diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index 68ef99227113..ccead3123669 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import subprocess, os.path diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index c0d006a2eaa6..07f4674123f7 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os.path diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 669e9f7ed953..5f1c2fc0e1c0 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1,15 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2023 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import copy diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index c6dabc50eacc..0bfca97842d2 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from .base import Dependency, InternalDependency, ExternalDependency, NotFoundDependency, MissingCompiler from .base import ( diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 6ab2bef7eac9..0d946b8535b4 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for external dependencies. # Custom logic for several other packages are in separate files. diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 19c629d5beed..a72b3d162f01 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import re diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 46a58c13456b..c76592ba3804 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .base import ExternalDependency, DependencyException, DependencyTypeName diff --git a/mesonbuild/dependencies/coarrays.py b/mesonbuild/dependencies/coarrays.py index 1c59792e646c..7701c06ecf54 100644 --- a/mesonbuild/dependencies/coarrays.py +++ b/mesonbuild/dependencies/coarrays.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import functools diff --git a/mesonbuild/dependencies/configtool.py b/mesonbuild/dependencies/configtool.py index 3c523560115b..679c69f5d9be 100644 --- a/mesonbuild/dependencies/configtool.py +++ b/mesonbuild/dependencies/configtool.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .base import ExternalDependency, DependencyException, DependencyTypeName diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index aaed6b32c9f3..1a7b3caceb4d 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import glob diff --git a/mesonbuild/dependencies/detect.py b/mesonbuild/dependencies/detect.py index 9428d547bb02..faf024de9c31 100644 --- a/mesonbuild/dependencies/detect.py +++ b/mesonbuild/dependencies/detect.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import collections, functools, importlib diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 09f55b705d42..b4732e4d25bc 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -1,20 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file contains the detection logic for external dependencies useful for -# development purposes, such as testing, debugging, etc.. - from __future__ import annotations import glob diff --git a/mesonbuild/dependencies/dub.py b/mesonbuild/dependencies/dub.py index c206ce9e73bf..e4f09d4d36f0 100644 --- a/mesonbuild/dependencies/dub.py +++ b/mesonbuild/dependencies/dub.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .base import ExternalDependency, DependencyException, DependencyTypeName diff --git a/mesonbuild/dependencies/factory.py b/mesonbuild/dependencies/factory.py index d50ce0f6b253..aac09cafa616 100644 --- a/mesonbuild/dependencies/factory.py +++ b/mesonbuild/dependencies/factory.py @@ -1,17 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import functools diff --git a/mesonbuild/dependencies/framework.py b/mesonbuild/dependencies/framework.py index 6c0b1f14fae3..cd53ff71894b 100644 --- a/mesonbuild/dependencies/framework.py +++ b/mesonbuild/dependencies/framework.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .base import DependencyTypeName, ExternalDependency, DependencyException diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index a437e847252d..a00b5988b41a 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for miscellaneous external dependencies. from __future__ import annotations diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index b41f3c2610d7..bec1466e9053 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for miscellaneous external dependencies. from __future__ import annotations diff --git a/mesonbuild/dependencies/mpi.py b/mesonbuild/dependencies/mpi.py index d9a1585e1e12..f9c911c29a2a 100644 --- a/mesonbuild/dependencies/mpi.py +++ b/mesonbuild/dependencies/mpi.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import functools diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index e86206b88c2e..d000018110af 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from pathlib import Path diff --git a/mesonbuild/dependencies/platform.py b/mesonbuild/dependencies/platform.py index 87726b57949f..335faed2cdbb 100644 --- a/mesonbuild/dependencies/platform.py +++ b/mesonbuild/dependencies/platform.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for external dependencies that are # platform-specific (generally speaking). from __future__ import annotations diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 9aea6bda83fb..342d94e72f4d 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import functools, json, os, textwrap diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index 25cf610f094e..a331187ed203 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -1,18 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2017 The Meson development team -# Copyright © 2021 Intel Corporation -# SPDX-license-identifier: Apache-2.0 +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Dependency finders for the Qt framework.""" diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index a8e20f405e92..bfc83b138f42 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from pathlib import Path diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 6de55348bf24..cc17377a649b 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for external dependencies that # are UI-related. from __future__ import annotations diff --git a/mesonbuild/depfile.py b/mesonbuild/depfile.py index d346136edc6f..bd4f06c33470 100644 --- a/mesonbuild/depfile.py +++ b/mesonbuild/depfile.py @@ -1,15 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 Red Hat, Inc. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 07f1229e3065..a717732495e7 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from dataclasses import dataclass diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 2ba20548f481..326a1c9ede52 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import itertools diff --git a/mesonbuild/interpreter/__init__.py b/mesonbuild/interpreter/__init__.py index 016e4dce5ac1..e2ccce479093 100644 --- a/mesonbuild/interpreter/__init__.py +++ b/mesonbuild/interpreter/__init__.py @@ -1,18 +1,6 @@ # SPDX-license-identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright © 2021-2023 Intel Corporation """Meson interpreter.""" diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index e885010b23a1..f2e84a822ee0 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1,15 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mparser diff --git a/mesonbuild/interpreter/primitives/__init__.py b/mesonbuild/interpreter/primitives/__init__.py index aebef414f9fc..80532149e65b 100644 --- a/mesonbuild/interpreter/primitives/__init__.py +++ b/mesonbuild/interpreter/primitives/__init__.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 __all__ = [ 'ArrayHolder', diff --git a/mesonbuild/interpreter/primitives/array.py b/mesonbuild/interpreter/primitives/array.py index eeea112e2cf5..b42ddeaa4303 100644 --- a/mesonbuild/interpreter/primitives/array.py +++ b/mesonbuild/interpreter/primitives/array.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 from __future__ import annotations import typing as T diff --git a/mesonbuild/interpreter/primitives/dict.py b/mesonbuild/interpreter/primitives/dict.py index ac7c99b8a8a3..ab4c15fface5 100644 --- a/mesonbuild/interpreter/primitives/dict.py +++ b/mesonbuild/interpreter/primitives/dict.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 from __future__ import annotations import typing as T diff --git a/mesonbuild/interpreter/primitives/integer.py b/mesonbuild/interpreter/primitives/integer.py index 50def2cb7b19..cdf2355f0c0e 100644 --- a/mesonbuild/interpreter/primitives/integer.py +++ b/mesonbuild/interpreter/primitives/integer.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 from __future__ import annotations from ...interpreterbase import ( diff --git a/mesonbuild/interpreter/primitives/range.py b/mesonbuild/interpreter/primitives/range.py index 5eb5e033e03e..23d5617b8e83 100644 --- a/mesonbuild/interpreter/primitives/range.py +++ b/mesonbuild/interpreter/primitives/range.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 from __future__ import annotations import typing as T diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py index bc98934dc00f..7cb492da7efc 100644 --- a/mesonbuild/interpreter/primitives/string.py +++ b/mesonbuild/interpreter/primitives/string.py @@ -1,5 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# SPDX-license-identifier: Apache-2.0 from __future__ import annotations import re diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py index 8a2e0788ffc5..934375a0ee93 100644 --- a/mesonbuild/interpreterbase/__init__.py +++ b/mesonbuild/interpreterbase/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - __all__ = [ 'InterpreterObject', 'MesonInterpreterObject', diff --git a/mesonbuild/interpreterbase/_unholder.py b/mesonbuild/interpreterbase/_unholder.py index 4f1edc1027f1..c62aafe8e97b 100644 --- a/mesonbuild/interpreterbase/_unholder.py +++ b/mesonbuild/interpreterbase/_unholder.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/interpreterbase/baseobjects.py b/mesonbuild/interpreterbase/baseobjects.py index 38b181e27324..9a119a98a75d 100644 --- a/mesonbuild/interpreterbase/baseobjects.py +++ b/mesonbuild/interpreterbase/baseobjects.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mparser diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py index 17c6c8c8fdf8..6524aa92dd4f 100644 --- a/mesonbuild/interpreterbase/decorators.py +++ b/mesonbuild/interpreterbase/decorators.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mesonlib, mlog diff --git a/mesonbuild/interpreterbase/disabler.py b/mesonbuild/interpreterbase/disabler.py index 182bb625ccc3..bad0d712977a 100644 --- a/mesonbuild/interpreterbase/disabler.py +++ b/mesonbuild/interpreterbase/disabler.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/interpreterbase/exceptions.py b/mesonbuild/interpreterbase/exceptions.py index cdbe0fb3b059..495531e0f6aa 100644 --- a/mesonbuild/interpreterbase/exceptions.py +++ b/mesonbuild/interpreterbase/exceptions.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from ..mesonlib import MesonException class InterpreterException(MesonException): diff --git a/mesonbuild/interpreterbase/helpers.py b/mesonbuild/interpreterbase/helpers.py index 917969b26d47..0ded85b0e604 100644 --- a/mesonbuild/interpreterbase/helpers.py +++ b/mesonbuild/interpreterbase/helpers.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mesonlib, mparser diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 315bdf4031c6..365e2fd4bf16 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool. from __future__ import annotations diff --git a/mesonbuild/interpreterbase/operator.py b/mesonbuild/interpreterbase/operator.py index 5dec8d0a8671..3419c4becb14 100644 --- a/mesonbuild/interpreterbase/operator.py +++ b/mesonbuild/interpreterbase/operator.py @@ -1,4 +1,4 @@ -# SPDX-license-identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 from enum import Enum diff --git a/mesonbuild/linkers/__init__.py b/mesonbuild/linkers/__init__.py index 7c3569400adb..356a43d4cd1f 100644 --- a/mesonbuild/linkers/__init__.py +++ b/mesonbuild/linkers/__init__.py @@ -1,18 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - from .base import ArLikeLinker, RSPFileSyntax from .detect import ( defaults, diff --git a/mesonbuild/linkers/base.py b/mesonbuild/linkers/base.py index a656bb40c0eb..c8efc9d6d82c 100644 --- a/mesonbuild/linkers/base.py +++ b/mesonbuild/linkers/base.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2023 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# https://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Core public classes for linkers. from __future__ import annotations diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index b86405a7673f..918f2e63426b 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations from .. import mlog diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index ec8edba11934..0e181299baa7 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import abc diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 60d71333b08d..9c2f5e1e84ce 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Entrypoint script for backend agnostic compile.""" diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 04f6d5bcbd5b..b9547f0b251d 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import itertools diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index c46670e0c411..67442885a389 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/mesonbuild/mesondata.py b/mesonbuild/mesondata.py index da641fda7593..50a88857172a 100644 --- a/mesonbuild/mesondata.py +++ b/mesonbuild/mesondata.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index be69a1271098..9da2786fa933 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -1,18 +1,6 @@ # SPDX-license-identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright © 2021-2023 Intel Corporation # pylint: skip-file diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 72a7ab945d43..0fbc717f8b28 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations # Work around some pathlib bugs... diff --git a/mesonbuild/minit.py b/mesonbuild/minit.py index 39027fd11497..cb5de231e419 100644 --- a/mesonbuild/minit.py +++ b/mesonbuild/minit.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """Code that creates simple startup projects.""" from __future__ import annotations diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 297afb4e23d5..643adcd9a420 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2014 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from glob import glob diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index a980c7c55e3d..81b15d27e8fb 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """This is a helper script for IDE developers. It allows you to diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index ca07f03f4428..a8b0185371d1 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2014 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """This is (mostly) a standalone module used to write logging information about Meson runs. Some output goes to screen, some to logging dir and some goes to both.""" diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index bbfb5bdbd40f..5580acbb4be7 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the base representation for import('modname') from __future__ import annotations diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index ee4e844d10c0..fe6457511f99 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import re import os, os.path, pathlib diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index 6f809cb34f1b..a5b1f7b83ded 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/dlang.py b/mesonbuild/modules/dlang.py index 6d5359fe3018..ed4ac8c62377 100644 --- a/mesonbuild/modules/dlang.py +++ b/mesonbuild/modules/dlang.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This file contains the detection logic for external dependencies that # are UI-related. from __future__ import annotations diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index 4247ba0cf656..bf482e21749f 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from pathlib import Path diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 5a9533cba141..3657be08c4a6 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations from pathlib import Path, PurePath, PureWindowsPath import hashlib diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index d8367ddbe260..32df2a60e151 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - '''This module provides helper functions for Gnome/GLib related functionality such as gobject-introspection, gresources and gtk-doc''' from __future__ import annotations diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index f11354900dd0..fc8832efcba8 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations '''This module provides helper functions for generating documentation using hotdoc''' diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index e375674d98e3..c2a11dd207e0 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from os import path diff --git a/mesonbuild/modules/icestorm.py b/mesonbuild/modules/icestorm.py index 8c1c6f123d94..18bf0e2022c8 100644 --- a/mesonbuild/modules/icestorm.py +++ b/mesonbuild/modules/icestorm.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import itertools import typing as T diff --git a/mesonbuild/modules/java.py b/mesonbuild/modules/java.py index f6e448454924..56611ade26c6 100644 --- a/mesonbuild/modules/java.py +++ b/mesonbuild/modules/java.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import pathlib diff --git a/mesonbuild/modules/keyval.py b/mesonbuild/modules/keyval.py index 48afe814998a..b5608fe879c0 100644 --- a/mesonbuild/modules/keyval.py +++ b/mesonbuild/modules/keyval.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017, 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/modules/modtest.py b/mesonbuild/modules/modtest.py index 5c2584061196..ebc019d581c6 100644 --- a/mesonbuild/modules/modtest.py +++ b/mesonbuild/modules/modtest.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index fa543fdb5fda..3f9ce7b71e10 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations from collections import defaultdict from dataclasses import dataclass diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index ec95374d38ab..7a2cd2837733 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import copy, json, os, shutil, re diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index bc4d9af3ab90..a5e9cca01dc7 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sysconfig diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index 83dcf31bdfb3..c2a315c7f030 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -1,17 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py index 6bdf1c51db1f..354b4a5cf131 100644 --- a/mesonbuild/modules/qt4.py +++ b/mesonbuild/modules/qt4.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py index d9f0a5ecd13d..11958c981beb 100644 --- a/mesonbuild/modules/qt5.py +++ b/mesonbuild/modules/qt5.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/qt6.py b/mesonbuild/modules/qt6.py index cafc531af894..b23204678420 100644 --- a/mesonbuild/modules/qt6.py +++ b/mesonbuild/modules/qt6.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 8e55ad4f811b..eb15473de1b8 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright © 2020-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import itertools import os diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index b8baf39ef34a..bfdc0c2dfc2d 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py index ae594b5aa197..c11fef699c2f 100644 --- a/mesonbuild/modules/sourceset.py +++ b/mesonbuild/modules/sourceset.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import typing as T diff --git a/mesonbuild/modules/wayland.py b/mesonbuild/modules/wayland.py index 99f71d000979..cab2ff453e23 100644 --- a/mesonbuild/modules/wayland.py +++ b/mesonbuild/modules/wayland.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2022 Mark Bolhuis -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import os import typing as T diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index b7cdeb33f13d..29ae96b08548 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import enum diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 0f63c9e5a47e..eaf238108b27 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from dataclasses import dataclass, field import re diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index f8e242ae2bf2..2c663ec6c8e9 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import argparse, datetime, glob, json, os, platform, shutil, sys, tempfile, time diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index b7d2bc6cf4f9..c0775ef7f583 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # A tool to run tests in many different ways. from __future__ import annotations diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py index ba6ffb3ebe7c..df045a104636 100644 --- a/mesonbuild/munstable_coredata.py +++ b/mesonbuild/munstable_coredata.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 895cada54ae8..e9c201eeca37 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2014 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import re diff --git a/mesonbuild/programs.py b/mesonbuild/programs.py index beb5bc566f74..b73f9e4025df 100644 --- a/mesonbuild/programs.py +++ b/mesonbuild/programs.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Representations and logic for External and Internal Programs.""" diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 88a99e543b89..626551014a08 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -1,20 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This class contains the basic functionality needed to run any interpreter -# or an interpreter-based tool. - # This tool is used to manipulate an existing Meson build definition. # # - add a file to a target diff --git a/mesonbuild/scripts/__init__.py b/mesonbuild/scripts/__init__.py index 72777713aadd..9e63221d3981 100644 --- a/mesonbuild/scripts/__init__.py +++ b/mesonbuild/scripts/__init__.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from pathlib import PurePath def destdir_join(d1: str, d2: str) -> str: diff --git a/mesonbuild/scripts/clangformat.py b/mesonbuild/scripts/clangformat.py index c66df1600ebe..9ce050458986 100644 --- a/mesonbuild/scripts/clangformat.py +++ b/mesonbuild/scripts/clangformat.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import argparse diff --git a/mesonbuild/scripts/clangtidy.py b/mesonbuild/scripts/clangtidy.py index 943bde578ac6..353cdc19c288 100644 --- a/mesonbuild/scripts/clangtidy.py +++ b/mesonbuild/scripts/clangtidy.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import argparse diff --git a/mesonbuild/scripts/cleantrees.py b/mesonbuild/scripts/cleantrees.py index 3512f5658782..a888808efc7b 100644 --- a/mesonbuild/scripts/cleantrees.py +++ b/mesonbuild/scripts/cleantrees.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/copy.py b/mesonbuild/scripts/copy.py index dba13a57ed98..73908638b852 100644 --- a/mesonbuild/scripts/copy.py +++ b/mesonbuild/scripts/copy.py @@ -1,5 +1,5 @@ -# SPDX-License-Identifer: Apache-2.0 -# Copyright © 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021-2023 Intel Corporation from __future__ import annotations """Helper script to copy files at build time. diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 54b00cbc4d92..d89213065ce5 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild import environment, mesonlib diff --git a/mesonbuild/scripts/delwithsuffix.py b/mesonbuild/scripts/delwithsuffix.py index f58b19ce3cac..4719b43189ec 100644 --- a/mesonbuild/scripts/delwithsuffix.py +++ b/mesonbuild/scripts/delwithsuffix.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os, sys diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 10399332cfc9..61b7ffa642f1 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index 3ae14c0b35f1..d5b8a0734c30 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import json diff --git a/mesonbuild/scripts/dirchanger.py b/mesonbuild/scripts/dirchanger.py index 60c4f120ceb6..ba16d90adbdf 100644 --- a/mesonbuild/scripts/dirchanger.py +++ b/mesonbuild/scripts/dirchanger.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations '''CD into dir given as first argument and execute diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index 8811b6cf813d..3fb9b8a9509d 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sys, os, subprocess, shutil diff --git a/mesonbuild/scripts/externalproject.py b/mesonbuild/scripts/externalproject.py index 17c2251c3a45..ce49fbcbf26e 100644 --- a/mesonbuild/scripts/externalproject.py +++ b/mesonbuild/scripts/externalproject.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index 4a6bb9c8360a..94e002da592b 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/gtkdochelper.py b/mesonbuild/scripts/gtkdochelper.py index ded952d55a5b..06844289fc1a 100644 --- a/mesonbuild/scripts/gtkdochelper.py +++ b/mesonbuild/scripts/gtkdochelper.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sys, os diff --git a/mesonbuild/scripts/itstool.py b/mesonbuild/scripts/itstool.py index 16af1c23528b..b7cdecfcb0c7 100644 --- a/mesonbuild/scripts/itstool.py +++ b/mesonbuild/scripts/itstool.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py index da89dd4f1a9b..e928e9c1ee85 100644 --- a/mesonbuild/scripts/meson_exe.py +++ b/mesonbuild/scripts/meson_exe.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/msgfmthelper.py b/mesonbuild/scripts/msgfmthelper.py index 28bcc8b83226..0f6642e2b5ff 100644 --- a/mesonbuild/scripts/msgfmthelper.py +++ b/mesonbuild/scripts/msgfmthelper.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import argparse diff --git a/mesonbuild/scripts/pycompile.py b/mesonbuild/scripts/pycompile.py index b236a1ca322e..619398a3472c 100644 --- a/mesonbuild/scripts/pycompile.py +++ b/mesonbuild/scripts/pycompile.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # ignore all lints for this file, since it is run by python2 as well # type: ignore diff --git a/mesonbuild/scripts/regen_checker.py b/mesonbuild/scripts/regen_checker.py index f3a6f3cad484..e638f50f6e65 100644 --- a/mesonbuild/scripts/regen_checker.py +++ b/mesonbuild/scripts/regen_checker.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sys, os diff --git a/mesonbuild/scripts/run_tool.py b/mesonbuild/scripts/run_tool.py index adf767a81779..a1641e90adb5 100644 --- a/mesonbuild/scripts/run_tool.py +++ b/mesonbuild/scripts/run_tool.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import itertools diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py index be60024da329..d7fbcf4fee33 100644 --- a/mesonbuild/scripts/scanbuild.py +++ b/mesonbuild/scripts/scanbuild.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import subprocess diff --git a/mesonbuild/scripts/symbolextractor.py b/mesonbuild/scripts/symbolextractor.py index 08d839bfdb9f..52b9b80c51ea 100644 --- a/mesonbuild/scripts/symbolextractor.py +++ b/mesonbuild/scripts/symbolextractor.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # This script extracts the symbols of a given shared library # into a file. If the symbols have not changed, the file is not # touched. This information is used to skip link steps if the diff --git a/mesonbuild/scripts/tags.py b/mesonbuild/scripts/tags.py index c85680705d0f..c7acb6f6fa5f 100644 --- a/mesonbuild/scripts/tags.py +++ b/mesonbuild/scripts/tags.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/uninstall.py b/mesonbuild/scripts/uninstall.py index 8548766150a1..bcfeb76bf326 100644 --- a/mesonbuild/scripts/uninstall.py +++ b/mesonbuild/scripts/uninstall.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import os diff --git a/mesonbuild/scripts/vcstagger.py b/mesonbuild/scripts/vcstagger.py index c484ee111859..26c1e81aebcf 100644 --- a/mesonbuild/scripts/vcstagger.py +++ b/mesonbuild/scripts/vcstagger.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sys, os, subprocess, re diff --git a/mesonbuild/templates/cpptemplates.py b/mesonbuild/templates/cpptemplates.py index d3d29d3cbc59..70e4dd42b2a7 100644 --- a/mesonbuild/templates/cpptemplates.py +++ b/mesonbuild/templates/cpptemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileHeaderImpl diff --git a/mesonbuild/templates/cstemplates.py b/mesonbuild/templates/cstemplates.py index d2d5ec9f34b3..4b16b7265ec2 100644 --- a/mesonbuild/templates/cstemplates.py +++ b/mesonbuild/templates/cstemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import ClassImpl diff --git a/mesonbuild/templates/ctemplates.py b/mesonbuild/templates/ctemplates.py index 14eeaf789b7c..d7616054a814 100644 --- a/mesonbuild/templates/ctemplates.py +++ b/mesonbuild/templates/ctemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileHeaderImpl diff --git a/mesonbuild/templates/cudatemplates.py b/mesonbuild/templates/cudatemplates.py index f59d79aeb632..12eefa5a86ef 100644 --- a/mesonbuild/templates/cudatemplates.py +++ b/mesonbuild/templates/cudatemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileHeaderImpl diff --git a/mesonbuild/templates/dlangtemplates.py b/mesonbuild/templates/dlangtemplates.py index 6a8a0710cda5..2e9a32915e59 100644 --- a/mesonbuild/templates/dlangtemplates.py +++ b/mesonbuild/templates/dlangtemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileImpl diff --git a/mesonbuild/templates/fortrantemplates.py b/mesonbuild/templates/fortrantemplates.py index 8895e321e64b..9ac001564c70 100644 --- a/mesonbuild/templates/fortrantemplates.py +++ b/mesonbuild/templates/fortrantemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileImpl diff --git a/mesonbuild/templates/javatemplates.py b/mesonbuild/templates/javatemplates.py index 4163ffd32b0d..e229d7add2fe 100644 --- a/mesonbuild/templates/javatemplates.py +++ b/mesonbuild/templates/javatemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import ClassImpl diff --git a/mesonbuild/templates/mesontemplates.py b/mesonbuild/templates/mesontemplates.py index bc059fa08cc2..db553c09dd75 100644 --- a/mesonbuild/templates/mesontemplates.py +++ b/mesonbuild/templates/mesontemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/templates/objcpptemplates.py b/mesonbuild/templates/objcpptemplates.py index a1021656c9c6..33bff2d79fcf 100644 --- a/mesonbuild/templates/objcpptemplates.py +++ b/mesonbuild/templates/objcpptemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileHeaderImpl diff --git a/mesonbuild/templates/objctemplates.py b/mesonbuild/templates/objctemplates.py index 4e31beb8d26f..8f46d91fd9b2 100644 --- a/mesonbuild/templates/objctemplates.py +++ b/mesonbuild/templates/objctemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileHeaderImpl diff --git a/mesonbuild/templates/rusttemplates.py b/mesonbuild/templates/rusttemplates.py index 26548b837483..5bb7e4c19006 100644 --- a/mesonbuild/templates/rusttemplates.py +++ b/mesonbuild/templates/rusttemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 8e200e200572..0083c614a36d 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import typing as T diff --git a/mesonbuild/templates/sampleimpl.py b/mesonbuild/templates/sampleimpl.py index e34cad7718af..570a370b8e3f 100644 --- a/mesonbuild/templates/sampleimpl.py +++ b/mesonbuild/templates/sampleimpl.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import abc diff --git a/mesonbuild/templates/valatemplates.py b/mesonbuild/templates/valatemplates.py index aa82de73fbd8..1520de0a708f 100644 --- a/mesonbuild/templates/valatemplates.py +++ b/mesonbuild/templates/valatemplates.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from mesonbuild.templates.sampleimpl import FileImpl diff --git a/mesonbuild/utils/core.py b/mesonbuild/utils/core.py index 6e2ec6ac225c..1b005cf95ca7 100644 --- a/mesonbuild/utils/core.py +++ b/mesonbuild/utils/core.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """ Contains the strict minimum to run scripts. diff --git a/mesonbuild/utils/platform.py b/mesonbuild/utils/platform.py index 4a3927ddf733..8e762b63f969 100644 --- a/mesonbuild/utils/platform.py +++ b/mesonbuild/utils/platform.py @@ -1,18 +1,7 @@ -# SPDX-license-identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """base classes providing no-op functionality..""" diff --git a/mesonbuild/utils/posix.py b/mesonbuild/utils/posix.py index cd05d2758652..e8387ba17589 100644 --- a/mesonbuild/utils/posix.py +++ b/mesonbuild/utils/posix.py @@ -1,18 +1,7 @@ -# SPDX-license-identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Posix specific implementations of mesonlib functionality.""" diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 93e64c0a2e05..952d6f7b1588 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. """A library of random helper functionality.""" diff --git a/mesonbuild/utils/win32.py b/mesonbuild/utils/win32.py index 18ee0d04e210..4fcb8ed8327f 100644 --- a/mesonbuild/utils/win32.py +++ b/mesonbuild/utils/win32.py @@ -1,18 +1,7 @@ -# SPDX-license-identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2023 Intel Corporation -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations """Windows specific implementations of mesonlib functionality.""" diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index ea8b4bf61e18..9a310bc414f6 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations from .. import mlog diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index 187bfaa79c6b..5486a26a7782 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -1,16 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations import sys, os diff --git a/packaging/createmsi.py b/packaging/createmsi.py index fef2b38759d0..77667fe68a36 100755 --- a/packaging/createmsi.py +++ b/packaging/createmsi.py @@ -1,18 +1,6 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017-2021 The Meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. ''' This script is for generating MSI packages diff --git a/packaging/createpkg.py b/packaging/createpkg.py index fd022d9e5801..b5a1c9f82537 100755 --- a/packaging/createpkg.py +++ b/packaging/createpkg.py @@ -1,18 +1,6 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017-2021 The Meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import subprocess import shutil, sys, os diff --git a/run_cross_test.py b/run_cross_test.py index bafdbb67d5bb..2394a27ef9a0 100755 --- a/run_cross_test.py +++ b/run_cross_test.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - '''Runs the basic test suite through a cross compiler. This is now just a wrapper around run_project_tests.py with specific arguments diff --git a/run_format_tests.py b/run_format_tests.py index ca3e715f2c28..9be8549dfcfb 100755 --- a/run_format_tests.py +++ b/run_format_tests.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2019 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # some simple checks on the file format of: # - python code # - code samples in tests diff --git a/run_meson_command_tests.py b/run_meson_command_tests.py index 093d6ea9e0bf..d405a5b8790e 100755 --- a/run_meson_command_tests.py +++ b/run_meson_command_tests.py @@ -1,18 +1,6 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import os import tempfile diff --git a/run_project_tests.py b/run_project_tests.py index be3a3329811b..e75b98fbc64e 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. from __future__ import annotations # Work around some pathlib bugs... diff --git a/run_single_test.py b/run_single_test.py index 5cd4f5e9feae..8db9b402d90a 100755 --- a/run_single_test.py +++ b/run_single_test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# SPDX-license-identifier: Apache-2.0 -# Copyright © 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021-2023 Intel Corporation """Script for running a single project test. diff --git a/run_tests.py b/run_tests.py index a959d6ab5833..5347be87befe 100755 --- a/run_tests.py +++ b/run_tests.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Work around some pathlib bugs... from mesonbuild import _pathlib import sys diff --git a/run_unittests.py b/run_unittests.py index 7a2502a6e886..33b0e0988753 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # Work around some pathlib bugs... from mesonbuild import _pathlib import sys diff --git a/setup.py b/setup.py index 7ff28e2a1d6b..305005416c60 100644 --- a/setup.py +++ b/setup.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. import sys diff --git a/skip_ci.py b/skip_ci.py index 4ade979835a6..44408266fe2d 100755 --- a/skip_ci.py +++ b/skip_ci.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - import argparse import os import subprocess diff --git a/test cases/common/152 index customtarget/gen_sources.py b/test cases/common/152 index customtarget/gen_sources.py index 0bdb529cd882..3ea2940366d1 100644 --- a/test cases/common/152 index customtarget/gen_sources.py +++ b/test cases/common/152 index customtarget/gen_sources.py @@ -1,16 +1,5 @@ -# Copyright © 2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2017-2023 Intel Corporation import argparse import textwrap diff --git a/test cases/rust/12 bindgen/src/gen_header.py b/test cases/rust/12 bindgen/src/gen_header.py index 099e4ec74720..07b699b1cd55 100644 --- a/test cases/rust/12 bindgen/src/gen_header.py +++ b/test cases/rust/12 bindgen/src/gen_header.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# SPDX-license-identifer: Apache-2.0 -# Copyright © 2021 Intel Corporation +# SPDX-license-Identifier: Apache-2.0 +# Copyright © 2021-2023 Intel Corporation import argparse import shutil diff --git a/tools/ac_converter.py b/tools/ac_converter.py index f2a559988c4a..319b7e6d8fdf 100755 --- a/tools/ac_converter.py +++ b/tools/ac_converter.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2015 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - help_message = """Usage: {} This script reads config.h.meson, looks for header diff --git a/tools/boost_names.py b/tools/boost_names.py index f27d524e0ce5..3afff163c4d6 100755 --- a/tools/boost_names.py +++ b/tools/boost_names.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2017 Niklas Claesson -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - """This is two implementations for how to get module names from the boost sources. One relies on json metadata files in the sources, the other relies on the folder names. diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py index 7889cd8251ad..f9153d109da1 100755 --- a/tools/cmake2meson.py +++ b/tools/cmake2meson.py @@ -1,19 +1,7 @@ #!/usr/bin/env python3 - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2014 Jussi Pakkanen -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import typing as T from pathlib import Path import sys diff --git a/tools/copy_files.py b/tools/copy_files.py index de251897222b..c13ebcc9ee3d 100644 --- a/tools/copy_files.py +++ b/tools/copy_files.py @@ -1,20 +1,6 @@ #!/usr/bin/env python3 - - # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ''' Copy files ''' diff --git a/tools/dircondenser.py b/tools/dircondenser.py index 1b262f98083b..fcdb1d5dc8d5 100755 --- a/tools/dircondenser.py +++ b/tools/dircondenser.py @@ -1,20 +1,7 @@ #!/usr/bin/env python3 - - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - '''Renames test case directories using Git from this: 1 something diff --git a/tools/regenerate_docs.py b/tools/regenerate_docs.py index 6e4d8f9ad9d0..b7484e7657dc 100755 --- a/tools/regenerate_docs.py +++ b/tools/regenerate_docs.py @@ -1,20 +1,7 @@ #!/usr/bin/env python3 - - +# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ''' Regenerate markdown docs by using `meson.py` from the root dir ''' diff --git a/tools/run_with_cov.py b/tools/run_with_cov.py index 3f78efcb3a45..0d3fba654f9f 100755 --- a/tools/run_with_cov.py +++ b/tools/run_with_cov.py @@ -1,18 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import coverage import os diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 86a6b61c9a8f..c15519874113 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import re import json diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 514f3b759b80..ec3f18908466 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from pathlib import PurePath from unittest import mock, TestCase, SkipTest import json diff --git a/unittests/darwintests.py b/unittests/darwintests.py index 91ccb42b5943..5528bbc9fdc7 100644 --- a/unittests/darwintests.py +++ b/unittests/darwintests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import re import os diff --git a/unittests/datatests.py b/unittests/datatests.py index 70fdcba46846..ae32a949130f 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import re import unittest from itertools import chain diff --git a/unittests/failuretests.py b/unittests/failuretests.py index 2b7c73ea5eb9..baa59204766f 100644 --- a/unittests/failuretests.py +++ b/unittests/failuretests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import tempfile import os diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 3dc0fe7e64b9..945faa18b209 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from configparser import ConfigParser from pathlib import Path from unittest import mock diff --git a/unittests/linuxcrosstests.py b/unittests/linuxcrosstests.py index 28bf41555ed9..a35633cdd79b 100644 --- a/unittests/linuxcrosstests.py +++ b/unittests/linuxcrosstests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import os import shutil import unittest diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index a02c99e8f447..271822962902 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2022 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import stat import subprocess import re diff --git a/unittests/machinefiletests.py b/unittests/machinefiletests.py index d2309f802322..c3802618df20 100644 --- a/unittests/machinefiletests.py +++ b/unittests/machinefiletests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from __future__ import annotations import subprocess diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 31dea0ffe8ec..581ecacccabe 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import json import os import pickle diff --git a/unittests/pythontests.py b/unittests/pythontests.py index afcfec37831b..6079bd587681 100644 --- a/unittests/pythontests.py +++ b/unittests/pythontests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import glob, os, pathlib, shutil, subprocess, unittest from run_tests import ( diff --git a/unittests/rewritetests.py b/unittests/rewritetests.py index 7932fecae26a..af5e204dcb47 100644 --- a/unittests/rewritetests.py +++ b/unittests/rewritetests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess from itertools import zip_longest import json diff --git a/unittests/subprojectscommandtests.py b/unittests/subprojectscommandtests.py index d50828b2954d..85950a08450b 100644 --- a/unittests/subprojectscommandtests.py +++ b/unittests/subprojectscommandtests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import tempfile import textwrap diff --git a/unittests/taptests.py b/unittests/taptests.py index 6c2ccb0ec4df..26d96eafdec4 100644 --- a/unittests/taptests.py +++ b/unittests/taptests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import unittest import io diff --git a/unittests/windowstests.py b/unittests/windowstests.py index be53d65a0d5d..fc56eaa984c6 100644 --- a/unittests/windowstests.py +++ b/unittests/windowstests.py @@ -1,17 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import subprocess import re import os @@ -184,7 +173,7 @@ def test_msvc_cpp17(self): # to the right reason). return self.build() - + @skipIf(is_cygwin(), 'Test only applicable to Windows') def test_genvslite(self): # The test framework itself might be forcing a specific, non-ninja backend across a set of tests, which @@ -225,7 +214,7 @@ def test_genvslite(self): # Wrap the following bulk of setup and msbuild invocation testing in a try-finally because any exception, # failure, or success must always clean up any of the suffixed build dir folders that may have been generated. try: - # Since this + # Since this self.init(testdir, extra_args=['--genvslite', 'vs2022']) # We need to bear in mind that the BasePlatformTests framework creates and cleans up its own temporary # build directory. However, 'genvslite' creates a set of suffixed build directories which we'll have From 9322a29d7f359cbcf378408e0080ea2b030b0d5b Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 15 Dec 2023 18:28:00 +0100 Subject: [PATCH 495/855] Skip pkg-config-dependent tests if it's missing --- unittests/linuxliketests.py | 1 + unittests/machinefiletests.py | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 271822962902..2328107caac8 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -928,6 +928,7 @@ def test_build_rpath_pkgconfig(self): install_rpath = get_rpath(os.path.join(self.installdir, 'usr/bin/progcxx')) self.assertEqual(install_rpath, 'baz:/foo/dummy') + @skipIfNoPkgconfig def test_global_rpath(self): if is_cygwin(): raise SkipTest('Windows PE/COFF binaries do not use RPATH') diff --git a/unittests/machinefiletests.py b/unittests/machinefiletests.py index c3802618df20..22341cb9a000 100644 --- a/unittests/machinefiletests.py +++ b/unittests/machinefiletests.py @@ -215,9 +215,12 @@ def test_python_module(self): # We not have python2, check for it for v in ['2', '2.7', '-2.7']: - rc = subprocess.call(['pkg-config', '--cflags', f'python{v}'], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) + try: + rc = subprocess.call(['pkg-config', '--cflags', f'python{v}'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except FileNotFoundError: + raise SkipTest('Not running Python 2 tests because pkg-config not found.') if rc == 0: break else: From 059b9e048d3b69f3aa62c559e9c0da8c7b943bfd Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Sun, 17 Dec 2023 16:13:23 -0600 Subject: [PATCH 496/855] Update Users.md (#12634) * Update Users.md --- docs/markdown/Users.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 86a50e500eef..7ab211644bcd 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -164,10 +164,15 @@ 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 - - [Trilobite XUnit Test](https://github.com/trilobite-stdlib/trilo-xtest-c), a framework for testing C code - - [Trilobite XType](https://github.com/trilobite-stdlib/trilo-xtype-c), a data type library for C code - - [Trilobite XCore](https://github.com/trilobite-stdlib/trilo-xcore-c), a core essential library for C code - - [Trilobite XData](https://github.com/trilobite-stdlib/trilo-xdata-c), a data structures and algorithms for C code + - [TSCL Xtest](https://github.com/trilobite-stdlib/tscl-xtest-c), a framework for testing C/C++ code + - [TSCL Xmock](https://github.com/trilobite-stdlib/tscl-xtest-c), a framework for mocking C/C++ code + - [TSCL Xmemory](https://github.com/trilobite-stdlib/tscl-xmemory-c), a library for low-level, memory and bitwise operations in C + - [TSCL Xscience](https://github.com/trilobite-stdlib/tscl-xscience-c), a library for scientific calculations in C + - [TSCL Xstring](https://github.com/trilobite-stdlib/tscl-xstring-c), a library for working with strings and ciphers in C + - [TSCL Xdata](https://github.com/trilobite-stdlib/tscl-xdata-c), a library with data structures and algorithms in C + - [TSCL Xutil](https://github.com/trilobite-stdlib/tscl-xutil-c), a library with utilities for the most tedious task in C + - [TSCL Xmath](https://github.com/trilobite-stdlib/tscl-xmath-c), a library with mathematical components for projects in C + - [TSCL Xcore](https://github.com/trilobite-stdlib/tscl-xcore-c), a core framework with essentials for any projects in C - [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 0c3e84bbaf39a4b7f6dfd48faaee7adf61287b36 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 11 Dec 2023 16:58:58 +0100 Subject: [PATCH 497/855] dependencies/llvm: strip default include dirs also for config-tool version This should have been done in my earlier fix, but kinda forgot to test and fix it there as well. See https://github.com/mesonbuild/meson/pull/11733 for the discussion. Fixes: 8284be813 ("dependencies/llvm: strip default include dirs") Signed-off-by: Karol Herbst --- mesonbuild/dependencies/dev.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index b4732e4d25bc..17642878d8a5 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -218,6 +218,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. cargs = mesonlib.OrderedSet(self.get_config_value(['--cppflags'], 'compile_args')) self.compile_args = list(cargs.difference(self.__cpp_blacklist)) + self.compile_args = strip_system_includedirs(environment, self.for_machine, self.compile_args) if version_compare(self.version, '>= 3.9'): self._set_new_link_args(environment) From 67c51820b71d2f3db728b373383cb36daac7bb7a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 13 Jan 2022 10:07:02 -0800 Subject: [PATCH 498/855] compilers: Add partial docstrings for a couple of Compiler methods --- mesonbuild/compilers/compilers.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 69e9f93867b2..cba530fd8222 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2022 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -784,11 +785,23 @@ def get_program_dirs(self, env: 'Environment') -> T.List[str]: return [] def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + """Checks if the compiler has all of the arguments. + + :returns: + A tuple of (bool, bool). The first value is whether the check + succeeded, and the second is whether it was retrieved from a cache + """ raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + """Checks if the linker has all of the arguments. + + :returns: + A tuple of (bool, bool). The first value is whether the check + succeeded, and the second is whether it was retrieved from a cache + """ return self.linker.has_multi_arguments(args, env) def _get_compile_output(self, dirname: str, mode: CompileCheckMode) -> str: @@ -1330,6 +1343,12 @@ def compiles(self, code: 'mesonlib.FileOrString', env: 'Environment', *, dependencies: T.Optional[T.List['Dependency']] = None, mode: CompileCheckMode = CompileCheckMode.COMPILE, disable_cache: bool = False) -> T.Tuple[bool, bool]: + """Run a compilation or link test to see if code can be compiled/linked. + + :returns: + A tuple of (bool, bool). The first value is whether the check + succeeded, and the second is whether it was retrieved from a cache + """ with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: return p.returncode == 0, p.cached From 8db1ca1766033cb18d0749a11c077773d84d3d63 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 13 Jan 2022 09:54:11 -0800 Subject: [PATCH 499/855] interpreter: Don't warn on -fsanitze-* We really only want to warn on `-fsanitize=foo` or `-fsanitize foo`, but not things like `-fsanitize-recover=...` Fixes #9822 Fixes #7192 --- mesonbuild/interpreter/interpreter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f2e84a822ee0..adb99b827bf9 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -2922,7 +2923,8 @@ def _warn_about_builtin_args(self, args: T.List[str]) -> None: elif arg == '-g': mlog.warning(f'Consider using the built-in debug option instead of using "{arg}".', location=self.current_node) - elif arg.startswith('-fsanitize'): + # Don't catch things like `-fsanitize-recover` + elif arg == '-fsanitize' or arg.startswith('-fsanitize='): mlog.warning(f'Consider using the built-in option for sanitizers instead of using "{arg}".', location=self.current_node) elif arg.startswith('-std=') or arg.startswith('/std:'): From 730cce09bd75bfa3b1d702e42a5462a7c7d4f8ba Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 13 Jan 2022 10:35:19 -0800 Subject: [PATCH 500/855] interpreter: Also check for msvc style /fsanitize --- mesonbuild/interpreter/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index adb99b827bf9..b736aea415ce 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2924,7 +2924,7 @@ def _warn_about_builtin_args(self, args: T.List[str]) -> None: mlog.warning(f'Consider using the built-in debug option instead of using "{arg}".', location=self.current_node) # Don't catch things like `-fsanitize-recover` - elif arg == '-fsanitize' or arg.startswith('-fsanitize='): + elif arg in {'-fsanitize', '/fsanitize'} or arg.startswith(('-fsanitize=', '/fsanitize=')): mlog.warning(f'Consider using the built-in option for sanitizers instead of using "{arg}".', location=self.current_node) elif arg.startswith('-std=') or arg.startswith('/std:'): From 191449f60879a622661b96600babaec67477d5bb Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 20 Dec 2023 13:39:44 +0530 Subject: [PATCH 501/855] ci: Don't auto-update brew when installing We're getting errors that we don't care about on the CI like: ``` ==> Pouring node@18--18.19.0.monterey.bottle.tar.gz The formula built, but is not symlinked into /usr/local Error: The `brew link` step did not complete successfully Could not symlink lib/node_modules/npm/docs/content/commands/npm-sbom.md Target /usr/local/lib/node_modules/npm/docs/content/commands/npm-sbom.md already exists. You may want to remove it: rm '/usr/local/lib/node_modules/npm/docs/content/commands/npm-sbom.md' ``` We don't care about node, the only reason it's getting updated is because it's already installed on the image and brew is auto-updating it. So let's disable auto-update. --- .github/workflows/macos.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index c195af96d4c4..adbfcb21c743 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -44,6 +44,7 @@ jobs: LDFLAGS: "-L/usr/local/lib" MESON_CI_JOBNAME: unittests-appleclang MESON_UNIT_TEST_BACKEND: ninja + HOMEBREW_NO_AUTO_UPDATE: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | export SDKROOT="$(xcodebuild -version -sdk macosx Path)" @@ -77,6 +78,7 @@ jobs: name: ${{ matrix.NAME }} env: MESON_CI_JOBNAME: ${{ matrix.NAME }} + HOMEBREW_NO_AUTO_UPDATE: 1 steps: - uses: actions/checkout@v3 @@ -99,6 +101,7 @@ jobs: CPPFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" MESON_ARGS: --unity=${{ matrix.unity }} + HOMEBREW_NO_AUTO_UPDATE: 1 CI: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | @@ -126,6 +129,8 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.x' + - env: + HOMEBREW_NO_AUTO_UPDATE: 1 - run: python -m pip install -e . - run: brew install pkg-config ninja gcc - run: brew tap cartr/qt4 From 8bc8f93436599835bd4434672e038545cce6c164 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 21 Dec 2023 10:21:17 -0800 Subject: [PATCH 502/855] cmake/interperter: Add missing type annotation Which mypy is suddenly complaining about. --- mesonbuild/cmake/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index eb65f25402f8..14e15b8fde90 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -293,7 +293,7 @@ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, su if i not in self.compile_opts: continue - temp = [] + temp: T.List[str] = [] for j in self.compile_opts[i]: m = ConverterTarget.std_regex.match(j) ctgt = output_target_map.generated(Path(j)) From 35d89301a908a42b9fe1284dd616cffabdfc45aa Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 13 Dec 2023 09:01:37 -0500 Subject: [PATCH 503/855] tests: skip symlink creation when not supported --- run_project_tests.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index e75b98fbc64e..ab567d327589 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1574,8 +1574,11 @@ def clear_transitive_files() -> None: pass def setup_symlinks() -> None: - symlink_file1.symlink_to('file1') - symlink_file2.symlink_to('file1') + try: + symlink_file1.symlink_to('file1') + symlink_file2.symlink_to('file1') + except OSError: + print('symlinks are not supported on this system') if __name__ == '__main__': if under_ci and not raw_ci_jobname: From c37cd4fe9a764622cdc2107da9bdcfc47ce229a7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 22 Dec 2023 09:55:36 -0800 Subject: [PATCH 504/855] stop using the interpreter holders for the MachineInfo Anywhere we have that, we also have the Environment object, which is just wrapped by the Interpreter methods anyway. This avoids inderections that are unnecessary. --- mesonbuild/backend/vs2010backend.py | 10 +++++----- mesonbuild/msetup.py | 18 ++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index d5e1b3d74285..c84b2e6f6a6a 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -225,10 +225,10 @@ def generate(self, # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'') - target_machine = self.interpreter.builtin['target_machine'].cpu_family_method(None, None) + target_machine = self.environment.machines.target.cpu_family if target_machine in {'64', 'x86_64'}: # amd64 or x86_64 - target_system = self.interpreter.builtin['target_machine'].system_method(None, None) + target_system = self.environment.machines.target.system if detect_microsoft_gdk(target_system): self.platform = target_system else: @@ -237,7 +237,7 @@ def generate(self, # x86 self.platform = 'Win32' elif target_machine in {'aarch64', 'arm64'}: - target_cpu = self.interpreter.builtin['target_machine'].cpu_method(None, None) + target_cpu = self.environment.machines.target.cpu if target_cpu == 'arm64ec': self.platform = 'arm64ec' else: @@ -247,7 +247,7 @@ def generate(self, else: raise MesonException('Unsupported Visual Studio platform: ' + target_machine) - build_machine = self.interpreter.builtin['build_machine'].cpu_family_method(None, None) + build_machine = self.environment.machines.build.cpu_family if build_machine in {'64', 'x86_64'}: # amd64 or x86_64 self.build_platform = 'x64' @@ -255,7 +255,7 @@ def generate(self, # x86 self.build_platform = 'Win32' elif build_machine in {'aarch64', 'arm64'}: - target_cpu = self.interpreter.builtin['build_machine'].cpu_method(None, None) + target_cpu = self.environment.machines.build.cpu if target_cpu == 'arm64ec': self.build_platform = 'arm64ec' else: diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 2c663ec6c8e9..90227842fb0c 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -196,18 +196,12 @@ def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: T.O # even to write `T.Callable[[*mlog.TV_Loggable], None]` logger_fun = T.cast('T.Callable[[mlog.TV_Loggable, mlog.TV_Loggable], None]', (mlog.log if env.is_cross_build() else mlog.debug)) - build_machine = intr.builtin['build_machine'] - host_machine = intr.builtin['host_machine'] - target_machine = intr.builtin['target_machine'] - assert isinstance(build_machine, interpreter.MachineHolder) - assert isinstance(host_machine, interpreter.MachineHolder) - assert isinstance(target_machine, interpreter.MachineHolder) - logger_fun('Build machine cpu family:', mlog.bold(build_machine.cpu_family_method([], {}))) - logger_fun('Build machine cpu:', mlog.bold(build_machine.cpu_method([], {}))) - mlog.log('Host machine cpu family:', mlog.bold(host_machine.cpu_family_method([], {}))) - mlog.log('Host machine cpu:', mlog.bold(host_machine.cpu_method([], {}))) - logger_fun('Target machine cpu family:', mlog.bold(target_machine.cpu_family_method([], {}))) - logger_fun('Target machine cpu:', mlog.bold(target_machine.cpu_method([], {}))) + logger_fun('Build machine cpu family:', mlog.bold(env.machines.build.cpu_family)) + logger_fun('Build machine cpu:', mlog.bold(env.machines.build.cpu)) + mlog.log('Host machine cpu family:', mlog.bold(env.machines.host.cpu_family)) + mlog.log('Host machine cpu:', mlog.bold(env.machines.host.cpu)) + logger_fun('Target machine cpu family:', mlog.bold(env.machines.target.cpu_family)) + logger_fun('Target machine cpu:', mlog.bold(env.machines.target.cpu)) try: if self.options.profile: fname = os.path.join(self.build_dir, 'meson-logs', 'profile-interpreter.log') From 7cbaa6613a84b0a1e4b37926950bf7879eb4776d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 22 Dec 2023 10:00:13 -0800 Subject: [PATCH 505/855] backend/vs: use the host machine instead of the target machine This could lead to subtle bugs if you happened to be building a project that is some sort of toolchain (compiler, linker, etc) --- mesonbuild/backend/vs2010backend.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c84b2e6f6a6a..30f4991493d2 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -225,27 +225,27 @@ def generate(self, # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'') - target_machine = self.environment.machines.target.cpu_family - if target_machine in {'64', 'x86_64'}: + host_machine = self.environment.machines.host.cpu_family + if host_machine in {'64', 'x86_64'}: # amd64 or x86_64 - target_system = self.environment.machines.target.system + target_system = self.environment.machines.host.system if detect_microsoft_gdk(target_system): self.platform = target_system else: self.platform = 'x64' - elif target_machine == 'x86': + elif host_machine == 'x86': # x86 self.platform = 'Win32' - elif target_machine in {'aarch64', 'arm64'}: - target_cpu = self.environment.machines.target.cpu + elif host_machine in {'aarch64', 'arm64'}: + target_cpu = self.environment.machines.host.cpu if target_cpu == 'arm64ec': self.platform = 'arm64ec' else: self.platform = 'arm64' - elif 'arm' in target_machine.lower(): + elif 'arm' in host_machine.lower(): self.platform = 'ARM' else: - raise MesonException('Unsupported Visual Studio platform: ' + target_machine) + raise MesonException('Unsupported Visual Studio platform: ' + host_machine) build_machine = self.environment.machines.build.cpu_family if build_machine in {'64', 'x86_64'}: From 6ccd708f30e3649f6d531eebb8301132cb0f0759 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 22 Dec 2023 10:05:17 -0800 Subject: [PATCH 506/855] modules: get rid of the .*machine variables They're hardly used, and can be gotten directly from the Environment instead --- mesonbuild/modules/__init__.py | 4 ---- mesonbuild/modules/cuda.py | 2 +- mesonbuild/modules/external_project.py | 8 +++----- mesonbuild/modules/python3.py | 2 +- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 5580acbb4be7..90a7f09b5bde 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -16,7 +16,6 @@ if T.TYPE_CHECKING: from ..interpreter import Interpreter from ..interpreter.interpreter import ProgramVersionFunc - from ..interpreter.interpreterobjects import MachineHolder from ..interpreterbase import TYPE_var, TYPE_kwargs from ..programs import OverrideProgram from ..wrap import WrapMode @@ -52,9 +51,6 @@ def __init__(self, interpreter: 'Interpreter') -> None: self.man = interpreter.build.get_man() self.global_args = interpreter.build.global_args.host self.project_args = interpreter.build.projects_args.host.get(interpreter.subproject, {}) - self.build_machine = T.cast('MachineHolder', interpreter.builtin['build_machine']).held_object - self.host_machine = T.cast('MachineHolder', interpreter.builtin['host_machine']).held_object - self.target_machine = T.cast('MachineHolder', interpreter.builtin['target_machine']).held_object self.current_node = interpreter.current_node def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDirs]], prefix: str = '-I') -> T.List[str]: diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index a5b1f7b83ded..5250108397e6 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -82,7 +82,7 @@ def min_driver_version(self, state: 'ModuleState', driver_version = 'unknown' for d in driver_version_table: if version_compare(cuda_version, d['cuda_version']): - driver_version = d.get(state.host_machine.system, d['linux']) + driver_version = d.get(state.environment.machines.host.system, d['linux']) break return driver_version diff --git a/mesonbuild/modules/external_project.py b/mesonbuild/modules/external_project.py index bf482e21749f..5fdb0214c539 100644 --- a/mesonbuild/modules/external_project.py +++ b/mesonbuild/modules/external_project.py @@ -65,8 +65,6 @@ def __init__(self, self.project_version = state.project_version self.subproject = state.subproject self.env = state.environment - self.build_machine = state.build_machine - self.host_machine = state.host_machine self.configure_command = configure_command self.configure_options = configure_options self.cross_configure_options = cross_configure_options @@ -126,10 +124,10 @@ def _configure(self, state: 'ModuleState') -> None: configure_cmd += self._format_options(self.configure_options, d) if self.env.is_cross_build(): - host = '{}-{}-{}'.format(self.host_machine.cpu, - 'pc' if self.host_machine.cpu_family in {"x86", "x86_64"} + host = '{}-{}-{}'.format(state.environment.machines.host.cpu, + 'pc' if state.environment.machines.host.cpu_family in {"x86", "x86_64"} else 'unknown', - self.host_machine.system) + state.environment.machines.host.system) d = [('HOST', None, host)] configure_cmd += self._format_options(self.cross_configure_options, d) diff --git a/mesonbuild/modules/python3.py b/mesonbuild/modules/python3.py index a5e9cca01dc7..45ad850aa129 100644 --- a/mesonbuild/modules/python3.py +++ b/mesonbuild/modules/python3.py @@ -41,7 +41,7 @@ def __init__(self, *args, **kwargs): @typed_pos_args('python3.extension_module', str, varargs=(str, mesonlib.File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget)) @typed_kwargs('python3.extension_module', *_MOD_KWARGS, allow_unknown=True) def extension_module(self, state: ModuleState, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs: SharedModuleKW): - host_system = state.host_machine.system + host_system = state.environment.machines.host.system if host_system == 'darwin': # Default suffix is 'dylib' but Python does not use it for extensions. suffix = 'so' From 360d81e4aa3eb1230997a7a1c74130bca00fd896 Mon Sep 17 00:00:00 2001 From: Denis Drakhnia Date: Sat, 23 Dec 2023 06:57:11 +0200 Subject: [PATCH 507/855] compilers/elbrus: wrap get_default_include_dirs with lru_cache --- mesonbuild/compilers/mixins/elbrus.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py index b4c3f3511734..27cba803c9fc 100644 --- a/mesonbuild/compilers/mixins/elbrus.py +++ b/mesonbuild/compilers/mixins/elbrus.py @@ -5,6 +5,7 @@ """Abstractions for the Elbrus family of compilers.""" +import functools import os import typing as T import subprocess @@ -59,6 +60,7 @@ def get_program_dirs(self, env: 'Environment') -> T.List[str]: return [os.path.realpath(p) for p in libstr.split(':')] return [] + @functools.lru_cache(maxsize=None) def get_default_include_dirs(self) -> T.List[str]: os_env = os.environ.copy() os_env['LC_ALL'] = 'C' From 4761e4cad946b42daa8723672957e9c1eaeaa5be Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 1 Dec 2023 13:55:09 -0500 Subject: [PATCH 508/855] Remove `get_buildtype_args` function This is a first step to make `buildtype` a true alias of `debug` and `optimization` options. See #10808. Relates to: - #11645 - #12096 - #5920 - #5814 - #8220 - #8493 - #9540 - #10487 - #12265 - #8308 - #8214 - #7194 - #11732 --- mesonbuild/backend/backends.py | 5 -- mesonbuild/backend/ninjabackend.py | 6 +- mesonbuild/backend/vs2010backend.py | 14 ++- mesonbuild/compilers/asm.py | 12 --- mesonbuild/compilers/compilers.py | 95 +-------------------- mesonbuild/compilers/cs.py | 20 ++--- mesonbuild/compilers/cuda.py | 29 ++++--- mesonbuild/compilers/cython.py | 4 - mesonbuild/compilers/d.py | 47 +++++----- mesonbuild/compilers/fortran.py | 7 +- mesonbuild/compilers/java.py | 15 ++-- mesonbuild/compilers/mixins/arm.py | 24 ------ mesonbuild/compilers/mixins/ccrx.py | 12 --- mesonbuild/compilers/mixins/compcert.py | 14 +-- mesonbuild/compilers/mixins/gnu.py | 12 --- mesonbuild/compilers/mixins/intel.py | 28 +++--- mesonbuild/compilers/mixins/islinker.py | 2 +- mesonbuild/compilers/mixins/metrowerks.py | 12 --- mesonbuild/compilers/mixins/pgi.py | 12 --- mesonbuild/compilers/mixins/ti.py | 12 --- mesonbuild/compilers/mixins/visualstudio.py | 3 - mesonbuild/compilers/mixins/xc16.py | 12 --- mesonbuild/compilers/rust.py | 5 +- mesonbuild/compilers/swift.py | 5 +- mesonbuild/compilers/vala.py | 5 -- mesonbuild/linkers/linkers.py | 59 ++++++------- 26 files changed, 108 insertions(+), 363 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index ac8fa9020198..b28289e8693f 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1001,11 +1001,6 @@ def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Com # command-line or default_options inside project(). commands += compiler.get_option_compile_args(copt_proxy) - # Add buildtype args: optimization level, debugging, etc. - buildtype = target.get_option(OptionKey('buildtype')) - assert isinstance(buildtype, str), 'for mypy' - commands += compiler.get_buildtype_args(buildtype) - optimization = target.get_option(OptionKey('optimization')) assert isinstance(optimization, str), 'for mypy' commands += compiler.get_optimization_args(optimization) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b4a312bb2e07..0fa4cc91fc79 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1444,7 +1444,6 @@ def generate_cs_resource_tasks(self, target): return args, deps def generate_cs_target(self, target: build.BuildTarget): - buildtype = target.get_option(OptionKey('buildtype')) fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() @@ -1452,7 +1451,6 @@ def generate_cs_target(self, target: build.BuildTarget): rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] deps = [] commands = compiler.compiler_args(target.extra_args['cs']) - commands += compiler.get_buildtype_args(buildtype) commands += compiler.get_optimization_args(target.get_option(OptionKey('optimization'))) commands += compiler.get_debug_args(target.get_option(OptionKey('debug'))) if isinstance(target, build.Executable): @@ -1495,7 +1493,6 @@ def generate_cs_target(self, target: build.BuildTarget): def determine_single_java_compile_args(self, target, compiler): args = [] - args += compiler.get_buildtype_args(target.get_option(OptionKey('buildtype'))) args += self.build.get_global_args(compiler, target.for_machine) args += self.build.get_project_args(compiler, target.subproject, target.for_machine) args += target.get_java_args() @@ -1726,7 +1723,6 @@ def generate_cython_transpile(self, target: build.BuildTarget) -> \ args: T.List[str] = [] args += cython.get_always_args() - args += cython.get_buildtype_args(target.get_option(OptionKey('buildtype'))) args += cython.get_debug_args(target.get_option(OptionKey('debug'))) args += cython.get_optimization_args(target.get_option(OptionKey('optimization'))) args += cython.get_option_compile_args(target.get_options()) @@ -3358,7 +3354,7 @@ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T. # Add things like /NOLOGO; usually can't be overridden commands += linker.get_linker_always_args() # Add buildtype linker args: optimization level, etc. - commands += linker.get_buildtype_linker_args(target.get_option(OptionKey('buildtype'))) + commands += linker.get_optimization_link_args(target.get_option(OptionKey('optimization'))) # Add /DEBUG and the pdb filename when using MSVC if target.get_option(OptionKey('debug')): commands += self.get_link_debugfile_args(linker, target) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 30f4991493d2..bcae160bf9f0 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1103,9 +1103,8 @@ def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_includ return (target_args, file_args), (target_defines, file_defines), (target_inc_dirs, file_inc_dirs) @staticmethod - def get_build_args(compiler, buildtype: str, optimization_level: str, debug: bool, sanitize: str) -> T.List[str]: - build_args = compiler.get_buildtype_args(buildtype) - build_args += compiler.get_optimization_args(optimization_level) + def get_build_args(compiler, optimization_level: str, debug: bool, sanitize: str) -> T.List[str]: + build_args = compiler.get_optimization_args(optimization_level) build_args += compiler.get_debug_args(debug) build_args += compiler.sanitizer_compile_args(sanitize) @@ -1267,7 +1266,7 @@ def add_non_makefile_vcxproj_elements( file_args ) -> None: compiler = self._get_cl_compiler(target) - buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) + buildtype_link_args = compiler.get_optimization_link_args(self.optimization) # Prefix to use to access the build root from the vcxproj dir down = self.target_to_build_root(target) @@ -1380,10 +1379,7 @@ def add_non_makefile_vcxproj_elements( # Linker options link = ET.SubElement(compiles, 'Link') extra_link_args = compiler.compiler_args() - # FIXME: Can these buildtype linker args be added as tags in the - # vcxproj file (similar to buildtype compiler args) instead of in - # AdditionalOptions? - extra_link_args += compiler.get_buildtype_linker_args(self.buildtype) + extra_link_args += compiler.get_optimization_link_args(self.optimization) # Generate Debug info if self.debug: self.generate_debug_information(link) @@ -1611,7 +1607,7 @@ def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ gen_hdrs += custom_hdrs compiler = self._get_cl_compiler(target) - build_args = Vs2010Backend.get_build_args(compiler, self.buildtype, self.optimization, self.debug, self.sanitize) + build_args = Vs2010Backend.get_build_args(compiler, self.optimization, self.debug, self.sanitize) assert isinstance(target, (build.Executable, build.SharedLibrary, build.StaticLibrary, build.SharedModule)), 'for mypy' # Prefix to use to access the build root from the vcxproj dir diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index 09cf9e11eed0..d04fbd2938fb 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -98,10 +98,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if self.info.cpu_family not in {'x86', 'x86_64'}: raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # FIXME: Not implemented - return [] - def get_pic_args(self) -> T.List[str]: return [] @@ -185,10 +181,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if self.info.cpu_family not in {'x86', 'x86_64'}: raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # FIXME: Not implemented - return [] - def get_pic_args(self) -> T.List[str]: return [] @@ -240,10 +232,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if self.info.cpu_family not in {'arm', 'aarch64'}: raise EnvironmentException(f'ASM compiler {self.id!r} does not support {self.info.cpu_family} CPU family') - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # FIXME: Not implemented - return [] - def get_pic_args(self) -> T.List[str]: return [] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index cba530fd8222..f1a2b7376413 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -181,78 +181,6 @@ class CompileCheckMode(enum.Enum): LINK = 'link' -cuda_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': ['-g', '-G'], - 'debugoptimized': ['-g', '-lineinfo'], - 'release': [], - 'minsize': [], - 'custom': [], -} - -java_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': ['-g'], - 'debugoptimized': ['-g'], - 'release': [], - 'minsize': [], - 'custom': [], -} - -rust_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - -d_gdc_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': ['-finline-functions'], - 'release': ['-finline-functions'], - 'minsize': [], - 'custom': [], -} - -d_ldc_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'], - 'release': ['-enable-inlining', '-Hkeep-all-bodies'], - 'minsize': [], - 'custom': [], -} - -d_dmd_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': ['-inline'], - 'release': ['-inline'], - 'minsize': [], - 'custom': [], -} - -mono_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': ['-optimize+'], - 'release': ['-optimize+'], - 'minsize': [], - 'custom': [], -} - -swift_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] @@ -270,26 +198,12 @@ class CompileCheckMode(enum.Enum): 's': ['-Os'], } -cuda_optimization_args: T.Dict[str, T.List[str]] = { - 'plain': [], - '0': [], - 'g': ['-O0'], - '1': ['-O1'], - '2': ['-O2'], - '3': ['-O3'], - 's': ['-O3'] -} - -cuda_debug_args: T.Dict[bool, T.List[str]] = { - False: [], - True: ['-g'] -} - clike_debug_args: T.Dict[bool, T.List[str]] = { False: [], True: ['-g'] } + MSCRT_VALS = ['none', 'md', 'mdd', 'mt', 'mtd'] base_options: 'KeyedOptionDictType' = { @@ -1070,11 +984,8 @@ def headerpad_args(self) -> T.List[str]: def bitcode_args(self) -> T.List[str]: return self.linker.bitcode_args() - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - raise EnvironmentException(f'{self.id} does not implement get_buildtype_args') - - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: - return self.linker.get_buildtype_args(buildtype) + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: + return self.linker.get_optimization_link_args(optimization_level) def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, suffix: str, soversion: str, diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index 15672f709066..3a6365f42611 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -10,7 +10,7 @@ from ..mesonlib import EnvironmentException from ..linkers import RSPFileSyntax -from .compilers import Compiler, mono_buildtype_args +from .compilers import Compiler from .mixins.islinker import BasicLinkerIsCompilerMixin if T.TYPE_CHECKING: @@ -103,9 +103,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: def needs_static_linker(self) -> bool: return False - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return mono_buildtype_args[buildtype] - def get_debug_args(self, is_debug: bool) -> T.List[str]: return ['-debug'] if is_debug else [] @@ -129,16 +126,11 @@ class VisualStudioCsCompiler(CsCompiler): id = 'csc' - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - res = mono_buildtype_args[buildtype] - if not self.info.is_windows(): - tmp = [] - for flag in res: - if flag == '-debug': - flag = '-debug:portable' - tmp.append(flag) - res = tmp - return res + def get_debug_args(self, is_debug: bool) -> T.List[str]: + if is_debug: + return ['-debug'] if self.info.is_windows() else ['-debug:portable'] + else: + return [] def rsp_file_syntax(self) -> 'RSPFileSyntax': return RSPFileSyntax.MSVC diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 0d79947bba27..969040ad94a6 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -14,8 +14,7 @@ EnvironmentException, Popen_safe, is_windows, LibType, OptionKey, version_compare, ) -from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args, - cuda_debug_args) +from .compilers import Compiler if T.TYPE_CHECKING: from .compilers import CompileCheckMode @@ -29,6 +28,22 @@ from ..programs import ExternalProgram +cuda_optimization_args: T.Dict[str, T.List[str]] = { + 'plain': [], + '0': ['-G'], + 'g': ['-O0'], + '1': ['-O1'], + '2': ['-O2', '-lineinfo'], + '3': ['-O3'], + 's': ['-O3'] +} + +cuda_debug_args: T.Dict[bool, T.List[str]] = { + False: [], + True: ['-g'] +} + + class _Phase(enum.Enum): COMPILER = 'compiler' @@ -692,12 +707,6 @@ def get_werror_args(self) -> T.List[str]: def get_warn_args(self, level: str) -> T.List[str]: return self.warn_args[level] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # nvcc doesn't support msvc's "Edit and Continue" PDB format; "downgrade" to - # a regular PDB to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi') - host_args = ['/Zi' if arg == '/ZI' else arg for arg in self.host_compiler.get_buildtype_args(buildtype)] - return cuda_buildtype_args[buildtype] + self._to_host_flags(host_args) - def get_include_args(self, path: str, is_system: bool) -> T.List[str]: if path == '': path = '.' @@ -712,8 +721,8 @@ def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: def get_depfile_suffix(self) -> str: return 'd' - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: - return self._to_host_flags(self.host_compiler.get_buildtype_linker_args(buildtype), _Phase.LINKER) + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: + return self._to_host_flags(self.host_compiler.get_optimization_link_args(optimization_level), _Phase.LINKER) def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, rpath_paths: T.Tuple[str, ...], build_rpath: str, diff --git a/mesonbuild/compilers/cython.py b/mesonbuild/compilers/cython.py index 9bbfebeb0ef9..a58b3a81421f 100644 --- a/mesonbuild/compilers/cython.py +++ b/mesonbuild/compilers/cython.py @@ -54,10 +54,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: if p.returncode != 0: raise EnvironmentException(f'Cython compiler {self.id!r} cannot compile programs') - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # Cython doesn't implement this, but Meson requires an implementation - return [] - def get_pic_args(self) -> T.List[str]: # We can lie here, it's fine return [] diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index a44ab5db693e..4a4144d45df0 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -18,9 +18,6 @@ from . import compilers from .compilers import ( - d_dmd_buildtype_args, - d_gdc_buildtype_args, - d_ldc_buildtype_args, clike_debug_args, Compiler, CompileCheckMode, @@ -67,8 +64,8 @@ '0': [], 'g': [], '1': ['-O1'], - '2': ['-O2'], - '3': ['-O3'], + '2': ['-O2', '-enable-inlining', '-Hkeep-all-bodies'], + '3': ['-O3', '-enable-inlining', '-Hkeep-all-bodies'], 's': ['-Oz'], } @@ -77,11 +74,21 @@ '0': [], 'g': [], '1': ['-O'], - '2': ['-O'], - '3': ['-O'], + '2': ['-O', '-inline'], + '3': ['-O', '-inline'], 's': ['-O'], } +gdc_optimization_args: T.Dict[str, T.List[str]] = { + 'plain': [], + '0': ['-O0'], + 'g': ['-Og'], + '1': ['-O1'], + '2': ['-O2', '-finline-functions'], + '3': ['-O3', '-finline-functions'], + 's': ['-Os'], +} + class DmdLikeCompilerMixin(CompilerMixinBase): @@ -161,8 +168,8 @@ def get_pic_args(self) -> T.List[str]: return [] return ['-fPIC'] - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: - if buildtype != 'plain': + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: + if optimization_level != 'plain': return self._get_target_arch_args() return [] @@ -531,8 +538,8 @@ def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]: return res - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: - if buildtype != 'plain': + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: + if optimization_level != 'plain': return self._get_target_arch_args() return [] @@ -697,8 +704,8 @@ def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: def get_warn_args(self, level: str) -> T.List[str]: return self.warn_args[level] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return d_gdc_buildtype_args[buildtype] + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + return gdc_optimization_args[optimization_level] def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: @@ -764,11 +771,6 @@ def get_warn_args(self, level: str) -> T.List[str]: return ['-wi'] return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - if buildtype != 'plain': - return self._get_target_arch_args() + d_ldc_buildtype_args[buildtype] - return d_ldc_buildtype_args[buildtype] - def get_pic_args(self) -> T.List[str]: return ['-relocation-model=pic'] @@ -779,6 +781,8 @@ def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: return self._unix_args_to_native(args, self.info, self.linker.id) def get_optimization_args(self, optimization_level: str) -> T.List[str]: + if optimization_level != 'plain': + return self._get_target_arch_args() + ldc_optimization_args[optimization_level] return ldc_optimization_args[optimization_level] @classmethod @@ -824,11 +828,6 @@ def get_colorout_args(self, colortype: str) -> T.List[str]: return ['-color=on'] return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - if buildtype != 'plain': - return self._get_target_arch_args() + d_dmd_buildtype_args[buildtype] - return d_dmd_buildtype_args[buildtype] - def get_std_exe_link_args(self) -> T.List[str]: if self.info.is_windows(): # DMD links against D runtime only when main symbol is found, @@ -870,6 +869,8 @@ def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: return self._unix_args_to_native(args, self.info, self.linker.id) def get_optimization_args(self, optimization_level: str) -> T.List[str]: + if optimization_level != 'plain': + return self._get_target_arch_args() + dmd_optimization_args[optimization_level] return dmd_optimization_args[optimization_level] def can_linker_accept_rsp(self) -> bool: diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 4b4136e2f609..d68c547e1492 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -13,9 +13,7 @@ CompileCheckMode, ) from .mixins.clike import CLikeCompiler -from .mixins.gnu import ( - GnuCompiler, gnulike_buildtype_args, gnu_optimization_args -) +from .mixins.gnu import GnuCompiler, gnu_optimization_args from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler @@ -66,9 +64,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: code = 'program main; print *, "Fortran compilation is working."; end program\n' return self._sanity_check_impl(work_dir, environment, source_name, code) - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return gnulike_buildtype_args[buildtype] - def get_optimization_args(self, optimization_level: str) -> T.List[str]: return gnu_optimization_args[optimization_level] diff --git a/mesonbuild/compilers/java.py b/mesonbuild/compilers/java.py index d063554eb8da..540e2aa78b31 100644 --- a/mesonbuild/compilers/java.py +++ b/mesonbuild/compilers/java.py @@ -11,7 +11,7 @@ import typing as T from ..mesonlib import EnvironmentException -from .compilers import Compiler, java_buildtype_args +from .compilers import Compiler from .mixins.islinker import BasicLinkerIsCompilerMixin if T.TYPE_CHECKING: @@ -19,6 +19,12 @@ from ..environment import Environment from ..mesonlib import MachineChoice + +java_debug_args: T.Dict[bool, T.List[str]] = { + False: ['-g:none'], + True: ['-g'] +} + class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler): language = 'java' @@ -56,9 +62,6 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: def get_pch_name(self, name: str) -> str: return '' - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return java_buildtype_args[buildtype] - def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): @@ -107,6 +110,4 @@ def get_optimization_args(self, optimization_level: str) -> T.List[str]: return [] def get_debug_args(self, is_debug: bool) -> T.List[str]: - if is_debug: - return ['-g'] - return ['-g:none'] + return java_debug_args[is_debug] diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index 06ca8d416fb9..942156fab1a9 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -24,15 +24,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -arm_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - arm_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], @@ -43,15 +34,6 @@ 's': ['-O3'], # Compiler defaults to -Ospace } -armclang_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - armclang_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': [], # Compiler defaults to -O0 @@ -86,9 +68,6 @@ def get_pic_args(self) -> T.List[str]: # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return arm_buildtype_args[buildtype] - # Override CCompiler.get_always_args def get_always_args(self) -> T.List[str]: return [] @@ -162,9 +141,6 @@ def get_pic_args(self) -> T.List[str]: def get_colorout_args(self, colortype: str) -> T.List[str]: return clang_color_args[colortype][:] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return armclang_buildtype_args[buildtype] - def get_pch_suffix(self) -> str: return 'gch' diff --git a/mesonbuild/compilers/mixins/ccrx.py b/mesonbuild/compilers/mixins/ccrx.py index 45992bf75f03..63270726bc4c 100644 --- a/mesonbuild/compilers/mixins/ccrx.py +++ b/mesonbuild/compilers/mixins/ccrx.py @@ -21,15 +21,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -ccrx_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - ccrx_optimization_args: T.Dict[str, T.List[str]] = { '0': ['-optimize=0'], 'g': ['-optimize=0'], @@ -71,9 +62,6 @@ def get_pic_args(self) -> T.List[str]: # if users want to use it, they need to add the required arguments explicitly return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return ccrx_buildtype_args[buildtype] - def get_pch_suffix(self) -> str: return 'pch' diff --git a/mesonbuild/compilers/mixins/compcert.py b/mesonbuild/compilers/mixins/compcert.py index 8b2ee1e7c22d..86d20a0d6c09 100644 --- a/mesonbuild/compilers/mixins/compcert.py +++ b/mesonbuild/compilers/mixins/compcert.py @@ -20,15 +20,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -ccomp_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [''], - 'debug': ['-O0', '-g'], - 'debugoptimized': ['-O0', '-g'], - 'release': ['-O3'], - 'minsize': ['-Os'], - 'custom': ['-Obranchless'], -} - ccomp_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], @@ -41,7 +32,7 @@ ccomp_debug_args: T.Dict[bool, T.List[str]] = { False: [], - True: ['-g'] + True: ['-O0', '-g'] } # As of CompCert 20.04, these arguments should be passed to the underlying gcc linker (via -WUl,) @@ -74,9 +65,6 @@ def get_pic_args(self) -> T.List[str]: # As of now, CompCert does not support PIC return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return ccomp_buildtype_args[buildtype] - def get_pch_suffix(self) -> str: return 'pch' diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 95c6cecb1402..9c0c3f290531 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -37,15 +37,6 @@ True: ['-g'], } -gnulike_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - gnu_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], @@ -390,9 +381,6 @@ def get_pic_args(self) -> T.List[str]: def get_pie_args(self) -> T.List[str]: return ['-fPIE'] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return gnulike_buildtype_args[buildtype] - @abc.abstractmethod def get_optimization_args(self, optimization_level: str) -> T.List[str]: pass diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py index da0ab21335a9..d38a42ebbf52 100644 --- a/mesonbuild/compilers/mixins/intel.py +++ b/mesonbuild/compilers/mixins/intel.py @@ -40,13 +40,9 @@ class IntelGnuLikeCompiler(GnuLikeCompiler): minsize: -O2 """ - BUILD_ARGS: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': ["-g", "-traceback"], - 'debugoptimized': ["-g", "-traceback"], - 'release': [], - 'minsize': [], - 'custom': [], + DEBUG_ARGS: T.Dict[bool, T.List[str]] = { + False: [], + True: ['-g', '-traceback'] } OPTIM_ARGS: T.Dict[str, T.List[str]] = { @@ -105,8 +101,8 @@ def get_profile_generate_args(self) -> T.List[str]: def get_profile_use_args(self) -> T.List[str]: return ['-prof-use'] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return self.BUILD_ARGS[buildtype] + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return self.DEBUG_ARGS[is_debug] def get_optimization_args(self, optimization_level: str) -> T.List[str]: return self.OPTIM_ARGS[optimization_level] @@ -119,13 +115,9 @@ class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): """Abstractions for ICL, the Intel compiler on Windows.""" - BUILD_ARGS: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': ["/Zi", "/traceback"], - 'debugoptimized': ["/Zi", "/traceback"], - 'release': [], - 'minsize': [], - 'custom': [], + DEBUG_ARGS: T.Dict[bool, T.List[str]] = { + False: [], + True: ['/Zi', '/traceback'] } OPTIM_ARGS: T.Dict[str, T.List[str]] = { @@ -165,8 +157,8 @@ def get_toolset_version(self) -> T.Optional[str]: def openmp_flags(self) -> T.List[str]: return ['/Qopenmp'] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return self.BUILD_ARGS[buildtype] + def get_debug_args(self, is_debug: bool) -> T.List[str]: + return self.DEBUG_ARGS[is_debug] def get_optimization_args(self, optimization_level: str) -> T.List[str]: return self.OPTIM_ARGS[optimization_level] diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py index 05a74fab2b10..8d17a94b2d16 100644 --- a/mesonbuild/compilers/mixins/islinker.py +++ b/mesonbuild/compilers/mixins/islinker.py @@ -107,7 +107,7 @@ def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, def get_asneeded_args(self) -> T.List[str]: return [] - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: return [] def get_link_debugfile_name(self, targetfile: str) -> T.Optional[str]: diff --git a/mesonbuild/compilers/mixins/metrowerks.py b/mesonbuild/compilers/mixins/metrowerks.py index 1d72afb45f49..4be27c5dac32 100644 --- a/mesonbuild/compilers/mixins/metrowerks.py +++ b/mesonbuild/compilers/mixins/metrowerks.py @@ -20,15 +20,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -mwcc_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - mwccarm_instruction_set_args: T.Dict[str, T.List[str]] = { 'generic': ['-proc', 'generic'], 'v4': ['-proc', 'v4'], @@ -203,9 +194,6 @@ def depfile_for_object(self, objfile: str) -> T.Optional[str]: def get_always_args(self) -> T.List[str]: return ['-gccinc'] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return mwcc_buildtype_args[buildtype] - def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: return [] diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py index 9f474f117e9a..0d8245a21540 100644 --- a/mesonbuild/compilers/mixins/pgi.py +++ b/mesonbuild/compilers/mixins/pgi.py @@ -22,15 +22,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -pgi_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - class PGICompiler(Compiler): @@ -63,9 +54,6 @@ def get_pic_args(self) -> T.List[str]: def openmp_flags(self) -> T.List[str]: return ['-mp'] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return pgi_buildtype_args[buildtype] - def get_optimization_args(self, optimization_level: str) -> T.List[str]: return clike_optimization_args[optimization_level] diff --git a/mesonbuild/compilers/mixins/ti.py b/mesonbuild/compilers/mixins/ti.py index 6d15b6bd2684..93cc31ee874c 100644 --- a/mesonbuild/compilers/mixins/ti.py +++ b/mesonbuild/compilers/mixins/ti.py @@ -21,15 +21,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -ti_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - ti_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], @@ -70,9 +61,6 @@ def get_pic_args(self) -> T.List[str]: # if users want to use it, they need to add the required arguments explicitly return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return ti_buildtype_args[buildtype] - def get_pch_suffix(self) -> str: return 'pch' diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 20af8ceef63c..5dcebecef8ec 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -178,9 +178,6 @@ def get_output_args(self, outputname: str) -> T.List[str]: return ['/Fe' + outputname] return ['/Fo' + outputname] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return [] - def get_debug_args(self, is_debug: bool) -> T.List[str]: return msvc_debug_args[is_debug] diff --git a/mesonbuild/compilers/mixins/xc16.py b/mesonbuild/compilers/mixins/xc16.py index c1b3dba20c3a..d95674e3e25f 100644 --- a/mesonbuild/compilers/mixins/xc16.py +++ b/mesonbuild/compilers/mixins/xc16.py @@ -21,15 +21,6 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -xc16_buildtype_args: T.Dict[str, T.List[str]] = { - 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], -} - xc16_optimization_args: T.Dict[str, T.List[str]] = { 'plain': [], '0': ['-O0'], @@ -71,9 +62,6 @@ def get_pic_args(self) -> T.List[str]: # if users want to use it, they need to add the required arguments explicitly return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return xc16_buildtype_args[buildtype] - def get_pch_suffix(self) -> str: return 'pch' diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index f9929088f8cb..e10cb4cf3d5f 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -10,7 +10,7 @@ from .. import coredata from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged, OptionKey -from .compilers import Compiler, rust_buildtype_args, clike_debug_args +from .compilers import Compiler, clike_debug_args if T.TYPE_CHECKING: from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType @@ -113,9 +113,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return ['--dep-info', outfile] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return rust_buildtype_args[buildtype] - def get_sysroot(self) -> str: cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot'] p, stdo, stde = Popen_safe_logged(cmd) diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index ccead3123669..e200276e2646 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -8,7 +8,7 @@ from ..mesonlib import EnvironmentException -from .compilers import Compiler, swift_buildtype_args, clike_debug_args +from .compilers import Compiler, clike_debug_args if T.TYPE_CHECKING: from ..envconfig import MachineInfo @@ -64,9 +64,6 @@ def get_header_import_args(self, headername: str) -> T.List[str]: def get_warn_args(self, level: str) -> T.List[str]: return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return swift_buildtype_args[buildtype] - def get_std_exe_link_args(self) -> T.List[str]: return ['-emit-executable'] diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 07f4674123f7..52097c94e973 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -91,11 +91,6 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: msg = f'Vala compiler {self.name_string()!r} cannot compile programs' raise EnvironmentException(msg) - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - if buildtype in {'debug', 'debugoptimized', 'minsize'}: - return ['--debug'] - return [] - def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]: if extra_dirs and isinstance(extra_dirs, str): diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 0e181299baa7..e4db0157fd62 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -45,7 +45,7 @@ def get_exelist(self) -> T.List[str]: def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: return [] - def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: return [] def get_output_args(self, target: str) -> T.List[str]: @@ -103,13 +103,14 @@ class DynamicLinker(metaclass=abc.ABCMeta): """Base class for dynamic linkers.""" - _BUILDTYPE_ARGS: T.Dict[str, T.List[str]] = { + _OPTIMIZATION_ARGS: T.Dict[str, T.List[str]] = { 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': [], - 'minsize': [], - 'custom': [], + '0': [], + 'g': [], + '1': [], + '2': [], + '3': [], + 's': [], } @abc.abstractproperty @@ -189,6 +190,11 @@ def get_debugfile_args(self, targetfile: str) -> T.List[str]: """ return [] + def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: + # We can override these in children by just overriding the + # _OPTIMIZATION_ARGS value. + return mesonlib.listify([self._apply_prefix(a) for a in self._OPTIMIZATION_ARGS[optimization_level]]) + def get_std_shared_lib_args(self) -> T.List[str]: return [] @@ -210,11 +216,6 @@ def get_thinlto_cache_args(self, path: str) -> T.List[str]: def sanitizer_args(self, value: str) -> T.List[str]: return [] - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # We can override these in children by just overriding the - # _BUILDTYPE_ARGS value. - return self._BUILDTYPE_ARGS[buildtype] - def get_asneeded_args(self) -> T.List[str]: return [] @@ -580,13 +581,14 @@ class GnuLikeDynamicLinkerMixin(DynamicLinkerBase): for_machine = MachineChoice.HOST def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... - _BUILDTYPE_ARGS: T.Dict[str, T.List[str]] = { + _OPTIMIZATION_ARGS: T.Dict[str, T.List[str]] = { 'plain': [], - 'debug': [], - 'debugoptimized': [], - 'release': ['-O1'], - 'minsize': [], - 'custom': [], + '0': [], + 'g': [], + '1': [], + '2': [], + '3': ['-O1'], + 's': [], } _SUBSYSTEMS: T.Dict[str, str] = { @@ -601,11 +603,6 @@ def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... "boot_application": "16", } - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - # We can override these in children by just overriding the - # _BUILDTYPE_ARGS value. - return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) - def get_pie_args(self) -> T.List[str]: return ['-pie'] @@ -1231,15 +1228,16 @@ class VisualStudioLikeLinkerMixin(DynamicLinkerBase): for_machine = MachineChoice.HOST def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ... - _BUILDTYPE_ARGS: T.Dict[str, T.List[str]] = { + _OPTIMIZATION_ARGS: T.Dict[str, T.List[str]] = { 'plain': [], - 'debug': [], - 'debugoptimized': [], + '0': [], + 'g': [], + '1': [], + '2': [], # The otherwise implicit REF and ICF linker optimisations are disabled by # /DEBUG. REF implies ICF. - 'release': ['/OPT:REF'], - 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], - 'custom': [], + '3': ['/OPT:REF'], + 's': ['/INCREMENTAL:NO', '/OPT:REF'], } def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, @@ -1250,9 +1248,6 @@ def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, self.machine = machine self.direct = direct - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]]) - def invoked_by_compiler(self) -> bool: return not self.direct From 7d652a6138c69e7af992c4108a9645c2b5c72317 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 23 Dec 2023 23:18:49 -0500 Subject: [PATCH 509/855] project tests: handle code internally fetching the meson command Fixes crash when running the tests and yasm is installed, but nasm is not. When printing the compilers at early startup in run_project_tests.py, we try to detect the nasm compiler, which in this case turns out to be yasm, and its exelist assumes that the meson command is set. Fixes #12662 --- run_project_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_project_tests.py b/run_project_tests.py index ab567d327589..c9d8fec00f48 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1623,6 +1623,7 @@ def setup_symlinks() -> None: clear_transitive_files() setup_symlinks() + mesonlib.set_meson_command(get_meson_script()) print('Meson build system', meson_version, 'Project Tests') print('Using python', sys.version.split('\n')[0], f'({sys.executable!r})') From f1035e0cd0c888bc7aa18fc6e5d92c93e9e96a83 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 23 Dec 2023 23:26:17 -0500 Subject: [PATCH 510/855] run_project_tests: fix assertion that crashes if you have git worktrees git worktrees are frequently a handy tool to use. This glob pattern asserts an error if the same named directory appears more than once, which it will -- once per worktree -- but only because it is globbing the entire project root, even though it should always only exclusively care about files in `test cases/`. So just glob correctly, and then I can run the testsuite locally again. --- run_project_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_project_tests.py b/run_project_tests.py index c9d8fec00f48..4458fce760df 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1550,7 +1550,7 @@ def get_version(t: ToolInfo) -> str: print('{0:<{2}}: {1}'.format(tool.tool, get_version(tool), max_width)) print() -tmpdir = list(Path('.').glob('**/*install functions and follow symlinks')) +tmpdir = list(Path('.').glob('test cases/**/*install functions and follow symlinks')) assert(len(tmpdir) == 1) symlink_test_dir = tmpdir[0] symlink_file1 = symlink_test_dir / 'foo/link1' From 5ff60499453a390465aac2c60dd743d2c6964797 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Tue, 26 Dec 2023 17:05:34 +0200 Subject: [PATCH 511/855] swift: Support swift_args Fixes #12533 --- mesonbuild/backend/ninjabackend.py | 1 + test cases/swift/8 extra args/main.swift | 1 + test cases/swift/8 extra args/meson.build | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 test cases/swift/8 extra args/main.swift create mode 100644 test cases/swift/8 extra args/meson.build diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0fa4cc91fc79..d675882db4ec 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2172,6 +2172,7 @@ def generate_swift_target(self, target): srctreedir = os.path.normpath(os.path.join(self.environment.get_build_dir(), self.build_to_src, expdir)) sargs = swiftc.get_include_args(srctreedir, False) compile_args += sargs + compile_args += target.get_extra_args('swift') link_args = swiftc.get_output_args(os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))) link_args += self.build.get_project_link_args(swiftc, target.subproject, target.for_machine) link_args += self.build.get_global_link_args(swiftc, target.for_machine) diff --git a/test cases/swift/8 extra args/main.swift b/test cases/swift/8 extra args/main.swift new file mode 100644 index 000000000000..1ff8e07c7075 --- /dev/null +++ b/test cases/swift/8 extra args/main.swift @@ -0,0 +1 @@ +print("test") diff --git a/test cases/swift/8 extra args/meson.build b/test cases/swift/8 extra args/meson.build new file mode 100644 index 000000000000..ead2ff509fc2 --- /dev/null +++ b/test cases/swift/8 extra args/meson.build @@ -0,0 +1,18 @@ +project('extra args', 'swift') + +trace_fname = 'trace.json' + +lib = static_library('main', + 'main.swift', + swift_args: [ + '-emit-loaded-module-trace', + '-emit-loaded-module-trace-path', '../' + trace_fname + ], +) + +custom_target('trace_check', + output: trace_fname, + command: ['cat', '@OUTPUT@'], + depends: lib, + build_always: true, +) From 2fbc7b5ce3aced483b196dd10ca9eee1713b7494 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 26 Dec 2023 15:06:12 -0500 Subject: [PATCH 512/855] Revert "clike: Deduplicate rpath linker flags" This reverts commit 53ea59ad8455277797117d225f326851fe7d369c. This breaks at least: - frameworks/17 mpi - frameworks/30 scalapack The problem is that openmpi's pkg-config emitted link arguments includes: ``` -Wl,-rpath -Wl,/path/to/libdir ``` The deduplication logic in meson doesn't contain sufficient information to tell when the compiler is passing an argument that requires values, and definitely cannot tell when that argument is split across argv. But for arguments that *can* do this, it is not possible to deduplicate a single argument as standalone, because it is not standalone. The argument for deduplicating rpath here was that if you have multiple dependencies that all add the same rpath, the Apple ld64 emits a non-fatal warning "duplicate -rpath ignored". Since this is non-fatal, it's not a major issue. A major issue is when builds fatally error out with: ``` FAILED: scalapack_c cc -o scalapack_c scalapack_c.p/main.c.o -Wl,--as-needed -Wl,--no-undefined -Wl,--start-group /usr/lib64/libscalapack.so /usr/lib64/liblapack.so /usr/lib64/libblas.so -Wl,-rpath -Wl,/usr/lib64 -Wl,/usr/lib64 -Wl,--enable-new-dtags /usr/lib64/libmpi.so -Wl,--end-group /usr/libexec/gcc/x86_64-pc-linux-gnu/ld: error: /usr/lib64: read: Is a directory ``` --- 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 b3fc96cec47c..76c8e041341c 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -54,7 +54,7 @@ class CLikeCompilerArgs(arglist.CompilerArgs): # NOTE: not thorough. A list of potential corner cases can be found in # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038 - dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic', '-Wl,-rpath') + dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic') dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a') dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread') From e2458c6f943ad9f3640036a0c48497759edee585 Mon Sep 17 00:00:00 2001 From: wrvsrx Date: Sat, 23 Dec 2023 11:32:32 +0800 Subject: [PATCH 513/855] nvcc compiler: support find dependency header files This commit supersedes PR #11229 and #10993. It also adds version check according to [comments](https://github.com/mesonbuild/meson/pull/11229#issuecomment-1370287546) --- mesonbuild/compilers/cuda.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 969040ad94a6..2ea5d9f245b8 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -744,6 +744,15 @@ def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], def get_output_args(self, target: str) -> T.List[str]: return ['-o', target] + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: + if version_compare(self.version, '>= 10.2'): + # According to nvcc Documentation, `-MD` option is added after 10.2 + # Reference: [CUDA 10.1](https://docs.nvidia.com/cuda/archive/10.1/cuda-compiler-driver-nvcc/index.html#options-for-specifying-compilation-phase-generate-nonsystem-dependencies) + # Reference: [CUDA 10.2](https://docs.nvidia.com/cuda/archive/10.2/cuda-compiler-driver-nvcc/index.html#options-for-specifying-compilation-phase-generate-nonsystem-dependencies) + return ['-MD', '-MT', outtarget, '-MF', outfile] + else: + return [] + def get_std_exe_link_args(self) -> T.List[str]: return self._to_host_flags(self.host_compiler.get_std_exe_link_args(), _Phase.LINKER) From d4fb2d693d01bc65790140a6ebb9221f0f1ed7dc Mon Sep 17 00:00:00 2001 From: wrvsrx Date: Sun, 24 Dec 2023 20:47:13 +0800 Subject: [PATCH 514/855] ninja backend: manually escape cuda target name Nvcc doesn't support `-MQ` flag, so we have to manually escape cuda target name. This commit escape `$out` to `$CUDA_ESCAPED_TARGET`, so now we can just use `-MT` flag in nvcc to generate header dependencies. --- mesonbuild/backend/ninjabackend.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d675882db4ec..9acc39c2a82e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2448,7 +2448,11 @@ def generate_compile_rule_for(self, langname, compiler): # See also: https://github.com/ninja-build/ninja/pull/2275 options['extra'] = 'restat = 1' rule = self.compiler_to_rule_name(compiler) - depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none) + if langname == 'cuda': + # for cuda, we manually escape target name ($out) as $CUDA_ESCAPED_TARGET because nvcc doesn't support `-MQ` flag + depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$CUDA_ESCAPED_TARGET', '$DEPFILE'), Quoting.none) + else: + depargs = NinjaCommandArg.list(compiler.get_dependency_gen_args('$out', '$DEPFILE'), Quoting.none) command = compiler.get_exelist() args = ['$ARGS'] + depargs + NinjaCommandArg.list(compiler.get_output_args('$out'), Quoting.none) + compiler.get_compile_only_args() + ['$in'] description = f'Compiling {compiler.get_display_language()} object $out' @@ -3003,6 +3007,28 @@ def generate_single_compile(self, target: build.BuildTarget, src, element.add_orderdep(i) if dep_file: element.add_item('DEPFILE', dep_file) + if compiler.get_language() == 'cuda': + # for cuda, we manually escape target name ($out) as $CUDA_ESCAPED_TARGET because nvcc doesn't support `-MQ` flag + def quote_make_target(targetName: str) -> str: + # this escape implementation is taken from llvm + result = '' + for (i, c) in enumerate(targetName): + if c in {' ', '\t'}: + # Escape the preceding backslashes + for j in range(i - 1, -1, -1): + if targetName[j] == '\\': + result += '\\' + else: + break + # Escape the space/tab + result += '\\' + elif c == '$': + result += '$' + elif c == '#': + result += '\\' + result += c + return result + element.add_item('CUDA_ESCAPED_TARGET', quote_make_target(rel_obj)) element.add_item('ARGS', commands) self.add_dependency_scanner_entries_to_element(target, compiler, element, src) From 4351f56f13519d0ba6fc26e651c4a0a0331d5767 Mon Sep 17 00:00:00 2001 From: "Marina.Kalashina" Date: Thu, 21 Dec 2023 15:37:25 +0400 Subject: [PATCH 515/855] Add CLion to the list of IDE integrations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLion was not mentioned in the list of IDE integrations. This commit adds it, also adds a “3rd party" prefix to the Meson Syntax Highlighter plugin to indicate that it doesn't come from JetBrains, and sorts the list alphabetically. --- docs/markdown/IDE-integration.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/markdown/IDE-integration.md b/docs/markdown/IDE-integration.md index ad7185a1fd7f..77edb755d388 100644 --- a/docs/markdown/IDE-integration.md +++ b/docs/markdown/IDE-integration.md @@ -418,11 +418,12 @@ schema is defined by the class structure given in # Existing integrations +- [CLion](https://www.jetbrains.com/clion/) +- [Eclipse CDT](https://www.eclipse.org/cdt/) - [Gnome Builder](https://wiki.gnome.org/Apps/Builder) - [KDevelop](https://www.kdevelop.org) -- [Eclipse CDT](https://www.eclipse.org/cdt/) -- [Meson Syntax Highlighter](https://plugins.jetbrains.com/plugin/13269-meson-syntax-highlighter) plugin for JetBrains IDEs. -- [vscode-meson](https://github.com/mesonbuild/vscode-meson) extension for VS Code/Codium -- [Qt Creator](https://doc.qt.io/qtcreator/creator-project-meson.html) +- [Meson Syntax Highlighter](https://plugins.jetbrains.com/plugin/13269-meson-syntax-highlighter) 3rd party plugin for JetBrains IDEs. - [Meson-UI](https://github.com/dreamer-coding-555/meson-ui) (build GUI for Meson) - [mmeson](https://github.com/stephanlachnit/mmeson) (ccmake clone for Meson) +- [Qt Creator](https://doc.qt.io/qtcreator/creator-project-meson.html) +- [vscode-meson](https://github.com/mesonbuild/vscode-meson) extension for VS Code/Codium From 4a96ad0170126f82b0aa13c26a31013f5d8127d8 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 28 Dec 2023 17:26:47 -0500 Subject: [PATCH 516/855] docs: fix regression that broke intended meaning of compiler variables note In commit 58c2aeb5e433ae7652488d53021c40db1712dea5, an asterisk used to indicate "see note at bottom" was doubled up into an "italicize this paragraph", which didn't contextually make any sense. See: https://github.com/mesonbuild/meson/pull/12674#issue-2057666653 --- docs/markdown/Reference-tables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 86f3e9ea5668..965a3cad6a13 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -377,7 +377,7 @@ machine](#Environment-variables-per-machine) section for details. | nasm | NASM | | Uses the C linker | *The old environment variables are still supported, but are deprecated -and will be removed in a future version of Meson.* +and will be removed in a future version of Meson. *changed in 1.3.0* Paths with spaces were split unconditionally to extract components such as the [path to Ccache](Feature-autodetection.md#ccache), From abeea418806f93a466894fcbc22f92db4d5461f6 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Wed, 27 Dec 2023 17:15:58 +0000 Subject: [PATCH 517/855] docs: Use Qt instead of qt --- docs/markdown/Qt6-module.md | 8 ++++---- docs/markdown/_include_qt_base.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/markdown/Qt6-module.md b/docs/markdown/Qt6-module.md index 4dbf64980540..cb83bd7d25da 100644 --- a/docs/markdown/Qt6-module.md +++ b/docs/markdown/Qt6-module.md @@ -19,7 +19,7 @@ It takes no positional arguments, and the following keyword arguments: A list of sources to be transpiled. Required, must have at least one source
*New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-rcc` - - `method` string: The method to use to detect qt, see [[dependency]] + - `method` string: The method to use to detect Qt, see [[dependency]] ## compile_ui @@ -32,7 +32,7 @@ It takes no positional arguments, and the following keyword arguments: A list of sources to be transpiled. Required, must have at least one source
*New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-uic` - - `method` string: The method to use to detect qt, see [[dependency]] + - `method` string: The method to use to detect Qt, see [[dependency]] ## compile_moc @@ -49,7 +49,7 @@ It takes no positional arguments, and the following keyword arguments: A list of headers to be transpiled into .cpp files
*New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-moc` - - `method` string: The method to use to detect qt, see [[dependency]] + - `method` string: The method to use to detect Qt, see [[dependency]] - `dependencies`: dependency objects whose include directories are used by moc. - `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()` objects used when transpiling the .moc files @@ -134,7 +134,7 @@ This method takes the following keyword arguments: - `required` bool | FeatureOption: by default, `required` is set to `false`. If `required` is set to `true` or an enabled [`feature`](Build-options.md#features) and some tools are missing Meson will abort. -- `method` string: The method to use to detect qt, see [[dependency]] +- `method` string: The method to use to detect Qt, see [[dependency]] ## Dependencies diff --git a/docs/markdown/_include_qt_base.md b/docs/markdown/_include_qt_base.md index 0a1192426b1a..883fdc37995c 100644 --- a/docs/markdown/_include_qt_base.md +++ b/docs/markdown/_include_qt_base.md @@ -12,7 +12,7 @@ It takes no positional arguments, and the following keyword arguments: A list of sources to be transpiled. Required, must have at least one source *New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-rcc` - - `method` string: The method to use to detect qt, see `dependency()` for more + - `method` string: The method to use to detect Qt, see `dependency()` for more information. ## compile_ui @@ -26,7 +26,7 @@ It takes no positional arguments, and the following keyword arguments: A list of sources to be transpiled. Required, must have at least one source *New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-uic` - - `method` string: The method to use to detect qt, see `dependency()` for more + - `method` string: The method to use to detect Qt, see `dependency()` for more information. ## compile_moc @@ -44,7 +44,7 @@ It takes no positional arguments, and the following keyword arguments: A list of headers to be transpiled into .cpp files *New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-moc` - - `method` string: The method to use to detect qt, see `dependency()` for more + - `method` string: The method to use to detect Qt, see `dependency()` for more information. - `dependencies`: dependency objects whose include directories are used by moc. - `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()` From dc3e0273802ad297ab564e08cfc5f2590e7e73b6 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Wed, 27 Dec 2023 17:15:58 +0000 Subject: [PATCH 518/855] docs: Rename Qt4 & Qt5 in Dependencies to Qt --- docs/markdown/Dependencies.md | 2 +- docs/markdown/Qt6-module.md | 2 +- docs/markdown/_include_qt_base.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 9ef436745556..d412a2526bcb 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -679,7 +679,7 @@ but dependency tries `pkg-config` first. `method` may be `auto`, `extraframework`, `pkg-config` or `sysconfig` -## Qt4 & Qt5 +## Qt Meson has native Qt support. Its usage is best demonstrated with an example. diff --git a/docs/markdown/Qt6-module.md b/docs/markdown/Qt6-module.md index cb83bd7d25da..7d40c4645de9 100644 --- a/docs/markdown/Qt6-module.md +++ b/docs/markdown/Qt6-module.md @@ -138,7 +138,7 @@ This method takes the following keyword arguments: ## Dependencies -See [Qt dependencies](Dependencies.md#qt4-qt5) +See [Qt dependencies](Dependencies.md#qt) The 'modules' argument is used to include Qt modules in the project. See the Qt documentation for the [list of diff --git a/docs/markdown/_include_qt_base.md b/docs/markdown/_include_qt_base.md index 883fdc37995c..d305ca91b822 100644 --- a/docs/markdown/_include_qt_base.md +++ b/docs/markdown/_include_qt_base.md @@ -128,7 +128,7 @@ This method takes the following keyword arguments: ## Dependencies -See [Qt dependencies](Dependencies.md#qt4-qt5) +See [Qt dependencies](Dependencies.md#qt) The 'modules' argument is used to include Qt modules in the project. See the Qt documentation for the [list of From 92bcf88f0ce2058e5957d397a7ba3c746f258d8f Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Fri, 29 Dec 2023 19:52:08 +0000 Subject: [PATCH 519/855] docs: Fix since for compile_translations in _include_qt_base --- docs/markdown/_include_qt_base.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/markdown/_include_qt_base.md b/docs/markdown/_include_qt_base.md index d305ca91b822..adc6f7c6fe0c 100644 --- a/docs/markdown/_include_qt_base.md +++ b/docs/markdown/_include_qt_base.md @@ -81,7 +81,9 @@ This method takes the following keyword arguments: It returns an array of targets and sources to pass to a compilation target. -## compile_translations (since v0.44.0) +## compile_translations + +*since 0.44.0* This method generates the necessary targets to build translation files with lrelease, it takes no positional arguments, and the following keyword arguments: From 65e4fb391faa8b3c979c4389e6ead241364e15d2 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Fri, 29 Dec 2023 19:52:08 +0000 Subject: [PATCH 520/855] docs: Document Qt tools updates in 0.63 Especially relevant for users of Ubuntu 22.04 which has packages for Qt 6.2 and Meson 0.61. a606ce22e ("Add support for Qt 6.1+", 2022-01-08) d68a0651e ("qt module: also prefer the changed name scheme for the tools", 2022-02-09) --- docs/markdown/Qt6-module.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/markdown/Qt6-module.md b/docs/markdown/Qt6-module.md index 7d40c4645de9..8e8ec71e073d 100644 --- a/docs/markdown/Qt6-module.md +++ b/docs/markdown/Qt6-module.md @@ -2,9 +2,15 @@ *New in Meson 0.57.0* -The Qt6 module provides tools to automatically deal with the various +The Qt6 module provides methods to automatically deal with the various tools and steps required for Qt. +
+Warning: before version 0.63.0 Meson would fail to find +Qt 6.1 or later due to the Qt tools having moved to the libexec subdirectory, +and tool names being suffixed with only the Qt major version number e.g. qmake6. +
+ ## compile_resources *New in 0.59.0* From 0e1cba6d8b8a3594664451534338fda5e2ae7d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Br=C3=A5then=20Solem?= Date: Wed, 27 Dec 2023 18:18:56 +0100 Subject: [PATCH 521/855] envconfig: read CYTHON from the environment and use it if set Add support for specifying Cython compiler using the CYTHON environment variable. If not set, proceed with the names hard coded for Cython. --- docs/markdown/Reference-tables.md | 1 + mesonbuild/envconfig.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 965a3cad6a13..af6a9b9f0bf4 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -374,6 +374,7 @@ machine](#Environment-variables-per-machine) section for details. | Rust | RUSTC | RUSTC_LD | Before 0.54 RUST_LD* | | Vala | VALAC | | Use CC_LD. Vala transpiles to C | | C# | CSC | CSC | The linker is the compiler | +| Cython | CYTHON | | | | nasm | NASM | | Uses the C linker | *The old environment variables are still supported, but are deprecated diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index a717732495e7..0e9cd23cc736 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -88,6 +88,7 @@ 'c': 'CC', 'cpp': 'CXX', 'cs': 'CSC', + 'cython': 'CYTHON', 'd': 'DC', 'fortran': 'FC', 'objc': 'OBJC', From 457161c0e8f67f74e4aafbc5080b66db9fdb35cb Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Mon, 1 Jan 2024 16:19:55 +0000 Subject: [PATCH 522/855] CI: Fix macos.yml error "Invalid workflow file" --- .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 adbfcb21c743..efa2b2d051a6 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -78,7 +78,7 @@ jobs: name: ${{ matrix.NAME }} env: MESON_CI_JOBNAME: ${{ matrix.NAME }} - HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_AUTO_UPDATE: 1 steps: - uses: actions/checkout@v3 From e110faed27616ea2a18eac160c335c3f039ac479 Mon Sep 17 00:00:00 2001 From: Roger Sanders Date: Thu, 28 Dec 2023 11:06:11 +1100 Subject: [PATCH 523/855] Fix intellisense errors in genvslite projects Standard include paths need to be added to resolve STL and platform headers. Additionally, compiler args need to be separated by spaces, not semicolons, in order to be recognised. --- mesonbuild/backend/vs2010backend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index bcae160bf9f0..80ecc0506309 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1118,7 +1118,7 @@ def get_build_args(compiler, optimization_level: str, debug: bool, sanitize: str # and include paths, e.g. - # '..\\some\\dir\\include;../../some/other/dir;' # and finally any remaining compiler options, e.g. - - # '/MDd;/W2;/std:c++17;/Od/Zi' + # '/MDd /W2 /std:c++17 /Od/Zi' @staticmethod def _extract_nmake_fields(captured_build_args: list[str]) -> T.Tuple[str, str, str]: include_dir_options = [ @@ -1131,7 +1131,7 @@ def _extract_nmake_fields(captured_build_args: list[str]) -> T.Tuple[str, str, s ] defs = '' - paths = '' + paths = '$(VC_IncludePath);$(WindowsSDK_IncludePath);' additional_opts = '' for arg in captured_build_args: if arg.startswith(('-D', '/D')): @@ -1141,7 +1141,7 @@ def _extract_nmake_fields(captured_build_args: list[str]) -> T.Tuple[str, str, s if opt_match: paths += arg[len(opt_match):] + ';' elif arg.startswith(('-', '/')): - additional_opts += arg + ';' + additional_opts += arg + ' ' return (defs, paths, additional_opts) @staticmethod From 8e366b87599f666eed865b27f7cf4732dbe6a565 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 2 Jan 2024 02:25:30 -0500 Subject: [PATCH 524/855] CI: fix even more brokenness in the macos CI Commit 191449f60879a622661b96600babaec67477d5bb has numerous issues, and being completely invalid yml syntax was just the tip of the iceberg. In this case, it fails the github schema, which requires that env be adjunct to a job or step definition, rather than its own thing. It did not even make sense in context, since the purpose of the variable is to modify brew. Fixes: #12644 Fixes: #12681 --- .github/workflows/macos.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index efa2b2d051a6..bdc5f20c9c55 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -101,7 +101,6 @@ jobs: CPPFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" MESON_ARGS: --unity=${{ matrix.unity }} - HOMEBREW_NO_AUTO_UPDATE: 1 CI: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | @@ -124,13 +123,13 @@ jobs: Qt4macos: runs-on: macos-latest + env: + HOMEBREW_NO_AUTO_UPDATE: 1 steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.x' - - env: - HOMEBREW_NO_AUTO_UPDATE: 1 - run: python -m pip install -e . - run: brew install pkg-config ninja gcc - run: brew tap cartr/qt4 From e4bbc630b67ef97ad842badd00855e64cff12e13 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 1 Jan 2024 22:45:10 -0500 Subject: [PATCH 525/855] tests: fix java JNI test assert for jni.h existing compiler.has_header() isn't an assert, even though the comments say it is. With `required: true` it is an actual assert. --- test cases/java/9 jni/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test cases/java/9 jni/meson.build b/test cases/java/9 jni/meson.build index 7a681659131f..a4051ad28093 100644 --- a/test cases/java/9 jni/meson.build +++ b/test cases/java/9 jni/meson.build @@ -17,9 +17,9 @@ java = find_program('java') jni_dep = dependency('jni', version : '>=1.8', modules: ['jvm', 'awt']) # Assert that the header can actually be found with the dependency. -cc.has_header('jni.h', dependencies: [jni_dep]) +cc.has_header('jni.h', dependencies: [jni_dep], required: true) # Assert that the platform-specific include directory is included in the compiler arguments. -cc.has_header('jni_md.h', dependencies: [jni_dep]) +cc.has_header('jni_md.h', dependencies: [jni_dep], required: true) # generate native headers subdir('src') From fbc744e6c6031f96cdbb89e5320d93188a18006c Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 5 Jan 2024 15:51:51 -0500 Subject: [PATCH 526/855] Fix warning_level=everything in vs backends Fixes #12688 --- mesonbuild/backend/vs2010backend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 80ecc0506309..4396b3c5665d 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1345,7 +1345,8 @@ def add_non_makefile_vcxproj_elements( ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true' # Warning level warning_level = T.cast('str', target.get_option(OptionKey('warning_level'))) - ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level)) + warning_level = 'EnableAllWarnings' if warning_level == 'everything' else 'Level' + str(1 + int(warning_level)) + ET.SubElement(clconf, 'WarningLevel').text = warning_level if target.get_option(OptionKey('werror')): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Optimization flags From 7700618181249ec02ebe774d9c276d1c343b5dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Fri, 22 Dec 2023 21:02:58 +0100 Subject: [PATCH 527/855] machine file: Fix parenthesized expressions Extends 79ed2415e9a5. Thanks @bruchar1 for the test case; I got absolutely lost trying to figure out where to add one. --- mesonbuild/coredata.py | 2 ++ test cases/common/222 native prop/nativefile.ini | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 5f1c2fc0e1c0..a6a14c8abf56 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1097,6 +1097,8 @@ def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, return node.value elif isinstance(node, mparser.NumberNode): return node.value + elif isinstance(node, mparser.ParenthesizedNode): + return self._evaluate_statement(node.inner) elif isinstance(node, mparser.ArrayNode): # TODO: This is where recursive types would come in handy return [self._evaluate_statement(arg) for arg in node.args.arguments] diff --git a/test cases/common/222 native prop/nativefile.ini b/test cases/common/222 native prop/nativefile.ini index 03c1e03973a7..790b27cef0c9 100644 --- a/test cases/common/222 native prop/nativefile.ini +++ b/test cases/common/222 native prop/nativefile.ini @@ -1,3 +1,4 @@ [properties] astring = 'mystring' -anarray = ['one', 'two'] \ No newline at end of file +anarray = ['one', 'two'] +withparentheses = ('anotherstring') # Ensure parentheses can be parsed \ No newline at end of file From 5cd11473540a4f7948daaa3268815c7f79c60cfb Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Dec 2023 13:20:00 -0800 Subject: [PATCH 528/855] ast/printer: fix mypy issues Other than one case that I think cannot be actually hit (or it would fail). --- mesonbuild/ast/printer.py | 18 ++++++++++-------- mesonbuild/ast/visitor.py | 4 ++-- run_mypy.py | 1 + 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index bbaca35d9e1b..459912f2d636 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -65,8 +65,9 @@ def visit_NumberNode(self, node: mparser.NumberNode) -> None: node.lineno = self.curr_line or node.lineno def escape(self, val: str) -> str: - return val.translate(str.maketrans({'\'': '\\\'', - '\\': '\\\\'})) + return val.translate(str.maketrans(T.cast( + 'T.Dict[str, T.Union[str, int]]', + {'\'': '\\\'', '\\': '\\\\'}))) def visit_StringNode(self, node: mparser.StringNode) -> None: assert isinstance(node.value, str) @@ -78,7 +79,7 @@ def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.append("f'" + self.escape(node.value) + "'", node) node.lineno = self.curr_line or node.lineno - def visit_MultilineStringNode(self, node: mparser.StringNode) -> None: + def visit_MultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: assert isinstance(node.value, str) self.append("'''" + node.value + "'''", node) node.lineno = self.curr_line or node.lineno @@ -241,21 +242,22 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: class RawPrinter(AstVisitor): - def __init__(self): + def __init__(self) -> None: self.result = '' - def visit_default_func(self, node: mparser.BaseNode): - self.result += node.value + def visit_default_func(self, node: mparser.BaseNode) -> None: + # XXX: this seems like it could never actually be reached... + self.result += node.value # type: ignore[attr-defined] if node.whitespaces: node.whitespaces.accept(self) - def visit_unary_operator(self, node: mparser.UnaryOperatorNode): + def visit_unary_operator(self, node: mparser.UnaryOperatorNode) -> None: node.operator.accept(self) node.value.accept(self) if node.whitespaces: node.whitespaces.accept(self) - def visit_binary_operator(self, node: mparser.BinaryOperatorNode): + def visit_binary_operator(self, node: mparser.BinaryOperatorNode) -> None: node.left.accept(self) node.operator.accept(self) node.right.accept(self) diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 2b5cea6748d5..60aca61f9695 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -32,7 +32,7 @@ def visit_StringNode(self, node: mparser.StringNode) -> None: def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.visit_default_func(node) - def visit_MultilineStringNode(self, node: mparser.StringNode) -> None: + def visit_MultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: self.visit_default_func(node) def visit_FormatMultilineStringNode(self, node: mparser.FormatStringNode) -> None: @@ -138,7 +138,7 @@ def visit_IfNode(self, node: mparser.IfNode) -> None: node.condition.accept(self) node.block.accept(self) - def visit_ElseNode(self, node: mparser.IfNode) -> None: + def visit_ElseNode(self, node: mparser.ElseNode) -> None: self.visit_default_func(node) node.block.accept(self) diff --git a/run_mypy.py b/run_mypy.py index 067080b9ad32..c3f391997059 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -24,6 +24,7 @@ 'mesonbuild/wrap/', # specific files + 'mesonbuild/ast/printer.py', 'mesonbuild/arglist.py', 'mesonbuild/backend/backends.py', 'mesonbuild/backend/nonebackend.py', From 25fa0e97216922a5d81181090c531493f1df1055 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Dec 2023 13:21:02 -0800 Subject: [PATCH 529/855] ast: mark visitor and preprocessor as mypy safe They already are warning free --- run_mypy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run_mypy.py b/run_mypy.py index c3f391997059..8e04a76ff089 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -25,6 +25,8 @@ # specific files 'mesonbuild/ast/printer.py', + 'mesonbuild/ast/postprocess.py', + 'mesonbuild/ast/visitor.py', 'mesonbuild/arglist.py', 'mesonbuild/backend/backends.py', 'mesonbuild/backend/nonebackend.py', From 7d0d610045b9ae5860eb1c7e0e50bb04eaa17673 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Dec 2023 13:35:37 -0800 Subject: [PATCH 530/855] ast/introspection: make mypy clean --- mesonbuild/ast/interpreter.py | 22 ++++++++++---------- mesonbuild/ast/introspection.py | 37 +++++++++++++++++---------------- mesonbuild/build.py | 2 +- run_mypy.py | 1 + 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index b6f7f9978467..783387df1e29 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -49,7 +49,7 @@ if T.TYPE_CHECKING: from .visitor import AstVisitor from ..interpreter import Interpreter - from ..interpreterbase import TYPE_nkwargs, TYPE_nvar + from ..interpreterbase import TYPE_nkwargs, TYPE_var from ..mparser import ( AndNode, ComparisonNode, @@ -159,7 +159,7 @@ def _unholder_args(self, args: _T, kwargs: _V) -> T.Tuple[_T, _V]: def _holderify(self, res: _T) -> _T: return res - def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> bool: + def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> bool: return True def load_root_meson_file(self) -> None: @@ -167,7 +167,7 @@ def load_root_meson_file(self) -> None: for i in self.visitors: self.ast.accept(i) - def func_subdir(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + def func_subdir(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None: args = self.flatten_args(args) if len(args) != 1 or not isinstance(args[0], str): sys.stderr.write(f'Unable to evaluate subdir({args}) in AstInterpreter --> Skipping\n') @@ -210,7 +210,7 @@ def evaluate_fstring(self, node: mparser.FormatStringNode) -> str: assert isinstance(node, mparser.FormatStringNode) return node.value - def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> TYPE_nvar: + def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> TYPE_var: return self.reduce_arguments(cur.args)[0] def evaluate_arithmeticstatement(self, cur: ArithmeticNode) -> int: @@ -261,9 +261,9 @@ def reduce_arguments( args: mparser.ArgumentNode, key_resolver: T.Callable[[mparser.BaseNode], str] = default_resolve_key, duplicate_key_error: T.Optional[str] = None, - ) -> T.Tuple[T.List[TYPE_nvar], TYPE_nkwargs]: + ) -> T.Tuple[T.List[TYPE_var], TYPE_nkwargs]: if isinstance(args, ArgumentNode): - kwargs: T.Dict[str, TYPE_nvar] = {} + kwargs: T.Dict[str, TYPE_var] = {} for key, val in args.kwargs.items(): kwargs[key_resolver(key)] = val if args.incorrect_order(): @@ -372,7 +372,7 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T elif isinstance(node, MethodNode): src = quick_resolve(node.source_object) margs = self.flatten_args(node.args.arguments, include_unknown_args, id_loop_detect) - mkwargs: T.Dict[str, TYPE_nvar] = {} + mkwargs: T.Dict[str, TYPE_var] = {} method_name = node.name.value try: if isinstance(src, str): @@ -392,7 +392,7 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T if isinstance(result, BaseNode): result = self.resolve_node(result, include_unknown_args, id_loop_detect) elif isinstance(result, list): - new_res: T.List[TYPE_nvar] = [] + new_res: T.List[TYPE_var] = [] for i in result: if isinstance(i, BaseNode): resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) @@ -404,14 +404,14 @@ def quick_resolve(n: BaseNode, loop_detect: T.Optional[T.List[str]] = None) -> T return result - def flatten_args(self, args_raw: T.Union[TYPE_nvar, T.Sequence[TYPE_nvar]], include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[TYPE_nvar]: + def flatten_args(self, args_raw: T.Union[TYPE_var, T.Sequence[TYPE_var]], include_unknown_args: bool = False, id_loop_detect: T.Optional[T.List[str]] = None) -> T.List[TYPE_var]: # Make sure we are always dealing with lists if isinstance(args_raw, list): args = args_raw else: args = [args_raw] - flattened_args: T.List[TYPE_nvar] = [] + flattened_args: T.List[TYPE_var] = [] # Resolve the contents of args for i in args: @@ -425,7 +425,7 @@ def flatten_args(self, args_raw: T.Union[TYPE_nvar, T.Sequence[TYPE_nvar]], incl flattened_args += [i] return flattened_args - def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_nvar], include_unknown_args: bool = False) -> T.Dict[str, TYPE_nvar]: + def flatten_kwargs(self, kwargs: T.Dict[str, TYPE_var], include_unknown_args: bool = False) -> T.Dict[str, TYPE_var]: flattened_kwargs = {} for key, val in kwargs.items(): if isinstance(val, BaseNode): diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 9a39314ad56a..49e58f43d101 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -21,7 +21,7 @@ if T.TYPE_CHECKING: from ..build import BuildTarget - from ..interpreterbase import TYPE_nvar + from ..interpreterbase import TYPE_var from .visitor import AstVisitor @@ -85,7 +85,7 @@ def __init__(self, 'both_libraries': self.func_both_lib, }) - def func_project(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + def func_project(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None: if self.project_node: raise InvalidArguments('Second call to project()') self.project_node = node @@ -146,9 +146,10 @@ def do_subproject(self, dirname: str) -> None: except (mesonlib.MesonException, RuntimeError): return - def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + def func_add_languages(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None: kwargs = self.flatten_kwargs(kwargs) required = kwargs.get('required', True) + assert isinstance(required, (bool, cdata.UserFeatureOption)), 'for mypy' if isinstance(required, cdata.UserFeatureOption): required = required.is_enabled() if 'native' in kwargs: @@ -158,7 +159,7 @@ def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T. for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: self._add_languages(args, required, for_machine) - def _add_languages(self, raw_langs: T.List[TYPE_nvar], required: bool, for_machine: MachineChoice) -> None: + def _add_languages(self, raw_langs: T.List[TYPE_var], required: bool, for_machine: MachineChoice) -> None: langs: T.List[str] = [] for l in self.flatten_args(raw_langs): if isinstance(l, str): @@ -185,7 +186,7 @@ def _add_languages(self, raw_langs: T.List[TYPE_nvar], required: bool, for_machi options[k] = v self.coredata.add_compiler_options(options, lang, for_machine, self.environment) - def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None: + def func_dependency(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None: args = self.flatten_args(args) kwargs = self.flatten_kwargs(kwargs) if not args: @@ -209,7 +210,7 @@ def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dic 'node': node }] - def build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs_raw: T.Dict[str, TYPE_nvar], targetclass: T.Type[BuildTarget]) -> T.Optional[T.Dict[str, T.Any]]: + def build_target(self, node: BaseNode, args: T.List[TYPE_var], kwargs_raw: T.Dict[str, TYPE_var], targetclass: T.Type[BuildTarget]) -> T.Optional[T.Dict[str, T.Any]]: args = self.flatten_args(args) if not args or not isinstance(args[0], str): return None @@ -270,7 +271,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: empty_sources: T.List[T.Any] = [] # Passing the unresolved sources list causes errors kwargs_reduced['_allow_no_sources'] = True - target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, [], objects, + target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, None, objects, self.environment, self.coredata.compilers[for_machine], kwargs_reduced) target.process_compilers_late() @@ -292,7 +293,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: self.targets += [new_target] return new_target - def build_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def build_library(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: default_library = self.coredata.get_option(OptionKey('default_library')) if default_library == 'shared': return self.build_target(node, args, kwargs, SharedLibrary) @@ -302,28 +303,28 @@ def build_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[ return self.build_target(node, args, kwargs, SharedLibrary) return None - def func_executable(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_executable(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, Executable) - def func_static_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_static_lib(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, StaticLibrary) - def func_shared_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_shared_lib(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedLibrary) - def func_both_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_both_lib(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedLibrary) - def func_shared_module(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_shared_module(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, SharedModule) - def func_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_library(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_library(node, args, kwargs) - def func_jar(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_jar(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: return self.build_target(node, args, kwargs, Jar) - def func_build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]: + def func_build_target(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> T.Optional[T.Dict[str, T.Any]]: if 'target_type' not in kwargs: return None target_type = kwargs.pop('target_type') @@ -358,11 +359,11 @@ def extract_subproject_dir(self) -> T.Optional[str]: and also calls parse_project() on every subproject. ''' if not self.ast.lines: - return + return None project = self.ast.lines[0] # first line is always project() if not isinstance(project, FunctionNode): - return + return None for kw, val in project.args.kwargs.items(): assert isinstance(kw, IdNode), 'for mypy' if kw.value == 'subproject_dir': diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 68513bb63614..51c4834320e2 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -887,7 +887,7 @@ def can_compile_remove_sources(compiler: 'Compiler', sources: T.List['FileOrStri removed = True return removed - def process_compilers_late(self): + def process_compilers_late(self) -> None: """Processes additional compilers after kwargs have been evaluated. This can add extra compilers that might be required by keyword diff --git a/run_mypy.py b/run_mypy.py index 8e04a76ff089..a9b52d9ac2f7 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -24,6 +24,7 @@ 'mesonbuild/wrap/', # specific files + 'mesonbuild/ast/introspection.py', 'mesonbuild/ast/printer.py', 'mesonbuild/ast/postprocess.py', 'mesonbuild/ast/visitor.py', From c41fbf5076a79d5561ea0655d59131f4c34ef535 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 14 Dec 2023 09:38:15 -0800 Subject: [PATCH 531/855] ast/interpreter: fix some low hanging type issues --- mesonbuild/ast/interpreter.py | 5 +++-- mesonbuild/ast/introspection.py | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 783387df1e29..0887fa2ebab1 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -49,7 +49,7 @@ if T.TYPE_CHECKING: from .visitor import AstVisitor from ..interpreter import Interpreter - from ..interpreterbase import TYPE_nkwargs, TYPE_var + from ..interpreterbase import SubProject, TYPE_nkwargs, TYPE_var from ..mparser import ( AndNode, ComparisonNode, @@ -84,8 +84,9 @@ class MockRunTarget(MesonInterpreterObject): _T = T.TypeVar('_T') _V = T.TypeVar('_V') + class AstInterpreter(InterpreterBase): - def __init__(self, source_root: str, subdir: str, subproject: str, visitors: T.Optional[T.List[AstVisitor]] = None): + def __init__(self, source_root: str, subdir: str, subproject: SubProject, visitors: T.Optional[T.List[AstVisitor]] = None): super().__init__(source_root, subdir, subproject) self.visitors = visitors if visitors is not None else [] self.processed_buildfiles: T.Set[str] = set() diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 49e58f43d101..095f30c14fd1 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -14,7 +14,7 @@ from .. import coredata as cdata from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary from ..compilers import detect_compiler_for -from ..interpreterbase import InvalidArguments +from ..interpreterbase import InvalidArguments, SubProject from ..mesonlib import MachineChoice, OptionKey from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, BaseStringNode from .interpreter import AstInterpreter @@ -51,7 +51,7 @@ def __init__(self, backend: str, visitors: T.Optional[T.List[AstVisitor]] = None, cross_file: T.Optional[str] = None, - subproject: str = '', + subproject: SubProject = SubProject(''), subproject_dir: str = 'subprojects', env: T.Optional[environment.Environment] = None): visitors = visitors if visitors is not None else [] @@ -126,7 +126,7 @@ def func_project(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[st if os.path.isdir(subprojects_dir): for i in os.listdir(subprojects_dir): if os.path.isdir(os.path.join(subprojects_dir, i)): - self.do_subproject(i) + self.do_subproject(SubProject(i)) self.coredata.init_backend_options(self.backend) options = {k: v for k, v in self.environment.options.items() if k.is_backend()} @@ -135,7 +135,7 @@ def func_project(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[st self._add_languages(proj_langs, True, MachineChoice.HOST) self._add_languages(proj_langs, True, MachineChoice.BUILD) - def do_subproject(self, dirname: str) -> None: + def do_subproject(self, dirname: SubProject) -> None: subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) subpr = os.path.join(subproject_dir_abs, dirname) try: From 90098473d51e6f059e775f1833b0a2ea91c8f8f9 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 2 Jan 2024 02:16:28 +0000 Subject: [PATCH 532/855] compilers: cpp: wire up stdlib assertions None of the options set here affect ABI and are intended for detecting constraint violations. For GCC, we simply need to set -D_GLIBCXX_ASSERTIONS. For Clang, the situation is far more complicated: * LLVM 18 uses a 'hardened mode' (https://libcxx.llvm.org/Hardening.html). There are several levels of severity available here. I've chosen _LIBCPP_HARDENING_MODE_EXTENSIVE as the strongest-but-one. The strongest one (_DEBUG) doesn't affect ABI still but is reserved for stldebug. * LLVM 15 uses a similar approach to libstdc++ called '_LIBCPP_ENABLE_ASSERTIONS' Note that LLVM 17 while in development had fully deprecated _LIBCPP_ENABLE_ASSERTIONS in favour of hardened, but changed its mind last-minute: https://discourse.llvm.org/t/rfc-hardening-in-libc/73925/4. Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- docs/markdown/snippets/cpp-debug.md | 10 ++++++++++ mesonbuild/compilers/cpp.py | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 docs/markdown/snippets/cpp-debug.md diff --git a/docs/markdown/snippets/cpp-debug.md b/docs/markdown/snippets/cpp-debug.md new file mode 100644 index 000000000000..2a62b93994b4 --- /dev/null +++ b/docs/markdown/snippets/cpp-debug.md @@ -0,0 +1,10 @@ +## `ndebug` setting now controls C++ stdlib assertions + +The `ndebug` setting, if disabled, now passes preprocessor defines to enable +debugging assertions within the C++ standard library. + +For GCC, `-D_GLIBCXX_ASSERTIONS=1` is set. + +For Clang, `-D_GLIBCXX_ASSERTIONS=1` is set to cover libstdc++ usage, +and `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` or +`-D_LIBCPP_ENABLE_ASSERTIONS=1` is used depending on the Clang version. diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 226605390356..f6a03caf218b 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -293,6 +293,20 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return libs return [] + def get_assert_args(self, disable: bool) -> T.List[str]: + args: T.List[str] = [] + if disable: + return ['-DNDEBUG'] + + # Clang supports both libstdc++ and libc++ + args.append('-D_GLIBCXX_ASSERTIONS=1') + if version_compare(self.version, '>=18'): + args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE') + elif version_compare(self.version, '>=15'): + args.append('-D_LIBCPP_ENABLE_ASSERTIONS=1') + + return args + class ArmLtdClangCPPCompiler(ClangCPPCompiler): @@ -462,6 +476,14 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return libs return [] + def get_assert_args(self, disable: bool) -> T.List[str]: + if disable: + return ['-DNDEBUG'] + + # XXX: This needs updating if/when GCC starts to support libc++. + # It currently only does so via an experimental configure arg. + return ['-D_GLIBCXX_ASSERTIONS=1'] + def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return ['-fpch-preprocess', '-include', os.path.basename(header)] From ce2db13e94fdeaff72d9e1f23b40072f9fb8818b Mon Sep 17 00:00:00 2001 From: byteblob Date: Mon, 8 Jan 2024 10:17:10 +0100 Subject: [PATCH 533/855] ninja: Use platform dependent quote instead of shlex.quote() in gcc_rsp_quote() --- mesonbuild/backend/ninjabackend.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9acc39c2a82e..0e1413f850d7 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -14,7 +14,6 @@ import os import pickle import re -import shlex import subprocess import typing as T @@ -67,16 +66,6 @@ def cmd_quote(arg: str) -> str: return arg -def gcc_rsp_quote(s: str) -> str: - # see: the function buildargv() in libiberty - # - # this differs from sh-quoting in that a backslash *always* escapes the - # following character, even inside single quotes. - - s = s.replace('\\', '\\\\') - - return shlex.quote(s) - # How ninja executes command lines differs between Unix and Windows # (see https://ninja-build.org/manual.html#ref_rule_command) if mesonlib.is_windows(): @@ -88,6 +77,15 @@ def gcc_rsp_quote(s: str) -> str: execute_wrapper = [] rmfile_prefix = ['rm', '-f', '{}', '&&'] +def gcc_rsp_quote(s: str) -> str: + # see: the function buildargv() in libiberty + # + # this differs from sh-quoting in that a backslash *always* escapes the + # following character, even inside single quotes. + + s = s.replace('\\', '\\\\') + + return quote_func(s) def get_rsp_threshold() -> int: '''Return a conservative estimate of the commandline size in bytes From a5fdd3771f8ec510167d44ef43cda1285ee05610 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 2 Jan 2024 03:03:57 +0000 Subject: [PATCH 534/855] compilers: cpp: wire up debugstl for Clang For Clang, we now pass -D_GLIBCXX_DEBUG=1 if debugstl is enabled, and we also pass -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG. Per https://discourse.llvm.org/t/building-a-program-with-d-libcpp-debug-1-against-a-libc-that-is-not-itself-built-with-that-define/59176/3, we can't use _LIBCPP_DEBUG for older Clang versions as it's unreliable unless libc++ was built with it. We choose MODE_DEBUG for stldebug while building with assertions will do MODE_EXTENSIVE. Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- docs/markdown/snippets/cpp-stldebug.md | 4 ++++ mesonbuild/compilers/cpp.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 docs/markdown/snippets/cpp-stldebug.md diff --git a/docs/markdown/snippets/cpp-stldebug.md b/docs/markdown/snippets/cpp-stldebug.md new file mode 100644 index 000000000000..ba0473608c8a --- /dev/null +++ b/docs/markdown/snippets/cpp-stldebug.md @@ -0,0 +1,4 @@ +## `stldebug` gains Clang support + +For Clang, we now pass `-D_GLIBCXX_DEBUG=1` if `debugstl` is enabled, and +we also pass `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG`. diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f6a03caf218b..0ff89a3eae61 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -242,6 +242,10 @@ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) key = OptionKey('key', machine=self.for_machine, lang=self.language) opts.update({ + key.evolve('debugstl'): coredata.UserBooleanOption( + 'STL debug mode', + False, + ), key.evolve('eh'): coredata.UserComboOption( 'C++ exception handling type.', ['none', 'default', 'a', 's', 'sc'], @@ -277,6 +281,15 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] non_msvc_eh_options(options[key.evolve('eh')].value, args) + if options[key.evolve('debugstl')].value: + args.append('-D_GLIBCXX_DEBUG=1') + + # We can't do _LIBCPP_DEBUG because it's unreliable unless libc++ was built with it too: + # https://discourse.llvm.org/t/building-a-program-with-d-libcpp-debug-1-against-a-libc-that-is-not-itself-built-with-that-define/59176/3 + # Note that unlike _GLIBCXX_DEBUG, _MODE_DEBUG doesn't break ABI. It's just slow. + if version_compare(self.version, '>=18'): + args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG') + if not options[key.evolve('rtti')].value: args.append('-fno-rtti') From ae857e841b0a6b9b595583e74f5e21676bb83f9d Mon Sep 17 00:00:00 2001 From: Valeri Date: Thu, 11 Jan 2024 18:55:02 +0300 Subject: [PATCH 535/855] Vala: fixes to gresource handling (#12418) * Vala: depend on gresources Valac uses gresource at compile time to look up .ui files * Automatically pass `--gresourcesdir` to valac * gnome.compile_resources: clean up duplicate paths better * Add a test for improved gresouce handling --- mesonbuild/backend/ninjabackend.py | 12 ++++++- mesonbuild/modules/__init__.py | 2 +- mesonbuild/modules/gnome.py | 6 +++- .../vala/28 generated ui file/TestBox.ui.in | 6 ++++ .../vala/28 generated ui file/meson.build | 34 +++++++++++++++++++ .../28 generated ui file/test.gresource.xml | 6 ++++ .../vala/28 generated ui file/test.vala | 7 ++++ 7 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 test cases/vala/28 generated ui file/TestBox.ui.in create mode 100644 test cases/vala/28 generated ui file/meson.build create mode 100644 test cases/vala/28 generated ui file/test.gresource.xml create mode 100644 test cases/vala/28 generated ui file/test.vala diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 0e1413f850d7..3143dff28c1b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1691,11 +1691,21 @@ def generate_vala_compile(self, target: build.BuildTarget) -> \ # Install GIR to default location if requested by user if len(target.install_dir) > 3 and target.install_dir[3] is True: target.install_dir[3] = os.path.join(self.environment.get_datadir(), 'gir-1.0') - # Detect gresources and add --gresources arguments for each + # Detect gresources and add --gresources/--gresourcesdir arguments for each + gres_dirs = [] for gensrc in other_src[1].values(): if isinstance(gensrc, modules.GResourceTarget): gres_xml, = self.get_custom_target_sources(gensrc) args += ['--gresources=' + gres_xml] + for source_dir in gensrc.source_dirs: + gres_dirs += [os.path.join(self.get_target_dir(gensrc), source_dir)] + # Ensure that resources are built before vala sources + # This is required since vala code using [GtkTemplate] effectively depends on .ui files + # GResourceHeaderTarget is not suitable due to lacking depfile + gres_c, = gensrc.get_outputs() + extra_dep_files += [os.path.join(self.get_target_dir(gensrc), gres_c)] + for gres_dir in OrderedSet(gres_dirs): + args += [f'--gresourcesdir={gres_dir}'] dependency_vapis = self.determine_dep_vapis(target) extra_dep_files += dependency_vapis extra_dep_files.extend(self.get_target_depend_files(target)) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 90a7f09b5bde..17b3631d983a 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -254,7 +254,7 @@ def __init__(self, return_value: T.Optional['TYPE_var'], self.new_objects: T.List[T.Union['TYPE_var', 'mesonlib.ExecutableSerialisation']] = new_objects class GResourceTarget(build.CustomTarget): - pass + source_dirs: T.List[str] = [] class GResourceHeaderTarget(build.CustomTarget): pass diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 32df2a60e151..9d6c1320991a 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -448,7 +448,10 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri # Always include current directory, but after paths set by user source_dirs.append(os.path.join(state.build_to_src, state.subdir)) - for source_dir in OrderedSet(source_dirs): + # Clean up duplicate directories + source_dirs = list(OrderedSet(os.path.normpath(dir) for dir in source_dirs)) + + for source_dir in source_dirs: cmd += ['--sourcedir', source_dir] if kwargs['c_name']: @@ -507,6 +510,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri install_dir=[kwargs['install_dir']] if kwargs['install_dir'] else [], install_tag=['runtime'], ) + target_c.source_dirs = source_dirs if gresource: # Only one target for .gresource files return ModuleReturnValue(target_c, [target_c]) diff --git a/test cases/vala/28 generated ui file/TestBox.ui.in b/test cases/vala/28 generated ui file/TestBox.ui.in new file mode 100644 index 000000000000..bf5c83178b65 --- /dev/null +++ b/test cases/vala/28 generated ui file/TestBox.ui.in @@ -0,0 +1,6 @@ + + + + + diff --git a/test cases/vala/28 generated ui file/meson.build b/test cases/vala/28 generated ui file/meson.build new file mode 100644 index 000000000000..fbf9840eba6a --- /dev/null +++ b/test cases/vala/28 generated ui file/meson.build @@ -0,0 +1,34 @@ +project('demo', 'c', 'vala') + +gnome = import('gnome', required: false) + +if not gnome.found() + error('MESON_SKIP_TEST: gnome module not supported') +endif + +deps = [ + dependency('glib-2.0', version : '>=2.50'), + dependency('gobject-2.0'), + dependency('gtk+-3.0'), +] + +ui_tgt = custom_target( + input: 'TestBox.ui.in', + output: 'TestBox.ui', + command: [find_program('cat')], + feed: true, + capture: true, +) + +resources = gnome.compile_resources('test-resources', + 'test.gresource.xml', + c_name: 'test_res', + dependencies: ui_tgt, +) + +executable( + 'demo', + 'test.vala', + resources, + dependencies: deps, +) diff --git a/test cases/vala/28 generated ui file/test.gresource.xml b/test cases/vala/28 generated ui file/test.gresource.xml new file mode 100644 index 000000000000..382b95193a7c --- /dev/null +++ b/test cases/vala/28 generated ui file/test.gresource.xml @@ -0,0 +1,6 @@ + + + + TestBox.ui + + diff --git a/test cases/vala/28 generated ui file/test.vala b/test cases/vala/28 generated ui file/test.vala new file mode 100644 index 000000000000..36f565b63451 --- /dev/null +++ b/test cases/vala/28 generated ui file/test.vala @@ -0,0 +1,7 @@ +[GtkTemplate (ui = "/com/mesonbuild/test/TestBox.ui")] +class TestBox: Gtk.Box { +} + +int main() { + return 0; +} From 1c852f0a985f2daa42ca209008eebcd7a42fb58e Mon Sep 17 00:00:00 2001 From: izimuth Date: Sun, 14 Jan 2024 09:50:07 -0800 Subject: [PATCH 536/855] Add a note for Windows users to GuiTutorial.md When compiling on Windows using MSVC, you also need to link the SDL2main.lib file. I've added a note to the GuiTutorial.md file to mention this. --- docs/markdown/GuiTutorial.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/markdown/GuiTutorial.md b/docs/markdown/GuiTutorial.md index 85930d7dc6bf..568246060c21 100644 --- a/docs/markdown/GuiTutorial.md +++ b/docs/markdown/GuiTutorial.md @@ -170,6 +170,20 @@ executable('sdlprog', 'sdlprog.c', dependencies: sdl2_dep) ``` +**NOTE:** If you're on Windows you need to include the sdl2main dependency as well; To do so you can modify the above build script like so: + +```meson +project('sdldemo', 'c', + default_options: 'default_library=static') + +sdl2_dep = dependency('sdl2') +sdl2_main_dep = dependency('sdl2main') + +executable('sdlprog', 'sdlprog.c', + win_subsystem: 'windows', + dependencies: [sdl2_dep, sdl2_main_dep]) +``` + In addition to the dependency this has a few other changes. First we specify that we want to build helper libraries statically. For simple projects like these it makes things simpler. We also need to tell From 0bfe98e7e62b62b96448c48e9d06409bbfdf8bc0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 9 Jan 2024 14:11:39 +0100 Subject: [PATCH 537/855] compilers: add c23 and gnu23 c_stds Closes: https://github.com/mesonbuild/meson/issues/12702 --- docs/markdown/Builtin-options.md | 2 +- docs/markdown/Configuring-a-build-directory.md | 2 +- mesonbuild/compilers/c.py | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index f3cbcea75d05..7cdf6e8d33d5 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -257,7 +257,7 @@ or compiler being used: | ------ | ------------- | --------------- | ----------- | | c_args | | free-form comma-separated list | C compile arguments to use | | c_link_args | | free-form comma-separated list | C link arguments to use | -| c_std | none | none, c89, c99, c11, c17, c18, c2x, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x | C language standard to use | +| c_std | none | none, c89, c99, c11, c17, c18, c2x, c23, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23 | C language standard to use | | c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | | c_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads | | cpp_args | | free-form comma-separated list | C++ compile arguments to use | diff --git a/docs/markdown/Configuring-a-build-directory.md b/docs/markdown/Configuring-a-build-directory.md index 1dcef4663c57..db6fc03ef453 100644 --- a/docs/markdown/Configuring-a-build-directory.md +++ b/docs/markdown/Configuring-a-build-directory.md @@ -61,7 +61,7 @@ a sample output for a simple project. ------ ------------- --------------- ----------- c_args [] Extra arguments passed to the C compiler c_link_args [] Extra arguments passed to the C linker - c_std c99 [none, c89, c99, c11, c17, c18, c2x, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x] C language standard to use + c_std c99 [none, c89, c99, c11, c17, c18, c2x, c23, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23] C language standard to use cpp_args [] Extra arguments passed to the C++ compiler cpp_debugstl false [true, false] STL debug mode cpp_link_args [] Extra arguments passed to the C++ linker diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 951ec8e38690..a943552e1958 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -46,7 +46,7 @@ else: CompilerMixinBase = object -_ALL_STDS = ['c89', 'c9x', 'c90', 'c99', 'c1x', 'c11', 'c17', 'c18', 'c2x'] +_ALL_STDS = ['c89', 'c9x', 'c90', 'c99', 'c1x', 'c11', 'c17', 'c18', 'c2x', 'c23'] _ALL_STDS += [f'gnu{std[1:]}' for std in _ALL_STDS] _ALL_STDS += ['iso9899:1990', 'iso9899:199409', 'iso9899:1999', 'iso9899:2011', 'iso9899:2017', 'iso9899:2018'] @@ -113,6 +113,7 @@ class _ClangCStds(CompilerMixinBase): _C17_VERSION = '>=6.0.0' _C18_VERSION = '>=8.0.0' _C2X_VERSION = '>=9.0.0' + _C23_VERSION = '>=18.0.0' def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() @@ -125,6 +126,8 @@ def get_options(self) -> 'MutableKeyedOptionDictType': stds += ['c18'] if version_compare(self.version, self._C2X_VERSION): stds += ['c2x'] + if version_compare(self.version, self._C23_VERSION): + stds += ['c23'] std_opt = opts[OptionKey('std', machine=self.for_machine, lang=self.language)] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(stds, gnu=True) @@ -253,6 +256,7 @@ class GnuCCompiler(GnuCompiler, CCompiler): _C18_VERSION = '>=8.0.0' _C2X_VERSION = '>=9.0.0' + _C23_VERSION = '>=14.0.0' _INVALID_PCH_VERSION = ">=3.4.0" def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, @@ -280,6 +284,8 @@ def get_options(self) -> 'MutableKeyedOptionDictType': stds += ['c17', 'c18'] if version_compare(self.version, self._C2X_VERSION): stds += ['c2x'] + if version_compare(self.version, self._C23_VERSION): + stds += ['c23'] key = OptionKey('std', machine=self.for_machine, lang=self.language) std_opt = opts[key] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' From 9797f7682b638427a567ab9ab354a8cc63ac1010 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Aug 2023 18:10:15 -0300 Subject: [PATCH 538/855] cmake: Fix blunt target filtering skipping GENERATED dependencies GENERATED files can be used as dependencies for other targets, so it's misguided (at best) to filter them with a blunt whitelist. However, there does exist an extension that needs to be skipped: on Windows + MSVC, CMake will by default try to generate a Visual Studio project, and there dependencies with no inputs are instead tied to a dummy .rule input file which is created by the generation step. The fileapi will still report those, so it will cause Meson to bail out when it realises there's no such file in the build tree. Fixes #11607 --- mesonbuild/cmake/interpreter.py | 10 +++++++++- .../8 custom command/subprojects/cmMod/CMakeLists.txt | 9 ++++++--- .../cmake/8 custom command/subprojects/cmMod/cmMod.cpp | 2 +- .../8 custom command/subprojects/cmMod/cpyBase.cpp.am | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 14e15b8fde90..68cbea497887 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -362,7 +362,15 @@ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, su supported += list(lang_suffixes[i]) supported = [f'.{x}' for x in supported] self.sources = [x for x in self.sources if any(x.name.endswith(y) for y in supported)] - self.generated_raw = [x for x in self.generated_raw if any(x.name.endswith(y) for y in supported)] + # Don't filter unsupported files from generated_raw because they + # can be GENERATED dependencies for other targets. + # See: https://github.com/mesonbuild/meson/issues/11607 + # However, the dummy CMake rule files for Visual Studio still + # need to be filtered out. They don't exist (because the project was + # not generated at this time) but the fileapi will still + # report them on Windows. + # See: https://stackoverflow.com/a/41816323 + self.generated_raw = [x for x in self.generated_raw if not x.name.endswith('.rule')] # Make paths relative def rel_path(x: Path, is_header: bool, is_generated: bool) -> T.Optional[Path]: diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt index 0185ddc91e97..a5da5e7d21ef 100644 --- a/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt +++ b/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt @@ -46,9 +46,12 @@ add_custom_command( DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/cpyBase.hpp.in" ) +# Slight tuning to the file extension (it's still a C++ header) +# checks that file extensions are not considered for the purposes +# of target dependencies add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyBase.hpp" - COMMAND mycpy cpyBase.hpp.something cpyBase.hpp + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyBase.txt" + COMMAND mycpy cpyBase.hpp.something cpyBase.txt DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/cpyBase.hpp.something" ) @@ -127,7 +130,7 @@ add_custom_command( ) include_directories("${CMAKE_CURRENT_BINARY_DIR}/cpyTest/some") -add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.hpp cpyNext.cpp cpyNext.hpp cpyTest.cpp cpyTest.hpp cpyTest2.hpp cpyTest3.hpp cpyTest/some/directory/cpyTest5.hpp) +add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.txt cpyNext.cpp cpyNext.hpp cpyTest.cpp cpyTest.hpp cpyTest2.hpp cpyTest3.hpp cpyTest/some/directory/cpyTest5.hpp) include(GenerateExportHeader) generate_export_header(cmModLib) diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp b/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp index a4663995a961..fceebeea3058 100644 --- a/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp +++ b/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp @@ -1,6 +1,6 @@ #include "cmMod.hpp" #include "genTest.hpp" -#include "cpyBase.hpp" +#include "cpyBase.txt" #include "cpyNext.hpp" #include "cpyTest.hpp" #include "cmModLib.hpp" diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am b/test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am index 98dd09c9cc2f..a0c716cf1485 100644 --- a/test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am +++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyBase.cpp.am @@ -1,4 +1,4 @@ -#include "cpyBase.hpp" +#include "cpyBase.txt" std::string getStrCpy() { return "Hello Copied File"; From 57b7fbb29d456b1a607adc8ab3ae3d5c9eeb7341 Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Fri, 6 Oct 2023 18:00:13 -0500 Subject: [PATCH 539/855] backend: Add rpaths for external 'cmake' deps Fixes https://github.com/mesonbuild/meson/issues/12338 --- mesonbuild/backend/backends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index b28289e8693f..85f689646d45 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -764,7 +764,7 @@ def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTar srcdir = self.environment.get_source_dir() for dep in target.external_deps: - if dep.type_name not in {'library', 'pkgconfig'}: + if dep.type_name not in {'library', 'pkgconfig', 'cmake'}: continue for libpath in dep.link_args: # For all link args that are absolute paths to a library file, add RPATH args From 76ad5fe8d387638d21258177328763f05a0e95ae Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Fri, 6 Oct 2023 18:06:41 -0500 Subject: [PATCH 540/855] backend: Add rpath for external versioned .so's On Linux many .so's are augmented with version information, e.g. libxyz.so.1.2.3. CMake will happily refer to these versioned .so's in its dependencies instead of libxyz.so (typically a symlink). Unfortunately these versioned .so's aren't recognized as libraries by the Backend's logic to produce build rpaths from library paths. Fix this by recognizing any .so extension as sufficient reason to produce a build rpath, not just if .so is the last extension. --- mesonbuild/backend/backends.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 85f689646d45..cb730de5b4f7 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -780,7 +780,11 @@ def rpaths_for_non_system_absolute_shared_libraries(self, target: build.BuildTar # Windows doesn't support rpaths, but we use this function to # emulate rpaths by setting PATH # .dll is there for mingw gcc - if os.path.splitext(libpath)[1] not in {'.dll', '.lib', '.so', '.dylib'}: + # .so's may be extended with version information, e.g. libxyz.so.1.2.3 + if not ( + os.path.splitext(libpath)[1] in {'.dll', '.lib', '.so', '.dylib'} + or re.match(r'.+\.so(\.|$)', os.path.basename(libpath)) + ): continue try: From 3a846ff409d93faf8b3c912ed3cdce6c49628f1d Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Mon, 30 Oct 2023 11:21:43 -0500 Subject: [PATCH 541/855] tests: Also test implicit rpaths from dependencies Meson will implicit rpaths when *.so/*.dll/etc. files are injected onto the link line from pkg-config and (now) cmake dependencies. Extend the "prebuilt shared" tests to test that these are added. --- .../unit/17 prebuilt shared/meson.build | 16 ++-- .../unit/17 prebuilt shared/meson_options.txt | 3 + unittests/allplatformstests.py | 92 +++++++++++++++++++ 3 files changed, 105 insertions(+), 6 deletions(-) diff --git a/test cases/unit/17 prebuilt shared/meson.build b/test cases/unit/17 prebuilt shared/meson.build index 7badcb746ce9..5107fca4f3dd 100644 --- a/test cases/unit/17 prebuilt shared/meson.build +++ b/test cases/unit/17 prebuilt shared/meson.build @@ -1,13 +1,17 @@ project('prebuilt shared library', 'c') -search_dir = get_option('search_dir') -if search_dir == 'auto' - search_dir = meson.current_source_dir() +if get_option('method') == 'find_library' + search_dir = get_option('search_dir') + if search_dir == 'auto' + search_dir = meson.current_source_dir() + endif + + cc = meson.get_compiler('c') + shlib = cc.find_library('alexandria', dirs : search_dir) +else + shlib = dependency('alexandria', method: get_option('method')) endif -cc = meson.get_compiler('c') -shlib = cc.find_library('alexandria', dirs : search_dir) - exe = executable('patron', 'patron.c', dependencies : shlib) test('visitation', exe) diff --git a/test cases/unit/17 prebuilt shared/meson_options.txt b/test cases/unit/17 prebuilt shared/meson_options.txt index 7876a6fd468a..d9d0d67c9fe5 100644 --- a/test cases/unit/17 prebuilt shared/meson_options.txt +++ b/test cases/unit/17 prebuilt shared/meson_options.txt @@ -1 +1,4 @@ +option('method', type : 'combo', + choices : ['find_library', 'pkg-config', 'cmake'], + value : 'find_library') option('search_dir', type : 'string', value : 'auto') diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index c15519874113..bfd0b18561dd 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1664,6 +1664,14 @@ def detect_prebuild_env(self): shared_suffix = 'so' return (cc, stlinker, object_suffix, shared_suffix) + def detect_prebuild_env_versioned(self): + (cc, stlinker, object_suffix, shared_suffix) = self.detect_prebuild_env() + shared_suffixes = [shared_suffix] + if shared_suffix == 'so': + # .so may have version information integrated into the filename + shared_suffixes += ['so.1', 'so.1.2.3', '1.so', '1.so.2.3'] + return (cc, stlinker, object_suffix, shared_suffixes) + def pbcompile(self, compiler, source, objectfile, extra_args=None): cmd = compiler.get_exelist() extra_args = extra_args or [] @@ -1787,6 +1795,90 @@ def test_prebuilt_shared_lib_rpath(self) -> None: self.build() self.run_tests() + @skipIfNoPkgconfig + def test_prebuilt_shared_lib_pkg_config(self) -> None: + (cc, _, object_suffix, shared_suffixes) = self.detect_prebuild_env_versioned() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + for shared_suffix in shared_suffixes: + with tempfile.TemporaryDirectory() as d: + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(d, 'alexandria.' + object_suffix) + impfile = os.path.join(d, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(d, 'alexandria.' + shared_suffix) + linkfile = impfile # MSVC links against the *.lib instead of the *.dll + elif is_cygwin(): + shlibfile = os.path.join(d, 'cygalexandria.' + shared_suffix) + linkfile = shlibfile + else: + shlibfile = os.path.join(d, 'libalexandria.' + shared_suffix) + linkfile = shlibfile + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(d): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + with open(os.path.join(d, 'alexandria.pc'), 'w', + encoding='utf-8') as f: + f.write(textwrap.dedent(''' + Name: alexandria + Description: alexandria + Version: 1.0.0 + Libs: {} + ''').format( + Path(linkfile).as_posix().replace(' ', r'\ '), + )) + + # Run the test + self.init(tdir, override_envvars={'PKG_CONFIG_PATH': d}, + extra_args=['-Dmethod=pkg-config']) + self.build() + self.run_tests() + + self.wipe() + + @skip_if_no_cmake + def test_prebuilt_shared_lib_cmake(self) -> None: + (cc, _, object_suffix, shared_suffixes) = self.detect_prebuild_env_versioned() + tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') + for shared_suffix in shared_suffixes: + with tempfile.TemporaryDirectory() as d: + source = os.path.join(tdir, 'alexandria.c') + objectfile = os.path.join(d, 'alexandria.' + object_suffix) + impfile = os.path.join(d, 'alexandria.lib') + if cc.get_argument_syntax() == 'msvc': + shlibfile = os.path.join(d, 'alexandria.' + shared_suffix) + linkfile = impfile # MSVC links against the *.lib instead of the *.dll + elif is_cygwin(): + shlibfile = os.path.join(d, 'cygalexandria.' + shared_suffix) + linkfile = shlibfile + else: + shlibfile = os.path.join(d, 'libalexandria.' + shared_suffix) + linkfile = shlibfile + # Ensure MSVC extra files end up in the directory that gets deleted + # at the end + with chdir(d): + self.build_shared_lib(cc, source, objectfile, shlibfile, impfile) + + with open(os.path.join(d, 'alexandriaConfig.cmake'), 'w', + encoding='utf-8') as f: + f.write(textwrap.dedent(''' + set(alexandria_FOUND ON) + set(alexandria_LIBRARIES "{}") + set(alexandria_INCLUDE_DIRS "{}") + ''').format( + re.sub(r'([\\"])', r'\\\1', linkfile), + re.sub(r'([\\"])', r'\\\1', tdir), + )) + + # Run the test + self.init(tdir, override_envvars={'CMAKE_PREFIX_PATH': d}, + extra_args=['-Dmethod=cmake']) + self.build() + self.run_tests() + + self.wipe() + def test_prebuilt_shared_lib_rpath_same_prefix(self) -> None: (cc, _, object_suffix, shared_suffix) = self.detect_prebuild_env() orig_tdir = os.path.join(self.unit_test_dir, '17 prebuilt shared') From 95cc34b3420b0ba7ece35408b2b5cb688ac2ffbc Mon Sep 17 00:00:00 2001 From: Roger Sanders Date: Fri, 29 Dec 2023 10:32:09 +1100 Subject: [PATCH 542/855] Improve project naming and build configuration in genvslite projects This change fixes two usability issues with the genvslite project generation. Unlike when using the full VS backend, under genvslite the ProjectName property wasn't being set for generated projects. This means projects end up being named according to the project files, which includes suffixes like "@exe" in the solution, which is undesirable. This change adds the ProjectName field in for genvslite projects, to keep the naming consistent with projects under the VS backend. Additionally, previously under genvslite, no projects were set to build under any solution configuration by default. This is inconvenient, as the user has to manually edit the build settings for each solution configuration before they can compile at the solution level. There was a note in the code to do something about this. This change enables compilation at the solution level for the default startup project in the solution, so the user can now just press F5 to build the solution and run the default startup project, as they would typically expect. --- mesonbuild/backend/vs2010backend.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 4396b3c5665d..7bf80d9e6c6c 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -480,7 +480,7 @@ def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> Non (self.environment.coredata.regen_guid, buildtype, self.platform, buildtype, self.platform)) # Create the solution configuration - for p in projlist: + for project_index, p in enumerate(projlist): if p[3] is MachineChoice.BUILD: config_platform = self.build_platform else: @@ -493,11 +493,11 @@ def generate_solution(self, sln_filename: str, projlist: T.List[Project]) -> Non # If we're building the solution with Visual Studio's build system, enable building of buildable # projects. However, if we're building with meson (via --genvslite), then, since each project's # 'build' action just ends up doing the same 'meson compile ...' we don't want the 'solution build' - # repeatedly going off and doing the same 'meson compile ...' multiple times over, so we just - # leave it up to the user to select or build just one project. - # FIXME: Would be slightly nicer if we could enable building of just one top level target/project, - # but not sure how to identify that. - if not self.gen_lite and \ + # repeatedly going off and doing the same 'meson compile ...' multiple times over, so we default + # to building the startup project, which is the first listed project in the solution file by + # default for Visual Studio. The user is free to change this afterwards, but this provides a + # sensible default. + if (not self.gen_lite or project_index == 0) and \ p[0] in default_projlist and \ not isinstance(self.build.targets[p[0]], build.RunTarget): ofile.write('\t\t{%s}.%s|%s.Build.0 = %s|%s\n' % @@ -650,6 +650,10 @@ def create_basic_project(self, target_name, *, # This is extremely unhelpful and misleading since the v14x build tools ARE installed. ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.props') + # This attribute makes sure project names are displayed as expected in solution files even when their project file names differ + pname = ET.SubElement(globalgroup, 'ProjectName') + pname.text = target_name + if not self.gen_lite: # Plenty of elements aren't necessary for 'makefile'-style project that just redirects to meson builds # XXX Wasn't here before for anything but gen_vcxproj , but seems fine? ns = ET.SubElement(globalgroup, 'RootNamespace') @@ -657,8 +661,6 @@ def create_basic_project(self, target_name, *, p = ET.SubElement(globalgroup, 'Platform') p.text = target_platform - pname = ET.SubElement(globalgroup, 'ProjectName') - pname.text = target_name if self.windows_target_platform_version: ET.SubElement(globalgroup, 'WindowsTargetPlatformVersion').text = self.windows_target_platform_version ET.SubElement(globalgroup, 'UseMultiToolTask').text = 'true' From bd3f1b2e0e70ef16dfa4f441686003212440a09b Mon Sep 17 00:00:00 2001 From: Peter Urban Date: Wed, 10 Jan 2024 00:32:29 +0100 Subject: [PATCH 543/855] fix openmp dependency for clang-cl - see https://github.com/mesonbuild/meson/issues/5298 --- mesonbuild/dependencies/misc.py | 14 ++++++++++++-- test cases/common/184 openmp/meson.build | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index bec1466e9053..b255813b60b9 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -103,6 +103,7 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No self.is_found = True self.compile_args = self.link_args = self.clib_compiler.openmp_flags() return + try: openmp_date = self.clib_compiler.get_define( '_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0] @@ -119,13 +120,22 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No if openmp_date == '_OPENMP': 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: if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: self.is_found = True - self.compile_args = self.clib_compiler.openmp_flags() - self.link_args = self.clib_compiler.openmp_link_flags() + self.compile_args.extend(self.clib_compiler.openmp_flags()) + self.link_args.extend(self.clib_compiler.openmp_link_flags()) break if not self.is_found: mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.') diff --git a/test cases/common/184 openmp/meson.build b/test cases/common/184 openmp/meson.build index a1154c22c0c4..4cbe80616970 100644 --- a/test cases/common/184 openmp/meson.build +++ b/test cases/common/184 openmp/meson.build @@ -10,8 +10,8 @@ endif if cc.get_id() == 'msvc' and cc.version().version_compare('<17') error('MESON_SKIP_TEST msvc is too old to support OpenMP.') endif -if cc.get_id() == 'clang-cl' - error('MESON_SKIP_TEST clang-cl does not support OpenMP.') +if cc.get_id() == 'clang-cl' and cc.version().version_compare('<10.0.0') + error('MESON_SKIP_TEST clang-cl is too old to support OpenMP.') endif if cc.get_id() == 'clang' and host_machine.system() == 'windows' error('MESON_SKIP_TEST Windows clang does not support OpenMP.') From 1ca2c74d16c3f5987f686e358b58ce5d2253ce9b Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 15 Dec 2023 19:06:13 +0100 Subject: [PATCH 544/855] rust: fix linking static executables For the same reason as for static libraries, we have to use -l when generating static executables. Fixes: https://github.com/mesonbuild/meson/issues/12585 --- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/compilers/rust.py | 7 +++++++ test cases/rust/23 crt-static/lib.c | 6 ++++++ test cases/rust/23 crt-static/main.rs | 9 +++++++++ test cases/rust/23 crt-static/meson.build | 9 +++++++++ test cases/rust/23 crt-static/test.json | 5 +++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test cases/rust/23 crt-static/lib.c create mode 100644 test cases/rust/23 crt-static/main.rs create mode 100644 test cases/rust/23 crt-static/meson.build create mode 100644 test cases/rust/23 crt-static/test.json diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3143dff28c1b..29298027184a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1998,7 +1998,7 @@ def _link_library(libname: str, static: bool, bundle: bool = False): # "-l" argument and does not rely on platform specific dynamic linker. lib = self.get_target_filename_for_linking(d) link_whole = d in target.link_whole_targets - if isinstance(target, build.StaticLibrary): + if isinstance(target, build.StaticLibrary) or (isinstance(target, build.Executable) and rustc.get_crt_static()): static = isinstance(d, build.StaticLibrary) libname = os.path.basename(lib) if verbatim else d.name _link_library(libname, static, bundle=link_whole) diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index e10cb4cf3d5f..89b913a58de1 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -3,6 +3,7 @@ from __future__ import annotations +import functools import subprocess, os.path import textwrap import re @@ -118,6 +119,12 @@ def get_sysroot(self) -> str: p, stdo, stde = Popen_safe_logged(cmd) return stdo.split('\n', maxsplit=1)[0] + @functools.lru_cache(maxsize=None) + def get_crt_static(self) -> bool: + cmd = self.get_exelist(ccache=False) + ['--print', 'cfg'] + p, stdo, stde = Popen_safe_logged(cmd) + return bool(re.search('^target_feature="crt-static"$', stdo, re.MULTILINE)) + def get_debug_args(self, is_debug: bool) -> T.List[str]: return clike_debug_args[is_debug] diff --git a/test cases/rust/23 crt-static/lib.c b/test cases/rust/23 crt-static/lib.c new file mode 100644 index 000000000000..f18e504a30eb --- /dev/null +++ b/test cases/rust/23 crt-static/lib.c @@ -0,0 +1,6 @@ +#include + +void test_function(void) +{ + puts("Hello, world!"); +} diff --git a/test cases/rust/23 crt-static/main.rs b/test cases/rust/23 crt-static/main.rs new file mode 100644 index 000000000000..d527ed970dd6 --- /dev/null +++ b/test cases/rust/23 crt-static/main.rs @@ -0,0 +1,9 @@ +extern "C" { + fn test_function(); +} + +pub fn main() { + unsafe { + test_function(); + } +} diff --git a/test cases/rust/23 crt-static/meson.build b/test cases/rust/23 crt-static/meson.build new file mode 100644 index 000000000000..dcdfc36e2c20 --- /dev/null +++ b/test cases/rust/23 crt-static/meson.build @@ -0,0 +1,9 @@ +project('rustprog', 'c') + +if not add_languages('rust', required : false) + error('MESON_SKIP_TEST crt-static doesn\'t work') +endif + +c_lib = static_library('lib', 'lib.c') + +executable('main', 'main.rs', link_with : c_lib) diff --git a/test cases/rust/23 crt-static/test.json b/test cases/rust/23 crt-static/test.json new file mode 100644 index 000000000000..2d94709850f2 --- /dev/null +++ b/test cases/rust/23 crt-static/test.json @@ -0,0 +1,5 @@ +{ + "env": { + "RUSTC": "rustc -C target-feature=+crt-static" + } +} From 92f638e1f9a9306a4296631cbc8f97c253e6ba88 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 13 Jan 2024 17:17:43 +0500 Subject: [PATCH 545/855] compiler.preprocess: add depends kwarg This patch adds 'depends' keyword to compiler.preprocess(). It allows to execute other targets before doing the preprocessing. Test-case is added to demonstrate that functionality: it generates the header before preprocessing the C source that uses that generated header. Thanks to @bruchar1 for getting this patch to work. --- docs/markdown/snippets/preprocess-depends.md | 5 +++++ docs/yaml/objects/compiler.yaml | 7 +++++++ mesonbuild/backend/backends.py | 11 ++++++++--- mesonbuild/backend/ninjabackend.py | 2 ++ mesonbuild/build.py | 13 ++++++++++--- mesonbuild/interpreter/compiler.py | 11 ++++++++++- test cases/common/259 preprocess/{foo.h => foo.x} | 0 test cases/common/259 preprocess/meson.build | 7 ++++++- 8 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 docs/markdown/snippets/preprocess-depends.md rename test cases/common/259 preprocess/{foo.h => foo.x} (100%) diff --git a/docs/markdown/snippets/preprocess-depends.md b/docs/markdown/snippets/preprocess-depends.md new file mode 100644 index 000000000000..531246462c1b --- /dev/null +++ b/docs/markdown/snippets/preprocess-depends.md @@ -0,0 +1,5 @@ +## `depends` kwarg now supported by compiler.preprocess() + +It is now possible to specify the dependent targets with `depends:` +for compiler.preprocess(). These targets should be built before the +preprocessing starts. diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index 239a9bcfd801..db2ff05fdf97 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -681,3 +681,10 @@ methods: type: dep | list[dep] description: Additionally dependencies required. since: 1.1.0 + depends: + type: list[build_tgt | custom_tgt] + description: | + Specifies that this target depends on the specified + target(s). These targets should be built before starting + to preprocess an input. + since: 1.4.0 diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index cb730de5b4f7..e8eaa5e61d86 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -2012,7 +2012,9 @@ def get_devenv(self) -> mesonlib.EnvironmentVariables: def compiler_to_generator(self, target: build.BuildTarget, compiler: 'Compiler', sources: _ALL_SOURCES_TYPE, - output_templ: str) -> build.GeneratedList: + output_templ: str, + depends: T.Optional[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = None, + ) -> build.GeneratedList: ''' Some backends don't support custom compilers. This is a convenience method to convert a Compiler to a Generator. @@ -2027,9 +2029,12 @@ def compiler_to_generator(self, target: build.BuildTarget, commands += compiler.get_compile_only_args() + ['@INPUT@'] commands += self.get_source_dir_include_args(target, compiler) commands += self.get_build_dir_include_args(target, compiler) - generator = build.Generator(exe, args + commands.to_native(), [output_templ], depfile='@PLAINNAME@.d') + generator = build.Generator(exe, args + commands.to_native(), + [output_templ], depfile='@PLAINNAME@.d', + depends=depends) return generator.process_files(sources, self.interpreter) def compile_target_to_generator(self, target: build.CompileTarget) -> build.GeneratedList: all_sources = T.cast('_ALL_SOURCES_TYPE', target.sources) + T.cast('_ALL_SOURCES_TYPE', target.generated) - return self.compiler_to_generator(target, target.compiler, all_sources, target.output_templ) + return self.compiler_to_generator(target, target.compiler, all_sources, + target.output_templ, target.depends) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 29298027184a..782b264acc90 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -718,6 +718,8 @@ def get_generated_headers(self, target): for dep in itertools.chain(target.link_targets, target.link_whole_targets): if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): header_deps += self.get_generated_headers(dep) + if isinstance(target, build.CompileTarget): + header_deps.extend(target.get_generated_headers()) target.cached_generated_headers = header_deps return header_deps diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 51c4834320e2..324721798b64 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1763,12 +1763,12 @@ def __init__(self, exe: T.Union['Executable', programs.ExternalProgram], *, depfile: T.Optional[str] = None, capture: bool = False, - depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget']]] = None, + depends: T.Optional[T.List[T.Union[BuildTarget, 'CustomTarget', 'CustomTargetIndex']]] = None, name: str = 'Generator'): self.exe = exe self.depfile = depfile self.capture = capture - self.depends: T.List[T.Union[BuildTarget, 'CustomTarget']] = depends or [] + self.depends: T.List[T.Union[BuildTarget, 'CustomTarget', 'CustomTargetIndex']] = depends or [] self.arglist = arguments self.outputs = output self.name = name @@ -2763,7 +2763,8 @@ def __init__(self, backend: Backend, compile_args: T.List[str], include_directories: T.List[IncludeDirs], - dependencies: T.List[dependencies.Dependency]): + dependencies: T.List[dependencies.Dependency], + depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]): compilers = {compiler.get_language(): compiler} kwargs = { 'build_by_default': False, @@ -2778,6 +2779,7 @@ def __init__(self, self.output_templ = output_templ self.outputs = [] self.sources_map: T.Dict[File, str] = {} + self.depends = list(depends or []) for f in self.sources: self._add_output(f) for gensrc in self.generated: @@ -2799,6 +2801,11 @@ def _add_output(self, f: File) -> None: self.outputs.append(o) self.sources_map[f] = o + def get_generated_headers(self) -> T.List[File]: + gen_headers: T.List[File] = [] + for dep in self.depends: + gen_headers += [File(True, dep.subdir, o) for o in dep.get_outputs()] + return gen_headers class RunTarget(Target, CommandBase): diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index ad6eb4b89c63..f31952867038 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -96,6 +96,7 @@ class PreprocessKW(TypedDict): compile_args: T.List[str] include_directories: T.List[build.IncludeDirs] dependencies: T.List[dependencies.Dependency] + depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]] class _TestMode(enum.Enum): @@ -148,6 +149,12 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: listify=True, default=[], ) +_DEPENDS_KW: KwargInfo[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = KwargInfo( + 'depends', + ContainerTypeInfo(list, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)), + listify=True, + default=[], +) _INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo( 'include_directories', ContainerTypeInfo(list, build.IncludeDirs), @@ -853,6 +860,7 @@ def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwa KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]), _INCLUDE_DIRS_KW, _DEPENDENCIES_KW.evolve(since='1.1.0'), + _DEPENDS_KW.evolve(since='1.4.0'), ) def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]: compiler = self.compiler.get_preprocessor() @@ -878,7 +886,8 @@ def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwar self.interpreter.backend, kwargs['compile_args'], kwargs['include_directories'], - kwargs['dependencies']) + kwargs['dependencies'], + kwargs['depends']) self.interpreter.add_target(tg.name, tg) # Expose this target as list of its outputs, so user can pass them to # other targets, list outputs, etc. diff --git a/test cases/common/259 preprocess/foo.h b/test cases/common/259 preprocess/foo.x similarity index 100% rename from test cases/common/259 preprocess/foo.h rename to test cases/common/259 preprocess/foo.x diff --git a/test cases/common/259 preprocess/meson.build b/test cases/common/259 preprocess/meson.build index 10e8b0984c2d..40168f95d8e5 100644 --- a/test cases/common/259 preprocess/meson.build +++ b/test cases/common/259 preprocess/meson.build @@ -13,9 +13,14 @@ bar_x = custom_target( capture: true, ) +foo_h = import('fs').copyfile('foo.x', 'foo.h') + dep = declare_dependency(compile_args: '-DPLOP=0') -pp_files = cc.preprocess('foo.c', bar_x, 'math.c', output: '@PLAINNAME@.c', dependencies: dep) +pp_files = cc.preprocess('foo.c', bar_x, 'math.c', + output: '@PLAINNAME@.c', + dependencies: dep, + depends: foo_h) foreach f : pp_files message(f.full_path()) From 85cfc1fafcda047fa497d1d6219a8c742523b5a6 Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 18 Jan 2024 07:03:17 +0000 Subject: [PATCH 546/855] Compilers: pass -Werror to the linker with b_lto With LTO, the linker will re-execute the compiler and various warnings may be emitted. We must therefore pass -Werror to the linker as well when -Werror is enabled to capture these. This is only required / useful with LTO. Closes: https://github.com/mesonbuild/meson/issues/7360 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/compilers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index f1a2b7376413..fbe30f6f0b7b 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -324,6 +324,9 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', args: T.List[str] = [] try: if options[OptionKey('b_lto')].value: + if options[OptionKey('werror')].value: + args.extend(linker.get_werror_args()) + thinlto_cache_dir = None if get_option_value(options, OptionKey('b_thinlto_cache'), False): thinlto_cache_dir = get_option_value(options, OptionKey('b_thinlto_cache_dir'), '') From 33527630f1bd0e51093044016557cb44e7bb6547 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Wed, 17 Jan 2024 17:04:45 +0100 Subject: [PATCH 547/855] linkers_detect: detect xtools (Apple ld64 derivative) xtools is in use on Gentoo Prefix x86_64 and ppc based Darwin installs. Pick it up as a valid linker. Since xtools is answering with a version to --version, as opposed to ld64, detection of xtools in the ld64 handling block is not possible, since --version already succeeded. Bug: https://bugs.gentoo.org/868516 Bug: https://github.com/mesonbuild/meson/issues/10805 Signed-off-by: Fabian Groffen Signed-off-by: Eli Schwartz --- mesonbuild/linkers/detect.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 918f2e63426b..1bce413f4f52 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -174,6 +174,11 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty v = search_version(o) linker = linkers.LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + # detect xtools first, bug #10805 + elif 'xtools-' in o.split('\n', maxsplit=1)[0]: + xtools = o.split(' ', maxsplit=1)[0] + v = xtools.split('-', maxsplit=2)[1] + linker = linkers.AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) # First might be apple clang, second is for real gcc, the third is icc. # Note that "ld: unknown option: " sometimes instead is "ld: unknown options:". elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option' in e: From 760d8d50b67ac2cf57ca6a450079885072b7a068 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sat, 20 Jan 2024 20:36:48 -0500 Subject: [PATCH 548/855] docs: fix another regression in having functional docs In commit 83a973ca04cf53dd98ff487b4273155b82cf554a a bunch of strange changes were made, that were not even tested. Make sure people get the correct command for running coverage targets. --- docs/markdown/Commands.md | 2 +- docs/markdown/howtox.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index 3fcdedd03ca3..831cba85d489 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -114,7 +114,7 @@ meson compile foo:shared_library foo:static_library bar Produce a coverage html report (if available): ``` -meson compile coverage-html +ninja coverage-html ``` ### dist diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index 79a87b7c04af..54831a3f7564 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -174,7 +174,7 @@ Then issue the following commands. ```console $ meson compile $ meson test -$ meson compile coverage-html (or coverage-xml) +$ ninja coverage-html (or coverage-xml) ``` The coverage report can be found in the meson-logs subdirectory. From 2936be7e29cc002b9338f74ed74fd1399a923f7f Mon Sep 17 00:00:00 2001 From: andy5995 Date: Wed, 24 Jan 2024 02:24:29 -0600 Subject: [PATCH 549/855] docs: Add NetPanzer to User.md --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 7ab211644bcd..6edbdf560b87 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -116,6 +116,7 @@ format files - [mrsh](https://github.com/emersion/mrsh), a minimal POSIX shell - [Nautilus](https://gitlab.gnome.org/GNOME/nautilus), the GNOME file manager - [Nemo](https://github.com/linuxmint/nemo), the file manager for the Cinnamon desktop environment + - [NetPanzer](https://github.com/netpanzer/netpanzer), a 2D online multiplayer tactical warfare game designed for fast action combat - [nvme-cli](https://github.com/linux-nvme/nvme-cli), NVMe management command line interface - [OcherBook](https://github.com/ccoffing/OcherBook), an open source book reader for Kobo devices - [oomd](https://github.com/facebookincubator/oomd), a userspace Out-Of-Memory (OOM) killer for Linux systems From b2ddcbad0cf3a3e546087ea540998266a13719be Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 24 Jan 2024 22:35:32 -0500 Subject: [PATCH 550/855] docs: add a technically unneeded "setup" verb to some invocations `meson -Dxxx=yyy` is technically accurate, but does cause confusion at least some of the time. --- docs/markdown/howtox.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index 54831a3f7564..8b56c807e592 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -166,7 +166,7 @@ execute permissions, the generated file will have them too. First initialize the build directory with this command. ```console -$ meson -Db_coverage=true +$ meson setup -Db_coverage=true ``` Then issue the following commands. @@ -202,7 +202,7 @@ sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html). Meson has native support for these with the `b_sanitize` option. ```console -$ meson -Db_sanitize=address +$ meson setup -Db_sanitize=address ``` After this you just compile your code and run the test suite. Address From 5e76e2a7ff9e245502f94f7c426dbee28243c864 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Jan 2024 00:15:28 -0500 Subject: [PATCH 551/855] Add missing FeatureNew for meson.add_dist_script Per the docs, it is available since 0.48.0. Notify about this at runtime too. Fixes #12773 --- mesonbuild/interpreter/mesonmain.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 66029a01999c..4d1f427da210 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -188,6 +188,7 @@ def add_postconf_script_method( varargs=(str, mesonlib.File, ExternalProgram) ) @noKwargs + @FeatureNew('meson.add_dist_script', '0.48.0') def add_dist_script_method( self, args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram], From 6bd4f7c10edb8f7018ed921b1baa346eb44a5c5b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 22 Jan 2024 14:18:45 -0800 Subject: [PATCH 552/855] modules/sourceset: remove unused attributes from SourceSetImpl --- mesonbuild/modules/sourceset.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py index c11fef699c2f..abd2e4499d11 100644 --- a/mesonbuild/modules/sourceset.py +++ b/mesonbuild/modules/sourceset.py @@ -84,9 +84,6 @@ class SourceSetImpl(SourceSet, MutableModuleObject): def __init__(self, interpreter: Interpreter): super().__init__() self.rules: T.List[SourceSetRule] = [] - self.subproject = interpreter.subproject - self.environment = interpreter.environment - self.subdir = interpreter.subdir self.frozen = False self.methods.update({ 'add': self.add_method, From 37883e7d5fe25f9abcc93f100655b61a0e23f8e5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 22 Jan 2024 14:36:46 -0800 Subject: [PATCH 553/855] modules/fs: use ModuleState object instead of Interpreter when possible --- mesonbuild/modules/fs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 3657be08c4a6..d3f37dcb93ab 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -69,7 +69,7 @@ def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: make an absolute path from a relative path, WITHOUT resolving symlinks """ if isinstance(arg, File): - return Path(arg.absolute_path(state.source_root, self.interpreter.environment.get_build_dir())) + return Path(arg.absolute_path(state.source_root, state.environment.get_build_dir())) return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser() def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: @@ -228,9 +228,9 @@ def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'Rea """ path = args[0] encoding = kwargs['encoding'] - src_dir = self.interpreter.environment.source_dir - sub_dir = self.interpreter.subdir - build_dir = self.interpreter.environment.get_build_dir() + src_dir = state.environment.source_dir + sub_dir = state.subdir + build_dir = state.environment.get_build_dir() if isinstance(path, File): if path.is_built: From adc8d6bae4010c06fc3b779b8d84c1c5b4a910ad Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 22 Jan 2024 15:49:44 -0800 Subject: [PATCH 554/855] interpreter: replace mock keyword argument with unittest.mock Python provides some nifty tools for mocking, without relying on altering running code. We should use these to simplify the actual run paths and move the complicated logic into tests. --- mesonbuild/interpreter/interpreter.py | 11 ++++------- unittests/datatests.py | 15 +++++++++++---- unittests/internaltests.py | 5 ++++- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index b736aea415ce..bee64aa94ba4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -266,7 +266,6 @@ def __init__( subdir: str = '', subproject_dir: str = 'subprojects', default_project_options: T.Optional[T.Dict[OptionKey, str]] = None, - mock: bool = False, ast: T.Optional[mparser.CodeBlockNode] = None, is_translated: bool = False, relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None, @@ -285,12 +284,11 @@ def __init__( self.subproject_directory_name = subdir.split(os.path.sep)[-1] self.subproject_dir = subproject_dir self.relaxations = relaxations or set() - if not mock and ast is None: + if ast is None: self.load_root_meson_file() - self.sanity_check_ast() - elif ast is not None: + else: self.ast = ast - self.sanity_check_ast() + self.sanity_check_ast() self.builtin.update({'meson': MesonMain(self.build, self)}) self.generators: T.List[build.Generator] = [] self.processed_buildfiles: T.Set[str] = set() @@ -319,8 +317,7 @@ def __init__( build_filename = os.path.join(self.subdir, environment.build_filename) if not is_translated: self.build_def_files.add(build_filename) - if not mock: - self.parse_project() + self.parse_project() self._redetect_machines() def __getnewargs_ex__(self) -> T.Tuple[T.Tuple[object], T.Dict[str, object]]: diff --git a/unittests/datatests.py b/unittests/datatests.py index ae32a949130f..4f9d52032fa4 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -5,6 +5,7 @@ import unittest from itertools import chain from pathlib import Path +from unittest import mock import mesonbuild.mlog import mesonbuild.depfile @@ -208,7 +209,10 @@ def test_modules_in_navbar(self): name = name.replace('_', '-') self.assertIn(name, html) - @unittest.mock.patch.dict(os.environ) + @mock.patch.dict(os.environ) + @mock.patch.object(Interpreter, 'load_root_meson_file', mock.Mock(return_value=None)) + @mock.patch.object(Interpreter, 'sanity_check_ast', mock.Mock(return_value=None)) + @mock.patch.object(Interpreter, 'parse_project', mock.Mock(return_value=None)) def test_vim_syntax_highlighting(self): ''' Ensure that vim syntax highlighting files were updated for new @@ -217,13 +221,16 @@ def test_vim_syntax_highlighting(self): # Disable unit test specific syntax del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] env = get_fake_env() - interp = Interpreter(FakeBuild(env), mock=True) + interp = Interpreter(FakeBuild(env)) with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f: res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE) defined = set([a.strip() for a in res.group().split('\\')][1:]) self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys()))) - @unittest.mock.patch.dict(os.environ) + @mock.patch.dict(os.environ) + @mock.patch.object(Interpreter, 'load_root_meson_file', mock.Mock(return_value=None)) + @mock.patch.object(Interpreter, 'sanity_check_ast', mock.Mock(return_value=None)) + @mock.patch.object(Interpreter, 'parse_project', mock.Mock(return_value=None)) def test_all_functions_defined_in_ast_interpreter(self): ''' Ensure that the all functions defined in the Interpreter are also defined @@ -232,6 +239,6 @@ def test_all_functions_defined_in_ast_interpreter(self): # Disable unit test specific syntax del os.environ['MESON_RUNNING_IN_PROJECT_TESTS'] env = get_fake_env() - interp = Interpreter(FakeBuild(env), mock=True) + interp = Interpreter(FakeBuild(env)) astint = AstInterpreter('.', '', '') self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys())) diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 945faa18b209..fd843c88c5db 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1662,13 +1662,16 @@ def mock_trial(value: str) -> T.Iterable[None]: actual = mesonbuild.environment.detect_cpu({}) self.assertEqual(actual, expected) + @mock.patch('mesonbuild.interpreter.Interpreter.load_root_meson_file', mock.Mock(return_value=None)) + @mock.patch('mesonbuild.interpreter.Interpreter.sanity_check_ast', mock.Mock(return_value=None)) + @mock.patch('mesonbuild.interpreter.Interpreter.parse_project', mock.Mock(return_value=None)) def test_interpreter_unpicklable(self) -> None: build = mock.Mock() build.environment = mock.Mock() build.environment.get_source_dir = mock.Mock(return_value='') with mock.patch('mesonbuild.interpreter.Interpreter._redetect_machines', mock.Mock()), \ self.assertRaises(mesonbuild.mesonlib.MesonBugException): - i = mesonbuild.interpreter.Interpreter(build, mock=True) + i = mesonbuild.interpreter.Interpreter(build) pickle.dumps(i) def test_major_versions_differ(self) -> None: From a9f9f034905459bed628d886c3315ded162a9789 Mon Sep 17 00:00:00 2001 From: Sune Vuorela Date: Thu, 25 Jan 2024 16:49:48 +0100 Subject: [PATCH 555/855] docs: Use common conventions for shared libs Use common conventions for documentation of shared library version and soversion. In general, the numeric version part is expected to be first component of version, so suggest this in the example code. --- docs/markdown/Build-targets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Build-targets.md b/docs/markdown/Build-targets.md index 780595caee16..a2f9b3291a5a 100644 --- a/docs/markdown/Build-targets.md +++ b/docs/markdown/Build-targets.md @@ -36,7 +36,7 @@ ignored if the library is configured as static at the compile time. ```meson project('shared lib', 'c') -library('mylib', 'source.c', version : '1.2.3', soversion : '0') +library('mylib', 'source.c', version : '1.2.3', soversion : '1') ``` It is common to build a library and then an executable that links From d7bf365acdadf6bb5a456bbe405132cd17c3e5af Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 9 Jan 2024 20:37:15 -0500 Subject: [PATCH 556/855] Fix compiler.preprocess compile_args not used As described in https://github.com/mesonbuild/meson/issues/12715#issuecomment-1883448780, the compiler.preprocess function ignores compile_args. This should fix it in both ninja and visualstudio backends. --- mesonbuild/backend/backends.py | 3 +++ mesonbuild/build.py | 2 +- mesonbuild/interpreter/compiler.py | 3 ++- test cases/common/259 preprocess/bar.c | 2 +- test cases/common/259 preprocess/meson.build | 4 +++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index e8eaa5e61d86..441a1eca5ec0 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -2029,6 +2029,9 @@ def compiler_to_generator(self, target: build.BuildTarget, commands += compiler.get_compile_only_args() + ['@INPUT@'] commands += self.get_source_dir_include_args(target, compiler) commands += self.get_build_dir_include_args(target, compiler) + # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these + # near the end since these are supposed to override everything else. + commands += self.escape_extra_args(target.get_extra_args(compiler.get_language())) generator = build.Generator(exe, args + commands.to_native(), [output_templ], depfile='@PLAINNAME@.d', depends=depends) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 324721798b64..934e7c1f01ab 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2768,7 +2768,7 @@ def __init__(self, compilers = {compiler.get_language(): compiler} kwargs = { 'build_by_default': False, - f'{compiler.language}_args': compile_args, + 'language_args': {compiler.language: compile_args}, 'include_directories': include_directories, 'dependencies': dependencies, } diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index f31952867038..0cd6aecf38aa 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -18,7 +18,7 @@ from ..compilers import SUFFIX_TO_LANG from ..compilers.compilers import CompileCheckMode from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs, - FeatureNew, disablerIfNotFound, + FeatureNew, FeatureNewKwargs, disablerIfNotFound, InterpreterException) from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args from ..mesonlib import OptionKey @@ -853,6 +853,7 @@ def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwa return self.compiler.get_argument_syntax() @FeatureNew('compiler.preprocess', '0.64.0') + @FeatureNewKwargs('compiler.preprocess', '1.3.2', ['compile_args'], extra_message='compile_args were ignored before this version') @typed_pos_args('compiler.preprocess', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList), min_varargs=1) @typed_kwargs( 'compiler.preprocess', diff --git a/test cases/common/259 preprocess/bar.c b/test cases/common/259 preprocess/bar.c index 0d961e6754ae..598abcab0c94 100644 --- a/test cases/common/259 preprocess/bar.c +++ b/test cases/common/259 preprocess/bar.c @@ -1,3 +1,3 @@ int @BAR@(void) { - return BAR + PLOP; + return BAR + PLOP + BAZ; } diff --git a/test cases/common/259 preprocess/meson.build b/test cases/common/259 preprocess/meson.build index 40168f95d8e5..2ca5bed594d0 100644 --- a/test cases/common/259 preprocess/meson.build +++ b/test cases/common/259 preprocess/meson.build @@ -20,7 +20,9 @@ dep = declare_dependency(compile_args: '-DPLOP=0') pp_files = cc.preprocess('foo.c', bar_x, 'math.c', output: '@PLAINNAME@.c', dependencies: dep, - depends: foo_h) + depends: foo_h, + compile_args: ['-DBAZ=0'], +) foreach f : pp_files message(f.full_path()) From d2740cf0d1ce049bb77da24e0a620292b7ff424d Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Fri, 28 Jul 2023 10:02:50 -0500 Subject: [PATCH 557/855] xcode: Autodetect host machine's CPU architecture Currently, the backend has "x86_64" hardcoded as the architecture, which breaks cross compiling and compiling normally on arm64. Fix this by setting it to the host machine's CPU architecture instead. --- mesonbuild/backend/xcodebackend.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 6cb7f3ff0f88..989b2bf9a1d6 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -195,6 +195,9 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.regen_dependency_id = self.gen_id() self.top_level_dict = PbxDict() self.generator_outputs = {} + self.arch = self.build.environment.machines.host.cpu + if self.arch == 'aarch64': + self.arch = 'arm64' # In Xcode files are not accessed via their file names, but rather every one of them # gets an unique id. More precisely they get one unique id per target they are used # in. If you generate only one id per file and use them, compilation will work but the @@ -233,11 +236,10 @@ def object_filename_from_source(self, target: build.BuildTarget, source: mesonli project = self.build.project_name buildtype = self.buildtype tname = target.get_id() - arch = 'x86_64' if isinstance(source, mesonlib.File): source = source.fname stem = os.path.splitext(os.path.basename(source))[0] - obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{arch}/{stem}.o' + obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{self.arch}/{stem}.o' return obj_path def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: @@ -1391,7 +1393,7 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: bt_dict.add_item('isa', 'XCBuildConfiguration') settings_dict = PbxDict() bt_dict.add_item('buildSettings', settings_dict) - settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ARCHS', f'"{self.arch}"') settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') settings_dict.add_item('SWIFT_VERSION', '5.0') settings_dict.add_item('SDKROOT', '"macosx"') @@ -1435,7 +1437,7 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: bt_dict.add_item('isa', 'XCBuildConfiguration') settings_dict = PbxDict() bt_dict.add_item('buildSettings', settings_dict) - settings_dict.add_item('ARCHS', '"$(NATIVE_ARCH_ACTUAL)"') + settings_dict.add_item('ARCHS', f'"{self.arch}"') settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') settings_dict.add_item('SDKROOT', '"macosx"') settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) From df6926250d39583d1289d91f0b06c5a980190320 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Wed, 20 Sep 2023 12:39:19 -0500 Subject: [PATCH 558/855] backends: Make object_filename_from_source() backend-agnostic Some backends may need to use its own target directories instead of our default one. For this, introduce an optional argument "targetdir" that will still use our default one when not specified. --- mesonbuild/backend/backends.py | 14 ++++++++------ mesonbuild/backend/vs2010backend.py | 4 +--- mesonbuild/backend/xcodebackend.py | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 441a1eca5ec0..5b947991577a 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -834,7 +834,7 @@ def canonicalize_filename(fname: str) -> str: fname = fname.replace(ch, '_') return hashed + fname - def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString') -> str: + def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOrString', targetdir: T.Optional[str] = None) -> str: assert isinstance(source, mesonlib.File) if isinstance(target, build.CompileTarget): return target.sources_map[source] @@ -855,9 +855,8 @@ def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOr elif source.is_built: if os.path.isabs(rel_src): rel_src = rel_src[len(build_dir) + 1:] - targetdir = self.get_target_private_dir(target) # A meson- prefixed directory is reserved; hopefully no-one creates a file name with such a weird prefix. - gen_source = 'meson-generated_' + os.path.relpath(rel_src, targetdir) + gen_source = 'meson-generated_' + os.path.relpath(rel_src, self.get_target_private_dir(target)) else: if os.path.isabs(rel_src): # Use the absolute path directly to avoid file name conflicts @@ -866,7 +865,10 @@ def object_filename_from_source(self, target: build.BuildTarget, source: 'FileOr gen_source = os.path.relpath(os.path.join(build_dir, rel_src), os.path.join(self.environment.get_source_dir(), target.get_subdir())) machine = self.environment.machines[target.for_machine] - return self.canonicalize_filename(gen_source) + '.' + machine.get_object_suffix() + ret = self.canonicalize_filename(gen_source) + '.' + machine.get_object_suffix() + if targetdir is not None: + return os.path.join(targetdir, ret) + return ret def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_build_root: str) -> T.List[str]: result: T.List[str] = [] @@ -920,8 +922,8 @@ def _determine_ext_objs(self, extobj: 'build.ExtractedObjects', proj_dir_to_buil sources.append(_src) for osrc in sources: - objname = self.object_filename_from_source(extobj.target, osrc) - objpath = os.path.join(proj_dir_to_build_root, targetdir, objname) + objname = self.object_filename_from_source(extobj.target, osrc, targetdir) + objpath = os.path.join(proj_dir_to_build_root, objname) result.append(objpath) return result diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 7bf80d9e6c6c..c7ae4793f7af 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1448,12 +1448,10 @@ def add_non_makefile_vcxproj_elements( extra_link_args.append(path[:-len(gen_src_ext)] + '.obj') for src in l.srclist: - obj_basename = None if self.environment.is_source(src): - obj_basename = self.object_filename_from_source(t, src) target_private_dir = self.relpath(self.get_target_private_dir(t), self.get_target_dir(t)) - rel_obj = os.path.join(target_private_dir, obj_basename) + rel_obj = self.object_filename_from_source(t, src, target_private_dir) extra_link_args.append(rel_obj) extra_link_args.extend(self.flatten_object_list(t)) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 989b2bf9a1d6..c951819a5f6b 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -230,7 +230,7 @@ def get_custom_target_output_dir(self, target: T.Union[build.Target, build.Custo os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname - def object_filename_from_source(self, target: build.BuildTarget, source: mesonlib.FileOrString) -> str: + def object_filename_from_source(self, target: build.BuildTarget, source: mesonlib.FileOrString, targetdir: T.Optional[str] = None) -> str: # Xcode has the following naming scheme: # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o project = self.build.project_name From 02ee16729614ba2aae5f5d921c2ebbc1f5d19b46 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 12 Aug 2023 10:15:02 -0500 Subject: [PATCH 559/855] xcode: Check custom target input for extracted objects If there are any specified, the build target that generates them must be added as a dependency. --- mesonbuild/backend/xcodebackend.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index c951819a5f6b..3a70d25e9ea4 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -585,12 +585,15 @@ def generate_pbx_aggregate_target(self, objects_dict: PbxDict) -> None: elif isinstance(d, build.BuildTarget): dependencies.append(self.pbx_dep_map[d.get_id()]) for s in t.sources: - if not isinstance(s, build.GeneratedList): - continue - build_phases.append(self.shell_targets[(tname, generator_id)]) - for d in s.depends: - dependencies.append(self.pbx_custom_dep_map[d.get_id()]) - generator_id += 1 + if isinstance(s, build.GeneratedList): + build_phases.append(self.shell_targets[(tname, generator_id)]) + for d in s.depends: + dependencies.append(self.pbx_custom_dep_map[d.get_id()]) + generator_id += 1 + elif isinstance(s, build.ExtractedObjects): + source_target_id = self.pbx_dep_map[s.target.get_id()] + if source_target_id not in dependencies: + dependencies.append(source_target_id) build_phases.append(self.shell_targets[tname]) aggregated_targets.append((ct_id, tname, self.buildconflistmap[tname], build_phases, dependencies)) From 6e381714c7cb15877e2bcaa304b93c212252ada3 Mon Sep 17 00:00:00 2001 From: Albert Tang Date: Sat, 19 Aug 2023 10:55:14 -0500 Subject: [PATCH 560/855] xcode: Fix "clean" operation under new build system Xcode 14 has dropped the legacy build system, forcing us to use the new one introduced in Xcode 9. The new system requires that we conform to its "clean build folder" behavior, or clean operations fail. CMake achieves this by setting other variables instead of SYMROOT, so we follow that approach while retaining our current behavior as much as possible. Ref: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7730 --- mesonbuild/backend/xcodebackend.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 3a70d25e9ea4..abdac0cc6964 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -239,7 +239,8 @@ def object_filename_from_source(self, target: build.BuildTarget, source: mesonli if isinstance(source, mesonlib.File): source = source.fname stem = os.path.splitext(os.path.basename(source))[0] - obj_path = f'{project}.build/{buildtype}/{tname}.build/Objects-normal/{self.arch}/{stem}.o' + # Append "build" before the actual object path to match OBJROOT + obj_path = f'build/{project}.build/{buildtype}/{tname}.build/Objects-normal/{self.arch}/{stem}.o' return obj_path def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: @@ -1397,10 +1398,12 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: settings_dict = PbxDict() bt_dict.add_item('buildSettings', settings_dict) settings_dict.add_item('ARCHS', f'"{self.arch}"') + settings_dict.add_item('BUILD_DIR', f'"{self.environment.get_build_dir()}"') + settings_dict.add_item('BUILD_ROOT', '"$(BUILD_DIR)"') settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') settings_dict.add_item('SWIFT_VERSION', '5.0') settings_dict.add_item('SDKROOT', '"macosx"') - settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) + settings_dict.add_item('OBJROOT', '"$(BUILD_DIR)/build"') bt_dict.add_item('name', f'"{buildtype}"') # Then the all target. @@ -1410,7 +1413,6 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: bt_dict.add_item('isa', 'XCBuildConfiguration') settings_dict = PbxDict() bt_dict.add_item('buildSettings', settings_dict) - settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) warn_array = PbxArray() warn_array.add_item('"$(inherited)"') settings_dict.add_item('WARNING_CFLAGS', warn_array) @@ -1424,7 +1426,6 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: bt_dict.add_item('isa', 'XCBuildConfiguration') settings_dict = PbxDict() bt_dict.add_item('buildSettings', settings_dict) - settings_dict.add_item('SYMROOT', '"%s"' % self.environment.get_build_dir()) warn_array = PbxArray() settings_dict.add_item('WARNING_CFLAGS', warn_array) warn_array.add_item('"$(inherited)"') @@ -1443,7 +1444,6 @@ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None: settings_dict.add_item('ARCHS', f'"{self.arch}"') settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES') settings_dict.add_item('SDKROOT', '"macosx"') - settings_dict.add_item('SYMROOT', '"%s/build"' % self.environment.get_build_dir()) bt_dict.add_item('name', f'"{buildtype}"') def determine_internal_dep_link_args(self, target, buildtype): @@ -1671,7 +1671,8 @@ def generate_single_build_target(self, objects_dict, target_name, target) -> Non settings_dict.add_item('SECTORDER_FLAGS', '""') if is_swift and bridging_header: settings_dict.add_item('SWIFT_OBJC_BRIDGING_HEADER', f'"{bridging_header}"') - settings_dict.add_item('SYMROOT', f'"{symroot}"') + settings_dict.add_item('BUILD_DIR', f'"{symroot}"') + settings_dict.add_item('OBJROOT', f'"{symroot}/build"') sysheader_arr = PbxArray() # XCode will change every -I flag that points inside these directories # to an -isystem. Thus set nothing in it since we control our own From 314d9f0c74b34905f1ebb697d1374f078ea32854 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 26 Jan 2024 11:23:05 -0800 Subject: [PATCH 561/855] Differentiate message between dynamic linker and archiver Currently both print `Detecting linker via`, which can be confusing. Clarifying this by printing "archiver" instead of "linker" for the static linker/archiver --- mesonbuild/compilers/detect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 9d4852bf1524..2df6f134d14c 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -197,7 +197,7 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker else: arg = '--version' try: - p, out, err = Popen_safe_logged(linker + [arg], msg='Detecting linker via') + p, out, err = Popen_safe_logged(linker + [arg], msg='Detecting archiver via') except OSError as e: popen_exceptions[join_args(linker + [arg])] = e continue From 708a108cded4b25928b838483a95aad764622716 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 28 Jan 2024 00:51:48 -0500 Subject: [PATCH 562/855] python module: correct the embedded path for bytecompiled files In recursive scanning, a script variable was overwritten that caused the logic *intended* to make the embedded path be trimmed based on $DESTDIR, to no longer apply. This resulted in embedding the staging path, but only when install_subdir() was used instead of specifying each file as the argument to install_sources. --- mesonbuild/scripts/pycompile.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mesonbuild/scripts/pycompile.py b/mesonbuild/scripts/pycompile.py index 619398a3472c..92fad579c176 100644 --- a/mesonbuild/scripts/pycompile.py +++ b/mesonbuild/scripts/pycompile.py @@ -19,16 +19,16 @@ def compileall(files): f = f[12:] ddir = None - fullpath = os.environ['MESON_INSTALL_DESTDIR_'+key] + f + fullpath = absf = os.environ['MESON_INSTALL_DESTDIR_'+key] + f f = os.environ['MESON_INSTALL_'+key] + f - if fullpath != f: + if absf != f: ddir = os.path.dirname(f) - if os.path.isdir(fullpath): - for root, _, files in os.walk(fullpath): + if os.path.isdir(absf): + for root, _, files in os.walk(absf): if ddir is not None: - ddir = root.replace(fullpath, f, 1) + ddir = root.replace(absf, f, 1) for dirf in files: if dirf.endswith('.py'): fullpath = os.path.join(root, dirf) From 55d30b61ffadb014abb0c814c039ebebfc7df347 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 19 Jan 2024 14:50:31 -0800 Subject: [PATCH 563/855] rust: Add `--extern proc_macro` in `rust.proc_macro() not in cargo translation Cargo does this by default, so it's reasonable that we do the same. Fixes: #12758 --- mesonbuild/cargo/interpreter.py | 3 +-- mesonbuild/modules/rust.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index a6634ac1b2a8..66e45acc1df6 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2022-2023 Intel Corporation +# Copyright © 2022-2024 Intel Corporation """Interpreter for converting Cargo Toml definitions to Meson AST @@ -418,7 +418,6 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR lib: mparser.BaseNode if cargo.lib.proc_macro or crate_type == 'proc-macro': - kwargs['rust_args'] = build.array([build.string('--extern'), build.string('proc_macro')]) lib = build.method('proc_macro', build.identifier('rust'), posargs, kwargs) else: if crate_type in {'lib', 'rlib', 'staticlib'}: diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index eb15473de1b8..96e1e6f16ebf 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright © 2020-2023 Intel Corporation +# Copyright © 2020-2024 Intel Corporation from __future__ import annotations import itertools @@ -283,6 +283,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType], kwargs: _kwargs.SharedLibrary) -> SharedLibrary: kwargs['native'] = True # type: ignore kwargs['rust_crate_type'] = 'proc-macro' # type: ignore + kwargs['rust_args'] = kwargs['rust_args'] + ['--extern', 'proc_macro'] target = state._interpreter.build_target(state.current_node, args, kwargs, SharedLibrary) return target From f5da446bb91f33cb0a67f95d08da70ce12fa042f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 17 Jan 2024 13:23:56 -0500 Subject: [PATCH 564/855] dependencies: hdf5: mark configtool dependency not-found for cmake build When hdf5 is built with cmake instead of autotools, it makes a number of weird changes. What we care about in particular is that h5cc exists but doesn't work -- it happily ignores -show and tries to compile stuff, then leaves us with a dependency that has no libraries, and fails when running `ninja`. See: #12748 --- mesonbuild/dependencies/hdf5.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mesonbuild/dependencies/hdf5.py b/mesonbuild/dependencies/hdf5.py index a00b5988b41a..62265302564c 100644 --- a/mesonbuild/dependencies/hdf5.py +++ b/mesonbuild/dependencies/hdf5.py @@ -122,13 +122,20 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. # and then without -c to get the link arguments. args = self.get_config_value(['-show', '-c'], 'args')[1:] args += self.get_config_value(['-show', '-noshlib' if self.static else '-shlib'], 'args')[1:] + found = False for arg in args: if arg.startswith(('-I', '-f', '-D')) or arg == '-pthread': self.compile_args.append(arg) elif arg.startswith(('-L', '-l', '-Wl')): self.link_args.append(arg) + found = True elif Path(arg).is_file(): self.link_args.append(arg) + found = True + + # cmake h5cc is broken + if not found: + raise DependencyException('HDF5 was built with cmake instead of autotools, and h5cc is broken.') def _sanitize_version(self, ver: str) -> str: v = re.search(r'\s*HDF5 Version: (\d+\.\d+\.\d+)', ver) From b50dd0607d7731308533538efce134a2bde077a2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 31 Jan 2024 23:12:30 -0500 Subject: [PATCH 565/855] CI: mark hdf5 as inaccessible on macOS with config-tool instead of pkg-config It is broken with the cmake build. With the previous commit, it now shows the former as UNEXSKIP instead of ERROR. --- test cases/frameworks/25 hdf5/test.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test cases/frameworks/25 hdf5/test.json b/test cases/frameworks/25 hdf5/test.json index dd073ece90eb..e42be3d65557 100644 --- a/test cases/frameworks/25 hdf5/test.json +++ b/test cases/frameworks/25 hdf5/test.json @@ -2,8 +2,8 @@ "matrix": { "options": { "method": [ - { "val": "pkg-config", "skip_on_jobname": ["macos"] }, - { "val": "config-tool" } + { "val": "pkg-config" }, + { "val": "config-tool", "skip_on_jobname": ["macos"] } ] } }, From cb54f0d707e5673eb1d8aaafae59a6d5fde25e18 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 1 Feb 2024 08:09:07 -0500 Subject: [PATCH 566/855] test cases: pass the c++11 std to boost-using code Apple Clang defaults to C++03 or earlier, and boost 1.84 has started requiring C++11 as a minimum. Fixes test failures on the macOS builders. Unneeded for GCC systems since GCC defaults to a more recent std -- but also semantically correct there too. --- test cases/common/219 include_type dependency/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/test cases/common/219 include_type dependency/meson.build b/test cases/common/219 include_type dependency/meson.build index 678fb4edfbbb..9d5d91a37d99 100644 --- a/test cases/common/219 include_type dependency/meson.build +++ b/test cases/common/219 include_type dependency/meson.build @@ -1,6 +1,7 @@ project( 'dependency include_type', ['c', 'cpp'], + default_options: ['cpp_std=c++11'], ) dep = dependency('zlib', method: 'pkg-config', required : false) From 6fcf8632c6ca7c7d3812bf611ca99820264fae65 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Fri, 2 Feb 2024 14:38:22 +0100 Subject: [PATCH 567/855] fix UnboundLocalError if guess_win_linker fails in detect_fortran_compiler --- mesonbuild/compilers/detect.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 2df6f134d14c..1f6bb484079d 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -769,6 +769,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C if 'flang' in out or 'clang' in out: cls = fortran.FlangFortranCompiler + linker = None if 'windows' in out or env.machines[for_machine].is_windows(): # If we're in a MINGW context this actually will use a gnu # style ld, but for flang on "real" windows we'll use From db51dcfa47d66b094a13eb127e09d3134d8dbf1f Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 2 Feb 2024 16:23:21 +0100 Subject: [PATCH 568/855] mdist: Hoist leftover late import From 23d3b98, the meson command is exposed through a function. Therefore, the caveat no longer applies. --- mesonbuild/mdist.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 67442885a389..93ef44eb1609 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -21,7 +21,7 @@ from glob import glob from pathlib import Path from mesonbuild.environment import detect_ninja -from mesonbuild.mesonlib import (MesonException, RealPathAction, quiet_git, +from mesonbuild.mesonlib import (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 @@ -327,9 +327,6 @@ def run(options: argparse.Namespace) -> int: b = build.load(options.wd) need_vsenv = T.cast('bool', b.environment.coredata.get_option(OptionKey('vsenv'))) setup_vsenv(need_vsenv) - # This import must be load delayed, otherwise it will get the default - # value of None. - from mesonbuild.mesonlib import get_meson_command src_root = b.environment.source_dir bld_root = b.environment.build_dir priv_dir = os.path.join(bld_root, 'meson-private') From 91caf7aa56ba622926f7056d4a42083a75c24e5a Mon Sep 17 00:00:00 2001 From: U2FsdGVkX1 Date: Sun, 4 Feb 2024 14:07:54 +0800 Subject: [PATCH 569/855] Fix ninja cannot find the library when libraries contain symlinks. --- mesonbuild/compilers/mixins/gnu.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 9c0c3f290531..ef7f120f8956 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -469,16 +469,13 @@ def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]: # paths under /lib would be considered not a "system path", # which is wrong and breaks things. Store everything, just to be sure. pobj = pathlib.Path(p) - unresolved = pobj.as_posix() if pobj.exists(): + resolved = pobj.resolve().as_posix() + if resolved not in result: + result.append(resolved) + unresolved = pobj.as_posix() if unresolved not in result: result.append(unresolved) - try: - resolved = pathlib.Path(p).resolve().as_posix() - if resolved not in result: - result.append(resolved) - except FileNotFoundError: - pass return result def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]: From 7a60218dcaf0e11694ff1cb0531168fe576dc390 Mon Sep 17 00:00:00 2001 From: U2FsdGVkX1 Date: Mon, 5 Feb 2024 17:24:21 +0800 Subject: [PATCH 570/855] Turn on strict mode, as it is no longer the default since Python 3.6 --- mesonbuild/compilers/mixins/gnu.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index ef7f120f8956..79f271607434 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -470,9 +470,12 @@ def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]: # which is wrong and breaks things. Store everything, just to be sure. pobj = pathlib.Path(p) if pobj.exists(): - resolved = pobj.resolve().as_posix() - if resolved not in result: - result.append(resolved) + try: + resolved = pobj.resolve(True).as_posix() + if resolved not in result: + result.append(resolved) + except FileNotFoundError: + pass unresolved = pobj.as_posix() if unresolved not in result: result.append(unresolved) From 80ed1dfa7ff6175b89038f98d935f803509cf86b Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Tue, 30 Jan 2024 22:01:46 +0100 Subject: [PATCH 571/855] Add a numpy dependency with pkg-config and configtool methods These are being added for NumPy 2.0 The implementation closely follows the one for the pybind11 dependency. --- docs/markdown/Dependencies.md | 8 ++++++++ .../snippets/numpy-custom-dependency.md | 9 +++++++++ mesonbuild/dependencies/__init__.py | 1 + mesonbuild/dependencies/python.py | 17 +++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 docs/markdown/snippets/numpy-custom-dependency.md diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index d412a2526bcb..965a3dde91a4 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -653,6 +653,14 @@ The `language` keyword may used. `method` may be `auto`, `pkg-config`, `system` or `cmake`. +## NumPy + +*(added 1.4.0)* + +`method` may be `auto`, `pkg-config`, or `config-tool`. +`dependency('numpy')` supports regular use of the NumPy C API. +Use of `numpy.f2py` for binding Fortran code isn't yet supported. + ## pcap *(added 0.42.0)* diff --git a/docs/markdown/snippets/numpy-custom-dependency.md b/docs/markdown/snippets/numpy-custom-dependency.md new file mode 100644 index 000000000000..5934180c001b --- /dev/null +++ b/docs/markdown/snippets/numpy-custom-dependency.md @@ -0,0 +1,9 @@ +## New numpy custom dependency + +Support for `dependency('numpy')` was added, via supporting the `numpy-config` tool and +pkg-config support, both of which are available since NumPy 2.0.0. + +Config-tool support is useful because it will work out of the box when +``numpy`` is installed, while the pkg-config file is located inside python's +site-packages, which makes it impossible to use in an out of the box manner +without setting `PKG_CONFIG_PATH`. diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 0bfca97842d2..abc2e22b2d86 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -228,6 +228,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. 'appleframeworks': 'platform', # from python: + 'numpy': 'python', 'python3': 'python', 'pybind11': 'python', diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 342d94e72f4d..6620eff20f16 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -61,6 +61,17 @@ def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.An self.compile_args = self.get_config_value(['--includes'], 'compile_args') +class NumPyConfigToolDependency(ConfigToolDependency): + + tools = ['numpy-config'] + + def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.Any]): + super().__init__(name, environment, kwargs) + if not self.is_found: + return + self.compile_args = self.get_config_value(['--cflags'], 'compile_args') + + class BasicPythonExternalProgram(ExternalProgram): def __init__(self, name: str, command: T.Optional[T.List[str]] = None, ext_prog: T.Optional[ExternalProgram] = None): @@ -412,3 +423,9 @@ def set_env(name: str, value: str) -> None: [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.CMAKE], configtool_class=Pybind11ConfigToolDependency, ) + +packages['numpy'] = numpy_factory = DependencyFactory( + 'numpy', + [DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL], + configtool_class=NumPyConfigToolDependency, +) From 9659a8e6cfa1e2d72b5b6ab5622b29a1e09a9e1e Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 10 Jan 2024 14:35:19 -0500 Subject: [PATCH 572/855] Fix minsize optimization for vs backend Fixes #12265 --- mesonbuild/backend/vs2010backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c7ae4793f7af..c7b5bb53aae7 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1368,7 +1368,7 @@ def add_non_makefile_vcxproj_elements( elif '/Ob2' in o_flags: ET.SubElement(clconf, 'InlineFunctionExpansion').text = 'AnySuitable' # Size-preserving flags - if '/Os' in o_flags: + if '/Os' in o_flags or '/O1' in o_flags: ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Size' # Note: setting FavorSizeOrSpeed with clang-cl conflicts with /Od and can make debugging difficult, so don't. elif '/Od' not in o_flags: From 99ea390af81e8eaa415e09fc14c98d0107410956 Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 8 Feb 2024 03:53:13 +0000 Subject: [PATCH 573/855] cmake: canonicalise -DSTATIC value CMake really prefers ON/OFF and in some cases, depending on how the condition is written, ON/OFF vs other "truthy" (as far as CMake's lang supports) values work differently. Just be safe and use ON/OFF. Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/dependencies/cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index c76592ba3804..da5db5c3a68a 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -379,7 +379,7 @@ def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[s cmake_opts += ['-DARCHS={}'.format(';'.join(self.cmakeinfo.archs))] cmake_opts += [f'-DVERSION={package_version}'] cmake_opts += ['-DCOMPS={}'.format(';'.join([x[0] for x in comp_mapped]))] - cmake_opts += [f'-DSTATIC={self.static}'] + cmake_opts += ['-DSTATIC={}'.format('ON' if self.static else 'OFF')] cmake_opts += args cmake_opts += self.traceparser.trace_args() cmake_opts += toolchain.get_cmake_args() From 369cc28e59e731af58110bb993743f643a767fb2 Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 8 Feb 2024 03:54:44 +0000 Subject: [PATCH 574/855] Fix comment typos Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/dependencies/dev.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 17642878d8a5..f53b93cbe201 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -329,7 +329,7 @@ def _set_old_link_args(self) -> None: Old versions of LLVM bring an extra level of insanity with them. llvm-config will provide the correct arguments for static linking, but - not for shared-linnking, we have to figure those out ourselves, because + not for shared-linking, we have to figure those out ourselves, because of course we do. """ if self.static: @@ -413,7 +413,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> if not self.is_found: return - #CMake will return not found due to not defined LLVM_DYLIB_COMPONENTS + # CMake will return not found due to not defined LLVM_DYLIB_COMPONENTS if not self.static and version_compare(self.version, '< 7.0') and self.llvm_modules: mlog.warning('Before version 7.0 cmake does not export modules for dynamic linking, cannot check required modules') return From d1b783fc6923efa1a891d6d3a717e4e5ad15de21 Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 8 Feb 2024 03:55:01 +0000 Subject: [PATCH 575/855] cmake: improve heuristics for static LLVM detection In 89146e84c9eab649d3847af101d61047cac45765, a heuristic was introduced where if libLLVMSupport is available as a static library, LLVM itself is assumed to be availble as a static library as a whole. This is unfortunately not the case at least on Gentoo and Arch Linux, where a subsequent llvm-config call yields: ``` $ /usr/lib/llvm/17/bin/llvm-config --libfiles --link-static llvm-config: error: missing: /usr/lib/llvm/17/lib64/libLLVMTargetParser.a llvm-config: error: missing: /usr/lib/llvm/17/lib64/libLLVMBinaryFormat.a llvm-config: error: missing: /usr/lib/llvm/17/lib64/libLLVMBitstreamReader.a llvm-config: error: missing: /usr/lib/llvm/17/lib64/libLLVMRemarks.a [...] ``` On Gentoo, where LLVM's static libraries are not included, we still have: ``` $ equery f llvm:17 | grep -i lib64/.*.a$ /usr/lib/llvm/17/lib64/libLLVMDemangle.a /usr/lib/llvm/17/lib64/libLLVMSupport.a /usr/lib/llvm/17/lib64/libLLVMTableGen.a /usr/lib/llvm/17/lib64/libLLVMTestingAnnotations.a /usr/lib/llvm/17/lib64/libLLVMTestingSupport.a /usr/lib/llvm/17/lib64/libllvm_gtest.a /usr/lib/llvm/17/lib64/libllvm_gtest_main.a ``` Therefore, testing for libLLVMSupport is insufficient. We now try libLLVMCore instead, as that appears to only be installed when LLVM truly has static libraries available. libLLVMCore is handled as a LLVM component which gives us some guarantee this is supposed to be happening and not a fluke. (Specifically, LLVM's llvm/lib/Support/CMakeLists.txt pays 0 attention to -DLLVM_BUILD_LLVM_DYLIB and -DLLVM_LINK_LLVM_DYLIB, and is hence only affected by -DBUILD_SHARED_LIBS, which LLVM upstream say is only to be used for development. Therefore, with -DBUILD_SHARED_LIBS=OFF (as is recommended/the default) and -DLLVM_BUILD_LLVM_DYLIB=ON, you will get a static libLLVMSupport, without it indicating anything about the rest of your configuration.) Closes: https://github.com/mesonbuild/meson/issues/12323 Fixes: 89146e84c9eab649d3847af101d61047cac45765 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/dependencies/data/CMakeListsLLVM.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/data/CMakeListsLLVM.txt b/mesonbuild/dependencies/data/CMakeListsLLVM.txt index 4a9382207b3d..593f7e6fd6e4 100644 --- a/mesonbuild/dependencies/data/CMakeListsLLVM.txt +++ b/mesonbuild/dependencies/data/CMakeListsLLVM.txt @@ -85,7 +85,7 @@ if(LLVM_FOUND) elseif(NOT LLVM_MESON_DYLIB) # Use LLVMSupport to check if static targets exist set(static_tg FALSE) - is_static(LLVMSupport static_tg) + is_static(LLVMCore static_tg) if(static_tg) set(PACKAGE_FOUND TRUE) endif(static_tg) From e0d83359aa125204429e3070eda1ae79767abafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Thu, 8 Feb 2024 22:02:48 +0100 Subject: [PATCH 576/855] find_tool: fix error message interpolation --- mesonbuild/modules/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 17b3631d983a..e7aeb8af1fb0 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -100,7 +100,7 @@ def find_tool(self, name: str, depname: str, varname: str, required: bool = True progobj = ExternalProgram(value) if not progobj.found(): msg = (f'Dependency {depname!r} tool variable {varname!r} contains erroneous value: {value!r}\n\n' - 'This is a distributor issue -- please report it to your {depname} provider.') + f'This is a distributor issue -- please report it to your {depname} provider.') raise mesonlib.MesonException(msg) return progobj From 348c2e93d23b3f087e72cb04c3f6e2f2572c4fa9 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 30 Oct 2023 21:55:22 +0530 Subject: [PATCH 577/855] Revert "Wrap: Use git instead of patch by default" This reverts commit 718c86a7d577e6474ff325957248724d9b786174. We can't always use git to apply patches because they might actually apply to a git submodule inside a git subproject, and git will not be able to apply the patch in that case. --- mesonbuild/wrap/wrap.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 9a310bc414f6..d302e9dcf398 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -809,17 +809,15 @@ def apply_diff_files(self) -> None: if not path.exists(): raise WrapException(f'Diff file "{path}" does not exist') relpath = os.path.relpath(str(path), self.dirname) - if GIT: - # Git is more likely to be available on Windows and more likely - # to apply correctly assuming patches are often generated by git. - # See https://github.com/mesonbuild/meson/issues/12092. - # The `--work-tree` is necessary in case we're inside a + if PATCH: + # Always pass a POSIX path to patch, because on Windows it's MSYS + cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] + elif GIT: + # If the `patch` command is not available, fall back to `git + # apply`. The `--work-tree` is necessary in case we're inside a # Git repository: by default, Git will try to apply the patch to # the repository root. cmd = [GIT, '--work-tree', '.', 'apply', '-p1', relpath] - elif PATCH: - # Always pass a POSIX path to patch, because on Windows it's MSYS - cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] else: raise WrapException('Missing "patch" or "git" commands to apply diff files') From 09c0803077b9887792b50520aa90bc30dc451f8c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 30 Oct 2023 22:02:54 +0530 Subject: [PATCH 578/855] wraps: Ignore whitespace when applying diff_file Fixes https://github.com/mesonbuild/meson/issues/12092 --- mesonbuild/wrap/wrap.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index d302e9dcf398..53caa0267383 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -811,13 +811,15 @@ def apply_diff_files(self) -> None: relpath = os.path.relpath(str(path), self.dirname) if PATCH: # Always pass a POSIX path to patch, because on Windows it's MSYS - cmd = [PATCH, '-f', '-p1', '-i', str(Path(relpath).as_posix())] + # Ignore whitespace when applying patches to workaround + # line-ending differences + cmd = [PATCH, '-l', '-f', '-p1', '-i', str(Path(relpath).as_posix())] elif GIT: # If the `patch` command is not available, fall back to `git # apply`. The `--work-tree` is necessary in case we're inside a # Git repository: by default, Git will try to apply the patch to # the repository root. - cmd = [GIT, '--work-tree', '.', 'apply', '-p1', relpath] + cmd = [GIT, '--work-tree', '.', 'apply', '--ignore-whitespace', '-p1', relpath] else: raise WrapException('Missing "patch" or "git" commands to apply diff files') From b08d531c022c427d2480e1c81a6676d9a85cd537 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 26 Jan 2024 13:14:48 -0600 Subject: [PATCH 579/855] Document that alias_target accepts run_tgts since 0.60.0 This was implemented in dc51740e2cdee171ac6ebc7ed261e5c08730c9a9, but was not added to the documentation or marked as a new feature. --- docs/yaml/functions/alias_target.yaml | 4 ++-- mesonbuild/interpreter/interpreter.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/yaml/functions/alias_target.yaml b/docs/yaml/functions/alias_target.yaml index 22ffdfd9881f..bc14f84da2fe 100644 --- a/docs/yaml/functions/alias_target.yaml +++ b/docs/yaml/functions/alias_target.yaml @@ -6,8 +6,8 @@ description: | targets, this integrates with the selected backend. For instance, with you can run it as `meson compile target_name`. This is a dummy target that does not execute any command, but ensures that all dependencies - are built. Dependencies can be any build target (e.g. return value of - [[executable]], [[custom_target]], etc) + are built. Dependencies can be any build target. Since 0.60.0, this includes + [[@run_tgt]]. posargs: target_name: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index bee64aa94ba4..deb3a9caf11a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2121,6 +2121,8 @@ def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str], def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[build.Target]], kwargs: 'TYPE_kwargs') -> build.AliasTarget: name, deps = args + if any(isinstance(d, build.RunTarget) for d in deps): + FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject) tg = build.AliasTarget(name, deps, self.subdir, self.subproject, self.environment) self.add_target(name, tg) return tg From 4ea51e1b25f92686e075c6b2b96b5e1cbeb8419b Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Tue, 31 Oct 2023 17:25:35 -0500 Subject: [PATCH 580/855] Continue fleshing out bash completion script This adds bash completion to everything that I could think of except for the rewriter. --- data/shell-completions/bash/meson | 1012 +++++++++++++++++++++++++++-- 1 file changed, 945 insertions(+), 67 deletions(-) diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index 595b5b5a5ad7..55c9c008d98c 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -1,6 +1,58 @@ +# shellcheck shell=bash + +_get_subprojects_dir() { + # TODO: meson-info/intro-projectinfo.json has the info for the subproject + # directory, but we can't know what the build directory is in these contexts. + # Let's default to subprojects. + + # Get subprojects directory. All subprojects subcommands support --sourcedir, + # so if that argument was passed, use it to find subprojects. + subprojects_dir="subprojects" + for (( i=${#COMP_WORDS[@]} - 1; i >= 0; i-- )); do + # Exit early if we have made our way back to the command + if [[ "${COMP_WORDS[$i]}" = "subprojects" ]]; then + break + fi + + prev=$((i - 1)) + if [[ $prev -gt 0 ]] && [[ "${COMP_WORDS[$prev]}" = "--sourcedir" ]]; then + subprojects_dir="${COMP_WORDS[$i]}" + break + fi + done + + echo "$subprojects_dir" +} + +_subprojects() { + subprojects_dir=$(_get_subprojects_dir) + pushd "$subprojects_dir" &>/dev/null || return + local COMPREPLY=() + _filedir + # _filedir for whatever reason can't reason about symlinks, so -d will them. + # Filter out wrap files with this expresion. + IFS=$'\n' echo "${COMPREPLY[*]}" | grep -vE '\.wrap$' | xargs + popd &>/dev/null +} + +_wraps() { + subprojects_dir=$(_get_subprojects_dir) + db="$subprojects_dir/wrapdb.json" + if [[ ! -f "$db" ]]; then + return + fi + + document=$(cat "$db") + wraps=($(python3 -c 'import sys, json +for wrap in json.load(sys.stdin).keys(): + print(wrap) +' <<< "$document")) + echo "${wraps[@]}" +} + _meson() { command="${COMP_WORDS[1]}" - meson_subcommands=( + subcommands=( setup configure dist @@ -17,8 +69,8 @@ _meson() { env2mfile ) - if [[ " ${meson_subcommands[*]} " =~ " ${command} " ]]; then - _meson-$command "${COMP_WORDS[@]:1}" + if [[ " ${subcommands[*]} " =~ " ${command} " ]]; then + "_meson-$command" "${COMP_WORDS[@]:1}" else _meson-setup "${COMP_WORDS[@]}" fi @@ -58,7 +110,6 @@ _meson_complete_option_value() { return fi -# TODO: support all the option types options=($(python3 -c 'import sys, json for option in json.load(sys.stdin): if option["name"] != "'$option_name'": @@ -70,6 +121,10 @@ for option in json.load(sys.stdin): elif option["type"] == "combo": for choice in option["choices"]: choices.append(choice) + elif option["type"] == "feature": + choices.append("auto") + choices.append("enabled") + choices.append("disabled") for choice in choices: if choice.startswith("'$cur'"): print(choice) @@ -80,7 +135,7 @@ for option in json.load(sys.stdin): _meson_get_options() { local options for builddir in "${COMP_WORDS[@]}"; do - if [ -d "$builddir" ]; then + if [[ -d "$builddir" ]]; then break fi builddir=. @@ -260,7 +315,7 @@ _meson-setup() { fi if [[ $COMP_CWORD == 1 ]]; then - COMPREPLY+=($(compgen -W "${meson_subcommands[*]}" -- "$cur")) + COMPREPLY+=($(compgen -W '${subcommands[*]}' -- "$cur")) fi fi } @@ -305,11 +360,111 @@ _meson-configure() { } _meson-dist() { - : TODO + shortopts=( + h + C + ) + + longopts=( + allow-dirty + help + formats + include-subprojects + no-tests + ) + + local cur prev + if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then + case $prev in + -C) + _filedir -d + return + ;; + + --formats) + formats=( + xztar + gztar + zip + ) + + COMPREPLY+=($(compgen -W '${formats[*]}' -- "$cur")) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi } _meson-install() { - : TODO + shortopts=( + h + n + C + ) + + longopts=( + help + no-rebuild + only-changed + quiet + destdir + dry-run + skip-subprojects + tags + strip + ) + + local cur prev + if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then + for i in "${!COMP_WORDS[@]}"; do + opt="${COMP_WORDS[i]}" + dir="${COMP_WORDS[i+1]}" + case "$opt" in + -C) + break + ;; + esac + dir=. + done + + case $prev in + -C | --destdir) + _filedir -d + return + ;; + + --tags) + tags=$(meson introspect "$dir" --install-plan | python3 -c 'import sys, json +targets = json.load(sys.stdin)["targets"] +for target, attributes in targets.items(): + print(attributes["tag"]) +' 2> /dev/null) + + if [[ $? == 0 ]]; then + COMPREPLY+=($(compgen -W '${tags[*]}' -- "$cur")) + fi + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi } _meson-introspect() { @@ -345,12 +500,12 @@ _meson-introspect() { if ! _meson_compgen_options "$cur"; then for dir in "${COMP_WORDS[@]}"; do - if [ -d "$dir" ]; then + if [[ -d "$dir" ]]; then break fi dir=. done - if [ ! -d "$dir/meson-private" ]; then + if [[ ! -d "$dir/meson-private" ]]; then _filedir -d fi @@ -397,6 +552,7 @@ _meson-init() { _meson-test() { shortopts=( h + j q v t @@ -435,11 +591,16 @@ _meson-test() { ;; --wrapper) - _command_offset $COMP_CWORD + _command_offset "$COMP_CWORD" + return + ;; + + --gdb-path) + _filedir return ;; - --gdb-path | -C) + -C) _filedir -d return ;; @@ -461,10 +622,10 @@ for test in json.load(sys.stdin): for suite in test["suite"]: print(suite) ' 2> /dev/null) -# TODO - what? if [[ $? == 0 ]]; then - COMPREPLY+=($(compgen -W "${suites[*]}" -- "$cur")) + COMPREPLY+=($(compgen -W '${suites[*]}' -- "$cur")) + __ltrim_colon_completions "$cur" fi return ;; @@ -474,7 +635,7 @@ for test in json.load(sys.stdin): return ;; - --num-processes) + -j | --num-processes) # number, can't be completed return ;; @@ -499,13 +660,13 @@ for test in json.load(sys.stdin): if ! _meson_compgen_options "$cur"; then for dir in "${COMP_WORDS[@]}"; do - if [ -d "$dir" ]; then + if [[ -d "$dir" ]]; then break fi dir=. done - if [ ! -d "$dir/meson-private" ]; then + if [[ ! -d "$dir/meson-private" ]]; then _filedir -d fi @@ -526,7 +687,7 @@ for test in json.load(sys.stdin): ' 2> /dev/null) if [[ $? == 0 ]]; then - COMPREPLY+=($(compgen -W "${tests[*]}" -- "$cur")) + COMPREPLY+=($(compgen -W '${tests[*]}' -- "$cur")) fi if [ -z "$cur" ]; then @@ -537,90 +698,807 @@ for test in json.load(sys.stdin): } _meson-wrap() { - : TODO -} - -_meson-subprojects() { - : TODO -} + shortopts=( + h + ) -_meson-help() { longopts=( - setup - configure - dist + help + ) + + subcommands=( + info install - introspect - init - test - wrap - subprojects - rewrite - compile - devenv - env2mfile + list + promote + search + status + update + update-db ) + for i in "$@"; do + if [[ " ${subcommands[*]} " =~ " $i " ]]; then + "_meson-wrap-$i" "${COMP_WORDS[i]:1}" + return + fi + done + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi - if _get_comp_words_by_ref cur prev &>/dev/null; then - COMPREPLY+=($(compgen -W '${longopts[*]}' -- "${cur}")) + if ! _meson_compgen_options "$cur"; then + COMPREPLY+=($(compgen -W '${subcommands[*]}' -- "$cur")) + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi fi } -_meson-rewrite() { - : TODO +_meson-wrap-info() { + shortopts=( + h + ) + + longopts=( + allow-insecure + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + read -ra wraps < <(_wraps) + COMPREPLY+=($(compgen -W '${wraps[*]}' -- "$cur")) } -_meson-compile() { +_meson-wrap-install() { shortopts=( h - C - j - l - v ) longopts=( + allow-insecure help - clean - jobs - load-average - verbose - ninja-args - vs-args - xcode-args ) local cur prev - if _get_comp_words_by_ref cur prev &>/dev/null; then - if [[ ${prev:0:2} == -- ]] && _meson_complete_option "${prev:2}" "$cur"; then - return - elif [[ ${prev:0:1} == - ]] && [[ ${prev:1:2} != - ]] && _meson_complete_option "${prev:1}"; then - return - fi - else + if ! _get_comp_words_by_ref cur prev &>/dev/null; then cur="${COMP_WORDS[COMP_CWORD]}" fi if ! _meson_compgen_options "$cur"; then - _filedir -d + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + read -ra wraps < <(_wraps) + COMPREPLY+=($(compgen -W '${wraps[*]}' -- "$cur")) +} +_meson-wrap-list() { + shortopts=( + h + ) + + longopts=( + allow-insecure + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then if [[ -z $cur ]]; then COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) fi + fi +} - if [[ $COMP_CWORD == 1 ]]; then - COMPREPLY+=($(compgen -W "${meson_subcommands[*]}" -- "$cur")) +_meson-wrap-promote() { + shortopts=( + h + ) + + longopts=( + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + _filedir + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) fi fi } -_meson-devenv() { - : TODO +_meson-wrap-search() { + shortopts=( + h + ) + + longopts=( + allow-insecure + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + read -ra wraps < <(_wraps) + COMPREPLY+=($(compgen -W '${wraps[*]}' -- "$cur")) } -_meson-env2mfile() { - : TODO +_meson-wrap-status() { + shortopts=( + h + ) + + longopts=( + allow-insecure + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-wrap-update() { + shortopts=( + h + ) + + longopts=( + allow-insecure + force + help + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-wrap-update-db() { + shortopts=( + h + ) + + longopts=( + allow-insecure + help + ) + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-subprojects() { + shortopts=( + h + ) + + longopts=( + help + ) + + subcommands=( + checkout + download + foreach + packagefiles + purge + update + ) + + for i in "$@"; do + if [[ " ${subcommands[*]} " =~ " $i " ]]; then + "_meson-subprojects-$i" "${COMP_WORDS[i]:1}" + return + fi + done + + local cur prev + if ! _get_comp_words_by_ref cur prev &>/dev/null; then + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + COMPREPLY+=($(compgen -W '${subcommands[*]}' -- "$cur")) + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-subprojects-checkout() { + shortopts=( + b + h + j + ) + + longopts=( + allow-insecure + help + num-processes + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-subprojects-download() { + shortopts=( + h + j + ) + + longopts=( + allow-insecure + help + num-processes + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-subprojects-foreach() { + shortopts=( + h + j + ) + + longopts=( + allow-insecure + help + num-processes + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-subprojects-packagefiles() { + shortopts=( + h + j + ) + + longopts=( + allow-insecure + apply + help + num-processes + save + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + + --apply | --save) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-subprojects-purge() { + shortopts=( + h + j + ) + + longopts=( + allow-insecure + confirm + help + include-cache + num-processes + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + + --apply | --save) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-subprojects-update() { + shortopts=( + h + j + ) + + longopts=( + allow-insecure + help + num-processes + rebase + reset + sourcedir + types + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + --sourcedir) + _filedir -d + return + ;; + + --types) + types=( + file + git + hg + svn + ) + + COMPREPLY+=($(compgen -W '${types[*]}' -- "$cur")) + return + ;; + + -j | --num-processes) + # number, can't be completed + return + ;; + + --rebase | --reset) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi + + COMPREPLY+=($(_subprojects)) +} + +_meson-help() { + longopts=( + setup + configure + dist + install + introspect + init + test + wrap + subprojects + rewrite + compile + devenv + env2mfile + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + COMPREPLY+=($(compgen -W '${longopts[*]}' -- "$cur")) + fi +} + +_meson-rewrite() { + : TODO +} + +_meson-compile() { + shortopts=( + h + C + j + l + v + ) + + longopts=( + help + clean + jobs + load-average + verbose + ninja-args + vs-args + xcode-args + ) + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + if [[ ${prev:0:2} == -- ]] && _meson_complete_option "${prev:2}" "$cur"; then + return + elif [[ ${prev:0:1} == - ]] && [[ ${prev:1:2} != - ]] && _meson_complete_option "${prev:1}"; then + return + fi + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + _filedir -d + + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-devenv() { + shortopts=( + h + w + ) + + longopts=( + dump + dump-format + help + workdir + ) + + local cur prev + if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then + case $prev in + -C | -w | --workdir) + _filedir -d + return + ;; + + --dump) + _filedir + return + ;; + + --dump-format) + dump_formats=( + sh + export + vscode + ) + + COMPREPLY+=($(compgen -W '${dump_formats[*]}' -- "$cur")) + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi +} + +_meson-env2mfile() { + shortopts=( + h + o + ) + + longopts=( + cpu + cpu-family + cross + debarch + endian + gccsuffix + help + kernel + native + subsystem + system + ) + + local cur prev + if _get_comp_words_by_ref -n ':' cur prev &>/dev/null; then + case $prev in + --endian) + endianness=( + big + little + ) + + COMPREPLY+=($(compgen -W '${endianness[*]}' -- "$cur")) + return + ;; + + -o) + _filedir + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + if ! _meson_compgen_options "$cur"; then + if [[ -z $cur ]]; then + COMPREPLY+=($(compgen -P '--' -W '${longopts[*]}')) + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}')) + fi + fi } From 87ba2484042597940ddf85d9f4819bf120ac90e6 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 6 Dec 2023 01:42:04 -0600 Subject: [PATCH 581/855] Mark the bash completion files for bash and zsh as Shell files This will add highlighting when viewing on GitHub. --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index 7fd80e241758..feb793d0d0cc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,5 @@ * text eol=lf *.png binary *.icns binary +data/shell-completions/bash/meson linguist-language=Shell +data/shell-completions/zsh/_meson linguist-language=Shell From fe8123b48413459c361c30bb36a87dbf66636011 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 3 Oct 2023 04:53:09 +0100 Subject: [PATCH 582/855] ci: add Gentoo We may want to consider our own binpkg cache for future to speed things up, in addition to the ones provided by Gentoo's own binhost. Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- .github/workflows/images.yml | 1 + .github/workflows/os_comp.yml | 1 + ci/ciimage/build.py | 4 + ci/ciimage/gentoo/image.json | 8 ++ ci/ciimage/gentoo/install.sh | 151 ++++++++++++++++++++++++ test cases/frameworks/15 llvm/test.json | 2 +- test cases/frameworks/25 hdf5/test.json | 2 +- 7 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 ci/ciimage/gentoo/image.json create mode 100755 ci/ciimage/gentoo/install.sh diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index dd4fe9ac4145..c43a1cf62f23 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -41,6 +41,7 @@ jobs: - { name: Arch Linux, id: arch } - { name: CUDA (on Arch), id: cuda } - { name: Fedora, id: fedora } + - { name: Gentoo, id: gentoo } - { name: OpenSUSE, id: opensuse } - { name: Ubuntu Bionic, id: bionic } - { name: Ubuntu Rolling, id: ubuntu-rolling } diff --git a/.github/workflows/os_comp.yml b/.github/workflows/os_comp.yml index 298963db1751..e9f5b7a1c82f 100644 --- a/.github/workflows/os_comp.yml +++ b/.github/workflows/os_comp.yml @@ -40,6 +40,7 @@ jobs: - { name: Arch Linux, id: arch } - { name: CUDA (on Arch), id: cuda } - { name: Fedora, id: fedora } + - { name: Gentoo, id: gentoo } - { name: OpenSUSE, id: opensuse } - { name: Ubuntu Bionic, id: bionic } container: mesonbuild/${{ matrix.cfg.id }}:latest diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py index b9d318158411..10fd099052cd 100755 --- a/ci/ciimage/build.py +++ b/ci/ciimage/build.py @@ -78,6 +78,10 @@ def gen_bashrc(self) -> None: if [ -f "$HOME/.cargo/env" ]; then source "$HOME/.cargo/env" fi + + if [ -f /etc/profile.env ]; then + source /etc/profile.env + fi ''' out_file.write_text(out_data, encoding='utf-8') diff --git a/ci/ciimage/gentoo/image.json b/ci/ciimage/gentoo/image.json new file mode 100644 index 000000000000..e59eee5eec35 --- /dev/null +++ b/ci/ciimage/gentoo/image.json @@ -0,0 +1,8 @@ +{ + "base_image": "gentoo/stage3:desktop", + "env": { + "CI": "1", + "MESON_CI_JOBNAME": "linux-gentoo-gcc", + "SKIP_STATIC_BOOST": "1" + } +} diff --git a/ci/ciimage/gentoo/install.sh b/ci/ciimage/gentoo/install.sh new file mode 100755 index 000000000000..dc6383c1441a --- /dev/null +++ b/ci/ciimage/gentoo/install.sh @@ -0,0 +1,151 @@ +#!/bin/bash +set -e + +source /ci/common.sh + +# We divide the package list into 'pkgs_stable' and 'pkgs_latest'. The trade-off +# is that latest stuff may not have a binpkg available, but of course we get +# better test coverage with the bleeding edge then. +pkgs_stable=( + app-portage/portage-utils + dev-build/cmake + dev-vcs/git + + # language support + dev-python/cython + dev-python/lxml + dev-python/pip + virtual/fortran + dev-lang/nasm + dev-lang/vala + dev-lang/python:2.7 + dev-java/openjdk-bin + # requires rustfmt, bin rebuild (TODO: file bug) + #dev-util/bindgen + + dev-libs/elfutils + dev-libs/gobject-introspection + dev-util/itstool + dev-libs/protobuf + + # custom deps + net-libs/libpcap + dev-util/gtk-doc + media-libs/libwmf + sys-cluster/openmpi + sci-libs/netcdf + media-libs/libsdl2 + dev-cpp/gtest + sci-libs/hdf5 + dev-qt/linguist-tools + sys-devel/llvm + # qt6 unstable + #dev-qt/qttools + + # misc + app-admin/sudo + app-text/doxygen + sys-apps/fakeroot + sys-devel/bison + sys-devel/gettext + + # TODO: vulkan-validation-layers + # TODO: cuda + #dev-cpp/gtkmm:3.0 + #dev-java/openjdk-bin:8 + #dev-lang/go + #dev-lang/mono + #dev-lang/python + #dev-lang/rust-bin + #dev-libs/wayland + #dev-libs/wayland-protocols + #dev-python/pypy3 + #dev-qt/qtbase:6 + #dev-qt/qtcore:5 + #dev-qt/qttools:6 + #dev-vcs/mercurial + #gnustep-base/gnustep-base + #media-gfx/graphviz + #sci-libs/netcdf-fortran + #sys-devel/clang + #x11-libs/gtk+:3 +) +pkgs_latest=( + # ~arch boost needed for py3.12 for now (needs 1.84) + dev-build/b2 + dev-libs/boost + + dev-build/autoconf + dev-build/automake + + # ~arch only + sci-libs/scalapack +) +pkgs=( "${pkgs_stable[@]}" "${pkgs_latest[@]}" ) + +emerge-webrsync --quiet + +# This means we can't really take advantage of the binhost but a lot of the +# advantages of using Gentoo in CI come from the bleeding edge side. +# With full ~arch, we don't get binpkgs for much at all. Instead, let's just +# do ~arch for the test deps we have. +#echo 'ACCEPT_KEYWORDS="~amd64"' >> /etc/portage/make.conf + +printf "%s\n" ${pkgs[@]} >> /var/lib/portage/world +printf "%s\n" ${pkgs_latest[@]} >> /etc/portage/package.accept_keywords/meson +cat /etc/portage/package.accept_keywords/meson + +cat <<-EOF > /etc/portage/package.accept_keywords/misc + dev-lang/python-exec + dev-lang/python +EOF + +mkdir /etc/portage/binrepos.conf || true +mkdir /etc/portage/profile || true +cat <<-EOF > /etc/portage/package.use/ci + dev-cpp/gtkmm X + + dev-libs/boost python + sys-libs/zlib static-libs +EOF + +cat <<-EOF >> /etc/portage/make.conf + EMERGE_DEFAULT_OPTS="--complete-graph --quiet=y --quiet-build=y --jobs=$(nproc) --load-average=$(nproc)" + EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --autounmask-write --autounmask-continue --autounmask-keep-keywords=y --autounmask-use=y" + EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --binpkg-respect-use=y" + + FEATURES="\${FEATURES} parallel-fetch parallel-install -merge-sync" + FEATURES="\${FEATURES} getbinpkg binpkg-request-signature" + + # These don't work in Docker, so reduce noise in logs + FEATURES="\${FEATURES} -ipc-sandbox -network-sandbox -pid-sandbox" +EOF + +# TODO: Enable all Pythons / add multiple jobs with diff. Python impls? +#echo '*/* PYTHON_TARGETS: python3_10 python3_11 python3_12' >> /etc/portage/package.use/python +echo '*/* PYTHON_TARGETS: python3_12' >> /etc/portage/package.use/python +cat <<-EOF >> /etc/portage/profile/use.mask +-python_targets_python3_12 +-python_single_target_python3_12 +EOF +cat <<-EOF >> /etc/portage/profile/use.stable.mask +-python_targets_python3_12 +-python_single_target_python3_12 +EOF + +echo 'dev-lang/python ensurepip' >> /etc/portage/package.use/python + +# Silly mono circular dep +#USE=minimal emerge --oneshot dev-lang/mono + +# If we don't want to do this, we could use the 'portage' container instead +# so the stage3/repo match. +emerge --update --deep --changed-use @world +qlop -d 'yesterday' + +env-update && . /etc/profile + +rm /usr/lib/python/EXTERNALLY-MANAGED +python3 -m ensurepip +install_python_packages +python3 -m pip install "${base_python_pkgs[@]}" diff --git a/test cases/frameworks/15 llvm/test.json b/test cases/frameworks/15 llvm/test.json index f9d730514220..177ecdeadd5d 100644 --- a/test cases/frameworks/15 llvm/test.json +++ b/test cases/frameworks/15 llvm/test.json @@ -7,7 +7,7 @@ { "val": "combination", "skip_on_jobname": ["msys2"] } ], "link-static": [ - { "val": true, "skip_on_jobname": ["opensuse"] }, + { "val": true, "skip_on_jobname": ["opensuse", "linux-gentoo-gcc"] }, { "val": false } ] } diff --git a/test cases/frameworks/25 hdf5/test.json b/test cases/frameworks/25 hdf5/test.json index e42be3d65557..a5c816f662fb 100644 --- a/test cases/frameworks/25 hdf5/test.json +++ b/test cases/frameworks/25 hdf5/test.json @@ -2,7 +2,7 @@ "matrix": { "options": { "method": [ - { "val": "pkg-config" }, + { "val": "pkg-config", "skip_on_jobname": ["linux-gentoo-gcc"] }, { "val": "config-tool", "skip_on_jobname": ["macos"] } ] } From 7d8b925144ae2b84ccccd603eac11b70d4243e46 Mon Sep 17 00:00:00 2001 From: Sam James Date: Fri, 9 Feb 2024 02:40:00 +0000 Subject: [PATCH 583/855] ci: fedora; add file package FAILED unittests/linuxliketests.py::LinuxlikeTests::test_install_strip - FileNotFoundError: [Errno 2] No such file or directory: 'file' Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- ci/ciimage/fedora/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/fedora/install.sh b/ci/ciimage/fedora/install.sh index dc9c20af3e74..2191a707ed9a 100755 --- a/ci/ciimage/fedora/install.sh +++ b/ci/ciimage/fedora/install.sh @@ -6,7 +6,7 @@ source /ci/common.sh pkgs=( python python-pip python3-devel - ninja-build make git autoconf automake patch + ninja-build make git autoconf automake patch file elfutils gcc gcc-c++ gcc-fortran gcc-objc gcc-objc++ vala rust bison flex ldc libasan libasan-static mono-core boost-devel gtkmm30 gtest-devel gmock-devel protobuf-devel wxGTK-devel gobject-introspection boost-python3-devel From 7e8b7454f5bd53ae2d15c270e741d6f524fbd3bf Mon Sep 17 00:00:00 2001 From: Sam James Date: Fri, 9 Feb 2024 03:30:04 +0000 Subject: [PATCH 584/855] test cases: use C++17 for protobuf because of abseil-cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the openSUSE builder, we got a horrifying CI failure like: ``` FAILED: asubdir/subdir-prog.p/main.cpp.o c++ -Iasubdir/subdir-prog.p -Iasubdir '-I../test cases/frameworks/5 protocol buffers/asubdir' -fdiagnostics-color=always -D_GLIBCXX_ASSERTIONS=1 -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -std=c++14 -O0 -g -DPROTOBUF_USE_DLLS -DNOMINMAX -MD -MQ asubdir/subdir-prog.p/main.cpp.o -MF asubdir/subdir-prog.p/main.cpp.o.d -o asubdir/subdir-prog.p/main.cpp.o -c '../test cases/frameworks/5 protocol buffers/asubdir/main.cpp' In file included from /usr/include/google/protobuf/stubs/common.h:20, from /usr/include/google/protobuf/io/coded_stream.h:107, from asubdir/subdir-prog.p/defs.pb.h:26, from ../test cases/frameworks/5 protocol buffers/asubdir/main.cpp:1: /usr/include/absl/strings/string_view.h:52:26: error: ‘string_view’ in namespace ‘std’ does not name a type 52 | using string_view = std::string_view; | ^~~~~~~~~~~ [...] ``` This turns out to be because of a *huge* mess with abseil-cpp and protobuf. We're still trying to handle it in Gentoo, even (see bgo#912819) and https://github.com/gentoo/gentoo/pull/32281. In summary, abseil-cpp started to require C++17 (unless built with a special option which causes ABI problems). Let's switch the protobuf test case to use C++17 accordingly. There's some precedence for Just Doing This, like in cb54f0d707e5673eb1d8aaafae59a6d5fde25e18 recently for Boost, and 792a84199b8829c923968e8816a27e021647d146 previously for protobuf itself. Bug: https://bugs.gentoo.org/912819 See also: https://github.com/gentoo/gentoo/pull/32281 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- test cases/frameworks/5 protocol buffers/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/5 protocol buffers/meson.build b/test cases/frameworks/5 protocol buffers/meson.build index 9a4154b652f3..f9e677c95f8f 100644 --- a/test cases/frameworks/5 protocol buffers/meson.build +++ b/test cases/frameworks/5 protocol buffers/meson.build @@ -1,4 +1,4 @@ -project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++14']) +project('protocol buffer test', 'cpp', default_options: ['cpp_std=c++17']) protoc = find_program('protoc', required : false) dep = dependency('protobuf', required : false) From c166b136a60e17d7d76916550d61de55ee6e62e2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 8 Feb 2024 23:29:46 -0500 Subject: [PATCH 585/855] Suppress LLVM static test on Arch It is properly detected as unavailable, ever since commit d1b783fc6923efa1a891d6d3a717e4e5ad15de21 --- test cases/frameworks/15 llvm/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/15 llvm/test.json b/test cases/frameworks/15 llvm/test.json index 177ecdeadd5d..cf8aa3acc7bd 100644 --- a/test cases/frameworks/15 llvm/test.json +++ b/test cases/frameworks/15 llvm/test.json @@ -7,7 +7,7 @@ { "val": "combination", "skip_on_jobname": ["msys2"] } ], "link-static": [ - { "val": true, "skip_on_jobname": ["opensuse", "linux-gentoo-gcc"] }, + { "val": true, "skip_on_jobname": ["arch", "opensuse", "linux-gentoo-gcc"] }, { "val": false } ] } From 3c7bc8cac3737796ef2ee1ce0ba6dd601f5f080b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Fri, 9 Feb 2024 16:13:18 -0500 Subject: [PATCH 586/855] CI image builder: fix profile loading for gentoo We need to load various environment variables from /etc/profile. We cannot unconditionally load it, because opensuse sources env_vars and their /etc/profile has a fatal bug in it that causes it to return nonzero and abort under `set -e` (which is *amazing* as a thing to have in /etc/profile specifically -- just saying). Alas, even /etc/profile.env is not enough since Java support depends on profile.d logic. Re-conditionalize this check to only be added to env_vars.sh for the image named "gentoo". --- .github/workflows/images.yml | 1 - ci/ciimage/build.py | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/images.yml b/.github/workflows/images.yml index c43a1cf62f23..dd91898efc24 100644 --- a/.github/workflows/images.yml +++ b/.github/workflows/images.yml @@ -7,7 +7,6 @@ concurrency: on: push: branches: - - master paths: - 'ci/ciimage/**' - '.github/workflows/images.yml' diff --git a/ci/ciimage/build.py b/ci/ciimage/build.py index 10fd099052cd..b355c47a78a9 100755 --- a/ci/ciimage/build.py +++ b/ci/ciimage/build.py @@ -78,12 +78,13 @@ def gen_bashrc(self) -> None: if [ -f "$HOME/.cargo/env" ]; then source "$HOME/.cargo/env" fi - - if [ -f /etc/profile.env ]; then - source /etc/profile.env - fi ''' + if self.data_dir.name == 'gentoo': + out_data += ''' + source /etc/profile + ''' + out_file.write_text(out_data, encoding='utf-8') # make it executable From 10e269271d9fb6cbb69afa91bcf0cfc03e214bca Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Sat, 3 Feb 2024 17:24:58 +0100 Subject: [PATCH 587/855] backends: restore shlex quoting of MESONINTROSPECT The type of quoting was changed in 522392e to one that is suitable for use with cmd.exe on Windows. However, the documentation states that the type of quoting in MESONINTROSPECT is compatible with shlex.split() and elsewhere in the code, the same variable is still quoted with shlex.quote(). As mostly identified in #12148, there are a few choices: 1. Use shlex.quote() consistently and support Python but not cmd.exe. 2. Use join_args and support cmd.exe but not Python. 3. Use join_args and support splitting through the mesonbuild Python library. This commit implements the first option and reverts part of 522392e. Regression testing is implemented in #12115. Fixes #12148 --- mesonbuild/backend/backends.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 5b947991577a..01ec422f4d15 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -14,6 +14,7 @@ import os import pickle import re +import shlex import shutil import typing as T import hashlib @@ -26,8 +27,7 @@ from ..compilers import LANGUAGES_USING_LDFLAGS, detect from ..mesonlib import ( File, MachineChoice, MesonException, OrderedSet, - classify_unity_sources, OptionKey, join_args, - ExecutableSerialisation + ExecutableSerialisation, classify_unity_sources, OptionKey ) if T.TYPE_CHECKING: @@ -1598,22 +1598,23 @@ def eval_custom_target_command( cmd = [i.replace('\\', '/') for i in cmd] return inputs, outputs, cmd + def get_introspect_command(self) -> str: + return ' '.join(shlex.quote(x) for x in self.environment.get_build_command() + ['introspect']) + def get_run_target_env(self, target: build.RunTarget) -> mesonlib.EnvironmentVariables: env = target.env if target.env else mesonlib.EnvironmentVariables() if target.default_env: - introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) env.set('MESON_SOURCE_ROOT', [self.environment.get_source_dir()]) env.set('MESON_BUILD_ROOT', [self.environment.get_build_dir()]) env.set('MESON_SUBDIR', [target.subdir]) - env.set('MESONINTROSPECT', [introspect_cmd]) + env.set('MESONINTROSPECT', [self.get_introspect_command()]) return env def run_postconf_scripts(self) -> None: from ..scripts.meson_exe import run_exe - introspect_cmd = join_args(self.environment.get_build_command() + ['introspect']) env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(), 'MESON_BUILD_ROOT': self.environment.get_build_dir(), - 'MESONINTROSPECT': introspect_cmd, + 'MESONINTROSPECT': self.get_introspect_command(), } for s in self.build.postconf_scripts: From ed1a1d567ae178253b0c80228ea223e172a335d9 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 12 Aug 2023 21:13:51 +0900 Subject: [PATCH 588/855] Print a proper sentence when reporting script failure --- mesonbuild/minstall.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 643adcd9a420..a82be5e0ec8f 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -700,11 +700,11 @@ def run_install_script(self, d: InstallData, destdir: str, fullprefix: str) -> N try: rc = self.run_exe(i, localenv) except OSError: - print(f'FAILED: install script \'{name}\' could not be run, stopped') + print(f'FAILED: install script \'{name}\' could not be run.') # POSIX shells return 127 when a command could not be found sys.exit(127) if rc != 0: - print(f'FAILED: install script \'{name}\' exit code {rc}, stopped') + print(f'FAILED: install script \'{name}\' failed with exit code {rc}.') sys.exit(rc) def install_targets(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: From adf09b8316706fe75fd7255125056b077ce05edb Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 12 Aug 2023 17:57:59 +0900 Subject: [PATCH 589/855] Raise if a postconf script fails Raise MesonException if a postconf script fails to let the user know about the failure. --- mesonbuild/backend/backends.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 01ec422f4d15..92cc9fb51d34 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1620,7 +1620,9 @@ def run_postconf_scripts(self) -> None: for s in self.build.postconf_scripts: name = ' '.join(s.cmd_args) mlog.log(f'Running postconf script {name!r}') - run_exe(s, env) + rc = run_exe(s, env) + if rc != 0: + raise MesonException(f'Postconf script \'{name}\' failed with exit code {rc}.') def create_install_data(self) -> InstallData: strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip') From 152a45a360e01d8911b4f2dfe17b330161618376 Mon Sep 17 00:00:00 2001 From: taz-007 Date: Wed, 3 Jan 2024 19:17:17 +0100 Subject: [PATCH 590/855] doc: benchmark: correct usage on unix --- docs/yaml/functions/benchmark.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yaml/functions/benchmark.yaml b/docs/yaml/functions/benchmark.yaml index 3082fbe12816..9d0ca3116130 100644 --- a/docs/yaml/functions/benchmark.yaml +++ b/docs/yaml/functions/benchmark.yaml @@ -8,9 +8,9 @@ description: | * benchmark() has no `is_parallel` keyword because benchmarks are not run in parallel * benchmark() does not automatically add the `MALLOC_PERTURB_` environment variable - Defined tests can be run in a backend-agnostic way by calling - `meson test` inside the build dir, or by using backend-specific - commands, such as `ninja test` or `msbuild RUN_TESTS.vcxproj`. + Defined benchmarks can be run in a backend-agnostic way by calling + `meson test --benchmark` inside the build dir, or by using backend-specific + commands, such as `ninja benchmark` or `msbuild RUN_TESTS.vcxproj`. notes: - Prior to 0.52.0 benchmark would warn that `depends` and From 524a66116b38a65210b7516781d26ed6efb690b9 Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 2 Feb 2024 18:20:37 +0100 Subject: [PATCH 591/855] Add MESONREWRITE to `meson dist` scripts Fixes #688 --- docs/markdown/Creating-releases.md | 27 +++++++++++++++++++ docs/markdown/Reference-tables.md | 1 + docs/yaml/builtins/meson.yaml | 11 ++++++++ mesonbuild/mdist.py | 12 +++++---- .../subprojects/sub/dist-script.py | 7 +++++ .../subprojects/sub/meson.build | 6 ++++- .../subprojects/sub/version-test.py | 5 ++++ 7 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 test cases/unit/35 dist script/subprojects/sub/version-test.py diff --git a/docs/markdown/Creating-releases.md b/docs/markdown/Creating-releases.md index 638125c87d45..e0c80af5b0e8 100644 --- a/docs/markdown/Creating-releases.md +++ b/docs/markdown/Creating-releases.md @@ -86,3 +86,30 @@ meson setup builddir meson dist -C builddir ``` This produces `builddir/meson-dist/mysubproject-1.0.tar.xz` tarball. + +## Cement a version obtained from VCS + +*Since 1.4.0* the `meson dist` command enables rewriting the build +configuration of the distribution tarball. This is needed when the +configuration depends on metadata from revision control such as in the +following example. + +`meson.build`: +```meson +project('tig', 'c', + version : run_command('version.sh', 'get-vcs').stdout.strip()) + +meson.add_dist_script('version.sh', 'set-dist', meson.project_version()) +``` +`version.sh`: +```sh +#!/bin/sh + +if [ "$1" = "get-vcs" ]; then + git -C "$MESON_SOURCE_ROOT" describe --always --dirty +elif [ "$1" = "set-dist" ]; then + $MESONREWRITE --sourcedir="$MESON_PROJECT_DIST_ROOT" kwargs set project / version "$2" +else + exit 1 +fi +``` diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index af6a9b9f0bf4..02ac083e50b1 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -85,6 +85,7 @@ For languages that don't have separate dynamic linkers such as C# and Java, the | Value | Comment | | ----- | ------- | | MESONINTROSPECT | Command to run to run the introspection command, may be of the form `python /path/to/meson introspect`, user is responsible for splitting the path if necessary. | +| MESONREWRITE | Command to run to run the rewriting command, only set when running `dist` scripts | | MESON_BUILD_ROOT | Absolute path to the build dir | | MESON_DIST_ROOT | Points to the root of the staging directory, only set when running `dist` scripts | | MESON_SOURCE_ROOT | Absolute path to the source dir | diff --git a/docs/yaml/builtins/meson.yaml b/docs/yaml/builtins/meson.yaml index 0d4eacf608c0..516e41c3d9ae 100644 --- a/docs/yaml/builtins/meson.yaml +++ b/docs/yaml/builtins/meson.yaml @@ -32,6 +32,17 @@ methods: scripts, but for subproject scripts they have the path to the root of the subproject appended, usually `subprojects/`. + *(since 1.4.0)* The `MESONREWRITE` environment variable contains the path + to the rewrite command that corresponds to the `meson` executable that + was used to configure the build. (This might be a different path than the + first executable found in `PATH`.) It can be used to remove or replace + any [[run_command]] that depends on the revision control system from the + build configuration. Note that the value will contain many parts. For + example, it may be `python3 /path/to/meson.py introspect`. The user is + responsible for splitting the string to an array if needed by splitting + lexically like a UNIX shell would. If your script uses Python, + `shlex.split()` is the easiest correct way to do this. + posargs: script_name: type: str | file | external_program diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 93ef44eb1609..23cc58035fcf 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -20,7 +20,7 @@ from dataclasses import dataclass from glob import glob from pathlib import Path -from mesonbuild.environment import detect_ninja +from mesonbuild.environment import Environment, detect_ninja from mesonbuild.mesonlib import (MesonException, RealPathAction, get_meson_command, quiet_git, windows_proof_rmtree, setup_vsenv, OptionKey) from mesonbuild.msetup import add_arguments as msetup_argparse @@ -102,10 +102,12 @@ def create_dist(self, archives: T.List[str]) -> T.List[str]: def run_dist_scripts(self) -> None: assert os.path.isabs(self.distdir) - env = {} - env['MESON_DIST_ROOT'] = self.distdir - env['MESON_SOURCE_ROOT'] = self.src_root - env['MESON_BUILD_ROOT'] = self.bld_root + mesonrewrite = Environment.get_build_command() + ['rewrite'] + env = {'MESON_DIST_ROOT': self.distdir, + 'MESON_SOURCE_ROOT': self.src_root, + 'MESON_BUILD_ROOT': self.bld_root, + 'MESONREWRITE': ' '.join(shlex.quote(x) for x in mesonrewrite), + } for d in self.dist_scripts: if d.subproject and d.subproject not in self.subprojects: continue diff --git a/test cases/unit/35 dist script/subprojects/sub/dist-script.py b/test cases/unit/35 dist script/subprojects/sub/dist-script.py index 1274f291bebd..5f1b4a12443a 100644 --- a/test cases/unit/35 dist script/subprojects/sub/dist-script.py +++ b/test cases/unit/35 dist script/subprojects/sub/dist-script.py @@ -2,11 +2,18 @@ import os import pathlib +import shlex +import subprocess import sys assert sys.argv[1] == 'success' source_root = pathlib.Path(os.environ['MESON_PROJECT_DIST_ROOT']) +mesonrewrite = shlex.split(os.environ['MESONREWRITE']) +rewrite_cmd = ['kwargs', 'set', 'project', '/', 'version', 'release'] + +subprocess.run([*mesonrewrite, '-s', source_root, *rewrite_cmd], check=True) + modfile = source_root / 'prog.c' with modfile.open('w') as f: f.write('int main(){return 0;}') diff --git a/test cases/unit/35 dist script/subprojects/sub/meson.build b/test cases/unit/35 dist script/subprojects/sub/meson.build index a41a3b685786..9dc047c56199 100644 --- a/test cases/unit/35 dist script/subprojects/sub/meson.build +++ b/test cases/unit/35 dist script/subprojects/sub/meson.build @@ -1,4 +1,5 @@ -project('sub', 'c') +project('sub', 'c', + version : 'vcs') if get_option('broken_dist_script') # Make sure we can add a dist script in a subproject, but it won't be run @@ -8,4 +9,7 @@ else # The dist script replace prog.c with something that actually build. meson.add_dist_script('dist-script.py', 'success') executable('prog', 'prog.c') + + versiontest = find_program('version-test.py') + test('dist version replacement', versiontest, args : meson.project_version()) endif diff --git a/test cases/unit/35 dist script/subprojects/sub/version-test.py b/test cases/unit/35 dist script/subprojects/sub/version-test.py new file mode 100644 index 000000000000..1dcafc49ab73 --- /dev/null +++ b/test cases/unit/35 dist script/subprojects/sub/version-test.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 + +from sys import argv + +assert argv[1] == 'release' From 6c2c4612cc8f141e27ab2dd8ccacd92894c29552 Mon Sep 17 00:00:00 2001 From: Sam James Date: Fri, 9 Feb 2024 05:57:59 +0000 Subject: [PATCH 592/855] Fix comment typo Oops. Fixes: 7b7d2e060b447de9c2642848847370a58711ac1c Signed-off-by: Sam James --- mesonbuild/mtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index c0775ef7f583..d9ae783d963a 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1408,7 +1408,7 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, # Sanitizers do not default to aborting on error. This is counter to # expectations when using -Db_sanitize and has led to confusion in the wild - # in CI. Set our own values of {ASAN,UBSAN}_OPTOINS to rectify this, but + # in CI. Set our own values of {ASAN,UBSAN}_OPTIONS to rectify this, but # only if the user has not defined them. if ('ASAN_OPTIONS' not in env or not env['ASAN_OPTIONS']): env['ASAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1' From f4f50db44155a4e050c58a74849ba8859e5daf51 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 17 May 2023 16:29:39 -0400 Subject: [PATCH 593/855] qt: add preserve_paths keyword to functions This allow to generate ui and moc under subdirectories, as this is allowed with generic generators. --- docs/markdown/Qt6-module.md | 17 ++++++++- docs/markdown/_include_qt_base.md | 15 ++++++++ .../snippets/qt_preserve_path_from.md | 10 +++++ mesonbuild/modules/qt.py | 38 +++++++++++++------ test cases/frameworks/4 qt/mainWindow.h | 2 +- test cases/frameworks/4 qt/meson.build | 10 +++-- .../frameworks/4 qt/{ => ui}/mainWindow.ui | 0 7 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 docs/markdown/snippets/qt_preserve_path_from.md rename test cases/frameworks/4 qt/{ => ui}/mainWindow.ui (100%) diff --git a/docs/markdown/Qt6-module.md b/docs/markdown/Qt6-module.md index 8e8ec71e073d..0a453dd41443 100644 --- a/docs/markdown/Qt6-module.md +++ b/docs/markdown/Qt6-module.md @@ -39,6 +39,11 @@ It takes no positional arguments, and the following keyword arguments: *New in 0.60.0*: support for custom_target, custom_target_index, and generator_output. - `extra_args` string[]: Extra arguments to pass directly to `qt-uic` - `method` string: The method to use to detect Qt, see [[dependency]] + - `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). ## compile_moc @@ -59,6 +64,11 @@ It takes no positional arguments, and the following keyword arguments: - `dependencies`: dependency objects whose include directories are used by moc. - `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()` objects used when transpiling the .moc files + - `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). ## preprocess @@ -96,7 +106,12 @@ This method takes the following keyword arguments: - `dependencies` Dependency[]: dependency objects needed by moc. - *Deprecated in 0.59.0.*: `sources`: a list of extra sources, which are added to the output unchanged. - + - `preserve_paths` bool: *Since 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). + It returns an array of targets and sources to pass to a compilation target. ## compile_translations diff --git a/docs/markdown/_include_qt_base.md b/docs/markdown/_include_qt_base.md index adc6f7c6fe0c..00d1f8344072 100644 --- a/docs/markdown/_include_qt_base.md +++ b/docs/markdown/_include_qt_base.md @@ -28,6 +28,11 @@ It takes no positional arguments, and the following keyword arguments: - `extra_args` string[]: Extra arguments to pass directly to `qt-uic` - `method` string: The method to use to detect Qt, see `dependency()` for more information. + - `preserve_paths` bool: *Since 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). ## compile_moc @@ -49,6 +54,11 @@ It takes no positional arguments, and the following keyword arguments: - `dependencies`: dependency objects whose include directories are used by moc. - `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()` objects used when transpiling the .moc files + - `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). ## preprocess @@ -78,6 +88,11 @@ This method takes the following keyword arguments: - `rcc_extra_arguments` string[]: any additional arguments to `rcc`. Since v0.49.0. - `dependencies` Dependency[]: dependency objects needed by moc. Available since v0.48.0. - `sources`: a list of extra sources, which are added to the output unchanged. Deprecated in 0.59.0. + - `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output + files need to maintain their directory structure inside the target temporary + directory. For instance, when a file called `subdir/one.input` is processed + it generates a file `{target private directory}/subdir/one.out` when `true`, + and `{target private directory}/one.out` when `false` (default). It returns an array of targets and sources to pass to a compilation target. diff --git a/docs/markdown/snippets/qt_preserve_path_from.md b/docs/markdown/snippets/qt_preserve_path_from.md new file mode 100644 index 000000000000..1a0923a72a05 --- /dev/null +++ b/docs/markdown/snippets/qt_preserve_path_from.md @@ -0,0 +1,10 @@ +## Added `preserve_paths` keyword argument to qt module functions. + +In `qt4`, `qt5`, and `qt6` modules, `compile_ui`, `compile_moc`, and +`preprocess` functions now have a `preserve_paths` keyword argument. + +If `'true`, it specifies that the output files need to maintain their directory +structure inside the target temporary directory. For instance, when a file +called `subdir/one.input` is processed it generates a file +`{target private directory}/subdir/one.out` when `true`, +and `{target private directory}/one.out` when `false` (default). diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index c2a315c7f030..7effa1f58401 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -48,6 +48,7 @@ class UICompilerKwArgs(TypedDict): sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] extra_args: T.List[str] method: str + preserve_paths: bool class MocCompilerKwArgs(TypedDict): @@ -59,6 +60,7 @@ class MocCompilerKwArgs(TypedDict): method: str include_directories: T.List[T.Union[str, build.IncludeDirs]] dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + preserve_paths: bool class PreprocessKwArgs(TypedDict): @@ -73,6 +75,7 @@ class PreprocessKwArgs(TypedDict): include_directories: T.List[T.Union[str, build.IncludeDirs]] dependencies: T.List[T.Union[Dependency, ExternalLibrary]] method: str + preserve_paths: bool class HasToolKwArgs(kwargs.ExtractRequired): @@ -376,9 +379,10 @@ def _compile_resources_impl(self, state: 'ModuleState', kwargs: 'ResourceCompile required=True, ), KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), - KwargInfo('method', str, default='auto') + KwargInfo('method', str, default='auto'), + KwargInfo('preserve_paths', bool, default=False, since='1.4.0'), ) - def compile_ui(self, state: 'ModuleState', args: T.Tuple, kwargs: 'UICompilerKwArgs') -> ModuleReturnValue: + def compile_ui(self, state: ModuleState, args: T.Tuple, kwargs: UICompilerKwArgs) -> ModuleReturnValue: """Compile UI resources into cpp headers.""" if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']): FeatureNew.single_use('qt.compile_ui: custom_target or generator for "sources" keyword argument', @@ -386,7 +390,7 @@ def compile_ui(self, state: 'ModuleState', args: T.Tuple, kwargs: 'UICompilerKwA out = self._compile_ui_impl(state, kwargs) return ModuleReturnValue(out, [out]) - def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> build.GeneratedList: + def _compile_ui_impl(self, state: ModuleState, kwargs: UICompilerKwArgs) -> build.GeneratedList: # Avoid the FeatureNew when dispatching from preprocess self._detect_tools(state, kwargs['method']) if not self.tools['uic'].found(): @@ -394,13 +398,14 @@ def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> "please check your qt{2} installation") raise MesonException(err_msg.format('UIC', f'uic-qt{self.qt_version}', self.qt_version)) + preserve_path_from = os.path.join(state.source_root, state.subdir) if kwargs['preserve_paths'] else None # TODO: This generator isn't added to the generator list in the Interpreter gen = build.Generator( self.tools['uic'], kwargs['extra_args'] + ['-o', '@OUTPUT@', '@INPUT@'], ['ui_@BASENAME@.h'], name=f'Qt{self.qt_version} ui') - return gen.process_files(kwargs['sources'], state) + return gen.process_files(kwargs['sources'], state, preserve_path_from) @FeatureNew('qt.compile_moc', '0.59.0') @noPosargs @@ -422,8 +427,9 @@ def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> KwargInfo('method', str, default='auto'), KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]), KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]), + KwargInfo('preserve_paths', bool, default=False, since='1.4.0'), ) - def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue: + def compile_moc(self, state: ModuleState, args: T.Tuple, kwargs: MocCompilerKwArgs) -> ModuleReturnValue: if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['headers']): FeatureNew.single_use('qt.compile_moc: custom_target or generator for "headers" keyword argument', '0.60.0', state.subproject, location=state.current_node) @@ -433,7 +439,7 @@ def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerK out = self._compile_moc_impl(state, kwargs) return ModuleReturnValue(out, [out]) - def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -> T.List[build.GeneratedList]: + def _compile_moc_impl(self, state: ModuleState, kwargs: MocCompilerKwArgs) -> T.List[build.GeneratedList]: # Avoid the FeatureNew when dispatching from preprocess self._detect_tools(state, kwargs['method']) if not self.tools['moc'].found(): @@ -458,18 +464,19 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') - DEPFILE_ARGS: T.List[str] = ['--output-dep-file'] if self._moc_supports_depfiles else [] arguments = kwargs['extra_args'] + DEPFILE_ARGS + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@'] + preserve_path_from = os.path.join(state.source_root, state.subdir) if kwargs['preserve_paths'] else None if kwargs['headers']: moc_gen = build.Generator( self.tools['moc'], arguments, ['moc_@BASENAME@.cpp'], depfile='moc_@BASENAME@.cpp.d', name=f'Qt{self.qt_version} moc header') - output.append(moc_gen.process_files(kwargs['headers'], state)) + output.append(moc_gen.process_files(kwargs['headers'], state, preserve_path_from)) if kwargs['sources']: moc_gen = build.Generator( self.tools['moc'], arguments, ['@BASENAME@.moc'], depfile='@BASENAME@.moc.d', name=f'Qt{self.qt_version} moc source') - output.append(moc_gen.process_files(kwargs['sources'], state)) + output.append(moc_gen.process_files(kwargs['sources'], state, preserve_path_from)) return output @@ -487,8 +494,9 @@ def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') - KwargInfo('method', str, default='auto'), KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]), KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]), + KwargInfo('preserve_paths', bool, default=False, since='1.4.0'), ) - def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwargs: 'PreprocessKwArgs') -> ModuleReturnValue: + def preprocess(self, state: ModuleState, args: T.List[T.Union[str, File]], kwargs: PreprocessKwArgs) -> ModuleReturnValue: _sources = args[1:] if _sources: FeatureDeprecated.single_use('qt.preprocess positional sources', '0.59', state.subproject, location=state.current_node) @@ -502,7 +510,7 @@ def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwa if kwargs['qresources']: # custom output name set? -> one output file, multiple otherwise - rcc_kwargs: 'ResourceCompilerKwArgs' = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method} + rcc_kwargs: ResourceCompilerKwArgs = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method} if args: name = args[0] if not isinstance(name, str): @@ -511,17 +519,23 @@ def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwa sources.extend(self._compile_resources_impl(state, rcc_kwargs)) if kwargs['ui_files']: - ui_kwargs: 'UICompilerKwArgs' = {'sources': kwargs['ui_files'], 'extra_args': kwargs['uic_extra_arguments'], 'method': method} + ui_kwargs: UICompilerKwArgs = { + 'sources': kwargs['ui_files'], + 'extra_args': kwargs['uic_extra_arguments'], + 'method': method, + 'preserve_paths': kwargs['preserve_paths'], + } sources.append(self._compile_ui_impl(state, ui_kwargs)) if kwargs['moc_headers'] or kwargs['moc_sources']: - moc_kwargs: 'MocCompilerKwArgs' = { + moc_kwargs: MocCompilerKwArgs = { 'extra_args': kwargs['moc_extra_arguments'], 'sources': kwargs['moc_sources'], 'headers': kwargs['moc_headers'], 'include_directories': kwargs['include_directories'], 'dependencies': kwargs['dependencies'], 'method': method, + 'preserve_paths': kwargs['preserve_paths'], } sources.extend(self._compile_moc_impl(state, moc_kwargs)) diff --git a/test cases/frameworks/4 qt/mainWindow.h b/test cases/frameworks/4 qt/mainWindow.h index 7f6d90601eb8..3be51a00fc41 100644 --- a/test cases/frameworks/4 qt/mainWindow.h +++ b/test cases/frameworks/4 qt/mainWindow.h @@ -3,7 +3,7 @@ #include #include -#include "ui_mainWindow.h" +#include "ui/ui_mainWindow.h" class NotificationModel; diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index f8ba1751fb51..759e6cc176b5 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -61,11 +61,15 @@ foreach qt : ['qt4', 'qt5', 'qt6'] method : get_option('method') ) # XML files that need to be compiled with the uic tol. - prep += qtmodule.compile_ui(sources : 'mainWindow.ui', method: get_option('method')) + prep += qtmodule.compile_ui( + sources : 'ui/mainWindow.ui', + method: get_option('method'), + preserve_paths: true) qtmodule.preprocess( - ui_files : 'mainWindow.ui', - method: get_option('method')) + ui_files : 'ui/mainWindow.ui', + method: get_option('method'), + preserve_paths: true) # Resource file(s) for rcc compiler extra_cpp_args = [] diff --git a/test cases/frameworks/4 qt/mainWindow.ui b/test cases/frameworks/4 qt/ui/mainWindow.ui similarity index 100% rename from test cases/frameworks/4 qt/mainWindow.ui rename to test cases/frameworks/4 qt/ui/mainWindow.ui From dbfc9d0908626c42036f0a4a1e7d8c45eaedc7d2 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 1 Jan 2024 10:07:34 -0500 Subject: [PATCH 594/855] dlang module: simplify dependency handling with DRY It can be a list or a single dependency, but the same logic happens either way. Instead of manually expanding the logic for both cases, just convert it to a list as needed. --- mesonbuild/modules/dlang.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/mesonbuild/modules/dlang.py b/mesonbuild/modules/dlang.py index ed4ac8c62377..34fea9081f85 100644 --- a/mesonbuild/modules/dlang.py +++ b/mesonbuild/modules/dlang.py @@ -13,7 +13,7 @@ from ..dependencies import Dependency from ..dependencies.dub import DubDependency from ..interpreterbase import typed_pos_args -from ..mesonlib import Popen_safe, MesonException +from ..mesonlib import Popen_safe, MesonException, listify class DlangModule(ExtensionModule): class_dubbin = None @@ -69,27 +69,18 @@ def generate_dub_file(self, state, args, kwargs): for key, value in kwargs.items(): if key == 'dependencies': + values = listify(value, flatten=False) config[key] = {} - if isinstance(value, list): - for dep in value: - if isinstance(dep, Dependency): - name = dep.get_name() - ret, res = self._call_dubbin(['describe', name]) - if ret == 0: - version = dep.get_version() - if version is None: - config[key][name] = '' - else: - config[key][name] = version - elif isinstance(value, Dependency): - name = value.get_name() - ret, res = self._call_dubbin(['describe', name]) - if ret == 0: - version = value.get_version() - if version is None: - config[key][name] = '' - else: - config[key][name] = version + for dep in values: + if isinstance(dep, Dependency): + name = dep.get_name() + ret, res = self._call_dubbin(['describe', name]) + if ret == 0: + version = dep.get_version() + if version is None: + config[key][name] = '' + else: + config[key][name] = version else: config[key] = value From 6be1262cc9693d00b84f66d95691a29adff7b895 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 11 Dec 2023 01:12:22 -0500 Subject: [PATCH 595/855] compilers: fix inconsistent None-breaking return value for compile() Since commit abc7e6af01714206100a752898c325282436501f it is not possible for this set of methods to return None, which was an odd thing to return to begin with. Cease to annotate it as such. --- mesonbuild/compilers/compilers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index fbe30f6f0b7b..74cb0bfe4d14 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -750,7 +750,7 @@ def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArg def compile(self, code: 'mesonlib.FileOrString', extra_args: T.Union[None, CompilerArgs, T.List[str]] = None, *, mode: CompileCheckMode = CompileCheckMode.LINK, want_output: bool = False, - temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + temp_dir: T.Optional[str] = None) -> T.Iterator[CompileResult]: # TODO: there isn't really any reason for this to be a contextmanager if mode == CompileCheckMode.PREPROCESS: @@ -812,7 +812,7 @@ def compile(self, code: 'mesonlib.FileOrString', def cached_compile(self, code: 'mesonlib.FileOrString', cdata: coredata.CoreData, *, extra_args: T.Union[None, T.List[str], CompilerArgs] = None, mode: CompileCheckMode = CompileCheckMode.LINK, - temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: + temp_dir: T.Optional[str] = None) -> T.Iterator[CompileResult]: # TODO: There's isn't really any reason for this to be a context manager # Calculate the key @@ -1238,7 +1238,7 @@ def _build_wrapper(self, code: 'mesonlib.FileOrString', env: 'Environment', extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, dependencies: T.Optional[T.List['Dependency']] = None, mode: CompileCheckMode = CompileCheckMode.COMPILE, want_output: bool = False, - disable_cache: bool = False) -> T.Iterator[T.Optional[CompileResult]]: + disable_cache: bool = False) -> T.Iterator[CompileResult]: """Helper for getting a cached value when possible. This method isn't meant to be called externally, it's mean to be From dabe7b16d9b2bbb67c93be27723e68978ae80e3b Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 11 Dec 2023 01:49:34 -0500 Subject: [PATCH 596/855] override subclass attribute type when we know it is not None --- mesonbuild/dependencies/qt.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py index a331187ed203..65b6a5810961 100644 --- a/mesonbuild/dependencies/qt.py +++ b/mesonbuild/dependencies/qt.py @@ -120,6 +120,7 @@ class _QtBase: clib_compiler: T.Union['MissingCompiler', 'Compiler'] env: 'Environment' libexecdir: T.Optional[str] = None + version: str def __init__(self, name: str, kwargs: T.Dict[str, T.Any]): self.name = name @@ -245,6 +246,7 @@ class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta): """Find Qt using Qmake as a config-tool.""" + version: str version_arg = '-v' def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): From 07c051ed27059f16edae803b9197871225d71193 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 11 Dec 2023 01:22:15 -0500 Subject: [PATCH 597/855] defer setting values until after we know it cannot be None --- mesonbuild/dependencies/cmake.py | 5 +++-- mesonbuild/dependencies/pkgconfig.py | 5 +++-- mesonbuild/wrap/wrap.py | 9 +++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index da5db5c3a68a..2a98020a9318 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -126,9 +126,10 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. cm_args = check_cmake_args(cm_args) if CMakeDependency.class_cmakeinfo[self.for_machine] is None: CMakeDependency.class_cmakeinfo[self.for_machine] = self._get_cmake_info(cm_args) - self.cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine] - if self.cmakeinfo is None: + cmakeinfo = CMakeDependency.class_cmakeinfo[self.for_machine] + if cmakeinfo is None: raise self._gen_exception('Unable to obtain CMake system information') + self.cmakeinfo = cmakeinfo package_version = kwargs.get('cmake_package_version', '') if not isinstance(package_version, str): diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index d000018110af..30e3d2896d46 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -277,13 +277,14 @@ def __init__(self, name: str, environment: Environment, kwargs: T.Dict[str, T.An super().__init__(DependencyTypeName('pkgconfig'), environment, kwargs, language=language) self.name = name self.is_libtool = False - self.pkgconfig = PkgConfigInterface.instance(self.env, self.for_machine, self.silent) - if not self.pkgconfig: + pkgconfig = PkgConfigInterface.instance(self.env, self.for_machine, self.silent) + if not pkgconfig: msg = f'Pkg-config for machine {self.for_machine} not found. Giving up.' if self.required: raise DependencyException(msg) mlog.debug(msg) return + self.pkgconfig = pkgconfig version = self.pkgconfig.version(name) if version is None: diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 53caa0267383..c355c6de9061 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -404,12 +404,13 @@ def find_program_provider(self, names: T.List[str]) -> T.Optional[str]: def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> T.Tuple[str, Method]: self.packagename = packagename self.directory = packagename - self.wrap = self.wraps.get(packagename) - if not self.wrap: - self.wrap = self.get_from_wrapdb(packagename) - if not self.wrap: + wrap = self.wraps.get(packagename) + if not wrap: + wrap = self.get_from_wrapdb(packagename) + if not wrap: m = f'Neither a subproject directory nor a {self.packagename}.wrap file was found.' raise WrapNotFoundException(m) + self.wrap = wrap self.directory = self.wrap.directory if self.wrap.has_wrap: From e184ef71e5863bcfe2bcd128cf008876afaa8dd3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 11 Dec 2023 01:31:45 -0500 Subject: [PATCH 598/855] cmake dependency: avoid setting property to None as a workaround It's an improper object model, but was used to signal to a subclass that self.traceparser did not exist. However, since it is always initialized from self.cmakebin, we can just check that instead. --- mesonbuild/dependencies/cmake.py | 12 +++--------- mesonbuild/dependencies/dev.py | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py index 2a98020a9318..66d331925574 100644 --- a/mesonbuild/dependencies/cmake.py +++ b/mesonbuild/dependencies/cmake.py @@ -94,10 +94,6 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. super().__init__(DependencyTypeName('cmake'), environment, kwargs, language=language) self.name = name self.is_libtool = False - # Store a copy of the CMake path on the object itself so it is - # stored in the pickled coredata and recovered. - self.cmakebin: T.Optional[CMakeExecutor] = None - self.cmakeinfo: T.Optional[CMakeInfo] = None # Where all CMake "build dirs" are located self.cmake_root_dir = environment.scratch_dir @@ -105,14 +101,12 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. # T.List of successfully found modules self.found_modules: T.List[str] = [] - # Initialize with None before the first return to avoid - # AttributeError exceptions in derived classes - self.traceparser: T.Optional[CMakeTraceParser] = None - + # Store a copy of the CMake path on the object itself so it is + # stored in the pickled coredata and recovered. + # # TODO further evaluate always using MachineChoice.BUILD self.cmakebin = CMakeExecutor(environment, CMakeDependency.class_cmake_version, self.for_machine, silent=self.silent) if not self.cmakebin.found(): - self.cmakebin = None msg = f'CMake binary for machine {self.for_machine} not found. Giving up.' if self.required: raise DependencyException(msg) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index f53b93cbe201..72dbb4522a81 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -407,7 +407,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> super().__init__(name, env, kwargs, language='cpp', force_use_global_compilers=True) - if self.traceparser is None: + if not self.cmakebin.found(): return if not self.is_found: From 546fe0f92b8e3e85f85ee6bdf07f8cc6156f0850 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 25 Dec 2023 02:18:24 -0500 Subject: [PATCH 599/855] correct type signature of Popen_safe to follow stdlib subprocess The standard library accepts None defaults for some kwargs and we should too. --- mesonbuild/utils/universal.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 952d6f7b1588..0fb860796ae7 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1499,9 +1499,9 @@ def partition(pred: T.Callable[[_T], object], iterable: T.Iterable[_T]) -> T.Tup def Popen_safe(args: T.List[str], write: T.Optional[str] = None, - stdin: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, - stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, - stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stdin: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, + stdout: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stderr: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.PIPE, **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: import locale encoding = locale.getpreferredencoding() @@ -1531,9 +1531,9 @@ def Popen_safe(args: T.List[str], write: T.Optional[str] = None, def Popen_safe_legacy(args: T.List[str], write: T.Optional[str] = None, - stdin: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, - stdout: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, - stderr: T.Union[T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stdin: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.DEVNULL, + stdout: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.PIPE, + stderr: T.Union[None, T.TextIO, T.BinaryIO, int] = subprocess.PIPE, **kwargs: T.Any) -> T.Tuple['subprocess.Popen[str]', str, str]: p = subprocess.Popen(args, universal_newlines=False, close_fds=False, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs) From 6e1556028c15ba92fff32ad68c88edf143d42c16 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 25 Dec 2023 02:32:14 -0500 Subject: [PATCH 600/855] python dependency: use exceptions to pass failure state around Instead of returning Optional, a state that is only possible during `__init__` and which prevents mypy from knowing what it is safe to assume it will get. --- mesonbuild/dependencies/python.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 6620eff20f16..b9b17f854cde 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -8,7 +8,7 @@ import typing as T from .. import mesonlib, mlog -from .base import process_method_kw, DependencyMethods, DependencyTypeName, ExternalDependency, SystemDependency +from .base import process_method_kw, DependencyException, DependencyMethods, DependencyTypeName, ExternalDependency, SystemDependency from .configtool import ConfigToolDependency from .detect import packages from .factory import DependencyFactory @@ -245,7 +245,7 @@ def find_libpy(self, environment: 'Environment') -> None: self.link_args = largs self.is_found = True - def get_windows_python_arch(self) -> T.Optional[str]: + def get_windows_python_arch(self) -> str: if self.platform.startswith('mingw'): if 'x86_64' in self.platform: return 'x86_64' @@ -254,16 +254,14 @@ def get_windows_python_arch(self) -> T.Optional[str]: elif 'aarch64' in self.platform: return 'aarch64' else: - mlog.log(f'MinGW Python built with unknown platform {self.platform!r}, please file a bug') - return None + raise DependencyException(f'MinGW Python built with unknown platform {self.platform!r}, please file a bug') elif self.platform == 'win32': return 'x86' elif self.platform in {'win64', 'win-amd64'}: return 'x86_64' elif self.platform in {'win-arm64'}: return 'aarch64' - mlog.log(f'Unknown Windows Python platform {self.platform!r}') - return None + raise DependencyException('Unknown Windows Python platform {self.platform!r}') def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]: if self.platform.startswith('win'): @@ -330,8 +328,10 @@ def find_libpy_windows(self, env: 'Environment', limited_api: bool = False) -> N Find python3 libraries on Windows and also verify that the arch matches what we are building for. ''' - pyarch = self.get_windows_python_arch() - if pyarch is None: + try: + pyarch = self.get_windows_python_arch() + except DependencyException as e: + mlog.log(str(e)) self.is_found = False return arch = detect_cpu_family(env.coredata.compilers.host) From 4e83675bf80b0b134ef4035acce747722e9def73 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 12 Feb 2024 17:38:56 -0500 Subject: [PATCH 601/855] rewriter: remove never-used default None when parsing arguments The add_arguments function is always called with a formatter in mesonmain.py, and if it were not, then it would be incorrect when calling argparse itself -- because formatter_class cannot be None, and defaults to its own builtin one. This violates None-safety. --- mesonbuild/rewriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 626551014a08..680eed1f89d4 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -25,7 +25,7 @@ class RewriterException(MesonException): # Note: when adding arguments, please also add them to the completion # scripts in $MESONSRC/data/shell-completions/ -def add_arguments(parser, formatter=None): +def add_arguments(parser, formatter): parser.add_argument('-s', '--sourcedir', type=str, default='.', metavar='SRCDIR', help='Path to source directory.') parser.add_argument('-V', '--verbose', action='store_true', default=False, help='Enable verbose output') parser.add_argument('-S', '--skip-errors', dest='skip', action='store_true', default=False, help='Skip errors instead of aborting') From fc41fd3542f1bafc0b8a2ade1ca92b25c072e054 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 15 Oct 2023 17:57:45 -0400 Subject: [PATCH 602/855] add type annotations to mesonmain An oddity: sys.stdout is statically defined as type TextIO instead of TextIOWrapper, and thus doesn't have a .reconfigure method. This is because they expect people to override sys.stdout with other objects, which we do not do. Instead, assume it is always correct. There are two final errors due to metaprogramming: ``` mesonbuild/mesonmain.py:196:13: error: Returning Any from function declared to return "int" [no-any-return] mesonbuild/mesonmain.py:225:9: error: Returning Any from function declared to return "int" [no-any-return] ``` --- mesonbuild/mesonmain.py | 38 ++++++++++++++++++++------------------ mesonbuild/rewriter.py | 3 ++- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 0fbc717f8b28..c01be49e59da 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -15,11 +15,12 @@ import platform import importlib import argparse +import typing as T from .utils.core import MesonException, MesonBugException from . import mlog -def errorhandler(e, command): +def errorhandler(e: Exception, command: str) -> int: import traceback if isinstance(e, MesonException): mlog.exception(e) @@ -43,8 +44,8 @@ def errorhandler(e, command): if command == 'runpython': return 2 elif isinstance(e, OSError): - mlog.exception("Unhandled python OSError. This is probably not a Meson bug, " - "but an issue with your build environment.") + mlog.exception(Exception("Unhandled python OSError. This is probably not a Meson bug, " + "but an issue with your build environment.")) return e.errno else: # Exception msg = 'Unhandled python exception' @@ -58,7 +59,7 @@ def errorhandler(e, command): # Note: when adding arguments, please also add them to the completion # scripts in $MESONSRC/data/shell-completions/ class CommandLineParser: - def __init__(self): + def __init__(self) -> None: # only import these once we do full argparse processing from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv from .scripts import env2mfile @@ -68,8 +69,8 @@ def __init__(self): self.term_width = shutil.get_terminal_size().columns self.formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=int(self.term_width / 2), width=self.term_width) - self.commands = {} - self.hidden_commands = [] + self.commands: T.Dict[str, argparse.ArgumentParser] = {} + self.hidden_commands: T.List[str] = [] self.parser = argparse.ArgumentParser(prog='meson', formatter_class=self.formatter) self.subparsers = self.parser.add_subparsers(title='Commands', dest='command', description='If no command is specified it defaults to setup command.') @@ -109,7 +110,8 @@ def __init__(self): self.add_command('unstable-coredata', munstable_coredata.add_arguments, munstable_coredata.run, help_msg=argparse.SUPPRESS) - def add_command(self, name, add_arguments_func, run_func, help_msg, aliases=None): + def add_command(self, name: str, add_arguments_func: T.Callable[[argparse.ArgumentParser], None], + run_func: T.Callable[[argparse.Namespace], int], help_msg: str, aliases: T.List[str] = None) -> None: aliases = aliases or [] # FIXME: Cannot have hidden subparser: # https://bugs.python.org/issue22848 @@ -123,13 +125,13 @@ def add_command(self, name, add_arguments_func, run_func, help_msg, aliases=None for i in [name] + aliases: self.commands[i] = p - def add_runpython_arguments(self, parser: argparse.ArgumentParser): + def add_runpython_arguments(self, parser: argparse.ArgumentParser) -> None: parser.add_argument('-c', action='store_true', dest='eval_arg', default=False) parser.add_argument('--version', action='version', version=platform.python_version()) parser.add_argument('script_file') parser.add_argument('script_args', nargs=argparse.REMAINDER) - def run_runpython_command(self, options): + def run_runpython_command(self, options: argparse.Namespace) -> int: sys.argv[1:] = options.script_args if options.eval_arg: exec(options.script_file) @@ -139,17 +141,17 @@ def run_runpython_command(self, options): runpy.run_path(options.script_file, run_name='__main__') return 0 - def add_help_arguments(self, parser): + def add_help_arguments(self, parser: argparse.ArgumentParser) -> None: parser.add_argument('command', nargs='?', choices=list(self.commands.keys())) - def run_help_command(self, options): + def run_help_command(self, options: argparse.Namespace) -> int: if options.command: self.commands[options.command].print_help() else: self.parser.print_help() return 0 - def run(self, args): + def run(self, args: T.List[str]) -> int: implicit_setup_command_notice = False # If first arg is not a known command, assume user wants to run the setup # command. @@ -193,7 +195,7 @@ def run(self, args): 'Meson will require Python 3.7 or newer', fatal=False) mlog.shutdown() -def run_script_command(script_name, script_args): +def run_script_command(script_name: str, script_args: T.List[str]) -> int: # Map script name to module name for those that doesn't match script_map = {'exe': 'meson_exe', 'install': 'meson_install', @@ -216,16 +218,16 @@ def run_script_command(script_name, script_args): mlog.exception(e) return 1 -def ensure_stdout_accepts_unicode(): +def ensure_stdout_accepts_unicode() -> None: if sys.stdout.encoding and not sys.stdout.encoding.upper().startswith('UTF-'): - sys.stdout.reconfigure(errors='surrogateescape') + sys.stdout.reconfigure(errors='surrogateescape') # type: ignore[attr-defined] -def set_meson_command(mainfile): +def set_meson_command(mainfile: str) -> None: # Set the meson command that will be used to run scripts and so on from . import mesonlib mesonlib.set_meson_command(mainfile) -def run(original_args, mainfile): +def run(original_args: T.List[str], mainfile: str) -> int: if os.environ.get('MESON_SHOW_DEPRECATIONS'): # workaround for https://bugs.python.org/issue34624 import warnings @@ -274,7 +276,7 @@ def run(original_args, mainfile): set_meson_command(mainfile) return CommandLineParser().run(args) -def main(): +def main() -> int: # Always resolve the command path so Ninja can find it for regen, tests, etc. if 'meson.exe' in sys.executable: assert os.path.isabs(sys.executable) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 680eed1f89d4..434b21974732 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -18,6 +18,7 @@ import typing as T if T.TYPE_CHECKING: + from argparse import ArgumentParser, HelpFormatter from .mparser import BaseNode class RewriterException(MesonException): @@ -25,7 +26,7 @@ class RewriterException(MesonException): # Note: when adding arguments, please also add them to the completion # scripts in $MESONSRC/data/shell-completions/ -def add_arguments(parser, formatter): +def add_arguments(parser: ArgumentParser, formatter: T.Callable[[str], HelpFormatter]) -> None: parser.add_argument('-s', '--sourcedir', type=str, default='.', metavar='SRCDIR', help='Path to source directory.') parser.add_argument('-V', '--verbose', action='store_true', default=False, help='Enable verbose output') parser.add_argument('-S', '--skip-errors', dest='skip', action='store_true', default=False, help='Skip errors instead of aborting') From 6f7e74505246ac0363a83c49339026e977a1c03d Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 11 Feb 2024 18:50:36 -0500 Subject: [PATCH 603/855] Remove implicit-optional assignment in `__init__` that cannot ever be true IfClauseNode is only ever initialized in such a way that this attribute is immediately set to something valid. And attempting to access its value when the value is None would be a pretty broken error anyway. The assignment served no purpose, but did perform a frivolous runtime op in addition to angering mypy's checks for implicit None. --- mesonbuild/mparser.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index eaf238108b27..28235b613fc7 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -603,7 +603,6 @@ def __init__(self, linenode: BaseNode): super().__init__(linenode.lineno, linenode.colno, linenode.filename) self.ifs = [] self.elseblock = EmptyNode(linenode.lineno, linenode.colno, linenode.filename) - self.endif = None @dataclass(unsafe_hash=True) class TestCaseClauseNode(BaseNode): From cf35d9b4cebecd3e565d49e4d9f4a5366429463a Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 15 Oct 2023 19:01:34 -0400 Subject: [PATCH 604/855] cuda module: use typed_kwargs This officially only ever accepted string or array of strings. --- mesonbuild/modules/cuda.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index 5250108397e6..7cfd3a04f093 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -8,18 +8,26 @@ from ..mesonlib import version_compare from ..compilers.cuda import CudaCompiler +from ..interpreter.type_checking import NoneType from . import NewExtensionModule, ModuleInfo from ..interpreterbase import ( - flatten, permittedKwargs, noKwargs, - InvalidArguments + ContainerTypeInfo, InvalidArguments, KwargInfo, flatten, noKwargs, typed_kwargs, ) if T.TYPE_CHECKING: + from typing_extensions import TypedDict + from . import ModuleState from ..compilers import Compiler + class ArchFlagsKwargs(TypedDict): + detected: T.Optional[T.List[str]] + + +DETECTED_KW: KwargInfo[T.Union[None, T.List[str]]] = KwargInfo('detected', (ContainerTypeInfo(list, str), NoneType), listify=True) + class CudaModule(NewExtensionModule): INFO = ModuleInfo('CUDA', '0.50.0', unstable=True) @@ -87,18 +95,18 @@ def min_driver_version(self, state: 'ModuleState', return driver_version - @permittedKwargs(['detected']) + @typed_kwargs('cuda.nvcc_arch_flags', DETECTED_KW) def nvcc_arch_flags(self, state: 'ModuleState', args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], - kwargs: T.Dict[str, T.Any]) -> T.List[str]: + kwargs: ArchFlagsKwargs) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[0] return ret - @permittedKwargs(['detected']) + @typed_kwargs('cuda.nvcc_arch_readable', DETECTED_KW) def nvcc_arch_readable(self, state: 'ModuleState', args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], - kwargs: T.Dict[str, T.Any]) -> T.List[str]: + kwargs: ArchFlagsKwargs) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[1] return ret @@ -110,10 +118,10 @@ def _break_arch_string(s): return s @staticmethod - def _detected_cc_from_compiler(c): + def _detected_cc_from_compiler(c) -> T.List[str]: if isinstance(c, CudaCompiler): - return c.detected_cc - return '' + return [c.detected_cc] + return [] @staticmethod def _version_from_compiler(c): @@ -123,7 +131,7 @@ def _version_from_compiler(c): return c return 'unknown' - def _validate_nvcc_arch_args(self, args, kwargs): + def _validate_nvcc_arch_args(self, args, kwargs: ArchFlagsKwargs): argerror = InvalidArguments('The first argument must be an NVCC compiler object, or its version string!') if len(args) < 1: @@ -141,8 +149,7 @@ def _validate_nvcc_arch_args(self, args, kwargs): raise InvalidArguments('''The special architectures 'All', 'Common' and 'Auto' must appear alone, as a positional argument!''') arch_list = arch_list[0] if len(arch_list) == 1 else arch_list - detected = kwargs.get('detected', self._detected_cc_from_compiler(compiler)) - detected = flatten([detected]) + detected = kwargs['detected'] if kwargs['detected'] is not None else self._detected_cc_from_compiler(compiler) detected = [self._break_arch_string(a) for a in detected] detected = flatten(detected) if not set(detected).isdisjoint({'All', 'Common', 'Auto'}): From 8ff25c0bcafac73a450a466c559ba59018e26437 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 3 Jan 2024 23:06:23 -0500 Subject: [PATCH 605/855] cuda module: fix type signature for oneshot function It is only ever invoked once. It has a statically known signature based on how it's used, so there's no good reason to allow it to accept any defaults -- and defaulting to None messes with type safety. Saturate is always given, so don't claim it is only sometimes. --- mesonbuild/modules/cuda.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index 7cfd3a04f093..b062bbf38e17 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -157,11 +157,11 @@ def _validate_nvcc_arch_args(self, args, kwargs: ArchFlagsKwargs): return cuda_version, arch_list, detected - def _filter_cuda_arch_list(self, cuda_arch_list, lo=None, hi=None, saturate=None): + def _filter_cuda_arch_list(self, cuda_arch_list, lo: str, hi: T.Optional[str], saturate: str) -> T.List[str]: """ Filter CUDA arch list (no codenames) for >= low and < hi architecture bounds, and deduplicate. - If saturate is provided, architectures >= hi are replaced with saturate. + Architectures >= hi are replaced with saturate. """ filtered_cuda_arch_list = [] @@ -170,8 +170,6 @@ def _filter_cuda_arch_list(self, cuda_arch_list, lo=None, hi=None, saturate=None if lo and version_compare(arch, '<' + lo): continue if hi and version_compare(arch, '>=' + hi): - if not saturate: - continue arch = saturate if arch not in filtered_cuda_arch_list: filtered_cuda_arch_list.append(arch) From 1b15176168d90c913153c0da598e130e9214b3ab Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 3 Jan 2024 23:29:19 -0500 Subject: [PATCH 606/855] cuda module: inline single-shot function to get compiler version It is pretty trivial and more confusing when standalone, especially the use of a sentinel "unknown" string as a standin for "this isn't one of the allowed object types". Much easier to directly raise an error in the fallthrough/else. --- mesonbuild/modules/cuda.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index b062bbf38e17..b52288ab5a7a 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -123,14 +123,6 @@ def _detected_cc_from_compiler(c) -> T.List[str]: return [c.detected_cc] return [] - @staticmethod - def _version_from_compiler(c): - if isinstance(c, CudaCompiler): - return c.version - if isinstance(c, str): - return c - return 'unknown' - def _validate_nvcc_arch_args(self, args, kwargs: ArchFlagsKwargs): argerror = InvalidArguments('The first argument must be an NVCC compiler object, or its version string!') @@ -138,8 +130,11 @@ def _validate_nvcc_arch_args(self, args, kwargs: ArchFlagsKwargs): raise argerror else: compiler = args[0] - cuda_version = self._version_from_compiler(compiler) - if cuda_version == 'unknown': + if isinstance(compiler, CudaCompiler): + cuda_version = compiler.version + elif isinstance(compiler, str): + cuda_version = compiler + else: raise argerror arch_list = [] if len(args) <= 1 else flatten(args[1:]) From 5899daf25b406737b436f2256dbcaf273fae6ee3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 3 Jan 2024 23:51:49 -0500 Subject: [PATCH 607/855] cuda module: use typed_pos_args for most methods The min_driver_version function has an extensive, informative custom error message, so leave that in place. The other two functions didn't have much information there, and it's fairly evident that the cuda compiler itself is the best thing to have here. Moreover, there was some fairly gnarly code to validate the allowed values, which we can greatly simplify by uplifting the typechecking parts to the dedicated decorators that are both really good at it, and have nicely formatted error messages complete with reference to the problematic functions. --- mesonbuild/modules/cuda.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index b52288ab5a7a..6900538689c0 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -13,14 +13,13 @@ from . import NewExtensionModule, ModuleInfo from ..interpreterbase import ( - ContainerTypeInfo, InvalidArguments, KwargInfo, flatten, noKwargs, typed_kwargs, + ContainerTypeInfo, InvalidArguments, KwargInfo, flatten, noKwargs, typed_kwargs, typed_pos_args, ) if T.TYPE_CHECKING: from typing_extensions import TypedDict from . import ModuleState - from ..compilers import Compiler class ArchFlagsKwargs(TypedDict): detected: T.Optional[T.List[str]] @@ -95,17 +94,19 @@ def min_driver_version(self, state: 'ModuleState', return driver_version + @typed_pos_args('cuda.nvcc_arch_flags', (str, CudaCompiler), varargs=str) @typed_kwargs('cuda.nvcc_arch_flags', DETECTED_KW) def nvcc_arch_flags(self, state: 'ModuleState', - args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], + args: T.Tuple[T.Union[CudaCompiler, str], T.List[str]], kwargs: ArchFlagsKwargs) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[0] return ret + @typed_pos_args('cuda.nvcc_arch_readable', (str, CudaCompiler), varargs=str) @typed_kwargs('cuda.nvcc_arch_readable', DETECTED_KW) def nvcc_arch_readable(self, state: 'ModuleState', - args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], + args: T.Tuple[T.Union[CudaCompiler, str], T.List[str]], kwargs: ArchFlagsKwargs) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[1] @@ -123,21 +124,15 @@ def _detected_cc_from_compiler(c) -> T.List[str]: return [c.detected_cc] return [] - def _validate_nvcc_arch_args(self, args, kwargs: ArchFlagsKwargs): - argerror = InvalidArguments('The first argument must be an NVCC compiler object, or its version string!') + def _validate_nvcc_arch_args(self, args: T.Tuple[T.Union[str, CudaCompiler], T.List[str]], kwargs: ArchFlagsKwargs): - if len(args) < 1: - raise argerror + compiler = args[0] + if isinstance(compiler, CudaCompiler): + cuda_version = compiler.version else: - compiler = args[0] - if isinstance(compiler, CudaCompiler): - cuda_version = compiler.version - elif isinstance(compiler, str): - cuda_version = compiler - else: - raise argerror + cuda_version = compiler - arch_list = [] if len(args) <= 1 else flatten(args[1:]) + arch_list = args[1] arch_list = [self._break_arch_string(a) for a in arch_list] arch_list = flatten(arch_list) if len(arch_list) > 1 and not set(arch_list).isdisjoint({'All', 'Common', 'Auto'}): From 65ee397f341688282291b0ef529a7c6aa4c2f9f8 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 15 Oct 2023 21:26:58 -0400 Subject: [PATCH 608/855] cuda module: fully type annotate Special notes: - _nvcc_arch_flags is always called with exact arguments, no need for default values - min_driver_version has its args annotation loosened because it has to fit the constraints of the module interface? --- mesonbuild/modules/cuda.py | 48 ++++++++++++++++++++------------------ run_mypy.py | 1 + 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/mesonbuild/modules/cuda.py b/mesonbuild/modules/cuda.py index 6900538689c0..eb73a5770661 100644 --- a/mesonbuild/modules/cuda.py +++ b/mesonbuild/modules/cuda.py @@ -3,27 +3,31 @@ from __future__ import annotations -import typing as T import re +import typing as T -from ..mesonlib import version_compare +from ..mesonlib import listify, version_compare from ..compilers.cuda import CudaCompiler from ..interpreter.type_checking import NoneType from . import NewExtensionModule, ModuleInfo from ..interpreterbase import ( - ContainerTypeInfo, InvalidArguments, KwargInfo, flatten, noKwargs, typed_kwargs, typed_pos_args, + ContainerTypeInfo, InvalidArguments, KwargInfo, noKwargs, typed_kwargs, typed_pos_args, ) if T.TYPE_CHECKING: from typing_extensions import TypedDict from . import ModuleState + from ..interpreter import Interpreter + from ..interpreterbase import TYPE_var class ArchFlagsKwargs(TypedDict): detected: T.Optional[T.List[str]] + AutoArch = T.Union[str, T.List[str]] + DETECTED_KW: KwargInfo[T.Union[None, T.List[str]]] = KwargInfo('detected', (ContainerTypeInfo(list, str), NoneType), listify=True) @@ -31,7 +35,7 @@ class CudaModule(NewExtensionModule): INFO = ModuleInfo('CUDA', '0.50.0', unstable=True) - def __init__(self, *args, **kwargs): + def __init__(self, interp: Interpreter): super().__init__() self.methods.update({ "min_driver_version": self.min_driver_version, @@ -41,7 +45,7 @@ def __init__(self, *args, **kwargs): @noKwargs def min_driver_version(self, state: 'ModuleState', - args: T.Tuple[str], + args: T.List[TYPE_var], kwargs: T.Dict[str, T.Any]) -> str: argerror = InvalidArguments('min_driver_version must have exactly one positional argument: ' + 'a CUDA Toolkit version string. Beware that, since CUDA 11.0, ' + @@ -113,18 +117,18 @@ def nvcc_arch_readable(self, state: 'ModuleState', return ret @staticmethod - def _break_arch_string(s): + def _break_arch_string(s: str) -> T.List[str]: s = re.sub('[ \t\r\n,;]+', ';', s) - s = s.strip(';').split(';') - return s + return s.strip(';').split(';') @staticmethod - def _detected_cc_from_compiler(c) -> T.List[str]: + def _detected_cc_from_compiler(c: T.Union[str, CudaCompiler]) -> T.List[str]: if isinstance(c, CudaCompiler): return [c.detected_cc] return [] - def _validate_nvcc_arch_args(self, args: T.Tuple[T.Union[str, CudaCompiler], T.List[str]], kwargs: ArchFlagsKwargs): + def _validate_nvcc_arch_args(self, args: T.Tuple[T.Union[str, CudaCompiler], T.List[str]], + kwargs: ArchFlagsKwargs) -> T.Tuple[str, AutoArch, T.List[str]]: compiler = args[0] if isinstance(compiler, CudaCompiler): @@ -132,22 +136,20 @@ def _validate_nvcc_arch_args(self, args: T.Tuple[T.Union[str, CudaCompiler], T.L else: cuda_version = compiler - arch_list = args[1] - arch_list = [self._break_arch_string(a) for a in arch_list] - arch_list = flatten(arch_list) + arch_list: AutoArch = args[1] + arch_list = listify([self._break_arch_string(a) for a in arch_list]) if len(arch_list) > 1 and not set(arch_list).isdisjoint({'All', 'Common', 'Auto'}): raise InvalidArguments('''The special architectures 'All', 'Common' and 'Auto' must appear alone, as a positional argument!''') arch_list = arch_list[0] if len(arch_list) == 1 else arch_list detected = kwargs['detected'] if kwargs['detected'] is not None else self._detected_cc_from_compiler(compiler) - detected = [self._break_arch_string(a) for a in detected] - detected = flatten(detected) + detected = [x for a in detected for x in self._break_arch_string(a)] if not set(detected).isdisjoint({'All', 'Common', 'Auto'}): raise InvalidArguments('''The special architectures 'All', 'Common' and 'Auto' must appear alone, as a positional argument!''') return cuda_version, arch_list, detected - def _filter_cuda_arch_list(self, cuda_arch_list, lo: str, hi: T.Optional[str], saturate: str) -> T.List[str]: + def _filter_cuda_arch_list(self, cuda_arch_list: T.List[str], lo: str, hi: T.Optional[str], saturate: str) -> T.List[str]: """ Filter CUDA arch list (no codenames) for >= low and < hi architecture bounds, and deduplicate. @@ -165,7 +167,7 @@ def _filter_cuda_arch_list(self, cuda_arch_list, lo: str, hi: T.Optional[str], s filtered_cuda_arch_list.append(arch) return filtered_cuda_arch_list - def _nvcc_arch_flags(self, cuda_version, cuda_arch_list='Auto', detected=''): + def _nvcc_arch_flags(self, cuda_version: str, cuda_arch_list: AutoArch, detected: T.List[str]) -> T.Tuple[T.List[str], T.List[str]]: """ Using the CUDA Toolkit version and the target architectures, compute the NVCC architecture flags. @@ -288,11 +290,11 @@ def _nvcc_arch_flags(self, cuda_version, cuda_arch_list='Auto', detected=''): cuda_arch_list = sorted(x for x in set(cuda_arch_list) if x) - cuda_arch_bin = [] - cuda_arch_ptx = [] + cuda_arch_bin: T.List[str] = [] + cuda_arch_ptx: T.List[str] = [] for arch_name in cuda_arch_list: - arch_bin = [] - arch_ptx = [] + arch_bin: T.Optional[T.List[str]] + arch_ptx: T.Optional[T.List[str]] add_ptx = arch_name.endswith('+PTX') if add_ptx: arch_name = arch_name[:-len('+PTX')] @@ -371,5 +373,5 @@ def _nvcc_arch_flags(self, cuda_version, cuda_arch_list='Auto', detected=''): return nvcc_flags, nvcc_archs_readable -def initialize(*args, **kwargs): - return CudaModule(*args, **kwargs) +def initialize(interp: Interpreter) -> CudaModule: + return CudaModule(interp) diff --git a/run_mypy.py b/run_mypy.py index a9b52d9ac2f7..c57a75c12276 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -51,6 +51,7 @@ 'mesonbuild/mlog.py', 'mesonbuild/msubprojects.py', 'mesonbuild/modules/__init__.py', + 'mesonbuild/modules/cuda.py', 'mesonbuild/modules/external_project.py', 'mesonbuild/modules/fs.py', 'mesonbuild/modules/gnome.py', From efad4ba9c52479150a23a094a89e821e937b1cbd Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Wed, 14 Feb 2024 09:15:05 +0100 Subject: [PATCH 609/855] docs: Remove outdated HDF5 dependency pkg-config statement A config-tool method has been supported since c02593f and it says so just a few lines below the outdated statement. --- docs/markdown/Dependencies.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 965a3dde91a4..88e6575a7825 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -476,9 +476,8 @@ language-specific, you must specify the requested language using the * `dependency('hdf5', language: 'cpp')` for the C++ HDF5 headers and libraries * `dependency('hdf5', language: 'fortran')` for the Fortran HDF5 headers and libraries -Meson uses pkg-config to find HDF5. The standard low-level HDF5 -function and the `HL` high-level HDF5 functions are linked for each -language. +The standard low-level HDF5 function and the `HL` high-level HDF5 +functions are linked for each language. `method` may be `auto`, `config-tool` or `pkg-config`. From c0bf597715f7077a0897fd1ebecbe829452be972 Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Wed, 14 Feb 2024 00:57:56 +0000 Subject: [PATCH 610/855] run_project_tests: Fix Cython compiler detection On Debian systems the cython compiler binary is installed as `cython3`. The current logic for detecting whether to run the Cython unit tests instead checks for `cython` or the value of the `CYTHON` environment variable, which leads to cases where the underlying Meson can correctly compile Cython code but the test harness excludes these tests from execution because it cannot find `cython3`. This commit makes the test harness use the same detection method as Meson itself. It also takes the opportunity to refactor some existing code which does the same job for Objective C and Objective C++ tests to avoid repetition. --- run_project_tests.py | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index 4458fce760df..60ff56f70851 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -37,7 +37,7 @@ from mesonbuild import mesonlib from mesonbuild import mlog from mesonbuild import mtest -from mesonbuild.compilers import compiler_from_language, detect_objc_compiler, detect_objcpp_compiler +from mesonbuild.compilers import compiler_from_language from mesonbuild.build import ConfigurationData from mesonbuild.mesonlib import MachineChoice, Popen_safe, TemporaryDirectoryWinProof, setup_vsenv from mesonbuild.mlog import blue, bold, cyan, green, red, yellow, normal_green @@ -964,33 +964,26 @@ def have_d_compiler() -> bool: return False def have_objc_compiler(use_tmp: bool) -> bool: - with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: - env = environment.Environment('', build_dir, get_fake_options('/')) - try: - objc_comp = detect_objc_compiler(env, MachineChoice.HOST) - except mesonlib.MesonException: - return False - if not objc_comp: - return False - env.coredata.process_new_compiler('objc', objc_comp, env) - try: - objc_comp.sanity_check(env.get_scratch_dir(), env) - except mesonlib.MesonException: - return False - return True + return have_working_compiler('objc', use_tmp) def have_objcpp_compiler(use_tmp: bool) -> bool: + return have_working_compiler('objcpp', use_tmp) + +def have_cython_compiler(use_tmp: bool) -> bool: + return have_working_compiler('cython', use_tmp) + +def have_working_compiler(lang: str, use_tmp: bool) -> bool: with TemporaryDirectoryWinProof(prefix='b ', dir=None if use_tmp else '.') as build_dir: env = environment.Environment('', build_dir, get_fake_options('/')) try: - objcpp_comp = detect_objcpp_compiler(env, MachineChoice.HOST) + compiler = compiler_from_language(env, lang, MachineChoice.HOST) except mesonlib.MesonException: return False - if not objcpp_comp: + if not compiler: return False - env.coredata.process_new_compiler('objcpp', objcpp_comp, env) + env.coredata.process_new_compiler(lang, compiler, env) try: - objcpp_comp.sanity_check(env.get_scratch_dir(), env) + compiler.sanity_check(env.get_scratch_dir(), env) except mesonlib.MesonException: return False return True @@ -1116,7 +1109,7 @@ def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandat TestCategory('java', 'java', backend is not Backend.ninja or not have_java()), TestCategory('C#', 'csharp', skip_csharp(backend)), TestCategory('vala', 'vala', backend is not Backend.ninja or not shutil.which(os.environ.get('VALAC', 'valac'))), - TestCategory('cython', 'cython', backend is not Backend.ninja or not shutil.which(os.environ.get('CYTHON', 'cython'))), + TestCategory('cython', 'cython', backend is not Backend.ninja or not have_cython_compiler(options.use_tmpdir)), TestCategory('rust', 'rust', should_skip_rust(backend)), TestCategory('d', 'd', backend is not Backend.ninja or not have_d_compiler()), TestCategory('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler(options.use_tmpdir)), From c80ece2410064b396baedd2da0bb8484e102a5dd Mon Sep 17 00:00:00 2001 From: Andrew McNulty Date: Wed, 14 Feb 2024 13:42:35 +0000 Subject: [PATCH 611/855] workflows: Trigger on all test harness changes The following workflows have been updated so that they are triggered when the any of the test harnesses are updated: macos, os-comp, msys2 Previously only changes to `run_unittests.py` caused these workflows to be executed. --- .github/workflows/macos.yml | 4 ++-- .github/workflows/msys2.yml | 4 ++-- .github/workflows/os_comp.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index bdc5f20c9c55..236b9792dba7 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -15,14 +15,14 @@ on: - "test cases/**" - "unittests/**" - ".github/workflows/macos.yml" - - "run_unittests.py" + - "run*tests.py" pull_request: paths: - "mesonbuild/**" - "test cases/**" - "unittests/**" - ".github/workflows/macos.yml" - - "run_unittests.py" + - "run*tests.py" permissions: contents: read diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index 0a949e3af62b..fe28a67edbad 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -15,14 +15,14 @@ on: - "test cases/**" - "unittests/**" - ".github/workflows/msys2.yml" - - "run_unittests.py" + - "run*tests.py" pull_request: paths: - "mesonbuild/**" - "test cases/**" - "unittests/**" - ".github/workflows/msys2.yml" - - "run_unittests.py" + - "run*tests.py" permissions: contents: read diff --git a/.github/workflows/os_comp.yml b/.github/workflows/os_comp.yml index e9f5b7a1c82f..1d779842e27a 100644 --- a/.github/workflows/os_comp.yml +++ b/.github/workflows/os_comp.yml @@ -16,7 +16,7 @@ on: - "unittests/**" - ".github/workflows/images.yml" - ".github/workflows/os_comp.yml" - - "run_unittests.py" + - "run*tests.py" pull_request: paths: - "mesonbuild/**" @@ -24,7 +24,7 @@ on: - "unittests/**" - ".github/workflows/images.yml" - ".github/workflows/os_comp.yml" - - "run_unittests.py" + - "run*tests.py" permissions: contents: read From abdb3afd7302147fac27551ada8cb91173194133 Mon Sep 17 00:00:00 2001 From: Esther Dalhuisen Date: Thu, 15 Feb 2024 18:08:19 +0100 Subject: [PATCH 612/855] coverage: pass .lcovrc config file to genhtml The .lcovrc file can contain several directives for genhtml, mostly pertaining the visualisation of the generated HTML report. Passing the config file to genhtml allows the user to customize their report. Fixes #12863 --- mesonbuild/scripts/coverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index d89213065ce5..2375e453ea57 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -145,7 +145,7 @@ def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build '--legend', '--show-details', '--branch-coverage', - covinfo]) + covinfo] + lcov_config) outfiles.append(('Html', pathlib.Path(htmloutdir, 'index.html'))) elif gcovr_exe and mesonlib.version_compare(gcovr_version, '>=3.3'): htmloutdir = os.path.join(log_dir, 'coveragereport') From 163d703a18b7d2766bd4db670c390ae59a4cc274 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sat, 10 Feb 2024 15:16:11 +0100 Subject: [PATCH 613/855] macros: Allow disabling verbose mode This allows using "--undefine __meson_verbose" to disable the verbose mode. This is useful when running rpmbuild in an interactive terminal and you don't want to be flooded with compilation outputs. We also add --quiet to the meson install macro if __meson_verbose is undefined to reduce the output generated by meson install. The default output stays the same, the output is only affected if __meson_verbose is explicitly undefined. --- data/macros.meson | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/macros.meson b/data/macros.meson index f5e3a15fda19..dcac9d98553c 100644 --- a/data/macros.meson +++ b/data/macros.meson @@ -1,6 +1,7 @@ %__meson %{_bindir}/meson %__meson_wrap_mode nodownload %__meson_auto_features enabled +%__meson_verbose 1 %meson \ %set_build_flags \ @@ -28,13 +29,14 @@ %{shrink:%{__meson} compile \ -C %{_vpath_builddir} \ -j %{_smp_build_ncpus} \ - --verbose \ + %{?__meson_verbose:--verbose} \ %{nil}} %meson_install \ %{shrink:DESTDIR=%{buildroot} %{__meson} install \ -C %{_vpath_builddir} \ --no-rebuild \ + %{!?__meson_verbose:--quiet} \ %{nil}} %meson_test \ From c46d0e733e7a06e71fb125add32e3e8ce31a129c Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Thu, 16 Feb 2023 22:33:29 +0900 Subject: [PATCH 614/855] doc: fix descriptions of dependency and find_program They accept list as documented --- docs/yaml/functions/find_program.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/yaml/functions/find_program.yaml b/docs/yaml/functions/find_program.yaml index 3153bd32786a..4a17e8637364 100644 --- a/docs/yaml/functions/find_program.yaml +++ b/docs/yaml/functions/find_program.yaml @@ -98,10 +98,10 @@ kwargs: instead of a not-found object. version: - type: str + type: str | list[str] since: 0.52.0 description: | - specifies the required version, see + Specifies the required version, see [[dependency]] for argument format. The version of the program is determined by running `program_name --version` command. If stdout is empty it fallbacks to stderr. If the output contains more text than simply a version From 43fe0061902f9d204eeeb8d4fef779480ec5487c Mon Sep 17 00:00:00 2001 From: Stephan Lachnit Date: Fri, 16 Feb 2024 13:40:25 +0100 Subject: [PATCH 615/855] Fix warning when using scan-build Using scan-build gives the following warning: "Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated." This commit fixes this issue by adding the setup keyword to the meson command. --- 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 782b264acc90..2606ac43ab44 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3574,7 +3574,7 @@ def generate_scanbuild(self) -> None: return cmd = self.environment.get_build_command() + \ ['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir, self.build.get_subproject_dir()] + \ - self.environment.get_build_command() + self.get_user_option_args() + self.environment.get_build_command() + ['setup'] + self.get_user_option_args() elem = self.create_phony_target('scan-build', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') From b290a8254122f53d6477b7ba24366d81cfc5e99c Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 8 Feb 2024 10:15:37 -0500 Subject: [PATCH 616/855] Fix KeyError in Python module 0e7fb07 introduced a subtile bug in the Python module. If a python version is found, but is missing a required module, it is added to the list of python installations, but the `run_bytecompile` attribute for that version was not initialized. Therefore, if any other python version added something to install, it was raising a KeyError when trying to read the `run_bytecompile` attribute for the python version with missing module. --- mesonbuild/modules/python.py | 2 +- test cases/python/5 modules kwarg/a.py | 0 test cases/python/5 modules kwarg/meson.build | 16 ++++++++++++++-- test cases/python/5 modules kwarg/test.json | 5 +++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 test cases/python/5 modules kwarg/a.py create mode 100644 test cases/python/5 modules kwarg/test.json diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 7a2cd2837733..59b5050c07b8 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -74,6 +74,7 @@ def sanity(self, state: T.Optional['ModuleState'] = None) -> bool: if ret: self.platlib = self._get_path(state, 'platlib') self.purelib = self._get_path(state, 'purelib') + self.run_bytecompile.setdefault(self.info['version'], False) return ret def _get_path(self, state: T.Optional['ModuleState'], key: str) -> str: @@ -544,7 +545,6 @@ def find_installation(self, state: 'ModuleState', args: T.Tuple[T.Optional[str]] assert isinstance(python, PythonExternalProgram), 'for mypy' python = copy.copy(python) python.pure = kwargs['pure'] - python.run_bytecompile.setdefault(python.info['version'], False) return python raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).') diff --git a/test cases/python/5 modules kwarg/a.py b/test cases/python/5 modules kwarg/a.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/python/5 modules kwarg/meson.build b/test cases/python/5 modules kwarg/meson.build index 41a9a4faee9a..6e745ba62e93 100644 --- a/test cases/python/5 modules kwarg/meson.build +++ b/test cases/python/5 modules kwarg/meson.build @@ -1,7 +1,19 @@ -project('python kwarg') +project('python kwarg', + default_options: [ + 'python.bytecompile=-1', + 'python.purelibdir=/pure', + ] +) py = import('python') -prog_python = py.find_installation('python3', modules : ['os', 'sys', 're']) +prog_python = py.find_installation('python3', modules : ['os', 'sys', 're'], pure: true) assert(prog_python.found() == true, 'python not found when should be') + +# In meson 1.2 - 1.3.2, there was a bug when a python installation +# with a different version did not have a module, and we try to install +# something with another python version... +py.find_installation('python3.7', modules: ['notamodule'], required: false) +prog_python.install_sources('a.py') + prog_python = py.find_installation('python3', modules : ['thisbetternotexistmod'], required : false) assert(prog_python.found() == false, 'python not found but reported as found') diff --git a/test cases/python/5 modules kwarg/test.json b/test cases/python/5 modules kwarg/test.json new file mode 100644 index 000000000000..cf874f102bef --- /dev/null +++ b/test cases/python/5 modules kwarg/test.json @@ -0,0 +1,5 @@ +{ + "installed": [ + { "type": "python_file", "file": "pure/a.py"} + ] +} \ No newline at end of file From 47acce8ec93ae73b5a95f3b21e35abb4b3c21f6a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 16 Feb 2024 14:42:51 -0800 Subject: [PATCH 617/855] Provide a better error message when mixing host and build machines Since we don't get a location for these errors, we can at least tell you which targets you happen to be mixing together that produce this problem. Ran into while trying to debug a target mixing bug. --- mesonbuild/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 934e7c1f01ab..066e6aa850a4 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1482,7 +1482,7 @@ def check_can_link_together(self, t: BuildTargetTypes) -> None: if not self.uses_rust() and links_with_rust_abi: raise InvalidArguments(f'Try to link Rust ABI library {t.name!r} with a non-Rust target {self.name!r}') if self.for_machine is not t.for_machine and (not links_with_rust_abi or t.rust_crate_type != 'proc-macro'): - msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' + msg = f'Tried to tied to mix a {t.for_machine} library ("{t.name}") with a {self.for_machine} target "{self.name}"' if self.environment.is_cross_build(): raise InvalidArguments(msg + ' This is not possible in a cross build.') else: From 4e5df4b3b7e0db0c4ed174f8b2de53b9004a1c45 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 14 Feb 2024 00:09:07 -0500 Subject: [PATCH 618/855] fix crash in generator.process() with an invalid preserve_path_from This code cleverly tried to use a fancy new pathlib.Path method to get the os.path.commonpath of two paths and check whether one is inside the other. It failed pretty badly, because of a hidden secret of pathlib: it is designed to throw random exceptions at all times (except when building os.PathLike interfaces) instead of performing useful work. Return to `os.path`. In particular, before this change, we wanted to check if files are NOT in a subpath of `preserve_path_from`, and raise a meson "ERROR: xxx" in such a case. However, the code to check for it would raise a python ValueError if that was the case, so we never got to the properly formatted error. --- mesonbuild/build.py | 7 +++++-- test cases/common/168 preserve gendir/meson.build | 5 +++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 066e6aa850a4..7aea229277ef 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1800,8 +1800,11 @@ def get_arglist(self, inname: str) -> T.List[str]: @staticmethod def is_parent_path(parent: str, trial: str) -> bool: - relpath = pathlib.PurePath(trial).relative_to(parent) - return relpath.parts[0] != '..' # For subdirs we can only go "down". + try: + common = os.path.commonpath((parent, trial)) + except ValueError: # Windows on different drives + return False + return pathlib.PurePath(common) == pathlib.PurePath(parent) def process_files(self, files: T.Iterable[T.Union[str, File, 'CustomTarget', 'CustomTargetIndex', 'GeneratedList']], state: T.Union['Interpreter', 'ModuleState'], diff --git a/test cases/common/168 preserve gendir/meson.build b/test cases/common/168 preserve gendir/meson.build index ce219f0d8c9e..d543b6019d6c 100644 --- a/test cases/common/168 preserve gendir/meson.build +++ b/test cases/common/168 preserve gendir/meson.build @@ -9,5 +9,10 @@ gen = generator(gprog, \ generated = gen.process('base.inp', 'com/mesonbuild/subbie.inp', preserve_path_from : meson.current_source_dir()) +testcase expect_error('generator.process: When using preserve_path_from, all input files must be in a subdirectory of the given dir.') + generated = gen.process('base.inp', 'com/mesonbuild/subbie.inp', + preserve_path_from : meson.current_source_dir() / 'com') +endtestcase + e = executable('testprog', 'testprog.c', generated) test('testprog', e) From a35d4d368a21f4b70afa3195da4d6292a649cb4c Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 7 May 2023 01:21:18 -0400 Subject: [PATCH 619/855] ciimage: fix pathological brokenness in homebrew packaging of python Followup to commit 5c479d7a13a518c18ccb4dc3b6bdd7bfc2a9bdb5. In this case, PEP 668 was created to allow a thing that Debian wanted, which is for `pip install foobar` to not break the system python. This despite the fact that the system python is fine, unless you use sudo pip which is discouraged for separate reasons, and it is in fact quite natural to install additional packages to the user site-packages. It isn't even the job of the operating system to decide whether the user site-packages is broken, whether the operating system gets the answer correct or not -- it is the job of the operating system to decide whether the operating system is broken, and that can be solved by e.g. enforcing a shebang policy for distribution-packaged software, which distros like Fedora do, and mandating not only that python shebangs do not contain `/usr/bin/env`, but that they *do* contain -s. Anyway, this entire kerfuffle is mostly just a bit of pointless interactive churn, but it bites pretty hard for our use case, which is a container image, so instead of failing to run because of theoretical conflicts with the base system (we specifically need base system integration...) we fail to run because 5 minutes into pulling homebrew updates at the very beginning, pip refuses point-blank to work. I especially do not know why it is the job of the operating system to throw errors intended for interactive users at people designing system integration containers who cannot "break" the system python anyway as it is thrown away after every use. Fix this by doing what homebrew should have done from the beginning, and opting containers out of this questionable feature entirely. --- .github/workflows/macos.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 236b9792dba7..cd58f9d455b3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -90,6 +90,10 @@ jobs: find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete sudo rm -rf /Library/Frameworks/Python.framework/ brew install --force python3 && brew unlink python3 && brew unlink python3 && brew link --overwrite python3 + # Delete nonsensical PEP 668 breakage. It is the wrong solution to the problem and isn't designed to be + # productive -- only victim blaming -- however it bites particularly badly because this is a container/VM + # See commit 5c479d7a13a518c18ccb4dc3b6bdd7bfc2a9bdb5 for a more thorough analysis. + find /usr/local/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 From 477783a65b6592b857d12b23abba6b1fb5dff01f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 15 Feb 2024 09:27:07 -0800 Subject: [PATCH 620/855] build: fix some type annotations for get_install_dir --- mesonbuild/build.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7aea229277ef..e97cc427d21e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -570,10 +570,11 @@ def get_default_install_dir(self) -> T.Tuple[str, str]: def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: raise NotImplementedError - def get_install_dir(self) -> T.Tuple[T.List[T.Union[str, Literal[False]]], str, Literal[False]]: + def get_install_dir(self) -> T.Tuple[T.List[T.Union[str, Literal[False]]], T.List[T.Optional[str]], bool]: # Find the installation directory. default_install_dir, default_install_dir_name = self.get_default_install_dir() - outdirs = self.get_custom_install_dir() + outdirs: T.List[T.Union[str, Literal[False]]] = self.get_custom_install_dir() + install_dir_names: T.List[T.Optional[str]] if outdirs and outdirs[0] != default_install_dir and outdirs[0] is not True: # Either the value is set to a non-default value, or is set to # False (which means we want this specific output out of many From 8283e4900dd071570083af3c1adf8c6cb264c70d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 15 Feb 2024 09:55:34 -0800 Subject: [PATCH 621/855] build: get_default_install_dir() can be (None, None) or (str, str) --- mesonbuild/build.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index e97cc427d21e..8e41f0bb02af 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -564,7 +564,7 @@ def __ge__(self, other: object) -> bool: return NotImplemented return self.get_id() >= other.get_id() - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: raise NotImplementedError def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: @@ -1103,7 +1103,7 @@ def get_link_dep_subdirs(self) -> T.AbstractSet[str]: result.update(i.get_link_dep_subdirs()) return result - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_libdir(), '{libdir}' def get_custom_install_dir(self) -> T.List[T.Union[str, Literal[False]]]: @@ -2030,7 +2030,7 @@ def process_kwargs(self, kwargs): if self.rust_crate_type != 'bin': raise InvalidArguments('Invalid rust_crate_type: must be "bin" for executables.') - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_bindir(), '{bindir}' def description(self): @@ -2141,7 +2141,7 @@ def post_init(self) -> None: def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: return {} - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_static_lib_dir(), '{libdir_static}' def type_suffix(self): @@ -2232,7 +2232,7 @@ def get_link_deps_mapping(self, prefix: str) -> T.Mapping[str, str]: mappings.update(result) return mappings - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_shared_lib_dir(), '{libdir_shared}' def determine_filenames(self): @@ -2468,7 +2468,7 @@ def __init__( # to build targets, see: https://github.com/mesonbuild/meson/issues/9492 self.force_soname = False - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_shared_module_dir(), '{moduledir_shared}' class BothLibraries(SecondLevelHolder): @@ -2607,7 +2607,7 @@ def __init__(self, # Whether to use absolute paths for all files on the commandline self.absolute_paths = absolute_paths - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return None, None def __repr__(self): @@ -2925,7 +2925,7 @@ def get_classpath_args(self): return ['-cp', os.pathsep.join(cp_paths)] return [] - def get_default_install_dir(self) -> T.Tuple[str, str]: + def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]: return self.environment.get_jar_dir(), '{jardir}' @dataclass(eq=False) From bc46ea22f73195f4bb1f857c9d19375229817e14 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 15 Feb 2024 10:19:16 -0800 Subject: [PATCH 622/855] modules/i18n: CustomTargets must have `install_dir` if installing Since they do not implement a default install dir like BuildTargets do. Fixes: #12843 --- mesonbuild/modules/i18n.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index c2a11dd207e0..27c9dc00e9b8 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -12,7 +12,7 @@ from .. import mesonlib from .. import mlog from ..interpreter.type_checking import CT_BUILD_BY_DEFAULT, CT_INPUT_KW, INSTALL_TAG_KW, OUTPUT_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, in_set_validator -from ..interpreterbase import FeatureNew +from ..interpreterbase import FeatureNew, InvalidArguments from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, noPosargs, typed_kwargs, typed_pos_args from ..programs import ExternalProgram from ..scripts.gettext import read_linguas @@ -155,6 +155,9 @@ def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]: KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})), ) def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue: + if kwargs['install'] and not kwargs['install_dir']: + raise InvalidArguments('i18n.merge_file: "install_dir" keyword argument must be set when "install" is true.') + if self.tools['msgfmt'] is None or not self.tools['msgfmt'].found(): self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD) if isinstance(self.tools['msgfmt'], ExternalProgram): @@ -339,6 +342,9 @@ def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') - KwargInfo('mo_targets', ContainerTypeInfo(list, build.CustomTarget), required=True), ) def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'ItsJoinFile') -> ModuleReturnValue: + if kwargs['install'] and not kwargs['install_dir']: + raise InvalidArguments('i18n.itstool_join: "install_dir" keyword argument must be set when "install" is true.') + if self.tools['itstool'] is None: self.tools['itstool'] = state.find_program('itstool', for_machine=mesonlib.MachineChoice.BUILD) mo_targets = kwargs['mo_targets'] From 413c288d0dbee0c3ac96624084acec15c25de017 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 16 Feb 2024 10:02:32 -0800 Subject: [PATCH 623/855] wrap: Mark some methods of Resolver as protected These aren't meant to be called externally. Additionally, they expect some statefulness from the `resolve()` method, and by making them protected we can more easily remove this statefulness. --- mesonbuild/wrap/wrap.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index c355c6de9061..6032967d9dce 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -481,15 +481,15 @@ def has_buildfile() -> bool: if os.path.isdir(cached_directory): self.copy_tree(cached_directory, self.dirname) elif self.wrap.type == 'file': - self.get_file() + self._get_file() else: self.check_can_download() if self.wrap.type == 'git': - self.get_git() + self._get_git() elif self.wrap.type == "hg": - self.get_hg() + self._get_hg() elif self.wrap.type == "svn": - self.get_svn() + self._get_svn() else: raise WrapException(f'Unknown wrap type {self.wrap.type!r}') try: @@ -555,7 +555,7 @@ def resolve_git_submodule(self) -> bool: return False raise WrapException(f'Unknown git submodule output: {out!r}') - def get_file(self) -> None: + def _get_file(self) -> None: path = self.get_file_internal('source') extract_dir = self.subdir_root # Some upstreams ship packages that do not have a leading directory. @@ -568,7 +568,7 @@ def get_file(self) -> None: except OSError as e: raise WrapException(f'failed to unpack archive with error: {str(e)}') from e - def get_git(self) -> None: + def _get_git(self) -> None: if not GIT: raise WrapException(f'Git program not found, cannot download {self.packagename}.wrap via git.') revno = self.wrap.get('revision') @@ -633,7 +633,7 @@ def is_git_full_commit_id(self, revno: str) -> bool: result = all(ch in '0123456789AaBbCcDdEeFf' for ch in revno) return result - def get_hg(self) -> None: + def _get_hg(self) -> None: revno = self.wrap.get('revision') hg = shutil.which('hg') if not hg: @@ -644,7 +644,7 @@ def get_hg(self) -> None: subprocess.check_call([hg, 'checkout', revno], cwd=self.dirname) - def get_svn(self) -> None: + def _get_svn(self) -> None: revno = self.wrap.get('revision') svn = shutil.which('svn') if not svn: @@ -743,7 +743,7 @@ def get_data_with_backoff(self, urlstring: str) -> T.Tuple[str, str]: time.sleep(d) return self.get_data(urlstring) - def download(self, what: str, ofname: str, fallback: bool = False) -> None: + def _download(self, what: str, ofname: str, fallback: bool = False) -> None: self.check_can_download() srcurl = self.wrap.get(what + ('_fallback_url' if fallback else '_url')) mlog.log('Downloading', mlog.bold(self.packagename), what, 'from', mlog.bold(srcurl)) @@ -756,7 +756,7 @@ def download(self, what: str, ofname: str, fallback: bool = False) -> None: except WrapException: if not fallback: if what + '_fallback_url' in self.wrap.values: - return self.download(what, ofname, fallback=True) + return self._download(what, ofname, fallback=True) mlog.log('A fallback URL could be specified using', mlog.bold(what + '_fallback_url'), 'key in the wrap file') raise @@ -773,7 +773,7 @@ def get_file_internal(self, what: str) -> str: return cache_path os.makedirs(self.cachedir, exist_ok=True) - self.download(what, cache_path) + self._download(what, cache_path) return cache_path else: path = Path(self.wrap.filesdir) / filename From 9a493f541f2f7c63e0ce1ab5ac1e6cc29be5fff5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 16 Feb 2024 10:03:56 -0800 Subject: [PATCH 624/855] wrap: correct return annotation of `Resolver.get_from_wrapdb()` It returns `None | PackageDefinition`, not `PackageDefinition` --- mesonbuild/wrap/wrap.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 6032967d9dce..ba4c5e383daf 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -351,7 +351,7 @@ def load_wrapdb(self) -> None: self.wrapdb_provided_deps.update({i: name for i in info.get('dependency_names', [])}) self.wrapdb_provided_programs.update({i: name for i in info.get('program_names', [])}) - def get_from_wrapdb(self, subp_name: str) -> PackageDefinition: + def get_from_wrapdb(self, subp_name: str) -> T.Optional[PackageDefinition]: info = self.wrapdb.get(subp_name) if not info: return None @@ -405,11 +405,10 @@ def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> self.packagename = packagename self.directory = packagename wrap = self.wraps.get(packagename) - if not wrap: + if wrap is None: wrap = self.get_from_wrapdb(packagename) - if not wrap: - m = f'Neither a subproject directory nor a {self.packagename}.wrap file was found.' - raise WrapNotFoundException(m) + if wrap is None: + raise WrapNotFoundException(f'Neither a subproject directory nor a {self.packagename}.wrap file was found.') self.wrap = wrap self.directory = self.wrap.directory From 0abc8729bfd0e12cc28f0e3958b232a1a6a0d98c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 16 Feb 2024 10:06:19 -0800 Subject: [PATCH 625/855] wrap: remove useless set of `Resolver.directory` It's overwritten before it's ever read --- mesonbuild/wrap/wrap.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index ba4c5e383daf..49f54e1583c7 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -403,7 +403,6 @@ def find_program_provider(self, names: T.List[str]) -> T.Optional[str]: def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> T.Tuple[str, Method]: self.packagename = packagename - self.directory = packagename wrap = self.wraps.get(packagename) if wrap is None: wrap = self.get_from_wrapdb(packagename) From 39e1bf19fb653ac4f040e48b9a33aaa59dea1196 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 16 Feb 2024 10:13:51 -0800 Subject: [PATCH 626/855] wrap: remove Resolver.packagename Instead of being instance state, it's passed around. This isn't a big deal internally since most of the users are protected, and the only time an external change is required is a couple of places in msubprojects, which is fine because the information is available. Fixes: #12869 --- mesonbuild/msubprojects.py | 4 ++-- mesonbuild/wrap/wrap.py | 33 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py index d8afd92ddec6..15db3f928a61 100755 --- a/mesonbuild/msubprojects.py +++ b/mesonbuild/msubprojects.py @@ -250,7 +250,7 @@ def git_reset(self, revision: str) -> bool: # avoid any data lost by mistake. self.git_stash() self.git_output(['reset', '--hard', 'FETCH_HEAD']) - self.wrap_resolver.apply_patch() + self.wrap_resolver.apply_patch(self.wrap.name) self.wrap_resolver.apply_diff_files() except GitException as e: self.log(' -> Could not reset', mlog.bold(self.repo_dir), 'to', mlog.bold(revision)) @@ -603,7 +603,7 @@ def packagefiles(self) -> bool: if not os.path.isdir(self.repo_dir): self.log(' -> Not downloaded yet') return True - self.wrap_resolver.apply_patch() + self.wrap_resolver.apply_patch(self.wrap.name) return True if options.save: if 'patch_directory' not in self.wrap.values: diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 49f54e1583c7..a8efd163a5d6 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -402,12 +402,11 @@ def find_program_provider(self, names: T.List[str]) -> T.Optional[str]: return None def resolve(self, packagename: str, force_method: T.Optional[Method] = None) -> T.Tuple[str, Method]: - self.packagename = packagename wrap = self.wraps.get(packagename) if wrap is None: wrap = self.get_from_wrapdb(packagename) if wrap is None: - raise WrapNotFoundException(f'Neither a subproject directory nor a {self.packagename}.wrap file was found.') + raise WrapNotFoundException(f'Neither a subproject directory nor a {packagename}.wrap file was found.') self.wrap = wrap self.directory = self.wrap.directory @@ -479,11 +478,11 @@ def has_buildfile() -> bool: if os.path.isdir(cached_directory): self.copy_tree(cached_directory, self.dirname) elif self.wrap.type == 'file': - self._get_file() + self._get_file(packagename) else: self.check_can_download() if self.wrap.type == 'git': - self._get_git() + self._get_git(packagename) elif self.wrap.type == "hg": self._get_hg() elif self.wrap.type == "svn": @@ -491,7 +490,7 @@ def has_buildfile() -> bool: else: raise WrapException(f'Unknown wrap type {self.wrap.type!r}') try: - self.apply_patch() + self.apply_patch(packagename) self.apply_diff_files() except Exception: windows_proof_rmtree(self.dirname) @@ -553,8 +552,8 @@ def resolve_git_submodule(self) -> bool: return False raise WrapException(f'Unknown git submodule output: {out!r}') - def _get_file(self) -> None: - path = self.get_file_internal('source') + def _get_file(self, packagename: str) -> None: + path = self._get_file_internal('source', packagename) extract_dir = self.subdir_root # Some upstreams ship packages that do not have a leading directory. # Create one for them. @@ -566,9 +565,9 @@ def _get_file(self) -> None: except OSError as e: raise WrapException(f'failed to unpack archive with error: {str(e)}') from e - def _get_git(self) -> None: + def _get_git(self, packagename: str) -> None: if not GIT: - raise WrapException(f'Git program not found, cannot download {self.packagename}.wrap via git.') + raise WrapException(f'Git program not found, cannot download {packagename}.wrap via git.') revno = self.wrap.get('revision') checkout_cmd = ['-c', 'advice.detachedHead=false', 'checkout', revno, '--'] is_shallow = False @@ -741,10 +740,10 @@ def get_data_with_backoff(self, urlstring: str) -> T.Tuple[str, str]: time.sleep(d) return self.get_data(urlstring) - def _download(self, what: str, ofname: str, fallback: bool = False) -> None: + def _download(self, what: str, ofname: str, packagename: str, fallback: bool = False) -> None: self.check_can_download() srcurl = self.wrap.get(what + ('_fallback_url' if fallback else '_url')) - mlog.log('Downloading', mlog.bold(self.packagename), what, 'from', mlog.bold(srcurl)) + mlog.log('Downloading', mlog.bold(packagename), what, 'from', mlog.bold(srcurl)) try: dhash, tmpfile = self.get_data_with_backoff(srcurl) expected = self.wrap.get(what + '_hash').lower() @@ -754,24 +753,24 @@ def _download(self, what: str, ofname: str, fallback: bool = False) -> None: except WrapException: if not fallback: if what + '_fallback_url' in self.wrap.values: - return self._download(what, ofname, fallback=True) + return self._download(what, ofname, packagename, fallback=True) mlog.log('A fallback URL could be specified using', mlog.bold(what + '_fallback_url'), 'key in the wrap file') raise os.rename(tmpfile, ofname) - def get_file_internal(self, what: str) -> str: + def _get_file_internal(self, what: str, packagename: str) -> str: filename = self.wrap.get(what + '_filename') if what + '_url' in self.wrap.values: cache_path = os.path.join(self.cachedir, filename) if os.path.exists(cache_path): self.check_hash(what, cache_path) - mlog.log('Using', mlog.bold(self.packagename), what, 'from cache.') + mlog.log('Using', mlog.bold(packagename), what, 'from cache.') return cache_path os.makedirs(self.cachedir, exist_ok=True) - self._download(what, cache_path) + self._download(what, cache_path, packagename) return cache_path else: path = Path(self.wrap.filesdir) / filename @@ -782,12 +781,12 @@ def get_file_internal(self, what: str) -> str: return path.as_posix() - def apply_patch(self) -> None: + def apply_patch(self, packagename: str) -> None: if 'patch_filename' in self.wrap.values and 'patch_directory' in self.wrap.values: m = f'Wrap file {self.wrap.basename!r} must not have both "patch_filename" and "patch_directory"' raise WrapException(m) if 'patch_filename' in self.wrap.values: - path = self.get_file_internal('patch') + path = self._get_file_internal('patch', packagename) try: shutil.unpack_archive(path, self.subdir_root) except Exception: From 95b3b9f710a19726f44eb76b15a6690e90c55b37 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 11 Dec 2023 11:48:21 -0800 Subject: [PATCH 627/855] coredata: use a Protocol for shared options between setup configure and dist These are all passed around interchangably inside Meson, so use a shared protocol for them. --- mesonbuild/ast/introspection.py | 13 +++++------ mesonbuild/coredata.py | 32 +++++++++++++++++++++------ mesonbuild/environment.py | 6 ++--- mesonbuild/interpreter/interpreter.py | 4 +--- mesonbuild/mdist.py | 3 ++- run_tests.py | 11 ++++++--- 6 files changed, 45 insertions(+), 24 deletions(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 095f30c14fd1..f9a6e11c0eb4 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -5,7 +5,6 @@ # or an interpreter-based tool from __future__ import annotations -import argparse import copy import os import typing as T @@ -31,13 +30,13 @@ 'static_library', 'both_libraries' ] -class IntrospectionHelper(argparse.Namespace): +class IntrospectionHelper: # mimic an argparse namespace - def __init__(self, cross_file: str): - super().__init__() - self.cross_file = cross_file - self.native_file: str = None - self.cmd_line_options: T.Dict[str, str] = {} + def __init__(self, cross_file: T.Optional[str]): + self.cross_file = [cross_file] if cross_file is not None else [] + self.native_file: T.List[str] = [] + self.cmd_line_options: T.Dict[OptionKey, str] = {} + self.projectoptions: T.List[str] = [] def __eq__(self, other: object) -> bool: return NotImplemented diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a6a14c8abf56..e361eb2fcf43 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2023 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -31,6 +32,8 @@ import typing as T if T.TYPE_CHECKING: + from typing_extensions import Protocol + from . import dependencies from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode from .dependencies.detect import TV_DepID @@ -38,6 +41,21 @@ from .mesonlib import FileOrString from .cmake.traceparser import CMakeCacheEntry + class SharedCMDOptions(Protocol): + + """Representation of command line options from Meson setup, configure, + and dist. + + :param projectoptions: The raw list of command line options given + :param cmd_line_options: command line options parsed into an OptionKey: + str mapping + """ + + cmd_line_options: T.Dict[OptionKey, str] + projectoptions: T.List[str] + cross_file: T.List[str] + native_file: T.List[str] + OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], 'OptionsView'] MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]'] KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView'] @@ -546,7 +564,7 @@ def languages(self) -> T.Set[str]: class CoreData: - def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command: T.List[str]): + def __init__(self, options: SharedCMDOptions, scratch_dir: str, meson_command: T.List[str]): self.lang_guids = { 'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', 'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', @@ -587,7 +605,7 @@ def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command: self.init_builtins('') @staticmethod - def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]: + def __load_config_files(options: SharedCMDOptions, scratch_dir: str, ftype: str) -> T.List[str]: # Need to try and make the passed filenames absolute because when the # files are parsed later we'll have chdir()d. if ftype == 'cross': @@ -1123,7 +1141,7 @@ def parse_machine_files(filenames: T.List[str], sourcedir: str): def get_cmd_line_file(build_dir: str) -> str: return os.path.join(build_dir, 'meson-private', 'cmd_line.txt') -def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: +def read_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None: filename = get_cmd_line_file(build_dir) if not os.path.isfile(filename): return @@ -1145,7 +1163,7 @@ def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: # literal_eval to get it into the list of strings. options.native_file = ast.literal_eval(properties.get('native_file', '[]')) -def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: +def write_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None: filename = get_cmd_line_file(build_dir) config = CmdLineFileParser() @@ -1160,7 +1178,7 @@ def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: with open(filename, 'w', encoding='utf-8') as f: config.write(f) -def update_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: +def update_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None: filename = get_cmd_line_file(build_dir) config = CmdLineFileParser() config.read(filename) @@ -1168,7 +1186,7 @@ def update_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: with open(filename, 'w', encoding='utf-8') as f: config.write(f) -def format_cmd_line_options(options: argparse.Namespace) -> str: +def format_cmd_line_options(options: SharedCMDOptions) -> str: cmdline = ['-D{}={}'.format(str(k), v) for k, v in options.cmd_line_options.items()] if options.cross_file: cmdline += [f'--cross-file={f}' for f in options.cross_file] @@ -1226,7 +1244,7 @@ def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[Op result[k] = value return result -def parse_cmd_line_options(args: argparse.Namespace) -> None: +def parse_cmd_line_options(args: SharedCMDOptions) -> None: args.cmd_line_options = create_options_dict(args.projectoptions) # Merge builtin options set with --option into the dict. diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 326a1c9ede52..14e4ee8564d2 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2020 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -35,7 +36,6 @@ from mesonbuild import envconfig if T.TYPE_CHECKING: - import argparse from configparser import ConfigParser from .compilers import Compiler @@ -485,7 +485,7 @@ class Environment: log_dir = 'meson-logs' info_dir = 'meson-info' - def __init__(self, source_dir: str, build_dir: str, options: 'argparse.Namespace') -> None: + def __init__(self, source_dir: str, build_dir: str, options: coredata.SharedCMDOptions) -> None: self.source_dir = source_dir self.build_dir = build_dir # Do not try to create build directories when build_dir is none. @@ -780,7 +780,7 @@ def _set_default_properties_from_env(self) -> None: self.properties[for_machine].properties.setdefault(name, p_env) break - def create_new_coredata(self, options: 'argparse.Namespace') -> None: + def create_new_coredata(self, options: coredata.SharedCMDOptions) -> None: # WARNING: Don't use any values from coredata in __init__. It gets # re-initialized with project options by the interpreter during # build file parsing. diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index deb3a9caf11a..7e9fe4a55087 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -106,8 +106,6 @@ import copy if T.TYPE_CHECKING: - import argparse - from . import kwargs as kwtypes from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs @@ -269,7 +267,7 @@ def __init__( ast: T.Optional[mparser.CodeBlockNode] = None, is_translated: bool = False, relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None, - user_defined_options: T.Optional['argparse.Namespace'] = None, + user_defined_options: T.Optional[coredata.SharedCMDOptions] = None, ) -> None: super().__init__(_build.environment.get_source_dir(), subdir, subproject) self.active_projectname = '' diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 67442885a389..f9a63bc027c5 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2017 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -304,7 +305,7 @@ def check_dist(packagename: str, meson_command: ImmutableListProtocol[str], extr def create_cmdline_args(bld_root: str) -> T.List[str]: parser = argparse.ArgumentParser() msetup_argparse(parser) - args = parser.parse_args([]) + args = T.cast('coredata.SharedCMDOptions', parser.parse_args([])) coredata.parse_cmd_line_options(args) coredata.read_cmd_line_file(bld_root, args) args.cmd_line_options.pop(OptionKey('backend'), '') diff --git a/run_tests.py b/run_tests.py index 5347be87befe..20765321981e 100755 --- a/run_tests.py +++ b/run_tests.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team +# Copyright © 2023-2024 Intel Corporation + +from __future__ import annotations # Work around some pathlib bugs... from mesonbuild import _pathlib @@ -33,6 +36,9 @@ from mesonbuild.coredata import backendlist, version as meson_version from mesonbuild.mesonlib import OptionKey, setup_vsenv +if T.TYPE_CHECKING: + from mesonbuild.coredata import SharedCMDOptions + NINJA_1_9_OR_NEWER = False NINJA_CMD = None # If we're on CI, detecting ninja for every subprocess unit test that we run is slow @@ -133,9 +139,8 @@ class FakeCompilerOptions: def __init__(self): self.value = [] -# TODO: use a typing.Protocol here -def get_fake_options(prefix: str = '') -> argparse.Namespace: - opts = argparse.Namespace() +def get_fake_options(prefix: str = '') -> SharedCMDOptions: + opts = T.cast('SharedCMDOptions', argparse.Namespace()) opts.native_file = [] opts.cross_file = None opts.wrap_mode = None From 5d1c3ae78700b90ad3f0b5ceb653c191eaf45758 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 11 Dec 2023 12:06:31 -0800 Subject: [PATCH 628/855] mconf|msetup: use Protocol for argparse options These are much easier to handle as one commit since msetup calls mconf internally. This has found one case where things are being carefully crafted to work in mconf even though msetup has slightly different options --- mesonbuild/mconf.py | 12 ++++++++++-- mesonbuild/msetup.py | 33 +++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index b9547f0b251d..8c18eab3102d 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -20,8 +21,15 @@ from .mesonlib import MachineChoice, OptionKey if T.TYPE_CHECKING: + from typing_extensions import Protocol import argparse + class CMDOptions(coredata.SharedCMDOptions, Protocol): + + builddir: str + clearcache: bool + pager: bool + # cannot be TV_Loggable, because non-ansidecorators do direct string concat LOGLINE = T.Union[str, mlog.AnsiDecorator] @@ -293,7 +301,7 @@ def print_nondefault_buildtype_options(self) -> None: for m in mismatching: mlog.log(f'{m[0]:21}{m[1]:10}{m[2]:10}') -def run_impl(options: argparse.Namespace, builddir: str) -> int: +def run_impl(options: CMDOptions, builddir: str) -> int: print_only = not options.cmd_line_options and not options.clearcache c = None try: @@ -325,7 +333,7 @@ def run_impl(options: argparse.Namespace, builddir: str) -> int: pass return 0 -def run(options: argparse.Namespace) -> int: +def run(options: CMDOptions) -> int: coredata.parse_cmd_line_options(options) builddir = os.path.abspath(os.path.realpath(options.builddir)) return run_impl(options, builddir) diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 90227842fb0c..c1d71e2e55e2 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2018 The Meson development team +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations @@ -11,6 +12,21 @@ from . import build, coredata, environment, interpreter, mesonlib, mintro, mlog from .mesonlib import MesonException +if T.TYPE_CHECKING: + from typing_extensions import Protocol + from .coredata import SharedCMDOptions + + class CMDOptions(SharedCMDOptions, Protocol): + + profile: bool + fatal_warnings: bool + reconfigure: bool + wipe: bool + clearcache: bool + builddir: str + sourcedir: str + pager: bool + git_ignore_file = '''# This file is autogenerated by Meson. If you change or delete it, it won't be recreated. * ''' @@ -53,7 +69,7 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('sourcedir', nargs='?', default=None) class MesonApp: - def __init__(self, options: argparse.Namespace) -> None: + def __init__(self, options: CMDOptions) -> None: self.options = options (self.source_dir, self.build_dir) = self.validate_dirs() if options.wipe: @@ -173,7 +189,7 @@ def generate(self, capture: bool = False, vslite_ctx: T.Optional[dict] = None) - def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: T.Optional[dict]) -> T.Optional[dict]: # Get all user defined options, including options that have been defined # during a previous invocation or using meson configure. - user_defined_options = argparse.Namespace(**vars(self.options)) + user_defined_options = T.cast('CMDOptions', argparse.Namespace(**vars(self.options))) coredata.read_cmd_line_file(self.build_dir, user_defined_options) mlog.debug('Build started at', datetime.datetime.now().isoformat()) @@ -294,7 +310,7 @@ def finalize_postconf_hooks(self, b: build.Build, intr: interpreter.Interpreter) for mod in intr.modules.values(): mod.postconf_hook(b) -def run_genvslite_setup(options: argparse.Namespace) -> None: +def run_genvslite_setup(options: CMDOptions) -> None: # With --genvslite, we essentially want to invoke multiple 'setup' iterations. I.e. - # meson setup ... builddirprefix_debug # meson setup ... builddirprefix_debugoptimized @@ -328,13 +344,18 @@ def run_genvslite_setup(options: argparse.Namespace) -> None: app = MesonApp(options) app.generate(capture=False, vslite_ctx=vslite_ctx) -def run(options: T.Union[argparse.Namespace, T.List[str]]) -> int: - if not isinstance(options, argparse.Namespace): +def run(options: T.Union[CMDOptions, T.List[str]]) -> int: + if isinstance(options, list): parser = argparse.ArgumentParser() add_arguments(parser) - options = parser.parse_args(options) + options = T.cast('CMDOptions', parser.parse_args(options)) coredata.parse_cmd_line_options(options) + # Msetup doesn't actually use this option, but we pass msetup options to + # mconf, and it does. We won't actally hit the path that uses it, but don't + # lie + options.pager = False + if mesonlib.OptionKey('genvslite') in options.cmd_line_options.keys(): run_genvslite_setup(options) else: From 20c9f3e621581b2ed9a1c6872b86c4dc9390aa6b Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 4 Jan 2024 08:56:42 -0500 Subject: [PATCH 629/855] Fix base options not reconfigurable Fixes #11732 --- mesonbuild/coredata.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e361eb2fcf43..658ae47b1118 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1003,9 +1003,11 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], # not differ between them even when they are valid for both. if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding: continue - # Skip base, compiler, and backend options, they are handled when + # Skip compiler and backend options, they are handled when # adding languages and setting backend. - if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}: + if k.type in {OptionType.COMPILER, OptionType.BACKEND}: + continue + if k.type == OptionType.BASE and env.first_invocation: continue options[k] = v From 6cd2ba42fff771d958c535f6024d2887823c0d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 9 Feb 2024 13:20:56 +0100 Subject: [PATCH 630/855] env2mfile: move language args to `built-in options` As putting them in the `properties` section is considered deprecated, and Meson would then complain when trying to consume the resulting machine file. --- mesonbuild/scripts/env2mfile.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index 3fb9b8a9509d..2dfe6b05ef7d 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -238,7 +238,7 @@ def write_machine_file(infos: MachineInfo, ofilename: str, write_system_info: bo write_args_line(ofile, exename, exe) ofile.write('\n') - ofile.write('[properties]\n') + ofile.write('[built-in options]\n') all_langs = list(set(infos.compile_args.keys()).union(set(infos.link_args.keys()))) all_langs.sort() for lang in all_langs: @@ -246,6 +246,9 @@ def write_machine_file(infos: MachineInfo, ofilename: str, write_system_info: bo write_args_line(ofile, lang + '_args', infos.compile_args[lang]) if lang in infos.link_args: write_args_line(ofile, lang + '_link_args', infos.link_args[lang]) + ofile.write('\n') + + ofile.write('[properties]\n') for k, v in infos.properties.items(): write_args_line(ofile, k, v) ofile.write('\n') From 2c7833b1c9e77d244bdbfc2b96422854f36fc68c Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Mon, 15 Jan 2024 14:36:50 -0500 Subject: [PATCH 631/855] doc: fix compiler.preprocess varargs documentation This was inherited from documentation of build target, but some sentences do not make sense in the context of the preprocessor. --- docs/yaml/objects/compiler.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index db2ff05fdf97..c86ef7f4ccb0 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -663,7 +663,17 @@ methods: will receive the same arguments (include directories, defines, etc) as with normal compilation. That includes for example args added with `add_project_arguments()`, or on the command line with `-Dc_args=-DFOO`. - varargs_inherit: _build_target_base + varargs: + name: source + type: str | file | custom_tgt | custom_idx | generated_list + description: | + Input source to preprocess. The following types are supported: + + - Strings relative to the current source directory + - [[@file]] objects defined in any preceding build file + - The return value of configure-time generators such as [[configure_file]] + - The return value of build-time generators such as + [[custom_target]] or [[generator.process]] kwargs_inherit: - compiler._include_directories kwargs: From 6a8330af598753d5982a37933beeac2d6b565386 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 10:00:52 -0700 Subject: [PATCH 632/855] rust/bindgen: Use Meson rules for C++ headers Bindgen natively only considers .hpp to be C++ headers, but Meson considers some additional extensions including .hh and .hxx to be C++. --- docs/markdown/snippets/rust-bindgen-cpp.md | 6 ++++++ mesonbuild/modules/rust.py | 25 +++++++++++++++------- test cases/rust/12 bindgen/meson.build | 16 +++++++++++++- test cases/rust/12 bindgen/src/cpp.rs | 19 ++++++++++++++++ test cases/rust/12 bindgen/src/header.hpp | 9 ++++++++ test cases/rust/12 bindgen/src/impl.cpp | 7 ++++++ 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 docs/markdown/snippets/rust-bindgen-cpp.md create mode 100644 test cases/rust/12 bindgen/src/cpp.rs create mode 100644 test cases/rust/12 bindgen/src/header.hpp create mode 100644 test cases/rust/12 bindgen/src/impl.cpp diff --git a/docs/markdown/snippets/rust-bindgen-cpp.md b/docs/markdown/snippets/rust-bindgen-cpp.md new file mode 100644 index 000000000000..e12e0f966fc1 --- /dev/null +++ b/docs/markdown/snippets/rust-bindgen-cpp.md @@ -0,0 +1,6 @@ +## Bindgen will now use Meson's hueristic for what is a C++ header + +Bindgen natively assumes that a file with the extension `.cpp` is a C++ header, +but that everything else is a C header. Meson has a whole list of extensions it +considers to be C++, and now will automatically look for those extensions and +set bindgen to treat those as C++ diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 96e1e6f16ebf..caa1be2967df 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -12,7 +12,7 @@ from .. import mlog from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) -from ..compilers.compilers import are_asserts_disabled +from ..compilers.compilers import are_asserts_disabled, lang_suffixes from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File @@ -230,13 +230,6 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu elif isinstance(s, CustomTarget): depends.append(s) - # We only want include directories and defines, other things may not be valid - cargs = state.get_option('args', state.subproject, lang='c') - assert isinstance(cargs, list), 'for mypy' - for a in itertools.chain(state.global_args.get('c', []), state.project_args.get('c', []), cargs): - if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): - clang_args.append(a) - if self._bindgen_bin is None: self._bindgen_bin = state.find_program('bindgen') @@ -248,6 +241,22 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu else: name = header.get_outputs()[0] + # bindgen assumes that C++ headers will be called .hpp. We want to + # ensure that anything Meson considers a C++ header is treated as one. + language = 'cpp' if os.path.splitext(name)[1][1:] in lang_suffixes['cpp'] else 'c' + + # We only want include directories and defines, other things may not be valid + cargs = state.get_option('args', state.subproject, lang=language) + assert isinstance(cargs, list), 'for mypy' + for a in itertools.chain(state.global_args.get(language, []), state.project_args.get(language, []), cargs): + if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): + clang_args.append(a) + + # bindgen assumes that C++ headers will be called .hpp. We want to + # ensure that anything Meson considers a C++ header is treated as one. + if language == 'cpp': + clang_args.extend(['-x', 'c++']) + cmd = self._bindgen_bin.get_command() + \ [ '@INPUT@', '--output', diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index e36e9e2d1a7b..840a8afabae9 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -1,7 +1,7 @@ # SPDX-license-identifer: Apache-2.0 # Copyright © 2021-2022 Intel Corporation -project('rustmod bindgen', ['c', 'rust'], meson_version : '>= 0.63') +project('rustmod bindgen', ['c', 'cpp', 'rust'], meson_version : '>= 0.63') prog_bindgen = find_program('bindgen', required : false) if not prog_bindgen.found() @@ -107,3 +107,17 @@ gp_exe = executable( ) test('global and project arguments', gp_exe) + +cpp_lib = static_library('cpplib', 'src/impl.cpp') + +cpp_bind = rust.bindgen( + input : 'src/header.hpp', + output : 'generated-cpp.rs', +) + +cpp_exe = executable( + 'cpp_exe', + structured_sources(['src/cpp.rs', cpp_bind]), + link_with : cpp_lib, +) +test('cpp', cpp_exe) diff --git a/test cases/rust/12 bindgen/src/cpp.rs b/test cases/rust/12 bindgen/src/cpp.rs new file mode 100644 index 000000000000..51a594cc4f4e --- /dev/null +++ b/test cases/rust/12 bindgen/src/cpp.rs @@ -0,0 +1,19 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2023 Intel Corporation + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("generated-cpp.rs"); + +fn main() { + let mut instance = std::mem::MaybeUninit::::uninit(); + let val: i32; + unsafe { + MyClass_MyClass(instance.as_mut_ptr()); + val = instance.assume_init_mut().method(); + } + let success = val == 7; + std::process::exit(!success as i32); +} diff --git a/test cases/rust/12 bindgen/src/header.hpp b/test cases/rust/12 bindgen/src/header.hpp new file mode 100644 index 000000000000..3f01c5f7d379 --- /dev/null +++ b/test cases/rust/12 bindgen/src/header.hpp @@ -0,0 +1,9 @@ +#pragma once + +class MyClass { + public: + MyClass(); + int method() const; + private: + int val; +}; diff --git a/test cases/rust/12 bindgen/src/impl.cpp b/test cases/rust/12 bindgen/src/impl.cpp new file mode 100644 index 000000000000..39c8f2ebe8f7 --- /dev/null +++ b/test cases/rust/12 bindgen/src/impl.cpp @@ -0,0 +1,7 @@ +#include "header.hpp" + +MyClass::MyClass() : val{7} {}; + +int MyClass::method() const { + return val; +} From 8ac434694395037e242318e6926c85c1fcccd9b8 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 17 Oct 2023 11:07:32 -0700 Subject: [PATCH 633/855] compilers: 'H' is a C++ header We list other C++ header types in this list, so H should be included --- mesonbuild/compilers/compilers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 74cb0bfe4d14..b59733745806 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -48,7 +48,7 @@ # First suffix is the language's default. lang_suffixes = { 'c': ('c',), - 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino', 'ixx', 'C'), + 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino', 'ixx', 'C', 'H'), 'cuda': ('cu',), # f90, f95, f03, f08 are for free-form fortran ('f90' recommended) # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended) From 05d49c6990aedb850266f22b40442af7a54e13fc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 10:07:32 -0700 Subject: [PATCH 634/855] modules/rust: Allow explicitly setting the language to bind This may be of particular use when a header is .h but should be treated as a C++ header instead of a C header. --- docs/markdown/Rust-module.md | 3 ++- .../snippets/rust-bindgen-language.md | 5 +++++ mesonbuild/modules/rust.py | 21 ++++++++++++++----- test cases/rust/12 bindgen/cpp/meson.build | 19 +++++++++++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 docs/markdown/snippets/rust-bindgen-language.md create mode 100644 test cases/rust/12 bindgen/cpp/meson.build diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 8ef8c433ee81..0ed5410c7239 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -3,7 +3,7 @@ short-description: Rust language integration module authors: - name: Dylan Baker email: dylan@pnwbakers.com - years: [2020, 2021, 2022] + years: [2020, 2021, 2022, 2024] ... # Rust module @@ -62,6 +62,7 @@ It takes the following keyword arguments - `c_args`: a list of string arguments to pass to clang untouched - `args`: a list of string arguments to pass to `bindgen` untouched. - `dependencies`: a list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) +- `language`: A literal string value of `c` or `cpp`. When set this will force bindgen to treat a source as the given language. Defaults to checking based on the input file extension. *(since 1.4.0)* ```meson rust = import('unstable-rust') diff --git a/docs/markdown/snippets/rust-bindgen-language.md b/docs/markdown/snippets/rust-bindgen-language.md new file mode 100644 index 000000000000..edfb3bfb4b87 --- /dev/null +++ b/docs/markdown/snippets/rust-bindgen-language.md @@ -0,0 +1,5 @@ +## Overriding bindgen language setting + +Even though Meson will now tell bindgen to do the right thing in most cases, +there may still be cases where Meson does not have the intended behavior, +specifically with headers with a `.h` suffix, but are C++ headers. diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index caa1be2967df..4978f1205eea 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -13,7 +13,10 @@ from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) from ..compilers.compilers import are_asserts_disabled, lang_suffixes -from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS +from ..interpreter.type_checking import ( + DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, + INCLUDE_DIRECTORIES, SOURCES_VARARGS, NoneType, in_set_validator +) from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File @@ -27,7 +30,7 @@ from ..programs import ExternalProgram, OverrideProgram from ..interpreter.type_checking import SourcesVarargsType - from typing_extensions import TypedDict + from typing_extensions import TypedDict, Literal class FuncTest(_kwargs.BaseTest): @@ -44,6 +47,7 @@ class FuncBindgen(TypedDict): input: T.List[SourceInputs] output: str dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + language: T.Optional[Literal['c', 'cpp']] class RustModule(ExtensionModule): @@ -187,6 +191,7 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func listify=True, required=True, ), + KwargInfo('language', (str, NoneType), since='1.4.0', validator=in_set_validator({'c', 'cpp'})), INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, DEPENDENCIES_KW.evolve(since='1.0.0'), @@ -243,7 +248,15 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu # bindgen assumes that C++ headers will be called .hpp. We want to # ensure that anything Meson considers a C++ header is treated as one. - language = 'cpp' if os.path.splitext(name)[1][1:] in lang_suffixes['cpp'] else 'c' + language = kwargs['language'] + if language is None: + ext = os.path.splitext(name)[1][1:] + if ext in lang_suffixes['cpp']: + language = 'cpp' + elif ext == 'h': + language = 'c' + else: + raise InterpreterException(f'Unknown file type extension for: {name}') # We only want include directories and defines, other things may not be valid cargs = state.get_option('args', state.subproject, lang=language) @@ -252,8 +265,6 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): clang_args.append(a) - # bindgen assumes that C++ headers will be called .hpp. We want to - # ensure that anything Meson considers a C++ header is treated as one. if language == 'cpp': clang_args.extend(['-x', 'c++']) diff --git a/test cases/rust/12 bindgen/cpp/meson.build b/test cases/rust/12 bindgen/cpp/meson.build new file mode 100644 index 000000000000..8e7103f81790 --- /dev/null +++ b/test cases/rust/12 bindgen/cpp/meson.build @@ -0,0 +1,19 @@ +# SPDX-license-identifer: Apache-2.0 +# Copyright © 2021-2023 Intel Corporation + +fs = import('fs') + +cpp_header = fs.copyfile('../src/header.hpp', 'cpp_header.h') + +cpp_bind_override = rust.bindgen( + input : cpp_header, + output : 'generated-cpp.rs', + language : 'cpp', +) + +cpp_exe2 = executable( + 'cpp_exe2', + structured_sources(['../src/cpp.rs', cpp_bind_override]), + link_with : cpp_lib, +) +test('cpp-forced', cpp_exe2) From a75ced6d50a3d479eda6dcdc9c3482493f2161f0 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 10:16:40 -0700 Subject: [PATCH 635/855] modules/rust: inject a C/C++ standard for bindgen Especially for C++ this is very important. --- docs/markdown/snippets/rust-bindgen-std.md | 3 +++ mesonbuild/modules/rust.py | 17 +++++++++++++++++ test cases/rust/12 bindgen/meson.build | 8 ++++++-- test cases/rust/12 bindgen/test.json | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 docs/markdown/snippets/rust-bindgen-std.md diff --git a/docs/markdown/snippets/rust-bindgen-std.md b/docs/markdown/snippets/rust-bindgen-std.md new file mode 100644 index 000000000000..2c94f9c2ca2c --- /dev/null +++ b/docs/markdown/snippets/rust-bindgen-std.md @@ -0,0 +1,3 @@ +## Bindgen now uses the same C/C++ as the project as a whole + +Which is very important for C++ bindings. diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 4978f1205eea..6a00fb3ceb8e 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -268,6 +268,23 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu if language == 'cpp': clang_args.extend(['-x', 'c++']) + # Add the C++ standard to the clang arguments. Attempt to translate VS + # extension versions into the nearest standard version + std = state.get_option('std', lang=language) + assert isinstance(std, str), 'for mypy' + if std.startswith('vc++'): + if std.endswith('latest'): + mlog.warning('Attempting to translate vc++latest into a clang compatible version.', + 'Currently this is hardcoded for c++20', once=True, fatal=False) + std = 'c++20' + else: + mlog.debug('The current C++ standard is a Visual Studio extension version.', + 'bindgen will use a the nearest C++ standard instead') + std = std[1:] + + if std != 'none': + clang_args.append(f'-std={std}') + cmd = self._bindgen_bin.get_command() + \ [ '@INPUT@', '--output', diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index 840a8afabae9..09575815c4af 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -1,7 +1,11 @@ # SPDX-license-identifer: Apache-2.0 -# Copyright © 2021-2022 Intel Corporation +# Copyright © 2021-2024 Intel Corporation -project('rustmod bindgen', ['c', 'cpp', 'rust'], meson_version : '>= 0.63') +project( + 'rustmod bindgen', + ['c', 'cpp', 'rust'], + meson_version : '>= 0.63', + default_options : ['cpp_std=c++17']) prog_bindgen = find_program('bindgen', required : false) if not prog_bindgen.found() diff --git a/test cases/rust/12 bindgen/test.json b/test cases/rust/12 bindgen/test.json index d45543b13223..25fafd2e120b 100644 --- a/test cases/rust/12 bindgen/test.json +++ b/test cases/rust/12 bindgen/test.json @@ -4,7 +4,7 @@ }, "stdout": [ { - "line": "test cases/rust/12 bindgen/meson.build:38: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." + "line": "test cases/rust/12 bindgen/meson.build:42: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." } ] } From 9752b89100a9ffc42a6eb4a788f806958bda1107 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 16:01:37 -0700 Subject: [PATCH 636/855] modules: fix find_program.wanted Which should be `str | list[str]`, not `str | None`. --- mesonbuild/modules/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index e7aeb8af1fb0..8d6b20f5a3b5 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -73,7 +73,7 @@ def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDi def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.FileOrString]], required: bool = True, version_func: T.Optional[ProgramVersionFunc] = None, - wanted: T.Optional[str] = None, silent: bool = False, + wanted: T.Union[str, T.List[str]] = '', silent: bool = False, for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.Executable, OverrideProgram]: if not isinstance(prog, list): prog = [prog] From e7f20efc8bd123bfc2c325198866850694612a23 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 16 Oct 2023 16:02:28 -0700 Subject: [PATCH 637/855] modules/rust: allow setting a version constraint on bindgen This allows us to ensure that the bindgen we're using is suitable for our purpose. --- docs/markdown/Rust-module.md | 1 + mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/modules/rust.py | 4 +++- test cases/rust/12 bindgen/meson.build | 9 +++++++-- test cases/rust/12 bindgen/test.json | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 0ed5410c7239..11966ca8ccea 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -63,6 +63,7 @@ It takes the following keyword arguments - `args`: a list of string arguments to pass to `bindgen` untouched. - `dependencies`: a list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) - `language`: A literal string value of `c` or `cpp`. When set this will force bindgen to treat a source as the given language. Defaults to checking based on the input file extension. *(since 1.4.0)* +- `bindgen_version`: a list of string version values. When set the found bindgen binary must conform to these constraints. *(since 1.4.0)* ```meson rust = import('unstable-rust') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 7e9fe4a55087..5603b99375c0 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 6a00fb3ceb8e..fb8528088142 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -48,6 +48,7 @@ class FuncBindgen(TypedDict): output: str dependencies: T.List[T.Union[Dependency, ExternalLibrary]] language: T.Optional[Literal['c', 'cpp']] + bindgen_version: T.List[str] class RustModule(ExtensionModule): @@ -192,6 +193,7 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func required=True, ), KwargInfo('language', (str, NoneType), since='1.4.0', validator=in_set_validator({'c', 'cpp'})), + KwargInfo('bindgen_version', ContainerTypeInfo(list, str), default=[], listify=True, since='1.4.0'), INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, DEPENDENCIES_KW.evolve(since='1.0.0'), @@ -236,7 +238,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu depends.append(s) if self._bindgen_bin is None: - self._bindgen_bin = state.find_program('bindgen') + self._bindgen_bin = state.find_program('bindgen', wanted=kwargs['bindgen_version']) name: str if isinstance(header, File): diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index 09575815c4af..a88ed81de94e 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -32,13 +32,18 @@ if result.returncode() != 0 error('MESON_SKIP_TEST bindgen does not seem to work') endif +rust = import('unstable-rust') + +# Check version, this case is obviously impossible +testcase expect_error('Program \'bindgen\' not found or not executable') + rust.bindgen(input : 'include/other.h', output : 'other.rs', bindgen_version : ['< 0.1', '> 10000']) +endtestcase + # This is to test the include_directories argument to bindgen inc = include_directories('include') c_lib = static_library('clib', 'src/source.c', include_directories : inc) -rust = import('unstable-rust') - gen = rust.bindgen( input : 'src/header.h', output : 'header.rs', diff --git a/test cases/rust/12 bindgen/test.json b/test cases/rust/12 bindgen/test.json index 25fafd2e120b..a3b7e29f30e9 100644 --- a/test cases/rust/12 bindgen/test.json +++ b/test cases/rust/12 bindgen/test.json @@ -4,7 +4,7 @@ }, "stdout": [ { - "line": "test cases/rust/12 bindgen/meson.build:42: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." + "line": "test cases/rust/12 bindgen/meson.build:47: WARNING: Project targets '>= 0.63' but uses feature introduced in '1.0.0': \"rust.bindgen\" keyword argument \"include_directories\" of type array[str]." } ] } From 1b40fb1089090b4d23d46a10239e1bfea7ba53a8 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 18 Aug 2023 01:50:24 -0500 Subject: [PATCH 638/855] Add location nodes to FeatureNews in the fs module --- mesonbuild/modules/fs.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index d3f37dcb93ab..c76e744abddb 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -97,7 +97,7 @@ def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[st @typed_pos_args('fs.is_absolute', (str, File)) def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File): - FeatureNew('fs.is_absolute_file', '0.59.0').use(state.subproject) + FeatureNew('fs.is_absolute_file', '0.59.0').use(state.subproject, location=state.current_node) return PurePath(str(args[0])).is_absolute() @noKwargs @@ -119,7 +119,7 @@ def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T @typed_pos_args('fs.is_symlink', (str, File)) def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File): - FeatureNew('fs.is_symlink_file', '0.59.0').use(state.subproject) + FeatureNew('fs.is_symlink_file', '0.59.0').use(state.subproject, location=state.current_node) return self._absolute_dir(state, args[0]).is_symlink() @noKwargs @@ -136,7 +136,7 @@ def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T @typed_pos_args('fs.hash', (str, File), str) def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.hash_file', '0.59.0').use(state.subproject) + FeatureNew('fs.hash_file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) if not file.is_file(): raise MesonException(f'{file} is not a file and therefore cannot be hashed') @@ -152,7 +152,7 @@ def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: @typed_pos_args('fs.size', (str, File)) def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int: if isinstance(args[0], File): - FeatureNew('fs.size_file', '0.59.0').use(state.subproject) + FeatureNew('fs.size_file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) if not file.is_file(): raise MesonException(f'{file} is not a file and therefore cannot be sized') @@ -165,7 +165,7 @@ def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Di @typed_pos_args('fs.is_samepath', (str, File), (str, File)) def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File) or isinstance(args[1], File): - FeatureNew('fs.is_samepath_file', '0.59.0').use(state.subproject) + FeatureNew('fs.is_samepath_file', '0.59.0').use(state.subproject, location=state.current_node) file1 = self._resolve_dir(state, args[0]) file2 = self._resolve_dir(state, args[1]) if not file1.exists(): @@ -181,7 +181,7 @@ def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileO @typed_pos_args('fs.replace_suffix', (str, File), str) def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.replace_suffix_file', '0.59.0').use(state.subproject) + FeatureNew('fs.replace_suffix_file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.with_suffix(args[1]) return str(new) @@ -190,7 +190,7 @@ def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str @typed_pos_args('fs.parent', (str, File)) def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.parent_file', '0.59.0').use(state.subproject) + FeatureNew('fs.parent_file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.parent return str(new) @@ -199,7 +199,7 @@ def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T. @typed_pos_args('fs.name', (str, File)) def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.name_file', '0.59.0').use(state.subproject) + FeatureNew('fs.name_file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.name return str(new) @@ -209,7 +209,7 @@ def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Di @FeatureNew('fs.stem', '0.54.0') def stem(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.stem_file', '0.59.0').use(state.subproject) + FeatureNew('fs.stem_file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.stem return str(new) From db8246b3fc52994eac2cccd1416e64e36c3369e2 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 18 Aug 2023 01:48:01 -0500 Subject: [PATCH 639/855] Alphabetize the fs module methods dict --- mesonbuild/modules/fs.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index c76e744abddb..296c7a8721dd 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -45,23 +45,23 @@ class FSModule(ExtensionModule): def __init__(self, interpreter: 'Interpreter') -> None: super().__init__(interpreter) self.methods.update({ - 'expanduser': self.expanduser, - 'is_absolute': self.is_absolute, 'as_posix': self.as_posix, + 'copyfile': self.copyfile, 'exists': self.exists, - 'is_symlink': self.is_symlink, - 'is_file': self.is_file, - 'is_dir': self.is_dir, + 'expanduser': self.expanduser, 'hash': self.hash, - 'size': self.size, + 'is_absolute': self.is_absolute, + 'is_dir': self.is_dir, + 'is_file': self.is_file, 'is_samepath': self.is_samepath, - 'replace_suffix': self.replace_suffix, - 'parent': self.parent, + 'is_symlink': self.is_symlink, 'name': self.name, - 'stem': self.stem, + 'parent': self.parent, 'read': self.read, - 'copyfile': self.copyfile, 'relative_to': self.relative_to, + 'replace_suffix': self.replace_suffix, + 'size': self.size, + 'stem': self.stem, }) def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: From 138e0fe9841b44a6d0402b66bbd0c10966cfe87b Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 10 Oct 2023 12:09:15 -0400 Subject: [PATCH 640/855] env.unset method --- docs/markdown/snippets/environment_unset.md | 4 ++ docs/yaml/objects/env.yaml | 7 +++ mesonbuild/interpreter/interpreterobjects.py | 7 +++ mesonbuild/utils/core.py | 17 +++++++ test cases/common/273 environment/meson.build | 50 +++++++++++++++++++ test cases/common/273 environment/testenv.py | 12 +++++ 6 files changed, 97 insertions(+) create mode 100644 docs/markdown/snippets/environment_unset.md create mode 100644 test cases/common/273 environment/meson.build create mode 100644 test cases/common/273 environment/testenv.py diff --git a/docs/markdown/snippets/environment_unset.md b/docs/markdown/snippets/environment_unset.md new file mode 100644 index 000000000000..887bc0d47cab --- /dev/null +++ b/docs/markdown/snippets/environment_unset.md @@ -0,0 +1,4 @@ +## New `unset()` method on `environment` objects + +[[@env]] now has an [[env.unset]] method to ensure an existing environment +is *not* defined. diff --git a/docs/yaml/objects/env.yaml b/docs/yaml/objects/env.yaml index d784c68b8b9d..714da4fe422a 100644 --- a/docs/yaml/objects/env.yaml +++ b/docs/yaml/objects/env.yaml @@ -82,3 +82,10 @@ methods: description: The values to set kwargs_inherit: env.append + +- name: unset + returns: void + since: 1.4.0 + description: | + Unset the specified environment variable. If this variable does not exist, + nothing happens. diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 4320cf52e924..9aefc2f97dd5 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -285,6 +285,7 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu def __init__(self, obj: mesonlib.EnvironmentVariables, interpreter: 'Interpreter'): super().__init__(obj, interpreter) self.methods.update({'set': self.set_method, + 'unset': self.unset_method, 'append': self.append_method, 'prepend': self.prepend_method, }) @@ -309,6 +310,12 @@ def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSepara name, values = args 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.held_object.unset(args[0]) + @typed_pos_args('environment.append', str, varargs=str, min_varargs=1) @typed_kwargs('environment.append', ENV_SEPARATOR_KW) def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None: diff --git a/mesonbuild/utils/core.py b/mesonbuild/utils/core.py index 1b005cf95ca7..92f9d2c70d40 100644 --- a/mesonbuild/utils/core.py +++ b/mesonbuild/utils/core.py @@ -63,6 +63,7 @@ def __init__(self, values: T.Optional[EnvInitValueType] = None, self.envvars: T.List[T.Tuple[T.Callable[[T.Dict[str, str], str, T.List[str], str, T.Optional[str]], str], str, T.List[str], str]] = [] # The set of all env vars we have operations for. Only used for self.has_name() self.varnames: T.Set[str] = set() + self.unset_vars: T.Set[str] = set() if values: init_func = getattr(self, init_method) @@ -92,16 +93,30 @@ def merge(self, other: EnvironmentVariables) -> None: for method, name, values, separator in other.envvars: self.varnames.add(name) self.envvars.append((method, name, values, separator)) + if name in self.unset_vars: + self.unset_vars.remove(name) + self.unset_vars.update(other.unset_vars) def set(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + if name in self.unset_vars: + raise MesonException(f'You cannot set the already unset variable {name!r}') self.varnames.add(name) self.envvars.append((self._set, name, values, separator)) + def unset(self, name: str) -> None: + if name in self.varnames: + raise MesonException(f'You cannot unset the {name!r} variable because it is already set') + self.unset_vars.add(name) + def append(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + if name in self.unset_vars: + raise MesonException(f'You cannot append to unset variable {name!r}') self.varnames.add(name) self.envvars.append((self._append, name, values, separator)) def prepend(self, name: str, values: T.List[str], separator: str = os.pathsep) -> None: + if name in self.unset_vars: + raise MesonException(f'You cannot prepend to unset variable {name!r}') self.varnames.add(name) self.envvars.append((self._prepend, name, values, separator)) @@ -124,6 +139,8 @@ def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) for method, name, values, separator in self.envvars: default_value = default_fmt.format(name) if default_fmt else None env[name] = method(env, name, values, separator, default_value) + for name in self.unset_vars: + env.pop(name, None) return env diff --git a/test cases/common/273 environment/meson.build b/test cases/common/273 environment/meson.build new file mode 100644 index 000000000000..af15c1b551ea --- /dev/null +++ b/test cases/common/273 environment/meson.build @@ -0,0 +1,50 @@ +project( + 'environment', + meson_version: '>=1.4.0', +) + +testenv = find_program(files('testenv.py')) + + +env = environment() +env.unset('foo') +test('not set', testenv, args: ['foo'], env: env) + +testcase expect_error('You cannot set the already unset variable \'foo\'') + env.set('foo', 'bar') +endtestcase + +testcase expect_error('You cannot append to unset variable \'foo\'') + env.append('foo', 'bar') +endtestcase + +testcase expect_error('You cannot prepend to unset variable \'foo\'') + env.prepend('foo', 'bar') +endtestcase + + +env1 = environment('foo=bar', method: 'append', separator: ':') +env1.append('foo', 'baz', separator: ':') +test('append', testenv, args: ['foo', 'bar:baz'], env: env1) + +testcase expect_error('You cannot unset the \'foo\' variable because it is already set') + env1.unset('foo') +endtestcase + + +env2 = environment(['foo=baz'], method: 'prepend', separator: ':') +env2.prepend('foo', 'bar', separator: ':') +test('prepend', testenv, args: ['foo', 'bar:baz'], env: env2) + +testcase expect_error('You cannot unset the \'foo\' variable because it is already set') + env2.unset('foo') +endtestcase + + +env3 = environment({'foo': 'foobar'}, method: 'set', separator: ':') +env3.set('foo', 'qux') +test('reset', testenv, args: ['foo', 'qux'], env: env3) + +testcase expect_error('You cannot unset the \'foo\' variable because it is already set') + env3.unset('foo') +endtestcase diff --git a/test cases/common/273 environment/testenv.py b/test cases/common/273 environment/testenv.py new file mode 100644 index 000000000000..1a59b8237c52 --- /dev/null +++ b/test cases/common/273 environment/testenv.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import os +import sys + +key = sys.argv[1] +expected = sys.argv[2] if len(sys.argv) > 2 else None + +if os.environ.get(key) == expected: + sys.exit(0) + +sys.exit(f'Expected {expected!r}, was {os.environ.get(key)!r}') From 715dc27b2b8432d9749df985f262de8a8347c59b Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 14 Feb 2024 08:57:35 -0500 Subject: [PATCH 641/855] Detect utf8 bom from meson build files Some text editors on Windows may use utf8bom encoding by default. Prevent crash and properly report misencoded files. Fixes #12766. --- mesonbuild/interpreterbase/interpreterbase.py | 9 +++++---- mesonbuild/mparser.py | 4 ++++ test cases/failing/130 utf8 with bom/meson.build | 3 +++ test cases/failing/130 utf8 with bom/test.json | 8 ++++++++ test cases/failing/131 utf8 with bom subdir/meson.build | 3 +++ .../failing/131 utf8 with bom subdir/subdir/meson.build | 1 + test cases/failing/131 utf8 with bom subdir/test.json | 8 ++++++++ test cases/failing/132 utf8 with bom options/meson.build | 1 + .../failing/132 utf8 with bom options/meson.options | 1 + test cases/failing/132 utf8 with bom options/test.json | 8 ++++++++ 10 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 test cases/failing/130 utf8 with bom/meson.build create mode 100644 test cases/failing/130 utf8 with bom/test.json create mode 100644 test cases/failing/131 utf8 with bom subdir/meson.build create mode 100644 test cases/failing/131 utf8 with bom subdir/subdir/meson.build create mode 100644 test cases/failing/131 utf8 with bom subdir/test.json create mode 100644 test cases/failing/132 utf8 with bom options/meson.build create mode 100644 test cases/failing/132 utf8 with bom options/meson.options create mode 100644 test cases/failing/132 utf8 with bom options/test.json diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 365e2fd4bf16..47dd46f328bd 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -107,10 +107,11 @@ def load_root_meson_file(self) -> None: self.handle_meson_version_from_ast() except mparser.ParseException as me: me.file = mesonfile - # try to detect parser errors from new syntax added by future - # meson versions, and just tell the user to update meson - self.ast = me.ast - self.handle_meson_version_from_ast() + if me.ast: + # try to detect parser errors from new syntax added by future + # meson versions, and just tell the user to update meson + self.ast = me.ast + self.handle_meson_version_from_ast() raise me def parse_project(self) -> None: diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 28235b613fc7..baccd2753e59 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -96,6 +96,10 @@ def __eq__(self, other: object) -> bool: class Lexer: def __init__(self, code: str): + if code.startswith(codecs.BOM_UTF8.decode('utf-8')): + line, *_ = code.split('\n', maxsplit=1) + raise ParseException('Builder file must be encoded in UTF-8 (with no BOM)', line, lineno=0, colno=0) + self.code = code self.keywords = {'true', 'false', 'if', 'else', 'elif', 'endif', 'and', 'or', 'not', 'foreach', 'endforeach', diff --git a/test cases/failing/130 utf8 with bom/meson.build b/test cases/failing/130 utf8 with bom/meson.build new file mode 100644 index 000000000000..492a0c69130b --- /dev/null +++ b/test cases/failing/130 utf8 with bom/meson.build @@ -0,0 +1,3 @@ +project('utf8 with bom') + +subdir('subdir') diff --git a/test cases/failing/130 utf8 with bom/test.json b/test cases/failing/130 utf8 with bom/test.json new file mode 100644 index 000000000000..2292bebe3950 --- /dev/null +++ b/test cases/failing/130 utf8 with bom/test.json @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "line": "test cases/failing/130 utf8 with bom/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + } + ] + } + \ No newline at end of file diff --git a/test cases/failing/131 utf8 with bom subdir/meson.build b/test cases/failing/131 utf8 with bom subdir/meson.build new file mode 100644 index 000000000000..8d3bbd7e8e7b --- /dev/null +++ b/test cases/failing/131 utf8 with bom subdir/meson.build @@ -0,0 +1,3 @@ +project('utf8 with bom subdir') + +subdir('subdir') diff --git a/test cases/failing/131 utf8 with bom subdir/subdir/meson.build b/test cases/failing/131 utf8 with bom subdir/subdir/meson.build new file mode 100644 index 000000000000..dbf2b9cc7757 --- /dev/null +++ b/test cases/failing/131 utf8 with bom subdir/subdir/meson.build @@ -0,0 +1 @@ +a = 'Hello, World!' diff --git a/test cases/failing/131 utf8 with bom subdir/test.json b/test cases/failing/131 utf8 with bom subdir/test.json new file mode 100644 index 000000000000..72cc5152dfc1 --- /dev/null +++ b/test cases/failing/131 utf8 with bom subdir/test.json @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "line": "test cases/failing/131 utf8 with bom subdir/subdir/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + } + ] + } + \ No newline at end of file diff --git a/test cases/failing/132 utf8 with bom options/meson.build b/test cases/failing/132 utf8 with bom options/meson.build new file mode 100644 index 000000000000..50413e031044 --- /dev/null +++ b/test cases/failing/132 utf8 with bom options/meson.build @@ -0,0 +1 @@ +project('utf8 with bom options') diff --git a/test cases/failing/132 utf8 with bom options/meson.options b/test cases/failing/132 utf8 with bom options/meson.options new file mode 100644 index 000000000000..250c03279711 --- /dev/null +++ b/test cases/failing/132 utf8 with bom options/meson.options @@ -0,0 +1 @@ +option('someoption', type : 'string', value : 'optval', description : 'An option') diff --git a/test cases/failing/132 utf8 with bom options/test.json b/test cases/failing/132 utf8 with bom options/test.json new file mode 100644 index 000000000000..c09f48e6a00a --- /dev/null +++ b/test cases/failing/132 utf8 with bom options/test.json @@ -0,0 +1,8 @@ +{ + "stdout": [ + { + "line": "test cases/failing/132 utf8 with bom options/meson.options:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + } + ] + } + \ No newline at end of file From 8ba0ea68017b489b0a461abbd375f319dc7a48f3 Mon Sep 17 00:00:00 2001 From: Sam James Date: Sat, 10 Feb 2024 16:56:29 +0000 Subject: [PATCH 642/855] mtest: set MSAN_OPTIONS to abort by default Followup to 7b7d2e060b447de9c2642848847370a58711ac1c which handles ASAN and UBSAN. It turns out that MSAN needs the same treatment. I've checked other sanitizers like HWASAN and TSAN - it looks like they may both need it too, but Meson doesn't currently suppose those anyway (see https://github.com/mesonbuild/meson/pull/12648). Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- docs/markdown/Unit-tests.md | 8 ++++---- docs/markdown/snippets/sanitizers_test.md | 6 ++++++ docs/yaml/functions/test.yaml | 7 ++++--- mesonbuild/mtest.py | 2 ++ 4 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 docs/markdown/snippets/sanitizers_test.md diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 7ad95d2649c1..dc509a8189b3 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -38,11 +38,11 @@ set to a random value between 1..255. This can help find memory leaks on configurations using glibc, including with non-GCC compilers. This feature can be disabled as discussed in [[test]]. -### ASAN_OPTIONS and UBSAN_OPTIONS +### ASAN_OPTIONS, UBSAN_OPTIONS, and MSAN_OPTIONS -By default, the environment variables `ASAN_OPTIONS` and `UBSAN_OPTIONS` are -set to enable aborting on detected violations and to give a backtrace. This -feature can be disabled as discussed in [[test]]. +By default, the environment variables `ASAN_OPTIONS`, `UBSAN_OPTIONS`, and +`MSAN_OPTIONS` are set to enable aborting on detected violations and to give a +backtrace. This feature can be disabled as discussed in [[test]]. ## Coverage diff --git a/docs/markdown/snippets/sanitizers_test.md b/docs/markdown/snippets/sanitizers_test.md new file mode 100644 index 000000000000..de9385253dc0 --- /dev/null +++ b/docs/markdown/snippets/sanitizers_test.md @@ -0,0 +1,6 @@ +## Tests now abort on errors by default under more sanitizers + +Sanitizers like MemorySanitizer do not abort +by default on detected violations. Meson now exports `MSAN_OPTIONS` (in addition to +`ASAN_OPTIONS` and `UBSAN_OPTIONS` from a previous release) when unset in the +environment to provide sensible abort-by-default behavior. diff --git a/docs/yaml/functions/test.yaml b/docs/yaml/functions/test.yaml index 622b7c3b0ba0..d56822e5828a 100644 --- a/docs/yaml/functions/test.yaml +++ b/docs/yaml/functions/test.yaml @@ -33,9 +33,10 @@ description: | test(..., env: nomalloc, ...) ``` - By default, the environment variables `ASAN_OPTIONS` and `UBSAN_OPTIONS` are - set to enable aborting on detected violations and to give a backtrace. To suppress - this, `ASAN_OPTIONS` and `UBSAN_OPTIONS` can be set in the environment. + By default, the environment variables `ASAN_OPTIONS`, `UBSAN_OPTIONS`, + and `MSAN_OPTIONS` are set to enable aborting on detected violations and to + give a backtrace. To suppress this, `ASAN_OPTIONS`, `UBSAN_OPTIONS`, or + `MSAN_OPTIONS` can be set in the environment. In addition to running individual executables as test cases, `test()` can also be used to invoke an external test harness. In this case, diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index d9ae783d963a..b43f165ed606 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1414,6 +1414,8 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, env['ASAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1' if ('UBSAN_OPTIONS' not in env or not env['UBSAN_OPTIONS']): env['UBSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' + if ('MSAN_OPTIONS' not in env or not env['MSAN_OPTIONS']): + env['UBSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0: timeout = None From 11f2e07071d062f31a69de531faa0a5d68b1f5bc Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 23 Feb 2024 11:40:15 -0500 Subject: [PATCH 643/855] Allow using CustomTarget as test executable Fixes #6567 --- .../test_using_custom_target_executable.md | 4 ++++ docs/yaml/functions/benchmark.yaml | 5 +++-- mesonbuild/backend/backends.py | 4 ++-- mesonbuild/interpreter/interpreter.py | 17 ++++++++++++----- mesonbuild/interpreter/interpreterobjects.py | 4 ++-- mesonbuild/mtest.py | 5 +++++ .../273 customtarget exe for test/generate.py | 14 ++++++++++++++ .../273 customtarget exe for test/meson.build | 14 ++++++++++++++ 8 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 docs/markdown/snippets/test_using_custom_target_executable.md create mode 100644 test cases/common/273 customtarget exe for test/generate.py create mode 100644 test cases/common/273 customtarget exe for test/meson.build diff --git a/docs/markdown/snippets/test_using_custom_target_executable.md b/docs/markdown/snippets/test_using_custom_target_executable.md new file mode 100644 index 000000000000..e8b08da6b2fe --- /dev/null +++ b/docs/markdown/snippets/test_using_custom_target_executable.md @@ -0,0 +1,4 @@ +## Use `custom_target` as test executable + +The [[test]] function now accepts [[@custom_tgt]] and [[@custom_idx]] for the +command to execute. diff --git a/docs/yaml/functions/benchmark.yaml b/docs/yaml/functions/benchmark.yaml index 9d0ca3116130..0323b26e41b9 100644 --- a/docs/yaml/functions/benchmark.yaml +++ b/docs/yaml/functions/benchmark.yaml @@ -22,8 +22,9 @@ posargs: description: The *unique* test id executable: - type: exe | jar | external_program | file - description: The program to execute + type: exe | jar | external_program | file | custom_tgt | custom_idx + description: | + The program to execute. *(Since 1.4.0)* A CustomTarget is also accepted. kwargs: args: diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 92cc9fb51d34..c3be900ab4bf 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1160,7 +1160,7 @@ def extract_dll_paths(cls, target: build.BuildTarget) -> T.Set[str]: return results def determine_windows_extra_paths( - self, target: T.Union[build.BuildTarget, build.CustomTarget, programs.ExternalProgram, mesonlib.File, str], + 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]: """On Windows there is no such thing as an rpath. @@ -1269,7 +1269,7 @@ def create_test_serialisation(self, tests: T.List['Test']) -> T.List[TestSeriali t.is_parallel, cmd_args, t_env, t.should_fail, t.timeout, t.workdir, extra_paths, t.protocol, t.priority, - isinstance(exe, build.Target), + isinstance(exe, (build.Target, build.CustomTargetIndex)), isinstance(exe, build.Executable), [x.get_id() for x in depends], self.environment.coredata.version, diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 5603b99375c0..aaffec0b966e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2151,17 +2151,17 @@ def func_generator(self, node: mparser.FunctionNode, self.generators.append(gen) return gen - @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File)) + @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)) @typed_kwargs('benchmark', *TEST_KWS) def func_benchmark(self, node: mparser.BaseNode, args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], kwargs: 'kwtypes.FuncBenchmark') -> None: self.add_test(node, args, kwargs, False) - @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File)) + @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)) @typed_kwargs('test', *TEST_KWS, KwargInfo('is_parallel', bool, default=True)) def func_test(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]], kwargs: 'kwtypes.FuncTest') -> None: self.add_test(node, args, kwargs, True) @@ -2175,7 +2175,7 @@ def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariables, T.Dict[str, 'TY return ENV_KW.convertor(envlist) def make_test(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]], kwargs: 'kwtypes.BaseTest') -> Test: name = args[0] if ':' in name: @@ -2188,6 +2188,10 @@ def make_test(self, node: mparser.BaseNode, raise InvalidArguments('Tried to use not-found external program as test exe') elif isinstance(exe, mesonlib.File): exe = self.find_program_impl([exe]) + elif isinstance(exe, build.CustomTarget): + kwargs.setdefault('depends', []).append(exe) + elif isinstance(exe, build.CustomTargetIndex): + kwargs.setdefault('depends', []).append(exe.target) env = self.unpack_env_kwarg(kwargs) @@ -2218,8 +2222,11 @@ def make_test(self, node: mparser.BaseNode, kwargs['verbose']) def add_test(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]], kwargs: T.Dict[str, T.Any], is_base_test: bool): + if isinstance(args[1], (build.CustomTarget, build.CustomTargetIndex)): + FeatureNew.single_use('test with CustomTarget as command', '1.4.0', self.subproject) + t = self.make_test(node, args, kwargs) if is_base_test: self.build.tests.append(t) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 9aefc2f97dd5..28e7170c9b2c 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -742,7 +742,7 @@ class GeneratedObjectsHolder(ObjectHolder[build.ExtractedObjects]): class Test(MesonInterpreterObject): def __init__(self, name: str, project: str, suite: T.List[str], - exe: T.Union[ExternalProgram, build.Executable, build.CustomTarget], + exe: T.Union[ExternalProgram, build.Executable, build.CustomTarget, build.CustomTargetIndex], depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]], is_parallel: bool, cmd_args: T.List[T.Union[str, mesonlib.File, build.Target]], @@ -765,7 +765,7 @@ def __init__(self, name: str, project: str, suite: T.List[str], self.priority = priority self.verbose = verbose - def get_exe(self) -> T.Union[ExternalProgram, build.Executable, build.CustomTarget]: + def get_exe(self) -> T.Union[ExternalProgram, build.Executable, build.CustomTarget, build.CustomTargetIndex]: return self.exe def get_name(self) -> str: diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index b43f165ed606..21414d2c5677 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1458,6 +1458,11 @@ def _get_test_cmd(self) -> T.Optional[T.List[str]]: 'found. Please check the command and/or add it to PATH.') raise TestException(msg.format(self.test.exe_wrapper.name)) return self.test.exe_wrapper.get_command() + self.test.fname + elif self.test.cmd_is_built and not self.test.cmd_is_exe and is_windows(): + test_cmd = ExternalProgram._shebang_to_cmd(self.test.fname[0]) + if test_cmd is not None: + test_cmd += self.test.fname[1:] + return test_cmd return self.test.fname def _get_cmd(self) -> T.Optional[T.List[str]]: diff --git a/test cases/common/273 customtarget exe for test/generate.py b/test cases/common/273 customtarget exe for test/generate.py new file mode 100644 index 000000000000..e66f1db70aad --- /dev/null +++ b/test cases/common/273 customtarget exe for test/generate.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import os +import sys + +program = '''#!/usr/bin/env python3 + +raise SystemExit({}) +''' + +for i, a in enumerate(sys.argv[1:]): + with open(a, 'w') as f: + print(program.format(i), file=f) + os.chmod(a, 0o755) diff --git a/test cases/common/273 customtarget exe for test/meson.build b/test cases/common/273 customtarget exe for test/meson.build new file mode 100644 index 000000000000..089d70dee49d --- /dev/null +++ b/test cases/common/273 customtarget exe for test/meson.build @@ -0,0 +1,14 @@ +project('test customtarget') + +ct1 = custom_target( + command: ['generate.py', '@OUTPUT@'], + output: 'a.py', +) +ct2 = custom_target( + command: ['generate.py', '@OUTPUT@'], + output: ['b.py', 'c.py'], +) + +test('using_custom_target', ct1) +test('using_custom_target_index', ct2[0]) +test('using_custom_target_index_1', ct2[1], should_fail: true) From d44185026d7cdd83dad8f2da9cb8534c97293ec1 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sun, 17 Sep 2023 12:12:13 +0200 Subject: [PATCH 644/855] meson/rust: wrap `bindgen`s `wrap-static-fns` functionality This way the `rust.bindgen` can generate a second output being a C file, which contains wrapper functions for static inline ones. This output file can then be compiled via C targets. --- docs/markdown/Rust-module.md | 3 +++ mesonbuild/modules/rust.py | 35 +++++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 11966ca8ccea..ee095e9d6da1 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -57,6 +57,9 @@ It takes the following keyword arguments - `input`: a list of Files, Strings, or CustomTargets. The first element is the header bindgen will parse, additional elements are dependencies. - `output`: the name of the output rust file +- `output_inline_wrapper`: the name of the optional output c file containing + wrappers for static inline function. This requires `bindgen-0.65` or + newer (*since 1.3.0*). - `include_directories`: A list of `include_directories` or `string` objects, these are passed to clang as `-I` arguments *(string since 1.0.0)* - `c_args`: a list of string arguments to pass to clang untouched diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index fb8528088142..73ac032afb21 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -9,7 +9,7 @@ from mesonbuild.interpreterbase.decorators import FeatureNew from . import ExtensionModule, ModuleReturnValue, ModuleInfo -from .. import mlog +from .. import mesonlib, mlog from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) from ..compilers.compilers import are_asserts_disabled, lang_suffixes @@ -19,6 +19,7 @@ ) from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File +from ..programs import ExternalProgram if T.TYPE_CHECKING: from . import ModuleState @@ -27,7 +28,7 @@ from ..interpreter import Interpreter from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs - from ..programs import ExternalProgram, OverrideProgram + from ..programs import OverrideProgram from ..interpreter.type_checking import SourcesVarargsType from typing_extensions import TypedDict, Literal @@ -46,6 +47,7 @@ class FuncBindgen(TypedDict): include_directories: T.List[IncludeDirs] input: T.List[SourceInputs] output: str + output_inline_wrapper: str dependencies: T.List[T.Union[Dependency, ExternalLibrary]] language: T.Optional[Literal['c', 'cpp']] bindgen_version: T.List[str] @@ -196,6 +198,12 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func KwargInfo('bindgen_version', ContainerTypeInfo(list, str), default=[], listify=True, since='1.4.0'), INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, + KwargInfo( + 'output_inline_wrapper', + str, + default='', + since='1.3.0', + ), DEPENDENCIES_KW.evolve(since='1.0.0'), ) def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> ModuleReturnValue: @@ -287,12 +295,27 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu if std != 'none': clang_args.append(f'-std={std}') + inline_wrapper_args: T.List[str] = [] + outputs = [kwargs['output']] + if kwargs['output_inline_wrapper']: + # Todo drop this isinstance once Executable supports version_compare + if isinstance(self._bindgen_bin, ExternalProgram): + if mesonlib.version_compare(self._bindgen_bin.get_version(), '< 0.65'): + raise InterpreterException('\'output_inline_wrapper\' parameter of rust.bindgen requires bindgen-0.65 or newer') + + outputs.append(kwargs['output_inline_wrapper']) + inline_wrapper_args = [ + '--experimental', '--wrap-static-fns', + '--wrap-static-fns-path', os.path.join(state.environment.build_dir, '@OUTPUT1@') + ] + cmd = self._bindgen_bin.get_command() + \ [ '@INPUT@', '--output', - os.path.join(state.environment.build_dir, '@OUTPUT@') + os.path.join(state.environment.build_dir, '@OUTPUT0@') ] + \ - kwargs['args'] + ['--'] + kwargs['c_args'] + clang_args + \ + kwargs['args'] + inline_wrapper_args + ['--'] + \ + kwargs['c_args'] + clang_args + \ ['-MD', '-MQ', '@INPUT@', '-MF', '@DEPFILE@'] target = CustomTarget( @@ -302,7 +325,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu state.environment, cmd, [header], - [kwargs['output']], + outputs, depfile='@PLAINNAME@.d', extra_depends=depends, depend_files=depend_files, @@ -310,7 +333,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu description='Generating bindings for Rust {}', ) - return ModuleReturnValue([target], [target]) + return ModuleReturnValue(target, [target]) # Allow a limited set of kwargs, but still use the full set of typed_kwargs() # because it could be setting required default values. From 8137eb437a974d9e0a74160d145a3808f68a1a59 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 18 Sep 2023 23:30:01 +0200 Subject: [PATCH 645/855] add test for generating static inline wrappers --- test cases/rust/12 bindgen/meson.build | 28 ++++++++++++++++++++++++ test cases/rust/12 bindgen/src/header3.h | 12 ++++++++++ test cases/rust/12 bindgen/src/main3.rs | 14 ++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 test cases/rust/12 bindgen/src/header3.h create mode 100644 test cases/rust/12 bindgen/src/main3.rs diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index a88ed81de94e..f31040ec7808 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -99,6 +99,34 @@ rust_bin2 = executable( test('generated header', rust_bin2) +if prog_bindgen.version().version_compare('>= 0.65') + # Test generating a static inline wrapper + gen3 = rust.bindgen( + input : 'src/header3.h', + output : 'header3.rs', + output_inline_wrapper : 'header3.c', + include_directories : 'include', + ) + c_inline_wrapper = static_library('c_wrapper', gen3[1]) + + f = configure_file( + input : 'src/main3.rs', + output : 'main3.rs', + copy : true, + ) + + rust_bin3 = executable( + 'rust_bin3', + [f, gen3[0]], + link_with : [ + c_lib, + c_inline_wrapper, + ], + ) + + test('static inline wrapper', rust_bin3) +endif + subdir('sub') subdir('dependencies') diff --git a/test cases/rust/12 bindgen/src/header3.h b/test cases/rust/12 bindgen/src/header3.h new file mode 100644 index 000000000000..958a79fd0f4d --- /dev/null +++ b/test cases/rust/12 bindgen/src/header3.h @@ -0,0 +1,12 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2023 Red Hat, Inc + +#pragma once + +#include "other.h" + +int32_t add(const int32_t, const int32_t); + +static inline int32_t sub(const int32_t a, const int32_t b) { + return a - b; +} diff --git a/test cases/rust/12 bindgen/src/main3.rs b/test cases/rust/12 bindgen/src/main3.rs new file mode 100644 index 000000000000..fa9d30b7ccb5 --- /dev/null +++ b/test cases/rust/12 bindgen/src/main3.rs @@ -0,0 +1,14 @@ +// SPDX-license-identifer: Apache-2.0 +// Copyright © 2023 Red Hat, Inc + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("header3.rs"); + +fn main() { + unsafe { + std::process::exit(add(0, sub(0, 0))); + }; +} From a234c001a0011cd10953a8e4f265d64a12ac0a50 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 23 Aug 2023 18:14:53 +0100 Subject: [PATCH 646/855] compilers/detect: Implemented logic for checking suffixed LLVM tools before non --- mesonbuild/compilers/detect.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 1f6bb484079d..d8f48f3e00ef 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -171,7 +171,11 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker trials = [defaults['gcc_static_linker']] + default_linkers elif compiler.id == 'clang': # Use llvm-ar if available; needed for LTO - trials = [defaults['clang_static_linker']] + default_linkers + llvm_ar = defaults['clang_static_linker'] + # Extract the version major of the compiler to use as a suffix + suffix = compiler.version.split('.')[0] + # Prefer suffixed llvm-ar first, then unsuffixed then the defaults + trials = [[f'{llvm_ar[0]}-{suffix}'], llvm_ar] + default_linkers elif compiler.language == 'd': # Prefer static linkers over linkers used by D compilers if is_windows(): From cfada46694aa952369063d3f4fa4e63d7e637ba3 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 23 Aug 2023 22:46:57 +0100 Subject: [PATCH 647/855] scripts/coverage: Implemented handling for passing the gcovr and llvm-cov binaries to use to the script --- mesonbuild/backend/ninjabackend.py | 3 ++- mesonbuild/environment.py | 21 +++++++++++---------- mesonbuild/scripts/coverage.py | 21 +++++++++++++++++---- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2606ac43ab44..421bb627495e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -630,7 +630,8 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional key = OptionKey('b_coverage') if (key in self.environment.coredata.options and self.environment.coredata.options[key].value): - gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, _ = environment.find_coverage_tools() + gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe = environment.find_coverage_tools(self.environment.coredata) + mlog.debug(f'Using {gcovr_exe} ({gcovr_version}), {lcov_exe} and {llvm_cov_exe} for code coverage') if gcovr_exe or (lcov_exe and genhtml_exe): self.add_build_comment(NinjaComment('Coverage rules')) self.generate_coverage_rules(gcovr_exe, gcovr_version) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 14e4ee8564d2..dd6d7ba93326 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -72,8 +72,7 @@ def _get_env_var(for_machine: MachineChoice, is_cross: bool, var_name: str) -> T return value -def detect_gcovr(min_version: str = '3.3', log: bool = False): - gcovr_exe = 'gcovr' +def detect_gcovr(gcovr_exe: str = 'gcovr', min_version: str = '3.3', log: bool = False): try: p, found = Popen_safe([gcovr_exe, '--version'])[0:2] except (FileNotFoundError, PermissionError): @@ -86,8 +85,7 @@ def detect_gcovr(min_version: str = '3.3', log: bool = False): return gcovr_exe, found return None, None -def detect_lcov(log: bool = False): - lcov_exe = 'lcov' +def detect_lcov(lcov_exe: str = 'lcov', log: bool = False): try: p, found = Popen_safe([lcov_exe, '--version'])[0:2] except (FileNotFoundError, PermissionError): @@ -107,16 +105,19 @@ def detect_llvm_cov(): return tool return None -def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: +def detect_lcov_genhtml(lcov_exe: str = 'lcov', genhtml_exe: str = 'genhtml'): + lcov_exe, lcov_version = detect_lcov(lcov_exe) + if not mesonlib.exe_exists([genhtml_exe, '--version']): + genhtml_exe = None + + return lcov_exe, lcov_version, genhtml_exe + +def find_coverage_tools(coredata: coredata.CoreData) -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: gcovr_exe, gcovr_version = detect_gcovr() llvm_cov_exe = detect_llvm_cov() - lcov_exe, lcov_version = detect_lcov() - genhtml_exe = 'genhtml' - - if not mesonlib.exe_exists([genhtml_exe, '--version']): - genhtml_exe = None + lcov_exe, lcov_version, genhtml_exe = detect_lcov_genhtml() return gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 2375e453ea57..bded052d4a49 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -8,11 +8,19 @@ import argparse, re, sys, os, subprocess, pathlib, stat import typing as T -def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build_root: str, log_dir: str, use_llvm_cov: bool) -> int: +def coverage(outputs: T.List[str], source_root: str, subproject_root: str, build_root: str, log_dir: str, use_llvm_cov: bool, + gcovr_exe: str, llvm_cov_exe: str) -> int: outfiles = [] exitcode = 0 - (gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe) = environment.find_coverage_tools() + if gcovr_exe == '': + gcovr_exe = None + else: + gcovr_exe, gcovr_version = environment.detect_gcovr(gcovr_exe) + if llvm_cov_exe == '' or not mesonlib.exe_exists([llvm_cov_exe, '--version']): + llvm_cov_exe = None + + lcov_exe, lcov_version, genhtml_exe = environment.detect_lcov_genhtml() # load config files for tools if available in the source tree # - lcov requires manually specifying a per-project config @@ -186,8 +194,12 @@ def run(args: T.List[str]) -> int: const='sonarqube', help='generate Sonarqube Xml report') parser.add_argument('--html', dest='outputs', action='append_const', const='html', help='generate Html report') - parser.add_argument('--use_llvm_cov', action='store_true', + parser.add_argument('--use-llvm-cov', action='store_true', help='use llvm-cov') + parser.add_argument('--gcovr', action='store', default='', + help='The gcovr executable to use if specified') + parser.add_argument('--llvm-cov', action='store', default='', + help='The llvm-cov executable to use if specified') parser.add_argument('source_root') parser.add_argument('subproject_root') parser.add_argument('build_root') @@ -195,7 +207,8 @@ def run(args: T.List[str]) -> int: options = parser.parse_args(args) return coverage(options.outputs, options.source_root, options.subproject_root, options.build_root, - options.log_dir, options.use_llvm_cov) + options.log_dir, options.use_llvm_cov, + options.gcovr, options.llvm_cov) if __name__ == '__main__': sys.exit(run(sys.argv[1:])) From d4450520e05c69438e8f5696f3576d6b4102c729 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 23 Aug 2023 22:47:33 +0100 Subject: [PATCH 648/855] environment: Built logic for computing the suffix of and automatically selecting suitable `llvm-cov` binaries to find_coverage_tools() --- mesonbuild/environment.py | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index dd6d7ba93326..645a7888f22e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -98,11 +98,39 @@ def detect_lcov(lcov_exe: str = 'lcov', log: bool = False): return lcov_exe, found return None, None -def detect_llvm_cov(): - tools = get_llvm_tool_names('llvm-cov') - for tool in tools: +def detect_llvm_cov(suffix: T.Optional[str] = None): + # If there's a known suffix or forced lack of suffix, use that + if suffix is not None: + if suffix == '': + tool = 'llvm-cov' + else: + tool = f'llvm-cov-{suffix}' if mesonlib.exe_exists([tool, '--version']): return tool + else: + # Otherwise guess in the dark + tools = get_llvm_tool_names('llvm-cov') + for tool in tools: + if mesonlib.exe_exists([tool, '--version']): + return tool + return None + +def compute_llvm_suffix(coredata: coredata.CoreData): + # Check to see if the user is trying to do coverage for either a C or C++ project + compilers = coredata.compilers[MachineChoice.BUILD] + cpp_compiler_is_clang = 'cpp' in compilers and compilers['cpp'].id == 'clang' + c_compiler_is_clang = 'c' in compilers and compilers['c'].id == 'clang' + # Extract first the C++ compiler if available. If it's a Clang of some kind, compute the suffix if possible + if cpp_compiler_is_clang: + suffix = compilers['cpp'].version.split('.')[0] + return suffix + + # Then the C compiler, again checking if it's some kind of Clang and computing the suffix + if c_compiler_is_clang: + suffix = compilers['c'].version.split('.')[0] + return suffix + + # Neither compiler is a Clang, or no compilers are for C or C++ return None def detect_lcov_genhtml(lcov_exe: str = 'lcov', genhtml_exe: str = 'genhtml'): @@ -115,7 +143,7 @@ def detect_lcov_genhtml(lcov_exe: str = 'lcov', genhtml_exe: str = 'genhtml'): def find_coverage_tools(coredata: coredata.CoreData) -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]: gcovr_exe, gcovr_version = detect_gcovr() - llvm_cov_exe = detect_llvm_cov() + llvm_cov_exe = detect_llvm_cov(compute_llvm_suffix(coredata)) lcov_exe, lcov_version, genhtml_exe = detect_lcov_genhtml() From 67afddbf431140c1ee064bf79a2fa5a95575488e Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 23 Aug 2023 22:50:37 +0100 Subject: [PATCH 649/855] environment: Add LLVM 18 support to get_llvm_tool_names() --- mesonbuild/environment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 645a7888f22e..af69f64ecf72 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -188,6 +188,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: # unless it becomes a stable release. suffixes = [ '', # base (no suffix) + '-18', '18', '-17', '17', '-16', '16', '-15', '15', From 5495dc43153cc3267b98f3b83f5658736e78a90f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Thu, 24 Aug 2023 15:59:11 +0100 Subject: [PATCH 650/855] backend/ninjabackend: Implemented logic for passing the discovered gcovr and llvm-cov along to the code coverage backend --- mesonbuild/backend/ninjabackend.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 421bb627495e..74994d0fd943 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -634,7 +634,7 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional mlog.debug(f'Using {gcovr_exe} ({gcovr_version}), {lcov_exe} and {llvm_cov_exe} for code coverage') if gcovr_exe or (lcov_exe and genhtml_exe): self.add_build_comment(NinjaComment('Coverage rules')) - self.generate_coverage_rules(gcovr_exe, gcovr_version) + self.generate_coverage_rules(gcovr_exe, gcovr_version, llvm_cov_exe) mlog.log_timestamp("Coverage rules generated") else: # FIXME: since we explicitly opted in, should this be an error? @@ -1209,9 +1209,15 @@ def generate_run_target(self, target: build.RunTarget): self.add_build(elem) self.processed_targets.add(target.get_id()) - def generate_coverage_command(self, elem, outputs): + def generate_coverage_command(self, elem, outputs: T.List[str], gcovr_exe: T.Optional[str], llvm_cov_exe: T.Optional[str]): targets = self.build.get_targets().values() use_llvm_cov = False + exe_args = [] + if gcovr_exe is not None: + exe_args += ['--gcov', gcovr_exe] + if llvm_cov_exe is not None: + exe_args += ['--llvm-cov', llvm_cov_exe] + for target in targets: if not hasattr(target, 'compilers'): continue @@ -1227,35 +1233,36 @@ def generate_coverage_command(self, elem, outputs): self.build.get_subproject_dir()), self.environment.get_build_dir(), self.environment.get_log_dir()] + - (['--use_llvm_cov'] if use_llvm_cov else [])) + exe_args + + (['--use-llvm-cov'] if use_llvm_cov else [])) - def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): + def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str], llvm_cov_exe: T.Optional[str]): e = self.create_phony_target('coverage', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, []) + self.generate_coverage_command(e, [], gcovr_exe, llvm_cov_exe) e.add_item('description', 'Generates coverage reports') self.add_build(e) - self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version) + self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version, llvm_cov_exe) - def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]): + def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str], llvm_cov_exe: T.Optional[str]): e = self.create_phony_target('coverage-html', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--html']) + self.generate_coverage_command(e, ['--html'], gcovr_exe, llvm_cov_exe) e.add_item('description', 'Generates HTML coverage report') self.add_build(e) if gcovr_exe: e = self.create_phony_target('coverage-xml', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--xml']) + self.generate_coverage_command(e, ['--xml'], gcovr_exe, llvm_cov_exe) e.add_item('description', 'Generates XML coverage report') self.add_build(e) e = self.create_phony_target('coverage-text', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--text']) + self.generate_coverage_command(e, ['--text'], gcovr_exe, llvm_cov_exe) e.add_item('description', 'Generates text coverage report') self.add_build(e) if mesonlib.version_compare(gcovr_version, '>=4.2'): e = self.create_phony_target('coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY') - self.generate_coverage_command(e, ['--sonarqube']) + self.generate_coverage_command(e, ['--sonarqube'], gcovr_exe, llvm_cov_exe) e.add_item('description', 'Generates Sonarqube XML coverage report') self.add_build(e) From 9cb44c9c5848c151d4f355757d33e5808311deba Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 18 Aug 2023 01:46:50 -0500 Subject: [PATCH 651/855] Fix bad escape character in doc comment --- mesonbuild/modules/fs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 296c7a8721dd..a666d6efe884 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -104,7 +104,7 @@ def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwarg @FeatureNew('fs.as_posix', '0.54.0') @typed_pos_args('fs.as_posix', str) def as_posix(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: - """ + r""" this function assumes you are passing a Windows path, even if on a Unix-like system and so ALL '\' are turned to '/', even if you meant to escape a character """ From 35c605272378def120e3499b3f59bbcbdf72fef5 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 23 Feb 2024 12:43:42 -0600 Subject: [PATCH 652/855] Fix fs module FeatureNew prefixes to match the function name They were appending _file to the function name when they were meant to suggest that the function now supports file objects. --- mesonbuild/modules/fs.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index a666d6efe884..1f670d373c41 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -97,7 +97,7 @@ def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[st @typed_pos_args('fs.is_absolute', (str, File)) def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File): - FeatureNew('fs.is_absolute_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.is_absolute with file', '0.59.0').use(state.subproject, location=state.current_node) return PurePath(str(args[0])).is_absolute() @noKwargs @@ -119,7 +119,7 @@ def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T @typed_pos_args('fs.is_symlink', (str, File)) def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File): - FeatureNew('fs.is_symlink_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.is_symlink with file', '0.59.0').use(state.subproject, location=state.current_node) return self._absolute_dir(state, args[0]).is_symlink() @noKwargs @@ -136,7 +136,7 @@ def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T @typed_pos_args('fs.hash', (str, File), str) def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.hash_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.hash with file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) if not file.is_file(): raise MesonException(f'{file} is not a file and therefore cannot be hashed') @@ -152,7 +152,7 @@ def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: @typed_pos_args('fs.size', (str, File)) def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int: if isinstance(args[0], File): - FeatureNew('fs.size_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.size with file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) if not file.is_file(): raise MesonException(f'{file} is not a file and therefore cannot be sized') @@ -165,7 +165,7 @@ def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Di @typed_pos_args('fs.is_samepath', (str, File), (str, File)) def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File) or isinstance(args[1], File): - FeatureNew('fs.is_samepath_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.is_samepath with file', '0.59.0').use(state.subproject, location=state.current_node) file1 = self._resolve_dir(state, args[0]) file2 = self._resolve_dir(state, args[1]) if not file1.exists(): @@ -181,7 +181,7 @@ def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileO @typed_pos_args('fs.replace_suffix', (str, File), str) def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.replace_suffix_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.replace_suffix with file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.with_suffix(args[1]) return str(new) @@ -199,7 +199,7 @@ def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T. @typed_pos_args('fs.name', (str, File)) def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.name_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.name with file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.name return str(new) @@ -209,7 +209,7 @@ def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Di @FeatureNew('fs.stem', '0.54.0') def stem(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): - FeatureNew('fs.stem_file', '0.59.0').use(state.subproject, location=state.current_node) + FeatureNew('fs.stem with file', '0.59.0').use(state.subproject, location=state.current_node) original = PurePath(str(args[0])) new = original.stem return str(new) From 0b19d1c015508023d13fd0cb460983e0ea28f02f Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 23 Feb 2024 12:44:55 -0600 Subject: [PATCH 653/855] Correct fs.read function name in exception message --- mesonbuild/modules/fs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 1f670d373c41..b977b99c07a8 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -235,7 +235,7 @@ def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'Rea if isinstance(path, File): if path.is_built: raise MesonException( - 'fs.read_file does not accept built files() objects') + 'fs.read does not accept built files() objects') path = os.path.join(src_dir, path.relative_name()) else: if sub_dir: From 6a119256a1b87f22a6afe59b494ac50e52e24f07 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Fri, 18 Aug 2023 01:51:47 -0500 Subject: [PATCH 654/855] Add support for BuildTargetTypes to various fs module functions The new support was added to fs.name, fs.parent, fs.replace_suffix, and fs.stem. --- .../additional_types_for_fs_module.md | 9 +++ mesonbuild/modules/fs.py | 56 +++++++++---------- test cases/common/220 fs module/btgt.c | 5 ++ test cases/common/220 fs module/ctgt.txt | 0 test cases/common/220 fs module/meson.build | 23 ++++++++ 5 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 docs/markdown/snippets/additional_types_for_fs_module.md create mode 100644 test cases/common/220 fs module/btgt.c create mode 100644 test cases/common/220 fs module/ctgt.txt diff --git a/docs/markdown/snippets/additional_types_for_fs_module.md b/docs/markdown/snippets/additional_types_for_fs_module.md new file mode 100644 index 000000000000..86f2de9f438a --- /dev/null +++ b/docs/markdown/snippets/additional_types_for_fs_module.md @@ -0,0 +1,9 @@ +## Added support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` to certain FS module functions + +Support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` was +added to the following FS module APIs: + +- `fs.name` +- `fs.parent` +- `fs.replace_suffix` +- `fs.stem` diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index b977b99c07a8..1fa368e1fef3 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -72,6 +72,18 @@ def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: return Path(arg.absolute_path(state.source_root, state.environment.get_build_dir())) return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser() + @staticmethod + def _obj_to_path(feature_new_prefix: str, obj: T.Union[FileOrString, BuildTargetTypes], state: ModuleState) -> PurePath: + if isinstance(obj, str): + return PurePath(obj) + + if isinstance(obj, File): + FeatureNew(f'{feature_new_prefix} with file', '0.59.0').use(state.subproject, location=state.current_node) + return PurePath(str(obj)) + + FeatureNew(f'{feature_new_prefix} with build_tgt, custom_tgt, and custom_idx', '1.4.0').use(state.subproject, location=state.current_node) + return PurePath(state.backend.get_target_filename(obj)) + def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: """ resolves symlinks and makes absolute a directory relative to calling meson.build, @@ -178,41 +190,29 @@ def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileO return False @noKwargs - @typed_pos_args('fs.replace_suffix', (str, File), str) - def replace_suffix(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: - if isinstance(args[0], File): - FeatureNew('fs.replace_suffix with file', '0.59.0').use(state.subproject, location=state.current_node) - original = PurePath(str(args[0])) - new = original.with_suffix(args[1]) - return str(new) + @typed_pos_args('fs.replace_suffix', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), str) + def replace_suffix(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], str], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_path('fs.replace_suffix', args[0], state) + return str(path.with_suffix(args[1])) @noKwargs - @typed_pos_args('fs.parent', (str, File)) - def parent(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: - if isinstance(args[0], File): - FeatureNew('fs.parent_file', '0.59.0').use(state.subproject, location=state.current_node) - original = PurePath(str(args[0])) - new = original.parent - return str(new) + @typed_pos_args('fs.parent', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) + def parent(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_path('fs.parent', args[0], state) + return str(path.parent) @noKwargs - @typed_pos_args('fs.name', (str, File)) - def name(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: - if isinstance(args[0], File): - FeatureNew('fs.name with file', '0.59.0').use(state.subproject, location=state.current_node) - original = PurePath(str(args[0])) - new = original.name - return str(new) + @typed_pos_args('fs.name', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) + def name(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_path('fs.name', args[0], state) + return str(path.name) @noKwargs - @typed_pos_args('fs.stem', (str, File)) + @typed_pos_args('fs.stem', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) @FeatureNew('fs.stem', '0.54.0') - def stem(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> str: - if isinstance(args[0], File): - FeatureNew('fs.stem with file', '0.59.0').use(state.subproject, location=state.current_node) - original = PurePath(str(args[0])) - new = original.stem - return str(new) + def stem(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_path('fs.stem', args[0], state) + return str(path.stem) @FeatureNew('fs.read', '0.57.0') @typed_pos_args('fs.read', (str, File)) diff --git a/test cases/common/220 fs module/btgt.c b/test cases/common/220 fs module/btgt.c new file mode 100644 index 000000000000..8479e67d1090 --- /dev/null +++ b/test cases/common/220 fs module/btgt.c @@ -0,0 +1,5 @@ +int +main(void) +{ + return 0; +} diff --git a/test cases/common/220 fs module/ctgt.txt b/test cases/common/220 fs module/ctgt.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test cases/common/220 fs module/meson.build b/test cases/common/220 fs module/meson.build index 80019631f6bc..e5397eebc4b2 100644 --- a/test cases/common/220 fs module/meson.build +++ b/test cases/common/220 fs module/meson.build @@ -5,6 +5,8 @@ is_windows = build_machine.system() == 'windows' fs = import('fs') f = files('meson.build') +btgt = executable('btgt', 'btgt.c') +ctgt = fs.copyfile('ctgt.txt') assert(fs.exists('meson.build'), 'Existing file reported as missing.') assert(not fs.exists('nonexisting'), 'Nonexisting file was found.') @@ -88,6 +90,13 @@ new_check = is_windows ? 'j:\\foo\\bar.ini' : '/foo/bar.ini' new = fs.replace_suffix(original, '.ini') assert(new == new_check, 'absolute path replace_suffix failed') +new = fs.replace_suffix(btgt, '.ini') +assert(new == 'btgt.ini', 'replace_suffix failed for build target') +new = fs.replace_suffix(ctgt, '.ini') +assert(new == 'ctgt.ini', 'replace_suffix failed for custom target') +new = fs.replace_suffix(ctgt[0], '.ini') +assert(new == 'ctgt.ini', 'replace_suffix failed for custom target index') + # -- hash md5 = fs.hash('subdir/subdirfile.txt', 'md5') @@ -135,11 +144,25 @@ assert(fs.parent(f[1]) == 'subdir/..', 'failed to get dirname') else assert(fs.parent(f[1]) == 'subdir\..', 'failed to get dirname') endif +assert(fs.parent(btgt) == '.', 'failed to get dirname for build target') +assert(fs.parent(ctgt) == '.', 'failed to get dirname for custom target') +assert(fs.parent(ctgt[0]) == '.', 'failed to get dirname for custom target index') + assert(fs.name('foo/bar') == 'bar', 'failed to get basename') assert(fs.name(f[1]) == 'meson.build', 'failed to get basename') assert(fs.name('foo/bar/baz.dll.a') == 'baz.dll.a', 'failed to get basename with compound suffix') +if host_machine.system() in ['cygwin', 'windows'] + assert(fs.name(btgt) == 'btgt.exe', 'failed to get basename of build target') +else + assert(fs.name(btgt) == 'btgt', 'failed to get basename of build target') +endif +assert(fs.name(ctgt) == 'ctgt.txt', 'failed to get basename of custom target') +assert(fs.name(ctgt[0]) == 'ctgt.txt', 'failed to get basename of custom target index') assert(fs.stem('foo/bar/baz.dll') == 'baz', 'failed to get stem with suffix') assert(fs.stem('foo/bar/baz.dll.a') == 'baz.dll', 'failed to get stem with compound suffix') +assert(fs.stem(btgt) == 'btgt', 'failed to get stem of build target') +assert(fs.stem(ctgt) == 'ctgt', 'failed to get stem of custom target') +assert(fs.stem(ctgt[0]) == 'ctgt', 'failed to get stem of custom target index') # relative_to if build_machine.system() == 'windows' From 05f4e0d6c5e74d5dfc1f1b32ac2ee26af664c950 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Aug 2023 20:16:08 -0300 Subject: [PATCH 655/855] cmake: Allow recasting a CMake dependency into an Apple framework Fixes #12160 --- mesonbuild/cmake/tracetargets.py | 50 ++++++++++++++++--- mesonbuild/dependencies/framework.py | 2 +- test cases/osx/9 framework recasting/main.cpp | 1 + .../osx/9 framework recasting/meson.build | 5 ++ 4 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 test cases/osx/9 framework recasting/main.cpp create mode 100644 test cases/osx/9 framework recasting/meson.build diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py index 69d88a88cc39..aee67ea595ce 100644 --- a/mesonbuild/cmake/tracetargets.py +++ b/mesonbuild/cmake/tracetargets.py @@ -4,6 +4,7 @@ from .common import cmake_is_debug from .. import mlog +from ..mesonlib import Version from pathlib import Path import re @@ -15,6 +16,28 @@ from ..compilers import Compiler from ..dependencies import MissingCompiler +# Small duplication of ExtraFramework to parse full +# framework paths as exposed by CMake +def _get_framework_latest_version(path: Path) -> str: + versions: list[Version] = [] + for each in path.glob('Versions/*'): + # macOS filesystems are usually case-insensitive + if each.name.lower() == 'current': + continue + versions.append(Version(each.name)) + if len(versions) == 0: + # most system frameworks do not have a 'Versions' directory + return 'Headers' + return 'Versions/{}/Headers'.format(sorted(versions)[-1]._s) + +def _get_framework_include_path(path: Path) -> T.Optional[str]: + trials = ('Headers', 'Versions/Current/Headers', _get_framework_latest_version(path)) + for each in trials: + trial = path / each + if trial.is_dir(): + return trial.as_posix() + return None + class ResolvedTarget: def __init__(self) -> None: self.include_directories: T.List[str] = [] @@ -46,10 +69,25 @@ def resolve_cmake_trace_targets(target_name: str, continue if curr not in trace.targets: + curr_path = Path(curr) if reg_is_lib.match(curr): res.libraries += [curr] - elif Path(curr).is_absolute() and Path(curr).exists(): - res.libraries += [curr] + elif curr_path.is_absolute() and curr_path.exists(): + if any(x.endswith('.framework') for x in curr_path.parts): + # Frameworks detected by CMake are passed as absolute paths + # Split into -F/path/to/ and -framework name + path_to_framework = [] + # Try to slice off the `Versions/X/name.tbd` + for x in curr_path.parts: + path_to_framework.append(x) + if x.endswith('.framework'): + break + curr_path = Path(*path_to_framework) + framework_path = curr_path.parent + framework_name = curr_path.stem + res.libraries += [f'-F{framework_path}', '-framework', framework_name] + else: + res.libraries += [curr] elif reg_is_maybe_bare_lib.match(curr) and clib_compiler: # CMake library dependencies can be passed as bare library names, # CMake brute-forces a combination of prefix/suffix combinations to find the @@ -115,9 +153,9 @@ def resolve_cmake_trace_targets(target_name: str, processed_targets += [curr] - res.include_directories = sorted(set(res.include_directories)) - res.link_flags = sorted(set(res.link_flags)) - res.public_compile_opts = sorted(set(res.public_compile_opts)) - res.libraries = sorted(set(res.libraries)) + # Do not sort flags here -- this breaks + # semantics of eg. `-framework CoreAudio` + # or `-Lpath/to/root -llibrary` + # see eg. #11113 return res diff --git a/mesonbuild/dependencies/framework.py b/mesonbuild/dependencies/framework.py index cd53ff71894b..3c880c7430af 100644 --- a/mesonbuild/dependencies/framework.py +++ b/mesonbuild/dependencies/framework.py @@ -79,7 +79,7 @@ def _get_framework_path(self, path: str, name: str) -> T.Optional[Path]: return None def _get_framework_latest_version(self, path: Path) -> str: - versions = [] + versions: T.List[Version] = [] for each in path.glob('Versions/*'): # macOS filesystems are usually case-insensitive if each.name.lower() == 'current': diff --git a/test cases/osx/9 framework recasting/main.cpp b/test cases/osx/9 framework recasting/main.cpp new file mode 100644 index 000000000000..76e8197013aa --- /dev/null +++ b/test cases/osx/9 framework recasting/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/test cases/osx/9 framework recasting/meson.build b/test cases/osx/9 framework recasting/meson.build new file mode 100644 index 000000000000..f139485ac2b9 --- /dev/null +++ b/test cases/osx/9 framework recasting/meson.build @@ -0,0 +1,5 @@ +project('framework recasting', 'c', 'cpp') + +x = dependency('openal') + +y = executable('tt', files('main.cpp'), dependencies: x) From a33c599f783d963ad2b04eb9bda76bdd38ad9234 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Mon, 21 Aug 2023 12:03:26 -0300 Subject: [PATCH 656/855] linkers: Fix detection of link arguments to Clang(-cl) + MSVC Currently, not only Meson lacks a way to induce a "--fatal-warnings" on LINK.exe, it is also unable to pass flags appropriately when using clang-cl or Microsoft's stock clang. This commit fixes it by implementing `fatal_warnings()` in the MSVCDynamicLinker and ClangCLDynamicLinker classes, and by implementing the requisite conversion steps in linker_to_compiler_args for ClangCompiler. --- mesonbuild/compilers/mixins/clang.py | 8 +++++++- mesonbuild/linkers/linkers.py | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index a57b9a9af9c1..c7e3a13c81c4 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -11,7 +11,7 @@ from ... import mesonlib from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ - MoldDynamicLinker + MoldDynamicLinker, MSVCDynamicLinker from ...mesonlib import OptionKey from ..compilers import CompileCheckMode from .gnu import GnuLikeCompiler @@ -155,6 +155,12 @@ def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T. args.extend(super().get_lto_compile_args(threads=threads)) return args + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + if isinstance(self.linker, (ClangClDynamicLinker, MSVCDynamicLinker)): + return [flag if flag.startswith('-Wl,') else f'-Wl,{flag}' for flag in args] + else: + return args + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default', thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]: args = self.get_lto_compile_args(threads=threads, mode=mode) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index e4db0157fd62..a807b7b98bc2 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1313,6 +1313,9 @@ def get_always_args(self) -> T.List[str]: def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) + def fatal_warnings(self) -> T.List[str]: + return ['-WX'] + class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): @@ -1342,6 +1345,9 @@ def get_win_subsystem_args(self, value: str) -> T.List[str]: def get_thinlto_cache_args(self, path: str) -> T.List[str]: return ["/lldltocache:" + path] + def fatal_warnings(self) -> T.List[str]: + return ['-WX'] + class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): From 3366756c0f959a5811f27d613f76d9371715c86a Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Thu, 24 Aug 2023 13:24:18 -0300 Subject: [PATCH 657/855] compilers: Forward Meson's preference of lld-link to clang-cl The latter prefers LINK.exe by default, which rejects GNU-like linker flags. --- mesonbuild/compilers/mixins/visualstudio.py | 12 ++++++++++++ mesonbuild/linkers/detect.py | 3 +++ 2 files changed, 15 insertions(+) diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 5dcebecef8ec..13f8cfa0f209 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -456,6 +456,18 @@ def get_include_args(self, path: str, is_system: bool) -> T.List[str]: path = '.' return ['/clang:-isystem' + path] if is_system else ['-I' + path] + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + # Clang additionally can use a linker specified as a path, unlike MSVC. + if linker == 'lld-link': + return ['-fuse-ld=lld-link'] + return super().use_linker_args(linker, version) + + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + # clang-cl forwards arguments span-wise with the /LINK flag + # therefore -Wl will be received by lld-link or LINK and rejected + return super().use_linker_args(self.linker.id, '') + super().linker_to_compiler_args([flag[4:] if flag.startswith('-Wl,') else flag for flag in args]) + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: if dep.get_include_type() == 'system': converted: T.List[str] = [] diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 1bce413f4f52..bb391d171833 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -55,6 +55,9 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty if value is not None: override = comp_class.use_linker_args(value[0], comp_version) check_args += override + elif 'lld-link' in compiler: + override = comp_class.use_linker_args('lld-link', comp_version) + check_args += override if extra_args is not None: check_args.extend(extra_args) From c5254429e4fdad4058104dc4c00531c0f7b109b6 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 5 Sep 2023 22:28:09 -0300 Subject: [PATCH 658/855] clang: Fix tests that use /DEF for MSVC LINK.exe --- mesonbuild/compilers/mixins/clang.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index c7e3a13c81c4..f982509f436b 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -111,6 +111,13 @@ def openmp_flags(self) -> T.List[str]: # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency. return [] + def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]: + if isinstance(self.linker, (MSVCDynamicLinker)): + # With MSVC, DLLs only export symbols that are explicitly exported, + # so if a module defs file is specified, we use that to export symbols + return ['-Wl,/DEF:' + defsfile] + return super().gen_vs_module_defs_args(defsfile) + @classmethod def use_linker_args(cls, linker: str, version: str) -> T.List[str]: # Clang additionally can use a linker specified as a path, which GCC From f3fad6cc5f948b0c7557bdce3959c71420183be9 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Thu, 24 Aug 2023 13:42:15 -0300 Subject: [PATCH 659/855] compilers: Add test for correct forwarding of flags to MSVC's Clang linkers --- .../common/180 has link arg/meson.build | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test cases/common/180 has link arg/meson.build b/test cases/common/180 has link arg/meson.build index 6bfbd59e721d..111b0b9ea177 100644 --- a/test cases/common/180 has link arg/meson.build +++ b/test cases/common/180 has link arg/meson.build @@ -45,3 +45,23 @@ endif assert(cc.has_multi_link_arguments(is_arg), 'Arg that should have worked does not work.') assert(cc.has_multi_link_arguments([useless, is_arg]), 'Arg that should have worked does not work.') + +# These are Visual Studio only flags +# Testing has_argument_syntax is incorrect as it skips Microsoft Clang +if cc.get_define('_MSC_FULL_VER') != '' + if cc.get_linker_id() == 'link' + is_only = '/OPT:REF' + is_shared = '/GUARD:CF' + else # ld-link + is_only = '--color-diagnostics' + is_shared = '-guard:cf' + endif + + # requires -Wl,xxx as it goes through the compiler + if cc.get_argument_syntax() != 'msvc' + is_only = '-Wl,@0@'.format(is_only) + is_shared = '-Wl,@0@'.format(is_shared) + endif + + assert(cc.has_multi_link_arguments([is_only, is_shared]), 'Arg that should have worked does not work.') +endif From 9ec26051c668fcbe5125dcd414cc9e613a0e29be Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Sun, 25 Feb 2024 19:50:06 +0100 Subject: [PATCH 660/855] Avoid use of deprecated command form on the cross compilation doc page --- docs/markdown/Cross-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Cross-compilation.md b/docs/markdown/Cross-compilation.md index e1ad837173cd..ccbcfd363ef5 100644 --- a/docs/markdown/Cross-compilation.md +++ b/docs/markdown/Cross-compilation.md @@ -256,7 +256,7 @@ to be the host machine. Once you have the cross file, starting a build is simple ```console -$ meson srcdir builddir --cross-file cross_file.txt +$ meson setup builddir --cross-file cross_file.txt ``` Once configuration is done, compilation is started by invoking `meson compile` From df2dbd06cfb1460ca8cc12d5cb140c32bcc4f91a Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Nov 2022 19:21:40 -0300 Subject: [PATCH 661/855] docs: clarify environment variables take only ExternalProgram.full_path() Fixes #10901 --- docs/yaml/objects/external_program.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/yaml/objects/external_program.yaml b/docs/yaml/objects/external_program.yaml index d175a01b5e34..4c24497a9f15 100644 --- a/docs/yaml/objects/external_program.yaml +++ b/docs/yaml/objects/external_program.yaml @@ -20,7 +20,8 @@ methods: and allows Meson to setup inter-target dependencies correctly (for example in cases where a program might be overridden by a [[@build_tgt]]). Only use this if you specifically need a string, such as when embedding - a program path into a header file. + a program path into a header file, or storing it into an environment + variable. For example: @@ -47,7 +48,8 @@ methods: and allows Meson to setup inter-target dependencies correctly (for example in cases where a program might be overridden by a [[@build_tgt]]). Only use this if you specifically need a string, such as when embedding - a program path into a header file. + a program path into a header file, or storing it into an environment + variable. For example: From 42944f72a438ea746dc6484b57bb0ffe429ea79f Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 25 Feb 2024 21:17:54 -0500 Subject: [PATCH 662/855] docs: fix some release notes snippet typos commit 6a8330af598753d5982a37933beeac2d6b565386: hpp was clearly meant and used several times, just not in the release notes themelves. commit a75ced6d50a3d479eda6dcdc9c3482493f2161f0: C/C++ "what"? We mention the std in the commit, but not in the text of the release notes. --- docs/markdown/snippets/rust-bindgen-cpp.md | 2 +- docs/markdown/snippets/rust-bindgen-std.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/snippets/rust-bindgen-cpp.md b/docs/markdown/snippets/rust-bindgen-cpp.md index e12e0f966fc1..7d1bec37d6ec 100644 --- a/docs/markdown/snippets/rust-bindgen-cpp.md +++ b/docs/markdown/snippets/rust-bindgen-cpp.md @@ -1,6 +1,6 @@ ## Bindgen will now use Meson's hueristic for what is a C++ header -Bindgen natively assumes that a file with the extension `.cpp` is a C++ header, +Bindgen natively assumes that a file with the extension `.hpp` is a C++ header, but that everything else is a C header. Meson has a whole list of extensions it considers to be C++, and now will automatically look for those extensions and set bindgen to treat those as C++ diff --git a/docs/markdown/snippets/rust-bindgen-std.md b/docs/markdown/snippets/rust-bindgen-std.md index 2c94f9c2ca2c..34ae611fc434 100644 --- a/docs/markdown/snippets/rust-bindgen-std.md +++ b/docs/markdown/snippets/rust-bindgen-std.md @@ -1,3 +1,3 @@ -## Bindgen now uses the same C/C++ as the project as a whole +## Bindgen now uses the same C/C++ std as the project as a whole Which is very important for C++ bindings. From 5654f03450e6ed0745a9429e578344dd4e581fc9 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 12:57:41 -0400 Subject: [PATCH 663/855] interpreter: Dependency variables can be empty string There is no reason to forbid empty variables, PkgConfigCLI.variable() even has code specifically for handling that case. --- mesonbuild/interpreter/interpreter.py | 2 ++ mesonbuild/interpreter/type_checking.py | 2 -- mesonbuild/modules/pkgconfig.py | 2 ++ .../meson.build | 16 ---------------- .../simple.c | 5 ----- .../simple.h | 6 ------ .../test.json | 7 ------- 7 files changed, 4 insertions(+), 36 deletions(-) delete mode 100644 test cases/failing/47 pkgconfig variables zero length value/meson.build delete mode 100644 test cases/failing/47 pkgconfig variables zero length value/simple.c delete mode 100644 test cases/failing/47 pkgconfig variables zero length value/simple.h delete mode 100644 test cases/failing/47 pkgconfig variables zero length value/test.json diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index aaffec0b966e..99c4f9625f4c 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -702,6 +702,8 @@ def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var] srcdir = Path(self.environment.source_dir) # convert variables which refer to an -uninstalled.pc style datadir for k, v in variables.items(): + if not v: + FeatureNew.single_use('empty variable value in declare_dependency', '1.4.0', self.subproject, location=node) try: p = Path(v) except ValueError: diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 616f4efbb58e..2ec7d58ceb38 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -144,8 +144,6 @@ def variables_validator(contents: T.Union[str, T.List[str], T.Dict[str, str]]) - for k, v in variables.items(): if not k: return 'empty variable name' - if not v: - return 'empty variable value' if any(c.isspace() for c in k): return f'invalid whitespace in variable name {k!r}' return None diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 3f9ce7b71e10..ebe0d92d5cb1 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -680,6 +680,8 @@ def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]: reserved = ['prefix', 'libdir', 'includedir'] variables = [] for name, value in vardict.items(): + if not value: + FeatureNew.single_use('empty variable value in pkg.generate', '1.4.0', state.subproject, location=state.current_node) if not dataonly and name in reserved: raise mesonlib.MesonException(f'Variable "{name}" is reserved') variables.append((name, value)) diff --git a/test cases/failing/47 pkgconfig variables zero length value/meson.build b/test cases/failing/47 pkgconfig variables zero length value/meson.build deleted file mode 100644 index 33977b273a22..000000000000 --- a/test cases/failing/47 pkgconfig variables zero length value/meson.build +++ /dev/null @@ -1,16 +0,0 @@ -project('variables-zero-length-value-test', 'c', version : '1.0') - -pkgg = import('pkgconfig') -lib = shared_library('simple', 'simple.c') -libver = '1.0' -h = install_headers('simple.h') - -pkgg.generate( - libraries : [lib, '-lz'], - subdirs : '.', - version : libver, - name : 'libsimple', - filebase : 'simple', - description : 'A simple demo library.', - variables : [ 'key=' ] -) diff --git a/test cases/failing/47 pkgconfig variables zero length value/simple.c b/test cases/failing/47 pkgconfig variables zero length value/simple.c deleted file mode 100644 index e8a6d83306ec..000000000000 --- a/test cases/failing/47 pkgconfig variables zero length value/simple.c +++ /dev/null @@ -1,5 +0,0 @@ -#include"simple.h" - -int simple_function() { - return 42; -} diff --git a/test cases/failing/47 pkgconfig variables zero length value/simple.h b/test cases/failing/47 pkgconfig variables zero length value/simple.h deleted file mode 100644 index bb52e6d727c7..000000000000 --- a/test cases/failing/47 pkgconfig variables zero length value/simple.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SIMPLE_H_ -#define SIMPLE_H_ - -int simple_function(); - -#endif diff --git a/test cases/failing/47 pkgconfig variables zero length value/test.json b/test cases/failing/47 pkgconfig variables zero length value/test.json deleted file mode 100644 index 0be572535ef8..000000000000 --- a/test cases/failing/47 pkgconfig variables zero length value/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/47 pkgconfig variables zero length value/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" empty variable value" - } - ] -} From c25f0b1d5483bb9471e313f52d0376bb391577e2 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 12:32:36 -0400 Subject: [PATCH 664/855] printer: notin operator should be printed as "not in" --- mesonbuild/ast/printer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 459912f2d636..ddeaf4498177 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -123,7 +123,7 @@ def visit_AndNode(self, node: mparser.AndNode) -> None: def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: node.left.accept(self) - self.append_padded(node.ctype, node) + self.append_padded(node.ctype if node.ctype != 'notin' else 'not in', node) node.lineno = self.curr_line or node.lineno node.right.accept(self) From cbf23f5eba4c2a323c31ff2bc0b6698789f5998a Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 12:33:01 -0400 Subject: [PATCH 665/855] printer: Add a newline after "else" --- mesonbuild/ast/printer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index ddeaf4498177..06b05ba89c9f 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -193,6 +193,7 @@ def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: i.accept(self) if not isinstance(node.elseblock, mparser.EmptyNode): self.append('else', node) + self.newline() node.elseblock.accept(self) self.append('endif', node) From 6cce6c51bf2ae4430d40331717bba8963ac475d8 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 9 Oct 2023 22:01:22 -0400 Subject: [PATCH 666/855] cargo: Builder: Add support for "+", "+=", "if" and "foreach" --- mesonbuild/cargo/builder.py | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 17b4ca52c9a6..ad2c760662fa 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -167,3 +167,45 @@ def block(self, lines: T.List[mparser.BaseNode]) -> mparser.CodeBlockNode: block = mparser.CodeBlockNode(self._token('node', '')) block.lines = lines return block + + def plus(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ArithmeticNode: + """Create an addition node + + :param lhs: The left of the addition + :param rhs: The right of the addition + :return: The ArithmeticNode + """ + return mparser.ArithmeticNode('add', lhs, self._symbol('+'), rhs) + + def plusassign(self, value: mparser.BaseNode, varname: str) -> mparser.PlusAssignmentNode: + """Create a "+=" node + + :param value: The value to add + :param varname: The variable to assign + :return: The PlusAssignmentNode + """ + return mparser.PlusAssignmentNode(self.identifier(varname), self._symbol('+='), value) + + def if_(self, condition: mparser.BaseNode, block: mparser.CodeBlockNode) -> mparser.IfClauseNode: + """Create a "if" block + + :param condition: The condition + :param block: Lines inside the condition + :return: The IfClauseNode + """ + clause = mparser.IfClauseNode(condition) + clause.ifs.append(mparser.IfNode(clause, self._symbol('if'), condition, block)) + clause.elseblock = mparser.EmptyNode(-1, -1, self.filename) + return clause + + def foreach(self, varnames: T.List[str], items: mparser.BaseNode, block: mparser.CodeBlockNode) -> mparser.ForeachClauseNode: + """Create a "foreach" loop + + :param varnames: Iterator variable names (one for list, two for dict). + :param items: The list of dict to iterate + :param block: Lines inside the loop + :return: The ForeachClauseNode + """ + varids = [self.identifier(i) for i in varnames] + commas = [self._symbol(',') for i in range(len(varnames) - 1)] + return mparser.ForeachClauseNode(self._symbol('foreach'), varids, commas, self._symbol(':'), items, block, self._symbol('endforeach')) From 53ba7196b93cb96d922c98efc6558715529a7117 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 12:34:26 -0400 Subject: [PATCH 667/855] cargo: Builder: Add support for "!=", "in" and "not in" operators --- mesonbuild/cargo/builder.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index ad2c760662fa..1127884446bb 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -137,6 +137,33 @@ def equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.Compari """ return mparser.ComparisonNode('==', lhs, self._symbol('=='), rhs) + def not_equal(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an inequality operation + + :param lhs: The left hand side of the "!=" + :param rhs: the right hand side of the "!=" + :return: A compraison node + """ + return mparser.ComparisonNode('!=', lhs, self._symbol('!='), rhs) + + def in_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an "in" operation + + :param lhs: The left hand side of the "in" + :param rhs: the right hand side of the "in" + :return: A compraison node + """ + return mparser.ComparisonNode('in', lhs, self._symbol('in'), rhs) + + def not_in(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.ComparisonNode: + """Create an "not in" operation + + :param lhs: The left hand side of the "not in" + :param rhs: the right hand side of the "not in" + :return: A compraison node + """ + return mparser.ComparisonNode('notin', lhs, self._symbol('not in'), rhs) + def or_(self, lhs: mparser.BaseNode, rhs: mparser.BaseNode) -> mparser.OrNode: """Create and OrNode From 8ca59775723930f0646a475c446275809334763e Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 13:54:24 -0400 Subject: [PATCH 668/855] cargo: Builder: method() object can be any BaseNode StringNode for example also have methods. --- mesonbuild/cargo/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/cargo/builder.py b/mesonbuild/cargo/builder.py index 1127884446bb..99659da11195 100644 --- a/mesonbuild/cargo/builder.py +++ b/mesonbuild/cargo/builder.py @@ -91,7 +91,7 @@ def identifier(self, value: str) -> mparser.IdNode: """ return mparser.IdNode(self._token('id', value)) - def method(self, name: str, id_: mparser.IdNode, + def method(self, name: str, id_: mparser.BaseNode, pos: T.Optional[T.List[mparser.BaseNode]] = None, kw: T.Optional[T.Mapping[str, mparser.BaseNode]] = None, ) -> mparser.MethodNode: From d075bdb3ca39a077994fa65e7fafb98cdebf5da6 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 12 Jun 2023 20:46:33 -0400 Subject: [PATCH 669/855] cargo: Use coredata.stable_version This avoids generated code print warnings when using features introduced in current dev cycle. --- mesonbuild/cargo/interpreter.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 66e45acc1df6..c5791ae4ced6 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -348,12 +348,11 @@ def _dependency_varname(package_name: str) -> str: return f'{fixup_meson_varname(package_name)}_dep' -def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) -> T.List[mparser.BaseNode]: +def _create_project(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: """Create a function call :param cargo: The Manifest to generate from :param build: The AST builder - :param env: Meson environment :return: a list nodes """ args: T.List[mparser.BaseNode] = [] @@ -366,7 +365,7 @@ def _create_project(cargo: Manifest, build: builder.Builder, env: Environment) - # Always assume that the generated meson is using the latest features # This will warn when when we generate deprecated code, which is helpful # for the upkeep of the module - 'meson_version': build.string(f'>= {env.coredata.version}'), + 'meson_version': build.string(f'>= {coredata.stable_version}'), 'default_options': build.array([build.string(f'rust_std={cargo.package.edition}')]), } if cargo.package.license: @@ -462,7 +461,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBloc filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') build = builder.Builder(filename) - ast = _create_project(cargo, build, env) + ast = _create_project(cargo, build) ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')] ast += _create_dependencies(cargo, build) From 114e032e6a27d0eb9ef5de1a811ce7b0461c3efc Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 10 Jun 2023 16:07:21 -0400 Subject: [PATCH 670/855] cargo: Expose features as Meson boolean options --- .../markdown/Wrap-dependency-system-manual.md | 20 +++ mesonbuild/cargo/interpreter.py | 135 +++++++++++++++++- mesonbuild/interpreter/interpreter.py | 3 +- .../subprojects/bar-rs/Cargo.toml | 11 ++ .../subprojects/extra-dep-rs/lib.c | 4 + .../subprojects/extra-dep-rs/meson.build | 10 ++ .../extra-dep-rs/meson_options.txt | 1 + .../subprojects/foo-rs/Cargo.toml | 19 ++- .../subprojects/foo-rs/src/lib.rs | 10 +- 9 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c create mode 100644 test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build create mode 100644 test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index e1e9474790cb..7a0cea6fe4ad 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -335,6 +335,26 @@ method = cargo dependency_names = foo-bar-rs ``` +Cargo features are exposed as Meson boolean options, with the `feature-` prefix. +For example the `default` feature is named `feature-default` and can be set from +the command line with `-Dfoo-rs:feature-default=false`. When a cargo subproject +depends on another cargo subproject, it will automatically enable features it +needs using the `dependency('foo-rs', default_options: ...)` mechanism. However, +unlike Cargo, the set of enabled features is not managed globally. Let's assume +the main project depends on `foo-rs` and `bar-rs`, and they both depend on +`common-rs`. The main project will first look up `foo-rs` which itself will +configure `common-rs` with a set of features. Later, when `bar-rs` does a lookup +for `common-rs` it has already been configured and the set of features cannot be +changed. It is currently the responsability of the main project to resolve those +issues by enabling extra features on each subproject: +```meson +project(..., + default_options: { + 'common-rs:feature-something': true, + }, +) +``` + ## Using wrapped projects Wraps provide a convenient way of obtaining a project into your diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index c5791ae4ced6..570087d6b6eb 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -17,11 +17,13 @@ import json import os import shutil +import collections import typing as T from . import builder from . import version -from ..mesonlib import MesonException, Popen_safe +from ..mesonlib import MesonException, Popen_safe, OptionKey +from .. import coredata if T.TYPE_CHECKING: from types import ModuleType @@ -29,6 +31,7 @@ from . import manifest from .. import mparser from ..environment import Environment + from ..coredata import KeyedOptionDictType # tomllib is present in python 3.11, before that it is a pypi module called tomli, # we try to import tomllib, then tomli, @@ -156,7 +159,7 @@ class Dependency: path: T.Optional[str] = None optional: bool = False package: T.Optional[str] = None - default_features: bool = False + default_features: bool = True features: T.List[str] = dataclasses.field(default_factory=list) @classmethod @@ -269,6 +272,9 @@ class Manifest: subdir: str path: str = '' + def __post_init__(self) -> None: + self.features.setdefault('default', []) + def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = '') -> Manifest: # This cast is a bit of a hack to deal with proc-macro @@ -348,6 +354,15 @@ def _dependency_varname(package_name: str) -> str: return f'{fixup_meson_varname(package_name)}_dep' +def _option_name(feature: str) -> str: + # Add a prefix to avoid collision with Meson reserved options (e.g. "debug") + return f'feature-{feature}' + + +def _options_varname(depname: str) -> str: + return f'{fixup_meson_varname(depname)}_options' + + def _create_project(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: """Create a function call @@ -376,13 +391,97 @@ def _create_project(cargo: Manifest, build: builder.Builder) -> T.List[mparser.B return [build.function('project', args, kwargs)] +def _process_feature(cargo: Manifest, feature: str) -> T.Tuple[T.Set[str], T.Dict[str, T.Set[str]], T.Set[str]]: + # Set of features that must also be enabled if this feature is enabled. + features: T.Set[str] = set() + # Map dependency name to a set of features that must also be enabled on that + # dependency if this feature is enabled. + dep_features: T.Dict[str, T.Set[str]] = collections.defaultdict(set) + # Set of dependencies that are required if this feature is enabled. + required_deps: T.Set[str] = set() + # Set of features that must be processed recursively. + to_process: T.Set[str] = {feature} + while to_process: + f = to_process.pop() + if '/' in f: + dep, dep_f = f.split('/', 1) + if dep[-1] == '?': + dep = dep[:-1] + else: + required_deps.add(dep) + dep_features[dep].add(dep_f) + elif f.startswith('dep:'): + required_deps.add(f[4:]) + elif f not in features: + features.add(f) + to_process.update(cargo.features.get(f, [])) + # A feature can also be a dependency + if f in cargo.dependencies: + required_deps.add(f) + return features, dep_features, required_deps + + +def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: + # https://doc.rust-lang.org/cargo/reference/features.html#the-features-section + + # Declare a dict that map enabled features to true. One for current project + # and one per dependency. + ast: T.List[mparser.BaseNode] = [] + ast.append(build.assign(build.dict({}), 'features')) + for depname in cargo.dependencies: + ast.append(build.assign(build.dict({}), _options_varname(depname))) + + # Declare a dict that map required dependencies to true + ast.append(build.assign(build.dict({}), 'required_deps')) + + for feature in cargo.features: + # if get_option(feature) + # required_deps += {'dep': true, ...} + # features += {'foo': true, ...} + # xxx_options += {'feature-foo': true, ...} + # ... + # endif + features, dep_features, required_deps = _process_feature(cargo, feature) + lines: T.List[mparser.BaseNode] = [ + build.plusassign( + build.dict({build.string(d): build.bool(True) for d in required_deps}), + 'required_deps'), + build.plusassign( + build.dict({build.string(f): build.bool(True) for f in features}), + 'features'), + ] + for depname, enabled_features in dep_features.items(): + lines.append(build.plusassign( + build.dict({build.string(_option_name(f)): build.bool(True) for f in enabled_features}), + _options_varname(depname))) + + ast.append(build.if_(build.function('get_option', [build.string(_option_name(feature))]), build.block(lines))) + + return ast + + def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: ast: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): package_name = dep.package or name + + # xxx_options += {'feature-default': true, ...} + extra_options: T.Dict[mparser.BaseNode, mparser.BaseNode] = { + build.string(_option_name('default')): build.bool(dep.default_features), + } + for f in dep.features: + extra_options[build.string(_option_name(f))] = build.bool(True) + ast.append(build.plusassign(build.dict(extra_options), _options_varname(name))) + kw = { 'version': build.array([build.string(s) for s in dep.version]), + 'default_options': build.identifier(_options_varname(name)), } + if dep.optional: + kw['required'] = build.method('get', build.identifier('required_deps'), [ + build.string(name), build.bool(False) + ]) + ast.extend([ build.assign( build.function( @@ -405,6 +504,8 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR if name != package_name: dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) + rust_args: T.List[mparser.BaseNode] = [build.identifier('features_args')] + posargs: T.List[mparser.BaseNode] = [ build.string(fixup_meson_varname(cargo.package.name)), build.string(os.path.join('src', 'lib.rs')), @@ -413,6 +514,7 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR kwargs: T.Dict[str, mparser.BaseNode] = { 'dependencies': build.array(dependencies), 'rust_dependency_map': build.dict(dependency_map), + 'rust_args': build.array(rust_args), } lib: mparser.BaseNode @@ -429,7 +531,24 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR kwargs['rust_abi'] = build.string('c') lib = build.function(target_type, posargs, kwargs) + # features_args = [] + # foreach f, _ : features + # features_args += ['--cfg', 'feature="' + f + '"'] + # endforeach + # lib = xxx_library() + # dep = declare_dependency() + # meson.override_dependency() return [ + build.assign(build.array([]), 'features_args'), + build.foreach(['f', '_'], build.identifier('features'), build.block([ + build.plusassign( + build.array([ + build.string('--cfg'), + build.plus(build.string('feature="'), build.plus(build.identifier('f'), build.string('"'))), + ]), + 'features_args') + ]) + ), build.assign(lib, 'lib'), build.assign( build.function( @@ -451,7 +570,7 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR ] -def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBlockNode: +def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.CodeBlockNode, KeyedOptionDictType]: package_name = subp_name[:-3] if subp_name.endswith('-rs') else subp_name manifests = _load_manifests(os.path.join(env.source_dir, subdir)) cargo = manifests.get(package_name) @@ -461,8 +580,16 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBloc filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml') build = builder.Builder(filename) + # Generate project options + options: T.Dict[OptionKey, coredata.UserOption] = {} + for feature in cargo.features: + key = OptionKey(_option_name(feature), subproject=subp_name) + enabled = feature == 'default' + options[key] = coredata.UserBooleanOption(f'Cargo {feature} feature', enabled) + ast = _create_project(cargo, build) ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')] + ast += _create_features(cargo, build) ast += _create_dependencies(cargo, build) # Libs are always auto-discovered and there's no other way to handle them, @@ -471,4 +598,4 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBloc for crate_type in cargo.lib.crate_type: ast.extend(_create_lib(cargo, build, crate_type)) - return build.block(ast) + return build.block(ast), options diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 99c4f9625f4c..79a61ed0ea2e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1034,7 +1034,8 @@ def _do_subproject_cargo(self, subp_name: str, subdir: str, from .. import cargo FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node) with mlog.nested(subp_name): - ast = cargo.interpret(subp_name, subdir, self.environment) + ast, options = cargo.interpret(subp_name, subdir, self.environment) + self.coredata.update_project_options(options) return self._do_subproject_meson( subp_name, subdir, default_options, kwargs, ast, # FIXME: Are there other files used by cargo interpreter? diff --git a/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml index 232b4d7d445d..d60a5d8f1c76 100644 --- a/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml +++ b/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml @@ -1,3 +1,14 @@ [package] name = "bar" version = "0.1" + +# This dependency does not exist, it is required by default but this subproject +# is called with default-features=false. +[dependencies.notfound] +optional = true +version = "1.0" + +[features] +default = ["f2"] +f1 = [] +f2 = ["notfound"] diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c new file mode 100644 index 000000000000..c2a0777ced1b --- /dev/null +++ b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c @@ -0,0 +1,4 @@ +int extra_func(void) +{ + return 0; +} diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build new file mode 100644 index 000000000000..3ba7852cf018 --- /dev/null +++ b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build @@ -0,0 +1,10 @@ +project('extra dep', 'c', version: '1.0') + +assert(get_option('feature-default') == true) + +l = static_library('extra-dep', 'lib.c') +d = declare_dependency(link_with: l, + variables: { + 'features': 'default', + }) +meson.override_dependency('extra-dep-rs', d) diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt new file mode 100644 index 000000000000..9311d9e8fa66 --- /dev/null +++ b/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt @@ -0,0 +1 @@ +option('feature-default', type: 'boolean', value: true) diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml index 214c3279c72e..796548d63f2a 100644 --- a/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml +++ b/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml @@ -6,5 +6,22 @@ edition = "2021" [lib] crate-type = ["cdylib"] +# This dependency does not exist, verify optional works. +[dependencies.notfound] +optional = true +version = "1.0" + +# This dependency is optional but required for f3 which is on by default. +[dependencies.extra-dep] +optional = true +version = "1.0" + [dependencies] -mybar = { version = "0.1", package = "bar" } +mybar = { version = "0.1", package = "bar", default-features = false } + +[features] +default = ["f1"] +f1 = ["f2", "f3"] +f2 = ["f1"] +f3 = ["mybar/f1", "dep:extra-dep", "notfound?/invalid"] +f4 = ["dep:notfound"] diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs index 732d7d20b10f..4f0a31079201 100644 --- a/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs +++ b/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs @@ -1,4 +1,12 @@ +extern "C" { + fn extra_func() -> i32; +} + #[no_mangle] pub extern "C" fn rust_func() -> i32 { - mybar::VALUE + let v: i32; + unsafe { + v = extra_func(); + }; + mybar::VALUE + v } From 4d55645c397e2f338a09ebd1f0f564c64b98dafa Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 13 Jun 2023 12:56:19 -0400 Subject: [PATCH 671/855] cargo: Abort if features are missing --- .../markdown/Wrap-dependency-system-manual.md | 3 +- mesonbuild/cargo/interpreter.py | 71 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index 7a0cea6fe4ad..70a7b3023cf8 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -345,7 +345,8 @@ the main project depends on `foo-rs` and `bar-rs`, and they both depend on `common-rs`. The main project will first look up `foo-rs` which itself will configure `common-rs` with a set of features. Later, when `bar-rs` does a lookup for `common-rs` it has already been configured and the set of features cannot be -changed. It is currently the responsability of the main project to resolve those +changed. If `bar-rs` wants extra features from `common-rs`, Meson will error out. +It is currently the responsability of the main project to resolve those issues by enabling extra features on each subproject: ```meson project(..., diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 570087d6b6eb..6680ea1b0095 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -354,9 +354,12 @@ def _dependency_varname(package_name: str) -> str: return f'{fixup_meson_varname(package_name)}_dep' +_OPTION_NAME_PREFIX = 'feature-' + + def _option_name(feature: str) -> str: # Add a prefix to avoid collision with Meson reserved options (e.g. "debug") - return f'feature-{feature}' + return _OPTION_NAME_PREFIX + feature def _options_varname(depname: str) -> str: @@ -457,6 +460,11 @@ def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser. ast.append(build.if_(build.function('get_option', [build.string(_option_name(feature))]), build.block(lines))) + ast.append(build.function('message', [ + build.string('Enabled features:'), + build.method('keys', build.identifier('features'))], + )) + return ast @@ -482,7 +490,19 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.string(name), build.bool(False) ]) + # Lookup for this dependency with the features we want in default_options kwarg. + # + # However, this subproject could have been previously configured with a + # different set of features. Cargo collects the set of features globally + # but Meson can only use features enabled by the first call that triggered + # the configuration of that subproject. + # + # Verify all features that we need are actually enabled for that dependency, + # otherwise abort with an error message. The user has to set the corresponding + # option manually with -Dxxx-rs:feature-yyy=true, or the main project can do + # that in its project(..., default_options: ['xxx-rs:feature-yyy=true']). ast.extend([ + # xxx_dep = dependency('xxx', version : ..., default_options : xxx_options) build.assign( build.function( 'dependency', @@ -491,6 +511,52 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar ), _dependency_varname(package_name), ), + # if xxx_dep.found() + build.if_(build.method('found', build.identifier(_dependency_varname(package_name))), build.block([ + # actual_features = xxx_dep.get_variable('features', default_value : '').split(',') + build.assign( + build.method( + 'split', + build.method( + 'get_variable', + build.identifier(_dependency_varname(package_name)), + [build.string('features')], + {'default_value': build.string('')} + ), + [build.string(',')], + ), + 'actual_features' + ), + # needed_features = [] + # foreach f, _ : xxx_options + # needed_features += f.substring(8) + # endforeach + build.assign(build.array([]), 'needed_features'), + build.foreach(['f', 'enabled'], build.identifier(_options_varname(name)), build.block([ + build.if_(build.identifier('enabled'), build.block([ + build.plusassign( + build.method('substring', build.identifier('f'), [build.number(len(_OPTION_NAME_PREFIX))]), + 'needed_features'), + ])), + ])), + # foreach f : needed_features + # if f not in actual_features + # error() + # endif + # endforeach + build.foreach(['f'], build.identifier('needed_features'), build.block([ + build.if_(build.not_in(build.identifier('f'), build.identifier('actual_features')), build.block([ + build.function('error', [ + build.string('Dependency'), + build.string(_dependency_name(package_name)), + build.string('previously configured with features'), + build.identifier('actual_features'), + build.string('but need'), + build.identifier('needed_features'), + ]) + ])) + ])), + ])), ]) return ast @@ -555,6 +621,9 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR 'declare_dependency', kw={ 'link_with': build.identifier('lib'), + 'variables': build.dict({ + build.string('features'): build.method('join', build.string(','), [build.method('keys', build.identifier('features'))]), + }) }, ), 'dep' From 435e881c18cda15fc4f8fc9e42f566cdc86cd791 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 12 Jun 2023 08:46:21 -0400 Subject: [PATCH 672/855] cargo: Call into meson subdir if it exists This allows projects to manually add extra rust args and deps. This is intended to replace build.rs logic. --- .../markdown/Wrap-dependency-system-manual.md | 8 +++++ mesonbuild/cargo/interpreter.py | 35 ++++++++++++++++++- .../subprojects/foo-rs/meson/meson.build | 1 + .../subprojects/foo-rs/src/lib.rs | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index 70a7b3023cf8..bba1971c4950 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -356,6 +356,14 @@ project(..., ) ``` +In addition, if the file `meson/meson.build` exists, Meson will call `subdir('meson')` +where the project can add manual logic that would usually be part of `build.rs`. +Some naming conventions need to be respected: +- The `extra_args` variable is pre-defined and can be used to add any Rust arguments. + This is typically used as `extra_args += ['--cfg', 'foo']`. +- The `extra_deps` variable is pre-defined and can be used to add extra dependencies. + This is typically used as `extra_deps += dependency('foo')`. + ## Using wrapped projects Wraps provide a convenient way of obtaining a project into your diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 6680ea1b0095..2797f9fe074e 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -366,6 +366,14 @@ def _options_varname(depname: str) -> str: return f'{fixup_meson_varname(depname)}_options' +def _extra_args_varname() -> str: + return 'extra_args' + + +def _extra_deps_varname() -> str: + return 'extra_deps' + + def _create_project(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: """Create a function call @@ -561,6 +569,25 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar return ast +def _create_meson_subdir(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: + # Allow Cargo subprojects to add extra Rust args in meson/meson.build file. + # This is used to replace build.rs logic. + + # extra_args = [] + # extra_deps = [] + # fs = import('fs') + # if fs.is_dir('meson') + # subdir('meson') + # endif + return [ + build.assign(build.array([]), _extra_args_varname()), + build.assign(build.array([]), _extra_deps_varname()), + build.assign(build.function('import', [build.string('fs')]), 'fs'), + build.if_(build.method('is_dir', build.identifier('fs'), [build.string('meson')]), + build.block([build.function('subdir', [build.string('meson')])])) + ] + + def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CRATE_TYPE) -> T.List[mparser.BaseNode]: dependencies: T.List[mparser.BaseNode] = [] dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {} @@ -570,7 +597,12 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR if name != package_name: dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) - rust_args: T.List[mparser.BaseNode] = [build.identifier('features_args')] + rust_args: T.List[mparser.BaseNode] = [ + build.identifier('features_args'), + build.identifier(_extra_args_varname()) + ] + + dependencies.append(build.identifier(_extra_deps_varname())) posargs: T.List[mparser.BaseNode] = [ build.string(fixup_meson_varname(cargo.package.name)), @@ -660,6 +692,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser. ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')] ast += _create_features(cargo, build) ast += _create_dependencies(cargo, build) + ast += _create_meson_subdir(cargo, build) # Libs are always auto-discovered and there's no other way to handle them, # which is unfortunate for reproducability diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build b/test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build new file mode 100644 index 000000000000..67c7b82f9955 --- /dev/null +++ b/test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build @@ -0,0 +1 @@ +extra_args += ['--cfg', 'feature="foo"'] diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs index 4f0a31079201..1c8cbc9d3fb5 100644 --- a/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs +++ b/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs @@ -2,6 +2,7 @@ extern "C" { fn extra_func() -> i32; } +#[cfg(feature = "foo")] #[no_mangle] pub extern "C" fn rust_func() -> i32 { let v: i32; From 0cd2a8dc002ee83335a2f17b9eaf980152d24864 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 26 Feb 2024 01:08:00 +0200 Subject: [PATCH 673/855] Condense directory names for RC1. --- .../common/{273 environment => 274 environment}/meson.build | 0 test cases/common/{273 environment => 274 environment}/testenv.py | 0 .../failing build/{2 hidden symbol => 1 hidden symbol}/bob.c | 0 .../failing build/{2 hidden symbol => 1 hidden symbol}/bob.h | 0 .../failing build/{2 hidden symbol => 1 hidden symbol}/bobuser.c | 0 .../{2 hidden symbol => 1 hidden symbol}/meson.build | 0 .../{3 pch disabled => 2 pch disabled}/c/meson.build | 0 .../failing build/{3 pch disabled => 2 pch disabled}/c/pch/prog.h | 0 .../{3 pch disabled => 2 pch disabled}/c/pch/prog_pch.c | 0 .../failing build/{3 pch disabled => 2 pch disabled}/c/prog.c | 0 .../failing build/{3 pch disabled => 2 pch disabled}/meson.build | 0 .../incDir/fileA.hpp | 0 .../main.cpp | 0 .../meson.build | 0 .../subprojects/cmMod/CMakeLists.txt | 0 .../subprojects/cmMod/cmMod.cpp | 0 .../subprojects/cmMod/cmMod.hpp | 0 .../test.json | 0 .../failing build/{5 failed pickled => 4 failed pickled}/false.py | 0 .../{5 failed pickled => 4 failed pickled}/meson.build | 0 .../osx/{9 global variable ar => 10 global variable ar}/libfile.c | 0 .../{9 global variable ar => 10 global variable ar}/libfile2.c | 0 .../{9 global variable ar => 10 global variable ar}/meson.build | 0 .../nativefile.ini | 0 .../osx/{9 global variable ar => 10 global variable ar}/prog.c | 0 25 files changed, 0 insertions(+), 0 deletions(-) rename test cases/common/{273 environment => 274 environment}/meson.build (100%) rename test cases/common/{273 environment => 274 environment}/testenv.py (100%) rename test cases/failing build/{2 hidden symbol => 1 hidden symbol}/bob.c (100%) rename test cases/failing build/{2 hidden symbol => 1 hidden symbol}/bob.h (100%) rename test cases/failing build/{2 hidden symbol => 1 hidden symbol}/bobuser.c (100%) rename test cases/failing build/{2 hidden symbol => 1 hidden symbol}/meson.build (100%) rename test cases/failing build/{3 pch disabled => 2 pch disabled}/c/meson.build (100%) rename test cases/failing build/{3 pch disabled => 2 pch disabled}/c/pch/prog.h (100%) rename test cases/failing build/{3 pch disabled => 2 pch disabled}/c/pch/prog_pch.c (100%) rename test cases/failing build/{3 pch disabled => 2 pch disabled}/c/prog.c (100%) rename test cases/failing build/{3 pch disabled => 2 pch disabled}/meson.build (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/incDir/fileA.hpp (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/main.cpp (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/meson.build (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/subprojects/cmMod/CMakeLists.txt (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/subprojects/cmMod/cmMod.cpp (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/subprojects/cmMod/cmMod.hpp (100%) rename test cases/failing build/{4 cmake subproject isolation => 3 cmake subproject isolation}/test.json (100%) rename test cases/failing build/{5 failed pickled => 4 failed pickled}/false.py (100%) rename test cases/failing build/{5 failed pickled => 4 failed pickled}/meson.build (100%) rename test cases/osx/{9 global variable ar => 10 global variable ar}/libfile.c (100%) rename test cases/osx/{9 global variable ar => 10 global variable ar}/libfile2.c (100%) rename test cases/osx/{9 global variable ar => 10 global variable ar}/meson.build (100%) rename test cases/osx/{9 global variable ar => 10 global variable ar}/nativefile.ini (100%) rename test cases/osx/{9 global variable ar => 10 global variable ar}/prog.c (100%) diff --git a/test cases/common/273 environment/meson.build b/test cases/common/274 environment/meson.build similarity index 100% rename from test cases/common/273 environment/meson.build rename to test cases/common/274 environment/meson.build diff --git a/test cases/common/273 environment/testenv.py b/test cases/common/274 environment/testenv.py similarity index 100% rename from test cases/common/273 environment/testenv.py rename to test cases/common/274 environment/testenv.py diff --git a/test cases/failing build/2 hidden symbol/bob.c b/test cases/failing build/1 hidden symbol/bob.c similarity index 100% rename from test cases/failing build/2 hidden symbol/bob.c rename to test cases/failing build/1 hidden symbol/bob.c diff --git a/test cases/failing build/2 hidden symbol/bob.h b/test cases/failing build/1 hidden symbol/bob.h similarity index 100% rename from test cases/failing build/2 hidden symbol/bob.h rename to test cases/failing build/1 hidden symbol/bob.h diff --git a/test cases/failing build/2 hidden symbol/bobuser.c b/test cases/failing build/1 hidden symbol/bobuser.c similarity index 100% rename from test cases/failing build/2 hidden symbol/bobuser.c rename to test cases/failing build/1 hidden symbol/bobuser.c diff --git a/test cases/failing build/2 hidden symbol/meson.build b/test cases/failing build/1 hidden symbol/meson.build similarity index 100% rename from test cases/failing build/2 hidden symbol/meson.build rename to test cases/failing build/1 hidden symbol/meson.build diff --git a/test cases/failing build/3 pch disabled/c/meson.build b/test cases/failing build/2 pch disabled/c/meson.build similarity index 100% rename from test cases/failing build/3 pch disabled/c/meson.build rename to test cases/failing build/2 pch disabled/c/meson.build diff --git a/test cases/failing build/3 pch disabled/c/pch/prog.h b/test cases/failing build/2 pch disabled/c/pch/prog.h similarity index 100% rename from test cases/failing build/3 pch disabled/c/pch/prog.h rename to test cases/failing build/2 pch disabled/c/pch/prog.h diff --git a/test cases/failing build/3 pch disabled/c/pch/prog_pch.c b/test cases/failing build/2 pch disabled/c/pch/prog_pch.c similarity index 100% rename from test cases/failing build/3 pch disabled/c/pch/prog_pch.c rename to test cases/failing build/2 pch disabled/c/pch/prog_pch.c diff --git a/test cases/failing build/3 pch disabled/c/prog.c b/test cases/failing build/2 pch disabled/c/prog.c similarity index 100% rename from test cases/failing build/3 pch disabled/c/prog.c rename to test cases/failing build/2 pch disabled/c/prog.c diff --git a/test cases/failing build/3 pch disabled/meson.build b/test cases/failing build/2 pch disabled/meson.build similarity index 100% rename from test cases/failing build/3 pch disabled/meson.build rename to test cases/failing build/2 pch disabled/meson.build diff --git a/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp b/test cases/failing build/3 cmake subproject isolation/incDir/fileA.hpp similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp rename to test cases/failing build/3 cmake subproject isolation/incDir/fileA.hpp diff --git a/test cases/failing build/4 cmake subproject isolation/main.cpp b/test cases/failing build/3 cmake subproject isolation/main.cpp similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/main.cpp rename to test cases/failing build/3 cmake subproject isolation/main.cpp diff --git a/test cases/failing build/4 cmake subproject isolation/meson.build b/test cases/failing build/3 cmake subproject isolation/meson.build similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/meson.build rename to test cases/failing build/3 cmake subproject isolation/meson.build diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt b/test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt rename to test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp b/test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/cmMod.cpp similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp rename to test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/cmMod.cpp diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp b/test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/cmMod.hpp similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp rename to test cases/failing build/3 cmake subproject isolation/subprojects/cmMod/cmMod.hpp diff --git a/test cases/failing build/4 cmake subproject isolation/test.json b/test cases/failing build/3 cmake subproject isolation/test.json similarity index 100% rename from test cases/failing build/4 cmake subproject isolation/test.json rename to test cases/failing build/3 cmake subproject isolation/test.json diff --git a/test cases/failing build/5 failed pickled/false.py b/test cases/failing build/4 failed pickled/false.py similarity index 100% rename from test cases/failing build/5 failed pickled/false.py rename to test cases/failing build/4 failed pickled/false.py diff --git a/test cases/failing build/5 failed pickled/meson.build b/test cases/failing build/4 failed pickled/meson.build similarity index 100% rename from test cases/failing build/5 failed pickled/meson.build rename to test cases/failing build/4 failed pickled/meson.build diff --git a/test cases/osx/9 global variable ar/libfile.c b/test cases/osx/10 global variable ar/libfile.c similarity index 100% rename from test cases/osx/9 global variable ar/libfile.c rename to test cases/osx/10 global variable ar/libfile.c diff --git a/test cases/osx/9 global variable ar/libfile2.c b/test cases/osx/10 global variable ar/libfile2.c similarity index 100% rename from test cases/osx/9 global variable ar/libfile2.c rename to test cases/osx/10 global variable ar/libfile2.c diff --git a/test cases/osx/9 global variable ar/meson.build b/test cases/osx/10 global variable ar/meson.build similarity index 100% rename from test cases/osx/9 global variable ar/meson.build rename to test cases/osx/10 global variable ar/meson.build diff --git a/test cases/osx/9 global variable ar/nativefile.ini b/test cases/osx/10 global variable ar/nativefile.ini similarity index 100% rename from test cases/osx/9 global variable ar/nativefile.ini rename to test cases/osx/10 global variable ar/nativefile.ini diff --git a/test cases/osx/9 global variable ar/prog.c b/test cases/osx/10 global variable ar/prog.c similarity index 100% rename from test cases/osx/9 global variable ar/prog.c rename to test cases/osx/10 global variable ar/prog.c From 9afe62232c64a7151d210900367674bb090cb3b3 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 26 Feb 2024 01:54:17 +0200 Subject: [PATCH 674/855] Fix lint warning. --- mesonbuild/compilers/d.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 4a4144d45df0..32f6d04ed8b8 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -488,11 +488,9 @@ def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]: # Parse all debug identifiers and the largest debug level identifier for d in kwargs['debug']: if isinstance(d, int): - if d > debug_level: - debug_level = d + debug_level = max(debug_level, d) elif isinstance(d, str) and d.isdigit(): - if int(d) > debug_level: - debug_level = int(d) + debug_level = max(debug_level, int(d)) else: res.append(f'{debug_arg}={d}') @@ -507,11 +505,9 @@ def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]: # Parse all version identifiers and the largest version level identifier for v in kwargs['versions']: if isinstance(v, int): - if v > version_level: - version_level = v + version_level = max(version_level, v) elif isinstance(v, str) and v.isdigit(): - if int(v) > version_level: - version_level = int(v) + version_level = max(version_level, int(v)) else: res.append(f'{version_arg}={v}') From 2b5c8cc6a76233d38dce025c38a348400ffb8786 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 26 Feb 2024 09:59:39 -0800 Subject: [PATCH 675/855] modules/rust: Fix New Version check that was not updated Should be 1.4.0 but was 1.3.0 --- mesonbuild/modules/rust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 73ac032afb21..8534dfa31a1e 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -202,7 +202,7 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func 'output_inline_wrapper', str, default='', - since='1.3.0', + since='1.4.0', ), DEPENDENCIES_KW.evolve(since='1.0.0'), ) From fb72a8ecdb9d571f15163454e4f513ded0b28cc5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 26 Feb 2024 10:15:14 -0800 Subject: [PATCH 676/855] docs: fix typo in snippet: "hueristic" -> "heuristic" --- docs/markdown/snippets/rust-bindgen-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/snippets/rust-bindgen-cpp.md b/docs/markdown/snippets/rust-bindgen-cpp.md index 7d1bec37d6ec..bcb1feac2040 100644 --- a/docs/markdown/snippets/rust-bindgen-cpp.md +++ b/docs/markdown/snippets/rust-bindgen-cpp.md @@ -1,4 +1,4 @@ -## Bindgen will now use Meson's hueristic for what is a C++ header +## Bindgen will now use Meson's heuristic for what is a C++ header Bindgen natively assumes that a file with the extension `.hpp` is a C++ header, but that everything else is a C header. Meson has a whole list of extensions it From f013a688980a6014cab03386910d1c464a4e4a8f Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 26 Jan 2024 13:44:19 +0100 Subject: [PATCH 677/855] rewriter: allow setting values regardless of the previous type Alterations to kwargs come in two flavors: 1. Remove/replace values (delete/set) 2. Modify values (add/remove) Only for the second flavor do we care about the type of any existing value. --- mesonbuild/rewriter.py | 188 ++++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 87 deletions(-) diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index 434b21974732..fd5413ac1c0f 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -98,17 +98,23 @@ def _symbol(val: str) -> SymbolNode: class MTypeBase: def __init__(self, node: T.Optional[BaseNode] = None): if node is None: - self.node = self._new_node() # lgtm [py/init-calls-subclass] (node creation does not depend on base class state) + self.node = self.new_node() else: self.node = node self.node_type = None - for i in self.supported_nodes(): # lgtm [py/init-calls-subclass] (listing nodes does not depend on base class state) + for i in self.supported_nodes(): if isinstance(self.node, i): self.node_type = i - def _new_node(self): + @classmethod + def new_node(cls, value=None): # Overwrite in derived class - raise RewriterException('Internal error: _new_node of MTypeBase was called') + raise RewriterException('Internal error: new_node of MTypeBase was called') + + @classmethod + def supported_nodes(cls): + # Overwrite in derived class + return [] def can_modify(self): return self.node_type is not None @@ -116,14 +122,6 @@ def can_modify(self): def get_node(self): return self.node - def supported_nodes(self): - # Overwrite in derived class - return [] - - def set_value(self, value): - # Overwrite in derived class - mlog.warning('Cannot set the value of type', mlog.bold(type(self).__name__), '--> skipping') - def add_value(self, value): # Overwrite in derived class mlog.warning('Cannot add a value of type', mlog.bold(type(self).__name__), '--> skipping') @@ -140,63 +138,74 @@ class MTypeStr(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return StringNode(Token('', '', 0, 0, 0, None, '')) + @classmethod + def new_node(cls, value=None): + if value is None: + value = '' + return StringNode(Token('', '', 0, 0, 0, None, str(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [StringNode] - def set_value(self, value): - self.node.value = str(value) - class MTypeBool(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return BooleanNode(Token('', '', 0, 0, 0, None, False)) + @classmethod + def new_node(cls, value=None): + return BooleanNode(Token('', '', 0, 0, 0, None, bool(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [BooleanNode] - def set_value(self, value): - self.node.value = bool(value) - class MTypeID(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return IdNode(Token('', '', 0, 0, 0, None, '')) + @classmethod + def new_node(cls, value=None): + if value is None: + value = '' + return IdNode(Token('', '', 0, 0, 0, None, str(value))) - def supported_nodes(self): + @classmethod + def supported_nodes(cls): return [IdNode] - def set_value(self, value): - self.node.value = str(value) - class MTypeList(MTypeBase): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_node(self): - return ArrayNode(_symbol('['), ArgumentNode(Token('', '', 0, 0, 0, None, '')), _symbol(']')) - - def _new_element_node(self, value): + @classmethod + def new_node(cls, value=None): + if value is None: + value = [] + elif not isinstance(value, list): + return cls._new_element_node(value) + args = ArgumentNode(Token('', '', 0, 0, 0, None, '')) + args.arguments = [cls._new_element_node(i) for i in value] + return ArrayNode(_symbol('['), args, _symbol(']')) + + @classmethod + def _new_element_node(cls, value): # Overwrite in derived class raise RewriterException('Internal error: _new_element_node of MTypeList was called') def _ensure_array_node(self): if not isinstance(self.node, ArrayNode): tmp = self.node - self.node = self._new_node() - self.node.args.arguments += [tmp] + self.node = self.new_node() + self.node.args.arguments = [tmp] - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: # Overwrite in derived class return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: # Overwrite in derived class return False @@ -206,20 +215,14 @@ def get_node(self): return self.node.args.arguments[0] return self.node - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): # Overwrite in derived class return [] - def supported_nodes(self): - return [ArrayNode] + self.supported_element_nodes() - - def set_value(self, value): - if not isinstance(value, list): - value = [value] - self._ensure_array_node() - self.node.args.arguments = [] # Remove all current nodes - for i in value: - self.node.args.arguments += [self._new_element_node(i)] + @classmethod + def supported_nodes(cls): + return [ArrayNode] + cls.supported_element_nodes() def add_value(self, value): if not isinstance(value, list): @@ -254,40 +257,48 @@ class MTypeStrList(MTypeList): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_element_node(self, value): + @classmethod + def _new_element_node(cls, value): return StringNode(Token('', '', 0, 0, 0, None, str(value))) - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: if isinstance(node, BaseStringNode): return node.value == value return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): return [StringNode] class MTypeIDList(MTypeList): def __init__(self, node: T.Optional[BaseNode] = None): super().__init__(node) - def _new_element_node(self, value): + @classmethod + def _new_element_node(cls, value): return IdNode(Token('', '', 0, 0, 0, None, str(value))) - def _check_is_equal(self, node, value) -> bool: + @staticmethod + def _check_is_equal(node, value) -> bool: if isinstance(node, IdNode): return node.value == value return False - def _check_regex_matches(self, node, regex: str) -> bool: + @staticmethod + def _check_regex_matches(node, regex: str) -> bool: if isinstance(node, BaseStringNode): return re.match(regex, node.value) is not None return False - def supported_element_nodes(self): + @classmethod + def supported_element_nodes(cls): return [IdNode] rewriter_keys = { @@ -548,39 +559,42 @@ def process_kwargs(self, cmd): self.handle_error() continue - # Remove the key from the kwargs if cmd['operation'] == 'delete': - if key in arg_node.kwargs: - mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') - del arg_node.kwargs[key] - num_changed += 1 - else: + # Remove the key from the kwargs + if key not in arg_node.kwargs: mlog.log(' -- Key', mlog.bold(key), 'is already deleted') - continue + continue + mlog.log(' -- Deleting', mlog.bold(key), 'from the kwargs') + del arg_node.kwargs[key] + elif cmd['operation'] == 'set': + # Replace the key from the kwargs + mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(str(val))) + arg_node.kwargs[key] = kwargs_def[key].new_node(val) + else: + # Modify the value from the kwargs + + if key not in arg_node.kwargs: + arg_node.kwargs[key] = None + modifier = kwargs_def[key](arg_node.kwargs[key]) + if not modifier.can_modify(): + mlog.log(' -- Skipping', mlog.bold(key), 'because it is too complex to modify') + continue + + # Apply the operation + val_str = str(val) + if cmd['operation'] == 'add': + mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) + modifier.add_value(val) + elif cmd['operation'] == 'remove': + mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_value(val) + elif cmd['operation'] == 'remove_regex': + mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) + modifier.remove_regex(val) + + # Write back the result + arg_node.kwargs[key] = modifier.get_node() - if key not in arg_node.kwargs: - arg_node.kwargs[key] = None - modifier = kwargs_def[key](arg_node.kwargs[key]) - if not modifier.can_modify(): - mlog.log(' -- Skipping', mlog.bold(key), 'because it is to complex to modify') - - # Apply the operation - val_str = str(val) - if cmd['operation'] == 'set': - mlog.log(' -- Setting', mlog.bold(key), 'to', mlog.yellow(val_str)) - modifier.set_value(val) - elif cmd['operation'] == 'add': - mlog.log(' -- Adding', mlog.yellow(val_str), 'to', mlog.bold(key)) - modifier.add_value(val) - elif cmd['operation'] == 'remove': - mlog.log(' -- Removing', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifier.remove_value(val) - elif cmd['operation'] == 'remove_regex': - mlog.log(' -- Removing all values matching', mlog.yellow(val_str), 'from', mlog.bold(key)) - modifier.remove_regex(val) - - # Write back the result - arg_node.kwargs[key] = modifier.get_node() num_changed += 1 # Convert the keys back to IdNode's From 0dc2499b2ae58e35e21d6796be238d6cca42466c Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 26 Feb 2024 22:52:57 +0200 Subject: [PATCH 678/855] Bump version number for rc1. --- man/meson.1 | 2 +- mesonbuild/coredata.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/meson.1 b/man/meson.1 index b98401312b8b..8bd483759c20 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "November 2023" "meson 1.3.0" "User Commands" +.TH MESON "1" "February 2024" "meson 1.4.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 658ae47b1118..e6e831a2f9cb 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright 2013-2023 The Meson development team +# Copyright 2013-2024 The Meson development team # Copyright © 2023 Intel Corporation from __future__ import annotations @@ -70,7 +70,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.3.99' +version = '1.4.0.rc1' # 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 e9ee63ed033cb2fa64349fbe35f10e82ae264024 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 27 Feb 2024 23:24:28 +0100 Subject: [PATCH 679/855] cargo: support lib.path in Cargo.toml Cargo implements this configuration option to override the entry point of the library. To get test coverage, I've modified one of the two Cargo subprojects in the test to use a non-default library entrypoint. The other still uses the default. --- mesonbuild/cargo/interpreter.py | 5 +++-- .../rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml | 1 + .../22 cargo subproject/subprojects/foo-rs/{src => }/lib.rs | 0 3 files changed, 4 insertions(+), 2 deletions(-) rename test cases/rust/22 cargo subproject/subprojects/foo-rs/{src => }/lib.rs (100%) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 2797f9fe074e..3cbc453ef73c 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -206,6 +206,7 @@ class Library(BuildTarget): doctest: bool = True doc: bool = True + path: str = os.path.join('src', 'lib.rs') proc_macro: bool = False crate_type: T.List[manifest.CRATE_TYPE] = dataclasses.field(default_factory=lambda: ['lib']) doc_scrape_examples: bool = True @@ -606,7 +607,7 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR posargs: T.List[mparser.BaseNode] = [ build.string(fixup_meson_varname(cargo.package.name)), - build.string(os.path.join('src', 'lib.rs')), + build.string(cargo.lib.path), ] kwargs: T.Dict[str, mparser.BaseNode] = { @@ -696,7 +697,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser. # Libs are always auto-discovered and there's no other way to handle them, # which is unfortunate for reproducability - if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, 'src', 'lib.rs')): + if os.path.exists(os.path.join(env.source_dir, cargo.subdir, cargo.path, cargo.lib.path)): for crate_type in cargo.lib.crate_type: ast.extend(_create_lib(cargo, build, crate_type)) diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml index 796548d63f2a..0f0225d06cc9 100644 --- a/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml +++ b/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [lib] crate-type = ["cdylib"] +path = "lib.rs" # This dependency does not exist, verify optional works. [dependencies.notfound] diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/foo-rs/lib.rs similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/foo-rs/src/lib.rs rename to test cases/rust/22 cargo subproject/subprojects/foo-rs/lib.rs From 95e31b756f67f72939dd1587dccca9f497e09a18 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 28 Feb 2024 00:19:30 -0500 Subject: [PATCH 680/855] remove junk file from the repository root Sider has not been used by meson for a long time. Also it appears to no longer exist. --- sider.yml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 sider.yml diff --git a/sider.yml b/sider.yml deleted file mode 100644 index 5c56196924b8..000000000000 --- a/sider.yml +++ /dev/null @@ -1,7 +0,0 @@ -linter: - flake8: - version: 3 - plugins: - - flake8-blind-except - - flake8-builtins - - flake8-bugbear From 937d1c639a9a83e0671e7e4cd3686ca3e8c9566b Mon Sep 17 00:00:00 2001 From: David Seifert Date: Tue, 27 Feb 2024 12:52:10 +0100 Subject: [PATCH 681/855] nvcc: avoid adding `-Wpedantic` to compile lines * `-Wpedantic` creates useless churn due to its use of gcc-line directives: ../foo.cu:1:3: warning: style of line directive is a GCC extension 1 | namespace Foo { | ^~ https://stackoverflow.com/a/31001220 --- mesonbuild/compilers/cuda.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 2ea5d9f245b8..0e2d9457850e 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -192,7 +192,13 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ self.exe_wrapper = exe_wrapper self.host_compiler = host_compiler self.base_options = host_compiler.base_options - self.warn_args = {level: self._to_host_flags(flags) for level, flags in host_compiler.warn_args.items()} + # -Wpedantic generates useless churn due to nvcc's dual compilation model producing + # a temporary host C++ file that includes gcc-style line directives: + # https://stackoverflow.com/a/31001220 + self.warn_args = { + level: self._to_host_flags(list(f for f in flags if f != '-Wpedantic')) + for level, flags in host_compiler.warn_args.items() + } @classmethod def _shield_nvcc_list_arg(cls, arg: str, listmode: bool = True) -> str: From aee941559c4b88a062e88186819a820c69c200ae Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 27 Feb 2024 14:51:25 -0500 Subject: [PATCH 682/855] rust: recursively pull proc-macro dependencies as well When the proc-macro rlib is in a different subdir, it would miss the needed -L argument and rustc would not find it. Meson was assuming that proc-macros are only needed when building libraries that uses it, but it turns out that was wrong, as show by the unit test. --- mesonbuild/build.py | 2 -- 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 +++++++ 5 files changed, 27 insertions(+), 2 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 8e41f0bb02af..3c9d3a06c699 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1295,8 +1295,6 @@ 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': - continue if include_internals or not t.is_internal(): result.add(t) if isinstance(t, StaticLibrary): 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()); +} From c67a6e1d7cdb7883621eaceda9af08b9eecf34a8 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 27 Feb 2024 20:59:33 -0500 Subject: [PATCH 683/855] Revert "Fix base options not reconfigurable" This reverts commit 98db3e7a2e498a6d96ec50b39ef51ef312d6f0a3. --- mesonbuild/coredata.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e6e831a2f9cb..25a506848b2b 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1003,11 +1003,9 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], # not differ between them even when they are valid for both. if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding: continue - # Skip compiler and backend options, they are handled when + # Skip base, compiler, and backend options, they are handled when # adding languages and setting backend. - if k.type in {OptionType.COMPILER, OptionType.BACKEND}: - continue - if k.type == OptionType.BASE and env.first_invocation: + if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}: continue options[k] = v From 4ed6d75d962b3d43a9f7e8f5154e48d0bef01cc9 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 28 Feb 2024 11:58:29 -0500 Subject: [PATCH 684/855] Set PYTHONIOENCODING when running tests For instance, on Windows, if the terminal is in cp65001, the subprocess output is not encoded correctly and it results in error when running unit test. --- unittests/allplatformstests.py | 2 +- unittests/baseplatformtests.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index bfd0b18561dd..777f2f92a127 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -471,7 +471,7 @@ def test_replace_unencodable_xml_chars_unit(self): # Ensure command output and JSON / text logs are not mangled. raw_output_sample = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b' assert raw_output_sample in tests_command_output - text_log = Path(self.logdir, 'testlog.txt').read_text() + text_log = Path(self.logdir, 'testlog.txt').read_text(encoding='utf-8') assert raw_output_sample in text_log json_log = json.loads(Path(self.logdir, 'testlog.json').read_bytes()) assert raw_output_sample in json_log['stdout'] diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index ec3f18908466..6125ed933209 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -85,6 +85,7 @@ def setUp(self): # XCode backend is untested with unit tests, help welcome! self.no_rebuild_stdout = [f'UNKNOWN BACKEND {self.backend.name!r}'] os.environ['COLUMNS'] = '80' + os.environ['PYTHONIOENCODING'] = 'utf8' self.builddirs = [] self.new_builddir() From 76f6874e4841954a63ac9fb79deec353f50648d1 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 27 Feb 2024 21:47:50 -0500 Subject: [PATCH 685/855] Fix base and compiler options not reconfigurable. Fixes #12920. --- mesonbuild/compilers/detect.py | 2 +- mesonbuild/coredata.py | 17 +++++++++-------- mesonbuild/interpreter/interpreter.py | 3 +++ run_project_tests.py | 2 +- .../122 reconfigure base options/meson.build | 5 +++++ unittests/platformagnostictests.py | 10 ++++++++++ 6 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 test cases/unit/122 reconfigure base options/meson.build diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index d8f48f3e00ef..dbc2b4879208 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -106,7 +106,7 @@ def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoic if comp is None: return comp assert comp.for_machine == for_machine - env.coredata.process_new_compiler(lang, comp, env) + env.coredata.process_compiler_options(lang, comp, env) if not skip_sanity_check: comp.sanity_check(env.get_scratch_dir(), env) env.coredata.compilers[comp.for_machine][lang] = comp diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 25a506848b2b..b2b966b7d726 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1017,6 +1017,7 @@ def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str, value = env.options.get(k) if value is not None: o.set_value(value) + self.options[k] = o # override compiler option on reconfigure self.options.setdefault(k, o) def add_lang_args(self, lang: str, comp: T.Type['Compiler'], @@ -1028,20 +1029,20 @@ def add_lang_args(self, lang: str, comp: T.Type['Compiler'], # `self.options.update()`` is perfectly safe. self.options.update(compilers.get_global_options(lang, comp, for_machine, env)) - def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: + def process_compiler_options(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: from . import compilers self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env) enabled_opts: T.List[OptionKey] = [] for key in comp.base_options: - if key in self.options: - continue - oobj = copy.deepcopy(compilers.base_options[key]) - if key in env.options: - oobj.set_value(env.options[key]) - enabled_opts.append(key) - self.options[key] = oobj + if key not in self.options: + self.options[key] = copy.deepcopy(compilers.base_options[key]) + if key in env.options: + self.options[key].set_value(env.options[key]) + enabled_opts.append(key) + elif key in env.options: + self.options[key].set_value(env.options[key]) self.emit_base_options_warnings(enabled_opts) def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 79a61ed0ea2e..e5a201e053e4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1518,6 +1518,9 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach continue else: raise + else: + # update new values from commandline, if it applies + self.coredata.process_compiler_options(lang, comp, self.environment) # Add per-subproject compiler options. They inherit value from main project. if self.subproject: diff --git a/run_project_tests.py b/run_project_tests.py index 60ff56f70851..6fc9cb7f77fa 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -981,7 +981,7 @@ def have_working_compiler(lang: str, use_tmp: bool) -> bool: return False if not compiler: return False - env.coredata.process_new_compiler(lang, compiler, env) + env.coredata.process_compiler_options(lang, compiler, env) try: compiler.sanity_check(env.get_scratch_dir(), env) except mesonlib.MesonException: diff --git a/test cases/unit/122 reconfigure base options/meson.build b/test cases/unit/122 reconfigure base options/meson.build new file mode 100644 index 000000000000..67e83d1e490b --- /dev/null +++ b/test cases/unit/122 reconfigure base options/meson.build @@ -0,0 +1,5 @@ +project('reconfigure', 'c', +default_options: ['c_std=c89']) + +message('b_ndebug: ' + get_option('b_ndebug')) +message('c_std: ' + get_option('c_std')) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 581ecacccabe..6884da42e763 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -275,3 +275,13 @@ def test_error_configuring_subdir(self): self.assertIn('first statement must be a call to project()', out) # provide guidance diagnostics by finding a file whose first AST statement is project() self.assertIn(f'Did you mean to run meson from the directory: "{testdir}"?', out) + + def test_reconfigure_base_options(self): + testdir = os.path.join(self.unit_test_dir, '122 reconfigure base options') + out = self.init(testdir, extra_args=['-Db_ndebug=true']) + self.assertIn('\nMessage: b_ndebug: true\n', out) + self.assertIn('\nMessage: c_std: c89\n', out) + + out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dc_std=c99']) + self.assertIn('\nMessage: b_ndebug: if-release\n', out) + self.assertIn('\nMessage: c_std: c99\n', out) From cc4cfbcad92945a1629c80664e1eb755c68905dd Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 28 Feb 2024 09:23:46 -0500 Subject: [PATCH 686/855] Fix unknown base options not detected in commandline arguments --- mesonbuild/coredata.py | 7 ++++++- unittests/allplatformstests.py | 2 +- unittests/platformagnostictests.py | 7 +++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index b2b966b7d726..e7de3d7fde32 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -974,6 +974,8 @@ def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', f return dirty def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None: + from .compilers import base_options + # Main project can set default options on subprojects, but subprojects # can only set default options on themselves. # Preserve order: if env.options has 'buildtype' it must come after @@ -1005,7 +1007,10 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], continue # Skip base, compiler, and backend options, they are handled when # adding languages and setting backend. - if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}: + if k.type in {OptionType.COMPILER, OptionType.BACKEND}: + continue + if k.type == OptionType.BASE and k in base_options: + # set_options will report unknown base options continue options[k] = v diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 777f2f92a127..1064e6adb34d 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2694,7 +2694,7 @@ def test_command_line(self): # It is not an error to set wrong option for unknown subprojects or # language because we don't have control on which one will be selected. - self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1', '-Db_wrong=1']) + self.init(testdir, extra_args=['-Dc_wrong=1', '-Dwrong:bad=1']) self.wipe() # Test we can set subproject option diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 6884da42e763..21cb3b94563c 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -285,3 +285,10 @@ def test_reconfigure_base_options(self): out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dc_std=c99']) self.assertIn('\nMessage: b_ndebug: if-release\n', out) self.assertIn('\nMessage: c_std: c99\n', out) + + def test_setup_with_unknown_option(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + + for option in ('not_an_option', 'b_not_an_option'): + out = self.init(testdir, extra_args=['--wipe', f'-D{option}=1'], allow_fail=True) + self.assertIn(f'ERROR: Unknown options: "{option}"', out) From 46f3cff5b26230900473efcd743763daa7c90453 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 26 Feb 2024 18:54:47 -0500 Subject: [PATCH 687/855] compilers: avoid catching -Wl,-soname and wrapping with start/end group This is just a bad regex match, because it matches *.so as a prospective filename input even though it is actually not an input but a linker flag. --start-group is only relevant to input files... --- 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 76c8e041341c..0c840a4f6d02 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -44,7 +44,7 @@ # do). This gives up DRYer type checking, with no runtime impact Compiler = object -GROUP_FLAGS = re.compile(r'''\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | +GROUP_FLAGS = re.compile(r'''^(?!-Wl,) .*\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ | ^(?:-Wl,)?-l | \.a$''', re.X) From 4d1bfd0939105d244f974974d52e73c46de0ab53 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 26 Feb 2024 19:55:54 -0500 Subject: [PATCH 688/855] compilers: only wrap multiple input libraries with start/end group When only a single input file shows up in an arglist, it makes no sense to inject `-W,--start-group -lone -Wl,--end-group`, since there is nothing being grouped together. It's just longer command lines for nothing. --- mesonbuild/compilers/mixins/clike.py | 3 ++- mesonbuild/linkers/linkers.py | 4 ++-- unittests/internaltests.py | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 0c840a4f6d02..25feb5c3866c 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -84,7 +84,8 @@ def to_native(self, copy: bool = False) -> T.List[str]: if group_start < 0: # First occurrence of a library group_start = i - if group_start >= 0: + # Only add groups if there are multiple libraries. + if group_end > group_start >= 0: # Last occurrence of a library new.insert(group_end + 1, '-Wl,--end-group') new.insert(group_start, '-Wl,--start-group') diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index e4db0157fd62..2048268193a5 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -978,7 +978,7 @@ def __init__(self, for_machine: mesonlib.MachineChoice, version=version) def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: - if not args: + if len(args) < 2: return args return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') @@ -1064,7 +1064,7 @@ def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, version=version) def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: - if not args: + if len(args) < 2: return args return self._apply_prefix('--start-group') + args + self._apply_prefix('--end-group') diff --git a/unittests/internaltests.py b/unittests/internaltests.py index fd843c88c5db..0f2622e35bbe 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -241,7 +241,7 @@ def test_compiler_args_class_gnuld(self): gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] ## Test that 'direct' append and extend works l = gcc.compiler_args(['-Lfoodir', '-lfoo']) - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-lfoo']) # Direct-adding a library and a libpath appends both correctly l.extend_direct(['-Lbardir', '-lbar']) self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Lbardir', '-lbar', '-Wl,--end-group']) @@ -269,10 +269,10 @@ def test_compiler_args_remove_system(self): gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] ## Test that 'direct' append and extend works l = gcc.compiler_args(['-Lfoodir', '-lfoo']) - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-lfoo']) ## Test that to_native removes all system includes l += ['-isystem/usr/include', '-isystem=/usr/share/include', '-DSOMETHING_IMPORTANT=1', '-isystem', '/usr/local/include'] - self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-Wl,--start-group', '-lfoo', '-Wl,--end-group', '-DSOMETHING_IMPORTANT=1']) + self.assertEqual(l.to_native(copy=True), ['-Lfoodir', '-lfoo', '-DSOMETHING_IMPORTANT=1']) def test_string_templates_substitution(self): dictfunc = mesonbuild.mesonlib.get_filenames_templates_dict From ac1d0aea582b225869732f53108754af2ccde7e1 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 3 Mar 2024 22:05:33 +0200 Subject: [PATCH 689/855] Condense test dirs for rc2. --- test cases/failing/100 bool in combo/test.json | 5 ----- .../meson.build | 0 .../test.json | 2 +- .../{102 no fallback => 101 no fallback}/meson.build | 0 .../subprojects/foob/meson.build | 0 .../failing/{102 no fallback => 101 no fallback}/test.json | 0 .../meson.build | 0 .../meson_options.txt | 0 .../{103 feature require => 102 feature require}/test.json | 0 .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../sub/meson.build | 0 .../test.json | 2 +- .../109 invalid fstring/meson.build | 0 .../109 invalid fstring/test.json | 0 .../meson.build | 0 .../{107 invalid fstring => 106 invalid fstring}/test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../{109 empty fallback => 108 empty fallback}/meson.build | 0 .../subprojects/foo/meson.build | 0 .../{109 empty fallback => 108 empty fallback}/test.json | 2 +- .../meson.build | 0 .../subprojects/cmlib/CMakeLists.txt | 0 .../subprojects/cmlib/main.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../src/header.h | 0 .../src/source.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../trivial.c | 0 .../meson.build | 0 .../test.json | 2 +- .../trivial.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/A/meson.build | 0 .../subprojects/B/meson.build | 0 .../test.json | 2 +- .../main.rs | 0 .../meson.build | 0 .../test.json | 2 +- .../main.rs | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/sub/main.c | 0 .../subprojects/sub/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/cmlib/CMakeLists.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../subprojects/subproj1/file.txt | 0 .../subprojects/subproj1/meson.build | 0 .../subprojects/subproj1/nested/meson.build | 0 .../subprojects/subproj2/file.txt | 0 .../subprojects/subproj2/meson.build | 0 .../subprojects/subproj2/nested/meson.build | 0 .../subprojects/subproj3/file.txt | 0 .../subprojects/subproj3/meson.build | 0 .../test.json | 2 +- .../inc/lib.h | 0 .../lib.c | 0 .../meson.build | 0 .../subprojects/a/meson.build | 0 .../subprojects/a/prog.c | 0 .../test.json | 2 +- .../inc/lib.h | 0 .../lib.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../src1.c | 0 .../src2.c | 0 .../test.json | 2 +- .../main.c | 0 .../meson.build | 0 .../subprojects/sub/meson.build | 0 .../test.json | 2 +- .../exe.c | 0 .../lib.in | 0 .../meson.build | 0 .../test.json | 0 .../{128 invalid ast => 127 invalid ast}/meson.build | 0 .../failing/{128 invalid ast => 127 invalid ast}/test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../{130 utf8 with bom => 129 utf8 with bom}/meson.build | 0 .../{130 utf8 with bom => 129 utf8 with bom}/test.json | 2 +- .../meson.build | 0 .../subdir/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson.options | 0 .../test.json | 2 +- .../meson.build | 0 .../simple.c | 0 .../simple.h | 0 .../test.json | 2 +- .../meson.build | 0 .../prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../failing/{51 slashname => 50 slashname}/meson.build | 0 .../failing/{51 slashname => 50 slashname}/sub/meson.build | 0 .../failing/{51 slashname => 50 slashname}/sub/prog.c | 0 test cases/failing/{51 slashname => 50 slashname}/test.json | 2 +- .../meson-foo/meson.build | 0 .../meson.build | 0 .../test.json | 2 +- .../{53 or on new line => 52 or on new line}/meson.build | 0 .../meson_options.txt | 0 .../{53 or on new line => 52 or on new line}/test.json | 2 +- .../meson.build | 0 .../module.c | 0 .../prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subprojects/abc/meson.build | 0 .../subprojects/abc/meson_options.txt | 0 .../{56 getoption prefix => 55 getoption prefix}/test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 2 +- .../meson.build | 0 .../{58 subproj filegrab => 57 subproj filegrab}/prog.c | 0 .../subprojects/a/meson.build | 0 .../{58 subproj filegrab => 57 subproj filegrab}/test.json | 2 +- .../{59 grab subproj => 58 grab subproj}/meson.build | 0 .../subprojects/foo/meson.build | 0 .../subprojects/foo/sub.c | 0 .../failing/{59 grab subproj => 58 grab subproj}/test.json | 2 +- .../{60 grab sibling => 59 grab sibling}/meson.build | 0 .../subprojects/a/meson.build | 0 .../subprojects/b/meson.build | 0 .../subprojects/b/sneaky.c | 0 .../failing/{60 grab sibling => 59 grab sibling}/test.json | 2 +- .../meson.build | 0 .../prog.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../main.c | 0 .../meson.build | 0 .../subprojects/a/a.c | 0 .../subprojects/a/a.h | 0 .../subprojects/a/meson.build | 0 .../subprojects/b/b.c | 0 .../subprojects/b/b.h | 0 .../subprojects/b/meson.build | 0 .../subprojects/c/c.h | 0 .../subprojects/c/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../file1.txt | 0 .../file2.txt | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subdir/meson.build | 0 .../{66 skip only subdir => 65 skip only subdir}/test.json | 2 +- .../{67 dual override => 66 dual override}/meson.build | 0 .../{67 dual override => 66 dual override}/overrides.py | 0 .../{67 dual override => 66 dual override}/test.json | 2 +- .../{68 override used => 67 override used}/meson.build | 0 .../failing/{68 override used => 67 override used}/other.py | 0 .../{68 override used => 67 override used}/something.py | 0 .../{68 override used => 67 override used}/test.json | 2 +- .../meson.build | 0 .../returncode.py | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../input | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../module.c | 0 .../prog.c | 0 .../test.json | 2 +- .../config9.h.in | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../failing/{75 unfound run => 74 unfound run}/meson.build | 0 .../failing/{75 unfound run => 74 unfound run}/test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../foo.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../failing/{81 dub library => 80 dub library}/meson.build | 0 .../failing/{81 dub library => 80 dub library}/test.json | 2 +- .../{82 dub executable => 81 dub executable}/meson.build | 0 .../{82 dub executable => 81 dub executable}/test.json | 2 +- .../{83 dub compiler => 82 dub compiler}/meson.build | 0 .../failing/{83 dub compiler => 82 dub compiler}/test.json | 2 +- .../meson.build | 0 .../subprojects/somesubproj/meson.build | 0 .../test.json | 2 +- .../input | 0 .../meson.build | 0 .../test.json | 2 +- .../failing/{86 kwarg dupe => 85 kwarg dupe}/meson.build | 0 test cases/failing/{86 kwarg dupe => 85 kwarg dupe}/prog.c | 0 .../failing/{86 kwarg dupe => 85 kwarg dupe}/test.json | 2 +- .../meson.build | 0 .../{87 missing pch file => 86 missing pch file}/prog.c | 0 .../{87 missing pch file => 86 missing pch file}/test.json | 2 +- .../include/pch.h | 0 .../meson.build | 0 .../prog.c | 0 .../src/pch.c | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../Info.plist.cpp | 0 .../meson.build | 0 .../preproc.py | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../{94 no native compiler => 93 no native compiler}/main.c | 0 .../meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../subdir/meson.build | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../test.json | 2 +- test cases/failing/{97 no lang => 96 no lang}/main.c | 0 test cases/failing/{97 no lang => 96 no lang}/meson.build | 0 test cases/failing/{97 no lang => 96 no lang}/test.json | 2 +- .../meson.build | 0 .../test.json | 2 +- .../trivial.gresource.xml | 0 .../{99 number in combo => 98 number in combo}/meson.build | 0 .../nativefile.ini | 0 .../{99 number in combo => 98 number in combo}/test.json | 2 +- .../{100 bool in combo => 99 bool in combo}/meson.build | 0 .../meson_options.txt | 0 .../{100 bool in combo => 99 bool in combo}/nativefile.ini | 0 test cases/failing/99 bool in combo/test.json | 5 +++++ unittests/allplatformstests.py | 6 +++--- 273 files changed, 88 insertions(+), 88 deletions(-) delete mode 100644 test cases/failing/100 bool in combo/test.json rename test cases/failing/{101 compiler no lang => 100 compiler no lang}/meson.build (100%) rename test cases/failing/{101 compiler no lang => 100 compiler no lang}/test.json (66%) rename test cases/failing/{102 no fallback => 101 no fallback}/meson.build (100%) rename test cases/failing/{102 no fallback => 101 no fallback}/subprojects/foob/meson.build (100%) rename test cases/failing/{102 no fallback => 101 no fallback}/test.json (100%) rename test cases/failing/{103 feature require => 102 feature require}/meson.build (100%) rename test cases/failing/{103 feature require => 102 feature require}/meson_options.txt (100%) rename test cases/failing/{103 feature require => 102 feature require}/test.json (100%) rename test cases/failing/{104 feature require.bis => 103 feature require.bis}/meson.build (100%) rename test cases/failing/{104 feature require.bis => 103 feature require.bis}/meson_options.txt (100%) rename test cases/failing/{104 feature require.bis => 103 feature require.bis}/test.json (100%) rename test cases/failing/{105 no build get_external_property => 104 no build get_external_property}/meson.build (100%) rename test cases/failing/{105 no build get_external_property => 104 no build get_external_property}/test.json (63%) rename test cases/failing/{106 enter subdir twice => 105 enter subdir twice}/meson.build (100%) rename test cases/failing/{106 enter subdir twice => 105 enter subdir twice}/sub/meson.build (100%) rename test cases/failing/{106 enter subdir twice => 105 enter subdir twice}/test.json (64%) rename test cases/failing/{107 invalid fstring => 106 invalid fstring}/109 invalid fstring/meson.build (100%) rename test cases/failing/{107 invalid fstring => 106 invalid fstring}/109 invalid fstring/test.json (100%) rename test cases/failing/{107 invalid fstring => 106 invalid fstring}/meson.build (100%) rename test cases/failing/{107 invalid fstring => 106 invalid fstring}/test.json (63%) rename test cases/failing/{108 compiler argument checking => 107 compiler argument checking}/meson.build (100%) rename test cases/failing/{108 compiler argument checking => 107 compiler argument checking}/test.json (66%) rename test cases/failing/{109 empty fallback => 108 empty fallback}/meson.build (100%) rename test cases/failing/{109 empty fallback => 108 empty fallback}/subprojects/foo/meson.build (100%) rename test cases/failing/{109 empty fallback => 108 empty fallback}/test.json (65%) rename test cases/failing/{110 cmake executable dependency => 109 cmake executable dependency}/meson.build (100%) rename test cases/failing/{110 cmake executable dependency => 109 cmake executable dependency}/subprojects/cmlib/CMakeLists.txt (100%) rename test cases/failing/{110 cmake executable dependency => 109 cmake executable dependency}/subprojects/cmlib/main.c (100%) rename test cases/failing/{110 cmake executable dependency => 109 cmake executable dependency}/test.json (77%) rename test cases/failing/{111 allow_fallback with fallback => 110 allow_fallback with fallback}/meson.build (100%) rename test cases/failing/{111 allow_fallback with fallback => 110 allow_fallback with fallback}/test.json (70%) rename test cases/failing/{112 nonsensical bindgen => 111 nonsensical bindgen}/meson.build (100%) rename test cases/failing/{112 nonsensical bindgen => 111 nonsensical bindgen}/src/header.h (100%) rename test cases/failing/{112 nonsensical bindgen => 111 nonsensical bindgen}/src/source.c (100%) rename test cases/failing/{112 nonsensical bindgen => 111 nonsensical bindgen}/test.json (69%) rename test cases/failing/{113 run_target in test => 112 run_target in test}/meson.build (100%) rename test cases/failing/{113 run_target in test => 112 run_target in test}/test.json (77%) rename test cases/failing/{113 run_target in test => 112 run_target in test}/trivial.c (100%) rename test cases/failing/{114 run_target in add_install_script => 113 run_target in add_install_script}/meson.build (100%) rename test cases/failing/{114 run_target in add_install_script => 113 run_target in add_install_script}/test.json (81%) rename test cases/failing/{114 run_target in add_install_script => 113 run_target in add_install_script}/trivial.c (100%) rename test cases/failing/{115 pathsep in install_symlink => 114 pathsep in install_symlink}/meson.build (100%) rename test cases/failing/{115 pathsep in install_symlink => 114 pathsep in install_symlink}/test.json (74%) rename test cases/failing/{116 subproject version conflict => 115 subproject version conflict}/meson.build (100%) rename test cases/failing/{116 subproject version conflict => 115 subproject version conflict}/subprojects/A/meson.build (100%) rename test cases/failing/{116 subproject version conflict => 115 subproject version conflict}/subprojects/B/meson.build (100%) rename test cases/failing/{116 subproject version conflict => 115 subproject version conflict}/test.json (66%) rename test cases/failing/{117 structured source empty string => 116 structured source empty string}/main.rs (100%) rename test cases/failing/{117 structured source empty string => 116 structured source empty string}/meson.build (100%) rename test cases/failing/{117 structured source empty string => 116 structured source empty string}/test.json (71%) rename test cases/failing/{118 structured_sources conflicts => 117 structured_sources conflicts}/main.rs (100%) rename test cases/failing/{118 structured_sources conflicts => 117 structured_sources conflicts}/meson.build (100%) rename test cases/failing/{118 structured_sources conflicts => 117 structured_sources conflicts}/test.json (67%) rename test cases/failing/{119 missing compiler => 118 missing compiler}/meson.build (100%) rename test cases/failing/{119 missing compiler => 118 missing compiler}/subprojects/sub/main.c (100%) rename test cases/failing/{119 missing compiler => 118 missing compiler}/subprojects/sub/meson.build (100%) rename test cases/failing/{119 missing compiler => 118 missing compiler}/test.json (68%) rename test cases/failing/{120 cmake subproject error => 119 cmake subproject error}/meson.build (100%) rename test cases/failing/{120 cmake subproject error => 119 cmake subproject error}/subprojects/cmlib/CMakeLists.txt (100%) rename test cases/failing/{120 cmake subproject error => 119 cmake subproject error}/test.json (74%) rename test cases/failing/{121 pkgconfig not relocatable outside prefix => 120 pkgconfig not relocatable outside prefix}/meson.build (100%) rename test cases/failing/{121 pkgconfig not relocatable outside prefix => 120 pkgconfig not relocatable outside prefix}/test.json (78%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/meson_options.txt (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj1/file.txt (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj1/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj1/nested/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj2/file.txt (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj2/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj2/nested/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj3/file.txt (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/subprojects/subproj3/meson.build (100%) rename test cases/failing/{122 subproject sandbox violation => 121 subproject sandbox violation}/test.json (82%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/inc/lib.h (100%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/lib.c (100%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/meson.build (100%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/subprojects/a/meson.build (100%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/subprojects/a/prog.c (100%) rename test cases/failing/{123 override and add_project_dependency => 122 override and add_project_dependency}/test.json (66%) rename test cases/failing/{124 targets before add_project_dependency => 123 targets before add_project_dependency}/inc/lib.h (100%) rename test cases/failing/{124 targets before add_project_dependency => 123 targets before add_project_dependency}/lib.c (100%) rename test cases/failing/{124 targets before add_project_dependency => 123 targets before add_project_dependency}/meson.build (100%) rename test cases/failing/{124 targets before add_project_dependency => 123 targets before add_project_dependency}/test.json (70%) rename test cases/failing/{125 extract from unity => 124 extract from unity}/meson.build (100%) rename test cases/failing/{125 extract from unity => 124 extract from unity}/src1.c (100%) rename test cases/failing/{125 extract from unity => 124 extract from unity}/src2.c (100%) rename test cases/failing/{125 extract from unity => 124 extract from unity}/test.json (73%) rename test cases/failing/{126 subproject object as a dependency => 125 subproject object as a dependency}/main.c (100%) rename test cases/failing/{126 subproject object as a dependency => 125 subproject object as a dependency}/meson.build (100%) rename test cases/failing/{126 subproject object as a dependency => 125 subproject object as a dependency}/subprojects/sub/meson.build (100%) rename test cases/failing/{126 subproject object as a dependency => 125 subproject object as a dependency}/test.json (64%) rename test cases/failing/{127 generator host binary => 126 generator host binary}/exe.c (100%) rename test cases/failing/{127 generator host binary => 126 generator host binary}/lib.in (100%) rename test cases/failing/{127 generator host binary => 126 generator host binary}/meson.build (100%) rename test cases/failing/{127 generator host binary => 126 generator host binary}/test.json (100%) rename test cases/failing/{128 invalid ast => 127 invalid ast}/meson.build (100%) rename test cases/failing/{128 invalid ast => 127 invalid ast}/test.json (67%) rename test cases/failing/{129 invalid project function => 128 invalid project function}/meson.build (100%) rename test cases/failing/{129 invalid project function => 128 invalid project function}/test.json (69%) rename test cases/failing/{130 utf8 with bom => 129 utf8 with bom}/meson.build (100%) rename test cases/failing/{130 utf8 with bom => 129 utf8 with bom}/test.json (63%) rename test cases/failing/{131 utf8 with bom subdir => 130 utf8 with bom subdir}/meson.build (100%) rename test cases/failing/{131 utf8 with bom subdir => 130 utf8 with bom subdir}/subdir/meson.build (100%) rename test cases/failing/{131 utf8 with bom subdir => 130 utf8 with bom subdir}/test.json (66%) rename test cases/failing/{132 utf8 with bom options => 131 utf8 with bom options}/meson.build (100%) rename test cases/failing/{132 utf8 with bom options => 131 utf8 with bom options}/meson.options (100%) rename test cases/failing/{132 utf8 with bom options => 131 utf8 with bom options}/test.json (65%) rename test cases/failing/{48 pkgconfig variables not key value => 47 pkgconfig variables not key value}/meson.build (100%) rename test cases/failing/{48 pkgconfig variables not key value => 47 pkgconfig variables not key value}/simple.c (100%) rename test cases/failing/{48 pkgconfig variables not key value => 47 pkgconfig variables not key value}/simple.h (100%) rename test cases/failing/{48 pkgconfig variables not key value => 47 pkgconfig variables not key value}/test.json (75%) rename test cases/failing/{49 executable comparison => 48 executable comparison}/meson.build (100%) rename test cases/failing/{49 executable comparison => 48 executable comparison}/prog.c (100%) rename test cases/failing/{49 executable comparison => 48 executable comparison}/test.json (73%) rename test cases/failing/{50 inconsistent comparison => 49 inconsistent comparison}/meson.build (100%) rename test cases/failing/{50 inconsistent comparison => 49 inconsistent comparison}/test.json (69%) rename test cases/failing/{51 slashname => 50 slashname}/meson.build (100%) rename test cases/failing/{51 slashname => 50 slashname}/sub/meson.build (100%) rename test cases/failing/{51 slashname => 50 slashname}/sub/prog.c (100%) rename test cases/failing/{51 slashname => 50 slashname}/test.json (67%) rename test cases/failing/{52 reserved meson prefix => 51 reserved meson prefix}/meson-foo/meson.build (100%) rename test cases/failing/{52 reserved meson prefix => 51 reserved meson prefix}/meson.build (100%) rename test cases/failing/{52 reserved meson prefix => 51 reserved meson prefix}/test.json (67%) rename test cases/failing/{53 or on new line => 52 or on new line}/meson.build (100%) rename test cases/failing/{53 or on new line => 52 or on new line}/meson_options.txt (100%) rename test cases/failing/{53 or on new line => 52 or on new line}/test.json (50%) rename test cases/failing/{54 link with executable => 53 link with executable}/meson.build (100%) rename test cases/failing/{54 link with executable => 53 link with executable}/module.c (100%) rename test cases/failing/{54 link with executable => 53 link with executable}/prog.c (100%) rename test cases/failing/{54 link with executable => 53 link with executable}/test.json (58%) rename test cases/failing/{55 assign custom target index => 54 assign custom target index}/meson.build (100%) rename test cases/failing/{55 assign custom target index => 54 assign custom target index}/test.json (59%) rename test cases/failing/{56 getoption prefix => 55 getoption prefix}/meson.build (100%) rename test cases/failing/{56 getoption prefix => 55 getoption prefix}/subprojects/abc/meson.build (100%) rename test cases/failing/{56 getoption prefix => 55 getoption prefix}/subprojects/abc/meson_options.txt (100%) rename test cases/failing/{56 getoption prefix => 55 getoption prefix}/test.json (72%) rename test cases/failing/{57 bad option argument => 56 bad option argument}/meson.build (100%) rename test cases/failing/{57 bad option argument => 56 bad option argument}/meson_options.txt (100%) rename test cases/failing/{57 bad option argument => 56 bad option argument}/test.json (63%) rename test cases/failing/{58 subproj filegrab => 57 subproj filegrab}/meson.build (100%) rename test cases/failing/{58 subproj filegrab => 57 subproj filegrab}/prog.c (100%) rename test cases/failing/{58 subproj filegrab => 57 subproj filegrab}/subprojects/a/meson.build (100%) rename test cases/failing/{58 subproj filegrab => 57 subproj filegrab}/test.json (68%) rename test cases/failing/{59 grab subproj => 58 grab subproj}/meson.build (100%) rename test cases/failing/{59 grab subproj => 58 grab subproj}/subprojects/foo/meson.build (100%) rename test cases/failing/{59 grab subproj => 58 grab subproj}/subprojects/foo/sub.c (100%) rename test cases/failing/{59 grab subproj => 58 grab subproj}/test.json (64%) rename test cases/failing/{60 grab sibling => 59 grab sibling}/meson.build (100%) rename test cases/failing/{60 grab sibling => 59 grab sibling}/subprojects/a/meson.build (100%) rename test cases/failing/{60 grab sibling => 59 grab sibling}/subprojects/b/meson.build (100%) rename test cases/failing/{60 grab sibling => 59 grab sibling}/subprojects/b/sneaky.c (100%) rename test cases/failing/{60 grab sibling => 59 grab sibling}/test.json (68%) rename test cases/failing/{61 string as link target => 60 string as link target}/meson.build (100%) rename test cases/failing/{61 string as link target => 60 string as link target}/prog.c (100%) rename test cases/failing/{61 string as link target => 60 string as link target}/test.json (53%) rename test cases/failing/{62 dependency not-found and required => 61 dependency not-found and required}/meson.build (100%) rename test cases/failing/{62 dependency not-found and required => 61 dependency not-found and required}/test.json (63%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/main.c (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/meson.build (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/a/a.c (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/a/a.h (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/a/meson.build (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/b/b.c (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/b/b.h (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/b/meson.build (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/c/c.h (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/subprojects/c/meson.build (100%) rename test cases/failing/{63 subproj different versions => 62 subproj different versions}/test.json (64%) rename test cases/failing/{64 wrong boost module => 63 wrong boost module}/meson.build (100%) rename test cases/failing/{64 wrong boost module => 63 wrong boost module}/test.json (60%) rename test cases/failing/{65 install_data rename bad size => 64 install_data rename bad size}/file1.txt (100%) rename test cases/failing/{65 install_data rename bad size => 64 install_data rename bad size}/file2.txt (100%) rename test cases/failing/{65 install_data rename bad size => 64 install_data rename bad size}/meson.build (100%) rename test cases/failing/{65 install_data rename bad size => 64 install_data rename bad size}/test.json (75%) rename test cases/failing/{66 skip only subdir => 65 skip only subdir}/meson.build (100%) rename test cases/failing/{66 skip only subdir => 65 skip only subdir}/subdir/meson.build (100%) rename test cases/failing/{66 skip only subdir => 65 skip only subdir}/test.json (55%) rename test cases/failing/{67 dual override => 66 dual override}/meson.build (100%) rename test cases/failing/{67 dual override => 66 dual override}/overrides.py (100%) rename test cases/failing/{67 dual override => 66 dual override}/test.json (65%) rename test cases/failing/{68 override used => 67 override used}/meson.build (100%) rename test cases/failing/{68 override used => 67 override used}/other.py (100%) rename test cases/failing/{68 override used => 67 override used}/something.py (100%) rename test cases/failing/{68 override used => 67 override used}/test.json (67%) rename test cases/failing/{69 run_command unclean exit => 68 run_command unclean exit}/meson.build (100%) rename test cases/failing/{69 run_command unclean exit => 68 run_command unclean exit}/returncode.py (100%) rename test cases/failing/{69 run_command unclean exit => 68 run_command unclean exit}/test.json (56%) rename test cases/failing/{70 int literal leading zero => 69 int literal leading zero}/meson.build (100%) rename test cases/failing/{70 int literal leading zero => 69 int literal leading zero}/test.json (69%) rename test cases/failing/{71 configuration immutable => 70 configuration immutable}/input (100%) rename test cases/failing/{71 configuration immutable => 70 configuration immutable}/meson.build (100%) rename test cases/failing/{71 configuration immutable => 70 configuration immutable}/test.json (65%) rename test cases/failing/{72 link with shared module on osx => 71 link with shared module on osx}/meson.build (100%) rename test cases/failing/{72 link with shared module on osx => 71 link with shared module on osx}/module.c (100%) rename test cases/failing/{72 link with shared module on osx => 71 link with shared module on osx}/prog.c (100%) rename test cases/failing/{72 link with shared module on osx => 71 link with shared module on osx}/test.json (68%) rename test cases/failing/{73 non-ascii in ascii encoded configure file => 72 non-ascii in ascii encoded configure file}/config9.h.in (100%) rename test cases/failing/{73 non-ascii in ascii encoded configure file => 72 non-ascii in ascii encoded configure file}/meson.build (100%) rename test cases/failing/{73 non-ascii in ascii encoded configure file => 72 non-ascii in ascii encoded configure file}/test.json (79%) rename test cases/failing/{74 subproj dependency not-found and required => 73 subproj dependency not-found and required}/meson.build (100%) rename test cases/failing/{74 subproj dependency not-found and required => 73 subproj dependency not-found and required}/test.json (68%) rename test cases/failing/{75 unfound run => 74 unfound run}/meson.build (100%) rename test cases/failing/{75 unfound run => 74 unfound run}/test.json (60%) rename test cases/failing/{76 framework dependency with version => 75 framework dependency with version}/meson.build (100%) rename test cases/failing/{76 framework dependency with version => 75 framework dependency with version}/test.json (72%) rename test cases/failing/{77 override exe config => 76 override exe config}/foo.c (100%) rename test cases/failing/{77 override exe config => 76 override exe config}/meson.build (100%) rename test cases/failing/{77 override exe config => 76 override exe config}/test.json (72%) rename test cases/failing/{78 gl dependency with version => 77 gl dependency with version}/meson.build (100%) rename test cases/failing/{78 gl dependency with version => 77 gl dependency with version}/test.json (69%) rename test cases/failing/{79 threads dependency with version => 78 threads dependency with version}/meson.build (100%) rename test cases/failing/{79 threads dependency with version => 78 threads dependency with version}/test.json (71%) rename test cases/failing/{80 gtest dependency with version => 79 gtest dependency with version}/meson.build (100%) rename test cases/failing/{80 gtest dependency with version => 79 gtest dependency with version}/test.json (62%) rename test cases/failing/{81 dub library => 80 dub library}/meson.build (100%) rename test cases/failing/{81 dub library => 80 dub library}/test.json (57%) rename test cases/failing/{82 dub executable => 81 dub executable}/meson.build (100%) rename test cases/failing/{82 dub executable => 81 dub executable}/test.json (59%) rename test cases/failing/{83 dub compiler => 82 dub compiler}/meson.build (100%) rename test cases/failing/{83 dub compiler => 82 dub compiler}/test.json (81%) rename test cases/failing/{84 subproj not-found dep => 83 subproj not-found dep}/meson.build (100%) rename test cases/failing/{84 subproj not-found dep => 83 subproj not-found dep}/subprojects/somesubproj/meson.build (100%) rename test cases/failing/{84 subproj not-found dep => 83 subproj not-found dep}/test.json (62%) rename test cases/failing/{85 invalid configure file => 84 invalid configure file}/input (100%) rename test cases/failing/{85 invalid configure file => 84 invalid configure file}/meson.build (100%) rename test cases/failing/{85 invalid configure file => 84 invalid configure file}/test.json (67%) rename test cases/failing/{86 kwarg dupe => 85 kwarg dupe}/meson.build (100%) rename test cases/failing/{86 kwarg dupe => 85 kwarg dupe}/prog.c (100%) rename test cases/failing/{86 kwarg dupe => 85 kwarg dupe}/test.json (65%) rename test cases/failing/{87 missing pch file => 86 missing pch file}/meson.build (100%) rename test cases/failing/{87 missing pch file => 86 missing pch file}/prog.c (100%) rename test cases/failing/{87 missing pch file => 86 missing pch file}/test.json (74%) rename test cases/failing/{88 pch source different folder => 87 pch source different folder}/include/pch.h (100%) rename test cases/failing/{88 pch source different folder => 87 pch source different folder}/meson.build (100%) rename test cases/failing/{88 pch source different folder => 87 pch source different folder}/prog.c (100%) rename test cases/failing/{88 pch source different folder => 87 pch source different folder}/src/pch.c (100%) rename test cases/failing/{88 pch source different folder => 87 pch source different folder}/test.json (62%) rename test cases/failing/{89 unknown config tool => 88 unknown config tool}/meson.build (100%) rename test cases/failing/{89 unknown config tool => 88 unknown config tool}/test.json (60%) rename test cases/failing/{90 custom target install data => 89 custom target install data}/Info.plist.cpp (100%) rename test cases/failing/{90 custom target install data => 89 custom target install data}/meson.build (100%) rename test cases/failing/{90 custom target install data => 89 custom target install data}/preproc.py (100%) rename test cases/failing/{90 custom target install data => 89 custom target install data}/test.json (71%) rename test cases/failing/{91 add dict non string key => 90 add dict non string key}/meson.build (100%) rename test cases/failing/{91 add dict non string key => 90 add dict non string key}/test.json (54%) rename test cases/failing/{92 add dict duplicate keys => 91 add dict duplicate keys}/meson.build (100%) rename test cases/failing/{92 add dict duplicate keys => 91 add dict duplicate keys}/test.json (58%) rename test cases/failing/{93 no host get_external_property => 92 no host get_external_property}/meson.build (100%) rename test cases/failing/{93 no host get_external_property => 92 no host get_external_property}/test.json (63%) rename test cases/failing/{94 no native compiler => 93 no native compiler}/main.c (100%) rename test cases/failing/{94 no native compiler => 93 no native compiler}/meson.build (100%) rename test cases/failing/{94 no native compiler => 93 no native compiler}/test.json (58%) rename test cases/failing/{95 subdir parse error => 94 subdir parse error}/meson.build (100%) rename test cases/failing/{95 subdir parse error => 94 subdir parse error}/subdir/meson.build (100%) rename test cases/failing/{95 subdir parse error => 94 subdir parse error}/test.json (59%) rename test cases/failing/{96 invalid option file => 95 invalid option file}/meson.build (100%) rename test cases/failing/{96 invalid option file => 95 invalid option file}/meson_options.txt (100%) rename test cases/failing/{96 invalid option file => 95 invalid option file}/test.json (50%) rename test cases/failing/{97 no lang => 96 no lang}/main.c (100%) rename test cases/failing/{97 no lang => 96 no lang}/meson.build (100%) rename test cases/failing/{97 no lang => 96 no lang}/test.json (54%) rename test cases/failing/{98 no glib-compile-resources => 97 no glib-compile-resources}/meson.build (100%) rename test cases/failing/{98 no glib-compile-resources => 97 no glib-compile-resources}/test.json (65%) rename test cases/failing/{98 no glib-compile-resources => 97 no glib-compile-resources}/trivial.gresource.xml (100%) rename test cases/failing/{99 number in combo => 98 number in combo}/meson.build (100%) rename test cases/failing/{99 number in combo => 98 number in combo}/nativefile.ini (100%) rename test cases/failing/{99 number in combo => 98 number in combo}/test.json (77%) rename test cases/failing/{100 bool in combo => 99 bool in combo}/meson.build (100%) rename test cases/failing/{100 bool in combo => 99 bool in combo}/meson_options.txt (100%) rename test cases/failing/{100 bool in combo => 99 bool in combo}/nativefile.ini (100%) create mode 100644 test cases/failing/99 bool in combo/test.json diff --git a/test cases/failing/100 bool in combo/test.json b/test cases/failing/100 bool in combo/test.json deleted file mode 100644 index 357d7a875534..000000000000 --- a/test cases/failing/100 bool in combo/test.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "stdout": [ - { "line": "test cases/failing/100 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } - ] -} diff --git a/test cases/failing/101 compiler no lang/meson.build b/test cases/failing/100 compiler no lang/meson.build similarity index 100% rename from test cases/failing/101 compiler no lang/meson.build rename to test cases/failing/100 compiler no lang/meson.build diff --git a/test cases/failing/101 compiler no lang/test.json b/test cases/failing/100 compiler no lang/test.json similarity index 66% rename from test cases/failing/101 compiler no lang/test.json rename to test cases/failing/100 compiler no lang/test.json index 364efa9e8912..935d79d1c5d8 100644 --- a/test cases/failing/101 compiler no lang/test.json +++ b/test cases/failing/100 compiler no lang/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/101 compiler no lang/meson.build:2:6: ERROR: Tried to access compiler for language \"c\", not specified for host machine." + "line": "test cases/failing/100 compiler no lang/meson.build:2:6: ERROR: Tried to access compiler for language \"c\", not specified for host machine." } ] } diff --git a/test cases/failing/102 no fallback/meson.build b/test cases/failing/101 no fallback/meson.build similarity index 100% rename from test cases/failing/102 no fallback/meson.build rename to test cases/failing/101 no fallback/meson.build diff --git a/test cases/failing/102 no fallback/subprojects/foob/meson.build b/test cases/failing/101 no fallback/subprojects/foob/meson.build similarity index 100% rename from test cases/failing/102 no fallback/subprojects/foob/meson.build rename to test cases/failing/101 no fallback/subprojects/foob/meson.build diff --git a/test cases/failing/102 no fallback/test.json b/test cases/failing/101 no fallback/test.json similarity index 100% rename from test cases/failing/102 no fallback/test.json rename to test cases/failing/101 no fallback/test.json diff --git a/test cases/failing/103 feature require/meson.build b/test cases/failing/102 feature require/meson.build similarity index 100% rename from test cases/failing/103 feature require/meson.build rename to test cases/failing/102 feature require/meson.build diff --git a/test cases/failing/103 feature require/meson_options.txt b/test cases/failing/102 feature require/meson_options.txt similarity index 100% rename from test cases/failing/103 feature require/meson_options.txt rename to test cases/failing/102 feature require/meson_options.txt diff --git a/test cases/failing/103 feature require/test.json b/test cases/failing/102 feature require/test.json similarity index 100% rename from test cases/failing/103 feature require/test.json rename to test cases/failing/102 feature require/test.json diff --git a/test cases/failing/104 feature require.bis/meson.build b/test cases/failing/103 feature require.bis/meson.build similarity index 100% rename from test cases/failing/104 feature require.bis/meson.build rename to test cases/failing/103 feature require.bis/meson.build diff --git a/test cases/failing/104 feature require.bis/meson_options.txt b/test cases/failing/103 feature require.bis/meson_options.txt similarity index 100% rename from test cases/failing/104 feature require.bis/meson_options.txt rename to test cases/failing/103 feature require.bis/meson_options.txt diff --git a/test cases/failing/104 feature require.bis/test.json b/test cases/failing/103 feature require.bis/test.json similarity index 100% rename from test cases/failing/104 feature require.bis/test.json rename to test cases/failing/103 feature require.bis/test.json diff --git a/test cases/failing/105 no build get_external_property/meson.build b/test cases/failing/104 no build get_external_property/meson.build similarity index 100% rename from test cases/failing/105 no build get_external_property/meson.build rename to test cases/failing/104 no build get_external_property/meson.build diff --git a/test cases/failing/105 no build get_external_property/test.json b/test cases/failing/104 no build get_external_property/test.json similarity index 63% rename from test cases/failing/105 no build get_external_property/test.json rename to test cases/failing/104 no build get_external_property/test.json index e8b282c6fd9f..5792213b0388 100644 --- a/test cases/failing/105 no build get_external_property/test.json +++ b/test cases/failing/104 no build get_external_property/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/105 no build get_external_property/meson.build:3:14: ERROR: Unknown property for build machine: nonexisting" + "line": "test cases/failing/104 no build get_external_property/meson.build:3:14: ERROR: Unknown property for build machine: nonexisting" } ] } diff --git a/test cases/failing/106 enter subdir twice/meson.build b/test cases/failing/105 enter subdir twice/meson.build similarity index 100% rename from test cases/failing/106 enter subdir twice/meson.build rename to test cases/failing/105 enter subdir twice/meson.build diff --git a/test cases/failing/106 enter subdir twice/sub/meson.build b/test cases/failing/105 enter subdir twice/sub/meson.build similarity index 100% rename from test cases/failing/106 enter subdir twice/sub/meson.build rename to test cases/failing/105 enter subdir twice/sub/meson.build diff --git a/test cases/failing/106 enter subdir twice/test.json b/test cases/failing/105 enter subdir twice/test.json similarity index 64% rename from test cases/failing/106 enter subdir twice/test.json rename to test cases/failing/105 enter subdir twice/test.json index 9a8b11d060ed..80e8c101a358 100644 --- a/test cases/failing/106 enter subdir twice/test.json +++ b/test cases/failing/105 enter subdir twice/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/106 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited." + "line": "test cases/failing/105 enter subdir twice/meson.build:3:0: ERROR: Tried to enter directory \"sub\", which has already been visited." } ] } diff --git a/test cases/failing/107 invalid fstring/109 invalid fstring/meson.build b/test cases/failing/106 invalid fstring/109 invalid fstring/meson.build similarity index 100% rename from test cases/failing/107 invalid fstring/109 invalid fstring/meson.build rename to test cases/failing/106 invalid fstring/109 invalid fstring/meson.build diff --git a/test cases/failing/107 invalid fstring/109 invalid fstring/test.json b/test cases/failing/106 invalid fstring/109 invalid fstring/test.json similarity index 100% rename from test cases/failing/107 invalid fstring/109 invalid fstring/test.json rename to test cases/failing/106 invalid fstring/109 invalid fstring/test.json diff --git a/test cases/failing/107 invalid fstring/meson.build b/test cases/failing/106 invalid fstring/meson.build similarity index 100% rename from test cases/failing/107 invalid fstring/meson.build rename to test cases/failing/106 invalid fstring/meson.build diff --git a/test cases/failing/107 invalid fstring/test.json b/test cases/failing/106 invalid fstring/test.json similarity index 63% rename from test cases/failing/107 invalid fstring/test.json rename to test cases/failing/106 invalid fstring/test.json index ccd82b574c32..8d5342885ffa 100644 --- a/test cases/failing/107 invalid fstring/test.json +++ b/test cases/failing/106 invalid fstring/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/107 invalid fstring/meson.build:3:4: ERROR: Identifier \"foo\" does not name a variable." + "line": "test cases/failing/106 invalid fstring/meson.build:3:4: ERROR: Identifier \"foo\" does not name a variable." } ] } diff --git a/test cases/failing/108 compiler argument checking/meson.build b/test cases/failing/107 compiler argument checking/meson.build similarity index 100% rename from test cases/failing/108 compiler argument checking/meson.build rename to test cases/failing/107 compiler argument checking/meson.build diff --git a/test cases/failing/108 compiler argument checking/test.json b/test cases/failing/107 compiler argument checking/test.json similarity index 66% rename from test cases/failing/108 compiler argument checking/test.json rename to test cases/failing/107 compiler argument checking/test.json index e9e27af574fe..a1576aa69e58 100644 --- a/test cases/failing/108 compiler argument checking/test.json +++ b/test cases/failing/107 compiler argument checking/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/108 compiler argument checking/meson.build:4:25: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" + "line": "test cases/failing/107 compiler argument checking/meson.build:4:25: ERROR: Compiler for C does not support \"-meson-goober-arg-for-testing\"" } ] } diff --git a/test cases/failing/109 empty fallback/meson.build b/test cases/failing/108 empty fallback/meson.build similarity index 100% rename from test cases/failing/109 empty fallback/meson.build rename to test cases/failing/108 empty fallback/meson.build diff --git a/test cases/failing/109 empty fallback/subprojects/foo/meson.build b/test cases/failing/108 empty fallback/subprojects/foo/meson.build similarity index 100% rename from test cases/failing/109 empty fallback/subprojects/foo/meson.build rename to test cases/failing/108 empty fallback/subprojects/foo/meson.build diff --git a/test cases/failing/109 empty fallback/test.json b/test cases/failing/108 empty fallback/test.json similarity index 65% rename from test cases/failing/109 empty fallback/test.json rename to test cases/failing/108 empty fallback/test.json index 46a4ec51495d..c6318823170d 100644 --- a/test cases/failing/109 empty fallback/test.json +++ b/test cases/failing/108 empty fallback/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/109 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found.*" + "line": "test cases/failing/108 empty fallback/meson.build:6:0: ERROR: Dependency \"foo\" not found.*" } ] } diff --git a/test cases/failing/110 cmake executable dependency/meson.build b/test cases/failing/109 cmake executable dependency/meson.build similarity index 100% rename from test cases/failing/110 cmake executable dependency/meson.build rename to test cases/failing/109 cmake executable dependency/meson.build diff --git a/test cases/failing/110 cmake executable dependency/subprojects/cmlib/CMakeLists.txt b/test cases/failing/109 cmake executable dependency/subprojects/cmlib/CMakeLists.txt similarity index 100% rename from test cases/failing/110 cmake executable dependency/subprojects/cmlib/CMakeLists.txt rename to test cases/failing/109 cmake executable dependency/subprojects/cmlib/CMakeLists.txt diff --git a/test cases/failing/110 cmake executable dependency/subprojects/cmlib/main.c b/test cases/failing/109 cmake executable dependency/subprojects/cmlib/main.c similarity index 100% rename from test cases/failing/110 cmake executable dependency/subprojects/cmlib/main.c rename to test cases/failing/109 cmake executable dependency/subprojects/cmlib/main.c diff --git a/test cases/failing/110 cmake executable dependency/test.json b/test cases/failing/109 cmake executable dependency/test.json similarity index 77% rename from test cases/failing/110 cmake executable dependency/test.json rename to test cases/failing/109 cmake executable dependency/test.json index 80d01fe0d3ec..f7c477555694 100644 --- a/test cases/failing/110 cmake executable dependency/test.json +++ b/test cases/failing/109 cmake executable dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/110 cmake executable dependency/meson.build:9:14: ERROR: main is an executable and does not support the dependency() method. Use target() instead." + "line": "test cases/failing/109 cmake executable dependency/meson.build:9:14: ERROR: main is an executable and does not support the dependency() method. Use target() instead." } ], "tools": { diff --git a/test cases/failing/111 allow_fallback with fallback/meson.build b/test cases/failing/110 allow_fallback with fallback/meson.build similarity index 100% rename from test cases/failing/111 allow_fallback with fallback/meson.build rename to test cases/failing/110 allow_fallback with fallback/meson.build diff --git a/test cases/failing/111 allow_fallback with fallback/test.json b/test cases/failing/110 allow_fallback with fallback/test.json similarity index 70% rename from test cases/failing/111 allow_fallback with fallback/test.json rename to test cases/failing/110 allow_fallback with fallback/test.json index 92aa19af306c..b558eccaefbc 100644 --- a/test cases/failing/111 allow_fallback with fallback/test.json +++ b/test cases/failing/110 allow_fallback with fallback/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/111 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive" + "line": "test cases/failing/110 allow_fallback with fallback/meson.build:3:0: ERROR: \"fallback\" and \"allow_fallback\" arguments are mutually exclusive" } ] } diff --git a/test cases/failing/112 nonsensical bindgen/meson.build b/test cases/failing/111 nonsensical bindgen/meson.build similarity index 100% rename from test cases/failing/112 nonsensical bindgen/meson.build rename to test cases/failing/111 nonsensical bindgen/meson.build diff --git a/test cases/failing/112 nonsensical bindgen/src/header.h b/test cases/failing/111 nonsensical bindgen/src/header.h similarity index 100% rename from test cases/failing/112 nonsensical bindgen/src/header.h rename to test cases/failing/111 nonsensical bindgen/src/header.h diff --git a/test cases/failing/112 nonsensical bindgen/src/source.c b/test cases/failing/111 nonsensical bindgen/src/source.c similarity index 100% rename from test cases/failing/112 nonsensical bindgen/src/source.c rename to test cases/failing/111 nonsensical bindgen/src/source.c diff --git a/test cases/failing/112 nonsensical bindgen/test.json b/test cases/failing/111 nonsensical bindgen/test.json similarity index 69% rename from test cases/failing/112 nonsensical bindgen/test.json rename to test cases/failing/111 nonsensical bindgen/test.json index a2b4b719602d..f2dc92c89498 100644 --- a/test cases/failing/112 nonsensical bindgen/test.json +++ b/test cases/failing/111 nonsensical bindgen/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/112 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target" + "line": "test cases/failing/111 nonsensical bindgen/meson.build:17:24: ERROR: bindgen source file must be a C header, not an object or build target" } ] } diff --git a/test cases/failing/113 run_target in test/meson.build b/test cases/failing/112 run_target in test/meson.build similarity index 100% rename from test cases/failing/113 run_target in test/meson.build rename to test cases/failing/112 run_target in test/meson.build diff --git a/test cases/failing/113 run_target in test/test.json b/test cases/failing/112 run_target in test/test.json similarity index 77% rename from test cases/failing/113 run_target in test/test.json rename to test cases/failing/112 run_target in test/test.json index 0e1ded4ea354..100db94821d3 100644 --- a/test cases/failing/113 run_target in test/test.json +++ b/test cases/failing/112 run_target in test/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/113 run_target in test/meson.build:7:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]" + "line": "test cases/failing/112 run_target in test/meson.build:7:0: ERROR: test keyword argument 'args' was of type array[RunTarget] but should have been array[str | File | BuildTarget | CustomTarget | CustomTargetIndex]" } ] } diff --git a/test cases/failing/113 run_target in test/trivial.c b/test cases/failing/112 run_target in test/trivial.c similarity index 100% rename from test cases/failing/113 run_target in test/trivial.c rename to test cases/failing/112 run_target in test/trivial.c diff --git a/test cases/failing/114 run_target in add_install_script/meson.build b/test cases/failing/113 run_target in add_install_script/meson.build similarity index 100% rename from test cases/failing/114 run_target in add_install_script/meson.build rename to test cases/failing/113 run_target in add_install_script/meson.build diff --git a/test cases/failing/114 run_target in add_install_script/test.json b/test cases/failing/113 run_target in add_install_script/test.json similarity index 81% rename from test cases/failing/114 run_target in add_install_script/test.json rename to test cases/failing/113 run_target in add_install_script/test.json index 0b28f9b15ff1..c9ed33ecfd30 100644 --- a/test cases/failing/114 run_target in add_install_script/test.json +++ b/test cases/failing/113 run_target in add_install_script/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/114 run_target in add_install_script/meson.build:7:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\"" + "line": "test cases/failing/113 run_target in add_install_script/meson.build:7:6: ERROR: meson.add_install_script argument 2 was of type \"RunTarget\" but should have been one of: \"str\", \"File\", \"BuildTarget\", \"CustomTarget\", \"CustomTargetIndex\", \"ExternalProgram\"" } ] } diff --git a/test cases/failing/114 run_target in add_install_script/trivial.c b/test cases/failing/113 run_target in add_install_script/trivial.c similarity index 100% rename from test cases/failing/114 run_target in add_install_script/trivial.c rename to test cases/failing/113 run_target in add_install_script/trivial.c diff --git a/test cases/failing/115 pathsep in install_symlink/meson.build b/test cases/failing/114 pathsep in install_symlink/meson.build similarity index 100% rename from test cases/failing/115 pathsep in install_symlink/meson.build rename to test cases/failing/114 pathsep in install_symlink/meson.build diff --git a/test cases/failing/115 pathsep in install_symlink/test.json b/test cases/failing/114 pathsep in install_symlink/test.json similarity index 74% rename from test cases/failing/115 pathsep in install_symlink/test.json rename to test cases/failing/114 pathsep in install_symlink/test.json index fee661f4ed63..bca4e0e1de93 100644 --- a/test cases/failing/115 pathsep in install_symlink/test.json +++ b/test cases/failing/114 pathsep in install_symlink/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/115 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir." + "line": "test cases/failing/114 pathsep in install_symlink/meson.build:3:0: ERROR: Link name is \"foo/bar\", but link names cannot contain path separators. The dir part should be in install_dir." } ] } diff --git a/test cases/failing/116 subproject version conflict/meson.build b/test cases/failing/115 subproject version conflict/meson.build similarity index 100% rename from test cases/failing/116 subproject version conflict/meson.build rename to test cases/failing/115 subproject version conflict/meson.build diff --git a/test cases/failing/116 subproject version conflict/subprojects/A/meson.build b/test cases/failing/115 subproject version conflict/subprojects/A/meson.build similarity index 100% rename from test cases/failing/116 subproject version conflict/subprojects/A/meson.build rename to test cases/failing/115 subproject version conflict/subprojects/A/meson.build diff --git a/test cases/failing/116 subproject version conflict/subprojects/B/meson.build b/test cases/failing/115 subproject version conflict/subprojects/B/meson.build similarity index 100% rename from test cases/failing/116 subproject version conflict/subprojects/B/meson.build rename to test cases/failing/115 subproject version conflict/subprojects/B/meson.build diff --git a/test cases/failing/116 subproject version conflict/test.json b/test cases/failing/115 subproject version conflict/test.json similarity index 66% rename from test cases/failing/116 subproject version conflict/test.json rename to test cases/failing/115 subproject version conflict/test.json index c827744968f8..23c7eb5e949c 100644 --- a/test cases/failing/116 subproject version conflict/test.json +++ b/test cases/failing/115 subproject version conflict/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/116 subproject version conflict/meson.build:4:8: ERROR: Subproject B version is 100 but ['1'] required." + "line": "test cases/failing/115 subproject version conflict/meson.build:4:8: ERROR: Subproject B version is 100 but ['1'] required." } ] } diff --git a/test cases/failing/117 structured source empty string/main.rs b/test cases/failing/116 structured source empty string/main.rs similarity index 100% rename from test cases/failing/117 structured source empty string/main.rs rename to test cases/failing/116 structured source empty string/main.rs diff --git a/test cases/failing/117 structured source empty string/meson.build b/test cases/failing/116 structured source empty string/meson.build similarity index 100% rename from test cases/failing/117 structured source empty string/meson.build rename to test cases/failing/116 structured source empty string/meson.build diff --git a/test cases/failing/117 structured source empty string/test.json b/test cases/failing/116 structured source empty string/test.json similarity index 71% rename from test cases/failing/117 structured source empty string/test.json rename to test cases/failing/116 structured source empty string/test.json index 7c90b0325355..00efbe39a7e8 100644 --- a/test cases/failing/117 structured source empty string/test.json +++ b/test cases/failing/116 structured source empty string/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/117 structured source empty string/meson.build:9:2: ERROR: structured_sources: keys to dictionary argument may not be an empty string." + "line": "test cases/failing/116 structured source empty string/meson.build:9:2: ERROR: structured_sources: keys to dictionary argument may not be an empty string." } ] } diff --git a/test cases/failing/118 structured_sources conflicts/main.rs b/test cases/failing/117 structured_sources conflicts/main.rs similarity index 100% rename from test cases/failing/118 structured_sources conflicts/main.rs rename to test cases/failing/117 structured_sources conflicts/main.rs diff --git a/test cases/failing/118 structured_sources conflicts/meson.build b/test cases/failing/117 structured_sources conflicts/meson.build similarity index 100% rename from test cases/failing/118 structured_sources conflicts/meson.build rename to test cases/failing/117 structured_sources conflicts/meson.build diff --git a/test cases/failing/118 structured_sources conflicts/test.json b/test cases/failing/117 structured_sources conflicts/test.json similarity index 67% rename from test cases/failing/118 structured_sources conflicts/test.json rename to test cases/failing/117 structured_sources conflicts/test.json index 55b1228906e1..a7201b5f3af7 100644 --- a/test cases/failing/118 structured_sources conflicts/test.json +++ b/test cases/failing/117 structured_sources conflicts/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/118 structured_sources conflicts/meson.build:7:0: ERROR: Conflicting sources in structured sources: main.rs" + "line": "test cases/failing/117 structured_sources conflicts/meson.build:7:0: ERROR: Conflicting sources in structured sources: main.rs" } ] } diff --git a/test cases/failing/119 missing compiler/meson.build b/test cases/failing/118 missing compiler/meson.build similarity index 100% rename from test cases/failing/119 missing compiler/meson.build rename to test cases/failing/118 missing compiler/meson.build diff --git a/test cases/failing/119 missing compiler/subprojects/sub/main.c b/test cases/failing/118 missing compiler/subprojects/sub/main.c similarity index 100% rename from test cases/failing/119 missing compiler/subprojects/sub/main.c rename to test cases/failing/118 missing compiler/subprojects/sub/main.c diff --git a/test cases/failing/119 missing compiler/subprojects/sub/meson.build b/test cases/failing/118 missing compiler/subprojects/sub/meson.build similarity index 100% rename from test cases/failing/119 missing compiler/subprojects/sub/meson.build rename to test cases/failing/118 missing compiler/subprojects/sub/meson.build diff --git a/test cases/failing/119 missing compiler/test.json b/test cases/failing/118 missing compiler/test.json similarity index 68% rename from test cases/failing/119 missing compiler/test.json rename to test cases/failing/118 missing compiler/test.json index c5f3fb1caaee..a2494e4bc815 100644 --- a/test cases/failing/119 missing compiler/test.json +++ b/test cases/failing/118 missing compiler/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/119 missing compiler/subprojects/sub/meson.build:4:0: ERROR: No host machine compiler for 'subprojects/sub/main.c'" + "line": "test cases/failing/118 missing compiler/subprojects/sub/meson.build:4:0: ERROR: No host machine compiler for 'subprojects/sub/main.c'" } ] } diff --git a/test cases/failing/120 cmake subproject error/meson.build b/test cases/failing/119 cmake subproject error/meson.build similarity index 100% rename from test cases/failing/120 cmake subproject error/meson.build rename to test cases/failing/119 cmake subproject error/meson.build diff --git a/test cases/failing/120 cmake subproject error/subprojects/cmlib/CMakeLists.txt b/test cases/failing/119 cmake subproject error/subprojects/cmlib/CMakeLists.txt similarity index 100% rename from test cases/failing/120 cmake subproject error/subprojects/cmlib/CMakeLists.txt rename to test cases/failing/119 cmake subproject error/subprojects/cmlib/CMakeLists.txt diff --git a/test cases/failing/120 cmake subproject error/test.json b/test cases/failing/119 cmake subproject error/test.json similarity index 74% rename from test cases/failing/120 cmake subproject error/test.json rename to test cases/failing/119 cmake subproject error/test.json index d88e708bfd35..625e45175fc1 100644 --- a/test cases/failing/120 cmake subproject error/test.json +++ b/test cases/failing/119 cmake subproject error/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/120 cmake subproject error/meson.build:8:14: ERROR: Failed to configure the CMake subproject: Fancy error message" + "line": "test cases/failing/119 cmake subproject error/meson.build:8:14: ERROR: Failed to configure the CMake subproject: Fancy error message" } ], "tools": { diff --git a/test cases/failing/121 pkgconfig not relocatable outside prefix/meson.build b/test cases/failing/120 pkgconfig not relocatable outside prefix/meson.build similarity index 100% rename from test cases/failing/121 pkgconfig not relocatable outside prefix/meson.build rename to test cases/failing/120 pkgconfig not relocatable outside prefix/meson.build diff --git a/test cases/failing/121 pkgconfig not relocatable outside prefix/test.json b/test cases/failing/120 pkgconfig not relocatable outside prefix/test.json similarity index 78% rename from test cases/failing/121 pkgconfig not relocatable outside prefix/test.json rename to test cases/failing/120 pkgconfig not relocatable outside prefix/test.json index c0dfb87e2354..32c6e0931f09 100644 --- a/test cases/failing/121 pkgconfig not relocatable outside prefix/test.json +++ b/test cases/failing/120 pkgconfig not relocatable outside prefix/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/121 pkgconfig not relocatable outside prefix/meson\\.build:17:5: ERROR: Pkgconfig prefix cannot be outside of the prefix when pkgconfig\\.relocatable=true. Pkgconfig prefix is (C:)?/opt/lib/pkgconfig.", + "line": "test cases/failing/120 pkgconfig not relocatable outside prefix/meson\\.build:17:5: ERROR: Pkgconfig prefix cannot be outside of the prefix when pkgconfig\\.relocatable=true. Pkgconfig prefix is (C:)?/opt/lib/pkgconfig.", "match": "re" } ] diff --git a/test cases/failing/122 subproject sandbox violation/meson.build b/test cases/failing/121 subproject sandbox violation/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/meson.build rename to test cases/failing/121 subproject sandbox violation/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/meson_options.txt b/test cases/failing/121 subproject sandbox violation/meson_options.txt similarity index 100% rename from test cases/failing/122 subproject sandbox violation/meson_options.txt rename to test cases/failing/121 subproject sandbox violation/meson_options.txt diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/file.txt b/test cases/failing/121 subproject sandbox violation/subprojects/subproj1/file.txt similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj1/file.txt rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj1/file.txt diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/meson.build b/test cases/failing/121 subproject sandbox violation/subprojects/subproj1/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj1/meson.build rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj1/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj1/nested/meson.build b/test cases/failing/121 subproject sandbox violation/subprojects/subproj1/nested/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj1/nested/meson.build rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj1/nested/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/file.txt b/test cases/failing/121 subproject sandbox violation/subprojects/subproj2/file.txt similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj2/file.txt rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj2/file.txt diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/meson.build b/test cases/failing/121 subproject sandbox violation/subprojects/subproj2/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj2/meson.build rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj2/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj2/nested/meson.build b/test cases/failing/121 subproject sandbox violation/subprojects/subproj2/nested/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj2/nested/meson.build rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj2/nested/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj3/file.txt b/test cases/failing/121 subproject sandbox violation/subprojects/subproj3/file.txt similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj3/file.txt rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj3/file.txt diff --git a/test cases/failing/122 subproject sandbox violation/subprojects/subproj3/meson.build b/test cases/failing/121 subproject sandbox violation/subprojects/subproj3/meson.build similarity index 100% rename from test cases/failing/122 subproject sandbox violation/subprojects/subproj3/meson.build rename to test cases/failing/121 subproject sandbox violation/subprojects/subproj3/meson.build diff --git a/test cases/failing/122 subproject sandbox violation/test.json b/test cases/failing/121 subproject sandbox violation/test.json similarity index 82% rename from test cases/failing/122 subproject sandbox violation/test.json rename to test cases/failing/121 subproject sandbox violation/test.json index 4bd40288403a..d8c28d702cba 100644 --- a/test cases/failing/122 subproject sandbox violation/test.json +++ b/test cases/failing/121 subproject sandbox violation/test.json @@ -10,7 +10,7 @@ }, "stdout": [ { - "line": "test cases/failing/122 subproject sandbox violation/meson.build:24:0: ERROR: Sandbox violation: Tried to grab file file.txt from a nested subproject." + "line": "test cases/failing/121 subproject sandbox violation/meson.build:24:0: ERROR: Sandbox violation: Tried to grab file file.txt from a nested subproject." } ] } diff --git a/test cases/failing/123 override and add_project_dependency/inc/lib.h b/test cases/failing/122 override and add_project_dependency/inc/lib.h similarity index 100% rename from test cases/failing/123 override and add_project_dependency/inc/lib.h rename to test cases/failing/122 override and add_project_dependency/inc/lib.h diff --git a/test cases/failing/123 override and add_project_dependency/lib.c b/test cases/failing/122 override and add_project_dependency/lib.c similarity index 100% rename from test cases/failing/123 override and add_project_dependency/lib.c rename to test cases/failing/122 override and add_project_dependency/lib.c diff --git a/test cases/failing/123 override and add_project_dependency/meson.build b/test cases/failing/122 override and add_project_dependency/meson.build similarity index 100% rename from test cases/failing/123 override and add_project_dependency/meson.build rename to test cases/failing/122 override and add_project_dependency/meson.build diff --git a/test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build b/test cases/failing/122 override and add_project_dependency/subprojects/a/meson.build similarity index 100% rename from test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build rename to test cases/failing/122 override and add_project_dependency/subprojects/a/meson.build diff --git a/test cases/failing/123 override and add_project_dependency/subprojects/a/prog.c b/test cases/failing/122 override and add_project_dependency/subprojects/a/prog.c similarity index 100% rename from test cases/failing/123 override and add_project_dependency/subprojects/a/prog.c rename to test cases/failing/122 override and add_project_dependency/subprojects/a/prog.c diff --git a/test cases/failing/123 override and add_project_dependency/test.json b/test cases/failing/122 override and add_project_dependency/test.json similarity index 66% rename from test cases/failing/123 override and add_project_dependency/test.json rename to test cases/failing/122 override and add_project_dependency/test.json index e0a4433cb172..08eb0c6b472f 100644 --- a/test cases/failing/123 override and add_project_dependency/test.json +++ b/test cases/failing/122 override and add_project_dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/123 override and add_project_dependency/subprojects/a/meson.build:6:0: ERROR: Dependencies must be external dependencies" + "line": "test cases/failing/122 override and add_project_dependency/subprojects/a/meson.build:6:0: ERROR: Dependencies must be external dependencies" } ] } diff --git a/test cases/failing/124 targets before add_project_dependency/inc/lib.h b/test cases/failing/123 targets before add_project_dependency/inc/lib.h similarity index 100% rename from test cases/failing/124 targets before add_project_dependency/inc/lib.h rename to test cases/failing/123 targets before add_project_dependency/inc/lib.h diff --git a/test cases/failing/124 targets before add_project_dependency/lib.c b/test cases/failing/123 targets before add_project_dependency/lib.c similarity index 100% rename from test cases/failing/124 targets before add_project_dependency/lib.c rename to test cases/failing/123 targets before add_project_dependency/lib.c diff --git a/test cases/failing/124 targets before add_project_dependency/meson.build b/test cases/failing/123 targets before add_project_dependency/meson.build similarity index 100% rename from test cases/failing/124 targets before add_project_dependency/meson.build rename to test cases/failing/123 targets before add_project_dependency/meson.build diff --git a/test cases/failing/124 targets before add_project_dependency/test.json b/test cases/failing/123 targets before add_project_dependency/test.json similarity index 70% rename from test cases/failing/124 targets before add_project_dependency/test.json rename to test cases/failing/123 targets before add_project_dependency/test.json index d856ba4fdab2..4a21eec5507b 100644 --- a/test cases/failing/124 targets before add_project_dependency/test.json +++ b/test cases/failing/123 targets before add_project_dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/124 targets before add_project_dependency/meson.build:5:0: ERROR: Tried to use 'add_project_dependencies' after a build target has been declared." + "line": "test cases/failing/123 targets before add_project_dependency/meson.build:5:0: ERROR: Tried to use 'add_project_dependencies' after a build target has been declared." } ] } diff --git a/test cases/failing/125 extract from unity/meson.build b/test cases/failing/124 extract from unity/meson.build similarity index 100% rename from test cases/failing/125 extract from unity/meson.build rename to test cases/failing/124 extract from unity/meson.build diff --git a/test cases/failing/125 extract from unity/src1.c b/test cases/failing/124 extract from unity/src1.c similarity index 100% rename from test cases/failing/125 extract from unity/src1.c rename to test cases/failing/124 extract from unity/src1.c diff --git a/test cases/failing/125 extract from unity/src2.c b/test cases/failing/124 extract from unity/src2.c similarity index 100% rename from test cases/failing/125 extract from unity/src2.c rename to test cases/failing/124 extract from unity/src2.c diff --git a/test cases/failing/125 extract from unity/test.json b/test cases/failing/124 extract from unity/test.json similarity index 73% rename from test cases/failing/125 extract from unity/test.json rename to test cases/failing/124 extract from unity/test.json index 2f6468d36493..ef76d2f4fe07 100644 --- a/test cases/failing/125 extract from unity/test.json +++ b/test cases/failing/124 extract from unity/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/125 extract from unity/meson.build:4:37: ERROR: Single object files cannot be extracted in Unity builds. You can only extract all the object files for each compiler at once." + "line": "test cases/failing/124 extract from unity/meson.build:4:37: ERROR: Single object files cannot be extracted in Unity builds. You can only extract all the object files for each compiler at once." } ] } diff --git a/test cases/failing/126 subproject object as a dependency/main.c b/test cases/failing/125 subproject object as a dependency/main.c similarity index 100% rename from test cases/failing/126 subproject object as a dependency/main.c rename to test cases/failing/125 subproject object as a dependency/main.c diff --git a/test cases/failing/126 subproject object as a dependency/meson.build b/test cases/failing/125 subproject object as a dependency/meson.build similarity index 100% rename from test cases/failing/126 subproject object as a dependency/meson.build rename to test cases/failing/125 subproject object as a dependency/meson.build diff --git a/test cases/failing/126 subproject object as a dependency/subprojects/sub/meson.build b/test cases/failing/125 subproject object as a dependency/subprojects/sub/meson.build similarity index 100% rename from test cases/failing/126 subproject object as a dependency/subprojects/sub/meson.build rename to test cases/failing/125 subproject object as a dependency/subprojects/sub/meson.build diff --git a/test cases/failing/126 subproject object as a dependency/test.json b/test cases/failing/125 subproject object as a dependency/test.json similarity index 64% rename from test cases/failing/126 subproject object as a dependency/test.json rename to test cases/failing/125 subproject object as a dependency/test.json index 4bf7f5b8bffe..0cb257151705 100644 --- a/test cases/failing/126 subproject object as a dependency/test.json +++ b/test cases/failing/125 subproject object as a dependency/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/126 subproject object as a dependency/meson.build:3:0: ERROR: Tried to use subproject object as a dependency." + "line": "test cases/failing/125 subproject object as a dependency/meson.build:3:0: ERROR: Tried to use subproject object as a dependency." } ] } diff --git a/test cases/failing/127 generator host binary/exe.c b/test cases/failing/126 generator host binary/exe.c similarity index 100% rename from test cases/failing/127 generator host binary/exe.c rename to test cases/failing/126 generator host binary/exe.c diff --git a/test cases/failing/127 generator host binary/lib.in b/test cases/failing/126 generator host binary/lib.in similarity index 100% rename from test cases/failing/127 generator host binary/lib.in rename to test cases/failing/126 generator host binary/lib.in diff --git a/test cases/failing/127 generator host binary/meson.build b/test cases/failing/126 generator host binary/meson.build similarity index 100% rename from test cases/failing/127 generator host binary/meson.build rename to test cases/failing/126 generator host binary/meson.build diff --git a/test cases/failing/127 generator host binary/test.json b/test cases/failing/126 generator host binary/test.json similarity index 100% rename from test cases/failing/127 generator host binary/test.json rename to test cases/failing/126 generator host binary/test.json diff --git a/test cases/failing/128 invalid ast/meson.build b/test cases/failing/127 invalid ast/meson.build similarity index 100% rename from test cases/failing/128 invalid ast/meson.build rename to test cases/failing/127 invalid ast/meson.build diff --git a/test cases/failing/128 invalid ast/test.json b/test cases/failing/127 invalid ast/test.json similarity index 67% rename from test cases/failing/128 invalid ast/test.json rename to test cases/failing/127 invalid ast/test.json index e5c3873dc5c1..db7bfe821d14 100644 --- a/test cases/failing/128 invalid ast/test.json +++ b/test cases/failing/127 invalid ast/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/128 invalid ast/meson.build:1:44: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + "line": "test cases/failing/127 invalid ast/meson.build:1:44: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" } ] } diff --git a/test cases/failing/129 invalid project function/meson.build b/test cases/failing/128 invalid project function/meson.build similarity index 100% rename from test cases/failing/129 invalid project function/meson.build rename to test cases/failing/128 invalid project function/meson.build diff --git a/test cases/failing/129 invalid project function/test.json b/test cases/failing/128 invalid project function/test.json similarity index 69% rename from test cases/failing/129 invalid project function/test.json rename to test cases/failing/128 invalid project function/test.json index b28266cb166e..17c1ac6522ab 100644 --- a/test cases/failing/129 invalid project function/test.json +++ b/test cases/failing/128 invalid project function/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/129 invalid project function/meson.build:1:67: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" + "line": "test cases/failing/128 invalid project function/meson.build:1:67: ERROR: Meson version is [0-9.]+(\\.rc[0-9]+)? but project requires 0.1.0" } ] } diff --git a/test cases/failing/130 utf8 with bom/meson.build b/test cases/failing/129 utf8 with bom/meson.build similarity index 100% rename from test cases/failing/130 utf8 with bom/meson.build rename to test cases/failing/129 utf8 with bom/meson.build diff --git a/test cases/failing/130 utf8 with bom/test.json b/test cases/failing/129 utf8 with bom/test.json similarity index 63% rename from test cases/failing/130 utf8 with bom/test.json rename to test cases/failing/129 utf8 with bom/test.json index 2292bebe3950..ec2df13bb97f 100644 --- a/test cases/failing/130 utf8 with bom/test.json +++ b/test cases/failing/129 utf8 with bom/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/130 utf8 with bom/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + "line": "test cases/failing/129 utf8 with bom/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" } ] } diff --git a/test cases/failing/131 utf8 with bom subdir/meson.build b/test cases/failing/130 utf8 with bom subdir/meson.build similarity index 100% rename from test cases/failing/131 utf8 with bom subdir/meson.build rename to test cases/failing/130 utf8 with bom subdir/meson.build diff --git a/test cases/failing/131 utf8 with bom subdir/subdir/meson.build b/test cases/failing/130 utf8 with bom subdir/subdir/meson.build similarity index 100% rename from test cases/failing/131 utf8 with bom subdir/subdir/meson.build rename to test cases/failing/130 utf8 with bom subdir/subdir/meson.build diff --git a/test cases/failing/131 utf8 with bom subdir/test.json b/test cases/failing/130 utf8 with bom subdir/test.json similarity index 66% rename from test cases/failing/131 utf8 with bom subdir/test.json rename to test cases/failing/130 utf8 with bom subdir/test.json index 72cc5152dfc1..bbaea1b30448 100644 --- a/test cases/failing/131 utf8 with bom subdir/test.json +++ b/test cases/failing/130 utf8 with bom subdir/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/131 utf8 with bom subdir/subdir/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + "line": "test cases/failing/130 utf8 with bom subdir/subdir/meson.build:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" } ] } diff --git a/test cases/failing/132 utf8 with bom options/meson.build b/test cases/failing/131 utf8 with bom options/meson.build similarity index 100% rename from test cases/failing/132 utf8 with bom options/meson.build rename to test cases/failing/131 utf8 with bom options/meson.build diff --git a/test cases/failing/132 utf8 with bom options/meson.options b/test cases/failing/131 utf8 with bom options/meson.options similarity index 100% rename from test cases/failing/132 utf8 with bom options/meson.options rename to test cases/failing/131 utf8 with bom options/meson.options diff --git a/test cases/failing/132 utf8 with bom options/test.json b/test cases/failing/131 utf8 with bom options/test.json similarity index 65% rename from test cases/failing/132 utf8 with bom options/test.json rename to test cases/failing/131 utf8 with bom options/test.json index c09f48e6a00a..e6391c57da11 100644 --- a/test cases/failing/132 utf8 with bom options/test.json +++ b/test cases/failing/131 utf8 with bom options/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/132 utf8 with bom options/meson.options:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" + "line": "test cases/failing/131 utf8 with bom options/meson.options:0:0: ERROR: Builder file must be encoded in UTF-8 (with no BOM)" } ] } diff --git a/test cases/failing/48 pkgconfig variables not key value/meson.build b/test cases/failing/47 pkgconfig variables not key value/meson.build similarity index 100% rename from test cases/failing/48 pkgconfig variables not key value/meson.build rename to test cases/failing/47 pkgconfig variables not key value/meson.build diff --git a/test cases/failing/48 pkgconfig variables not key value/simple.c b/test cases/failing/47 pkgconfig variables not key value/simple.c similarity index 100% rename from test cases/failing/48 pkgconfig variables not key value/simple.c rename to test cases/failing/47 pkgconfig variables not key value/simple.c diff --git a/test cases/failing/48 pkgconfig variables not key value/simple.h b/test cases/failing/47 pkgconfig variables not key value/simple.h similarity index 100% rename from test cases/failing/48 pkgconfig variables not key value/simple.h rename to test cases/failing/47 pkgconfig variables not key value/simple.h diff --git a/test cases/failing/48 pkgconfig variables not key value/test.json b/test cases/failing/47 pkgconfig variables not key value/test.json similarity index 75% rename from test cases/failing/48 pkgconfig variables not key value/test.json rename to test cases/failing/47 pkgconfig variables not key value/test.json index 96422a923389..11cd374f9121 100644 --- a/test cases/failing/48 pkgconfig variables not key value/test.json +++ b/test cases/failing/47 pkgconfig variables not key value/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/48 pkgconfig variables not key value/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" variable 'this_should_be_key_value' must have a value separated by equals sign." + "line": "test cases/failing/47 pkgconfig variables not key value/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" variable 'this_should_be_key_value' must have a value separated by equals sign." } ] } diff --git a/test cases/failing/49 executable comparison/meson.build b/test cases/failing/48 executable comparison/meson.build similarity index 100% rename from test cases/failing/49 executable comparison/meson.build rename to test cases/failing/48 executable comparison/meson.build diff --git a/test cases/failing/49 executable comparison/prog.c b/test cases/failing/48 executable comparison/prog.c similarity index 100% rename from test cases/failing/49 executable comparison/prog.c rename to test cases/failing/48 executable comparison/prog.c diff --git a/test cases/failing/49 executable comparison/test.json b/test cases/failing/48 executable comparison/test.json similarity index 73% rename from test cases/failing/49 executable comparison/test.json rename to test cases/failing/48 executable comparison/test.json index 76c310b38b91..db6dac3e37fb 100644 --- a/test cases/failing/49 executable comparison/test.json +++ b/test cases/failing/48 executable comparison/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/49 executable comparison/meson.build:6:14: ERROR: Object of type Executable does not support the `<` operator." + "line": "test cases/failing/48 executable comparison/meson.build:6:14: ERROR: Object of type Executable does not support the `<` operator." } ] } diff --git a/test cases/failing/50 inconsistent comparison/meson.build b/test cases/failing/49 inconsistent comparison/meson.build similarity index 100% rename from test cases/failing/50 inconsistent comparison/meson.build rename to test cases/failing/49 inconsistent comparison/meson.build diff --git a/test cases/failing/50 inconsistent comparison/test.json b/test cases/failing/49 inconsistent comparison/test.json similarity index 69% rename from test cases/failing/50 inconsistent comparison/test.json rename to test cases/failing/49 inconsistent comparison/test.json index fa71eeff41eb..4440a86d2bcb 100644 --- a/test cases/failing/50 inconsistent comparison/test.json +++ b/test cases/failing/49 inconsistent comparison/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/50 inconsistent comparison/meson.build:5:12: ERROR: Object <[ArrayHolder] holds [list]: []> of type array does not support the `<` operator." + "line": "test cases/failing/49 inconsistent comparison/meson.build:5:12: ERROR: Object <[ArrayHolder] holds [list]: []> of type array does not support the `<` operator." } ] } diff --git a/test cases/failing/51 slashname/meson.build b/test cases/failing/50 slashname/meson.build similarity index 100% rename from test cases/failing/51 slashname/meson.build rename to test cases/failing/50 slashname/meson.build diff --git a/test cases/failing/51 slashname/sub/meson.build b/test cases/failing/50 slashname/sub/meson.build similarity index 100% rename from test cases/failing/51 slashname/sub/meson.build rename to test cases/failing/50 slashname/sub/meson.build diff --git a/test cases/failing/51 slashname/sub/prog.c b/test cases/failing/50 slashname/sub/prog.c similarity index 100% rename from test cases/failing/51 slashname/sub/prog.c rename to test cases/failing/50 slashname/sub/prog.c diff --git a/test cases/failing/51 slashname/test.json b/test cases/failing/50 slashname/test.json similarity index 67% rename from test cases/failing/51 slashname/test.json rename to test cases/failing/50 slashname/test.json index 39346a955bb4..44b566c2ba7a 100644 --- a/test cases/failing/51 slashname/test.json +++ b/test cases/failing/50 slashname/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/51 slashname/meson.build:9:0: ERROR: Target \"sub/prog\" has a path segment pointing to directory \"sub\". This is an error." + "line": "test cases/failing/50 slashname/meson.build:9:0: ERROR: Target \"sub/prog\" has a path segment pointing to directory \"sub\". This is an error." } ] } diff --git a/test cases/failing/52 reserved meson prefix/meson-foo/meson.build b/test cases/failing/51 reserved meson prefix/meson-foo/meson.build similarity index 100% rename from test cases/failing/52 reserved meson prefix/meson-foo/meson.build rename to test cases/failing/51 reserved meson prefix/meson-foo/meson.build diff --git a/test cases/failing/52 reserved meson prefix/meson.build b/test cases/failing/51 reserved meson prefix/meson.build similarity index 100% rename from test cases/failing/52 reserved meson prefix/meson.build rename to test cases/failing/51 reserved meson prefix/meson.build diff --git a/test cases/failing/52 reserved meson prefix/test.json b/test cases/failing/51 reserved meson prefix/test.json similarity index 67% rename from test cases/failing/52 reserved meson prefix/test.json rename to test cases/failing/51 reserved meson prefix/test.json index 707cd73a58c5..9eb1fa452406 100644 --- a/test cases/failing/52 reserved meson prefix/test.json +++ b/test cases/failing/51 reserved meson prefix/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/52 reserved meson prefix/meson.build:3:0: ERROR: The \"meson-\" prefix is reserved and cannot be used for top-level subdir()." + "line": "test cases/failing/51 reserved meson prefix/meson.build:3:0: ERROR: The \"meson-\" prefix is reserved and cannot be used for top-level subdir()." } ] } diff --git a/test cases/failing/53 or on new line/meson.build b/test cases/failing/52 or on new line/meson.build similarity index 100% rename from test cases/failing/53 or on new line/meson.build rename to test cases/failing/52 or on new line/meson.build diff --git a/test cases/failing/53 or on new line/meson_options.txt b/test cases/failing/52 or on new line/meson_options.txt similarity index 100% rename from test cases/failing/53 or on new line/meson_options.txt rename to test cases/failing/52 or on new line/meson_options.txt diff --git a/test cases/failing/53 or on new line/test.json b/test cases/failing/52 or on new line/test.json similarity index 50% rename from test cases/failing/53 or on new line/test.json rename to test cases/failing/52 or on new line/test.json index 33900255503e..49a7255b0c74 100644 --- a/test cases/failing/53 or on new line/test.json +++ b/test cases/failing/52 or on new line/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/53 or on new line/meson.build:4:8: ERROR: Invalid or clause." + "line": "test cases/failing/52 or on new line/meson.build:4:8: ERROR: Invalid or clause." } ] } diff --git a/test cases/failing/54 link with executable/meson.build b/test cases/failing/53 link with executable/meson.build similarity index 100% rename from test cases/failing/54 link with executable/meson.build rename to test cases/failing/53 link with executable/meson.build diff --git a/test cases/failing/54 link with executable/module.c b/test cases/failing/53 link with executable/module.c similarity index 100% rename from test cases/failing/54 link with executable/module.c rename to test cases/failing/53 link with executable/module.c diff --git a/test cases/failing/54 link with executable/prog.c b/test cases/failing/53 link with executable/prog.c similarity index 100% rename from test cases/failing/54 link with executable/prog.c rename to test cases/failing/53 link with executable/prog.c diff --git a/test cases/failing/54 link with executable/test.json b/test cases/failing/53 link with executable/test.json similarity index 58% rename from test cases/failing/54 link with executable/test.json rename to test cases/failing/53 link with executable/test.json index 2b51bdd5af9c..8c25e07bd2fb 100644 --- a/test cases/failing/54 link with executable/test.json +++ b/test cases/failing/53 link with executable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/54 link with executable/meson.build:4:4: ERROR: Link target 'prog' is not linkable." + "line": "test cases/failing/53 link with executable/meson.build:4:4: ERROR: Link target 'prog' is not linkable." } ] } diff --git a/test cases/failing/55 assign custom target index/meson.build b/test cases/failing/54 assign custom target index/meson.build similarity index 100% rename from test cases/failing/55 assign custom target index/meson.build rename to test cases/failing/54 assign custom target index/meson.build diff --git a/test cases/failing/55 assign custom target index/test.json b/test cases/failing/54 assign custom target index/test.json similarity index 59% rename from test cases/failing/55 assign custom target index/test.json rename to test cases/failing/54 assign custom target index/test.json index 39983fb678cc..15287d6daa88 100644 --- a/test cases/failing/55 assign custom target index/test.json +++ b/test cases/failing/54 assign custom target index/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/55 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id." + "line": "test cases/failing/54 assign custom target index/meson.build:24:0: ERROR: Assignment target must be an id." } ] } diff --git a/test cases/failing/56 getoption prefix/meson.build b/test cases/failing/55 getoption prefix/meson.build similarity index 100% rename from test cases/failing/56 getoption prefix/meson.build rename to test cases/failing/55 getoption prefix/meson.build diff --git a/test cases/failing/56 getoption prefix/subprojects/abc/meson.build b/test cases/failing/55 getoption prefix/subprojects/abc/meson.build similarity index 100% rename from test cases/failing/56 getoption prefix/subprojects/abc/meson.build rename to test cases/failing/55 getoption prefix/subprojects/abc/meson.build diff --git a/test cases/failing/56 getoption prefix/subprojects/abc/meson_options.txt b/test cases/failing/55 getoption prefix/subprojects/abc/meson_options.txt similarity index 100% rename from test cases/failing/56 getoption prefix/subprojects/abc/meson_options.txt rename to test cases/failing/55 getoption prefix/subprojects/abc/meson_options.txt diff --git a/test cases/failing/56 getoption prefix/test.json b/test cases/failing/55 getoption prefix/test.json similarity index 72% rename from test cases/failing/56 getoption prefix/test.json rename to test cases/failing/55 getoption prefix/test.json index c52dffc71c99..9f3a93656875 100644 --- a/test cases/failing/56 getoption prefix/test.json +++ b/test cases/failing/55 getoption prefix/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/56 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects." + "line": "test cases/failing/55 getoption prefix/meson.build:5:0: ERROR: Having a colon in option name is forbidden, projects are not allowed to directly access options of other subprojects." } ] } diff --git a/test cases/failing/57 bad option argument/meson.build b/test cases/failing/56 bad option argument/meson.build similarity index 100% rename from test cases/failing/57 bad option argument/meson.build rename to test cases/failing/56 bad option argument/meson.build diff --git a/test cases/failing/57 bad option argument/meson_options.txt b/test cases/failing/56 bad option argument/meson_options.txt similarity index 100% rename from test cases/failing/57 bad option argument/meson_options.txt rename to test cases/failing/56 bad option argument/meson_options.txt diff --git a/test cases/failing/57 bad option argument/test.json b/test cases/failing/56 bad option argument/test.json similarity index 63% rename from test cases/failing/57 bad option argument/test.json rename to test cases/failing/56 bad option argument/test.json index 622acdffc186..c7957cdc441f 100644 --- a/test cases/failing/57 bad option argument/test.json +++ b/test cases/failing/56 bad option argument/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/57 bad option argument/meson_options.txt:1:0: ERROR: string option got unknown keyword arguments \"value_\"" + "line": "test cases/failing/56 bad option argument/meson_options.txt:1:0: ERROR: string option got unknown keyword arguments \"value_\"" } ] } diff --git a/test cases/failing/58 subproj filegrab/meson.build b/test cases/failing/57 subproj filegrab/meson.build similarity index 100% rename from test cases/failing/58 subproj filegrab/meson.build rename to test cases/failing/57 subproj filegrab/meson.build diff --git a/test cases/failing/58 subproj filegrab/prog.c b/test cases/failing/57 subproj filegrab/prog.c similarity index 100% rename from test cases/failing/58 subproj filegrab/prog.c rename to test cases/failing/57 subproj filegrab/prog.c diff --git a/test cases/failing/58 subproj filegrab/subprojects/a/meson.build b/test cases/failing/57 subproj filegrab/subprojects/a/meson.build similarity index 100% rename from test cases/failing/58 subproj filegrab/subprojects/a/meson.build rename to test cases/failing/57 subproj filegrab/subprojects/a/meson.build diff --git a/test cases/failing/58 subproj filegrab/test.json b/test cases/failing/57 subproj filegrab/test.json similarity index 68% rename from test cases/failing/58 subproj filegrab/test.json rename to test cases/failing/57 subproj filegrab/test.json index 950e109c9d1d..8b0b27f67168 100644 --- a/test cases/failing/58 subproj filegrab/test.json +++ b/test cases/failing/57 subproj filegrab/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/58 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project." + "line": "test cases/failing/57 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project." } ] } diff --git a/test cases/failing/59 grab subproj/meson.build b/test cases/failing/58 grab subproj/meson.build similarity index 100% rename from test cases/failing/59 grab subproj/meson.build rename to test cases/failing/58 grab subproj/meson.build diff --git a/test cases/failing/59 grab subproj/subprojects/foo/meson.build b/test cases/failing/58 grab subproj/subprojects/foo/meson.build similarity index 100% rename from test cases/failing/59 grab subproj/subprojects/foo/meson.build rename to test cases/failing/58 grab subproj/subprojects/foo/meson.build diff --git a/test cases/failing/59 grab subproj/subprojects/foo/sub.c b/test cases/failing/58 grab subproj/subprojects/foo/sub.c similarity index 100% rename from test cases/failing/59 grab subproj/subprojects/foo/sub.c rename to test cases/failing/58 grab subproj/subprojects/foo/sub.c diff --git a/test cases/failing/59 grab subproj/test.json b/test cases/failing/58 grab subproj/test.json similarity index 64% rename from test cases/failing/59 grab subproj/test.json rename to test cases/failing/58 grab subproj/test.json index 7c9020280b0b..bdb0fdfc4f30 100644 --- a/test cases/failing/59 grab subproj/test.json +++ b/test cases/failing/58 grab subproj/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/59 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject." + "line": "test cases/failing/58 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject." } ] } diff --git a/test cases/failing/60 grab sibling/meson.build b/test cases/failing/59 grab sibling/meson.build similarity index 100% rename from test cases/failing/60 grab sibling/meson.build rename to test cases/failing/59 grab sibling/meson.build diff --git a/test cases/failing/60 grab sibling/subprojects/a/meson.build b/test cases/failing/59 grab sibling/subprojects/a/meson.build similarity index 100% rename from test cases/failing/60 grab sibling/subprojects/a/meson.build rename to test cases/failing/59 grab sibling/subprojects/a/meson.build diff --git a/test cases/failing/60 grab sibling/subprojects/b/meson.build b/test cases/failing/59 grab sibling/subprojects/b/meson.build similarity index 100% rename from test cases/failing/60 grab sibling/subprojects/b/meson.build rename to test cases/failing/59 grab sibling/subprojects/b/meson.build diff --git a/test cases/failing/60 grab sibling/subprojects/b/sneaky.c b/test cases/failing/59 grab sibling/subprojects/b/sneaky.c similarity index 100% rename from test cases/failing/60 grab sibling/subprojects/b/sneaky.c rename to test cases/failing/59 grab sibling/subprojects/b/sneaky.c diff --git a/test cases/failing/60 grab sibling/test.json b/test cases/failing/59 grab sibling/test.json similarity index 68% rename from test cases/failing/60 grab sibling/test.json rename to test cases/failing/59 grab sibling/test.json index 8f42badb3fb8..ec17e7e05bc3 100644 --- a/test cases/failing/60 grab sibling/test.json +++ b/test cases/failing/59 grab sibling/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/60 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project." + "line": "test cases/failing/59 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project." } ] } diff --git a/test cases/failing/61 string as link target/meson.build b/test cases/failing/60 string as link target/meson.build similarity index 100% rename from test cases/failing/61 string as link target/meson.build rename to test cases/failing/60 string as link target/meson.build diff --git a/test cases/failing/61 string as link target/prog.c b/test cases/failing/60 string as link target/prog.c similarity index 100% rename from test cases/failing/61 string as link target/prog.c rename to test cases/failing/60 string as link target/prog.c diff --git a/test cases/failing/61 string as link target/test.json b/test cases/failing/60 string as link target/test.json similarity index 53% rename from test cases/failing/61 string as link target/test.json rename to test cases/failing/60 string as link target/test.json index b7f6bd784b30..a97b124ea887 100644 --- a/test cases/failing/61 string as link target/test.json +++ b/test cases/failing/60 string as link target/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/61 string as link target/meson.build:2:0: ERROR: '' is not a target." + "line": "test cases/failing/60 string as link target/meson.build:2:0: ERROR: '' is not a target." } ] } diff --git a/test cases/failing/62 dependency not-found and required/meson.build b/test cases/failing/61 dependency not-found and required/meson.build similarity index 100% rename from test cases/failing/62 dependency not-found and required/meson.build rename to test cases/failing/61 dependency not-found and required/meson.build diff --git a/test cases/failing/62 dependency not-found and required/test.json b/test cases/failing/61 dependency not-found and required/test.json similarity index 63% rename from test cases/failing/62 dependency not-found and required/test.json rename to test cases/failing/61 dependency not-found and required/test.json index 69a67ffbb52e..f7a6c9f21c6b 100644 --- a/test cases/failing/62 dependency not-found and required/test.json +++ b/test cases/failing/61 dependency not-found and required/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/62 dependency not-found and required/meson.build:2:6: ERROR: Dependency is required but has no candidates." + "line": "test cases/failing/61 dependency not-found and required/meson.build:2:6: ERROR: Dependency is required but has no candidates." } ] } diff --git a/test cases/failing/63 subproj different versions/main.c b/test cases/failing/62 subproj different versions/main.c similarity index 100% rename from test cases/failing/63 subproj different versions/main.c rename to test cases/failing/62 subproj different versions/main.c diff --git a/test cases/failing/63 subproj different versions/meson.build b/test cases/failing/62 subproj different versions/meson.build similarity index 100% rename from test cases/failing/63 subproj different versions/meson.build rename to test cases/failing/62 subproj different versions/meson.build diff --git a/test cases/failing/63 subproj different versions/subprojects/a/a.c b/test cases/failing/62 subproj different versions/subprojects/a/a.c similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/a/a.c rename to test cases/failing/62 subproj different versions/subprojects/a/a.c diff --git a/test cases/failing/63 subproj different versions/subprojects/a/a.h b/test cases/failing/62 subproj different versions/subprojects/a/a.h similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/a/a.h rename to test cases/failing/62 subproj different versions/subprojects/a/a.h diff --git a/test cases/failing/63 subproj different versions/subprojects/a/meson.build b/test cases/failing/62 subproj different versions/subprojects/a/meson.build similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/a/meson.build rename to test cases/failing/62 subproj different versions/subprojects/a/meson.build diff --git a/test cases/failing/63 subproj different versions/subprojects/b/b.c b/test cases/failing/62 subproj different versions/subprojects/b/b.c similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/b/b.c rename to test cases/failing/62 subproj different versions/subprojects/b/b.c diff --git a/test cases/failing/63 subproj different versions/subprojects/b/b.h b/test cases/failing/62 subproj different versions/subprojects/b/b.h similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/b/b.h rename to test cases/failing/62 subproj different versions/subprojects/b/b.h diff --git a/test cases/failing/63 subproj different versions/subprojects/b/meson.build b/test cases/failing/62 subproj different versions/subprojects/b/meson.build similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/b/meson.build rename to test cases/failing/62 subproj different versions/subprojects/b/meson.build diff --git a/test cases/failing/63 subproj different versions/subprojects/c/c.h b/test cases/failing/62 subproj different versions/subprojects/c/c.h similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/c/c.h rename to test cases/failing/62 subproj different versions/subprojects/c/c.h diff --git a/test cases/failing/63 subproj different versions/subprojects/c/meson.build b/test cases/failing/62 subproj different versions/subprojects/c/meson.build similarity index 100% rename from test cases/failing/63 subproj different versions/subprojects/c/meson.build rename to test cases/failing/62 subproj different versions/subprojects/c/meson.build diff --git a/test cases/failing/63 subproj different versions/test.json b/test cases/failing/62 subproj different versions/test.json similarity index 64% rename from test cases/failing/63 subproj different versions/test.json rename to test cases/failing/62 subproj different versions/test.json index f2535fafd587..705ff51f1754 100644 --- a/test cases/failing/63 subproj different versions/test.json +++ b/test cases/failing/62 subproj different versions/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/63 subproj different versions/subprojects/b/meson.build:3:8: ERROR: Dependency 'c' is required but not found." + "line": "test cases/failing/62 subproj different versions/subprojects/b/meson.build:3:8: ERROR: Dependency 'c' is required but not found." } ] } diff --git a/test cases/failing/64 wrong boost module/meson.build b/test cases/failing/63 wrong boost module/meson.build similarity index 100% rename from test cases/failing/64 wrong boost module/meson.build rename to test cases/failing/63 wrong boost module/meson.build diff --git a/test cases/failing/64 wrong boost module/test.json b/test cases/failing/63 wrong boost module/test.json similarity index 60% rename from test cases/failing/64 wrong boost module/test.json rename to test cases/failing/63 wrong boost module/test.json index 78e206999120..ec3c1b083abd 100644 --- a/test cases/failing/64 wrong boost module/test.json +++ b/test cases/failing/63 wrong boost module/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/64 wrong boost module/meson.build:9:10: ERROR: Dependency \"boost\" not found, tried system" + "line": "test cases/failing/63 wrong boost module/meson.build:9:10: ERROR: Dependency \"boost\" not found, tried system" } ] } diff --git a/test cases/failing/65 install_data rename bad size/file1.txt b/test cases/failing/64 install_data rename bad size/file1.txt similarity index 100% rename from test cases/failing/65 install_data rename bad size/file1.txt rename to test cases/failing/64 install_data rename bad size/file1.txt diff --git a/test cases/failing/65 install_data rename bad size/file2.txt b/test cases/failing/64 install_data rename bad size/file2.txt similarity index 100% rename from test cases/failing/65 install_data rename bad size/file2.txt rename to test cases/failing/64 install_data rename bad size/file2.txt diff --git a/test cases/failing/65 install_data rename bad size/meson.build b/test cases/failing/64 install_data rename bad size/meson.build similarity index 100% rename from test cases/failing/65 install_data rename bad size/meson.build rename to test cases/failing/64 install_data rename bad size/meson.build diff --git a/test cases/failing/65 install_data rename bad size/test.json b/test cases/failing/64 install_data rename bad size/test.json similarity index 75% rename from test cases/failing/65 install_data rename bad size/test.json rename to test cases/failing/64 install_data rename bad size/test.json index efc62907db4e..5ed47480ae22 100644 --- a/test cases/failing/65 install_data rename bad size/test.json +++ b/test cases/failing/64 install_data rename bad size/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/65 install_data rename bad size/meson.build:3:0: ERROR: \"rename\" and \"sources\" argument lists must be the same length if \"rename\" is given. Rename has 1 elements and sources has 2." + "line": "test cases/failing/64 install_data rename bad size/meson.build:3:0: ERROR: \"rename\" and \"sources\" argument lists must be the same length if \"rename\" is given. Rename has 1 elements and sources has 2." } ] } diff --git a/test cases/failing/66 skip only subdir/meson.build b/test cases/failing/65 skip only subdir/meson.build similarity index 100% rename from test cases/failing/66 skip only subdir/meson.build rename to test cases/failing/65 skip only subdir/meson.build diff --git a/test cases/failing/66 skip only subdir/subdir/meson.build b/test cases/failing/65 skip only subdir/subdir/meson.build similarity index 100% rename from test cases/failing/66 skip only subdir/subdir/meson.build rename to test cases/failing/65 skip only subdir/subdir/meson.build diff --git a/test cases/failing/66 skip only subdir/test.json b/test cases/failing/65 skip only subdir/test.json similarity index 55% rename from test cases/failing/66 skip only subdir/test.json rename to test cases/failing/65 skip only subdir/test.json index de21e006c6fb..2747566dcfaa 100644 --- a/test cases/failing/66 skip only subdir/test.json +++ b/test cases/failing/65 skip only subdir/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/66 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist." + "line": "test cases/failing/65 skip only subdir/meson.build:8:0: ERROR: File main.cpp does not exist." } ] } diff --git a/test cases/failing/67 dual override/meson.build b/test cases/failing/66 dual override/meson.build similarity index 100% rename from test cases/failing/67 dual override/meson.build rename to test cases/failing/66 dual override/meson.build diff --git a/test cases/failing/67 dual override/overrides.py b/test cases/failing/66 dual override/overrides.py similarity index 100% rename from test cases/failing/67 dual override/overrides.py rename to test cases/failing/66 dual override/overrides.py diff --git a/test cases/failing/67 dual override/test.json b/test cases/failing/66 dual override/test.json similarity index 65% rename from test cases/failing/67 dual override/test.json rename to test cases/failing/66 dual override/test.json index b50f3aca8959..b8c26510de63 100644 --- a/test cases/failing/67 dual override/test.json +++ b/test cases/failing/66 dual override/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/67 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden." + "line": "test cases/failing/66 dual override/meson.build:5:6: ERROR: Tried to override executable \"override\" which has already been overridden." } ] } diff --git a/test cases/failing/68 override used/meson.build b/test cases/failing/67 override used/meson.build similarity index 100% rename from test cases/failing/68 override used/meson.build rename to test cases/failing/67 override used/meson.build diff --git a/test cases/failing/68 override used/other.py b/test cases/failing/67 override used/other.py similarity index 100% rename from test cases/failing/68 override used/other.py rename to test cases/failing/67 override used/other.py diff --git a/test cases/failing/68 override used/something.py b/test cases/failing/67 override used/something.py similarity index 100% rename from test cases/failing/68 override used/something.py rename to test cases/failing/67 override used/something.py diff --git a/test cases/failing/68 override used/test.json b/test cases/failing/67 override used/test.json similarity index 67% rename from test cases/failing/68 override used/test.json rename to test cases/failing/67 override used/test.json index f11aac61983c..90d8b4b8def2 100644 --- a/test cases/failing/68 override used/test.json +++ b/test cases/failing/67 override used/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/68 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found." + "line": "test cases/failing/67 override used/meson.build:5:6: ERROR: Tried to override finding of executable \"something.py\" which has already been found." } ] } diff --git a/test cases/failing/69 run_command unclean exit/meson.build b/test cases/failing/68 run_command unclean exit/meson.build similarity index 100% rename from test cases/failing/69 run_command unclean exit/meson.build rename to test cases/failing/68 run_command unclean exit/meson.build diff --git a/test cases/failing/69 run_command unclean exit/returncode.py b/test cases/failing/68 run_command unclean exit/returncode.py similarity index 100% rename from test cases/failing/69 run_command unclean exit/returncode.py rename to test cases/failing/68 run_command unclean exit/returncode.py diff --git a/test cases/failing/69 run_command unclean exit/test.json b/test cases/failing/68 run_command unclean exit/test.json similarity index 56% rename from test cases/failing/69 run_command unclean exit/test.json rename to test cases/failing/68 run_command unclean exit/test.json index 96c2141fc9fa..cef67e515285 100644 --- a/test cases/failing/69 run_command unclean exit/test.json +++ b/test cases/failing/68 run_command unclean exit/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/69 run_command unclean exit/meson\\.build:4:0: ERROR: Command `.*['\"].*[\\\\/]test cases[\\\\/]failing[\\\\/]69 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py['\"] 1` failed with status 1\\." + "line": "test cases/failing/68 run_command unclean exit/meson\\.build:4:0: ERROR: Command `.*['\"].*[\\\\/]test cases[\\\\/]failing[\\\\/]68 run_command unclean exit[\\\\/]\\.[\\\\/]returncode\\.py['\"] 1` failed with status 1\\." } ] } diff --git a/test cases/failing/70 int literal leading zero/meson.build b/test cases/failing/69 int literal leading zero/meson.build similarity index 100% rename from test cases/failing/70 int literal leading zero/meson.build rename to test cases/failing/69 int literal leading zero/meson.build diff --git a/test cases/failing/70 int literal leading zero/test.json b/test cases/failing/69 int literal leading zero/test.json similarity index 69% rename from test cases/failing/70 int literal leading zero/test.json rename to test cases/failing/69 int literal leading zero/test.json index fafbf0d044e2..200b569b21cd 100644 --- a/test cases/failing/70 int literal leading zero/test.json +++ b/test cases/failing/69 int literal leading zero/test.json @@ -2,7 +2,7 @@ "stdout": [ { "comment": "this error message is not very informative", - "line": "test cases/failing/70 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number." + "line": "test cases/failing/69 int literal leading zero/meson.build:5:13: ERROR: Expecting eof got number." } ] } diff --git a/test cases/failing/71 configuration immutable/input b/test cases/failing/70 configuration immutable/input similarity index 100% rename from test cases/failing/71 configuration immutable/input rename to test cases/failing/70 configuration immutable/input diff --git a/test cases/failing/71 configuration immutable/meson.build b/test cases/failing/70 configuration immutable/meson.build similarity index 100% rename from test cases/failing/71 configuration immutable/meson.build rename to test cases/failing/70 configuration immutable/meson.build diff --git a/test cases/failing/71 configuration immutable/test.json b/test cases/failing/70 configuration immutable/test.json similarity index 65% rename from test cases/failing/71 configuration immutable/test.json rename to test cases/failing/70 configuration immutable/test.json index af1a65ddd184..fc735fa38ece 100644 --- a/test cases/failing/71 configuration immutable/test.json +++ b/test cases/failing/70 configuration immutable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/71 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." + "line": "test cases/failing/70 configuration immutable/meson.build:12:16: ERROR: Can not set values on configuration object that has been used." } ] } diff --git a/test cases/failing/72 link with shared module on osx/meson.build b/test cases/failing/71 link with shared module on osx/meson.build similarity index 100% rename from test cases/failing/72 link with shared module on osx/meson.build rename to test cases/failing/71 link with shared module on osx/meson.build diff --git a/test cases/failing/72 link with shared module on osx/module.c b/test cases/failing/71 link with shared module on osx/module.c similarity index 100% rename from test cases/failing/72 link with shared module on osx/module.c rename to test cases/failing/71 link with shared module on osx/module.c diff --git a/test cases/failing/72 link with shared module on osx/prog.c b/test cases/failing/71 link with shared module on osx/prog.c similarity index 100% rename from test cases/failing/72 link with shared module on osx/prog.c rename to test cases/failing/71 link with shared module on osx/prog.c diff --git a/test cases/failing/72 link with shared module on osx/test.json b/test cases/failing/71 link with shared module on osx/test.json similarity index 68% rename from test cases/failing/72 link with shared module on osx/test.json rename to test cases/failing/71 link with shared module on osx/test.json index 1a2d78cd7e16..206d4297b5bb 100644 --- a/test cases/failing/72 link with shared module on osx/test.json +++ b/test cases/failing/71 link with shared module on osx/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/72 link with shared module on osx/meson.build:8:4: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" + "line": "test cases/failing/71 link with shared module on osx/meson.build:8:4: ERROR: target prog links against shared module mymodule. This is not permitted on OSX" } ] } diff --git a/test cases/failing/73 non-ascii in ascii encoded configure file/config9.h.in b/test cases/failing/72 non-ascii in ascii encoded configure file/config9.h.in similarity index 100% rename from test cases/failing/73 non-ascii in ascii encoded configure file/config9.h.in rename to test cases/failing/72 non-ascii in ascii encoded configure file/config9.h.in diff --git a/test cases/failing/73 non-ascii in ascii encoded configure file/meson.build b/test cases/failing/72 non-ascii in ascii encoded configure file/meson.build similarity index 100% rename from test cases/failing/73 non-ascii in ascii encoded configure file/meson.build rename to test cases/failing/72 non-ascii in ascii encoded configure file/meson.build diff --git a/test cases/failing/73 non-ascii in ascii encoded configure file/test.json b/test cases/failing/72 non-ascii in ascii encoded configure file/test.json similarity index 79% rename from test cases/failing/73 non-ascii in ascii encoded configure file/test.json rename to test cases/failing/72 non-ascii in ascii encoded configure file/test.json index 63f5bef8530d..1dc0b913ab39 100644 --- a/test cases/failing/73 non-ascii in ascii encoded configure file/test.json +++ b/test cases/failing/72 non-ascii in ascii encoded configure file/test.json @@ -2,7 +2,7 @@ "stdout": [ { "match": "re", - "line": "test cases/failing/73 non-ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)" + "line": "test cases/failing/72 non-ascii in ascii encoded configure file/meson\\.build:5:0: ERROR: Could not write output file .*[\\\\/]config9\\.h: 'ascii' codec can't encode character '\\\\u0434' in position 17: ordinal not in range\\(128\\)" } ] } diff --git a/test cases/failing/74 subproj dependency not-found and required/meson.build b/test cases/failing/73 subproj dependency not-found and required/meson.build similarity index 100% rename from test cases/failing/74 subproj dependency not-found and required/meson.build rename to test cases/failing/73 subproj dependency not-found and required/meson.build diff --git a/test cases/failing/74 subproj dependency not-found and required/test.json b/test cases/failing/73 subproj dependency not-found and required/test.json similarity index 68% rename from test cases/failing/74 subproj dependency not-found and required/test.json rename to test cases/failing/73 subproj dependency not-found and required/test.json index 997bc56b2cc8..11ab0318b3cc 100644 --- a/test cases/failing/74 subproj dependency not-found and required/test.json +++ b/test cases/failing/73 subproj dependency not-found and required/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/74 subproj dependency not-found and required/meson.build:2:10: ERROR: Neither a subproject directory nor a missing.wrap file was found." + "line": "test cases/failing/73 subproj dependency not-found and required/meson.build:2:10: ERROR: Neither a subproject directory nor a missing.wrap file was found." } ] } diff --git a/test cases/failing/75 unfound run/meson.build b/test cases/failing/74 unfound run/meson.build similarity index 100% rename from test cases/failing/75 unfound run/meson.build rename to test cases/failing/74 unfound run/meson.build diff --git a/test cases/failing/75 unfound run/test.json b/test cases/failing/74 unfound run/test.json similarity index 60% rename from test cases/failing/75 unfound run/test.json rename to test cases/failing/74 unfound run/test.json index 855c2a477d0d..8d31785f7a1e 100644 --- a/test cases/failing/75 unfound run/test.json +++ b/test cases/failing/74 unfound run/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/75 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'" + "line": "test cases/failing/74 unfound run/meson.build:4:0: ERROR: Tried to use non-existing executable 'nonexisting_prog'" } ] } diff --git a/test cases/failing/76 framework dependency with version/meson.build b/test cases/failing/75 framework dependency with version/meson.build similarity index 100% rename from test cases/failing/76 framework dependency with version/meson.build rename to test cases/failing/75 framework dependency with version/meson.build diff --git a/test cases/failing/76 framework dependency with version/test.json b/test cases/failing/75 framework dependency with version/test.json similarity index 72% rename from test cases/failing/76 framework dependency with version/test.json rename to test cases/failing/75 framework dependency with version/test.json index 07b4a6eba4e8..8a01356b2130 100644 --- a/test cases/failing/76 framework dependency with version/test.json +++ b/test cases/failing/75 framework dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/76 framework dependency with version/meson.build:8:6: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/75 framework dependency with version/meson.build:8:6: ERROR: Dependency lookup for appleframeworks with method 'framework' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/77 override exe config/foo.c b/test cases/failing/76 override exe config/foo.c similarity index 100% rename from test cases/failing/77 override exe config/foo.c rename to test cases/failing/76 override exe config/foo.c diff --git a/test cases/failing/77 override exe config/meson.build b/test cases/failing/76 override exe config/meson.build similarity index 100% rename from test cases/failing/77 override exe config/meson.build rename to test cases/failing/76 override exe config/meson.build diff --git a/test cases/failing/77 override exe config/test.json b/test cases/failing/76 override exe config/test.json similarity index 72% rename from test cases/failing/77 override exe config/test.json rename to test cases/failing/76 override exe config/test.json index a0dd7ae6e6ed..23b9055ea92e 100644 --- a/test cases/failing/77 override exe config/test.json +++ b/test cases/failing/76 override exe config/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/77 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration" + "line": "test cases/failing/76 override exe config/meson.build:6:0: ERROR: Program 'bar' was overridden with the compiled executable 'foo' and therefore cannot be used during configuration" } ] } diff --git a/test cases/failing/78 gl dependency with version/meson.build b/test cases/failing/77 gl dependency with version/meson.build similarity index 100% rename from test cases/failing/78 gl dependency with version/meson.build rename to test cases/failing/77 gl dependency with version/meson.build diff --git a/test cases/failing/78 gl dependency with version/test.json b/test cases/failing/77 gl dependency with version/test.json similarity index 69% rename from test cases/failing/78 gl dependency with version/test.json rename to test cases/failing/77 gl dependency with version/test.json index fbd9ff9ee478..83665cbfba3e 100644 --- a/test cases/failing/78 gl dependency with version/test.json +++ b/test cases/failing/77 gl dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/78 gl dependency with version/meson.build:9:6: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/77 gl dependency with version/meson.build:9:6: ERROR: Dependency lookup for gl with method 'system' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/79 threads dependency with version/meson.build b/test cases/failing/78 threads dependency with version/meson.build similarity index 100% rename from test cases/failing/79 threads dependency with version/meson.build rename to test cases/failing/78 threads dependency with version/meson.build diff --git a/test cases/failing/79 threads dependency with version/test.json b/test cases/failing/78 threads dependency with version/test.json similarity index 71% rename from test cases/failing/79 threads dependency with version/test.json rename to test cases/failing/78 threads dependency with version/test.json index 890695b64b00..ec02c2bfd6a0 100644 --- a/test cases/failing/79 threads dependency with version/test.json +++ b/test cases/failing/78 threads dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/79 threads dependency with version/meson.build:3:6: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." + "line": "test cases/failing/78 threads dependency with version/meson.build:3:6: ERROR: Dependency lookup for threads with method 'system' failed: Unknown version, but need ['>0']." } ] } diff --git a/test cases/failing/80 gtest dependency with version/meson.build b/test cases/failing/79 gtest dependency with version/meson.build similarity index 100% rename from test cases/failing/80 gtest dependency with version/meson.build rename to test cases/failing/79 gtest dependency with version/meson.build diff --git a/test cases/failing/80 gtest dependency with version/test.json b/test cases/failing/79 gtest dependency with version/test.json similarity index 62% rename from test cases/failing/80 gtest dependency with version/test.json rename to test cases/failing/79 gtest dependency with version/test.json index 3f9934d49e60..a32a3c20716b 100644 --- a/test cases/failing/80 gtest dependency with version/test.json +++ b/test cases/failing/79 gtest dependency with version/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/80 gtest dependency with version/meson.build:8:6: ERROR: Dependency 'gtest' is required but not found." + "line": "test cases/failing/79 gtest dependency with version/meson.build:8:6: ERROR: Dependency 'gtest' is required but not found." } ] } diff --git a/test cases/failing/81 dub library/meson.build b/test cases/failing/80 dub library/meson.build similarity index 100% rename from test cases/failing/81 dub library/meson.build rename to test cases/failing/80 dub library/meson.build diff --git a/test cases/failing/81 dub library/test.json b/test cases/failing/80 dub library/test.json similarity index 57% rename from test cases/failing/81 dub library/test.json rename to test cases/failing/80 dub library/test.json index 2db91eed594d..d3c7d426449e 100644 --- a/test cases/failing/81 dub library/test.json +++ b/test cases/failing/80 dub library/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/81 dub library/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" + "line": "test cases/failing/80 dub library/meson.build:11:0: ERROR: Dependency \"dubtestproject\" not found" } ] } diff --git a/test cases/failing/82 dub executable/meson.build b/test cases/failing/81 dub executable/meson.build similarity index 100% rename from test cases/failing/82 dub executable/meson.build rename to test cases/failing/81 dub executable/meson.build diff --git a/test cases/failing/82 dub executable/test.json b/test cases/failing/81 dub executable/test.json similarity index 59% rename from test cases/failing/82 dub executable/test.json rename to test cases/failing/81 dub executable/test.json index 8ae46b84864f..8aefa170689e 100644 --- a/test cases/failing/82 dub executable/test.json +++ b/test cases/failing/81 dub executable/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/82 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found" + "line": "test cases/failing/81 dub executable/meson.build:11:0: ERROR: Dependency \"dubtestproject:test1\" not found" } ] } diff --git a/test cases/failing/83 dub compiler/meson.build b/test cases/failing/82 dub compiler/meson.build similarity index 100% rename from test cases/failing/83 dub compiler/meson.build rename to test cases/failing/82 dub compiler/meson.build diff --git a/test cases/failing/83 dub compiler/test.json b/test cases/failing/82 dub compiler/test.json similarity index 81% rename from test cases/failing/83 dub compiler/test.json rename to test cases/failing/82 dub compiler/test.json index 07241d21ed47..89d1882d9652 100644 --- a/test cases/failing/83 dub compiler/test.json +++ b/test cases/failing/82 dub compiler/test.json @@ -13,7 +13,7 @@ }, "stdout": [ { - "line": "test cases/failing/83 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found" + "line": "test cases/failing/82 dub compiler/meson.build:17:0: ERROR: Dependency \"dubtestproject:test2\" not found" } ] } diff --git a/test cases/failing/84 subproj not-found dep/meson.build b/test cases/failing/83 subproj not-found dep/meson.build similarity index 100% rename from test cases/failing/84 subproj not-found dep/meson.build rename to test cases/failing/83 subproj not-found dep/meson.build diff --git a/test cases/failing/84 subproj not-found dep/subprojects/somesubproj/meson.build b/test cases/failing/83 subproj not-found dep/subprojects/somesubproj/meson.build similarity index 100% rename from test cases/failing/84 subproj not-found dep/subprojects/somesubproj/meson.build rename to test cases/failing/83 subproj not-found dep/subprojects/somesubproj/meson.build diff --git a/test cases/failing/84 subproj not-found dep/test.json b/test cases/failing/83 subproj not-found dep/test.json similarity index 62% rename from test cases/failing/84 subproj not-found dep/test.json rename to test cases/failing/83 subproj not-found dep/test.json index bea1ed0e3614..5da4fb9a3140 100644 --- a/test cases/failing/84 subproj not-found dep/test.json +++ b/test cases/failing/83 subproj not-found dep/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/84 subproj not-found dep/meson.build:2:10: ERROR: Dependency '(anonymous)' is required but not found." + "line": "test cases/failing/83 subproj not-found dep/meson.build:2:10: ERROR: Dependency '(anonymous)' is required but not found." } ] } diff --git a/test cases/failing/85 invalid configure file/input b/test cases/failing/84 invalid configure file/input similarity index 100% rename from test cases/failing/85 invalid configure file/input rename to test cases/failing/84 invalid configure file/input diff --git a/test cases/failing/85 invalid configure file/meson.build b/test cases/failing/84 invalid configure file/meson.build similarity index 100% rename from test cases/failing/85 invalid configure file/meson.build rename to test cases/failing/84 invalid configure file/meson.build diff --git a/test cases/failing/85 invalid configure file/test.json b/test cases/failing/84 invalid configure file/test.json similarity index 67% rename from test cases/failing/85 invalid configure file/test.json rename to test cases/failing/84 invalid configure file/test.json index 1cee20880a4d..2b7a7457b805 100644 --- a/test cases/failing/85 invalid configure file/test.json +++ b/test cases/failing/84 invalid configure file/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/85 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true" + "line": "test cases/failing/84 invalid configure file/meson.build:3:0: ERROR: \"install_dir\" must be specified when \"install\" in a configure_file is true" } ] } diff --git a/test cases/failing/86 kwarg dupe/meson.build b/test cases/failing/85 kwarg dupe/meson.build similarity index 100% rename from test cases/failing/86 kwarg dupe/meson.build rename to test cases/failing/85 kwarg dupe/meson.build diff --git a/test cases/failing/86 kwarg dupe/prog.c b/test cases/failing/85 kwarg dupe/prog.c similarity index 100% rename from test cases/failing/86 kwarg dupe/prog.c rename to test cases/failing/85 kwarg dupe/prog.c diff --git a/test cases/failing/86 kwarg dupe/test.json b/test cases/failing/85 kwarg dupe/test.json similarity index 65% rename from test cases/failing/86 kwarg dupe/test.json rename to test cases/failing/85 kwarg dupe/test.json index 229debbea812..99719ad4ca8c 100644 --- a/test cases/failing/86 kwarg dupe/test.json +++ b/test cases/failing/85 kwarg dupe/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/86 kwarg dupe/meson.build:6:2: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." + "line": "test cases/failing/85 kwarg dupe/meson.build:6:2: ERROR: Entry \"install\" defined both as a keyword argument and in a \"kwarg\" entry." } ] } diff --git a/test cases/failing/87 missing pch file/meson.build b/test cases/failing/86 missing pch file/meson.build similarity index 100% rename from test cases/failing/87 missing pch file/meson.build rename to test cases/failing/86 missing pch file/meson.build diff --git a/test cases/failing/87 missing pch file/prog.c b/test cases/failing/86 missing pch file/prog.c similarity index 100% rename from test cases/failing/87 missing pch file/prog.c rename to test cases/failing/86 missing pch file/prog.c diff --git a/test cases/failing/87 missing pch file/test.json b/test cases/failing/86 missing pch file/test.json similarity index 74% rename from test cases/failing/87 missing pch file/test.json rename to test cases/failing/86 missing pch file/test.json index a54acb7a7562..d6a50c237440 100644 --- a/test cases/failing/87 missing pch file/test.json +++ b/test cases/failing/86 missing pch file/test.json @@ -2,7 +2,7 @@ "stdout": [ { "comment": "literal 'pch/prog.h' from meson.build appears in output, irrespective of os.path.sep", - "line": "test cases/failing/87 missing pch file/meson.build:2:6: ERROR: File pch/prog.h does not exist." + "line": "test cases/failing/86 missing pch file/meson.build:2:6: ERROR: File pch/prog.h does not exist." } ] } diff --git a/test cases/failing/88 pch source different folder/include/pch.h b/test cases/failing/87 pch source different folder/include/pch.h similarity index 100% rename from test cases/failing/88 pch source different folder/include/pch.h rename to test cases/failing/87 pch source different folder/include/pch.h diff --git a/test cases/failing/88 pch source different folder/meson.build b/test cases/failing/87 pch source different folder/meson.build similarity index 100% rename from test cases/failing/88 pch source different folder/meson.build rename to test cases/failing/87 pch source different folder/meson.build diff --git a/test cases/failing/88 pch source different folder/prog.c b/test cases/failing/87 pch source different folder/prog.c similarity index 100% rename from test cases/failing/88 pch source different folder/prog.c rename to test cases/failing/87 pch source different folder/prog.c diff --git a/test cases/failing/88 pch source different folder/src/pch.c b/test cases/failing/87 pch source different folder/src/pch.c similarity index 100% rename from test cases/failing/88 pch source different folder/src/pch.c rename to test cases/failing/87 pch source different folder/src/pch.c diff --git a/test cases/failing/88 pch source different folder/test.json b/test cases/failing/87 pch source different folder/test.json similarity index 62% rename from test cases/failing/88 pch source different folder/test.json rename to test cases/failing/87 pch source different folder/test.json index 60fa4e0a6f07..0a9d39d6ff8f 100644 --- a/test cases/failing/88 pch source different folder/test.json +++ b/test cases/failing/87 pch source different folder/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/88 pch source different folder/meson.build:4:6: ERROR: PCH files must be stored in the same folder." + "line": "test cases/failing/87 pch source different folder/meson.build:4:6: ERROR: PCH files must be stored in the same folder." } ] } diff --git a/test cases/failing/89 unknown config tool/meson.build b/test cases/failing/88 unknown config tool/meson.build similarity index 100% rename from test cases/failing/89 unknown config tool/meson.build rename to test cases/failing/88 unknown config tool/meson.build diff --git a/test cases/failing/89 unknown config tool/test.json b/test cases/failing/88 unknown config tool/test.json similarity index 60% rename from test cases/failing/89 unknown config tool/test.json rename to test cases/failing/88 unknown config tool/test.json index f5c0d96abb13..5a53b26f02f6 100644 --- a/test cases/failing/89 unknown config tool/test.json +++ b/test cases/failing/88 unknown config tool/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/89 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found" + "line": "test cases/failing/88 unknown config tool/meson.build:2:0: ERROR: Dependency \"no-such-config-tool\" not found" } ] } diff --git a/test cases/failing/90 custom target install data/Info.plist.cpp b/test cases/failing/89 custom target install data/Info.plist.cpp similarity index 100% rename from test cases/failing/90 custom target install data/Info.plist.cpp rename to test cases/failing/89 custom target install data/Info.plist.cpp diff --git a/test cases/failing/90 custom target install data/meson.build b/test cases/failing/89 custom target install data/meson.build similarity index 100% rename from test cases/failing/90 custom target install data/meson.build rename to test cases/failing/89 custom target install data/meson.build diff --git a/test cases/failing/90 custom target install data/preproc.py b/test cases/failing/89 custom target install data/preproc.py similarity index 100% rename from test cases/failing/90 custom target install data/preproc.py rename to test cases/failing/89 custom target install data/preproc.py diff --git a/test cases/failing/90 custom target install data/test.json b/test cases/failing/89 custom target install data/test.json similarity index 71% rename from test cases/failing/90 custom target install data/test.json rename to test cases/failing/89 custom target install data/test.json index d495163f2a2b..3364a6a6c8c7 100644 --- a/test cases/failing/90 custom target install data/test.json +++ b/test cases/failing/89 custom target install data/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/90 custom target install data/meson.build:11:0: ERROR: install_data argument 1 was of type \"CustomTarget\" but should have been one of: \"str\", \"File\"" + "line": "test cases/failing/89 custom target install data/meson.build:11:0: ERROR: install_data argument 1 was of type \"CustomTarget\" but should have been one of: \"str\", \"File\"" } ] } diff --git a/test cases/failing/91 add dict non string key/meson.build b/test cases/failing/90 add dict non string key/meson.build similarity index 100% rename from test cases/failing/91 add dict non string key/meson.build rename to test cases/failing/90 add dict non string key/meson.build diff --git a/test cases/failing/91 add dict non string key/test.json b/test cases/failing/90 add dict non string key/test.json similarity index 54% rename from test cases/failing/91 add dict non string key/test.json rename to test cases/failing/90 add dict non string key/test.json index db506b2e021e..822e09f54ba9 100644 --- a/test cases/failing/91 add dict non string key/test.json +++ b/test cases/failing/90 add dict non string key/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/91 add dict non string key/meson.build:9:9: ERROR: Key must be a string" + "line": "test cases/failing/90 add dict non string key/meson.build:9:9: ERROR: Key must be a string" } ] } diff --git a/test cases/failing/92 add dict duplicate keys/meson.build b/test cases/failing/91 add dict duplicate keys/meson.build similarity index 100% rename from test cases/failing/92 add dict duplicate keys/meson.build rename to test cases/failing/91 add dict duplicate keys/meson.build diff --git a/test cases/failing/92 add dict duplicate keys/test.json b/test cases/failing/91 add dict duplicate keys/test.json similarity index 58% rename from test cases/failing/92 add dict duplicate keys/test.json rename to test cases/failing/91 add dict duplicate keys/test.json index b428a5387348..b6941e75fc96 100644 --- a/test cases/failing/92 add dict duplicate keys/test.json +++ b/test cases/failing/91 add dict duplicate keys/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/92 add dict duplicate keys/meson.build:9:27: ERROR: Duplicate dictionary key: myKey" + "line": "test cases/failing/91 add dict duplicate keys/meson.build:9:27: ERROR: Duplicate dictionary key: myKey" } ] } diff --git a/test cases/failing/93 no host get_external_property/meson.build b/test cases/failing/92 no host get_external_property/meson.build similarity index 100% rename from test cases/failing/93 no host get_external_property/meson.build rename to test cases/failing/92 no host get_external_property/meson.build diff --git a/test cases/failing/93 no host get_external_property/test.json b/test cases/failing/92 no host get_external_property/test.json similarity index 63% rename from test cases/failing/93 no host get_external_property/test.json rename to test cases/failing/92 no host get_external_property/test.json index b26f3c9b6b59..0f7a803ff2b4 100644 --- a/test cases/failing/93 no host get_external_property/test.json +++ b/test cases/failing/92 no host get_external_property/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/93 no host get_external_property/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" + "line": "test cases/failing/92 no host get_external_property/meson.build:3:14: ERROR: Unknown property for host machine: nonexisting" } ] } diff --git a/test cases/failing/94 no native compiler/main.c b/test cases/failing/93 no native compiler/main.c similarity index 100% rename from test cases/failing/94 no native compiler/main.c rename to test cases/failing/93 no native compiler/main.c diff --git a/test cases/failing/94 no native compiler/meson.build b/test cases/failing/93 no native compiler/meson.build similarity index 100% rename from test cases/failing/94 no native compiler/meson.build rename to test cases/failing/93 no native compiler/meson.build diff --git a/test cases/failing/94 no native compiler/test.json b/test cases/failing/93 no native compiler/test.json similarity index 58% rename from test cases/failing/94 no native compiler/test.json rename to test cases/failing/93 no native compiler/test.json index 7181c6b7ee5d..adf99f1a2478 100644 --- a/test cases/failing/94 no native compiler/test.json +++ b/test cases/failing/93 no native compiler/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/94 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\"" + "line": "test cases/failing/93 no native compiler/meson.build:12:0: ERROR: No host machine compiler for \"main.c\"" } ] } diff --git a/test cases/failing/95 subdir parse error/meson.build b/test cases/failing/94 subdir parse error/meson.build similarity index 100% rename from test cases/failing/95 subdir parse error/meson.build rename to test cases/failing/94 subdir parse error/meson.build diff --git a/test cases/failing/95 subdir parse error/subdir/meson.build b/test cases/failing/94 subdir parse error/subdir/meson.build similarity index 100% rename from test cases/failing/95 subdir parse error/subdir/meson.build rename to test cases/failing/94 subdir parse error/subdir/meson.build diff --git a/test cases/failing/95 subdir parse error/test.json b/test cases/failing/94 subdir parse error/test.json similarity index 59% rename from test cases/failing/95 subdir parse error/test.json rename to test cases/failing/94 subdir parse error/test.json index c94ed58d47d5..0bf82c1e23f5 100644 --- a/test cases/failing/95 subdir parse error/test.json +++ b/test cases/failing/94 subdir parse error/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/95 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id." + "line": "test cases/failing/94 subdir parse error/subdir/meson.build:1:0: ERROR: Plusassignment target must be an id." } ] } diff --git a/test cases/failing/96 invalid option file/meson.build b/test cases/failing/95 invalid option file/meson.build similarity index 100% rename from test cases/failing/96 invalid option file/meson.build rename to test cases/failing/95 invalid option file/meson.build diff --git a/test cases/failing/96 invalid option file/meson_options.txt b/test cases/failing/95 invalid option file/meson_options.txt similarity index 100% rename from test cases/failing/96 invalid option file/meson_options.txt rename to test cases/failing/95 invalid option file/meson_options.txt diff --git a/test cases/failing/96 invalid option file/test.json b/test cases/failing/95 invalid option file/test.json similarity index 50% rename from test cases/failing/96 invalid option file/test.json rename to test cases/failing/95 invalid option file/test.json index 5f1a89f7ced1..073ac67177af 100644 --- a/test cases/failing/96 invalid option file/test.json +++ b/test cases/failing/95 invalid option file/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/96 invalid option file/meson_options.txt:1:0: ERROR: lexer" + "line": "test cases/failing/95 invalid option file/meson_options.txt:1:0: ERROR: lexer" } ] } diff --git a/test cases/failing/97 no lang/main.c b/test cases/failing/96 no lang/main.c similarity index 100% rename from test cases/failing/97 no lang/main.c rename to test cases/failing/96 no lang/main.c diff --git a/test cases/failing/97 no lang/meson.build b/test cases/failing/96 no lang/meson.build similarity index 100% rename from test cases/failing/97 no lang/meson.build rename to test cases/failing/96 no lang/meson.build diff --git a/test cases/failing/97 no lang/test.json b/test cases/failing/96 no lang/test.json similarity index 54% rename from test cases/failing/97 no lang/test.json rename to test cases/failing/96 no lang/test.json index a2af0a1970b9..ab4ca5cdf144 100644 --- a/test cases/failing/97 no lang/test.json +++ b/test cases/failing/96 no lang/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/97 no lang/meson.build:2:0: ERROR: No host machine compiler for 'main.c'" + "line": "test cases/failing/96 no lang/meson.build:2:0: ERROR: No host machine compiler for 'main.c'" } ] } diff --git a/test cases/failing/98 no glib-compile-resources/meson.build b/test cases/failing/97 no glib-compile-resources/meson.build similarity index 100% rename from test cases/failing/98 no glib-compile-resources/meson.build rename to test cases/failing/97 no glib-compile-resources/meson.build diff --git a/test cases/failing/98 no glib-compile-resources/test.json b/test cases/failing/97 no glib-compile-resources/test.json similarity index 65% rename from test cases/failing/98 no glib-compile-resources/test.json rename to test cases/failing/97 no glib-compile-resources/test.json index d5edd7692da2..f3d92ddfbd17 100644 --- a/test cases/failing/98 no glib-compile-resources/test.json +++ b/test cases/failing/97 no glib-compile-resources/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/98 no glib-compile-resources/meson.build:8:12: ERROR: Program 'glib-compile-resources' not found or not executable" + "line": "test cases/failing/97 no glib-compile-resources/meson.build:8:12: ERROR: Program 'glib-compile-resources' not found or not executable" } ] } diff --git a/test cases/failing/98 no glib-compile-resources/trivial.gresource.xml b/test cases/failing/97 no glib-compile-resources/trivial.gresource.xml similarity index 100% rename from test cases/failing/98 no glib-compile-resources/trivial.gresource.xml rename to test cases/failing/97 no glib-compile-resources/trivial.gresource.xml diff --git a/test cases/failing/99 number in combo/meson.build b/test cases/failing/98 number in combo/meson.build similarity index 100% rename from test cases/failing/99 number in combo/meson.build rename to test cases/failing/98 number in combo/meson.build diff --git a/test cases/failing/99 number in combo/nativefile.ini b/test cases/failing/98 number in combo/nativefile.ini similarity index 100% rename from test cases/failing/99 number in combo/nativefile.ini rename to test cases/failing/98 number in combo/nativefile.ini diff --git a/test cases/failing/99 number in combo/test.json b/test cases/failing/98 number in combo/test.json similarity index 77% rename from test cases/failing/99 number in combo/test.json rename to test cases/failing/98 number in combo/test.json index f59812e3bcda..ecac6676d96b 100644 --- a/test cases/failing/99 number in combo/test.json +++ b/test cases/failing/98 number in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/99 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + { "line": "test cases/failing/98 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } ] } diff --git a/test cases/failing/100 bool in combo/meson.build b/test cases/failing/99 bool in combo/meson.build similarity index 100% rename from test cases/failing/100 bool in combo/meson.build rename to test cases/failing/99 bool in combo/meson.build diff --git a/test cases/failing/100 bool in combo/meson_options.txt b/test cases/failing/99 bool in combo/meson_options.txt similarity index 100% rename from test cases/failing/100 bool in combo/meson_options.txt rename to test cases/failing/99 bool in combo/meson_options.txt diff --git a/test cases/failing/100 bool in combo/nativefile.ini b/test cases/failing/99 bool in combo/nativefile.ini similarity index 100% rename from test cases/failing/100 bool in combo/nativefile.ini rename to test cases/failing/99 bool in combo/nativefile.ini diff --git a/test cases/failing/99 bool in combo/test.json b/test cases/failing/99 bool in combo/test.json new file mode 100644 index 000000000000..364dde8a4099 --- /dev/null +++ b/test cases/failing/99 bool in combo/test.json @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/99 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + ] +} diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 1064e6adb34d..2475b17f91e0 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -2317,9 +2317,9 @@ def test_error_location_path(self): for (t, f) in [ ('10 out of bounds', 'meson.build'), ('18 wrong plusassign', 'meson.build'), - ('57 bad option argument', 'meson_options.txt'), - ('95 subdir parse error', os.path.join('subdir', 'meson.build')), - ('96 invalid option file', 'meson_options.txt'), + ('56 bad option argument', 'meson_options.txt'), + ('94 subdir parse error', os.path.join('subdir', 'meson.build')), + ('95 invalid option file', 'meson_options.txt'), ]: tdir = os.path.join(self.src_root, 'test cases', 'failing', t) From d532c79d9c2412a0e80bba3073578ff7b5e56b86 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 3 Mar 2024 23:34:21 +0200 Subject: [PATCH 690/855] 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 8bd483759c20..0221faad13df 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "February 2024" "meson 1.4.0" "User Commands" +.TH MESON "1" "March 2024" "meson 1.4.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e7de3d7fde32..bb155d033dcc 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -70,7 +70,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.4.0.rc1' +version = '1.4.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 8357548ca06ef3679a95b43af737a259407f7cc2 Mon Sep 17 00:00:00 2001 From: LIU Hao Date: Mon, 4 Mar 2024 23:47:38 +0800 Subject: [PATCH 691/855] doc/Users: Add asteria and mcfgthread --- docs/markdown/Users.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 6edbdf560b87..b28e4d635eb4 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -19,6 +19,7 @@ topic](https://github.com/topics/meson). - [Akira](https://github.com/akiraux/Akira), a native Linux app for UI and UX design built in Vala and Gtk - [AQEMU](https://github.com/tobimensch/aqemu), a Qt GUI for QEMU virtual machines, since version 0.9.3 - [Arduino sample project](https://github.com/jpakkane/mesonarduino) + - [Asteria](https://github.com/lhmouse/asteria), another scripting language - [Audacious](https://github.com/audacious-media-player), a lightweight and versatile audio player - [bolt](https://gitlab.freedesktop.org/bolt/bolt), userspace daemon to enable security levels for Thunderbolt™ 3 on Linux - [bsdutils](https://github.com/dcantrell/bsdutils), alternative to GNU coreutils using software from FreeBSD @@ -109,6 +110,7 @@ format files - [Libzim](https://github.com/openzim/libzim), the reference implementation for the ZIM file format - [LXC](https://github.com/lxc/lxc), Linux container runtime - [Marker](https://github.com/fabiocolacio/Marker), a GTK-3 markdown editor + - [mcfgthread](https://github.com/lhmouse/mcfgthread), cornerstone library for C++11 threading on mingw-w64 - [Mesa](https://mesa3d.org/), an open source graphics driver project - [Miniz](https://github.com/richgel999/miniz), a zlib replacement library - [MiracleCast](https://github.com/albfan/miraclecast), connect external monitors to your system via WiFi-Display specification aka Miracast From a9d42a7c1e567fb18f835c9f352c0b0efad8391b Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 1 Mar 2024 19:09:33 +0100 Subject: [PATCH 692/855] test cases/common/103 has header symbol: fix for musl 1.2.5 musl 1.2.5 exposes this symbol in the default profile, and in future will expose it unconditionally, as it is on track to becoming part of POSIX. So rather than maintaining a list of systems to run this on, let's just skip testing the feature test macro if we find ppoll in the default profile. --- test cases/common/103 has header symbol/meson.build | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test cases/common/103 has header symbol/meson.build b/test cases/common/103 has header symbol/meson.build index 459049100fbd..4f493e8409e3 100644 --- a/test cases/common/103 has header symbol/meson.build +++ b/test cases/common/103 has header symbol/meson.build @@ -18,10 +18,8 @@ foreach comp : [cc, cpp] assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') endforeach -# This is available on Glibc, Solaris & the BSD's, so just test for _GNU_SOURCE -# on Linux -if cc.has_function('ppoll') and host_machine.system() == 'linux' - assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') +# Glibc requires _GNU_SOURCE for ppoll. Other libcs do not. +if cc.has_function('ppoll') and not cc.has_header_symbol('poll.h', 'ppoll') assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') endif From 5e0a3073dad6ec4c4bdbccb755338f01b805fe53 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 4 Mar 2024 16:01:04 -0500 Subject: [PATCH 693/855] rust: Link with rlib external dependencies When linking with a Rust rlib, we should also link with its external system dependencies. This was currently done only for C ABI crates, do it for both rlib and staticlib now. --- mesonbuild/backend/ninjabackend.py | 5 ++--- test cases/rust/24 system deps/main.rs | 5 +++++ test cases/rust/24 system deps/meson.build | 9 +++++++++ test cases/rust/24 system deps/wrapper.rs | 9 +++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 test cases/rust/24 system deps/main.rs create mode 100644 test cases/rust/24 system deps/meson.build create mode 100644 test cases/rust/24 system deps/wrapper.rs diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 74994d0fd943..f665e610adc6 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1979,6 +1979,8 @@ def _link_library(libname: str, static: bool, bundle: bool = False): for d in target_deps: linkdirs.add(d.subdir) deps.append(self.get_dependency_filename(d)) + if isinstance(d, build.StaticLibrary): + external_deps.extend(d.external_deps) if d.uses_rust_abi(): if d not in itertools.chain(target.link_targets, target.link_whole_targets): # Indirect Rust ABI dependency, we only need its path in linkdirs. @@ -1993,9 +1995,6 @@ def _link_library(libname: str, static: bool, bundle: bool = False): # Link a C ABI library - if isinstance(d, build.StaticLibrary): - external_deps.extend(d.external_deps) - # Pass native libraries directly to the linker with "-C link-arg" # because rustc's "-l:+verbatim=" is not portable and we cannot rely # on linker to find the right library without using verbatim filename. diff --git a/test cases/rust/24 system deps/main.rs b/test cases/rust/24 system deps/main.rs new file mode 100644 index 000000000000..cfa599ba6686 --- /dev/null +++ b/test cases/rust/24 system deps/main.rs @@ -0,0 +1,5 @@ +extern crate wrapper; + +fn main() { + wrapper::func(); +} diff --git a/test cases/rust/24 system deps/meson.build b/test cases/rust/24 system deps/meson.build new file mode 100644 index 000000000000..d9160f108079 --- /dev/null +++ b/test cases/rust/24 system deps/meson.build @@ -0,0 +1,9 @@ +project('system deps', 'rust') + +glib = dependency('glib-2.0', required: false) +if not glib.found() + error('MESON_SKIP_TEST: Need glib system dependency') +endif + +rlib = static_library('wrapper', 'wrapper.rs', dependencies: glib) +exe = executable('main', 'main.rs', link_with: rlib) diff --git a/test cases/rust/24 system deps/wrapper.rs b/test cases/rust/24 system deps/wrapper.rs new file mode 100644 index 000000000000..630cd7791118 --- /dev/null +++ b/test cases/rust/24 system deps/wrapper.rs @@ -0,0 +1,9 @@ +extern "C" { + fn g_hash_table_new() -> *mut std::ffi::c_void; +} + +pub fn func() { + unsafe { + g_hash_table_new(); + } +} From 0cd74c96f1b58fe89ef9565ab40905d04538d7ed Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 6 Mar 2024 15:49:42 +0100 Subject: [PATCH 694/855] cuda: respect host compiler `-Werror` The cuda compiler also executes the host compiler and generally needs to know the host compiler flags. We did this for regular args but not for error args. We use `-Xcompiler=` since that's how nvcc tells the difference between args it uses itself for device code and args it passes to the host compiler. Signed-off-by: Eli Schwartz [eli: fix quoting style] --- mesonbuild/compilers/cuda.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 0e2d9457850e..e17ba3f5fc2c 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -199,6 +199,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ level: self._to_host_flags(list(f for f in flags if f != '-Wpedantic')) for level, flags in host_compiler.warn_args.items() } + self.host_werror_args = ['-Xcompiler=' + x for x in self.host_compiler.get_werror_args()] @classmethod def _shield_nvcc_list_arg(cls, arg: str, listmode: bool = True) -> str: @@ -708,7 +709,8 @@ def get_debug_args(self, is_debug: bool) -> T.List[str]: return cuda_debug_args[is_debug] def get_werror_args(self) -> T.List[str]: - return ['-Werror=cross-execution-space-call,deprecated-declarations,reorder'] + device_werror_args = ['-Werror=cross-execution-space-call,deprecated-declarations,reorder'] + return device_werror_args + self.host_werror_args def get_warn_args(self, level: str) -> T.List[str]: return self.warn_args[level] From 9e270f030f3016be2a419b698b8062e5ed5373b8 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 6 Mar 2024 07:26:25 -0500 Subject: [PATCH 695/855] Fix detection of unknown base options in subproj cc4cfbcad92945a1629c80664e1eb755c68905dd added detection for unknown base options, but it was not working for subproject base options. This should fix it. --- mesonbuild/coredata.py | 2 +- test cases/unit/122 reconfigure base options/meson.build | 2 ++ .../122 reconfigure base options/subprojects/sub/meson.build | 5 +++++ unittests/platformagnostictests.py | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 test cases/unit/122 reconfigure base options/subprojects/sub/meson.build diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index bb155d033dcc..f2ea879935f7 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1009,7 +1009,7 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], # adding languages and setting backend. if k.type in {OptionType.COMPILER, OptionType.BACKEND}: continue - if k.type == OptionType.BASE and k in base_options: + if k.type == OptionType.BASE and k.as_root() in base_options: # set_options will report unknown base options continue options[k] = v diff --git a/test cases/unit/122 reconfigure base options/meson.build b/test cases/unit/122 reconfigure base options/meson.build index 67e83d1e490b..8a13b78b2cc8 100644 --- a/test cases/unit/122 reconfigure base options/meson.build +++ b/test cases/unit/122 reconfigure base options/meson.build @@ -1,5 +1,7 @@ project('reconfigure', 'c', default_options: ['c_std=c89']) +subproject('sub') + message('b_ndebug: ' + get_option('b_ndebug')) message('c_std: ' + get_option('c_std')) diff --git a/test cases/unit/122 reconfigure base options/subprojects/sub/meson.build b/test cases/unit/122 reconfigure base options/subprojects/sub/meson.build new file mode 100644 index 000000000000..ba740d1cae90 --- /dev/null +++ b/test cases/unit/122 reconfigure base options/subprojects/sub/meson.build @@ -0,0 +1,5 @@ +project('sub', 'c', +default_options: ['c_std=c89']) + +message('b_ndebug: ' + get_option('b_ndebug')) +message('c_std: ' + get_option('c_std')) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 21cb3b94563c..a6db173411f1 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -282,7 +282,7 @@ def test_reconfigure_base_options(self): self.assertIn('\nMessage: b_ndebug: true\n', out) self.assertIn('\nMessage: c_std: c89\n', out) - out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dc_std=c99']) + out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99']) self.assertIn('\nMessage: b_ndebug: if-release\n', out) self.assertIn('\nMessage: c_std: c99\n', out) From f9479787a01106235e14d2a08a74352f4b1177ef Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Wed, 6 Mar 2024 14:10:08 -0500 Subject: [PATCH 696/855] fix reconfigure subproject base options --- mesonbuild/ast/introspection.py | 4 +-- mesonbuild/compilers/detect.py | 4 +-- mesonbuild/coredata.py | 44 +++++++++++++++++++-------- mesonbuild/interpreter/interpreter.py | 6 ++-- mesonbuild/modules/java.py | 2 +- run_project_tests.py | 2 +- unittests/allplatformstests.py | 14 ++++----- unittests/platformagnostictests.py | 4 ++- 8 files changed, 51 insertions(+), 29 deletions(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index f9a6e11c0eb4..046c0a2b69fd 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -170,7 +170,7 @@ def _add_languages(self, raw_langs: T.List[TYPE_var], required: bool, for_machin lang = lang.lower() if lang not in self.coredata.compilers[for_machine]: try: - comp = detect_compiler_for(self.environment, lang, for_machine, True) + comp = detect_compiler_for(self.environment, lang, for_machine, True, self.subproject) except mesonlib.MesonException: # do we even care about introspecting this language? if required: @@ -183,7 +183,7 @@ def _add_languages(self, raw_langs: T.List[TYPE_var], required: bool, for_machin v = copy.copy(self.coredata.options[k]) k = k.evolve(subproject=self.subproject) options[k] = v - self.coredata.add_compiler_options(options, lang, for_machine, self.environment) + self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject) def func_dependency(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str, TYPE_var]) -> None: args = self.flatten_args(args) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index dbc2b4879208..c117c22bbd7b 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -101,12 +101,12 @@ def compiler_from_language(env: 'Environment', lang: str, for_machine: MachineCh } return lang_map[lang](env, for_machine) if lang in lang_map else None -def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool) -> T.Optional[Compiler]: +def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoice, skip_sanity_check: bool, subproject: str) -> T.Optional[Compiler]: comp = compiler_from_language(env, lang, for_machine) if comp is None: return comp assert comp.for_machine == for_machine - env.coredata.process_compiler_options(lang, comp, env) + env.coredata.process_compiler_options(lang, comp, env, subproject) if not skip_sanity_check: comp.sanity_check(env.get_scratch_dir(), env) env.coredata.compilers[comp.for_machine][lang] = comp diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index f2ea879935f7..fa70cfc3cff2 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1016,15 +1016,24 @@ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], self.set_options(options, subproject=subproject, first_invocation=env.first_invocation) - def add_compiler_options(self, options: 'MutableKeyedOptionDictType', lang: str, for_machine: MachineChoice, - env: 'Environment') -> None: + def add_compiler_options(self, options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice, + env: Environment, subproject: str) -> None: for k, o in options.items(): value = env.options.get(k) if value is not None: o.set_value(value) - self.options[k] = o # override compiler option on reconfigure + if not subproject: + self.options[k] = o # override compiler option on reconfigure self.options.setdefault(k, o) + if subproject: + sk = k.evolve(subproject=subproject) + value = env.options.get(sk) or value + if value is not None: + o.set_value(value) + self.options[sk] = o # override compiler option on reconfigure + self.options.setdefault(sk, o) + def add_lang_args(self, lang: str, comp: T.Type['Compiler'], for_machine: MachineChoice, env: 'Environment') -> None: """Add global language arguments that are needed before compiler/linker detection.""" @@ -1034,20 +1043,31 @@ def add_lang_args(self, lang: str, comp: T.Type['Compiler'], # `self.options.update()`` is perfectly safe. self.options.update(compilers.get_global_options(lang, comp, for_machine, env)) - def process_compiler_options(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: + def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None: from . import compilers - self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env) + self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env, subproject) enabled_opts: T.List[OptionKey] = [] for key in comp.base_options: - if key not in self.options: - self.options[key] = copy.deepcopy(compilers.base_options[key]) - if key in env.options: - self.options[key].set_value(env.options[key]) - enabled_opts.append(key) - elif key in env.options: - self.options[key].set_value(env.options[key]) + if subproject: + skey = key.evolve(subproject=subproject) + else: + skey = key + if skey not in self.options: + self.options[skey] = copy.deepcopy(compilers.base_options[key]) + if skey in env.options: + self.options[skey].set_value(env.options[skey]) + enabled_opts.append(skey) + elif subproject and key in env.options: + self.options[skey].set_value(env.options[key]) + enabled_opts.append(skey) + if subproject and key not in self.options: + self.options[key] = copy.deepcopy(self.options[skey]) + elif skey in env.options: + self.options[skey].set_value(env.options[skey]) + elif subproject and key in env.options: + self.options[skey].set_value(env.options[key]) self.emit_base_options_warnings(enabled_opts) def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index e5a201e053e4..47d0d2d2d5d3 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1506,7 +1506,7 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach skip_sanity_check = self.should_skip_sanity_check(for_machine) if skip_sanity_check: mlog.log('Cross compiler sanity tests disabled via the cross file.', once=True) - comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check) + comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check, self.subproject) if comp is None: raise InvalidArguments(f'Tried to use unknown language "{lang}".') except mesonlib.MesonException: @@ -1520,7 +1520,7 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach raise else: # update new values from commandline, if it applies - self.coredata.process_compiler_options(lang, comp, self.environment) + self.coredata.process_compiler_options(lang, comp, self.environment, self.subproject) # Add per-subproject compiler options. They inherit value from main project. if self.subproject: @@ -1529,7 +1529,7 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach v = copy.copy(self.coredata.options[k]) k = k.evolve(subproject=self.subproject) options[k] = v - self.coredata.add_compiler_options(options, lang, for_machine, self.environment) + self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject) if for_machine == MachineChoice.HOST or self.environment.is_cross_build(): logger_fun = mlog.log diff --git a/mesonbuild/modules/java.py b/mesonbuild/modules/java.py index 56611ade26c6..abef4acdfffa 100644 --- a/mesonbuild/modules/java.py +++ b/mesonbuild/modules/java.py @@ -32,7 +32,7 @@ def __init__(self, interpreter: Interpreter): def __get_java_compiler(self, state: ModuleState) -> Compiler: if 'java' not in state.environment.coredata.compilers[MachineChoice.BUILD]: - detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False) + detect_compiler_for(state.environment, 'java', MachineChoice.BUILD, False, state.subproject) return state.environment.coredata.compilers[MachineChoice.BUILD]['java'] @FeatureNew('java.generate_native_headers', '0.62.0') diff --git a/run_project_tests.py b/run_project_tests.py index 6fc9cb7f77fa..a14741364aab 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -981,7 +981,7 @@ def have_working_compiler(lang: str, use_tmp: bool) -> bool: return False if not compiler: return False - env.coredata.process_compiler_options(lang, compiler, env) + env.coredata.process_compiler_options(lang, compiler, env, '') try: compiler.sanity_check(env.get_scratch_dir(), env) except mesonlib.MesonException: diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 2475b17f91e0..0e563758798c 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -944,7 +944,7 @@ def test_build_generated_pyx_directly(self): testdir = os.path.join("test cases/cython", '2 generated sources') env = get_fake_env(testdir, self.builddir, self.prefix) try: - detect_compiler_for(env, "cython", MachineChoice.HOST, True) + detect_compiler_for(env, "cython", MachineChoice.HOST, True, '') except EnvironmentException: raise SkipTest("Cython is not installed") self.init(testdir) @@ -969,7 +969,7 @@ def test_build_pyx_depfiles(self): testdir = os.path.join("test cases/cython", '2 generated sources') env = get_fake_env(testdir, self.builddir, self.prefix) try: - cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True) + cython = detect_compiler_for(env, "cython", MachineChoice.HOST, True, '') if not version_compare(cython.version, '>=0.29.33'): raise SkipTest('Cython is too old') except EnvironmentException: @@ -2355,7 +2355,7 @@ def test_templates(self): env = get_fake_env() for l in ['cpp', 'cs', 'd', 'java', 'cuda', 'fortran', 'objc', 'objcpp', 'rust', 'vala']: try: - comp = detect_compiler_for(env, l, MachineChoice.HOST, True) + comp = detect_compiler_for(env, l, MachineChoice.HOST, True, '') with tempfile.TemporaryDirectory() as d: comp.sanity_check(d, env) langs.append(l) @@ -2373,7 +2373,7 @@ def test_templates(self): if is_windows() and lang == 'fortran' and target_type == 'library': # non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way # see "test cases/fortran/6 dynamic" - fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True) + fc = detect_compiler_for(env, 'fortran', MachineChoice.HOST, True, '') if fc.get_id() in {'intel-cl', 'pgi'}: continue # test empty directory @@ -4433,18 +4433,18 @@ def test_env_flags_to_linker(self) -> None: env = get_fake_env() # Get the compiler so we know which compiler class to mock. - cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '') cc_type = type(cc) # Test a compiler that acts as a linker with mock.patch.object(cc_type, 'INVOKES_LINKER', True): - cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '') link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) self.assertEqual(sorted(link_args), sorted(['-DCFLAG', '-flto'])) # And one that doesn't with mock.patch.object(cc_type, 'INVOKES_LINKER', False): - cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True) + cc = detect_compiler_for(env, 'c', MachineChoice.HOST, True, '') link_args = env.coredata.get_external_link_args(cc.for_machine, cc.language) self.assertEqual(sorted(link_args), sorted(['-flto'])) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index a6db173411f1..b75a78052b06 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -282,9 +282,11 @@ def test_reconfigure_base_options(self): self.assertIn('\nMessage: b_ndebug: true\n', out) self.assertIn('\nMessage: c_std: c89\n', out) - out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99']) + out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99', '-Dsub:c_std=c11']) self.assertIn('\nMessage: b_ndebug: if-release\n', out) self.assertIn('\nMessage: c_std: c99\n', out) + self.assertIn('\nsub| Message: b_ndebug: false\n', out) + self.assertIn('\nsub| Message: c_std: c11\n', out) def test_setup_with_unknown_option(self): testdir = os.path.join(self.common_test_dir, '1 trivial') From 675c323b194c098fe95ab0be4635eb1c6a5fa5e3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 10:09:16 -0800 Subject: [PATCH 697/855] CI: pin mypy to version 1.8 Version 1.9 removes support for python 3.7, so we either need to pin the version to 1.8 as long as we're support Python 3.7, or we need to drop linting for 3.7 --- .github/workflows/lint.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 58860bd8c300..e8cd37341762 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -46,7 +46,8 @@ jobs: - uses: actions/setup-python@v4 with: python-version: '3.x' - - run: python -m pip install mypy coverage strictyaml types-PyYAML types-tqdm types-chevron + # Pin mypy to version 1.8, so we retain the ability to lint for Python 3.7 + - run: python -m pip install "mypy==1.8" coverage strictyaml types-PyYAML types-tqdm types-chevron - run: python run_mypy.py --allver env: PYTHONUNBUFFERED: 1 From e4622ff1eebec393531d731cafa71334f900f121 Mon Sep 17 00:00:00 2001 From: Elliot <35050275+apache-hb@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:23:33 -0400 Subject: [PATCH 698/855] Only link to generated pch object when using msvc. (#12957) backend: Only link to generated pch object when using msvc --- mesonbuild/backend/ninjabackend.py | 5 ++++- mesonbuild/compilers/compilers.py | 3 +++ mesonbuild/compilers/mixins/visualstudio.py | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f665e610adc6..f7ba6468a495 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3121,7 +3121,10 @@ def generate_msvc_pch_command(self, target, compiler, pch): commands += self._generate_single_compile(target, compiler) commands += self.get_compile_debugfile_args(compiler, target, objname) dep = dst + '.' + compiler.get_depfile_suffix() - return commands, dep, dst, [objname], source + + link_objects = [objname] if compiler.should_link_pch_object() else [] + + return commands, dep, dst, link_objects, source def generate_gcc_pch_command(self, target, compiler, pch): commands = self._generate_single_compile(target, compiler) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index b59733745806..8bc1294f8ae7 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -843,6 +843,9 @@ def get_colorout_args(self, colortype: str) -> T.List[str]: def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: return [] + def should_link_pch_object(self) -> bool: + return False + def get_link_debugfile_name(self, targetfile: str) -> T.Optional[str]: return self.linker.get_debugfile_name(targetfile) diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 5dcebecef8ec..d6ebd6e0d3ab 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -425,6 +425,10 @@ def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[st def get_pch_base_name(self, header: str) -> str: return os.path.basename(header) + # MSVC requires linking to the generated object file when linking a build target + # that uses a precompiled header + def should_link_pch_object(self) -> bool: + return True class ClangClCompiler(VisualStudioLikeCompiler): From eaefe29463a61a311a6b1de6cd539f39500399ff Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 12 Mar 2024 19:57:31 +0200 Subject: [PATCH 699/855] Bump version number for release. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index fa70cfc3cff2..a112f7cc51ba 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -70,7 +70,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.4.0.rc2' +version = '1.4.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 7399be4ab263f7729e0f516aba3bbfea07aa593d Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 12 Mar 2024 20:33:47 +0200 Subject: [PATCH 700/855] Bump version number for new development. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a112f7cc51ba..bb481cae9128 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -70,7 +70,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.4.0' +version = '1.4.99' # 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 eb74bb8dbf74ac22a02e369b6622ee0ef8b5d6a3 Mon Sep 17 00:00:00 2001 From: Petr Machacek Date: Tue, 12 Sep 2023 09:11:50 +0200 Subject: [PATCH 701/855] Added support for Texas Instruments C6000 compiler. --- cross/ti-c6000.txt | 22 +++++++++++ docs/markdown/Reference-tables.md | 3 ++ .../snippets/ti_c6000_compiler_support.md | 4 ++ mesonbuild/build.py | 4 +- mesonbuild/compilers/c.py | 3 ++ mesonbuild/compilers/cpp.py | 3 ++ mesonbuild/compilers/detect.py | 38 ++++++++++++------- mesonbuild/compilers/mixins/clike.py | 4 ++ mesonbuild/envconfig.py | 1 + mesonbuild/linkers/linkers.py | 6 +++ 10 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 cross/ti-c6000.txt create mode 100644 docs/markdown/snippets/ti_c6000_compiler_support.md diff --git a/cross/ti-c6000.txt b/cross/ti-c6000.txt new file mode 100644 index 000000000000..f9361cfeacae --- /dev/null +++ b/cross/ti-c6000.txt @@ -0,0 +1,22 @@ +# Cross file tested on Texas Instruments C6000 compiler (bare metal DSP devices) +# This file assumes that path to the Texas Instruments C6000 toolchain is added +# to the environment(PATH) variable. + +[host_machine] +system = 'c6000' +cpu_family = 'c6000' +cpu = 'c64x' +endian = 'little' + +[binaries] +c = 'cl6x' +cpp = 'cl6x' +ar = 'ar6x' +strip = 'strip6x' +nm = 'nm6x' +as = 'asm6x' + +[properties] +needs_exe_wrapper = true +has_function_printf = true +bits = 32 diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 02ac083e50b1..d30d22a50096 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -37,6 +37,7 @@ These are return values of the `get_id` (Compiler family) and | rustc | Rust compiler | | | sun | Sun Fortran compiler | | | c2000 | Texas Instruments C/C++ Compiler (C2000) | | +| c6000 | Texas Instruments C/C++ Compiler (C6000) | | | ti | Texas Instruments C/C++ Compiler | | | valac | Vala compiler | | | xc16 | Microchip XC16 C compiler | | @@ -70,6 +71,7 @@ These are return values of the `get_linker_id` method in a compiler object. | xc16-ar | The Microchip linker, used with XC16 only | | ar2000 | The Texas Instruments linker, used with C2000 only | | ti-ar | The Texas Instruments linker | +| ar6000 | The Texas Instruments linker, used with C6000 only | | armlink | The ARM linker (arm and armclang compilers) | | pgi | Portland/Nvidia PGI | | nvlink | Nvidia Linker used with cuda | @@ -105,6 +107,7 @@ set in the cross file. | arm | 32 bit ARM processor | | avr | Atmel AVR processor | | c2000 | 32 bit C2000 processor | +| c6000 | 32 bit C6000 processor | | csky | 32 bit CSky processor | | dspic | 16 bit Microchip dsPIC | | e2k | MCST Elbrus processor | diff --git a/docs/markdown/snippets/ti_c6000_compiler_support.md b/docs/markdown/snippets/ti_c6000_compiler_support.md new file mode 100644 index 000000000000..03533e6091cd --- /dev/null +++ b/docs/markdown/snippets/ti_c6000_compiler_support.md @@ -0,0 +1,4 @@ +## 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/mesonbuild/build.py b/mesonbuild/build.py index 3c9d3a06c699..2b6ce8875f17 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1976,8 +1976,8 @@ def post_init(self) -> None: self.suffix = 'abs' elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('xc16')): self.suffix = 'elf' - elif ('c' in self.compilers and self.compilers['c'].get_id() in {'ti', 'c2000'} or - 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'ti', 'c2000'}): + elif ('c' in self.compilers and self.compilers['c'].get_id() in {'ti', 'c2000', 'c6000'} or + 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'ti', 'c2000', 'c6000'}): self.suffix = 'out' elif ('c' in self.compilers and self.compilers['c'].get_id() in {'mwccarm', 'mwcceppc'} or 'cpp' in self.compilers and self.compilers['cpp'].get_id() in {'mwccarm', 'mwcceppc'}): diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index a943552e1958..8c76a2147f0e 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -735,6 +735,9 @@ class C2000CCompiler(TICCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' +class C6000CCompiler(TICCompiler): + id = 'c6000' + class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): id = 'mwccarm' diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 0ff89a3eae61..c5c2735ad6f6 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -960,6 +960,9 @@ class C2000CPPCompiler(TICPPCompiler): # Required for backwards compat with projects created before ti-cgt support existed id = 'c2000' +class C6000CPPCompiler(TICPPCompiler): + id = 'c6000' + class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): id = 'mwccarm' diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index c117c22bbd7b..f047242ca31b 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -198,6 +198,8 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker if any(os.path.basename(x) in {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'} for x in linker): arg = '/?' + elif linker_name in {'ar2000', 'ar2000.exe', 'ar430', 'ar430.exe', 'armar', 'armar.exe', 'ar6x', 'ar6x.exe'}: + arg = '?' else: arg = '--version' try: @@ -231,6 +233,9 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker return linkers.C2000Linker(linker) else: return linkers.TILinker(linker) + if 'Texas Instruments Incorporated' in out: + if 'ar6000' in linker_name: + return linkers.C6000Linker(linker) if out.startswith('The CompCert'): return linkers.CompCertLinker(linker) if out.strip().startswith('Metrowerks') or out.strip().startswith('Freescale'): @@ -308,7 +313,7 @@ def sanitize(p: str) -> str: arg = '--version' elif 'ccomp' in compiler_name: arg = '-version' - elif compiler_name in {'cl2000', 'cl2000.exe', 'cl430', 'cl430.exe', 'armcl', 'armcl.exe'}: + elif compiler_name in {'cl2000', 'cl2000.exe', 'cl430', 'cl430.exe', 'armcl', 'armcl.exe', 'cl6x', 'cl6x.exe'}: # TI compiler arg = '-version' elif compiler_name in {'icl', 'icl.exe'}: @@ -428,6 +433,24 @@ def sanitize(p: str) -> str: return cls( compiler, version, for_machine, is_cross, info, target, exe_wrap, linker=linker) + + # must be detected here before clang because TI compilers contain 'clang' in their output and so that they can be detected as 'clang' + ti_compilers = { + 'TMS320C2000 C/C++': (c.C2000CCompiler, cpp.C2000CPPCompiler, linkers.C2000DynamicLinker), + 'TMS320C6x C/C++': (c.C6000CCompiler, cpp.C6000CPPCompiler, linkers.C6000DynamicLinker), + 'TI ARM C/C++ Compiler': (c.TICCompiler, cpp.TICPPCompiler, linkers.TIDynamicLinker), + 'MSP430 C/C++': (c.TICCompiler, cpp.TICPPCompiler, linkers.TIDynamicLinker) + } + for indentifier, compiler_classes in ti_compilers.items(): + if indentifier in out: + cls = compiler_classes[0] if lang == 'c' else compiler_classes[1] + lnk = compiler_classes[2] + env.coredata.add_lang_args(cls.language, cls, for_machine, env) + linker = lnk(compiler, for_machine, version=version) + return cls( + ccache, compiler, version, for_machine, is_cross, info, + exe_wrap, full_version=full_version, linker=linker) + if 'clang' in out or 'Clang' in out: linker = None @@ -525,19 +548,6 @@ def sanitize(p: str) -> str: return cls( ccache, compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=l) - if 'TMS320C2000 C/C++' in out or 'MSP430 C/C++' in out or 'TI ARM C/C++ Compiler' in out: - if 'TMS320C2000 C/C++' in out: - cls = c.C2000CCompiler if lang == 'c' else cpp.C2000CPPCompiler - lnk = linkers.C2000DynamicLinker - else: - cls = c.TICCompiler if lang == 'c' else cpp.TICPPCompiler - lnk = linkers.TIDynamicLinker - - env.coredata.add_lang_args(cls.language, cls, for_machine, env) - linker = lnk(compiler, for_machine, version=version) - return cls( - ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) if 'ARM' in out and not ('Metrowerks' in out or 'Freescale' in out): cls = c.ArmCCompiler if lang == 'c' else cpp.ArmCPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 25feb5c3866c..5e6adedcf459 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1052,6 +1052,10 @@ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool elif env.machines[self.for_machine].is_cygwin(): shlibext = ['dll', 'dll.a'] prefixes = ['cyg'] + prefixes + elif self.id.lower() == 'c6000' or self.id.lower() == 'ti': + # TI C6000 compiler can use both extensions for static or dynamic libs. + stlibext = ['a', 'lib'] + shlibext = ['dll', 'so'] else: # Linux/BSDs shlibext = ['so'] diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 0e9cd23cc736..86bad9be23ee 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -34,6 +34,7 @@ 'arm', 'avr', 'c2000', + 'c6000', 'csky', 'dspic', 'e2k', diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 2048268193a5..657e3618bbd5 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -492,6 +492,9 @@ class C2000Linker(TILinker): # Required for backwards compat with projects created before ti-cgt support existed id = 'ar2000' +class C6000Linker(TILinker): + id = 'ar6000' + class AIXArLinker(ArLikeLinker, StaticLinker): id = 'aixar' @@ -1094,6 +1097,9 @@ class C2000DynamicLinker(TIDynamicLinker): # Required for backwards compat with projects created before ti-cgt support existed id = 'cl2000' +class C6000DynamicLinker(TIDynamicLinker): + id = 'cl6000' + class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): From 675b47b0692131fae974298829ba807d730ab098 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 12 Mar 2024 23:35:48 +0000 Subject: [PATCH 702/855] compilers: cpp: improve libc++ vs libstdc++ detection (again) The previous approach wasn't great because you couldn't control what the detected C++ stdlib impl was. We just had a preference list we tweaked the searched order for per OS. That doesn't work great for e.g. Gentoo with libc++ or Gentoo Prefix on macOS where we might be using libstdc++ even though the host is libc++. Jonathan Wakely, the libstdc++ maintainer, gave a helpful answer on how to best detect libc++ vs libstdc++ via macros on SO [0]. Implement it. TL;DR: Use from C++20 if we can, use otherwise. Check for _LIBCPP_VERSION as libstdc++ doesn't always define a macro. [0] https://stackoverflow.com/a/31658120 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index c5c2735ad6f6..fdf632a8c858 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -203,17 +203,14 @@ def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: machine = env.machines[self.for_machine] assert machine is not None, 'for mypy' - # We need to determine whether to use libc++ or libstdc++. We can't - # really know the answer in most cases, only the most likely answer, - # because a user can install things themselves or build custom images. - search_order: T.List[str] = [] - if machine.system in {'android', 'darwin', 'dragonfly', 'freebsd', 'netbsd', 'openbsd'}: - search_order = ['c++', 'stdc++'] - else: - search_order = ['stdc++', 'c++'] - for lib in search_order: - if self.find_library(lib, env, []) is not None: - return search_dirs + [f'-l{lib}'] + # https://stackoverflow.com/a/31658120 + header = 'version' if self.has_header('', '', env) else 'ciso646' + is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env)[0] + lib = 'c++' if is_libcxx else 'stdc++' + + if self.find_library(lib, env, []) is not None: + return search_dirs + [f'-l{lib}'] + # TODO: maybe a bug exception? raise MesonException('Could not detect either libc++ or libstdc++ as your C++ stdlib implementation.') From fd626e345a0e0f25eead718aa08586554244349d Mon Sep 17 00:00:00 2001 From: William Toohey Date: Mon, 20 Feb 2023 15:57:27 +1000 Subject: [PATCH 703/855] Basic support for TI ARM-CLANG toolchain --- docs/markdown/snippets/ti_armclang.md | 3 +++ mesonbuild/linkers/detect.py | 2 +- mesonbuild/linkers/linkers.py | 27 ++++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 docs/markdown/snippets/ti_armclang.md diff --git a/docs/markdown/snippets/ti_armclang.md b/docs/markdown/snippets/ti_armclang.md new file mode 100644 index 000000000000..7f0f912c0ed8 --- /dev/null +++ b/docs/markdown/snippets/ti_armclang.md @@ -0,0 +1,3 @@ +## 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/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 1bce413f4f52..15ce6cb69930 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -138,7 +138,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty v = search_version(o + e) linker: DynamicLinker - if 'LLD' in o.split('\n', maxsplit=1)[0]: + if 'LLD' in o.split('\n', maxsplit=1)[0] or 'tiarmlnk' in e: if isinstance(comp_class.LINKER_PREFIX, str): cmd = compiler + override + [comp_class.LINKER_PREFIX + '-v'] + extra_args else: diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 657e3618bbd5..ca98d017752f 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -885,15 +885,36 @@ def __init__(self, exelist: T.List[str], super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) # Some targets don't seem to support this argument (windows, wasm, ...) - _, _, e = mesonlib.Popen_safe(self.exelist + always_args + self._apply_prefix('--allow-shlib-undefined')) - # Versions < 9 do not have a quoted argument - self.has_allow_shlib_undefined = ('unknown argument: --allow-shlib-undefined' not in e) and ("unknown argument: '--allow-shlib-undefined'" not in e) + self.has_allow_shlib_undefined = self._supports_flag('--allow-shlib-undefined', always_args) + # These aren't supported by TI Arm Clang + self.has_as_needed = self._supports_flag('--as-needed', always_args) + self.has_no_undefined = self._supports_flag('--no-undefined', always_args) + + def _supports_flag(self, flag: str, always_args: T.List[str]) -> bool: + _, _, e = mesonlib.Popen_safe(self.exelist + always_args + self._apply_prefix(flag)) + return ( + # Versions < 9 do not have a quoted argument + (f'unknown argument: {flag}' not in e) and + (f"unknown argument: '{flag}'" not in e) and + # TI Arm Clang uses a different message + (f'invalid option: {flag}' not in e) + ) def get_allow_undefined_args(self) -> T.List[str]: if self.has_allow_shlib_undefined: return self._apply_prefix('--allow-shlib-undefined') return [] + def get_asneeded_args(self) -> T.List[str]: + if self.has_as_needed: + return self._apply_prefix('--as-needed') + return [] + + def no_undefined_args(self) -> T.List[str]: + if self.has_no_undefined: + return self._apply_prefix('--no-undefined') + return [] + def get_thinlto_cache_args(self, path: str) -> T.List[str]: return ['-Wl,--thinlto-cache-dir=' + path] From 0b7b4a3d9e41901b000074e903ad0bb8a299785c Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 13 Mar 2024 21:20:29 +0200 Subject: [PATCH 704/855] Generate relnotes for 1.4.0. --- docs/markdown/Release-notes-for-1.4.0.md | 111 ++++++++++++++++++ .../additional_types_for_fs_module.md | 9 -- .../snippets/cmake-project-version.md | 6 - docs/markdown/snippets/cpp-debug.md | 10 -- docs/markdown/snippets/cpp-stldebug.md | 4 - docs/markdown/snippets/environment_unset.md | 4 - docs/markdown/snippets/file-full-path.md | 7 -- .../snippets/numpy-custom-dependency.md | 9 -- docs/markdown/snippets/preprocess-depends.md | 5 - .../snippets/qt_preserve_path_from.md | 10 -- docs/markdown/snippets/rust-bindgen-cpp.md | 6 - .../snippets/rust-bindgen-language.md | 5 - docs/markdown/snippets/rust-bindgen-std.md | 3 - docs/markdown/snippets/sanitizers_test.md | 6 - .../test_using_custom_target_executable.md | 4 - docs/sitemap.txt | 1 + 16 files changed, 112 insertions(+), 88 deletions(-) create mode 100644 docs/markdown/Release-notes-for-1.4.0.md delete mode 100644 docs/markdown/snippets/additional_types_for_fs_module.md delete mode 100644 docs/markdown/snippets/cmake-project-version.md delete mode 100644 docs/markdown/snippets/cpp-debug.md delete mode 100644 docs/markdown/snippets/cpp-stldebug.md delete mode 100644 docs/markdown/snippets/environment_unset.md delete mode 100644 docs/markdown/snippets/file-full-path.md delete mode 100644 docs/markdown/snippets/numpy-custom-dependency.md delete mode 100644 docs/markdown/snippets/preprocess-depends.md delete mode 100644 docs/markdown/snippets/qt_preserve_path_from.md delete mode 100644 docs/markdown/snippets/rust-bindgen-cpp.md delete mode 100644 docs/markdown/snippets/rust-bindgen-language.md delete mode 100644 docs/markdown/snippets/rust-bindgen-std.md delete mode 100644 docs/markdown/snippets/sanitizers_test.md delete mode 100644 docs/markdown/snippets/test_using_custom_target_executable.md diff --git a/docs/markdown/Release-notes-for-1.4.0.md b/docs/markdown/Release-notes-for-1.4.0.md new file mode 100644 index 000000000000..12dc3a8986e5 --- /dev/null +++ b/docs/markdown/Release-notes-for-1.4.0.md @@ -0,0 +1,111 @@ +--- +title: Release 1.4.0 +short-description: Release notes for 1.4.0 +... + +# New features + +Meson 1.4.0 was released on 12 March 2024 + +## Added support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` to certain FS module functions + +Support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` was +added to the following FS module APIs: + +- `fs.name` +- `fs.parent` +- `fs.replace_suffix` +- `fs.stem` + +## Meson now reads the project version of cmake subprojects + +CMake subprojects configured by meson will now have their project +version set to the project version in their CMakeLists.txt. This +allows version constraints to be properly checked when falling back to +a cmake subproject. + +## `ndebug` setting now controls C++ stdlib assertions + +The `ndebug` setting, if disabled, now passes preprocessor defines to enable +debugging assertions within the C++ standard library. + +For GCC, `-D_GLIBCXX_ASSERTIONS=1` is set. + +For Clang, `-D_GLIBCXX_ASSERTIONS=1` is set to cover libstdc++ usage, +and `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` or +`-D_LIBCPP_ENABLE_ASSERTIONS=1` is used depending on the Clang version. + +## `stldebug` gains Clang support + +For Clang, we now pass `-D_GLIBCXX_DEBUG=1` if `debugstl` is enabled, and +we also pass `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG`. + +## New `unset()` method on `environment` objects + +[[@env]] now has an [[env.unset]] method to ensure an existing environment +is *not* defined. + +## File object now has `full_path()` method + +Returns a full path pointing to the file. This is useful for printing the path +with e.g [[message]] function for debugging purpose. + +**NOTE:** In most cases using the object itself will do the same job +as this and will also allow Meson to setup dependencies correctly. + +## New numpy custom dependency + +Support for `dependency('numpy')` was added, via supporting the `numpy-config` tool and +pkg-config support, both of which are available since NumPy 2.0.0. + +Config-tool support is useful because it will work out of the box when +``numpy`` is installed, while the pkg-config file is located inside python's +site-packages, which makes it impossible to use in an out of the box manner +without setting `PKG_CONFIG_PATH`. + +## `depends` kwarg now supported by compiler.preprocess() + +It is now possible to specify the dependent targets with `depends:` +for compiler.preprocess(). These targets should be built before the +preprocessing starts. + +## Added `preserve_paths` keyword argument to qt module functions. + +In `qt4`, `qt5`, and `qt6` modules, `compile_ui`, `compile_moc`, and +`preprocess` functions now have a `preserve_paths` keyword argument. + +If `'true`, it specifies that the output files need to maintain their directory +structure inside the target temporary directory. For instance, when a file +called `subdir/one.input` is processed it generates a file +`{target private directory}/subdir/one.out` when `true`, +and `{target private directory}/one.out` when `false` (default). + +## Bindgen will now use Meson's heuristic for what is a C++ header + +Bindgen natively assumes that a file with the extension `.hpp` is a C++ header, +but that everything else is a C header. Meson has a whole list of extensions it +considers to be C++, and now will automatically look for those extensions and +set bindgen to treat those as C++ + +## Overriding bindgen language setting + +Even though Meson will now tell bindgen to do the right thing in most cases, +there may still be cases where Meson does not have the intended behavior, +specifically with headers with a `.h` suffix, but are C++ headers. + +## Bindgen now uses the same C/C++ std as the project as a whole + +Which is very important for C++ bindings. + +## Tests now abort on errors by default under more sanitizers + +Sanitizers like MemorySanitizer do not abort +by default on detected violations. Meson now exports `MSAN_OPTIONS` (in addition to +`ASAN_OPTIONS` and `UBSAN_OPTIONS` from a previous release) when unset in the +environment to provide sensible abort-by-default behavior. + +## Use `custom_target` as test executable + +The [[test]] function now accepts [[@custom_tgt]] and [[@custom_idx]] for the +command to execute. + diff --git a/docs/markdown/snippets/additional_types_for_fs_module.md b/docs/markdown/snippets/additional_types_for_fs_module.md deleted file mode 100644 index 86f2de9f438a..000000000000 --- a/docs/markdown/snippets/additional_types_for_fs_module.md +++ /dev/null @@ -1,9 +0,0 @@ -## Added support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` to certain FS module functions - -Support for `[[@build_tgt]]`, `[[@custom_tgt]]`, and `[[@custom_idx]]` was -added to the following FS module APIs: - -- `fs.name` -- `fs.parent` -- `fs.replace_suffix` -- `fs.stem` diff --git a/docs/markdown/snippets/cmake-project-version.md b/docs/markdown/snippets/cmake-project-version.md deleted file mode 100644 index 0bc120b9febe..000000000000 --- a/docs/markdown/snippets/cmake-project-version.md +++ /dev/null @@ -1,6 +0,0 @@ -## Meson now reads the project version of cmake subprojects - -CMake subprojects configured by meson will now have their project -version set to the project version in their CMakeLists.txt. This -allows version constraints to be properly checked when falling back to -a cmake subproject. diff --git a/docs/markdown/snippets/cpp-debug.md b/docs/markdown/snippets/cpp-debug.md deleted file mode 100644 index 2a62b93994b4..000000000000 --- a/docs/markdown/snippets/cpp-debug.md +++ /dev/null @@ -1,10 +0,0 @@ -## `ndebug` setting now controls C++ stdlib assertions - -The `ndebug` setting, if disabled, now passes preprocessor defines to enable -debugging assertions within the C++ standard library. - -For GCC, `-D_GLIBCXX_ASSERTIONS=1` is set. - -For Clang, `-D_GLIBCXX_ASSERTIONS=1` is set to cover libstdc++ usage, -and `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` or -`-D_LIBCPP_ENABLE_ASSERTIONS=1` is used depending on the Clang version. diff --git a/docs/markdown/snippets/cpp-stldebug.md b/docs/markdown/snippets/cpp-stldebug.md deleted file mode 100644 index ba0473608c8a..000000000000 --- a/docs/markdown/snippets/cpp-stldebug.md +++ /dev/null @@ -1,4 +0,0 @@ -## `stldebug` gains Clang support - -For Clang, we now pass `-D_GLIBCXX_DEBUG=1` if `debugstl` is enabled, and -we also pass `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG`. diff --git a/docs/markdown/snippets/environment_unset.md b/docs/markdown/snippets/environment_unset.md deleted file mode 100644 index 887bc0d47cab..000000000000 --- a/docs/markdown/snippets/environment_unset.md +++ /dev/null @@ -1,4 +0,0 @@ -## New `unset()` method on `environment` objects - -[[@env]] now has an [[env.unset]] method to ensure an existing environment -is *not* defined. diff --git a/docs/markdown/snippets/file-full-path.md b/docs/markdown/snippets/file-full-path.md deleted file mode 100644 index fbb8e548d80d..000000000000 --- a/docs/markdown/snippets/file-full-path.md +++ /dev/null @@ -1,7 +0,0 @@ -## File object now has `full_path()` method - -Returns a full path pointing to the file. This is useful for printing the path -with e.g [[message]] function for debugging purpose. - -**NOTE:** In most cases using the object itself will do the same job -as this and will also allow Meson to setup dependencies correctly. diff --git a/docs/markdown/snippets/numpy-custom-dependency.md b/docs/markdown/snippets/numpy-custom-dependency.md deleted file mode 100644 index 5934180c001b..000000000000 --- a/docs/markdown/snippets/numpy-custom-dependency.md +++ /dev/null @@ -1,9 +0,0 @@ -## New numpy custom dependency - -Support for `dependency('numpy')` was added, via supporting the `numpy-config` tool and -pkg-config support, both of which are available since NumPy 2.0.0. - -Config-tool support is useful because it will work out of the box when -``numpy`` is installed, while the pkg-config file is located inside python's -site-packages, which makes it impossible to use in an out of the box manner -without setting `PKG_CONFIG_PATH`. diff --git a/docs/markdown/snippets/preprocess-depends.md b/docs/markdown/snippets/preprocess-depends.md deleted file mode 100644 index 531246462c1b..000000000000 --- a/docs/markdown/snippets/preprocess-depends.md +++ /dev/null @@ -1,5 +0,0 @@ -## `depends` kwarg now supported by compiler.preprocess() - -It is now possible to specify the dependent targets with `depends:` -for compiler.preprocess(). These targets should be built before the -preprocessing starts. diff --git a/docs/markdown/snippets/qt_preserve_path_from.md b/docs/markdown/snippets/qt_preserve_path_from.md deleted file mode 100644 index 1a0923a72a05..000000000000 --- a/docs/markdown/snippets/qt_preserve_path_from.md +++ /dev/null @@ -1,10 +0,0 @@ -## Added `preserve_paths` keyword argument to qt module functions. - -In `qt4`, `qt5`, and `qt6` modules, `compile_ui`, `compile_moc`, and -`preprocess` functions now have a `preserve_paths` keyword argument. - -If `'true`, it specifies that the output files need to maintain their directory -structure inside the target temporary directory. For instance, when a file -called `subdir/one.input` is processed it generates a file -`{target private directory}/subdir/one.out` when `true`, -and `{target private directory}/one.out` when `false` (default). diff --git a/docs/markdown/snippets/rust-bindgen-cpp.md b/docs/markdown/snippets/rust-bindgen-cpp.md deleted file mode 100644 index bcb1feac2040..000000000000 --- a/docs/markdown/snippets/rust-bindgen-cpp.md +++ /dev/null @@ -1,6 +0,0 @@ -## Bindgen will now use Meson's heuristic for what is a C++ header - -Bindgen natively assumes that a file with the extension `.hpp` is a C++ header, -but that everything else is a C header. Meson has a whole list of extensions it -considers to be C++, and now will automatically look for those extensions and -set bindgen to treat those as C++ diff --git a/docs/markdown/snippets/rust-bindgen-language.md b/docs/markdown/snippets/rust-bindgen-language.md deleted file mode 100644 index edfb3bfb4b87..000000000000 --- a/docs/markdown/snippets/rust-bindgen-language.md +++ /dev/null @@ -1,5 +0,0 @@ -## Overriding bindgen language setting - -Even though Meson will now tell bindgen to do the right thing in most cases, -there may still be cases where Meson does not have the intended behavior, -specifically with headers with a `.h` suffix, but are C++ headers. diff --git a/docs/markdown/snippets/rust-bindgen-std.md b/docs/markdown/snippets/rust-bindgen-std.md deleted file mode 100644 index 34ae611fc434..000000000000 --- a/docs/markdown/snippets/rust-bindgen-std.md +++ /dev/null @@ -1,3 +0,0 @@ -## Bindgen now uses the same C/C++ std as the project as a whole - -Which is very important for C++ bindings. diff --git a/docs/markdown/snippets/sanitizers_test.md b/docs/markdown/snippets/sanitizers_test.md deleted file mode 100644 index de9385253dc0..000000000000 --- a/docs/markdown/snippets/sanitizers_test.md +++ /dev/null @@ -1,6 +0,0 @@ -## Tests now abort on errors by default under more sanitizers - -Sanitizers like MemorySanitizer do not abort -by default on detected violations. Meson now exports `MSAN_OPTIONS` (in addition to -`ASAN_OPTIONS` and `UBSAN_OPTIONS` from a previous release) when unset in the -environment to provide sensible abort-by-default behavior. diff --git a/docs/markdown/snippets/test_using_custom_target_executable.md b/docs/markdown/snippets/test_using_custom_target_executable.md deleted file mode 100644 index e8b08da6b2fe..000000000000 --- a/docs/markdown/snippets/test_using_custom_target_executable.md +++ /dev/null @@ -1,4 +0,0 @@ -## Use `custom_target` as test executable - -The [[test]] function now accepts [[@custom_tgt]] and [[@custom_idx]] for the -command to execute. diff --git a/docs/sitemap.txt b/docs/sitemap.txt index 5eb2284eb3ce..04f7fdae344f 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.4.0.md Release-notes-for-1.3.0.md Release-notes-for-1.2.0.md Release-notes-for-1.1.0.md From bc91eb581407fec0aaf798782823121479b95276 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 14 Mar 2024 08:30:53 +0100 Subject: [PATCH 705/855] interpreterobjects.py: fix a typo Use a capital letter at the beginning of a sentence. --- mesonbuild/interpreter/interpreterobjects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 28e7170c9b2c..5f712a57348f 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -379,7 +379,7 @@ def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.C # We already have typed_pos_args checking that this is either a bool or # an int. if not isinstance(args[1], bool): - mlog.deprecation('configuration_data.set10 with number. the `set10` ' + mlog.deprecation('configuration_data.set10 with number. The `set10` ' 'method should only be used with booleans', location=self.interpreter.current_node) if args[1] < 0: From 3f73aaed2da61808ba84dc992ae9e5d109b18196 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 11 Oct 2023 16:37:58 -0400 Subject: [PATCH 706/855] cargo: Ensure Dependency.package always has a value --- mesonbuild/cargo/interpreter.py | 39 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 3cbc453ef73c..a919563e088c 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -151,6 +151,7 @@ class Dependency: """Representation of a Cargo Dependency Entry.""" + name: dataclasses.InitVar[str] version: T.List[str] registry: T.Optional[str] = None git: T.Optional[str] = None @@ -158,16 +159,19 @@ class Dependency: rev: T.Optional[str] = None path: T.Optional[str] = None optional: bool = False - package: T.Optional[str] = None + package: str = '' default_features: bool = True features: T.List[str] = dataclasses.field(default_factory=list) + def __post_init__(self, name: str) -> None: + self.package = self.package or name + @classmethod - def from_raw(cls, raw: manifest.DependencyV) -> Dependency: + def from_raw(cls, name: str, raw: manifest.DependencyV) -> Dependency: """Create a dependency from a raw cargo dictionary""" if isinstance(raw, str): - return cls(version.convert(raw)) - return cls(**_fixup_raw_mappings(raw)) + return cls(name, version.convert(raw)) + return cls(name, **_fixup_raw_mappings(raw)) @dataclasses.dataclass @@ -290,16 +294,16 @@ def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = return Manifest( Package(**pkg), - {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dependencies', {}).items()}, - {k: Dependency.from_raw(v) for k, v in raw_manifest.get('dev-dependencies', {}).items()}, - {k: Dependency.from_raw(v) for k, v in raw_manifest.get('build-dependencies', {}).items()}, + {k: Dependency.from_raw(k, v) for k, v in raw_manifest.get('dependencies', {}).items()}, + {k: Dependency.from_raw(k, v) for k, v in raw_manifest.get('dev-dependencies', {}).items()}, + {k: Dependency.from_raw(k, v) for k, v in raw_manifest.get('build-dependencies', {}).items()}, Library(**lib), [Binary(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bin', {})], [Test(**_fixup_raw_mappings(b)) for b in raw_manifest.get('test', {})], [Benchmark(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bench', {})], [Example(**_fixup_raw_mappings(b)) for b in raw_manifest.get('example', {})], raw_manifest.get('features', {}), - {k: {k2: Dependency.from_raw(v2) for k2, v2 in v.get('dependencies', {}).items()} + {k: {k2: Dependency.from_raw(k2, v2) for k2, v2 in v.get('dependencies', {}).items()} for k, v in raw_manifest.get('target', {}).items()}, subdir, path, @@ -480,8 +484,6 @@ def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser. def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]: ast: T.List[mparser.BaseNode] = [] for name, dep in cargo.dependencies.items(): - package_name = dep.package or name - # xxx_options += {'feature-default': true, ...} extra_options: T.Dict[mparser.BaseNode, mparser.BaseNode] = { build.string(_option_name('default')): build.bool(dep.default_features), @@ -515,20 +517,20 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.assign( build.function( 'dependency', - [build.string(_dependency_name(package_name))], + [build.string(_dependency_name(dep.package))], kw, ), - _dependency_varname(package_name), + _dependency_varname(dep.package), ), # if xxx_dep.found() - build.if_(build.method('found', build.identifier(_dependency_varname(package_name))), build.block([ + build.if_(build.method('found', build.identifier(_dependency_varname(dep.package))), build.block([ # actual_features = xxx_dep.get_variable('features', default_value : '').split(',') build.assign( build.method( 'split', build.method( 'get_variable', - build.identifier(_dependency_varname(package_name)), + build.identifier(_dependency_varname(dep.package)), [build.string('features')], {'default_value': build.string('')} ), @@ -557,7 +559,7 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.if_(build.not_in(build.identifier('f'), build.identifier('actual_features')), build.block([ build.function('error', [ build.string('Dependency'), - build.string(_dependency_name(package_name)), + build.string(_dependency_name(dep.package)), build.string('previously configured with features'), build.identifier('actual_features'), build.string('but need'), @@ -593,10 +595,9 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR dependencies: T.List[mparser.BaseNode] = [] dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {} for name, dep in cargo.dependencies.items(): - package_name = dep.package or name - dependencies.append(build.identifier(_dependency_varname(package_name))) - if name != package_name: - dependency_map[build.string(fixup_meson_varname(package_name))] = build.string(name) + dependencies.append(build.identifier(_dependency_varname(dep.package))) + if name != dep.package: + dependency_map[build.string(fixup_meson_varname(dep.package))] = build.string(name) rust_args: T.List[mparser.BaseNode] = [ build.identifier('features_args'), From 4d3fb88753c4a501adf04111cf8b3c1adfdd9b0c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 11 Oct 2023 16:41:19 -0400 Subject: [PATCH 707/855] cargo: Add API version into dependency name --- .../markdown/Wrap-dependency-system-manual.md | 41 ++++++++++++------- docs/markdown/snippets/cargo_dep_name.md | 19 +++++++++ mesonbuild/cargo/interpreter.py | 40 +++++++++++++++--- .../rust/22 cargo subproject/meson.build | 2 +- .../{bar-rs.wrap => bar-0.1-rs.wrap} | 0 .../{bar-rs => bar-0.1-rs}/Cargo.toml | 0 .../{bar-rs => bar-0.1-rs}/src/lib.rs | 0 .../{extra-dep-rs => extra-dep-1-rs}/lib.c | 0 .../meson.build | 2 +- .../meson_options.txt | 0 .../{foo-rs.wrap => foo-0-rs.wrap} | 0 .../{foo-rs => foo-0-rs}/Cargo.toml | 0 .../subprojects/{foo-rs => foo-0-rs}/lib.rs | 0 .../{foo-rs => foo-0-rs}/meson/meson.build | 0 14 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 docs/markdown/snippets/cargo_dep_name.md rename test cases/rust/22 cargo subproject/subprojects/{bar-rs.wrap => bar-0.1-rs.wrap} (100%) rename test cases/rust/22 cargo subproject/subprojects/{bar-rs => bar-0.1-rs}/Cargo.toml (100%) rename test cases/rust/22 cargo subproject/subprojects/{bar-rs => bar-0.1-rs}/src/lib.rs (100%) rename test cases/rust/22 cargo subproject/subprojects/{extra-dep-rs => extra-dep-1-rs}/lib.c (100%) rename test cases/rust/22 cargo subproject/subprojects/{extra-dep-rs => extra-dep-1-rs}/meson.build (82%) rename test cases/rust/22 cargo subproject/subprojects/{extra-dep-rs => extra-dep-1-rs}/meson_options.txt (100%) rename test cases/rust/22 cargo subproject/subprojects/{foo-rs.wrap => foo-0-rs.wrap} (100%) rename test cases/rust/22 cargo subproject/subprojects/{foo-rs => foo-0-rs}/Cargo.toml (100%) rename test cases/rust/22 cargo subproject/subprojects/{foo-rs => foo-0-rs}/lib.rs (100%) rename test cases/rust/22 cargo subproject/subprojects/{foo-rs => foo-0-rs}/meson/meson.build (100%) diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md index bba1971c4950..5f0b473e7a2b 100644 --- a/docs/markdown/Wrap-dependency-system-manual.md +++ b/docs/markdown/Wrap-dependency-system-manual.md @@ -316,11 +316,24 @@ foo-bar-1.0 = foo_bar_dep ``` ### Cargo wraps -Cargo subprojects automatically override the `-rs` dependency name. -`package_name` is defined in `[package] name = ...` section of the `Cargo.toml` -and `-rs` suffix is added. That means the `.wrap` file should have -`dependency_names = foo-rs` in their `[provide]` section when `Cargo.toml` has -package name `foo`. +Cargo subprojects automatically override the `--rs` dependency +name: +- `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`. + +Note that the version component was added in Meson 1.4, previous versions were +using `-rs` format. Cargo subprojects require a toml parser. Python >= 3.11 have one built-in, older Python versions require either the external `tomli` module or `toml2json` program. @@ -332,26 +345,26 @@ file like that: ... method = cargo [provide] -dependency_names = foo-bar-rs +dependency_names = foo-bar-0.1-rs ``` Cargo features are exposed as Meson boolean options, with the `feature-` prefix. For example the `default` feature is named `feature-default` and can be set from -the command line with `-Dfoo-rs:feature-default=false`. When a cargo subproject +the command line with `-Dfoo-1-rs:feature-default=false`. When a cargo subproject depends on another cargo subproject, it will automatically enable features it -needs using the `dependency('foo-rs', default_options: ...)` mechanism. However, +needs using the `dependency('foo-1-rs', default_options: ...)` mechanism. However, unlike Cargo, the set of enabled features is not managed globally. Let's assume -the main project depends on `foo-rs` and `bar-rs`, and they both depend on -`common-rs`. The main project will first look up `foo-rs` which itself will -configure `common-rs` with a set of features. Later, when `bar-rs` does a lookup -for `common-rs` it has already been configured and the set of features cannot be -changed. If `bar-rs` wants extra features from `common-rs`, Meson will error out. +the main project depends on `foo-1-rs` and `bar-1-rs`, and they both depend on +`common-1-rs`. The main project will first look up `foo-1-rs` which itself will +configure `common-rs` with a set of features. Later, when `bar-1-rs` does a lookup +for `common-1-rs` it has already been configured and the set of features cannot be +changed. If `bar-1-rs` wants extra features from `common-1-rs`, Meson will error out. It is currently the responsability of the main project to resolve those issues by enabling extra features on each subproject: ```meson project(..., default_options: { - 'common-rs:feature-something': true, + 'common-1-rs:feature-something': true, }, ) ``` diff --git a/docs/markdown/snippets/cargo_dep_name.md b/docs/markdown/snippets/cargo_dep_name.md new file mode 100644 index 000000000000..b769f2b9034f --- /dev/null +++ b/docs/markdown/snippets/cargo_dep_name.md @@ -0,0 +1,19 @@ +## 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/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index a919563e088c..f1ed23953850 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -162,9 +162,23 @@ class Dependency: package: str = '' default_features: bool = True features: T.List[str] = dataclasses.field(default_factory=list) + api: str = dataclasses.field(init=False) def __post_init__(self, name: str) -> None: self.package = self.package or name + # Extract wanted API version from version constraints. + api = set() + for v in self.version: + if v.startswith(('>=', '==')): + api.add(_version_to_api(v[2:].strip())) + elif v.startswith('='): + api.add(_version_to_api(v[1:].strip())) + if not api: + self.api = '0' + elif len(api) == 1: + self.api = api.pop() + else: + raise MesonException(f'Cannot determine minimum API version from {self.version}.') @classmethod def from_raw(cls, name: str, raw: manifest.DependencyV) -> Dependency: @@ -351,8 +365,21 @@ def _load_manifests(subdir: str) -> T.Dict[str, Manifest]: return manifests -def _dependency_name(package_name: str) -> str: - return package_name if package_name.endswith('-rs') else f'{package_name}-rs' +def _version_to_api(version: str) -> str: + # x.y.z -> x + # 0.x.y -> 0.x + # 0.0.x -> 0 + vers = version.split('.') + if int(vers[0]) != 0: + return vers[0] + elif len(vers) >= 2 and int(vers[1]) != 0: + return f'0.{vers[1]}' + return '0' + + +def _dependency_name(package_name: str, api: str) -> str: + basename = package_name[:-3] if package_name.endswith('-rs') else package_name + return f'{basename}-{api}-rs' def _dependency_varname(package_name: str) -> str: @@ -517,7 +544,7 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.assign( build.function( 'dependency', - [build.string(_dependency_name(dep.package))], + [build.string(_dependency_name(dep.package, dep.api))], kw, ), _dependency_varname(dep.package), @@ -559,7 +586,7 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar build.if_(build.not_in(build.identifier('f'), build.identifier('actual_features')), build.block([ build.function('error', [ build.string('Dependency'), - build.string(_dependency_name(dep.package)), + build.string(_dependency_name(dep.package, dep.api)), build.string('previously configured with features'), build.identifier('actual_features'), build.string('but need'), @@ -666,7 +693,7 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR 'override_dependency', build.identifier('meson'), [ - build.string(_dependency_name(cargo.package.name)), + build.string(_dependency_name(cargo.package.name, _version_to_api(cargo.package.version))), build.identifier('dep'), ], ), @@ -674,7 +701,8 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.CodeBlockNode, KeyedOptionDictType]: - package_name = subp_name[:-3] if subp_name.endswith('-rs') else subp_name + # subp_name should be in the form "foo-0.1-rs" + package_name = subp_name.rsplit('-', 2)[0] manifests = _load_manifests(os.path.join(env.source_dir, subdir)) cargo = manifests.get(package_name) if not cargo: diff --git a/test cases/rust/22 cargo subproject/meson.build b/test cases/rust/22 cargo subproject/meson.build index 420e6e3b9ccf..1b60014c59e8 100644 --- a/test cases/rust/22 cargo subproject/meson.build +++ b/test cases/rust/22 cargo subproject/meson.build @@ -1,6 +1,6 @@ project('cargo subproject', 'c') -foo_dep = dependency('foo-rs') +foo_dep = dependency('foo-0-rs') exe = executable('app', 'main.c', dependencies: foo_dep, ) diff --git a/test cases/rust/22 cargo subproject/subprojects/bar-rs.wrap b/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs.wrap similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/bar-rs.wrap rename to test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs.wrap diff --git a/test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/bar-rs/Cargo.toml rename to test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml diff --git a/test cases/rust/22 cargo subproject/subprojects/bar-rs/src/lib.rs b/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/src/lib.rs similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/bar-rs/src/lib.rs rename to test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/src/lib.rs diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c b/test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/lib.c similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/lib.c rename to test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/lib.c diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build b/test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/meson.build similarity index 82% rename from test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build rename to test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/meson.build index 3ba7852cf018..40d109b2d0f8 100644 --- a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson.build +++ b/test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/meson.build @@ -7,4 +7,4 @@ d = declare_dependency(link_with: l, variables: { 'features': 'default', }) -meson.override_dependency('extra-dep-rs', d) +meson.override_dependency('extra-dep-1-rs', d) diff --git a/test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt b/test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/meson_options.txt similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/extra-dep-rs/meson_options.txt rename to test cases/rust/22 cargo subproject/subprojects/extra-dep-1-rs/meson_options.txt diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs.wrap b/test cases/rust/22 cargo subproject/subprojects/foo-0-rs.wrap similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/foo-rs.wrap rename to test cases/rust/22 cargo subproject/subprojects/foo-0-rs.wrap diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/foo-0-rs/Cargo.toml similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/foo-rs/Cargo.toml rename to test cases/rust/22 cargo subproject/subprojects/foo-0-rs/Cargo.toml diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/lib.rs b/test cases/rust/22 cargo subproject/subprojects/foo-0-rs/lib.rs similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/foo-rs/lib.rs rename to test cases/rust/22 cargo subproject/subprojects/foo-0-rs/lib.rs diff --git a/test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build b/test cases/rust/22 cargo subproject/subprojects/foo-0-rs/meson/meson.build similarity index 100% rename from test cases/rust/22 cargo subproject/subprojects/foo-rs/meson/meson.build rename to test cases/rust/22 cargo subproject/subprojects/foo-0-rs/meson/meson.build From 3afbe042afbdd48d73853b2087bb1d88a2afa753 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 13 Mar 2024 08:12:54 -0400 Subject: [PATCH 708/855] wayland: Stable protocols can have a version Fixes: #12968 --- .../snippets/wayland_stable_prot_version.md | 13 +++++++++++++ mesonbuild/modules/wayland.py | 16 ++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 docs/markdown/snippets/wayland_stable_prot_version.md diff --git a/docs/markdown/snippets/wayland_stable_prot_version.md b/docs/markdown/snippets/wayland_stable_prot_version.md new file mode 100644 index 000000000000..78d0a50d5c89 --- /dev/null +++ b/docs/markdown/snippets/wayland_stable_prot_version.md @@ -0,0 +1,13 @@ +## 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/mesonbuild/modules/wayland.py b/mesonbuild/modules/wayland.py index cab2ff453e23..e17cf995ced3 100644 --- a/mesonbuild/modules/wayland.py +++ b/mesonbuild/modules/wayland.py @@ -8,7 +8,7 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo from ..build import CustomTarget from ..interpreter.type_checking import NoneType, in_set_validator -from ..interpreterbase import typed_pos_args, typed_kwargs, KwargInfo +from ..interpreterbase import typed_pos_args, typed_kwargs, KwargInfo, FeatureNew from ..mesonlib import File, MesonException if T.TYPE_CHECKING: @@ -122,7 +122,7 @@ def find_protocol(self, state: ModuleState, args: T.Tuple[str], kwargs: FindProt raise MesonException(f'{xml_state} protocols require a version number.') if xml_state == 'stable' and version is not None: - raise MesonException('stable protocols do not require a version number.') + FeatureNew.single_use('Version number in stable wayland protocol', '1.5.0', state.subproject, location=state.current_node) if self.protocols_dep is None: self.protocols_dep = state.dependency('wayland-protocols') @@ -130,12 +130,12 @@ def find_protocol(self, state: ModuleState, args: T.Tuple[str], kwargs: FindProt if self.pkgdatadir is None: self.pkgdatadir = self.protocols_dep.get_variable(pkgconfig='pkgdatadir', internal='pkgdatadir') - if xml_state == 'stable': - xml_name = f'{base_name}.xml' - elif xml_state == 'staging': - xml_name = f'{base_name}-v{version}.xml' - else: - xml_name = f'{base_name}-unstable-v{version}.xml' + xml_name = base_name + if xml_state == 'unstable': + xml_name += '-unstable' + if version is not None: + xml_name += f'-v{version}' + xml_name += '.xml' path = os.path.join(self.pkgdatadir, xml_state, base_name, xml_name) From f41a95ddf28317abf9b58f913e1650a006c26c76 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 3 Nov 2023 15:12:24 -0400 Subject: [PATCH 709/855] compilers: Every compiler can run code Compiling and linking code is part of the Compiler base class, there is no reason it cannot also run executables. --- docs/markdown/snippets/compiler_run.md | 4 ++++ mesonbuild/compilers/compilers.py | 25 +++++++++++++++++++++++-- mesonbuild/compilers/d.py | 26 ++------------------------ mesonbuild/compilers/mixins/clike.py | 26 -------------------------- mesonbuild/interpreter/compiler.py | 3 +++ test cases/rust/1 basic/meson.build | 3 +++ 6 files changed, 35 insertions(+), 52 deletions(-) create mode 100644 docs/markdown/snippets/compiler_run.md diff --git a/docs/markdown/snippets/compiler_run.md b/docs/markdown/snippets/compiler_run.md new file mode 100644 index 000000000000..f4b0847a5dc4 --- /dev/null +++ b/docs/markdown/snippets/compiler_run.md @@ -0,0 +1,4 @@ +## 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/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 8bc1294f8ae7..faa147ad7d99 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -623,10 +623,31 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str, dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) - def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: - raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) + need_exe_wrapper = env.need_exe_wrapper(self.for_machine) + if need_exe_wrapper and self.exe_wrapper is None: + raise CrossNoRunException('Can not run test applications in this cross environment.') + with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p: + if p.returncode != 0: + mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') + return RunResult(False) + if need_exe_wrapper: + cmdlist = self.exe_wrapper.get_command() + [p.output_name] + else: + cmdlist = [p.output_name] + try: + pe, so, se = mesonlib.Popen_safe(cmdlist) + except Exception as e: + mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') + return RunResult(False) + + mlog.debug('Program stdout:\n') + mlog.debug(so) + mlog.debug('Program stderr:\n') + mlog.debug(se) + return RunResult(True, pe.returncode, so, se) # Caching run() in general seems too risky (no way to know what the program # depends on), but some callers know more about the programs they intend to diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 32f6d04ed8b8..0ebeef4be485 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -9,7 +9,6 @@ import typing as T from .. import mesonlib -from .. import mlog from ..arglist import CompilerArgs from ..linkers import RSPFileSyntax from ..mesonlib import ( @@ -571,32 +570,11 @@ def _get_compile_extra_args(self, extra_args: T.Union[T.List[str], T.Callable[[C args.append(extra_args) return args - def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + def run(self, code: 'mesonlib.FileOrString', env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: - need_exe_wrapper = env.need_exe_wrapper(self.for_machine) - if need_exe_wrapper and self.exe_wrapper is None: - raise compilers.CrossNoRunException('Can not run test applications in this cross environment.') extra_args = self._get_compile_extra_args(extra_args) - with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p: - if p.returncode != 0: - mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') - return compilers.RunResult(False) - if need_exe_wrapper: - cmdlist = self.exe_wrapper.get_command() + [p.output_name] - else: - cmdlist = [p.output_name] - try: - pe, so, se = mesonlib.Popen_safe(cmdlist) - except Exception as e: - mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') - return compilers.RunResult(False) - - mlog.debug('Program stdout:\n') - mlog.debug(so) - mlog.debug('Program stderr:\n') - mlog.debug(se) - return compilers.RunResult(True, pe.returncode, so, se) + return super().run(code, env, extra_args, dependencies) def sizeof(self, typename: str, prefix: str, env: 'Environment', *, extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 5e6adedcf459..eb3a4f150a3e 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -459,32 +459,6 @@ def build_wrapper_args(self, env: 'Environment', args = cargs + extra_args + largs return args - def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, - extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: - need_exe_wrapper = env.need_exe_wrapper(self.for_machine) - if need_exe_wrapper and self.exe_wrapper is None: - raise compilers.CrossNoRunException('Can not run test applications in this cross environment.') - with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p: - if p.returncode != 0: - mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') - return compilers.RunResult(False) - if need_exe_wrapper: - cmdlist = self.exe_wrapper.get_command() + [p.output_name] - else: - cmdlist = [p.output_name] - try: - pe, so, se = mesonlib.Popen_safe(cmdlist) - except Exception as e: - mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') - return compilers.RunResult(False) - - mlog.debug('Program stdout:\n') - mlog.debug(so) - mlog.debug('Program stderr:\n') - mlog.debug(se) - return compilers.RunResult(True, pe.returncode, so, se) - def _compile_int(self, expression: str, prefix: str, env: 'Environment', extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], dependencies: T.Optional[T.List['Dependency']]) -> bool: diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 0cd6aecf38aa..0f91ba1e0bbc 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -302,6 +302,9 @@ def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int: @typed_pos_args('compiler.run', (str, mesonlib.File)) @typed_kwargs('compiler.run', *_COMPILES_KWS) def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult': + if self.compiler.language not in {'d', 'c', 'cpp', 'objc', 'objcpp'}: + FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language', + '1.5.0', self.subproject, location=self.current_node) code = args[0] if isinstance(code, mesonlib.File): self.interpreter.add_build_def_file(code) diff --git a/test cases/rust/1 basic/meson.build b/test cases/rust/1 basic/meson.build index 3ba987710675..f422beb74857 100644 --- a/test cases/rust/1 basic/meson.build +++ b/test cases/rust/1 basic/meson.build @@ -18,3 +18,6 @@ test( ), should_fail : true, ) + +rustc = meson.get_compiler('rust') +assert(rustc.run('fn main(){}').returncode() == 0) From b1358ef61f12f86b900bfa8071ae24c8d3468845 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 6 Nov 2023 08:00:43 -0500 Subject: [PATCH 710/855] compilers: Do not dump File content in log for compiler checks. When doing a compiler check with a File object, there is no need to dump the file into logs, we can just print the path. The file could potentially be big. --- mesonbuild/compilers/compilers.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index faa147ad7d99..6b598622c9e6 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -789,14 +789,10 @@ def compile(self, code: 'mesonlib.FileOrString', ofile.write(code) # ccache would result in a cache miss no_ccache = True - contents = code + code_debug = f'Code:\n{code}' else: srcname = code.fname - if not is_object(code.fname): - with open(code.fname, encoding='utf-8') as f: - contents = f.read() - else: - contents = '' + code_debug = f'Source file: {srcname}' # Construct the compiler command-line commands = self.compiler_args() @@ -817,7 +813,7 @@ def compile(self, code: 'mesonlib.FileOrString', command_list = self.get_exelist(ccache=not no_ccache) + commands.to_native() mlog.debug('Running compile:') mlog.debug('Working directory: ', tmpdirname) - mlog.debug('Code:\n', contents) + mlog.debug(code_debug) os_env = os.environ.copy() os_env['LC_ALL'] = 'C' if no_ccache: From 6b569527bca9354be77769f91a0607cfd692d861 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 6 Nov 2023 08:07:07 -0500 Subject: [PATCH 711/855] compilers: Allow setting env and workdir for run checks This is not exposed in API, but will be used internally. --- mesonbuild/compilers/compilers.py | 6 ++++-- mesonbuild/compilers/d.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 6b598622c9e6..474c87eb5de0 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -625,7 +625,9 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str, def run(self, code: 'mesonlib.FileOrString', env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: + dependencies: T.Optional[T.List['Dependency']] = None, + run_env: T.Optional[T.Dict[str, str]] = None, + run_cwd: T.Optional[str] = None) -> RunResult: need_exe_wrapper = env.need_exe_wrapper(self.for_machine) if need_exe_wrapper and self.exe_wrapper is None: raise CrossNoRunException('Can not run test applications in this cross environment.') @@ -638,7 +640,7 @@ def run(self, code: 'mesonlib.FileOrString', env: 'Environment', else: cmdlist = [p.output_name] try: - pe, so, se = mesonlib.Popen_safe(cmdlist) + pe, so, se = mesonlib.Popen_safe(cmdlist, env=run_env, cwd=run_cwd) except Exception as e: mlog.debug(f'Could not run: {cmdlist} (error: {e})\n') return RunResult(False) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 0ebeef4be485..8425ae22ddc2 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -572,9 +572,11 @@ def _get_compile_extra_args(self, extra_args: T.Union[T.List[str], T.Callable[[C def run(self, code: 'mesonlib.FileOrString', env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: + dependencies: T.Optional[T.List['Dependency']] = None, + run_env: T.Optional[T.Dict[str, str]] = None, + run_cwd: T.Optional[str] = None) -> compilers.RunResult: extra_args = self._get_compile_extra_args(extra_args) - return super().run(code, env, extra_args, dependencies) + return super().run(code, env, extra_args, dependencies, run_env, run_cwd) def sizeof(self, typename: str, prefix: str, env: 'Environment', *, extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, From c1076241af11f10acac28d771688bb54c6b0b340 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 27 Nov 2023 15:47:16 -0500 Subject: [PATCH 712/855] compilers: No need to pass exe_wrapper everywhere Places where compiler needs it already have access to Environment object and can use it directly. This fixes mypy complaining that not all compilers have self.exe_wrapper in run() method that got moved to base class. --- mesonbuild/backend/backends.py | 7 +- mesonbuild/compilers/c.py | 67 +++++++---------- mesonbuild/compilers/compilers.py | 4 +- mesonbuild/compilers/cpp.py | 64 ++++++++-------- mesonbuild/compilers/cuda.py | 12 ++- mesonbuild/compilers/d.py | 18 ++--- mesonbuild/compilers/detect.py | 107 +++++++++++++-------------- mesonbuild/compilers/fortran.py | 48 ++++++------ mesonbuild/compilers/mixins/clike.py | 17 ++--- mesonbuild/compilers/objc.py | 10 +-- mesonbuild/compilers/objcpp.py | 10 +-- mesonbuild/compilers/rust.py | 9 +-- mesonbuild/environment.py | 3 + 13 files changed, 163 insertions(+), 213 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index c3be900ab4bf..af730f88ef22 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -568,13 +568,12 @@ def get_executable_serialisation( else: extra_paths = [] - is_cross_built = not self.environment.machines.matches_build_machine(exe_for_machine) - if is_cross_built and self.environment.need_exe_wrapper(): - exe_wrapper = self.environment.get_exe_wrapper() - if not exe_wrapper or not exe_wrapper.found(): + if self.environment.need_exe_wrapper(exe_for_machine): + 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.' raise MesonException(msg) + exe_wrapper = self.environment.get_exe_wrapper() else: if exe_cmd[0].endswith('.jar'): exe_cmd = ['java', '-jar'] + exe_cmd diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 8c76a2147f0e..048649a32ac8 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -39,7 +39,6 @@ from ..environment import Environment from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice - from ..programs import ExternalProgram from .compilers import CompileCheckMode CompilerMixinBase = Compiler @@ -61,13 +60,13 @@ def attribute_check_func(self, name: str) -> str: language = 'c' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): # If a child ObjC or CPP class has already set it, don't set it ourselves Compiler.__init__(self, ccache, exelist, version, for_machine, info, is_cross=is_cross, full_version=full_version, linker=linker) - CLikeCompiler.__init__(self, exe_wrapper) + CLikeCompiler.__init__(self) def get_no_stdinc_args(self) -> T.List[str]: return ['-nostdinc'] @@ -137,11 +136,11 @@ def get_options(self) -> 'MutableKeyedOptionDictType': class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): - CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, linker=linker, full_version=full_version) ClangCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -202,7 +201,7 @@ class EmscriptenCCompiler(EmscriptenMixin, ClangCCompiler): id = 'emscripten' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): @@ -211,7 +210,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ if not version_compare(version, '>=1.39.19'): raise MesonException('Meson requires Emscripten >= 1.39.19') ClangCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper=exe_wrapper, linker=linker, + info, linker=linker, defines=defines, full_version=full_version) @@ -221,11 +220,11 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler): ''' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ArmclangCompiler.__init__(self) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -260,11 +259,11 @@ class GnuCCompiler(GnuCompiler, CCompiler): _INVALID_PCH_VERSION = ">=3.4.0" def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): - CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, exe_wrapper, linker=linker, full_version=full_version) + CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, info, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall'] if version_compare(self.version, self._INVALID_PCH_VERSION): @@ -322,11 +321,11 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: class PGICCompiler(PGICompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) PGICompiler.__init__(self) @@ -335,22 +334,22 @@ class NvidiaHPC_CCompiler(PGICompiler, CCompiler): id = 'nvidia_hpc' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) PGICompiler.__init__(self) class ElbrusCCompiler(ElbrusCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ElbrusCompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -385,11 +384,11 @@ def has_function(self, funcname: str, prefix: str, env: 'Environment', *, class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) IntelGnuLikeCompiler.__init__(self) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3'] @@ -453,11 +452,10 @@ class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompi def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, + info, linker=linker, full_version=full_version) MSVCCompiler.__init__(self, target) @@ -487,11 +485,10 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMixin, CCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, [], exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, + info, linker=linker, full_version=full_version) ClangClCompiler.__init__(self, target) @@ -509,11 +506,10 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, [], exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, + info, linker=linker, full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) @@ -543,11 +539,10 @@ class IntelLLVMClCCompiler(IntelClCCompiler): class ArmCCompiler(ArmCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, + info, linker=linker, full_version=full_version) ArmCompiler.__init__(self) @@ -570,11 +565,10 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] class CcrxCCompiler(CcrxCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) CcrxCompiler.__init__(self) # Override CCompiler.get_always_args @@ -622,11 +616,10 @@ def get_include_args(self, path: str, is_system: bool) -> T.List[str]: class Xc16CCompiler(Xc16Compiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) Xc16Compiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -668,11 +661,10 @@ def get_include_args(self, path: str, is_system: bool) -> T.List[str]: class CompCertCCompiler(CompCertCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) CompCertCompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -702,11 +694,10 @@ def get_include_args(self, path: str, is_system: bool) -> T.List[str]: class TICCompiler(TICompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) TICompiler.__init__(self) # Override CCompiler.get_always_args @@ -743,11 +734,10 @@ class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) MetrowerksCompiler.__init__(self) def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: @@ -772,11 +762,10 @@ class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) MetrowerksCompiler.__init__(self) def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 474c87eb5de0..9e99706c0a49 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -629,14 +629,14 @@ def run(self, code: 'mesonlib.FileOrString', env: 'Environment', run_env: T.Optional[T.Dict[str, str]] = None, run_cwd: T.Optional[str] = None) -> RunResult: need_exe_wrapper = env.need_exe_wrapper(self.for_machine) - if need_exe_wrapper and self.exe_wrapper is None: + if need_exe_wrapper and not env.has_exe_wrapper(): raise CrossNoRunException('Can not run test applications in this cross environment.') with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p: if p.returncode != 0: mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n') return RunResult(False) if need_exe_wrapper: - cmdlist = self.exe_wrapper.get_command() + [p.output_name] + cmdlist = env.exe_wrapper.get_command() + [p.output_name] else: cmdlist = [p.output_name] try: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index fdf632a8c858..5e412e7a5643 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -40,7 +40,6 @@ from ..environment import Environment from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice - from ..programs import ExternalProgram CompilerMixinBase = CLikeCompiler else: CompilerMixinBase = object @@ -67,14 +66,14 @@ def attribute_check_func(self, name: str) -> str: language = 'cpp' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): # If a child ObjCPP class has already set it, don't set it ourselves Compiler.__init__(self, ccache, exelist, version, for_machine, info, is_cross=is_cross, linker=linker, full_version=full_version) - CLikeCompiler.__init__(self, exe_wrapper) + CLikeCompiler.__init__(self) @classmethod def get_display_language(cls) -> str: @@ -221,12 +220,12 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler): _CPP26_VERSION = '>=17.0.0' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ClangCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -336,7 +335,7 @@ class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler): id = 'emscripten' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): @@ -345,7 +344,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ if not version_compare(version, '>=1.39.19'): raise MesonException('Meson requires Emscripten >= 1.39.19') ClangCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper=exe_wrapper, linker=linker, + info, linker=linker, defines=defines, full_version=full_version) def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -363,11 +362,11 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): ''' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ArmclangCompiler.__init__(self) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -408,12 +407,12 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -500,11 +499,11 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: class PGICPPCompiler(PGICompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) PGICompiler.__init__(self) @@ -513,22 +512,22 @@ class NvidiaHPC_CPPCompiler(PGICompiler, CPPCompiler): id = 'nvidia_hpc' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) PGICompiler.__init__(self) class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, defines: T.Optional[T.Dict[str, str]] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ElbrusCompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -596,11 +595,11 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) IntelGnuLikeCompiler.__init__(self) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-Wpch-messages'] @@ -776,11 +775,10 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) MSVCCompiler.__init__(self, target) # By default, MSVC has a broken __cplusplus define that pretends to be c++98: @@ -824,11 +822,10 @@ class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, Cl def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, [], exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ClangClCompiler.__init__(self, target) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -840,11 +837,10 @@ class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLike def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, [], exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -864,11 +860,11 @@ class IntelLLVMClCPPCompiler(IntelClCPPCompiler): class ArmCPPCompiler(ArmCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ArmCompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -897,11 +893,11 @@ def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: class CcrxCPPCompiler(CcrxCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) CcrxCompiler.__init__(self) # Override CCompiler.get_always_args @@ -925,11 +921,11 @@ def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: class TICPPCompiler(TICompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) TICompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -965,11 +961,10 @@ class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) MetrowerksCompiler.__init__(self) def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: @@ -994,11 +989,10 @@ class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): CPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) MetrowerksCompiler.__init__(self) def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index e17ba3f5fc2c..391107f847d3 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -25,7 +25,6 @@ from ..envconfig import MachineInfo from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice - from ..programs import ExternalProgram cuda_optimization_args: T.Dict[str, T.List[str]] = { @@ -184,12 +183,11 @@ class CudaCompiler(Compiler): id = 'nvcc' def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, - is_cross: bool, exe_wrapper: T.Optional['ExternalProgram'], + is_cross: bool, host_compiler: Compiler, info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): super().__init__(ccache, exelist, version, for_machine, info, linker=linker, full_version=full_version, is_cross=is_cross) - self.exe_wrapper = exe_wrapper self.host_compiler = host_compiler self.base_options = host_compiler.base_options # -Wpedantic generates useless churn due to nvcc's dual compilation model producing @@ -550,7 +548,7 @@ def sanity_check(self, work_dir: str, env: 'Environment') -> None: flags += self.get_ccbin_args(env.coredata.options) # If cross-compiling, we can't run the sanity check, only compile it. - if self.is_cross and self.exe_wrapper is None: + if env.need_exe_wrapper(self.for_machine) 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 @@ -572,11 +570,11 @@ 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 self.is_cross: - if self.exe_wrapper is None: + if env.need_exe_wrapper(self.for_machine): + if not env.has_exe_wrapper(): return else: - cmdlist = self.exe_wrapper.get_command() + [binary_name] + cmdlist = env.exe_wrapper.get_command() + [binary_name] else: cmdlist = self.exelist + ['--run', '"' + binary_name + '"'] mlog.debug('Sanity check run command line: ', ' '.join(cmdlist)) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 8425ae22ddc2..78ce2bc23aac 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -27,7 +27,6 @@ if T.TYPE_CHECKING: from ..build import DFeatures from ..dependencies import Dependency - from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment from ..linkers.linkers import DynamicLinker @@ -432,14 +431,12 @@ class DCompiler(Compiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', arch: str, *, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None, is_cross: bool = False): super().__init__([], exelist, version, for_machine, info, linker=linker, full_version=full_version, is_cross=is_cross) self.arch = arch - self.exe_wrapper = exe_wrapper def sanity_check(self, work_dir: str, environment: 'Environment') -> None: source_name = os.path.join(work_dir, 'sanity.d') @@ -450,11 +447,11 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: pc.wait() if pc.returncode != 0: raise EnvironmentException('D compiler %s cannot compile programs.' % self.name_string()) - if self.is_cross: - if self.exe_wrapper is None: + if environment.need_exe_wrapper(self.for_machine): + if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return - cmdlist = self.exe_wrapper.get_command() + [output_name] + cmdlist = environment.exe_wrapper.get_command() + [output_name] else: cmdlist = [output_name] if subprocess.call(cmdlist) != 0: @@ -641,12 +638,11 @@ class GnuDCompiler(GnuCompiler, DCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', arch: str, *, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None, is_cross: bool = False): DCompiler.__init__(self, exelist, version, for_machine, info, arch, - exe_wrapper=exe_wrapper, linker=linker, + linker=linker, full_version=full_version, is_cross=is_cross) GnuCompiler.__init__(self, {}) default_warn_args = ['-Wall', '-Wdeprecated'] @@ -725,12 +721,11 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', arch: str, *, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None, is_cross: bool = False, version_output: T.Optional[str] = None): DCompiler.__init__(self, exelist, version, for_machine, info, arch, - exe_wrapper=exe_wrapper, linker=linker, + linker=linker, full_version=full_version, is_cross=is_cross) DmdLikeCompilerMixin.__init__(self, dmd_frontend_version=find_ldc_dmd_frontend_version(version_output)) self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} @@ -789,12 +784,11 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, info: 'MachineInfo', arch: str, *, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None, is_cross: bool = False): DCompiler.__init__(self, exelist, version, for_machine, info, arch, - exe_wrapper=exe_wrapper, linker=linker, + linker=linker, full_version=full_version, is_cross=is_cross) DmdLikeCompilerMixin.__init__(self, version) self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']} diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index f047242ca31b..aed03391889d 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -28,7 +28,6 @@ from .rust import RustCompiler from ..linkers.linkers import StaticLinker, DynamicLinker from ..environment import Environment - from ..programs import ExternalProgram # Default compilers and linkers @@ -116,7 +115,7 @@ def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoic # Helpers # ======= -def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str], T.Optional['ExternalProgram']]: +def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str]]: ''' The list of compilers is detected in the exact same way for C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. @@ -132,12 +131,7 @@ def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> compilers = [[x] for x in defaults[lang]] ccache = BinaryTable.detect_compiler_cache() - if env.machines.matches_build_machine(for_machine): - exe_wrap: T.Optional[ExternalProgram] = None - else: - exe_wrap = env.get_exe_wrapper() - - return compilers, ccache, exe_wrap + return compilers, ccache def _handle_exceptions( exceptions: T.Mapping[str, T.Union[Exception, str]], @@ -269,7 +263,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin from . import c, cpp from ..linkers import linkers popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} - compilers, ccache, exe_wrap = _get_compilers(env, lang, for_machine) + compilers, ccache = _get_compilers(env, lang, for_machine) if override_compiler is not None: compilers = [override_compiler] is_cross = env.is_cross_build(for_machine) @@ -361,7 +355,7 @@ def sanitize(p: str) -> str: return cls( ccache, compiler, version, for_machine, is_cross, - info, exe_wrap, defines=defines, full_version=full_version, + info, defines=defines, full_version=full_version, linker=linker) if 'Emscripten' in out: @@ -380,7 +374,7 @@ def sanitize(p: str) -> str: [], version=search_version(o)) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, linker=linker, full_version=full_version) + linker=linker, full_version=full_version) if 'Arm C/C++/Fortran Compiler' in out: arm_ver_match = re.search(r'version (\d+)\.(\d+)\.?(\d+)? \(build number (\d+)\)', out) @@ -393,7 +387,7 @@ def sanitize(p: str) -> str: linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, linker=linker) + linker=linker) if 'armclang' in out: # The compiler version is not present in the first line of output, # instead it is present in second line, startswith 'Component:'. @@ -413,7 +407,7 @@ def sanitize(p: str) -> str: env.coredata.add_lang_args(cls.language, cls, for_machine, env) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'CL.EXE COMPATIBILITY' in out: # if this is clang-cl masquerading as cl, detect it as cl, not # clang @@ -432,7 +426,7 @@ def sanitize(p: str) -> str: linker = guess_win_linker(env, ['lld-link'], cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, target, - exe_wrap, linker=linker) + linker=linker) # must be detected here before clang because TI compilers contain 'clang' in their output and so that they can be detected as 'clang' ti_compilers = { @@ -449,7 +443,7 @@ def sanitize(p: str) -> str: linker = lnk(compiler, for_machine, version=version) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'clang' in out or 'Clang' in out: linker = None @@ -476,7 +470,7 @@ def sanitize(p: str) -> str: return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, defines=defines, full_version=full_version, linker=linker) + defines=defines, full_version=full_version, linker=linker) if 'Intel(R) C++ Intel(R)' in err: version = search_version(err) @@ -486,7 +480,7 @@ def sanitize(p: str) -> str: linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) return cls( compiler, version, for_machine, is_cross, info, target, - exe_wrap, linker=linker) + linker=linker) if 'Intel(R) oneAPI DPC++/C++ Compiler for applications' in err: version = search_version(err) target = 'x86' if 'IA-32' in err else 'x86_64' @@ -495,7 +489,7 @@ def sanitize(p: str) -> str: linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) return cls( compiler, version, for_machine, is_cross, info, target, - exe_wrap, linker=linker) + linker=linker) if 'Microsoft' in out or 'Microsoft' in err: # Latest versions of Visual Studio print version # number to stderr but earlier ones print version @@ -521,47 +515,47 @@ def sanitize(p: str) -> str: ccache = [] return cls( ccache, compiler, version, for_machine, is_cross, info, target, - exe_wrap, full_version=cl_signature, linker=linker) + full_version=cl_signature, linker=linker) if 'PGI Compilers' in out: cls = c.PGICCompiler if lang == 'c' else cpp.PGICPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) return cls( ccache, compiler, version, for_machine, is_cross, - info, exe_wrap, linker=linker) + info, linker=linker) if 'NVIDIA Compilers and Tools' in out: cls = c.NvidiaHPC_CCompiler if lang == 'c' else cpp.NvidiaHPC_CPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.NvidiaHPC_DynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) return cls( ccache, compiler, version, for_machine, is_cross, - info, exe_wrap, linker=linker) + info, linker=linker) if '(ICC)' in out: cls = c.IntelCCompiler if lang == 'c' else cpp.IntelCPPCompiler l = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=l) + full_version=full_version, linker=l) if 'Intel(R) oneAPI' in out: cls = c.IntelLLVMCCompiler if lang == 'c' else cpp.IntelLLVMCPPCompiler l = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=l) + full_version=full_version, linker=l) if 'ARM' in out and not ('Metrowerks' in out or 'Freescale' in out): cls = c.ArmCCompiler if lang == 'c' else cpp.ArmCPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.ArmDynamicLinker(for_machine, version=version) return cls( ccache, compiler, version, for_machine, is_cross, - info, exe_wrap, full_version=full_version, linker=linker) + info, full_version=full_version, linker=linker) if 'RX Family' in out: cls = c.CcrxCCompiler if lang == 'c' else cpp.CcrxCPPCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = linkers.CcrxDynamicLinker(for_machine, version=version) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'Microchip Technology' in out: cls = c.Xc16CCompiler @@ -569,7 +563,7 @@ def sanitize(p: str) -> str: linker = linkers.Xc16DynamicLinker(for_machine, version=version) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'CompCert' in out: cls = c.CompCertCCompiler @@ -577,7 +571,7 @@ def sanitize(p: str) -> str: linker = linkers.CompCertDynamicLinker(for_machine, version=version) return cls( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'Metrowerks C/C++' in out or 'Freescale C/C++' in out: if 'ARM' in out: @@ -607,7 +601,7 @@ def sanitize(p: str) -> str: return cls( ccache, compiler, compiler_version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) _handle_exceptions(popen_exceptions, compilers) raise EnvironmentException(f'Unknown compiler {compilers}') @@ -623,7 +617,7 @@ def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp from ..linkers.linkers import CudaLinker popen_exceptions = {} is_cross = env.is_cross_build(for_machine) - compilers, ccache, exe_wrap = _get_compilers(env, 'cuda', for_machine) + compilers, ccache = _get_compilers(env, 'cuda', for_machine) info = env.machines[for_machine] for compiler in compilers: arg = '--version' @@ -652,14 +646,14 @@ def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp cls = CudaCompiler env.coredata.add_lang_args(cls.language, cls, for_machine, env) linker = CudaLinker(compiler, for_machine, CudaCompiler.LINKER_PREFIX, [], version=CudaLinker.parse_version()) - return cls(ccache, compiler, version, for_machine, is_cross, exe_wrap, host_compiler=cpp_compiler, info=info, linker=linker) + return cls(ccache, compiler, version, for_machine, is_cross, host_compiler=cpp_compiler, info=info, linker=linker) raise EnvironmentException(f'Could not find suitable CUDA compiler: "{"; ".join([" ".join(c) for c in compilers])}"') def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: from . import fortran from ..linkers import linkers popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} - compilers, ccache, exe_wrap = _get_compilers(env, 'fortran', for_machine) + compilers, ccache = _get_compilers(env, 'fortran', for_machine) is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] cls: T.Type[FortranCompiler] @@ -691,14 +685,14 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, defines, full_version=full_version, linker=linker) + defines, full_version=full_version, linker=linker) else: version = _get_gnu_version_from_defines(defines) cls = fortran.GnuFortranCompiler linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, defines, full_version=full_version, linker=linker) + defines, full_version=full_version, linker=linker) if 'Arm C/C++/Fortran Compiler' in out: cls = fortran.ArmLtdFlangFortranCompiler @@ -708,13 +702,13 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, linker=linker) + linker=linker) if 'G95' in out: cls = fortran.G95FortranCompiler linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'Sun Fortran' in err: version = search_version(err) @@ -722,7 +716,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'Intel(R) Fortran Compiler for applications' in err: version = search_version(err) @@ -732,7 +726,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) return cls( compiler, version, for_machine, is_cross, info, - target, exe_wrap, linker=linker) + target, linker=linker) if 'Intel(R) Visual Fortran' in err or 'Intel(R) Fortran' in err: version = search_version(err) @@ -742,26 +736,26 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = linkers.XilinkDynamicLinker(for_machine, [], version=version) return cls( compiler, version, for_machine, is_cross, info, - target, exe_wrap, linker=linker) + target, linker=linker) if 'ifort (IFORT)' in out: cls = fortran.IntelFortranCompiler linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'ifx (IFORT)' in out or 'ifx (IFX)' in out: cls = fortran.IntelLLVMFortranCompiler linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'PathScale EKOPath(tm)' in err: return fortran.PathScaleFortranCompiler( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version) + full_version=full_version) if 'PGI Compilers' in out: cls = fortran.PGIFortranCompiler @@ -769,7 +763,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = linkers.PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) return cls( - compiler, version, for_machine, is_cross, info, exe_wrap, + compiler, version, for_machine, is_cross, info, full_version=full_version, linker=linker) if 'NVIDIA Compilers and Tools' in out: @@ -778,7 +772,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C linker = linkers.PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version) return cls( - compiler, version, for_machine, is_cross, info, exe_wrap, + compiler, version, for_machine, is_cross, info, full_version=full_version, linker=linker) if 'flang' in out or 'clang' in out: @@ -800,7 +794,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'Open64 Compiler Suite' in err: cls = fortran.Open64FortranCompiler @@ -808,7 +802,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) if 'NAG Fortran' in err: full_version = err.split('\n', 1)[0] @@ -820,7 +814,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C version=version) return cls( compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version, linker=linker) + full_version=full_version, linker=linker) _handle_exceptions(popen_exceptions, compilers) raise EnvironmentException('Unreachable code (exception to make mypy happy)') @@ -834,7 +828,7 @@ def detect_objcpp_compiler(env: 'Environment', for_machine: MachineChoice) -> 'C def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine: MachineChoice) -> 'Compiler': from . import objc, objcpp popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} - compilers, ccache, exe_wrap = _get_compilers(env, lang, for_machine) + compilers, ccache = _get_compilers(env, lang, for_machine) is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] comp: T.Union[T.Type[objc.ObjCCompiler], T.Type[objcpp.ObjCPPCompiler]] @@ -857,7 +851,7 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine: linker = guess_nix_linker(env, compiler, comp, version, for_machine) return comp( ccache, compiler, version, for_machine, is_cross, info, - exe_wrap, defines, linker=linker) + defines, linker=linker) if 'clang' in out: linker = None defines = _get_clang_compiler_defines(compiler) @@ -879,7 +873,7 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine: linker = guess_nix_linker(env, compiler, comp, version, for_machine) return comp( ccache, compiler, version, for_machine, - is_cross, info, exe_wrap, linker=linker, defines=defines) + is_cross, info, linker=linker, defines=defines) _handle_exceptions(popen_exceptions, compilers) raise EnvironmentException('Unreachable code (exception to make mypy happy)') @@ -908,7 +902,7 @@ def detect_java_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp def detect_cs_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: from . import cs - compilers, ccache, exe_wrap = _get_compilers(env, 'cs', for_machine) + compilers, ccache = _get_compilers(env, 'cs', for_machine) popen_exceptions = {} info = env.machines[for_machine] for comp in compilers: @@ -935,7 +929,7 @@ def detect_cs_compiler(env: 'Environment', for_machine: MachineChoice) -> Compil def detect_cython_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: """Search for a cython compiler.""" from .cython import CythonCompiler - compilers, _, _ = _get_compilers(env, 'cython', MachineChoice.BUILD) + compilers, _ = _get_compilers(env, 'cython', MachineChoice.BUILD) is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] @@ -985,7 +979,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust from . import rust from ..linkers import linkers popen_exceptions: T.Dict[str, Exception] = {} - compilers, _, exe_wrap = _get_compilers(env, 'rust', for_machine) + compilers, _ = _get_compilers(env, 'rust', for_machine) is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] @@ -1092,7 +1086,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust env.coredata.add_lang_args(cls.language, cls, for_machine, env) return cls( - compiler, version, for_machine, is_cross, info, exe_wrap, + compiler, version, for_machine, is_cross, info, linker=linker) _handle_exceptions(popen_exceptions, compilers) @@ -1117,7 +1111,7 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile popen_exceptions = {} is_cross = env.is_cross_build(for_machine) - compilers, ccache, exe_wrap = _get_compilers(env, 'd', for_machine) + compilers, ccache = _get_compilers(env, 'd', for_machine) cls: T.Type[d.DCompiler] for exelist in compilers: # Search for a D compiler. @@ -1172,8 +1166,7 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile linker = guess_nix_linker(env, exelist, cls, version, for_machine) return cls( exelist, version, for_machine, info, arch, - exe_wrapper=exe_wrap, is_cross=is_cross, - full_version=full_version, linker=linker) + is_cross=is_cross, full_version=full_version, linker=linker) elif 'The D Language Foundation' in out or 'Digital Mars' in out: cls = d.DmdDCompiler # DMD seems to require a file @@ -1237,7 +1230,7 @@ def detect_swift_compiler(env: 'Environment', for_machine: MachineChoice) -> Com def detect_nasm_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: from .asm import NasmCompiler, YasmCompiler, MetrowerksAsmCompilerARM, MetrowerksAsmCompilerEmbeddedPowerPC - compilers, _, _ = _get_compilers(env, 'nasm', for_machine) + compilers, _ = _get_compilers(env, 'nasm', for_machine) is_cross = env.is_cross_build(for_machine) # We need a C compiler to properly detect the machine info and linker diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index d68c547e1492..3a73650462d0 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -31,7 +31,6 @@ from ..environment import Environment from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice - from ..programs import ExternalProgram class FortranCompiler(CLikeCompiler, Compiler): @@ -39,12 +38,12 @@ class FortranCompiler(CLikeCompiler, Compiler): language = 'fortran' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): Compiler.__init__(self, [], exelist, version, for_machine, info, is_cross=is_cross, full_version=full_version, linker=linker) - CLikeCompiler.__init__(self, exe_wrapper) + CLikeCompiler.__init__(self) def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, @@ -128,12 +127,12 @@ def get_options(self) -> 'MutableKeyedOptionDictType': class GnuFortranCompiler(GnuCompiler, FortranCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall'] @@ -197,12 +196,12 @@ def has_header(self, hname: str, prefix: str, env: 'Environment', *, class ElbrusFortranCompiler(ElbrusCompiler, FortranCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ElbrusCompiler.__init__(self) def get_options(self) -> 'MutableKeyedOptionDictType': @@ -222,11 +221,11 @@ class G95FortranCompiler(FortranCompiler): id = 'g95' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) default_warn_args = ['-Wall'] self.warn_args = {'0': [], @@ -269,11 +268,11 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): id = 'intel' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler @@ -323,11 +322,10 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', target: str, - exe_wrapper: T.Optional['ExternalProgram'] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) IntelVisualStudioLikeCompiler.__init__(self, target) @@ -366,11 +364,11 @@ class PathScaleFortranCompiler(FortranCompiler): id = 'pathscale' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -386,11 +384,11 @@ def openmp_flags(self) -> T.List[str]: class PGIFortranCompiler(PGICompiler, FortranCompiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) PGICompiler.__init__(self) @@ -412,11 +410,11 @@ class NvidiaHPC_FortranCompiler(PGICompiler, FortranCompiler): id = 'nvidia_hpc' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) PGICompiler.__init__(self) @@ -433,11 +431,11 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler): id = 'flang' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) ClangCompiler.__init__(self, {}) default_warn_args = ['-Minform=inform'] @@ -467,11 +465,11 @@ class Open64FortranCompiler(FortranCompiler): id = 'open64' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) default_warn_args = ['-fullwarn'] self.warn_args = {'0': [], @@ -489,11 +487,11 @@ class NAGFortranCompiler(FortranCompiler): id = 'nagfor' def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, - info: 'MachineInfo', exe_wrapper: T.Optional['ExternalProgram'] = None, + info: 'MachineInfo', linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): FortranCompiler.__init__(self, exelist, version, for_machine, - is_cross, info, exe_wrapper, linker=linker, + is_cross, info, linker=linker, full_version=full_version) # Warnings are on by default; -w disables (by category): self.warn_args = { diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index eb3a4f150a3e..09bd438818ca 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -36,7 +36,6 @@ from ..._typing import ImmutableListProtocol from ...environment import Environment from ...compilers.compilers import Compiler - from ...programs import ExternalProgram 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 @@ -133,15 +132,9 @@ class CLikeCompiler(Compiler): find_framework_cache: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]] = {} internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS - def __init__(self, exe_wrapper: T.Optional['ExternalProgram'] = None): + def __init__(self) -> None: # If a child ObjC or CPP class has already set it, don't set it ourselves self.can_compile_suffixes.add('h') - # If the exe wrapper was not found, pretend it wasn't set so that the - # sanity check is skipped and compiler checks use fallbacks. - if not exe_wrapper or not exe_wrapper.found() or not exe_wrapper.get_command(): - self.exe_wrapper = None - else: - self.exe_wrapper = exe_wrapper # Lazy initialized in get_preprocessor() self.preprocessor: T.Optional[Compiler] = None @@ -285,7 +278,7 @@ def _sanity_check_impl(self, work_dir: str, environment: 'Environment', mode = CompileCheckMode.LINK if self.is_cross: binname += '_cross' - if self.exe_wrapper is None: + if environment.need_exe_wrapper(self.for_machine) and 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 @@ -315,11 +308,11 @@ 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 self.is_cross: - if self.exe_wrapper is None: + if environment.need_exe_wrapper(self.for_machine): + if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return - cmdlist = self.exe_wrapper.get_command() + [binary_name] + cmdlist = environment.exe_wrapper.get_command() + [binary_name] else: cmdlist = [binary_name] mlog.debug('Running test binary command: ', mesonlib.join_args(cmdlist)) diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index 23008e62cae8..f805bd6bebe2 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -14,7 +14,6 @@ from .mixins.clang import ClangCompiler if T.TYPE_CHECKING: - from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment from ..linkers.linkers import DynamicLinker @@ -27,13 +26,12 @@ class ObjCCompiler(CLikeCompiler, Compiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrap: T.Optional['ExternalProgram'], linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): Compiler.__init__(self, ccache, exelist, version, for_machine, info, is_cross=is_cross, full_version=full_version, linker=linker) - CLikeCompiler.__init__(self, exe_wrap) + CLikeCompiler.__init__(self) @staticmethod def get_display_language() -> str: @@ -47,12 +45,11 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: class GnuObjCCompiler(GnuCompiler, ObjCCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): ObjCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -67,12 +64,11 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ class ClangObjCCompiler(ClangCompiler, ObjCCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): ObjCCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ClangCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index a5664dab4a01..baf4fb5ca70d 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -14,7 +14,6 @@ from .mixins.clang import ClangCompiler if T.TYPE_CHECKING: - from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment from ..linkers.linkers import DynamicLinker @@ -26,13 +25,12 @@ class ObjCPPCompiler(CLikeCompiler, Compiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrap: T.Optional['ExternalProgram'], linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): Compiler.__init__(self, ccache, exelist, version, for_machine, info, is_cross=is_cross, full_version=full_version, linker=linker) - CLikeCompiler.__init__(self, exe_wrap) + CLikeCompiler.__init__(self) @staticmethod def get_display_language() -> str: @@ -46,12 +44,11 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): ObjCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) GnuCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], @@ -67,12 +64,11 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler): def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, defines: T.Optional[T.Dict[str, str]] = None, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None): ObjCPPCompiler.__init__(self, ccache, exelist, version, for_machine, is_cross, - info, exe_wrapper, linker=linker, full_version=full_version) + info, linker=linker, full_version=full_version) ClangCompiler.__init__(self, defines) default_warn_args = ['-Wall', '-Winvalid-pch'] self.warn_args = {'0': [], diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 89b913a58de1..f557e89fa536 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -19,7 +19,6 @@ from ..environment import Environment # noqa: F401 from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice - from ..programs import ExternalProgram from ..dependencies import Dependency @@ -59,13 +58,11 @@ class RustCompiler(Compiler): def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', - exe_wrapper: T.Optional['ExternalProgram'] = None, full_version: T.Optional[str] = None, linker: T.Optional['DynamicLinker'] = None): super().__init__([], exelist, version, for_machine, info, is_cross=is_cross, full_version=full_version, linker=linker) - self.exe_wrapper = exe_wrapper self.base_options.update({OptionKey(o) for o in ['b_colorout', 'b_ndebug']}) if 'link' in self.linker.id: self.base_options.add(OptionKey('b_vscrt')) @@ -87,11 +84,11 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: pc, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) if pc.returncode != 0: raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.') - if self.is_cross: - if self.exe_wrapper is None: + if environment.need_exe_wrapper(self.for_machine): + if not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do return - cmdlist = self.exe_wrapper.get_command() + [output_name] + cmdlist = environment.exe_wrapper.get_command() + [output_name] else: cmdlist = [output_name] pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index af69f64ecf72..86bbbb1368b8 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -957,3 +957,6 @@ def get_exe_wrapper(self) -> T.Optional[ExternalProgram]: if not self.need_exe_wrapper(): return None return self.exe_wrapper + + def has_exe_wrapper(self) -> bool: + return self.exe_wrapper and self.exe_wrapper.found() From 18f8aeda8b59a132f24fa1af800ff65cac2f61f4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 4 Dec 2023 17:02:01 -0800 Subject: [PATCH 713/855] rust: Get native-static-libs even when it cannot run host binaries When rustc cannot run host binaries it does an early return which skipped getting native-static-libs. Move that code earlier to always run it. While at it, failing to determine those libs is a fatal error. We would crash later when trying to access rustc.native_static_libs attribute otherwise. --- mesonbuild/compilers/rust.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index f557e89fa536..65f4ac1b1f7c 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -84,6 +84,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: pc, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) 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 not environment.has_exe_wrapper(): # Can't check if the binaries run so we have to assume they do @@ -95,18 +96,22 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: pe.wait() if pe.returncode != 0: raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.') + + def _native_static_libs(self, work_dir: str, source_name: str) -> None: # Get libraries needed to link with a Rust staticlib cmdlist = self.exelist + ['--crate-type', 'staticlib', '--print', 'native-static-libs', source_name] p, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) - if p.returncode == 0: - match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE) - if match: - # Exclude some well known libraries that we don't need because they - # are always part of C/C++ linkers. Rustc probably should not print - # them, pkg-config for example never specify them. - # FIXME: https://github.com/rust-lang/rust/issues/55120 - exclude = {'-lc', '-lgcc_s', '-lkernel32', '-ladvapi32'} - self.native_static_libs = [i for i in match.group(1).split() if i not in exclude] + if p.returncode != 0: + raise EnvironmentException('Rust compiler cannot compile staticlib.') + match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE) + if not match: + raise EnvironmentException('Failed to find native-static-libs in Rust compiler output.') + # Exclude some well known libraries that we don't need because they + # are always part of C/C++ linkers. Rustc probably should not print + # them, pkg-config for example never specify them. + # FIXME: https://github.com/rust-lang/rust/issues/55120 + exclude = {'-lc', '-lgcc_s', '-lkernel32', '-ladvapi32'} + self.native_static_libs = [i for i in match.group(1).split() if i not in exclude] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return ['--dep-info', outfile] From 6d713e40f81512eadb0cc4654408d90cb22ba774 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Mar 2024 13:30:34 -0700 Subject: [PATCH 714/855] dependency: define equality and hash operators for Dependency When a dependency is copied and its name is changed, we still need a way to say "this is the same dependency", which we now have. --- mesonbuild/dependencies/base.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 0d946b8535b4..29a60b774ad8 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1,5 +1,6 @@ # 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. @@ -106,6 +107,9 @@ 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 @@ -124,6 +128,14 @@ 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}>' From b1340e9bb1f243e4de8f2d89415a45ade476a3dc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 13 Mar 2024 12:48:06 -0700 Subject: [PATCH 715/855] interpreter: when overriding a dependency make its name match Otherwise internal dependencies have auto-generated names that are not human readable. Instead, use the name that the dependency overrides. For example: ```meson meson.override_dependency('zlib', declare_dependency()) dep_zlib = dependency('zlib') assert(dep_zlib.name() == 'zlib') ``` Fixes: #12967 --- mesonbuild/interpreter/mesonmain.py | 13 ++++++++++++- .../common/98 subproject subdir/meson.build | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 4d1f427da210..fb18fa8b6806 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -1,8 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2024 Intel Corporation from __future__ import annotations +import copy import os import typing as T @@ -347,6 +348,16 @@ 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 ef053d86c41c..d2bafedf5119 100644 --- a/test cases/common/98 subproject subdir/meson.build +++ b/test cases/common/98 subproject subdir/meson.build @@ -1,3 +1,7 @@ +# 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']) @@ -6,7 +10,19 @@ exe = executable('prog', 'prog.c', dependencies: libSub) test('subproject subdir', exe) # Verify the subproject has placed dependency override. -dependency('sub-1.0') +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.') # Verify we can now take 'sub' dependency without fallback, but only version 1.0. dependency('sub') From d08ef2c08bb0120f0ba20dbc10575b7e15577349 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 11 Jan 2024 15:20:14 -0500 Subject: [PATCH 716/855] move UserArrayOption.listify_value to mesonlib This function is used at 3 different places and it does not justify it as being a staticmethod instead of being a free function. --- mesonbuild/coredata.py | 27 +++------------------------ mesonbuild/mcompile.py | 5 ++--- mesonbuild/utils/universal.py | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index bb481cae9128..112310745c59 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -20,7 +20,7 @@ PerMachineDefaultable, default_libdir, default_libexecdir, default_prefix, default_datadir, default_includedir, default_infodir, default_localedir, default_mandir, default_sbindir, default_sysconfdir, - split_args, OptionKey, OptionType, stringlistify, + listify_array_value, OptionKey, OptionType, stringlistify, pickle_load ) from .wrap import WrapMode @@ -268,29 +268,8 @@ def __init__(self, description: str, value: T.Union[str, T.List[str]], self.allow_dups = allow_dups self.set_value(value) - @staticmethod - def listify_value(value: T.Union[str, T.List[str]], shlex_split_args: bool = False) -> T.List[str]: - if isinstance(value, str): - if value.startswith('['): - try: - newvalue = ast.literal_eval(value) - except ValueError: - raise MesonException(f'malformed option {value}') - elif value == '': - newvalue = [] - else: - if shlex_split_args: - newvalue = split_args(value) - else: - newvalue = [v.strip() for v in value.split(',')] - elif isinstance(value, list): - newvalue = value - else: - raise MesonException(f'"{value}" should be a string array, but it is not') - return newvalue - def listify(self, value: T.Any) -> T.List[T.Any]: - return self.listify_value(value, self.split_args) + return listify_array_value(value, self.split_args) def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: newvalue = self.listify(value) @@ -364,7 +343,7 @@ def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: self.choices += gnu_stds_map.keys() def validate_value(self, value: T.Union[str, T.List[str]]) -> str: - candidates = UserArrayOption.listify_value(value) + candidates = listify_array_value(value) unknown = [std for std in candidates if std not in self.all_stds] if unknown: raise MesonException(f'Unknown {self.lang.upper()} std {unknown}. Possible values are {self.all_stds}.') diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 9c2f5e1e84ce..b07b60a9e984 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -16,16 +16,15 @@ from . import mlog from . import mesonlib -from .mesonlib import MesonException, RealPathAction, join_args, setup_vsenv +from .mesonlib import MesonException, RealPathAction, join_args, listify_array_value, setup_vsenv from mesonbuild.environment import detect_ninja -from mesonbuild.coredata import UserArrayOption from mesonbuild import build if T.TYPE_CHECKING: import argparse def array_arg(value: str) -> T.List[str]: - return UserArrayOption.listify_value(value) + return listify_array_value(value) def validate_builddir(builddir: Path) -> None: if not (builddir / 'meson-private' / 'coredata.dat').is_file(): diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 0fb860796ae7..a5383455aa0e 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -7,6 +7,7 @@ from __future__ import annotations from pathlib import Path import argparse +import ast import enum import sys import stat @@ -129,6 +130,7 @@ class _VerPickleLoadable(Protocol): 'iter_regexin_iter', 'join_args', 'listify', + 'listify_array_value', 'partition', 'path_is_in_root', 'pickle_load', @@ -1435,6 +1437,26 @@ def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]: result.append(i) return result +def listify_array_value(value: T.Union[str, T.List[str]], shlex_split_args: bool = False) -> T.List[str]: + if isinstance(value, str): + if value.startswith('['): + try: + newvalue = ast.literal_eval(value) + except ValueError: + raise MesonException(f'malformed value {value}') + elif value == '': + newvalue = [] + else: + if shlex_split_args: + newvalue = split_args(value) + else: + newvalue = [v.strip() for v in value.split(',')] + elif isinstance(value, list): + newvalue = value + else: + raise MesonException(f'"{value}" should be a string array, but it is not') + assert isinstance(newvalue, list) + return newvalue def extract_as_list(dict_object: T.Dict[_T, _U], key: _T, pop: bool = False) -> T.List[_U]: ''' From dacb25db101e7ede60b6ba3dd5a7d1935dc5ff73 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 11 Jan 2024 15:20:44 -0500 Subject: [PATCH 717/855] Improve error messages for invalid option values By adding the option name to UserOption object, it is now possible to display the name of the affected option when the given option value is not valid. Fixes #12635 --- mesonbuild/cargo/interpreter.py | 2 +- mesonbuild/compilers/c.py | 39 ++-- mesonbuild/compilers/compilers.py | 78 +++++--- mesonbuild/compilers/cpp.py | 173 ++++++++++-------- mesonbuild/compilers/cuda.py | 23 +-- mesonbuild/compilers/cython.py | 27 ++- mesonbuild/compilers/fortran.py | 18 +- mesonbuild/compilers/mixins/emscripten.py | 15 +- mesonbuild/compilers/objc.py | 17 +- mesonbuild/compilers/objcpp.py | 23 ++- mesonbuild/compilers/rust.py | 15 +- mesonbuild/coredata.py | 91 +++++---- mesonbuild/optinterpreter.py | 26 +-- .../failing/98 number in combo/test.json | 2 +- test cases/failing/99 bool in combo/test.json | 2 +- unittests/platformagnostictests.py | 23 ++- 16 files changed, 325 insertions(+), 249 deletions(-) diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index f1ed23953850..e1b0928978f8 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -716,7 +716,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser. for feature in cargo.features: key = OptionKey(_option_name(feature), subproject=subp_name) enabled = feature == 'default' - options[key] = coredata.UserBooleanOption(f'Cargo {feature} feature', enabled) + options[key] = coredata.UserBooleanOption(key.name, f'Cargo {feature} feature', enabled) ast = _create_project(cargo, build) ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')] diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 048649a32ac8..7e2146111563 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -152,12 +152,13 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() if self.info.is_windows() or self.info.is_cygwin(): - opts.update({ - OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( - 'Standard Win libraries to link against', - gnu_winlibs, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserArrayOption, + OptionKey('winlibs', machine=self.for_machine, lang=self.language), + 'Standard Win libraries to link against', + gnu_winlibs), + ) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -290,12 +291,13 @@ def get_options(self) -> 'MutableKeyedOptionDictType': assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(stds, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): - opts.update({ - key.evolve('winlibs'): coredata.UserArrayOption( - 'Standard Win libraries to link against', - gnu_winlibs, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserArrayOption, + key.evolve('winlibs'), + 'Standard Win libraries to link against', + gnu_winlibs), + ) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -425,15 +427,16 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase): """Shared methods that apply to MSVC-like C compilers.""" - def get_options(self) -> 'MutableKeyedOptionDictType': - opts = super().get_options() - opts.update({ - OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption( + def get_options(self) -> MutableKeyedOptionDictType: + return self.update_options( + super().get_options(), + self.create_option( + coredata.UserArrayOption, + OptionKey('winlibs', machine=self.for_machine, lang=self.language), 'Windows libs to link against.', msvc_winlibs, ), - }) - return opts + ) def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: # need a TypeDict to make this work diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 9e99706c0a49..5854c9e603e8 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -9,6 +9,7 @@ import enum import itertools import typing as T +from dataclasses import dataclass from functools import lru_cache from .. import coredata @@ -34,6 +35,7 @@ CompilerType = T.TypeVar('CompilerType', bound='Compiler') _T = T.TypeVar('_T') + UserOptionType = T.TypeVar('UserOptionType', bound=coredata.UserOption) """This file contains the data files of all compilers Meson knows about. To support a new compiler, add its information below. @@ -206,36 +208,46 @@ class CompileCheckMode(enum.Enum): MSCRT_VALS = ['none', 'md', 'mdd', 'mt', 'mtd'] -base_options: 'KeyedOptionDictType' = { - OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), - OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), - OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None, 0)), - OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.', - ['default', 'thin'], - 'default'), - OptionKey('b_thinlto_cache'): coredata.UserBooleanOption('Use LLVM ThinLTO caching for faster incremental builds', False), - OptionKey('b_thinlto_cache_dir'): coredata.UserStringOption('Directory to store ThinLTO cache objects', ''), - OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use', - ['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined'], - 'none'), - OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), - OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), - OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization', - ['off', 'generate', 'use'], - 'off'), - OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False), - OptionKey('b_colorout'): coredata.UserComboOption('Use colored output', - ['auto', 'always', 'never'], - 'always'), - OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'), - OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True), - OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False), - OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False), - OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.', - MSCRT_VALS + ['from_buildtype', 'static_from_buildtype'], - 'from_buildtype'), +@dataclass +class BaseOption(T.Generic[coredata._T, coredata._U]): + opt_type: T.Type[coredata._U] + description: str + default: T.Any = None + choices: T.Any = None + + def init_option(self, name: OptionKey) -> coredata._U: + keywords = {'value': self.default} + if self.choices: + keywords['choices'] = self.choices + return self.opt_type(name.name, self.description, **keywords) + +BASE_OPTIONS: T.Mapping[OptionKey, BaseOption] = { + OptionKey('b_pch'): BaseOption(coredata.UserBooleanOption, 'Use precompiled headers', True), + OptionKey('b_lto'): BaseOption(coredata.UserBooleanOption, 'Use link time optimization', False), + OptionKey('b_lto_threads'): BaseOption(coredata.UserIntegerOption, 'Use multiple threads for Link Time Optimization', (None, None, 0)), + OptionKey('b_lto_mode'): BaseOption(coredata.UserComboOption, 'Select between different LTO modes.', 'default', + choices=['default', 'thin']), + OptionKey('b_thinlto_cache'): BaseOption(coredata.UserBooleanOption, 'Use LLVM ThinLTO caching for faster incremental builds', False), + OptionKey('b_thinlto_cache_dir'): BaseOption(coredata.UserStringOption, 'Directory to store ThinLTO cache objects', ''), + OptionKey('b_sanitize'): BaseOption(coredata.UserComboOption, 'Code sanitizer to use', 'none', + choices=['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined']), + OptionKey('b_lundef'): BaseOption(coredata.UserBooleanOption, 'Use -Wl,--no-undefined when linking', True), + OptionKey('b_asneeded'): BaseOption(coredata.UserBooleanOption, 'Use -Wl,--as-needed when linking', True), + OptionKey('b_pgo'): BaseOption(coredata.UserComboOption, 'Use profile guided optimization', 'off', + choices=['off', 'generate', 'use']), + OptionKey('b_coverage'): BaseOption(coredata.UserBooleanOption, 'Enable coverage tracking.', False), + OptionKey('b_colorout'): BaseOption(coredata.UserComboOption, 'Use colored output', 'always', + choices=['auto', 'always', 'never']), + OptionKey('b_ndebug'): BaseOption(coredata.UserComboOption, 'Disable asserts', 'false', choices=['true', 'false', 'if-release']), + OptionKey('b_staticpic'): BaseOption(coredata.UserBooleanOption, 'Build static libraries as position independent', True), + OptionKey('b_pie'): BaseOption(coredata.UserBooleanOption, 'Build executables as position independent', False), + OptionKey('b_bitcode'): BaseOption(coredata.UserBooleanOption, 'Generate and embed bitcode (only macOS/iOS/tvOS)', False), + OptionKey('b_vscrt'): BaseOption(coredata.UserComboOption, 'VS run-time library type to use.', 'from_buildtype', + choices=MSCRT_VALS + ['from_buildtype', 'static_from_buildtype']), } +base_options: KeyedOptionDictType = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()} + def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType', option: OptionKey) -> bool: try: @@ -577,6 +589,14 @@ def gen_import_library_args(self, implibname: str) -> T.List[str]: """ return [] + def create_option(self, option_type: T.Type[UserOptionType], option_key: OptionKey, *args: T.Any, **kwargs: T.Any) -> T.Tuple[OptionKey, UserOptionType]: + return option_key, option_type(f'{self.language}_{option_key.name}', *args, **kwargs) + + @staticmethod + def update_options(options: MutableKeyedOptionDictType, *args: T.Tuple[OptionKey, UserOptionType]) -> MutableKeyedOptionDictType: + options.update(args) + return options + def get_options(self) -> 'MutableKeyedOptionDictType': return {} @@ -1346,10 +1366,12 @@ def get_global_options(lang: str, link_options = env.options.get(largkey, []) cargs = coredata.UserArrayOption( + f'{lang}_{argkey.name}', description + ' compiler', comp_options, split_args=True, allow_dups=True) largs = coredata.UserArrayOption( + f'{lang}_{largkey.name}', description + ' linker', link_options, split_args=True, allow_dups=True) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 5e412e7a5643..540dedb1878e 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -237,18 +237,22 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) key = OptionKey('key', machine=self.for_machine, lang=self.language) - opts.update({ - key.evolve('debugstl'): coredata.UserBooleanOption( - 'STL debug mode', - False, - ), - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + self.create_option(coredata.UserBooleanOption, + key.evolve('rtti'), + 'Enable RTTI', + True), + self.create_option(coredata.UserBooleanOption, + key.evolve('debugstl'), + 'STL debug mode', + False), + ) cppstd_choices = [ 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20', ] @@ -260,12 +264,13 @@ def get_options(self) -> 'MutableKeyedOptionDictType': assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(cppstd_choices, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): - opts.update({ - key.evolve('winlibs'): coredata.UserArrayOption( - 'Standard Win libraries to link against', - gnu_winlibs, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserArrayOption, + key.evolve('winlibs'), + 'Standard Win libraries to link against', + gnu_winlibs), + ) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -378,13 +383,14 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = CPPCompiler.get_options(self) key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts.update({ - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + ) std_opt = opts[key] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(['c++98', 'c++03', 'c++11', 'c++14', 'c++17'], gnu=True) @@ -426,18 +432,22 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': key = OptionKey('std', machine=self.for_machine, lang=self.language) opts = CPPCompiler.get_options(self) - opts.update({ - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), - key.evolve('debugstl'): coredata.UserBooleanOption( - 'STL debug mode', - False, - ) - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + self.create_option(coredata.UserBooleanOption, + key.evolve('rtti'), + 'Enable RTTI', + True), + self.create_option(coredata.UserBooleanOption, + key.evolve('debugstl'), + 'STL debug mode', + False), + ) cppstd_choices = [ 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20', @@ -450,12 +460,13 @@ def get_options(self) -> 'MutableKeyedOptionDictType': assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(cppstd_choices, gnu=True) if self.info.is_windows() or self.info.is_cygwin(): - opts.update({ - key.evolve('winlibs'): coredata.UserArrayOption( - 'Standard Win libraries to link against', - gnu_winlibs, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserArrayOption, + key.evolve('winlibs'), + 'Standard Win libraries to link against', + gnu_winlibs), + ) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -550,17 +561,18 @@ def get_options(self) -> 'MutableKeyedOptionDictType': cpp_stds += ['c++20'] key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts.update({ - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - key.evolve('debugstl'): coredata.UserBooleanOption( - 'STL debug mode', - False, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + self.create_option(coredata.UserBooleanOption, + key.evolve('debugstl'), + 'STL debug mode', + False), + ) std_opt = opts[key] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(cpp_stds, gnu=True) @@ -628,15 +640,22 @@ def get_options(self) -> 'MutableKeyedOptionDictType': g_stds += ['gnu++2a'] key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts.update({ - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), - key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False), - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + self.create_option(coredata.UserBooleanOption, + key.evolve('rtti'), + 'Enable RTTI', + True), + self.create_option(coredata.UserBooleanOption, + key.evolve('debugstl'), + 'STL debug mode', + False), + ) std_opt = opts[key] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(c_stds + g_stds) @@ -694,18 +713,22 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: def _get_options_impl(self, opts: 'MutableKeyedOptionDictType', cpp_stds: T.List[str]) -> 'MutableKeyedOptionDictType': key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts.update({ - key.evolve('eh'): coredata.UserComboOption( - 'C++ exception handling type.', - ['none', 'default', 'a', 's', 'sc'], - 'default', - ), - key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True), - key.evolve('winlibs'): coredata.UserArrayOption( - 'Windows libs to link against.', - msvc_winlibs, - ), - }) + self.update_options( + opts, + self.create_option(coredata.UserComboOption, + key.evolve('eh'), + 'C++ exception handling type.', + ['none', 'default', 'a', 's', 'sc'], + 'default'), + self.create_option(coredata.UserBooleanOption, + key.evolve('rtti'), + 'Enable RTTI', + True), + self.create_option(coredata.UserArrayOption, + key.evolve('winlibs'), + 'Windows libs to link against.', + msvc_winlibs), + ) std_opt = opts[key] assert isinstance(std_opt, coredata.UserStdOption), 'for mypy' std_opt.set_versions(cpp_stds) diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 391107f847d3..ab4810798e5b 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -630,10 +630,6 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str, _CPP20_VERSION = '>=12.0' def get_options(self) -> 'MutableKeyedOptionDictType': - opts = super().get_options() - std_key = OptionKey('std', machine=self.for_machine, lang=self.language) - ccbindir_key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language) - cpp_stds = ['none', 'c++03', 'c++11'] if version_compare(self.version, self._CPP14_VERSION): cpp_stds += ['c++14'] @@ -642,13 +638,18 @@ def get_options(self) -> 'MutableKeyedOptionDictType': if version_compare(self.version, self._CPP20_VERSION): cpp_stds += ['c++20'] - opts.update({ - std_key: coredata.UserComboOption('C++ language standard to use with CUDA', - cpp_stds, 'none'), - ccbindir_key: coredata.UserStringOption('CUDA non-default toolchain directory to use (-ccbin)', - ''), - }) - return opts + return self.update_options( + super().get_options(), + self.create_option(coredata.UserComboOption, + OptionKey('std', machine=self.for_machine, lang=self.language), + 'C++ language standard to use with CUDA', + cpp_stds, + 'none'), + self.create_option(coredata.UserStringOption, + OptionKey('ccbindir', machine=self.for_machine, lang=self.language), + 'CUDA non-default toolchain directory to use (-ccbin)', + ''), + ) def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType': """ diff --git a/mesonbuild/compilers/cython.py b/mesonbuild/compilers/cython.py index a58b3a81421f..30cec81e369f 100644 --- a/mesonbuild/compilers/cython.py +++ b/mesonbuild/compilers/cython.py @@ -67,20 +67,19 @@ def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], return new def get_options(self) -> 'MutableKeyedOptionDictType': - opts = super().get_options() - opts.update({ - OptionKey('version', machine=self.for_machine, lang=self.language): coredata.UserComboOption( - 'Python version to target', - ['2', '3'], - '3', - ), - OptionKey('language', machine=self.for_machine, lang=self.language): coredata.UserComboOption( - 'Output C or C++ files', - ['c', 'cpp'], - 'c', - ) - }) - return opts + return self.update_options( + super().get_options(), + self.create_option(coredata.UserComboOption, + OptionKey('version', machine=self.for_machine, lang=self.language), + 'Python version to target', + ['2', '3'], + '3'), + self.create_option(coredata.UserComboOption, + OptionKey('language', machine=self.for_machine, lang=self.language), + 'Output C or C++ files', + ['c', 'cpp'], + 'c'), + ) def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: args: T.List[str] = [] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 3a73650462d0..2cdff36de441 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -112,16 +112,14 @@ def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.T return self._has_multi_link_arguments(args, env, 'stop; end program') def get_options(self) -> 'MutableKeyedOptionDictType': - opts = super().get_options() - key = OptionKey('std', machine=self.for_machine, lang=self.language) - opts.update({ - key: coredata.UserComboOption( - 'Fortran language standard to use', - ['none'], - 'none', - ), - }) - return opts + return self.update_options( + super().get_options(), + self.create_option(coredata.UserComboOption, + OptionKey('std', machine=self.for_machine, lang=self.language), + 'Fortran language standard to use', + ['none'], + 'none'), + ) class GnuFortranCompiler(GnuCompiler, FortranCompiler): diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py index d10c49987392..bb8a520546d4 100644 --- a/mesonbuild/compilers/mixins/emscripten.py +++ b/mesonbuild/compilers/mixins/emscripten.py @@ -55,17 +55,16 @@ def thread_link_flags(self, env: 'Environment') -> T.List[str]: args.append(f'-sPTHREAD_POOL_SIZE={count}') return args - def get_options(self) -> 'coredata.MutableKeyedOptionDictType': - opts = super().get_options() - key = OptionKey('thread_count', machine=self.for_machine, lang=self.language) - opts.update({ - key: coredata.UserIntegerOption( + def get_options(self) -> coredata.MutableKeyedOptionDictType: + return self.update_options( + super().get_options(), + self.create_option( + coredata.UserIntegerOption, + OptionKey('thread_count', machine=self.for_machine, lang=self.language), 'Number of threads to use in web assembly, set to 0 to disable', (0, None, 4), # Default was picked at random ), - }) - - return opts + ) @classmethod def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index f805bd6bebe2..7c19c1b7d591 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -78,15 +78,14 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ 'everything': ['-Weverything']} def get_options(self) -> 'coredata.MutableKeyedOptionDictType': - opts = super().get_options() - opts.update({ - OptionKey('std', machine=self.for_machine, lang='c'): coredata.UserComboOption( - 'C language standard to use', - ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'], - 'none', - ) - }) - return opts + return self.update_options( + super().get_options(), + self.create_option(coredata.UserComboOption, + OptionKey('std', machine=self.for_machine, lang='c'), + 'C language standard to use', + ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'], + 'none'), + ) def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]: args = [] diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index baf4fb5ca70d..46eaa504904d 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -77,18 +77,17 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ '3': default_warn_args + ['-Wextra', '-Wpedantic'], 'everything': ['-Weverything']} - def get_options(self) -> 'coredata.MutableKeyedOptionDictType': - opts = super().get_options() - opts.update({ - OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption( - 'C++ language standard to use', - ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b', - 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20', - 'gnu++2b'], - 'none', - ) - }) - return opts + def get_options(self) -> coredata.MutableKeyedOptionDictType: + return self.update_options( + super().get_options(), + self.create_option(coredata.UserComboOption, + OptionKey('std', machine=self.for_machine, lang='cpp'), + 'C++ language standard to use', + ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b', + 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20', + 'gnu++2b'], + 'none'), + ) def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]: args = [] diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 65f4ac1b1f7c..05e8b2b27745 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -156,15 +156,12 @@ def use_linker_args(cls, linker: str, version: str) -> T.List[str]: # C compiler for dynamic linking, as such we invoke the C compiler's # use_linker_args method instead. - def get_options(self) -> 'MutableKeyedOptionDictType': - key = OptionKey('std', machine=self.for_machine, lang=self.language) - return { - key: coredata.UserComboOption( - 'Rust edition to use', - ['none', '2015', '2018', '2021'], - 'none', - ), - } + def get_options(self) -> MutableKeyedOptionDictType: + return dict((self.create_option(coredata.UserComboOption, + OptionKey('std', machine=self.for_machine, lang=self.language), + 'Rust edition to use', + ['none', '2015', '2018', '2021'], + 'none'),)) def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: # Rust doesn't have dependency compile arguments so simply return diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 112310745c59..df575981a69f 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -109,10 +109,11 @@ def __init__(self, old_version: str, current_version: str, extra_msg: str = '') class UserOption(T.Generic[_T], HoldableObject): - def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], + def __init__(self, name: str, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], yielding: bool, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): super().__init__() + self.name = name self.choices = choices self.description = description if not isinstance(yielding, bool): @@ -140,20 +141,20 @@ def set_value(self, newvalue: T.Any) -> bool: return self.value != oldvalue class UserStringOption(UserOption[str]): - def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, None, yielding, deprecated) + super().__init__(name, description, None, yielding, deprecated) self.set_value(value) def validate_value(self, value: T.Any) -> str: if not isinstance(value, str): - raise MesonException('Value "%s" for string option is not a string.' % str(value)) + raise MesonException(f'The value of option "{self.name}" is "{value}", which is not a string.') return value class UserBooleanOption(UserOption[bool]): - def __init__(self, description: str, value: bool, yielding: bool = DEFAULT_YIELDING, + def __init__(self, name: str, description: str, value: bool, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, [True, False], yielding, deprecated) + super().__init__(name, description, [True, False], yielding, deprecated) self.set_value(value) def __bool__(self) -> bool: @@ -163,15 +164,15 @@ def validate_value(self, value: T.Any) -> bool: if isinstance(value, bool): return value if not isinstance(value, str): - raise MesonException(f'Value {value} cannot be converted to a boolean') + raise MesonException(f'Option "{self.name}" value {value} cannot be converted to a boolean') if value.lower() == 'true': return True if value.lower() == 'false': return False - raise MesonException('Value %s is not boolean (true or false).' % value) + raise MesonException(f'Option "{self.name}" value {value} is not boolean (true or false).') class UserIntegerOption(UserOption[int]): - def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): min_value, max_value, default_value = value self.min_value = min_value @@ -182,25 +183,25 @@ def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIEL if max_value is not None: c.append('<=' + str(max_value)) choices = ', '.join(c) - super().__init__(description, choices, yielding, deprecated) + super().__init__(name, description, choices, yielding, deprecated) self.set_value(default_value) def validate_value(self, value: T.Any) -> int: if isinstance(value, str): value = self.toint(value) if not isinstance(value, int): - raise MesonException('New value for integer option is not an integer.') + raise MesonException(f'Value {value!r} for option "{self.name}" is not an integer.') if self.min_value is not None and value < self.min_value: - raise MesonException('New value %d is less than minimum value %d.' % (value, self.min_value)) + raise MesonException(f'Value {value} for option "{self.name}" is less than minimum value {self.min_value}.') if self.max_value is not None and value > self.max_value: - raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value)) + raise MesonException(f'Value {value} for option "{self.name}" is more than maximum value {self.max_value}.') return value def toint(self, valuestring: str) -> int: try: return int(valuestring) except ValueError: - raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring) + raise MesonException(f'Value string "{valuestring}" for option "{self.name}" is not convertible to an integer.') class OctalInt(int): # NinjaBackend.get_user_option_args uses str() to converts it to a command line option @@ -210,9 +211,9 @@ def __str__(self) -> str: return oct(int(self)) class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]): - def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, (0, 0o777, value), yielding, deprecated) + super().__init__(name, description, (0, 0o777, value), yielding, deprecated) self.choices = ['preserve', '0000-0777'] def printable_value(self) -> str: @@ -229,18 +230,18 @@ def toint(self, valuestring: T.Union[str, OctalInt]) -> int: try: return int(valuestring, 8) except ValueError as e: - raise MesonException(f'Invalid mode: {e}') + raise MesonException(f'Invalid mode for option "{self.name}" {e}') class UserComboOption(UserOption[str]): - def __init__(self, description: str, choices: T.List[str], value: T.Any, + def __init__(self, name: str, description: str, choices: T.List[str], value: T.Any, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, choices, yielding, deprecated) + super().__init__(name, description, choices, yielding, deprecated) if not isinstance(self.choices, list): - raise MesonException('Combo choices must be an array.') + raise MesonException(f'Combo choices for option "{self.name}" must be an array.') for i in self.choices: if not isinstance(i, str): - raise MesonException('Combo choice elements must be strings.') + raise MesonException(f'Combo choice elements for option "{self.name}" must be strings.') self.set_value(value) def validate_value(self, value: T.Any) -> str: @@ -252,24 +253,27 @@ def validate_value(self, value: T.Any) -> str: else: _type = 'string' optionsstring = ', '.join([f'"{item}"' for item in self.choices]) - raise MesonException('Value "{}" (of type "{}") for combo option "{}" is not one of the choices.' + raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.' ' Possible choices are (as string): {}.'.format( - value, _type, self.description, optionsstring)) + value, _type, self.name, optionsstring)) return value class UserArrayOption(UserOption[T.List[str]]): - def __init__(self, description: str, value: T.Union[str, T.List[str]], + def __init__(self, name: str, description: str, value: T.Union[str, T.List[str]], split_args: bool = False, allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING, choices: T.Optional[T.List[str]] = None, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, choices if choices is not None else [], yielding, deprecated) + super().__init__(name, description, choices if choices is not None else [], yielding, deprecated) self.split_args = split_args self.allow_dups = allow_dups self.set_value(value) def listify(self, value: T.Any) -> T.List[T.Any]: - return listify_array_value(value, self.split_args) + try: + return listify_array_value(value, self.split_args) + except MesonException as e: + raise MesonException(f'error in option "{self.name}": {e!s}') def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: newvalue = self.listify(value) @@ -280,12 +284,17 @@ def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: mlog.deprecation(msg) for i in newvalue: if not isinstance(i, str): - raise MesonException(f'String array element "{newvalue!s}" is not a string.') + raise MesonException(f'String array element "{newvalue!s}" for option "{self.name}" is not a string.') if self.choices: bad = [x for x in newvalue if x not in self.choices] if bad: - raise MesonException('Options "{}" are not in allowed choices: "{}"'.format( - ', '.join(bad), ', '.join(self.choices))) + raise MesonException('Value{} "{}" for option "{}" {} not in allowed choices: "{}"'.format( + '' if len(bad) == 1 else 's', + ', '.join(bad), + self.name, + 'is' if len(bad) == 1 else 'are', + ', '.join(self.choices)) + ) return newvalue def extend_value(self, value: T.Union[str, T.List[str]]) -> None: @@ -297,9 +306,9 @@ def extend_value(self, value: T.Union[str, T.List[str]]) -> None: class UserFeatureOption(UserComboOption): static_choices = ['enabled', 'disabled', 'auto'] - def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, + def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(description, self.static_choices, value, yielding, deprecated) + super().__init__(name, description, self.static_choices, value, yielding, deprecated) self.name: T.Optional[str] = None # TODO: Refactor options to all store their name def is_enabled(self) -> bool: @@ -330,7 +339,8 @@ def __init__(self, lang: str, all_stds: T.List[str]) -> None: self.all_stds = ['none'] + all_stds # Map a deprecated std to its replacement. e.g. gnu11 -> c11. self.deprecated_stds: T.Dict[str, str] = {} - super().__init__(f'{lang} language standard to use', ['none'], 'none') + opt_name = 'cpp_std' if lang == 'c++' else f'{lang}_std' + super().__init__(opt_name, f'{lang} language standard to use', ['none'], 'none') def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None: assert all(std in self.all_stds for std in versions) @@ -343,10 +353,13 @@ def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: self.choices += gnu_stds_map.keys() def validate_value(self, value: T.Union[str, T.List[str]]) -> str: - candidates = listify_array_value(value) - unknown = [std for std in candidates if std not in self.all_stds] + try: + candidates = listify_array_value(value) + except MesonException as e: + raise MesonException(f'error in option "{self.name}": {e!s}') + unknown = ','.join(std for std in candidates if std not in self.all_stds) if unknown: - raise MesonException(f'Unknown {self.lang.upper()} std {unknown}. Possible values are {self.all_stds}.') + raise MesonException(f'Unknown option "{self.name}" value {unknown}. Possible values are {self.all_stds}.') # Check first if any of the candidates are not deprecated for std in candidates: if std in self.choices: @@ -360,10 +373,10 @@ def validate_value(self, value: T.Union[str, T.List[str]]) -> str: f'However, the deprecated {std} std currently falls back to {newstd}.\n' + 'This will be an error in the future.\n' + 'If the project supports both GNU and MSVC compilers, a value such as\n' + - '"c_std=gnu11,c11" specifies that GNU is prefered but it can safely fallback to plain c11.') + '"c_std=gnu11,c11" specifies that GNU is preferred but it can safely fallback to plain c11.') return newstd raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' + - f'Possible values are {self.choices}') + f'Possible values for option "{self.name}" are {self.choices}') @dataclass class OptionsView(abc.Mapping): @@ -720,11 +733,13 @@ def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey, def init_backend_options(self, backend_name: str) -> None: if backend_name == 'ninja': self.options[OptionKey('backend_max_links')] = UserIntegerOption( + 'backend_max_links', 'Maximum number of linker processes to run or 0 for no ' 'limit', (0, None, 0)) elif backend_name.startswith('vs'): self.options[OptionKey('backend_startup_project')] = UserStringOption( + 'backend_startup_project', 'Default project to execute in Visual Studio', '') @@ -1294,7 +1309,7 @@ def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) keywords = {'yielding': self.yielding, 'value': value} if self.choices: keywords['choices'] = self.choices - o = self.opt_type(self.description, **keywords) + o = self.opt_type(name.name, self.description, **keywords) o.readonly = self.readonly return o diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index e9c201eeca37..9da355a514e6 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -196,7 +196,7 @@ def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None: n_kwargs = {k: v for k, v in kwargs.items() if k not in {'type', 'description', 'deprecated', 'yield'}} - opt = parser(description, (kwargs['yield'], kwargs['deprecated']), n_kwargs) + opt = parser(opt_name, description, (kwargs['yield'], kwargs['deprecated']), n_kwargs) if key in self.options: mlog.deprecation(f'Option {opt_name} already exists.') self.options[key] = opt @@ -205,8 +205,8 @@ def func_option(self, args: T.Tuple[str], kwargs: 'FuncOptionArgs') -> None: 'string option', KwargInfo('value', str, default=''), ) - def string_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption: - return coredata.UserStringOption(description, kwargs['value'], *args) + def string_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption: + return coredata.UserStringOption(name, description, kwargs['value'], *args) @typed_kwargs( 'boolean option', @@ -218,20 +218,20 @@ def string_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], deprecated_values={str: ('1.1.0', 'use a boolean, not a string')}, ), ) - def boolean_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption: - return coredata.UserBooleanOption(description, kwargs['value'], *args) + def boolean_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption: + return coredata.UserBooleanOption(name, description, kwargs['value'], *args) @typed_kwargs( 'combo option', KwargInfo('value', (str, NoneType)), KwargInfo('choices', ContainerTypeInfo(list, str, allow_empty=False), required=True), ) - def combo_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption: + def combo_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption: choices = kwargs['choices'] value = kwargs['value'] if value is None: value = kwargs['choices'][0] - return coredata.UserComboOption(description, choices, value, *args) + return coredata.UserComboOption(name, description, choices, value, *args) @typed_kwargs( 'integer option', @@ -245,17 +245,17 @@ def combo_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], KwargInfo('min', (int, NoneType)), KwargInfo('max', (int, NoneType)), ) - def integer_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption: + def integer_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption: value = kwargs['value'] inttuple = (kwargs['min'], kwargs['max'], value) - return coredata.UserIntegerOption(description, inttuple, *args) + return coredata.UserIntegerOption(name, description, inttuple, *args) @typed_kwargs( 'string array option', KwargInfo('value', (ContainerTypeInfo(list, str), str, NoneType)), KwargInfo('choices', ContainerTypeInfo(list, str), default=[]), ) - def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption: + def string_array_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption: choices = kwargs['choices'] value = kwargs['value'] if kwargs['value'] is not None else choices if isinstance(value, str): @@ -263,7 +263,7 @@ def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ FeatureDeprecated('String value for array option', '1.3.0').use(self.subproject) else: raise mesonlib.MesonException('Value does not define an array: ' + value) - return coredata.UserArrayOption(description, value, + return coredata.UserArrayOption(name, description, value, choices=choices, yielding=args[0], deprecated=args[1]) @@ -272,5 +272,5 @@ def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ 'feature option', KwargInfo('value', str, default='auto', validator=in_set_validator({'auto', 'enabled', 'disabled'})), ) - def feature_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption: - return coredata.UserFeatureOption(description, kwargs['value'], *args) + def feature_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption: + return coredata.UserFeatureOption(name, description, kwargs['value'], *args) diff --git a/test cases/failing/98 number in combo/test.json b/test cases/failing/98 number in combo/test.json index ecac6676d96b..c1c94848024a 100644 --- a/test cases/failing/98 number in combo/test.json +++ b/test cases/failing/98 number in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/98 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + { "line": "test cases/failing/98 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for option \"optimization\" is not one of the choices. Possible choices are (as string): \"plain\", \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } ] } diff --git a/test cases/failing/99 bool in combo/test.json b/test cases/failing/99 bool in combo/test.json index 364dde8a4099..b3effc767bad 100644 --- a/test cases/failing/99 bool in combo/test.json +++ b/test cases/failing/99 bool in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/99 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + { "line": "test cases/failing/99 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } ] } diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index b75a78052b06..e3c25c70b92d 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -13,7 +13,7 @@ from .baseplatformtests import BasePlatformTests from .helpers import is_ci -from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, is_linux, python_command +from mesonbuild.mesonlib import EnvironmentVariables, ExecutableSerialisation, MesonException, is_linux, python_command from mesonbuild.optinterpreter import OptionInterpreter, OptionException from run_tests import Backend @@ -63,6 +63,27 @@ def write_file(code: str): fname = write_file("option('platlib', type: 'string')") interp.process(fname) + def test_option_validation(self): + """Test cases that are not catch by the optinterpreter itself.""" + interp = OptionInterpreter('') + + def write_file(code: str): + with tempfile.NamedTemporaryFile('w', dir=self.builddir, encoding='utf-8', delete=False) as f: + f.write(code) + return f.name + + fname = write_file("option('intminmax', type: 'integer', value: 10, min: 0, max: 5)") + self.assertRaisesRegex(MesonException, 'Value 10 for option "intminmax" is more than maximum value 5.', + interp.process, fname) + + fname = write_file("option('array', type: 'array', choices : ['one', 'two', 'three'], value : ['one', 'four'])") + self.assertRaisesRegex(MesonException, 'Value "four" for option "array" is not in allowed choices: "one, two, three"', + interp.process, fname) + + fname = write_file("option('array', type: 'array', choices : ['one', 'two', 'three'], value : ['four', 'five', 'six'])") + self.assertRaisesRegex(MesonException, 'Values "four, five, six" for option "array" are not in allowed choices: "one, two, three"', + interp.process, fname) + def test_python_dependency_without_pkgconfig(self): testdir = os.path.join(self.unit_test_dir, '103 python without pkgconfig') self.init(testdir, override_envvars={'PKG_CONFIG': 'notfound'}) From 6db1d2bca5eaf9ff3f92249340da7b66c91d26c5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 11 Mar 2024 11:31:05 -0700 Subject: [PATCH 718/855] unittests: Add a helper for copying source trees This is a useful thing to do when a test needs to modify the source tree, as it prevents races between tests. --- unittests/baseplatformtests.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 6125ed933209..93bfc8905b73 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2016-2021 The Meson development team +# Copyright © 2024 Intel Corporation +from __future__ import annotations from pathlib import PurePath from unittest import mock, TestCase, SkipTest import json @@ -9,6 +11,7 @@ import re import subprocess import sys +import shutil import tempfile import typing as T @@ -492,3 +495,23 @@ def assertPathDoesNotExist(self, path): def assertLength(self, val, length): assert len(val) == length, f'{val} is not length {length}' + + def copy_srcdir(self, srcdir: str) -> str: + """Copies a source tree and returns that copy. + + ensures that the copied tree is deleted after running. + + :param srcdir: The locaiton of the source tree to copy + :return: The location of the copy + """ + dest = tempfile.mkdtemp() + self.addCleanup(windows_proof_rmtree, dest) + + # shutil.copytree expects the destinatin directory to not exist, Once + # python 3.8 is required the `dirs_exist_ok` parameter negates the need + # for this + dest = os.path.join(dest, 'subdir') + + shutil.copytree(srcdir, dest) + + return dest From 05bbe45cc228c78c47f57c88a04acd937a60f8bb Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Tue, 5 Mar 2024 19:33:33 +0100 Subject: [PATCH 719/855] tests: Fix unit tests with high parallelism On Arch's shiny new 48-core/96-thread build server, the `test_install_log_content` test fails because of an unexpected `invalid-symlink.txt` file. Apparently the test runs in parallel with `test_install_subdir_symlinks`, which modifies the `59 install subdir` source directory. To fix this, make `install_subdir_invalid_symlinks` copy the entire test into a tmpdir before modifying it. --- unittests/linuxliketests.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 2328107caac8..bfe3586c1b84 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -1411,7 +1411,7 @@ def install_subdir_invalid_symlinks(self, testdir, subdir_path): Test that installation of broken symlinks works fine. https://github.com/mesonbuild/meson/issues/3914 ''' - testdir = os.path.join(self.common_test_dir, testdir) + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, testdir)) subdir = os.path.join(testdir, subdir_path) with chdir(subdir): # Can't distribute broken symlinks in the source tree because it breaks @@ -1419,17 +1419,14 @@ def install_subdir_invalid_symlinks(self, testdir, subdir_path): # hand. src = '../../nonexistent.txt' os.symlink(src, 'invalid-symlink.txt') - try: - self.init(testdir) - self.build() - self.install() - install_path = subdir_path.split(os.path.sep)[-1] - link = os.path.join(self.installdir, 'usr', 'share', install_path, 'invalid-symlink.txt') - self.assertTrue(os.path.islink(link), msg=link) - self.assertEqual(src, os.readlink(link)) - self.assertFalse(os.path.isfile(link), msg=link) - finally: - os.remove(os.path.join(subdir, 'invalid-symlink.txt')) + self.init(testdir) + self.build() + self.install() + install_path = subdir_path.split(os.path.sep)[-1] + link = os.path.join(self.installdir, 'usr', 'share', install_path, 'invalid-symlink.txt') + self.assertTrue(os.path.islink(link), msg=link) + self.assertEqual(src, os.readlink(link)) + self.assertFalse(os.path.isfile(link), msg=link) def test_install_subdir_symlinks(self): self.install_subdir_invalid_symlinks('59 install subdir', os.path.join('sub', 'sub1')) From 0762b86e59629d82c1e7efaeb5dc6c1381d5af1a Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Fri, 15 Mar 2024 19:21:51 +0100 Subject: [PATCH 720/855] tests: rename skip_on_jobname to expect_skip_on_jobname and skip_on_os to expect_skip_on_os The test.json format currently has three keys related to skipping tests: * `skip_on_jobname` * `skip_on_os` * `skip_on_env` While `skip_on_env` marks the test itself as skipped, i.e. they don't get run when the conditions are met, the other two skip options are just marking the test as "expected to be skipped" if the conditions apply, i.e. they want to see `MESON_SKIP_TEST` in the output and things will fail if that doesn't happen. They don't actually skip the tests as the names imply. To make this clearer rename the keys: * `skip_on_jobname` -> `expect_skip_on_jobname` * `skip_on_os` -> `expect_skip_on_os` `skip_on_env` stays the same, since that actually skips. The docs were also confused about this, so adjust that too. --- data/test.schema.json | 8 +++---- docs/markdown/Contributing.md | 22 ++++++++++--------- run_project_tests.py | 8 +++---- test cases/frameworks/1 boost/test.json | 2 +- test cases/frameworks/10 gtk-doc/test.json | 2 +- .../frameworks/11 gir subproject/test.json | 2 +- .../frameworks/12 multiple gir/test.json | 2 +- test cases/frameworks/13 yelp/test.json | 2 +- test cases/frameworks/14 doxygen/test.json | 2 +- test cases/frameworks/15 llvm/test.json | 10 ++++----- test cases/frameworks/16 sdl2/test.json | 6 ++--- test cases/frameworks/17 mpi/test.json | 4 ++-- test cases/frameworks/18 vulkan/test.json | 2 +- test cases/frameworks/19 pcap/test.json | 2 +- test cases/frameworks/2 gtest/test.json | 2 +- test cases/frameworks/20 cups/test.json | 2 +- test cases/frameworks/21 libwmf/test.json | 2 +- .../frameworks/22 gir link order/test.json | 2 +- test cases/frameworks/23 hotdoc/test.json | 2 +- test cases/frameworks/24 libgcrypt/test.json | 2 +- test cases/frameworks/25 hdf5/test.json | 6 ++--- test cases/frameworks/26 netcdf/test.json | 2 +- test cases/frameworks/27 gpgme/test.json | 2 +- .../frameworks/28 gir link order 2/test.json | 2 +- test cases/frameworks/29 blocks/test.json | 2 +- test cases/frameworks/3 gmock/test.json | 2 +- test cases/frameworks/30 scalapack/test.json | 2 +- test cases/frameworks/31 curses/test.json | 6 ++--- .../frameworks/34 gir static lib/test.json | 2 +- test cases/frameworks/36 gtkdoc cpp/test.json | 2 +- test cases/frameworks/37 gir cpp/test.json | 2 +- test cases/frameworks/4 qt/test.json | 2 +- .../frameworks/5 protocol buffers/test.json | 2 +- test cases/frameworks/6 gettext/test.json | 2 +- test cases/frameworks/7 gnome/test.json | 2 +- test cases/frameworks/8 flex/test.json | 2 +- 36 files changed, 64 insertions(+), 62 deletions(-) diff --git a/data/test.schema.json b/data/test.schema.json index 6f6a19381bf2..705413363771 100644 --- a/data/test.schema.json +++ b/data/test.schema.json @@ -87,13 +87,13 @@ "type": "string" } }, - "skip_on_jobname": { + "expect_skip_on_jobname": { "type": "array", "items": { "type": "string" } }, - "skip_on_os": { + "expect_skip_on_os": { "type": "array", "items": { "type": "string" @@ -167,13 +167,13 @@ "type": "string" } }, - "skip_on_jobname": { + "expect_skip_on_jobname": { "type": "array", "items": { "type": "string" } }, - "skip_on_os": { + "expect_skip_on_os": { "type": "array", "items": { "type": "string" diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md index 68e943bff3ff..731abc87d89a 100644 --- a/docs/markdown/Contributing.md +++ b/docs/markdown/Contributing.md @@ -334,9 +334,11 @@ Each value must contain the `val` key for the value of the option. `null` can be used for adding matrix entries without the current option. -The `skip_on_env`, `skip_on_jobname` and `skip_on_os` keys (as described below) -may be used in the value to skip that matrix entry, based on the current -environment. +The `skip_on_env` key (as described below) may be used in the value to skip that +matrix entry, based on the current environment. + +The `expect_skip_on_jobname` and `expect_skip_on_os` keys (as described below) +may be used to expect that the test will be skipped, based on the current environment. Similarly, the `compilers` key can be used to define a mapping of compilers to languages that are required for this value. @@ -412,23 +414,23 @@ The `skip_on_env` key can be used to specify a list of environment variables. If at least one environment variable in the `skip_on_env` list is present, the test is skipped. -#### skip_on_jobname +#### expect_skip_on_jobname -The `skip_on_jobname` key contains a list of strings. If the `MESON_CI_JOBNAME` +The `expect_skip_on_jobname` key contains a list of strings. If the `MESON_CI_JOBNAME` environment variable is set, and any of them are a sub-string of it, the test is expected to be skipped (that is, it is expected that the test will output `MESON_SKIP_TEST`, because the CI environment is not one in which it can run, for whatever reason). -The test is failed if it skips or runs unexpectedly. +The test is failed if it either skips unexpectedly or runs unexpectedly. -#### skip_on_os +#### expect_skip_on_os -The `skip_on_os` key can be used to specify a list of OS names (or their -negations, prefixed with a `!`). If at least one item in the `skip_on_os` list +The `expect_skip_on_os` key can be used to specify a list of OS names (or their +negations, prefixed with a `!`). If at least one item in the `expect_skip_on_os` list is matched, the test is expected to be skipped. -The test is failed if it skips or runs unexpectedly. +The test is failed if it either skips unexpectedly or runs unexpectedly. ### Skipping integration tests diff --git a/run_project_tests.py b/run_project_tests.py index a14741364aab..b159b3d6e02a 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -785,13 +785,13 @@ def _skip_keys(test_def: T.Dict) -> T.Tuple[bool, bool]: # Test is expected to skip if MESON_CI_JOBNAME contains any of the list of # substrings - if ('skip_on_jobname' in test_def) and (ci_jobname is not None): - skip_expected = any(s in ci_jobname for s in test_def['skip_on_jobname']) + if ('expect_skip_on_jobname' in test_def) and (ci_jobname is not None): + skip_expected = any(s in ci_jobname for s in test_def['expect_skip_on_jobname']) # Test is expected to skip if os matches - if 'skip_on_os' in test_def: + if 'expect_skip_on_os' in test_def: mesonenv = environment.Environment('', '', get_fake_options('/')) - for skip_os in test_def['skip_on_os']: + for skip_os in test_def['expect_skip_on_os']: if skip_os.startswith('!'): if mesonenv.machines.host.system != skip_os[1:]: skip_expected = True diff --git a/test cases/frameworks/1 boost/test.json b/test cases/frameworks/1 boost/test.json index 2c5b857e9e08..a09f7aa5d68a 100644 --- a/test cases/frameworks/1 boost/test.json +++ b/test cases/frameworks/1 boost/test.json @@ -18,5 +18,5 @@ { "static": "false", "b_vscrt": "mtd" } ] }, - "skip_on_jobname": ["azure", "msys2"] + "expect_skip_on_jobname": ["azure", "msys2"] } diff --git a/test cases/frameworks/10 gtk-doc/test.json b/test cases/frameworks/10 gtk-doc/test.json index 1085b55eeddf..796a60bdf13b 100644 --- a/test cases/frameworks/10 gtk-doc/test.json +++ b/test cases/frameworks/10 gtk-doc/test.json @@ -60,5 +60,5 @@ {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up.png"}, {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up-insensitive.png"} ], - "skip_on_jobname": ["azure", "msys2"] + "expect_skip_on_jobname": ["azure", "msys2"] } diff --git a/test cases/frameworks/11 gir subproject/test.json b/test cases/frameworks/11 gir subproject/test.json index aed0a1c71fa4..7c4be111c517 100644 --- a/test cases/frameworks/11 gir subproject/test.json +++ b/test cases/frameworks/11 gir subproject/test.json @@ -9,5 +9,5 @@ {"type": "expr", "file": "usr/lib/?libgirlib.so"}, {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirsubproject.dll.a"} ], - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy"] } diff --git a/test cases/frameworks/12 multiple gir/test.json b/test cases/frameworks/12 multiple gir/test.json index e59c3e6cd779..877c7c7ebe36 100644 --- a/test cases/frameworks/12 multiple gir/test.json +++ b/test cases/frameworks/12 multiple gir/test.json @@ -7,7 +7,7 @@ {"type": "expr", "file": "usr/lib/?libgirsubproject.so"}, {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirsubproject.dll.a"} ], - "skip_on_jobname": ["azure", "macos", "msys2"], + "expect_skip_on_jobname": ["azure", "macos", "msys2"], "stdout": [ { "comment": "This will either match in the future-deprecated notice summary, or match the warning summary", diff --git a/test cases/frameworks/13 yelp/test.json b/test cases/frameworks/13 yelp/test.json index 22e34d20db0e..9410bdc588b6 100644 --- a/test cases/frameworks/13 yelp/test.json +++ b/test cases/frameworks/13 yelp/test.json @@ -19,5 +19,5 @@ {"type": "file", "file": "usr/share/help/de/meson-linguas/index3.page"}, {"type": "file", "file": "usr/share/help/de/meson-linguas/media/test.txt"} ], - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/14 doxygen/test.json b/test cases/frameworks/14 doxygen/test.json index c8c4fb0f87fc..47d4c16bb785 100644 --- a/test cases/frameworks/14 doxygen/test.json +++ b/test cases/frameworks/14 doxygen/test.json @@ -2,5 +2,5 @@ "installed": [ {"type": "dir", "file": "usr/share/doc/spede/html"} ], - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/15 llvm/test.json b/test cases/frameworks/15 llvm/test.json index cf8aa3acc7bd..f9bb6458070e 100644 --- a/test cases/frameworks/15 llvm/test.json +++ b/test cases/frameworks/15 llvm/test.json @@ -2,17 +2,17 @@ "matrix": { "options": { "method": [ - { "val": "config-tool", "skip_on_jobname": ["msys2-gcc"] }, - { "val": "cmake", "skip_on_jobname": ["msys2"] }, - { "val": "combination", "skip_on_jobname": ["msys2"] } + { "val": "config-tool", "expect_skip_on_jobname": ["msys2-gcc"] }, + { "val": "cmake", "expect_skip_on_jobname": ["msys2"] }, + { "val": "combination", "expect_skip_on_jobname": ["msys2"] } ], "link-static": [ - { "val": true, "skip_on_jobname": ["arch", "opensuse", "linux-gentoo-gcc"] }, + { "val": true, "expect_skip_on_jobname": ["arch", "opensuse", "linux-gentoo-gcc"] }, { "val": false } ] } }, - "skip_on_jobname": ["azure", "cygwin"], + "expect_skip_on_jobname": ["azure", "cygwin"], "tools": { "cmake": ">=3.11" } diff --git a/test cases/frameworks/16 sdl2/test.json b/test cases/frameworks/16 sdl2/test.json index ee4112ae3cba..f19ba609a0df 100644 --- a/test cases/frameworks/16 sdl2/test.json +++ b/test cases/frameworks/16 sdl2/test.json @@ -6,10 +6,10 @@ { "val": "pkg-config" }, { "val": "config-tool" }, { "val": "sdlconfig" }, - { "val": "extraframework", "skip_on_os": ["!darwin"], "skip_on_jobname": ["macos"] }, - { "val": "cmake", "skip_on_jobname": ["bionic"] } + { "val": "extraframework", "expect_skip_on_os": ["!darwin"], "expect_skip_on_jobname": ["macos"] }, + { "val": "cmake", "expect_skip_on_jobname": ["bionic"] } ] } }, - "skip_on_jobname": ["azure", "cygwin", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "msys2"] } diff --git a/test cases/frameworks/17 mpi/test.json b/test cases/frameworks/17 mpi/test.json index 115f6f6f54ba..cbd1686121c5 100644 --- a/test cases/frameworks/17 mpi/test.json +++ b/test cases/frameworks/17 mpi/test.json @@ -5,7 +5,7 @@ { "val": "auto" }, { "val": "pkg-config" }, { "val": "config-tool", - "skip_on_jobname": ["fedora"] }, + "expect_skip_on_jobname": ["fedora"] }, { "val": "system", "compilers": { "c" :"msvc", "cpp": "msvc" } @@ -13,5 +13,5 @@ ] } }, - "skip_on_jobname": ["azure", "cygwin", "msys2", "opensuse"] + "expect_skip_on_jobname": ["azure", "cygwin", "msys2", "opensuse"] } diff --git a/test cases/frameworks/18 vulkan/test.json b/test cases/frameworks/18 vulkan/test.json index 6ace9de70107..66afb97c33ab 100644 --- a/test cases/frameworks/18 vulkan/test.json +++ b/test cases/frameworks/18 vulkan/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/19 pcap/test.json b/test cases/frameworks/19 pcap/test.json index 8ee026a60f07..23af7d93189d 100644 --- a/test cases/frameworks/19 pcap/test.json +++ b/test cases/frameworks/19 pcap/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "msys2"] } diff --git a/test cases/frameworks/2 gtest/test.json b/test cases/frameworks/2 gtest/test.json index 6ace9de70107..66afb97c33ab 100644 --- a/test cases/frameworks/2 gtest/test.json +++ b/test cases/frameworks/2 gtest/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/20 cups/test.json b/test cases/frameworks/20 cups/test.json index 8ee026a60f07..23af7d93189d 100644 --- a/test cases/frameworks/20 cups/test.json +++ b/test cases/frameworks/20 cups/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "msys2"] } diff --git a/test cases/frameworks/21 libwmf/test.json b/test cases/frameworks/21 libwmf/test.json index 6ace9de70107..66afb97c33ab 100644 --- a/test cases/frameworks/21 libwmf/test.json +++ b/test cases/frameworks/21 libwmf/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/22 gir link order/test.json b/test cases/frameworks/22 gir link order/test.json index a9d74fb8a9b0..b15798127b8a 100644 --- a/test cases/frameworks/22 gir link order/test.json +++ b/test cases/frameworks/22 gir link order/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "macos", "msys2"] } diff --git a/test cases/frameworks/23 hotdoc/test.json b/test cases/frameworks/23 hotdoc/test.json index e13971ee8df5..2a1f3a93c50c 100644 --- a/test cases/frameworks/23 hotdoc/test.json +++ b/test cases/frameworks/23 hotdoc/test.json @@ -5,5 +5,5 @@ "tools": { "hotdoc": ">=0.1.0" }, - "skip_on_jobname": ["msys2"] + "expect_skip_on_jobname": ["msys2"] } diff --git a/test cases/frameworks/24 libgcrypt/test.json b/test cases/frameworks/24 libgcrypt/test.json index 77b68c00cb73..de9b738f6c45 100644 --- a/test cases/frameworks/24 libgcrypt/test.json +++ b/test cases/frameworks/24 libgcrypt/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "msys2"] + "expect_skip_on_jobname": ["azure", "msys2"] } diff --git a/test cases/frameworks/25 hdf5/test.json b/test cases/frameworks/25 hdf5/test.json index a5c816f662fb..590d4bc20283 100644 --- a/test cases/frameworks/25 hdf5/test.json +++ b/test cases/frameworks/25 hdf5/test.json @@ -2,10 +2,10 @@ "matrix": { "options": { "method": [ - { "val": "pkg-config", "skip_on_jobname": ["linux-gentoo-gcc"] }, - { "val": "config-tool", "skip_on_jobname": ["macos"] } + { "val": "pkg-config", "expect_skip_on_jobname": ["linux-gentoo-gcc"] }, + { "val": "config-tool", "expect_skip_on_jobname": ["macos"] } ] } }, - "skip_on_jobname": ["azure", "cygwin", "fedora", "msys2", "opensuse"] + "expect_skip_on_jobname": ["azure", "cygwin", "fedora", "msys2", "opensuse"] } diff --git a/test cases/frameworks/26 netcdf/test.json b/test cases/frameworks/26 netcdf/test.json index 83c62916727f..3cf5207507f9 100644 --- a/test cases/frameworks/26 netcdf/test.json +++ b/test cases/frameworks/26 netcdf/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "macos", "msys2", "opensuse", "ubuntu"] + "expect_skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "macos", "msys2", "opensuse", "ubuntu"] } diff --git a/test cases/frameworks/27 gpgme/test.json b/test cases/frameworks/27 gpgme/test.json index 59eb0e24d871..f64d7189e4c6 100644 --- a/test cases/frameworks/27 gpgme/test.json +++ b/test cases/frameworks/27 gpgme/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch", "ubuntu"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "linux-arch", "ubuntu"] } diff --git a/test cases/frameworks/28 gir link order 2/test.json b/test cases/frameworks/28 gir link order 2/test.json index a9d74fb8a9b0..b15798127b8a 100644 --- a/test cases/frameworks/28 gir link order 2/test.json +++ b/test cases/frameworks/28 gir link order 2/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "macos", "msys2"] } diff --git a/test cases/frameworks/29 blocks/test.json b/test cases/frameworks/29 blocks/test.json index 34a8c415d39e..3bc0974dab2b 100644 --- a/test cases/frameworks/29 blocks/test.json +++ b/test cases/frameworks/29 blocks/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "gcc", "msys2"] + "expect_skip_on_jobname": ["azure", "gcc", "msys2"] } diff --git a/test cases/frameworks/3 gmock/test.json b/test cases/frameworks/3 gmock/test.json index 6ace9de70107..66afb97c33ab 100644 --- a/test cases/frameworks/3 gmock/test.json +++ b/test cases/frameworks/3 gmock/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/30 scalapack/test.json b/test cases/frameworks/30 scalapack/test.json index 0c40573168a4..fe1016a0fc2b 100644 --- a/test cases/frameworks/30 scalapack/test.json +++ b/test cases/frameworks/30 scalapack/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "msys2", "opensuse"] + "expect_skip_on_jobname": ["azure", "bionic", "cygwin", "fedora", "msys2", "opensuse"] } diff --git a/test cases/frameworks/31 curses/test.json b/test cases/frameworks/31 curses/test.json index 03ed3a201638..ed7c61929537 100644 --- a/test cases/frameworks/31 curses/test.json +++ b/test cases/frameworks/31 curses/test.json @@ -3,10 +3,10 @@ "options": { "method": [ { "val": "pkg-config" }, - { "val": "config-tool", "skip_on_jobname": ["msys2"] }, - { "val": "system", "skip_on_os": ["windows"] } + { "val": "config-tool", "expect_skip_on_jobname": ["msys2"] }, + { "val": "system", "expect_skip_on_os": ["windows"] } ] } }, - "skip_on_jobname": ["azure", "cygwin"] + "expect_skip_on_jobname": ["azure", "cygwin"] } diff --git a/test cases/frameworks/34 gir static lib/test.json b/test cases/frameworks/34 gir static lib/test.json index 8d7f707d7b50..c2ba9b2a886e 100644 --- a/test cases/frameworks/34 gir static lib/test.json +++ b/test cases/frameworks/34 gir static lib/test.json @@ -5,5 +5,5 @@ {"type": "file", "platform": "cygwin", "file": "usr/lib/libgirlib.dll.a"}, {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"} ], - "skip_on_jobname": ["azure", "bionic", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "bionic", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/36 gtkdoc cpp/test.json b/test cases/frameworks/36 gtkdoc cpp/test.json index b2d9bc88f6a0..c53e93ceff20 100644 --- a/test cases/frameworks/36 gtkdoc cpp/test.json +++ b/test cases/frameworks/36 gtkdoc cpp/test.json @@ -13,5 +13,5 @@ {"type": "file", "file": "usr/share/gtk-doc/html/foo/up.png"}, {"type": "file", "file": "usr/share/gtk-doc/html/foo/right.png"} ], - "skip_on_jobname": ["azure", "msys2"] + "expect_skip_on_jobname": ["azure", "msys2"] } diff --git a/test cases/frameworks/37 gir cpp/test.json b/test cases/frameworks/37 gir cpp/test.json index 3641d75ca9e8..aa7f44e13ad2 100644 --- a/test cases/frameworks/37 gir cpp/test.json +++ b/test cases/frameworks/37 gir cpp/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "macos", "msys2", "cygwin"] + "expect_skip_on_jobname": ["azure", "macos", "msys2", "cygwin"] } diff --git a/test cases/frameworks/4 qt/test.json b/test cases/frameworks/4 qt/test.json index 4df0b49a03c0..34de94101414 100644 --- a/test cases/frameworks/4 qt/test.json +++ b/test cases/frameworks/4 qt/test.json @@ -8,5 +8,5 @@ ] } }, - "skip_on_jobname": ["cygwin", "msys2", "azure"] + "expect_skip_on_jobname": ["cygwin", "msys2", "azure"] } diff --git a/test cases/frameworks/5 protocol buffers/test.json b/test cases/frameworks/5 protocol buffers/test.json index 6ace9de70107..66afb97c33ab 100644 --- a/test cases/frameworks/5 protocol buffers/test.json +++ b/test cases/frameworks/5 protocol buffers/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2"] } diff --git a/test cases/frameworks/6 gettext/test.json b/test cases/frameworks/6 gettext/test.json index 910fc1c74e8c..5eaed9c24287 100644 --- a/test cases/frameworks/6 gettext/test.json +++ b/test cases/frameworks/6 gettext/test.json @@ -22,5 +22,5 @@ ] } }, - "skip_on_jobname": ["azure", "cygwin"] + "expect_skip_on_jobname": ["azure", "cygwin"] } diff --git a/test cases/frameworks/7 gnome/test.json b/test cases/frameworks/7 gnome/test.json index f75ba131db56..77c9bdfb5216 100644 --- a/test cases/frameworks/7 gnome/test.json +++ b/test cases/frameworks/7 gnome/test.json @@ -36,5 +36,5 @@ {"type": "file", "file": "usr/include/simple-resources.h"}, {"type": "file", "file": "usr/include/generated-gdbus.h"} ], - "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy"] + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy"] } diff --git a/test cases/frameworks/8 flex/test.json b/test cases/frameworks/8 flex/test.json index 613cfe59f6b9..083c31ab33bc 100644 --- a/test cases/frameworks/8 flex/test.json +++ b/test cases/frameworks/8 flex/test.json @@ -1,3 +1,3 @@ { - "skip_on_jobname": ["azure", "cygwin"] + "expect_skip_on_jobname": ["azure", "cygwin"] } From dec93ce9a52b234ed4cb25646eaf13c503ba739a Mon Sep 17 00:00:00 2001 From: Sam James Date: Wed, 13 Mar 2024 00:39:07 +0000 Subject: [PATCH 721/855] environment: fix LLVM 18 support in get_llvm_tool_names() In 67afddbf431140c1ee064bf79a2fa5a95575488e, we added LLVM 18, but LLVM >= 18 uses a new version scheme of X.Y, not X.0.Y (where using "X" was enough). See https://discourse.llvm.org/t/rfc-name-the-first-release-from-a-branch-n-1-0-instead-of-n-0-0/75384. Without this, I get a test failure: ``` mesonbuild.interpreterbase.exceptions.InterpreterException: Assert failed: config-tool and cmake returns different major versions -> frameworks: 15 llvm (method=combination link-static=False) ``` Fixes: https://github.com/mesonbuild/meson/issues/12961 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/environment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 86bbbb1368b8..54fb50af117d 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -188,6 +188,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: # unless it becomes a stable release. suffixes = [ '', # base (no suffix) + '-18.1', '18.1', '-18', '18', '-17', '17', '-16', '16', From 2ac5c4b72081735cc9a2b67e5671c1afe682fcae Mon Sep 17 00:00:00 2001 From: Sam James Date: Wed, 13 Mar 2024 00:41:10 +0000 Subject: [PATCH 722/855] environment: update Debian development version in get_llvm_tool_names() As far as we can ascertain, the idea here was supposed to be that this version at the bottom gets updated as a last-resort for development LLVMs on Debian. Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 54fb50af117d..19b9e81b53b5 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -209,7 +209,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]: '-3.7', '37', '-3.6', '36', '-3.5', '35', - '-15', # Debian development snapshot + '-19', # Debian development snapshot '-devel', # FreeBSD development snapshot ] names: T.List[str] = [] From e7c7f6fa378aa4181e7e171ea563632277d191b4 Mon Sep 17 00:00:00 2001 From: Stephan Lachnit Date: Mon, 18 Mar 2024 14:09:51 +0100 Subject: [PATCH 723/855] cmake: fix incorrect decorator for append_link_args Signed-off-by: Stephan Lachnit --- mesonbuild/modules/cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index fe6457511f99..cd5c5f66af9e 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -216,7 +216,7 @@ def set_install(self, state: ModuleState, args: T.Tuple[bool], kwargs: TYPE_kwar def append_compile_args(self, state: ModuleState, args: T.Tuple[str, T.List[str]], kwargs: TYPE_kwargs) -> None: self._get_opts(kwargs).append_args(args[0], args[1]) - @typed_pos_args('subproject_options.append_compile_args', varargs=str, min_varargs=1) + @typed_pos_args('subproject_options.append_link_args', varargs=str, min_varargs=1) @permittedKwargs({'target'}) def append_link_args(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> None: self._get_opts(kwargs).append_link_args(args[0]) From 192ce8224333dd3280d87b720547395e89a3b4b4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 10:24:02 -0800 Subject: [PATCH 724/855] unittests: annotate BasePlatformTests.setconf --- unittests/baseplatformtests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 93bfc8905b73..7c8543d0629d 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -289,9 +289,11 @@ def run_target(self, target, *, override_envvars=None): ''' return self.build(target=target, override_envvars=override_envvars) - def setconf(self, arg, will_build=True): - if not isinstance(arg, list): + def setconf(self, arg: T.Sequence[str], will_build: bool = True) -> None: + if isinstance(arg, str): arg = [arg] + else: + arg = list(arg) if will_build: ensure_backend_detects_changes(self.backend) self._run(self.mconf_command + arg + [self.builddir]) From c793dc478bf005417dae95f62b6d6fc4fae6e5d8 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 10:32:00 -0800 Subject: [PATCH 725/855] tests: Add tests for configure on changed options This demonstrates a limitation of Meson that can happen in the following situation: `meson setup builddir` (such as git pull) `meson configure -Dnew_option=value builddir` Since Meson is unaware of the updates to the meson.options file. The purposes of these tests is to fix this behavior. --- unittests/platformagnostictests.py | 103 ++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index e3c25c70b92d..969cbd747862 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2021 The Meson development team +# Copyright © 2024 Intel Corporation +from __future__ import annotations import json import os import pickle @@ -8,7 +10,7 @@ import subprocess import textwrap import shutil -from unittest import skipIf, SkipTest +from unittest import expectedFailure, skipIf, SkipTest from pathlib import Path from .baseplatformtests import BasePlatformTests @@ -315,3 +317,102 @@ def test_setup_with_unknown_option(self): for option in ('not_an_option', 'b_not_an_option'): out = self.init(testdir, extra_args=['--wipe', f'-D{option}=1'], allow_fail=True) self.assertIn(f'ERROR: Unknown options: "{option}"', out) + + @expectedFailure + def test_configure_new_option(self) -> None: + """Adding a new option without reconfiguring should work.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) + self.init(testdir) + with open(os.path.join(testdir, 'meson_options.txt'), 'a', encoding='utf-8') as f: + f.write("option('new_option', type : 'boolean', value : false)") + self.setconf('-Dnew_option=true') + self.assertEqual(self.getconf('new_option'), True) + + @expectedFailure + def test_configure_removed_option(self) -> None: + """Removing an options without reconfiguring should still give an error.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) + self.init(testdir) + with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f: + opts = f.readlines() + with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f: + for line in opts: + if line.startswith("option('neg'"): + continue + f.write(line) + with self.assertRaises(subprocess.CalledProcessError) as e: + self.setconf('-Dneg_int_opt=0') + self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout) + + @expectedFailure + def test_configure_option_changed_constraints(self) -> None: + """Changing the constraints of an option without reconfiguring should work.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) + self.init(testdir) + with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f: + opts = f.readlines() + with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f: + for line in opts: + if line.startswith("option('neg'"): + f.write("option('neg_int_opt', type : 'integer', min : -10, max : 10, value : -3)\n") + else: + f.write(line) + self.setconf('-Dneg_int_opt=-10') + self.assertEqual(self.getconf('neg_int_opt'), -10) + + @expectedFailure + def test_configure_meson_options_txt_to_meson_options(self) -> None: + """Changing from a meson_options.txt to meson.options should still be detected.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) + self.init(testdir) + with open(os.path.join(testdir, 'meson_options.txt'), 'r', encoding='utf-8') as f: + opts = f.readlines() + with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f: + for line in opts: + if line.startswith("option('neg'"): + f.write("option('neg_int_opt', type : 'integer', min : -10, max : 10, value : -3)\n") + else: + f.write(line) + shutil.move(os.path.join(testdir, 'meson_options.txt'), os.path.join(testdir, 'meson.options')) + self.setconf('-Dneg_int_opt=-10') + self.assertEqual(self.getconf('neg_int_opt'), -10) + + @expectedFailure + def test_configure_options_file_deleted(self) -> None: + """Deleting all option files should make seting a project option an error.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) + self.init(testdir) + os.unlink(os.path.join(testdir, 'meson_options.txt')) + with self.assertRaises(subprocess.CalledProcessError) as e: + self.setconf('-Dneg_int_opt=0') + self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout) + + @expectedFailure + def test_configure_options_file_added(self) -> None: + """A new project option file should be detected.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial')) + self.init(testdir) + with open(os.path.join(testdir, 'meson.options'), 'w', encoding='utf-8') as f: + f.write("option('new_option', type : 'string', value : 'foo')") + self.setconf('-Dnew_option=bar') + self.assertEqual(self.getconf('new_option'), 'bar') + + @expectedFailure + def test_configure_options_file_added_old(self) -> None: + """A new project option file should be detected.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial')) + self.init(testdir) + with open(os.path.join(testdir, 'meson_options.txt'), 'w', encoding='utf-8') as f: + f.write("option('new_option', type : 'string', value : 'foo')") + self.setconf('-Dnew_option=bar') + self.assertEqual(self.getconf('new_option'), 'bar') + + @expectedFailure + def test_configure_new_option_subproject(self) -> None: + """Adding a new option to a subproject without reconfiguring should work.""" + testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '43 subproject options')) + self.init(testdir) + with open(os.path.join(testdir, 'subprojects/subproject/meson_options.txt'), 'a', encoding='utf-8') as f: + f.write("option('new_option', type : 'boolean', value : false)") + self.setconf('-Dsubproject:new_option=true') + self.assertEqual(self.getconf('subproject:new_option'), True) From 8a10c8a5399077cb3cd8436914ad1d8a71d1a3e7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 11:47:07 -0800 Subject: [PATCH 726/855] coredata: remove extraneous keys when updating project_options This can happen when a project's meson.options file is updated, and an old option is removed. --- mesonbuild/ast/introspection.py | 4 +++- mesonbuild/coredata.py | 14 +++++++++++--- mesonbuild/interpreter/interpreter.py | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 046c0a2b69fd..17eb1d5b9669 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team +# Copyright © 2024 Intel Corporation # This class contains the basic functionality needed to run any interpreter # or an interpreter-based tool @@ -106,7 +107,8 @@ def func_project(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[st if os.path.exists(optfile): oi = optinterpreter.OptionInterpreter(self.subproject) oi.process(optfile) - self.coredata.update_project_options(oi.options) + assert isinstance(proj_name, str), 'for mypy' + self.coredata.update_project_options(oi.options, T.cast('SubProject', proj_name)) def_opts = self.flatten_args(kwargs.get('default_options', [])) _project_default_options = mesonlib.stringlistify(def_opts) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index df575981a69f..0c2f5010c5c0 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2013-2024 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations @@ -15,7 +15,7 @@ from dataclasses import dataclass from .mesonlib import ( - HoldableObject, + HoldableObject, MesonBugException, MesonException, EnvironmentException, MachineChoice, PerMachine, PerMachineDefaultable, default_libdir, default_libexecdir, default_prefix, default_datadir, default_includedir, default_infodir, @@ -40,6 +40,7 @@ from .environment import Environment from .mesonlib import FileOrString from .cmake.traceparser import CMakeCacheEntry + from .interpreterbase import SubProject class SharedCMDOptions(Protocol): @@ -892,13 +893,15 @@ def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.Lis # mypy cannot analyze type of OptionKey return T.cast('T.List[str]', self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value) - def update_project_options(self, options: 'MutableKeyedOptionDictType') -> None: + def update_project_options(self, options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None: for key, value in options.items(): if not key.is_project(): continue if key not in self.options: self.options[key] = value continue + if key.subproject != subproject: + raise MesonBugException(f'Tried to set an option for subproject {key.subproject} from {subproject}!') oldval = self.options[key] if type(oldval) is not type(value): @@ -914,6 +917,11 @@ def update_project_options(self, options: 'MutableKeyedOptionDictType') -> None: mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).', fatal=False) + # Find any extranious keys for this project and remove them + for key in list(self.options.keys() - options.keys()): + if key.is_project() and key.subproject == subproject: + del self.options[key] + def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool: if when_building_for == MachineChoice.BUILD: return False diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 47d0d2d2d5d3..d870de191b5c 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1035,7 +1035,7 @@ def _do_subproject_cargo(self, subp_name: str, subdir: str, FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node) with mlog.nested(subp_name): ast, options = cargo.interpret(subp_name, subdir, self.environment) - self.coredata.update_project_options(options) + self.coredata.update_project_options(options, subp_name) return self._do_subproject_meson( subp_name, subdir, default_options, kwargs, ast, # FIXME: Are there other files used by cargo interpreter? @@ -1189,7 +1189,7 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str if os.path.exists(option_file): oi = optinterpreter.OptionInterpreter(self.subproject) oi.process(option_file) - self.coredata.update_project_options(oi.options) + self.coredata.update_project_options(oi.options, self.subproject) self.add_build_def_file(option_file) if self.subproject: From c6875305f327a6be506d6544516f35e792f6d625 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 10:40:42 -0800 Subject: [PATCH 727/855] coredata: add tracking of the options files When we load the option file in the interpreter record which file it was, and what the hash of that file was. This will let `meson configure` know that the options have changed since the last re-configure. --- mesonbuild/coredata.py | 5 +++++ mesonbuild/interpreter/interpreter.py | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 0c2f5010c5c0..b12ec8203b27 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -575,6 +575,11 @@ def __init__(self, options: SharedCMDOptions, scratch_dir: str, meson_command: T self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict()) + # Stores the (name, hash) of the options file, The name will be either + # "meson_options.txt" or "meson.options". + # This is used by mconf to reload the option file if it's changed. + self.options_files: T.Dict[SubProject, T.Optional[T.Tuple[str, str]]] = {} + # Set of subprojects that have already been initialized once, this is # required to be stored and reloaded with the coredata, as we don't # want to overwrite options for such subprojects. diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d870de191b5c..2c1ac89f6c5f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -4,6 +4,8 @@ from __future__ import annotations +import hashlib + from .. import mparser from .. import environment from .. import coredata @@ -1187,10 +1189,16 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str else: option_file = old_option_file if os.path.exists(option_file): + with open(option_file, 'rb') as f: + # We want fast, not cryptographically secure, this is just to see of + # the option file has changed + self.coredata.options_files[self.subproject] = (option_file, hashlib.sha1(f.read()).hexdigest()) oi = optinterpreter.OptionInterpreter(self.subproject) oi.process(option_file) self.coredata.update_project_options(oi.options, self.subproject) self.add_build_def_file(option_file) + else: + self.coredata.options_files[self.subproject] = None if self.subproject: self.project_default_options = {k.evolve(subproject=self.subproject): v From 2d7b7c3aaf23d08d51f375fa1eea80e0ffffed87 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 8 Mar 2024 11:17:58 -0800 Subject: [PATCH 728/855] mconf: Reload the options files if they have changed This fixes issues where a new option is added, an option is removed, the constraints of an option are changed, an option file is added where one didn't previously exist, an option file is deleted, or it is renamed between meson_options.txt and meson.options There is one case that is known to not work, but it's probably a less common case, which is setting options for an unconfigured subproject. We could probably make that work in some cases, but I don't think it makes sense to download a wrap during meson configure. --- .../meson_configure_options_changes.md | 12 +++++++ mesonbuild/interpreter/interpreter.py | 4 +-- mesonbuild/mconf.py | 31 ++++++++++++++++++- unittests/platformagnostictests.py | 10 +----- 4 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 docs/markdown/snippets/meson_configure_options_changes.md diff --git a/docs/markdown/snippets/meson_configure_options_changes.md b/docs/markdown/snippets/meson_configure_options_changes.md new file mode 100644 index 000000000000..c86792ceb52a --- /dev/null +++ b/docs/markdown/snippets/meson_configure_options_changes.md @@ -0,0 +1,12 @@ +## 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/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 2c1ac89f6c5f..730eddd4a170 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1190,8 +1190,8 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str option_file = old_option_file if os.path.exists(option_file): with open(option_file, 'rb') as f: - # We want fast, not cryptographically secure, this is just to see of - # the option file has changed + # We want fast not cryptographically secure, this is just to + # see if the option file has changed self.coredata.options_files[self.subproject] = (option_file, hashlib.sha1(f.read()).hexdigest()) oi = optinterpreter.OptionInterpreter(self.subproject) oi.process(option_file) diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 8c18eab3102d..2cef24fd77e1 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -1,10 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2014-2016 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations import itertools +import hashlib import shutil import os import textwrap @@ -19,6 +20,7 @@ from . import mlog from .ast import AstIDGenerator, IntrospectionInterpreter from .mesonlib import MachineChoice, OptionKey +from .optinterpreter import OptionInterpreter if T.TYPE_CHECKING: from typing_extensions import Protocol @@ -77,6 +79,33 @@ def __init__(self, build_dir: str): self.source_dir = self.build.environment.get_source_dir() self.coredata = self.build.environment.coredata self.default_values_only = False + + # if the option file has been updated, reload it + # This cannot handle options for a new subproject that has not yet + # been configured. + for sub, options in self.coredata.options_files.items(): + if options is not None and os.path.exists(options[0]): + opfile = options[0] + with open(opfile, 'rb') as f: + ophash = hashlib.sha1(f.read()).hexdigest() + if ophash != options[1]: + oi = OptionInterpreter(sub) + oi.process(opfile) + self.coredata.update_project_options(oi.options, sub) + self.coredata.options_files[sub] = (opfile, ophash) + else: + opfile = os.path.join(self.source_dir, 'meson.options') + if not os.path.exists(opfile): + opfile = os.path.join(self.source_dir, 'meson_options.txt') + if os.path.exists(opfile): + oi = OptionInterpreter(sub) + oi.process(opfile) + self.coredata.update_project_options(oi.options, sub) + with open(opfile, 'rb') as f: + ophash = hashlib.sha1(f.read()).hexdigest() + self.coredata.options_files[sub] = (opfile, ophash) + else: + self.coredata.update_project_options({}, sub) elif os.path.isfile(os.path.join(self.build_dir, environment.build_filename)): # Make sure that log entries in other parts of meson don't interfere with the JSON output with mlog.no_logging(): diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index 969cbd747862..ba3f5013c55e 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -10,7 +10,7 @@ import subprocess import textwrap import shutil -from unittest import expectedFailure, skipIf, SkipTest +from unittest import skipIf, SkipTest from pathlib import Path from .baseplatformtests import BasePlatformTests @@ -318,7 +318,6 @@ def test_setup_with_unknown_option(self): out = self.init(testdir, extra_args=['--wipe', f'-D{option}=1'], allow_fail=True) self.assertIn(f'ERROR: Unknown options: "{option}"', out) - @expectedFailure def test_configure_new_option(self) -> None: """Adding a new option without reconfiguring should work.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) @@ -328,7 +327,6 @@ def test_configure_new_option(self) -> None: self.setconf('-Dnew_option=true') self.assertEqual(self.getconf('new_option'), True) - @expectedFailure def test_configure_removed_option(self) -> None: """Removing an options without reconfiguring should still give an error.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) @@ -344,7 +342,6 @@ def test_configure_removed_option(self) -> None: self.setconf('-Dneg_int_opt=0') self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout) - @expectedFailure def test_configure_option_changed_constraints(self) -> None: """Changing the constraints of an option without reconfiguring should work.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) @@ -360,7 +357,6 @@ def test_configure_option_changed_constraints(self) -> None: self.setconf('-Dneg_int_opt=-10') self.assertEqual(self.getconf('neg_int_opt'), -10) - @expectedFailure def test_configure_meson_options_txt_to_meson_options(self) -> None: """Changing from a meson_options.txt to meson.options should still be detected.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) @@ -377,7 +373,6 @@ def test_configure_meson_options_txt_to_meson_options(self) -> None: self.setconf('-Dneg_int_opt=-10') self.assertEqual(self.getconf('neg_int_opt'), -10) - @expectedFailure def test_configure_options_file_deleted(self) -> None: """Deleting all option files should make seting a project option an error.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '40 options')) @@ -387,7 +382,6 @@ def test_configure_options_file_deleted(self) -> None: self.setconf('-Dneg_int_opt=0') self.assertIn('Unknown options: "neg_int_opt"', e.exception.stdout) - @expectedFailure def test_configure_options_file_added(self) -> None: """A new project option file should be detected.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial')) @@ -397,7 +391,6 @@ def test_configure_options_file_added(self) -> None: self.setconf('-Dnew_option=bar') self.assertEqual(self.getconf('new_option'), 'bar') - @expectedFailure def test_configure_options_file_added_old(self) -> None: """A new project option file should be detected.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '1 trivial')) @@ -407,7 +400,6 @@ def test_configure_options_file_added_old(self) -> None: self.setconf('-Dnew_option=bar') self.assertEqual(self.getconf('new_option'), 'bar') - @expectedFailure def test_configure_new_option_subproject(self) -> None: """Adding a new option to a subproject without reconfiguring should work.""" testdir = self.copy_srcdir(os.path.join(self.common_test_dir, '43 subproject options')) From 069d89223769a380ccecd069a01e3bd5d71fdef3 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 20 Mar 2024 02:04:08 +0530 Subject: [PATCH 729/855] devenv: Don't use Path.relative_to() to resolve relative paths It's utterly broken, and only works when one path is inside the other: Traceback (most recent call last): File "/usr/lib/python3.12/site-packages/mesonbuild/mesonmain.py", line 194, in run return options.run_func(options) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/site-packages/mesonbuild/mdevenv.py", line 188, in run write_gdb_script(privatedir, install_data, workdir) File "/usr/lib/python3.12/site-packages/mesonbuild/mdevenv.py", line 142, in write_gdb_script rel_path = gdbinit_path.relative_to(workdir_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.12/pathlib.py", line 682, in relative_to raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}") ValueError: '/path/to/builddir/.gdbinit' is not in the subpath of '/path/to/workdir' ERROR: Unhandled python exception This is a Meson bug and should be reported! --- mesonbuild/mdevenv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index c8d0144c562f..cc69fb6e084b 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -10,7 +10,7 @@ from pathlib import Path from . import build, minstall from .mesonlib import (EnvironmentVariables, MesonException, is_windows, setup_vsenv, OptionKey, - get_wine_shortpath, MachineChoice) + get_wine_shortpath, MachineChoice, relpath) from . import mlog @@ -140,7 +140,7 @@ def write_gdb_script(privatedir: Path, install_data: 'InstallData', workdir: Pat if first_time: gdbinit_path = gdbinit_path.resolve() workdir_path = workdir.resolve() - rel_path = gdbinit_path.relative_to(workdir_path) + rel_path = Path(relpath(gdbinit_path, workdir_path)) mlog.log('Meson detected GDB helpers and added config in', mlog.bold(str(rel_path))) mlog.log('To load it automatically you might need to:') mlog.log(' - Add', mlog.bold(f'add-auto-load-safe-path {gdbinit_path.parent}'), From 4b5caa887851613878be29410decb45477f0a3bc Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 20 Mar 2024 02:47:03 +0530 Subject: [PATCH 730/855] mesonlib: Fix bug in relpath return values found by mypy --- mesonbuild/utils/universal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index a5383455aa0e..edb309f0d000 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1930,14 +1930,14 @@ def difference_update(self, iterable: T.Iterable[_T]) -> None: for item in iterable: self.discard(item) -def relpath(path: str, start: str) -> str: +def relpath(path: T.Union[str, Path], start: T.Union[str, Path]) -> str: # On Windows a relative path can't be evaluated for paths on two different # drives (i.e. c:\foo and f:\bar). The only thing left to do is to use the # original absolute path. try: return os.path.relpath(path, start) except (TypeError, ValueError): - return path + return str(path) def path_is_in_root(path: Path, root: Path, resolve: bool = False) -> bool: # Check whether a path is within the root directory root From 8480f3e795395edeb9b8c25ae5fae4afb05559c7 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Wed, 20 Mar 2024 16:47:15 -0400 Subject: [PATCH 731/855] fix: set `MSAN_OPTIONS` when not set, rather than `UBSAN_OPTIONS` --- mesonbuild/mtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 21414d2c5677..b9f72fac7dab 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1415,7 +1415,7 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, if ('UBSAN_OPTIONS' not in env or not env['UBSAN_OPTIONS']): env['UBSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' if ('MSAN_OPTIONS' not in env or not env['MSAN_OPTIONS']): - env['UBSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' + env['MSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0: timeout = None From 3c8be4fe2637498ee9e774bb95500226a17dd2e9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 27 Mar 2024 10:12:59 -0700 Subject: [PATCH 732/855] interpreter: fix return type annotation of helper --- mesonbuild/interpreter/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 730eddd4a170..f88f407de636 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2440,7 +2440,7 @@ def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtyp # It was likely added "because it exists", but should never be used. In # theory it is useful for directories, but we never apply modes to # directories other than in install_emptydir. - def _warn_kwarg_install_mode_sticky(self, mode: FileMode) -> None: + def _warn_kwarg_install_mode_sticky(self, mode: FileMode) -> FileMode: if mode.perms > 0 and mode.perms & stat.S_ISVTX: mlog.deprecation('install_mode with the sticky bit on a file does not do anything and will ' 'be ignored since Meson 0.64.0', location=self.current_node) From 2ae1bfa17b194fca328756f8d80cbef089d42673 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 27 Mar 2024 10:48:27 -0700 Subject: [PATCH 733/855] interpreter/type_checking: remove stale TODO comment --- mesonbuild/interpreter/type_checking.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 2ec7d58ceb38..1256495d1a00 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -285,7 +285,6 @@ def _env_convertor(value: _FullEnvInitValueType) -> EnvironmentVariables: COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File]]] = KwargInfo( 'command', - # TODO: should accept CustomTargetIndex as well? ContainerTypeInfo(list, (str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File), allow_empty=False), required=True, listify=True, From 80e1d28b042def24b7325f84247dadf94c507bfd Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Sun, 17 Mar 2024 08:14:44 +0100 Subject: [PATCH 734/855] tests: don't expect msys2 llvm cmake tests to skip with llvm 18 They were skipped with llvm 17 based on the version, and they are now no longer skipped with v18 and also pass now. This depends on #12964 for llvm 18 support in meson. --- test cases/frameworks/15 llvm/test.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test cases/frameworks/15 llvm/test.json b/test cases/frameworks/15 llvm/test.json index f9bb6458070e..fa883b1f43c6 100644 --- a/test cases/frameworks/15 llvm/test.json +++ b/test cases/frameworks/15 llvm/test.json @@ -3,8 +3,8 @@ "options": { "method": [ { "val": "config-tool", "expect_skip_on_jobname": ["msys2-gcc"] }, - { "val": "cmake", "expect_skip_on_jobname": ["msys2"] }, - { "val": "combination", "expect_skip_on_jobname": ["msys2"] } + { "val": "cmake", "expect_skip_on_jobname": ["msys2-gcc"] }, + { "val": "combination", "expect_skip_on_jobname": ["msys2-gcc"] } ], "link-static": [ { "val": true, "expect_skip_on_jobname": ["arch", "opensuse", "linux-gentoo-gcc"] }, From 509a140529328f316702411b8e9940a930340d52 Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 12 Mar 2024 22:37:44 +0000 Subject: [PATCH 735/855] compilers: cpp: relax assertion level for libc++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Followup to 90098473d51e6f059e775f1833b0a2ea91c8f8f9. I changed my mind on this a few times. libcxx's documentation describes [0] the hardening modes as: """ 1) Unchecked mode/none, which disables all hardening checks. 2) Fast mode, which contains a set of security-critical checks that can be done with relatively little overhead in constant time and are intended to be used in production. We recommend most projects adopt this. 3) Extensive mode, which contains all the checks from fast mode and some additional checks for undefined behavior that incur relatively little overhead but aren’t security-critical. Production builds requiring a broader set of checks than fast mode should consider enabling extensive mode. The additional rigour impacts performance more than fast mode: we recommend benchmarking to determine if that is acceptable for your program. 4) Debug mode, which enables all the available checks in the library, including internal assertions, some of which might be very expensive. This mode is intended to be used for testing, not in production. """ We chose 3) before because it felt like a better fit for what we're trying to do and the most equivalent option to libstdc++'s _GLIBCXX_ASSERTIONS, but on reflection, maybe we're better off picking a default with less overhead and more importantly guarantees constant time checks. [0] https://libcxx.llvm.org/Hardening.html#using-hardening-modes Bug: https://github.com/mesonbuild/meson/issues/12962 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 540dedb1878e..f0d763b61edf 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -315,7 +315,7 @@ def get_assert_args(self, disable: bool) -> T.List[str]: # Clang supports both libstdc++ and libc++ args.append('-D_GLIBCXX_ASSERTIONS=1') if version_compare(self.version, '>=18'): - args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE') + args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST') elif version_compare(self.version, '>=15'): args.append('-D_LIBCPP_ENABLE_ASSERTIONS=1') From 31314419aac57c45d82578700051f6ed999176af Mon Sep 17 00:00:00 2001 From: Sam James Date: Tue, 12 Mar 2024 22:52:03 +0000 Subject: [PATCH 736/855] compilers: cpp: don't set stdlib assertion macros if already set Followup to 90098473d51e6f059e775f1833b0a2ea91c8f8f9. If the compiler already has one of these assertion macros [0] set, then don't interfere. e.g. a Linux distribution might be setting a stricter default than usual. This is a pitfall many fell into with _FORTIFY_SOURCE and it's why AX_ADD_FORTIFY_SOURCE [1] was contributed to autoconf-archive. [0] _GLIBCXX_ASSERTIONS, _LIBCPP_HARDENING_MODE, or _LIBCPP_ENABLE_ASSERTIONS. [1] https://www.gnu.org/software/autoconf-archive/ax_add_fortify_source.html Bug: https://github.com/mesonbuild/meson/issues/12962 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f0d763b61edf..2a2f7615d293 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -312,7 +312,13 @@ def get_assert_args(self, disable: bool) -> T.List[str]: if disable: return ['-DNDEBUG'] + # Don't inject the macro if the compiler already has it pre-defined. + for macro in ['_GLIBCXX_ASSERTIONS', '_LIBCPP_HARDENING_MODE', '_LIBCPP_ENABLE_ASSERTIONS']: + if self.defines.get(macro) is not None: + return [] + # Clang supports both libstdc++ and libc++ + # TODO: Pipe through the C++ stdlib impl information to here so we can avoid pollution args.append('-D_GLIBCXX_ASSERTIONS=1') if version_compare(self.version, '>=18'): args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST') @@ -500,8 +506,13 @@ def get_assert_args(self, disable: bool) -> T.List[str]: if disable: return ['-DNDEBUG'] + # Don't inject the macro if the compiler already has it pre-defined. + if self.defines.get('_GLIBCXX_ASSERTIONS') is not None: + return [] + # XXX: This needs updating if/when GCC starts to support libc++. # It currently only does so via an experimental configure arg. + # TODO: Pipe through the C++ stdlib impl information to here so we can avoid pollution return ['-D_GLIBCXX_ASSERTIONS=1'] def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: From 5bd28febf7887eebc8e55aa6e39962ae7da51281 Mon Sep 17 00:00:00 2001 From: Sam James Date: Wed, 13 Mar 2024 01:13:23 +0000 Subject: [PATCH 737/855] Pass Environment down from Backend We'll need it in a moment for get_base_compile_args -> get_assert_args. Bug: https://github.com/mesonbuild/meson/issues/12962 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/backend/ninjabackend.py | 6 +++--- mesonbuild/backend/vs2010backend.py | 2 +- mesonbuild/compilers/compilers.py | 6 +++--- mesonbuild/compilers/cpp.py | 4 ++-- mesonbuild/compilers/cuda.py | 4 ++-- mesonbuild/compilers/d.py | 6 +++--- mesonbuild/compilers/mixins/clike.py | 2 +- mesonbuild/compilers/rust.py | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f7ba6468a495..0f738f7ff744 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1871,7 +1871,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: base_proxy = target.get_options() args = rustc.compiler_args() # Compiler args for compiling this target - args += compilers.get_base_compile_args(base_proxy, rustc) + args += compilers.get_base_compile_args(base_proxy, rustc, self.environment) self.generate_generator_list_rules(target) # dependencies need to cause a relink, they're not just for ordering @@ -2757,7 +2757,7 @@ def generate_llvm_ir_compile(self, target, src): compiler = get_compiler_for_source(target.compilers.values(), src) commands = compiler.compiler_args() # Compiler args for compiling this target - commands += compilers.get_base_compile_args(base_proxy, compiler) + commands += compilers.get_base_compile_args(base_proxy, compiler, self.environment) if isinstance(src, File): if src.is_built: src_filename = os.path.join(src.subdir, src.fname) @@ -2822,7 +2822,7 @@ def _generate_single_compile_base_args(self, target: build.BuildTarget, compiler # options passed on the command-line, in default_options, etc. # These have the lowest priority. commands += compilers.get_base_compile_args(base_proxy, - compiler) + compiler, self.environment) return commands @lru_cache(maxsize=None) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index c7b5bb53aae7..a2ece96a3f5a 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -984,7 +984,7 @@ def get_args_defines_and_inc_dirs(self, target, compiler, generated_files_includ for l, comp in target.compilers.items(): if l in file_args: file_args[l] += compilers.get_base_compile_args( - target.get_options(), comp) + target.get_options(), comp, self.environment) file_args[l] += comp.get_option_compile_args( target.get_options()) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 5854c9e603e8..58941b70d689 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -283,7 +283,7 @@ def are_asserts_disabled(options: KeyedOptionDictType) -> bool: options[OptionKey('buildtype')].value in {'release', 'plain'})) -def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: +def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', env: 'Environment') -> T.List[str]: args: T.List[str] = [] try: if options[OptionKey('b_lto')].value: @@ -314,7 +314,7 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') except KeyError: pass try: - args += compiler.get_assert_args(are_asserts_disabled(options)) + args += compiler.get_assert_args(are_asserts_disabled(options), env) except KeyError: pass # This does not need a try...except @@ -1060,7 +1060,7 @@ def get_coverage_args(self) -> T.List[str]: def get_coverage_link_args(self) -> T.List[str]: return self.linker.get_coverage_args() - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: """Get arguments to enable or disable assertion. :param disable: Whether to disable assertions diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 2a2f7615d293..c26def9fccbc 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -307,7 +307,7 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return libs return [] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: args: T.List[str] = [] if disable: return ['-DNDEBUG'] @@ -502,7 +502,7 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return libs return [] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if disable: return ['-DNDEBUG'] diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index ab4810798e5b..7f7ad74951a8 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -802,5 +802,5 @@ def get_profile_generate_args(self) -> T.List[str]: def get_profile_use_args(self) -> T.List[str]: return ['-Xcompiler=' + x for x in self.host_compiler.get_profile_use_args()] - def get_assert_args(self, disable: bool) -> T.List[str]: - return self.host_compiler.get_assert_args(disable) + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: + return self.host_compiler.get_assert_args(disable, env) diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 78ce2bc23aac..de344c05781a 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -696,7 +696,7 @@ def get_linker_always_args(self) -> T.List[str]: return args return args + ['-shared-libphobos'] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if disable: return ['-frelease'] return [] @@ -766,7 +766,7 @@ def get_linker_always_args(self) -> T.List[str]: return args return args + ['-link-defaultlib-shared'] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if disable: return ['--release'] return [] @@ -852,7 +852,7 @@ def get_linker_always_args(self) -> T.List[str]: return args return args + ['-defaultlib=phobos2', '-debuglib=phobos2'] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if disable: return ['-release'] return [] diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 09bd438818ca..b58b163a6cb9 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1309,7 +1309,7 @@ def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, boo return self.compiles(self.attribute_check_func(name), env, extra_args=self.get_has_func_attribute_extra_args(name)) - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if disable: return ['-DNDEBUG'] return [] diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 05e8b2b27745..0dc65bf33235 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -215,7 +215,7 @@ def get_pie_args(self) -> T.List[str]: # pic is on by rustc return [] - def get_assert_args(self, disable: bool) -> T.List[str]: + def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: action = "no" if disable else "yes" return ['-C', f'debug-assertions={action}', '-C', 'overflow-checks=no'] From 3e1e37f563916221d2b090df41f684ab37e843bb Mon Sep 17 00:00:00 2001 From: Sam James Date: Wed, 13 Mar 2024 01:14:30 +0000 Subject: [PATCH 738/855] compilers: cpp: factor out C++ stdlib detection We're going to use it in some more places in a minute (for controlling assertions). Bug: https://github.com/mesonbuild/meson/issues/12962 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index c26def9fccbc..449a6888b70f 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -183,6 +183,13 @@ class _StdCPPLibMixin(CompilerMixinBase): """Detect whether to use libc++ or libstdc++.""" + def language_stdlib_provider(self, env: Environment) -> str: + # https://stackoverflow.com/a/31658120 + header = 'version' if self.has_header('', '', env) else 'ciso646' + is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env)[0] + lib = 'c++' if is_libcxx else 'stdc++' + return lib + @functools.lru_cache(None) def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: """Detect the C++ stdlib and default search dirs @@ -202,11 +209,7 @@ def language_stdlib_only_link_flags(self, env: Environment) -> T.List[str]: machine = env.machines[self.for_machine] assert machine is not None, 'for mypy' - # https://stackoverflow.com/a/31658120 - header = 'version' if self.has_header('', '', env) else 'ciso646' - is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env)[0] - lib = 'c++' if is_libcxx else 'stdc++' - + lib = self.language_stdlib_provider(env) if self.find_library(lib, env, []) is not None: return search_dirs + [f'-l{lib}'] From a63739d394dd77314270f5a46f79171a8c544e77 Mon Sep 17 00:00:00 2001 From: Sam James Date: Wed, 13 Mar 2024 01:15:07 +0000 Subject: [PATCH 739/855] compilers: cpp: reduce macro pollution for stdlib macros Now that we have access to Environment in get_assert_args, we can check what the actual C++ stdlib provider is and only set relevant macros rather than all possibly-relevant ones based on the compiler. Also, while we're here, now that's sorted, wire up the GCC experimental libc++ support in the macro emission given it doesn't uglify anything for libstdc++ users now. Bug: https://github.com/mesonbuild/meson/issues/12962 Signed-off-by: Sam James Signed-off-by: Eli Schwartz --- mesonbuild/compilers/cpp.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 449a6888b70f..525c9fcdf378 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -311,7 +311,6 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: - args: T.List[str] = [] if disable: return ['-DNDEBUG'] @@ -320,15 +319,15 @@ def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: if self.defines.get(macro) is not None: return [] - # Clang supports both libstdc++ and libc++ - # TODO: Pipe through the C++ stdlib impl information to here so we can avoid pollution - args.append('-D_GLIBCXX_ASSERTIONS=1') - if version_compare(self.version, '>=18'): - args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST') - elif version_compare(self.version, '>=15'): - args.append('-D_LIBCPP_ENABLE_ASSERTIONS=1') + if self.language_stdlib_provider(env) == 'stdc++': + return ['-D_GLIBCXX_ASSERTIONS=1'] + else: + if version_compare(self.version, '>=18'): + return ['-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST'] + elif version_compare(self.version, '>=15'): + return ['-D_LIBCPP_ENABLE_ASSERTIONS=1'] - return args + return [] class ArmLtdClangCPPCompiler(ClangCPPCompiler): @@ -510,13 +509,19 @@ def get_assert_args(self, disable: bool, env: 'Environment') -> T.List[str]: return ['-DNDEBUG'] # Don't inject the macro if the compiler already has it pre-defined. - if self.defines.get('_GLIBCXX_ASSERTIONS') is not None: - return [] + for macro in ['_GLIBCXX_ASSERTIONS', '_LIBCPP_HARDENING_MODE', '_LIBCPP_ENABLE_ASSERTIONS']: + if self.defines.get(macro) is not None: + return [] + + if self.language_stdlib_provider(env) == 'stdc++': + return ['-D_GLIBCXX_ASSERTIONS=1'] + else: + if version_compare(self.version, '>=18'): + return ['-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST'] + elif version_compare(self.version, '>=15'): + return ['-D_LIBCPP_ENABLE_ASSERTIONS=1'] - # XXX: This needs updating if/when GCC starts to support libc++. - # It currently only does so via an experimental configure arg. - # TODO: Pipe through the C++ stdlib impl information to here so we can avoid pollution - return ['-D_GLIBCXX_ASSERTIONS=1'] + return [] def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: return ['-fpch-preprocess', '-include', os.path.basename(header)] From 458827a5b2fabe7d15f23f39f97626efe6f5a5fc Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2023 23:29:20 -0800 Subject: [PATCH 740/855] depscan: use a defaultdict to simplify append action --- mesonbuild/scripts/depscan.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index d5b8a0734c30..3a61370a92b6 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -1,8 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations +import collections import json import os import pathlib @@ -37,7 +39,7 @@ def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]): self.sources = sources self.provided_by: T.Dict[str, str] = {} self.exports: T.Dict[str, str] = {} - self.needs: T.Dict[str, T.List[str]] = {} + self.needs: collections.defaultdict[str, T.List[str]] = collections.defaultdict(list) self.sources_with_exports: T.List[str] = [] def scan_file(self, fname: str) -> None: @@ -63,10 +65,7 @@ def scan_fortran_file(self, fname: str) -> None: # In Fortran you have an using declaration also for the module # you define in the same file. Prevent circular dependencies. if needed not in modules_in_this_file: - if fname in self.needs: - self.needs[fname].append(needed) - else: - self.needs[fname] = [needed] + self.needs[fname].append(needed) if export_match: exported_module = export_match.group(1).lower() assert exported_module not in modules_in_this_file @@ -97,10 +96,7 @@ def scan_fortran_file(self, fname: str) -> None: # submodule (a1:a2) a3 <- requires a1@a2.smod # # a3 does not depend on the a1 parent module directly, only transitively. - if fname in self.needs: - self.needs[fname].append(parent_module_name_full) - else: - self.needs[fname] = [parent_module_name_full] + self.needs[fname].append(parent_module_name_full) def scan_cpp_file(self, fname: str) -> None: fpath = pathlib.Path(fname) @@ -109,10 +105,7 @@ def scan_cpp_file(self, fname: str) -> None: export_match = CPP_EXPORT_RE.match(line) if import_match: needed = import_match.group(1) - if fname in self.needs: - self.needs[fname].append(needed) - else: - self.needs[fname] = [needed] + self.needs[fname].append(needed) if export_match: exported_module = export_match.group(1) if exported_module in self.provided_by: From 2812b21de56c578ec552e182a071dbaa7f2463ee Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2023 23:31:13 -0800 Subject: [PATCH 741/855] backend/ninja: use A dataclass for TargetDependencyScannerInfo --- mesonbuild/backend/ninjabackend.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f7ba6468a495..e808b0c92eab 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team +# Copyright © 2023 Intel Corporation from __future__ import annotations @@ -134,10 +135,20 @@ def ninja_quote(text: str, is_build_line: bool = False) -> str: raise MesonException(errmsg) return quote_re.sub(r'$\g<0>', text) + +@dataclass class TargetDependencyScannerInfo: - def __init__(self, private_dir: str, source2object: T.Dict[str, str]): - self.private_dir = private_dir - self.source2object = source2object + + """Information passed to the depscanner about a target. + + :param private_dir: The private scratch directory for the target. + :param source2object: A mapping of source file names to the objects that + will be created from them. + """ + + private_dir: str + source2object: T.Dict[str, str] + @unique class Quoting(Enum): From 875a9b789f2f53fe0bd35d2bbe8277e8294e59f6 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2023 23:40:36 -0800 Subject: [PATCH 742/855] backend/ninja: remove duplicate isinstance() check --- 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 e808b0c92eab..4987d75a9087 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2782,10 +2782,11 @@ def generate_llvm_ir_compile(self, target, src): rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) rel_obj += '.' + self.environment.machines[target.for_machine].get_object_suffix() commands += self.get_compile_debugfile_args(compiler, target, rel_obj) - if isinstance(src, File) and src.is_built: - rel_src = src.fname - elif isinstance(src, File): - rel_src = src.rel_to_builddir(self.build_to_src) + if isinstance(src, File): + if src.is_built: + rel_src = src.fname + else: + rel_src = src.rel_to_builddir(self.build_to_src) else: raise InvalidArguments(f'Invalid source type: {src!r}') # Write the Ninja build command From 934c9074bdd81c31a67d87a290247007332cdbcf Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2023 23:41:12 -0800 Subject: [PATCH 743/855] backend/ninja: add missing typing annotations --- mesonbuild/backend/ninjabackend.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 4987d75a9087..d729d19892a8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -855,8 +855,8 @@ def generate_target(self, target): self.generate_custom_target(target) if isinstance(target, build.RunTarget): self.generate_run_target(target) - compiled_sources = [] - source2object = {} + compiled_sources: T.List[str] = [] + source2object: T.Dict[str, str] = {} name = target.get_id() if name in self.processed_targets: return @@ -939,7 +939,7 @@ def generate_target(self, target): # this target's sources (generated sources and preexisting sources). # This will be set as dependencies of all the target's sources. At the # same time, also deal with generated sources that need to be compiled. - generated_source_files = [] + generated_source_files: T.List[File] = [] for rel_src in generated_sources.keys(): raw_src = File.from_built_relative(rel_src) if self.environment.is_source(rel_src): @@ -1084,7 +1084,10 @@ def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: return False return True - def generate_dependency_scan_target(self, target: build.BuildTarget, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], + def generate_dependency_scan_target(self, target: build.BuildTarget, + compiled_sources: T.List[str], + source2object: T.Dict[str, str], + generated_source_files: T.List[mesonlib.File], object_deps: T.List['mesonlib.FileOrString']) -> None: if not self.should_use_dyndeps_for_target(target): return @@ -1113,7 +1116,7 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, compiled_so pickle.dump(scaninfo, p) self.add_build(elem) - def select_sources_to_scan(self, compiled_sources): + def select_sources_to_scan(self, compiled_sources: T.List[str]) -> T.List[str]: # in practice pick up C++ and Fortran files. If some other language # requires scanning (possibly Java to deal with inner class files) # then add them here. @@ -2763,7 +2766,7 @@ def get_link_debugfile_name(self, linker, target) -> T.Optional[str]: def get_link_debugfile_args(self, linker, target): return linker.get_link_debugfile_args(self.get_target_debug_filename(target)) - def generate_llvm_ir_compile(self, target, src): + def generate_llvm_ir_compile(self, target, src: mesonlib.FileOrString): base_proxy = target.get_options() compiler = get_compiler_for_source(target.compilers.values(), src) commands = compiler.compiler_args() @@ -2925,7 +2928,8 @@ def generate_single_compile(self, target: build.BuildTarget, src, is_generated: bool = False, header_deps=None, order_deps: T.Optional[T.List['mesonlib.FileOrString']] = None, extra_args: T.Optional[T.List[str]] = None, - unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None) -> None: + unity_sources: T.Optional[T.List[mesonlib.FileOrString]] = None, + ) -> T.Tuple[str, str]: """ Compiles C/C++, ObjC/ObjC++, Fortran, and D sources """ From fae1363bd3d4b6aec4b2de41f58385e277d91eca Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 11 Dec 2023 10:01:10 -0800 Subject: [PATCH 744/855] scripts/depscan: combine pickle and JSON data into a single file We don't need to write and pass two separate files to the depscanner, I've used the pickle because the pickle serializer/deserializer should be faster than JSON, thought I haven't tested. --- mesonbuild/backend/ninjabackend.py | 19 ++++++++----------- mesonbuild/scripts/depscan.py | 13 +++++-------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index d729d19892a8..77e1b04db465 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -144,10 +144,12 @@ class TargetDependencyScannerInfo: :param private_dir: The private scratch directory for the target. :param source2object: A mapping of source file names to the objects that will be created from them. + :param sources: A list of all the sources in this target """ private_dir: str source2object: T.Dict[str, str] + sources: T.List[str] @unique @@ -1095,25 +1097,20 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, pickle_base = target.name + '.dat' pickle_file = os.path.join(self.get_target_private_dir(target), pickle_base).replace('\\', '/') pickle_abs = os.path.join(self.get_target_private_dir_abs(target), pickle_base).replace('\\', '/') - json_abs = os.path.join(self.get_target_private_dir_abs(target), f'{target.name}-deps.json').replace('\\', '/') rule_name = 'depscan' scan_sources = self.select_sources_to_scan(compiled_sources) - # Dump the sources as a json list. This avoids potential problems where - # the number of sources passed to depscan exceeds the limit imposed by - # the OS. - with open(json_abs, 'w', encoding='utf-8') as f: - json.dump(scan_sources, f) - elem = NinjaBuildElement(self.all_outputs, depscan_file, rule_name, json_abs) - elem.add_item('picklefile', pickle_file) + scaninfo = TargetDependencyScannerInfo( + self.get_target_private_dir(target), source2object, scan_sources) + with open(pickle_abs, 'wb') as p: + pickle.dump(scaninfo, p) + + elem = NinjaBuildElement(self.all_outputs, depscan_file, rule_name, pickle_file) # Add any generated outputs to the order deps of the scan target, so # that those sources are present for g in generated_source_files: elem.orderdeps.add(g.relative_name()) elem.orderdeps.update(object_deps) - scaninfo = TargetDependencyScannerInfo(self.get_target_private_dir(target), source2object) - with open(pickle_abs, 'wb') as p: - pickle.dump(scaninfo, p) self.add_build(elem) def select_sources_to_scan(self, compiled_sources: T.List[str]) -> T.List[str]: diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index 3a61370a92b6..c0ac09b52ef1 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -5,7 +5,6 @@ from __future__ import annotations import collections -import json import os import pathlib import pickle @@ -32,11 +31,11 @@ FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE) class DependencyScanner: - def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]): + def __init__(self, pickle_file: str, outfile: str): with open(pickle_file, 'rb') as pf: self.target_data: TargetDependencyScannerInfo = pickle.load(pf) self.outfile = outfile - self.sources = sources + self.sources = self.target_data.sources self.provided_by: T.Dict[str, str] = {} self.exports: T.Dict[str, str] = {} self.needs: collections.defaultdict[str, T.List[str]] = collections.defaultdict(list) @@ -183,9 +182,7 @@ def scan(self) -> int: return 0 def run(args: T.List[str]) -> int: - assert len(args) == 3, 'got wrong number of arguments!' - pickle_file, outfile, jsonfile = args - with open(jsonfile, encoding='utf-8') as f: - sources = json.load(f) - scanner = DependencyScanner(pickle_file, outfile, sources) + assert len(args) == 2, 'got wrong number of arguments!' + outfile, pickle_file = args + scanner = DependencyScanner(pickle_file, outfile) return scanner.scan() From 433117fc5a604e34a847b3480bbec15e59585b96 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 20 Nov 2023 23:56:06 -0800 Subject: [PATCH 745/855] scripts/depscan: pick language once, at configure time We already have to decide whether to scan a file at configure time, so we don't want to have to do it again at compile time, every time the depscan rule is run. We can do this by saving and passing the language to use in the pickle, so depscan doesn't have to re-calculate it. As an added bonus, this removes an import from depscan --- mesonbuild/backend/ninjabackend.py | 21 +++++++++--------- mesonbuild/scripts/depscan.py | 34 +++++++++++------------------- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 77e1b04db465..462ea27fe268 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -144,12 +144,13 @@ class TargetDependencyScannerInfo: :param private_dir: The private scratch directory for the target. :param source2object: A mapping of source file names to the objects that will be created from them. - :param sources: A list of all the sources in this target + :param sources: a list of sources mapping them to the language rules to use + to scan them. """ private_dir: str source2object: T.Dict[str, str] - sources: T.List[str] + sources: T.List[T.Tuple[str, Literal['cpp', 'fortran']]] @unique @@ -1098,7 +1099,7 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, pickle_file = os.path.join(self.get_target_private_dir(target), pickle_base).replace('\\', '/') pickle_abs = os.path.join(self.get_target_private_dir_abs(target), pickle_base).replace('\\', '/') rule_name = 'depscan' - scan_sources = self.select_sources_to_scan(compiled_sources) + scan_sources = list(self.select_sources_to_scan(compiled_sources)) scaninfo = TargetDependencyScannerInfo( self.get_target_private_dir(target), source2object, scan_sources) @@ -1113,19 +1114,17 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, elem.orderdeps.update(object_deps) self.add_build(elem) - def select_sources_to_scan(self, compiled_sources: T.List[str]) -> T.List[str]: + def select_sources_to_scan(self, compiled_sources: T.List[str] + ) -> T.Iterable[T.Tuple[str, Literal['cpp', 'fortran']]]: # in practice pick up C++ and Fortran files. If some other language # requires scanning (possibly Java to deal with inner class files) # then add them here. - all_suffixes = set(compilers.lang_suffixes['cpp']) | set(compilers.lang_suffixes['fortran']) - selected_sources = [] for source in compiled_sources: ext = os.path.splitext(source)[1][1:] - if ext != 'C': - ext = ext.lower() - if ext in all_suffixes: - selected_sources.append(source) - return selected_sources + if ext.lower() in compilers.lang_suffixes['cpp'] or ext == 'C': + yield source, 'cpp' + elif ext.lower() in compilers.lang_suffixes['fortran']: + yield source, 'fortran' def process_target_dependencies(self, target): for t in target.get_dependencies(): diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index c0ac09b52ef1..79934fb5fae4 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -9,13 +9,12 @@ import pathlib import pickle import re -import sys import typing as T from ..backend.ninjabackend import ninja_quote -from ..compilers.compilers import lang_suffixes if T.TYPE_CHECKING: + from typing_extensions import Literal from ..backend.ninjabackend import TargetDependencyScannerInfo CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);') @@ -41,16 +40,11 @@ def __init__(self, pickle_file: str, outfile: str): self.needs: collections.defaultdict[str, T.List[str]] = collections.defaultdict(list) self.sources_with_exports: T.List[str] = [] - def scan_file(self, fname: str) -> None: - suffix = os.path.splitext(fname)[1][1:] - if suffix != 'C': - suffix = suffix.lower() - if suffix in lang_suffixes['fortran']: + def scan_file(self, fname: str, lang: Literal['cpp', 'fortran']) -> None: + if lang == 'fortran': self.scan_fortran_file(fname) - elif suffix in lang_suffixes['cpp']: - self.scan_cpp_file(fname) else: - sys.exit(f'Can not scan files with suffix .{suffix}.') + self.scan_cpp_file(fname) def scan_fortran_file(self, fname: str) -> None: fpath = pathlib.Path(fname) @@ -118,9 +112,8 @@ def objname_for(self, src: str) -> str: assert isinstance(objname, str) return objname - def module_name_for(self, src: str) -> str: - suffix = os.path.splitext(src)[1][1:].lower() - if suffix in lang_suffixes['fortran']: + def module_name_for(self, src: str, lang: Literal['cpp', 'fortran']) -> str: + if lang == 'fortran': exported = self.exports[src] # Module foo:bar goes to a file name foo@bar.smod # Module Foo goes to a file name foo.mod @@ -130,23 +123,20 @@ def module_name_for(self, src: str) -> str: else: extension = 'mod' return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}') - elif suffix in lang_suffixes['cpp']: - return '{}.ifc'.format(self.exports[src]) - else: - raise RuntimeError('Unreachable code.') + return '{}.ifc'.format(self.exports[src]) def scan(self) -> int: - for s in self.sources: - self.scan_file(s) + for s, lang in self.sources: + self.scan_file(s, lang) with open(self.outfile, 'w', encoding='utf-8') as ofile: ofile.write('ninja_dyndep_version = 1\n') - for src in self.sources: + for src, lang in self.sources: objfilename = self.objname_for(src) mods_and_submods_needed = [] module_files_generated = [] module_files_needed = [] if src in self.sources_with_exports: - module_files_generated.append(self.module_name_for(src)) + module_files_generated.append(self.module_name_for(src, lang)) if src in self.needs: for modname in self.needs[src]: if modname not in self.provided_by: @@ -159,7 +149,7 @@ def scan(self) -> int: for modname in mods_and_submods_needed: provider_src = self.provided_by[modname] - provider_modfile = self.module_name_for(provider_src) + provider_modfile = self.module_name_for(provider_src, lang) # Prune self-dependencies if provider_src != src: module_files_needed.append(provider_modfile) From 3e9021a4c421d88501ee04aaaebb0e03f1f05540 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 21 Nov 2023 00:01:37 -0800 Subject: [PATCH 746/855] scripts/depscan: remove unnecessary function This basically existed for an assert which we don't need, as mypy would catch that issue for us anyway. Removing the function entirely has some small performance advantages --- mesonbuild/scripts/depscan.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mesonbuild/scripts/depscan.py b/mesonbuild/scripts/depscan.py index 79934fb5fae4..44e805447713 100644 --- a/mesonbuild/scripts/depscan.py +++ b/mesonbuild/scripts/depscan.py @@ -107,11 +107,6 @@ def scan_cpp_file(self, fname: str) -> None: self.provided_by[exported_module] = fname self.exports[fname] = exported_module - def objname_for(self, src: str) -> str: - objname = self.target_data.source2object[src] - assert isinstance(objname, str) - return objname - def module_name_for(self, src: str, lang: Literal['cpp', 'fortran']) -> str: if lang == 'fortran': exported = self.exports[src] @@ -131,7 +126,7 @@ def scan(self) -> int: with open(self.outfile, 'w', encoding='utf-8') as ofile: ofile.write('ninja_dyndep_version = 1\n') for src, lang in self.sources: - objfilename = self.objname_for(src) + objfilename = self.target_data.source2object[src] mods_and_submods_needed = [] module_files_generated = [] module_files_needed = [] From 2f8d51c833546b048f453947278fe03f33b26e59 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 28 Mar 2024 13:57:18 -0700 Subject: [PATCH 747/855] backend/ninja: don't rewrite the pickle data if it hasn't changed Which prevents spurious rebuilds of dyndeps --- mesonbuild/backend/ninjabackend.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 462ea27fe268..a2e7c2bf58d0 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1103,8 +1103,16 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, scaninfo = TargetDependencyScannerInfo( self.get_target_private_dir(target), source2object, scan_sources) - with open(pickle_abs, 'wb') as p: - pickle.dump(scaninfo, p) + + write = True + if os.path.exists(pickle_abs): + with open(pickle_abs, 'rb') as p: + old = pickle.load(p) + write = old != scaninfo + + if write: + with open(pickle_abs, 'wb') as p: + pickle.dump(scaninfo, p) elem = NinjaBuildElement(self.all_outputs, depscan_file, rule_name, pickle_file) # Add any generated outputs to the order deps of the scan target, so From 2171a017be671283c7d68b60efba4404bedf5e64 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 28 Mar 2024 16:38:14 -0700 Subject: [PATCH 748/855] backend/ninja: Don't run -t cleandead when using dyndeps There's a known ninja bug (https://github.com/ninja-build/ninja/issues/1952) that running this with dyndeps will result in Ninja deleting implicit outputs from the dyndeps, leading to pointless rebuilds. For reference, this is what CMake does as well. --- mesonbuild/backend/ninjabackend.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a2e7c2bf58d0..88e880bca4e5 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -494,6 +494,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.created_llvm_ir_rule = PerMachine(False, False) self.rust_crates: T.Dict[str, RustCrate] = {} self.implicit_meson_outs = [] + self._uses_dyndeps = False def create_phony_target(self, dummy_outfile: str, rulename: str, phony_infilename: str) -> NinjaBuildElement: ''' @@ -669,7 +670,8 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional os.replace(tempfilename, outfilename) mlog.cmd_ci_include(outfilename) # For CI debugging # Refresh Ninja's caches. https://github.com/ninja-build/ninja/pull/1685 - if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists(os.path.join(self.environment.build_dir, '.ninja_log')): + # Cannot use when running with dyndeps: https://github.com/ninja-build/ninja/issues/1952 + if mesonlib.version_compare(self.ninja_version, '>=1.10.0') and os.path.exists(os.path.join(self.environment.build_dir, '.ninja_log')) and not self._uses_dyndeps: subprocess.call(self.ninja_command + ['-t', 'restat'], cwd=self.environment.build_dir) subprocess.call(self.ninja_command + ['-t', 'cleandead'], cwd=self.environment.build_dir) self.generate_compdb() @@ -1094,6 +1096,7 @@ def generate_dependency_scan_target(self, target: build.BuildTarget, object_deps: T.List['mesonlib.FileOrString']) -> None: if not self.should_use_dyndeps_for_target(target): return + self._uses_dyndeps = True depscan_file = self.get_dep_scan_file_for(target) pickle_base = target.name + '.dat' pickle_file = os.path.join(self.get_target_private_dir(target), pickle_base).replace('\\', '/') From 27caa765ff33e1343546ea026f341f60d2fb05c0 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 29 Mar 2024 22:05:36 +0200 Subject: [PATCH 749/855] Update Pip install documentation. --- docs/markdown/Quick-guide.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/markdown/Quick-guide.md b/docs/markdown/Quick-guide.md index 534055aa750c..14914567fda3 100644 --- a/docs/markdown/Quick-guide.md +++ b/docs/markdown/Quick-guide.md @@ -79,19 +79,20 @@ $ meson setup builddir $ bash: /usr/bin/meson: No such file or directory ``` -Description: The default installation prefix for the python pip module -installation is not included in your shell environment PATH. The -default prefix for python pip installation modules is located under -``/usr/local``. +**Description**: The default installation prefix for the python pip module +installation might not be included in your shell environment `PATH`. +The default install location varies depending on your OS, distro and +Python version. -**Resolution: -This issue can be resolved by altering the default shell environment -PATH to include ``/usr/local/bin``. ** +**Resolution**: This issue can be resolved by altering the default shell +environment `PATH` to include the path where Pip installed the +binaries. This can be, e.g. ``/usr/local/bin`` or +`/home//.local/bin`. -*Note: There are other ways of fixing this issue such as using +**Note**: There are other ways of fixing this issue such as using symlinks or copying the binaries to a default path and these methods are not recommended or supported as they may break package management - interoperability.* + interoperability. Compiling a Meson project From 78e9009ff9d36925e04f329f9082841002ddd848 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Wed, 27 Mar 2024 17:20:16 +0000 Subject: [PATCH 750/855] depfixer: change fix_darwin to act like fix_rpathtype_entry This somewhat aligns "darwin" (Mach-O) with how ELF RPATHs are treated. Instead of blindly removing all RPATHs, only remove the ones that are in the rpath_dirs_to_remove set. This way, RPATHs that were added by the toolchain or user are left untouched. It is important not to remove RPATHs as they may be vital for the executable at runtime. Issues #12045 and #12288 are examples of this. Issue: https://github.com/mesonbuild/meson/issues/12045 Signed-off-by: Fabian Groffen Signed-off-by: Eli Schwartz --- mesonbuild/scripts/depfixer.py | 53 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 61b7ffa642f1..71599f784e73 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -379,7 +379,7 @@ 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_to_remove(fname: str) -> T.List[str]: +def get_darwin_rpaths(fname: str) -> T.List[str]: p, out, _ = Popen_safe(['otool', '-l', fname], stderr=subprocess.DEVNULL) if p.returncode != 0: raise subprocess.CalledProcessError(p.returncode, p.args, out) @@ -397,43 +397,32 @@ def get_darwin_rpaths_to_remove(fname: str) -> T.List[str]: result.append(rp) return result -def fix_darwin(fname: str, new_rpath: str, final_path: str, install_name_mappings: T.Dict[str, str]) -> None: +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: try: - rpaths = get_darwin_rpaths_to_remove(fname) + old_rpaths = get_darwin_rpaths(fname) except subprocess.CalledProcessError: # Otool failed, which happens when invoked on a # non-executable target. Just return. return + new_rpaths: OrderedSet[str] = OrderedSet() + if new_rpath: + new_rpaths.update(new_rpath) + # filter out build-only rpath entries, like in + # fix_rpathtype_entry + remove_rpaths = [x.decode('utf8') for x in rpath_dirs_to_remove] + for rpath_dir in old_rpaths: + if rpath_dir and rpath_dir not in remove_rpaths: + new_rpaths.add(rpath_dir) try: args = [] - if rpaths: - # TODO: fix this properly, not totally clear how - # - # removing rpaths from binaries on macOS has tons of - # weird edge cases. For instance, if the user provided - # a '-Wl,-rpath' argument in LDFLAGS that happens to - # coincide with an rpath generated from a dependency, - # this would cause installation failures, as meson would - # generate install_name_tool calls with two identical - # '-delete_rpath' arguments, which install_name_tool - # fails on. Because meson itself ensures that it never - # adds duplicate rpaths, duplicate rpaths necessarily - # come from user variables. The idea of using OrderedSet - # is to remove *at most one* duplicate RPATH entry. This - # is not optimal, as it only respects the user's choice - # partially: if they provided a non-duplicate '-Wl,-rpath' - # argument, it gets removed, if they provided a duplicate - # one, it remains in the final binary. A potentially optimal - # solution would split all user '-Wl,-rpath' arguments from - # LDFLAGS, and later add them back with '-add_rpath'. - for rp in OrderedSet(rpaths): - args += ['-delete_rpath', rp] - subprocess.check_call(['install_name_tool', fname] + args, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) - args = [] - if new_rpath: - args += ['-add_rpath', new_rpath] + # compute diff, translate it into -delete_rpath and -add_rpath + # calls + for path in new_rpaths: + if path not in old_rpaths: + args += ['-add_rpath', path] + for path in old_rpaths: + if path not in new_rpaths: + args += ['-delete_rpath', path] # Rewrite -install_name @rpath/libfoo.dylib to /path/to/libfoo.dylib if fname.endswith('dylib'): args += ['-id', final_path] @@ -492,4 +481,4 @@ def fix_rpath(fname: str, rpath_dirs_to_remove: T.Set[bytes], new_rpath: T.Union if INSTALL_NAME_TOOL: if isinstance(new_rpath, bytes): new_rpath = new_rpath.decode('utf8') - fix_darwin(fname, new_rpath, final_path, install_name_mappings) + fix_darwin(fname, rpath_dirs_to_remove, new_rpath, final_path, install_name_mappings) From 2d010c693b97694a82458ba89d4da569e21c60aa Mon Sep 17 00:00:00 2001 From: Junior Rantila <40562373+juniorrantila@users.noreply.github.com> Date: Tue, 2 Apr 2024 05:01:00 +0200 Subject: [PATCH 751/855] nasm: Add support for .nasm file extension (#13027) --- mesonbuild/compilers/compilers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 58941b70d689..44b998a67cda 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -64,7 +64,7 @@ 'swift': ('swift',), 'java': ('java',), 'cython': ('pyx', ), - 'nasm': ('asm',), + 'nasm': ('asm', 'nasm',), 'masm': ('masm',), } all_languages = lang_suffixes.keys() From 456d879ff42624a5c67512022ab700518d869b21 Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Wed, 3 Apr 2024 13:47:23 +1000 Subject: [PATCH 752/855] Fix regression in TI CGT support When C6000 support was added in #12246, TI compilers were given the correct version argument. This broke the previous check which relied on an error being thrown by the compiler. --- mesonbuild/compilers/detect.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index f047242ca31b..c7d866be00bd 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -228,14 +228,13 @@ def detect_static_linker(env: 'Environment', compiler: Compiler) -> StaticLinker return linkers.CcrxLinker(linker) if out.startswith('GNU ar') and 'xc16-ar' in linker_name: return linkers.Xc16Linker(linker) - if "--> error: bad option 'e'" in err: # TI + if 'Texas Instruments Incorporated' in out: if 'ar2000' in linker_name: return linkers.C2000Linker(linker) + elif 'ar6000' in linker_name: + return linkers.C6000Linker(linker) else: return linkers.TILinker(linker) - if 'Texas Instruments Incorporated' in out: - if 'ar6000' in linker_name: - return linkers.C6000Linker(linker) if out.startswith('The CompCert'): return linkers.CompCertLinker(linker) if out.strip().startswith('Metrowerks') or out.strip().startswith('Freescale'): @@ -441,8 +440,8 @@ def sanitize(p: str) -> str: 'TI ARM C/C++ Compiler': (c.TICCompiler, cpp.TICPPCompiler, linkers.TIDynamicLinker), 'MSP430 C/C++': (c.TICCompiler, cpp.TICPPCompiler, linkers.TIDynamicLinker) } - for indentifier, compiler_classes in ti_compilers.items(): - if indentifier in out: + for identifier, compiler_classes in ti_compilers.items(): + if identifier in out: cls = compiler_classes[0] if lang == 'c' else compiler_classes[1] lnk = compiler_classes[2] env.coredata.add_lang_args(cls.language, cls, for_machine, env) From e00710a0a98e818418a62466284bdfc200142b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Thu, 4 Apr 2024 14:53:47 +0200 Subject: [PATCH 753/855] env2mfile: Only consume LDFLAGS for relevant languages It makes no sense to add them into vala_link_args, for example. --- mesonbuild/scripts/env2mfile.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mesonbuild/scripts/env2mfile.py b/mesonbuild/scripts/env2mfile.py index 2dfe6b05ef7d..bc0101e26d5b 100755 --- a/mesonbuild/scripts/env2mfile.py +++ b/mesonbuild/scripts/env2mfile.py @@ -273,7 +273,6 @@ def write_machine_file(infos: MachineInfo, ofilename: str, write_system_info: bo os.replace(tmpfilename, ofilename) def detect_language_args_from_envvars(langname: str, envvar_suffix: str = '') -> T.Tuple[T.List[str], T.List[str]]: - ldflags = tuple(shlex.split(os.environ.get('LDFLAGS' + envvar_suffix, ''))) compile_args = [] if langname in compilers.CFLAGS_MAPPING: compile_args = shlex.split(os.environ.get(compilers.CFLAGS_MAPPING[langname] + envvar_suffix, '')) @@ -282,7 +281,10 @@ def detect_language_args_from_envvars(langname: str, envvar_suffix: str = '') -> lang_compile_args = list(cppflags) + compile_args else: lang_compile_args = compile_args - lang_link_args = list(ldflags) + compile_args + lang_link_args = [] + if langname in compilers.LANGUAGES_USING_LDFLAGS: + lang_link_args += shlex.split(os.environ.get('LDFLAGS' + envvar_suffix, '')) + lang_link_args += compile_args return (lang_compile_args, lang_link_args) def detect_compilers_from_envvars(envvar_suffix: str = '') -> MachineInfo: From 06bc8a8d37620506ec5d176577fdc9f6ae5f011b Mon Sep 17 00:00:00 2001 From: Gerion Entrup Date: Mon, 11 Mar 2024 11:21:56 +0100 Subject: [PATCH 754/855] depends keyword argument: accept CustomTargetIndex That holds for all of these meson function: run_target, generator and custom_target and additionally to the Windows and Gnome module. --- docs/markdown/Windows-module.md | 2 +- docs/yaml/functions/custom_target.yaml | 5 +++-- docs/yaml/functions/generator.yaml | 5 +++-- docs/yaml/functions/run_target.yaml | 5 +++-- mesonbuild/backend/vs2010backend.py | 5 ++++- mesonbuild/build.py | 8 ++++---- mesonbuild/interpreter/type_checking.py | 6 +++--- test cases/common/51 run target/meson.build | 5 +++++ test cases/common/71 ctarget dependency/meson.build | 5 +++++ 9 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/markdown/Windows-module.md b/docs/markdown/Windows-module.md index c6d52841d16a..025f046cc955 100644 --- a/docs/markdown/Windows-module.md +++ b/docs/markdown/Windows-module.md @@ -12,7 +12,7 @@ Windows. windows.compile_resources(...(string | File | CustomTarget | CustomTargetIndex), args: []string, depend_files: [](string | File), - depends: [](BuildTarget | CustomTarget) + depends: [](BuildTarget | CustomTarget | CustomTargetIndex) include_directories: [](IncludeDirectories | string)): []CustomTarget ``` diff --git a/docs/yaml/functions/custom_target.yaml b/docs/yaml/functions/custom_target.yaml index caccd4883bf2..cd5c60e2e7bf 100644 --- a/docs/yaml/functions/custom_target.yaml +++ b/docs/yaml/functions/custom_target.yaml @@ -138,14 +138,15 @@ kwargs: argument. Useful for adding regen dependencies. depends: - type: list[build_tgt | custom_tgt] + type: list[build_tgt | custom_tgt | custom_idx] description: | Specifies that this target depends on the specified target(s), even though it does not take any of them as a command line argument. This is meant for cases where you have a tool that e.g. does globbing internally. Usually you should just put the generated sources as inputs and Meson will set up all dependencies - automatically. + automatically (custom_idx was unavailable as a type between 0.60 + and 1.4.0). depfile: type: str diff --git a/docs/yaml/functions/generator.yaml b/docs/yaml/functions/generator.yaml index cec0b79e3b3f..6079d300f107 100644 --- a/docs/yaml/functions/generator.yaml +++ b/docs/yaml/functions/generator.yaml @@ -50,12 +50,13 @@ kwargs: depends: # Not sure why this is not just `target` - type: list[build_tgt | custom_tgt] + type: list[build_tgt | custom_tgt | custom_idx] since: 0.51.0 description: | An array of build targets that must be built before this generator can be run. This is used if you have a generator that calls - a second executable that is built in this project. + a second executable that is built in this project (custom_idx was not + available between 0.60 and 1.4.0). depfile: type: str diff --git a/docs/yaml/functions/run_target.yaml b/docs/yaml/functions/run_target.yaml index 66d6e8f1dd04..3ede1c91e0de 100644 --- a/docs/yaml/functions/run_target.yaml +++ b/docs/yaml/functions/run_target.yaml @@ -40,11 +40,12 @@ kwargs: the first item will find that command in `PATH` and run it. depends: - type: list[build_tgt | custom_tgt] + type: list[build_tgt | custom_tgt | custom_idx] description: | A list of targets that this target depends on but which are not listed in the command array (because, for example, the - script does file globbing internally) + script does file globbing internally, custom_idx was not possible + as a type between 0.60 and 1.4.0). env: since: 0.57.0 diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index a2ece96a3f5a..20ad266f0f52 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -324,9 +324,12 @@ def get_obj_target_deps(self, obj_list): result[o.target.get_id()] = o.target return result.items() - def get_target_deps(self, t: T.Dict[T.Any, build.Target], recursive=False): + def get_target_deps(self, t: T.Dict[T.Any, T.Union[build.Target, build.CustomTargetIndex]], recursive=False): all_deps: T.Dict[str, build.Target] = {} for target in t.values(): + if isinstance(target, build.CustomTargetIndex): + # just transfer it to the CustomTarget code + target = target.target if isinstance(target, build.CustomTarget): for d in target.get_target_dependencies(): # FIXME: this isn't strictly correct, as the target doesn't diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 2b6ce8875f17..6f0d6a2ddaac 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -2815,11 +2815,11 @@ class RunTarget(Target, CommandBase): def __init__(self, name: str, command: T.Sequence[T.Union[str, File, BuildTargetTypes, programs.ExternalProgram]], - dependencies: T.Sequence[Target], + dependencies: T.Sequence[T.Union[Target, CustomTargetIndex]], subdir: str, subproject: str, environment: environment.Environment, - env: T.Optional['EnvironmentVariables'] = None, + env: T.Optional[EnvironmentVariables] = None, default_env: bool = True): # These don't produce output artifacts super().__init__(name, subdir, subproject, False, MachineChoice.BUILD, environment) @@ -2834,10 +2834,10 @@ def __repr__(self) -> str: repr_str = "<{0} {1}: {2}>" return repr_str.format(self.__class__.__name__, self.get_id(), self.command[0]) - def get_dependencies(self) -> T.List[T.Union[BuildTarget, 'CustomTarget']]: + def get_dependencies(self) -> T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]: return self.dependencies - def get_generated_sources(self) -> T.List['GeneratedTypes']: + def get_generated_sources(self) -> T.List[GeneratedTypes]: return [] def get_sources(self) -> T.List[File]: diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 1256495d1a00..9b7e35c637ef 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -268,12 +268,12 @@ def _env_convertor(value: _FullEnvInitValueType) -> EnvironmentVariables: validator=lambda x: 'Depfile must be a plain filename with a subdirectory' if has_path_sep(x) else None ) -# TODO: CustomTargetIndex should be supported here as well -DEPENDS_KW: KwargInfo[T.List[T.Union[BuildTarget, CustomTarget]]] = KwargInfo( +DEPENDS_KW: KwargInfo[T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]]] = KwargInfo( 'depends', - ContainerTypeInfo(list, (BuildTarget, CustomTarget)), + ContainerTypeInfo(list, (BuildTarget, CustomTarget, CustomTargetIndex)), listify=True, default=[], + since_values={CustomTargetIndex: '1.5.0'}, ) DEPEND_FILES_KW: KwargInfo[T.List[T.Union[str, File]]] = KwargInfo( diff --git a/test cases/common/51 run target/meson.build b/test cases/common/51 run target/meson.build index dbb67322030a..3b5c16b3a898 100644 --- a/test cases/common/51 run target/meson.build +++ b/test cases/common/51 run target/meson.build @@ -33,6 +33,11 @@ run_target('upload2', depends : hex, ) +run_target('upload3', + command : [fakeburner, 'x:@0@:y'.format(hex.full_path())], + depends : hex[0], +) + python3 = find_program('python3', required : false) if not python3.found() python3 = find_program('python') diff --git a/test cases/common/71 ctarget dependency/meson.build b/test cases/common/71 ctarget dependency/meson.build index 40f7398fbd20..d3e73cec7f33 100644 --- a/test cases/common/71 ctarget dependency/meson.build +++ b/test cases/common/71 ctarget dependency/meson.build @@ -18,3 +18,8 @@ custom_target('output', output : 'output.dat', command : [g2, '@OUTDIR@', '@OUTPUT@'], depends : c1) + +custom_target('output2', +output : 'output2.dat', +command : [g2, '@OUTDIR@', '@OUTPUT@'], +depends : c1[0]) From 82399123797a838d92b60cdc0e56e1b34536aea6 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 30 Nov 2022 18:14:42 -0300 Subject: [PATCH 755/855] compilers: Ensure -L flags do not get reordered when used with MSVC If -L flags get into CLikeCompiler::build_wrapper_args, they will be correctly detected and the /LINK flag added to the list. However, CompilerArgs::__iadd__ will reorder them to the front, thinking they're GNU-style flags, and this will cause MSVC to ignore them after conversion. The fix is twofold: 1. Convert all the linker args into their compiler form, making sure the /LINK argument is dropped (see 2) 2. Insert /LINK into extra_args if not already present 3. Execute in situ the unix_to_native replacement, ensuring no further reordering occurs. Fixes #11113 --- mesonbuild/compilers/mixins/clike.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index b58b163a6cb9..ac2344bf857e 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -440,14 +440,20 @@ def build_wrapper_args(self, env: 'Environment', ca, la = self._get_basic_compiler_args(env, mode) cargs += ca - largs += la cargs += self.get_compiler_check_args(mode) # on MSVC compiler and linker flags must be separated by the "/link" argument # at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here - if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and '/link' not in extra_args: - extra_args += ['/link'] + largs += [l for l in self.linker_to_compiler_args(la) if l != '/link'] + + if self.linker_to_compiler_args([]) == ['/link']: + if largs != [] and '/link' not in extra_args: + extra_args += ['/link'] + # all linker flags must be converted now, otherwise the reordering + # of arglist will apply and -L flags will be reordered into + # breaking form. See arglist._should_prepend + largs = self.unix_args_to_native(largs) args = cargs + extra_args + largs return args From d86fce9594bd942da681aac3c8041202a7c38938 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 16 Jan 2024 23:06:04 -0300 Subject: [PATCH 756/855] compilers: Add test for detecting libraries with externally supplied linker flags --- .../lib/.gitignore | 2 ++ .../meson.build | 33 +++++++++++++++++++ .../nativefile.ini.in | 9 +++++ .../22 msvc library argument order/source.c | 3 ++ 4 files changed, 47 insertions(+) create mode 100644 test cases/windows/22 msvc library argument order/lib/.gitignore create mode 100644 test cases/windows/22 msvc library argument order/meson.build create mode 100644 test cases/windows/22 msvc library argument order/nativefile.ini.in create mode 100644 test cases/windows/22 msvc library argument order/source.c diff --git a/test cases/windows/22 msvc library argument order/lib/.gitignore b/test cases/windows/22 msvc library argument order/lib/.gitignore new file mode 100644 index 000000000000..b072cc19064f --- /dev/null +++ b/test cases/windows/22 msvc library argument order/lib/.gitignore @@ -0,0 +1,2 @@ +*.obj +*.lib diff --git a/test cases/windows/22 msvc library argument order/meson.build b/test cases/windows/22 msvc library argument order/meson.build new file mode 100644 index 000000000000..39a6efe7b203 --- /dev/null +++ b/test cases/windows/22 msvc library argument order/meson.build @@ -0,0 +1,33 @@ +project('can-this-find-an-external-library', 'c') + +cc = meson.get_compiler('c') + +if cc.get_argument_syntax() != 'msvc' + error('MESON_SKIP_TEST: test is only relevant for msvc and clang-cl') +endif + +# We need to conjure a static library for the current architecture +# Generate an object file manually. +run_command( + [ + meson.get_compiler('c').cmd_array().get(-1), + '/nologo', + '/MDd', + '/Fo@0@'.format(meson.current_source_dir() / 'lib' / 'source.obj'), + '/c', + files('source.c'), + ], + check: true +) +# Turn it into a library. +run_command( + [ + find_program('LIB'), + '/OUT:@0@'.format(meson.current_source_dir() / 'lib' / 'conjured.lib'), + meson.current_source_dir() / 'lib' / 'source.obj', + ], + check: true +) + +# Ensure this library can be found +dep = cc.find_library('conjured', required: true) diff --git a/test cases/windows/22 msvc library argument order/nativefile.ini.in b/test cases/windows/22 msvc library argument order/nativefile.ini.in new file mode 100644 index 000000000000..2beab5148d61 --- /dev/null +++ b/test cases/windows/22 msvc library argument order/nativefile.ini.in @@ -0,0 +1,9 @@ +[constants] +common_args = ['-I@MESON_TEST_ROOT@/include'] +common_link_args = ['-LIBPATH:@MESON_TEST_ROOT@/lib'] + +[properties] +c_args = common_args +cpp_args = common_args +c_link_args = common_link_args +cpp_link_args = common_link_args diff --git a/test cases/windows/22 msvc library argument order/source.c b/test cases/windows/22 msvc library argument order/source.c new file mode 100644 index 000000000000..1dc08e168c18 --- /dev/null +++ b/test cases/windows/22 msvc library argument order/source.c @@ -0,0 +1,3 @@ +int func1_in_obj(void) { + return 0; +} From e455cb09485d6251575c88280f8f384d13822f02 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2024 14:28:36 -0700 Subject: [PATCH 757/855] interpreter/compiler: Fortran.run() has always worked This incorrectly warns that `compiler.run()` is new in 1.5.0 for Fortran, but that works fine for older versions (noted with 1.2.3). This makes sense, as FortranCompiler inherits CLikeCompiler --- mesonbuild/interpreter/compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 0f91ba1e0bbc..fb43035a565f 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team -# Copyright © 2021 Intel Corporation +# Copyright © 2021-2024 Intel Corporation from __future__ import annotations import collections @@ -302,7 +302,7 @@ def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int: @typed_pos_args('compiler.run', (str, mesonlib.File)) @typed_kwargs('compiler.run', *_COMPILES_KWS) def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult': - if self.compiler.language not in {'d', 'c', 'cpp', 'objc', 'objcpp'}: + if self.compiler.language not in {'d', 'c', 'cpp', 'objc', 'objcpp', 'fortran'}: FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language', '1.5.0', self.subproject, location=self.current_node) code = args[0] From 24a96a3c95ea935c169b038ed91bf6379184ad66 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Mon, 25 Mar 2024 08:18:13 +0100 Subject: [PATCH 758/855] On OpenBSD there's no convention the .so numbers equal the boost version. Skip the check filtering on that condition. --- mesonbuild/dependencies/boost.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index a72b3d162f01..32932853c0c1 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -594,7 +594,8 @@ def filter_libraries(self, libs: T.List[BoostLibraryFile], lib_vers: str) -> T.L # mlog.debug(' - vscrt: {}'.format(vscrt)) libs = [x for x in libs if x.static == self.static or not self.explicit_static] libs = [x for x in libs if x.mt == self.multithreading] - libs = [x for x in libs if x.version_matches(lib_vers)] + if not self.env.machines[self.for_machine].is_openbsd(): + libs = [x for x in libs if x.version_matches(lib_vers)] libs = [x for x in libs if x.arch_matches(self.arch)] libs = [x for x in libs if x.vscrt_matches(vscrt)] libs = [x for x in libs if x.nvsuffix != 'dll'] # Only link to import libraries From b053eaba004f6dd291932e22b864786cf03134ab Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Mon, 8 Apr 2024 09:36:23 -0600 Subject: [PATCH 759/855] Update Users.md --- docs/markdown/Users.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index b28e4d635eb4..b0cc949ee9e7 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -167,15 +167,18 @@ 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 - - [TSCL Xtest](https://github.com/trilobite-stdlib/tscl-xtest-c), a framework for testing C/C++ code - - [TSCL Xmock](https://github.com/trilobite-stdlib/tscl-xtest-c), a framework for mocking C/C++ code - - [TSCL Xmemory](https://github.com/trilobite-stdlib/tscl-xmemory-c), a library for low-level, memory and bitwise operations in C - - [TSCL Xscience](https://github.com/trilobite-stdlib/tscl-xscience-c), a library for scientific calculations in C - - [TSCL Xstring](https://github.com/trilobite-stdlib/tscl-xstring-c), a library for working with strings and ciphers in C - - [TSCL Xdata](https://github.com/trilobite-stdlib/tscl-xdata-c), a library with data structures and algorithms in C - - [TSCL Xutil](https://github.com/trilobite-stdlib/tscl-xutil-c), a library with utilities for the most tedious task in C - - [TSCL Xmath](https://github.com/trilobite-stdlib/tscl-xmath-c), a library with mathematical components for projects in C - - [TSCL Xcore](https://github.com/trilobite-stdlib/tscl-xcore-c), a core framework with essentials for any projects in C + - [FSCL XTest](https://github.com/fossil-lib/tscl-xtest-c), a framework for testing C/C++ code + - [FSCL XMock](https://github.com/fossil-lib/tscl-xmock-c), a framework for mocking C/C++ code + - [FSCL XCore](https://github.com/fossil-lib/tscl-xcore-c), essintal compoments for C code + - [FSCL XTool](https://github.com/fossil-lib/tscl-xtool-c), essintal tool for low-level related task + - [FSCL XString](https://github.com/fossil-lib/tscl-xstring-c), string and char types in C + - [FSCL XToFu](https://github.com/fossil-lib/tscl-xtofu-c), a framework for generic types in C + - [FSCL XJellyfish](https://github.com/fossil-lib/tscl-xfish-c), a framework for AI development using JellyFish in C + - [FSCL XStructure](https://github.com/fossil-lib/tscl-xstructure-c), a framework for data structures in C + - [FSCL XAlgorithm](https://github.com/fossil-lib/tscl-xalgorithm-c), a framework for algorithms C + - [FSCL XPattern](https://github.com/fossil-lib/tscl-xpattern-c), a framework for design patterns C + - [FSCL XScience](https://github.com/fossil-lib/tscl-xscience-c), a framework for scientific projects in C + - [FSCL XCube](https://github.com/fossil-lib/tscl-xcube-c), a framework for creating a portable curses TUI in C - [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 bec84aced51f2dbc21a889f0d7c1869a4bbf6f5d Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Tue, 26 Sep 2023 09:18:01 -0400 Subject: [PATCH 760/855] Fix type checking in ast.printer - Wrong types were used for MultilineStringNode and FormatMultilineStringNode - Simplify the `escape` method to avoid use of T.Cast --- mesonbuild/ast/printer.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 06b05ba89c9f..e2191f9b7662 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -65,9 +65,7 @@ def visit_NumberNode(self, node: mparser.NumberNode) -> None: node.lineno = self.curr_line or node.lineno def escape(self, val: str) -> str: - return val.translate(str.maketrans(T.cast( - 'T.Dict[str, T.Union[str, int]]', - {'\'': '\\\'', '\\': '\\\\'}))) + return val.replace('\\', '\\\\').replace("'", "\'") def visit_StringNode(self, node: mparser.StringNode) -> None: assert isinstance(node.value, str) @@ -79,12 +77,12 @@ def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.append("f'" + self.escape(node.value) + "'", node) node.lineno = self.curr_line or node.lineno - def visit_MultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: + def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: assert isinstance(node.value, str) self.append("'''" + node.value + "'''", node) node.lineno = self.curr_line or node.lineno - def visit_FormatMultilineStringNode(self, node: mparser.FormatStringNode) -> None: + def visit_FormatMultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: assert isinstance(node.value, str) self.append("f'''" + node.value + "'''", node) node.lineno = self.curr_line or node.lineno From 154b9e78d556f7b11c0bf5200f3012d6a0bb7384 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 14 Sep 2023 15:04:43 -0400 Subject: [PATCH 761/855] fix colon wrongly named column in parser In #02ff955, I used the word `columns` instead of `colons`, but the meaning really was about the ':' symbol. --- mesonbuild/ast/printer.py | 10 +++++----- mesonbuild/mparser.py | 28 ++++++++++++++-------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index e2191f9b7662..4fa120c5aa50 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -391,7 +391,7 @@ def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: varname.accept(self) if comma is not None: comma.accept(self) - node.column.accept(self) + node.colon.accept(self) node.items.accept(self) node.block.accept(self) node.endforeach.accept(self) @@ -427,7 +427,7 @@ def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: node.condition.accept(self) node.questionmark.accept(self) node.trueblock.accept(self) - node.column.accept(self) + node.colon.accept(self) node.falseblock.accept(self) if node.whitespaces: node.whitespaces.accept(self) @@ -443,10 +443,10 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: except StopIteration: pass - assert len(node.columns) == len(node.kwargs) - for (key, val), column in zip(node.kwargs.items(), node.columns): + assert len(node.colons) == len(node.kwargs) + for (key, val), colon in zip(node.kwargs.items(), node.colons): key.accept(self) - column.accept(self) + colon.accept(self) val.accept(self) try: comma = next(commas_iter) diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index baccd2753e59..c1bceb294a76 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -338,14 +338,14 @@ class ArgumentNode(BaseNode): arguments: T.List[BaseNode] = field(hash=False) commas: T.List[SymbolNode] = field(hash=False) - columns: T.List[SymbolNode] = field(hash=False) + colons: T.List[SymbolNode] = field(hash=False) kwargs: T.Dict[BaseNode, BaseNode] = field(hash=False) def __init__(self, token: Token[TV_TokenTypes]): super().__init__(token.lineno, token.colno, token.filename) self.arguments = [] self.commas = [] - self.columns = [] + self.colons = [] self.kwargs = {} self.order_error = False @@ -556,17 +556,17 @@ class ForeachClauseNode(BaseNode): foreach_: SymbolNode = field(hash=False) varnames: T.List[IdNode] = field(hash=False) commas: T.List[SymbolNode] = field(hash=False) - column: SymbolNode = field(hash=False) + colon: SymbolNode = field(hash=False) items: BaseNode block: CodeBlockNode endforeach: SymbolNode = field(hash=False) - def __init__(self, foreach_: SymbolNode, varnames: T.List[IdNode], commas: T.List[SymbolNode], column: SymbolNode, items: BaseNode, block: CodeBlockNode, endforeach: SymbolNode): + def __init__(self, foreach_: SymbolNode, varnames: T.List[IdNode], commas: T.List[SymbolNode], colon: SymbolNode, items: BaseNode, block: CodeBlockNode, endforeach: SymbolNode): super().__init__(foreach_.lineno, foreach_.colno, foreach_.filename) self.foreach_ = foreach_ self.varnames = varnames self.commas = commas - self.column = column + self.colon = colon self.items = items self.block = block self.endforeach = endforeach @@ -629,15 +629,15 @@ class TernaryNode(BaseNode): condition: BaseNode questionmark: SymbolNode trueblock: BaseNode - column: SymbolNode + colon: SymbolNode falseblock: BaseNode - def __init__(self, condition: BaseNode, questionmark: SymbolNode, trueblock: BaseNode, column: SymbolNode, falseblock: BaseNode): + def __init__(self, condition: BaseNode, questionmark: SymbolNode, trueblock: BaseNode, colon: SymbolNode, falseblock: BaseNode): super().__init__(condition.lineno, condition.colno, condition.filename) self.condition = condition self.questionmark = questionmark self.trueblock = trueblock - self.column = column + self.colon = colon self.falseblock = falseblock @@ -780,10 +780,10 @@ def e1(self) -> BaseNode: self.in_ternary = True trueblock = self.e1() self.expect('colon') - column_node = self.create_node(SymbolNode, self.previous) + colon_node = self.create_node(SymbolNode, self.previous) falseblock = self.e1() self.in_ternary = False - return self.create_node(TernaryNode, left, qm_node, trueblock, column_node, falseblock) + return self.create_node(TernaryNode, left, qm_node, trueblock, colon_node, falseblock) return left def e2(self) -> BaseNode: @@ -946,7 +946,7 @@ def key_values(self) -> ArgumentNode: while not isinstance(s, EmptyNode): if self.accept('colon'): - a.columns.append(self.create_node(SymbolNode, self.previous)) + a.colons.append(self.create_node(SymbolNode, self.previous)) a.set_kwarg_no_check(s, self.statement()) if not self.accept('comma'): return a @@ -966,7 +966,7 @@ def args(self) -> ArgumentNode: a.commas.append(self.create_node(SymbolNode, self.previous)) a.append(s) elif self.accept('colon'): - a.columns.append(self.create_node(SymbolNode, self.previous)) + a.colons.append(self.create_node(SymbolNode, self.previous)) if not isinstance(s, IdNode): raise ParseException('Dictionary key must be a plain identifier.', self.getline(), s.lineno, s.colno) @@ -1021,11 +1021,11 @@ def foreachblock(self) -> ForeachClauseNode: varnames.append(self.create_node(IdNode, self.previous)) self.expect('colon') - column = self.create_node(SymbolNode, self.previous) + colon = self.create_node(SymbolNode, self.previous) items = self.statement() block = self.codeblock() endforeach = self.create_node(SymbolNode, self.current) - return self.create_node(ForeachClauseNode, foreach_, varnames, commas, column, items, block, endforeach) + return self.create_node(ForeachClauseNode, foreach_, varnames, commas, colon, items, block, endforeach) def ifblock(self) -> IfClauseNode: if_node = self.create_node(SymbolNode, self.previous) From be9e9af15a654e0a17992489b34ba14ba80ae7a2 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 14 Sep 2023 15:05:44 -0400 Subject: [PATCH 762/855] Add ast visitor for whitespaces and symbols The `AstVisitor` intentionally ignores whitespaces and symbols, as they are not useful for tne interpreter. However, when formatting a build file, we need them. This commit introduces a `FullAstVisitor` that visits every Nodes, including whitespaces and symbols. --- mesonbuild/ast/visitor.py | 183 +++++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 2 deletions(-) diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index 60aca61f9695..e75755ae3f44 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -6,6 +6,7 @@ from __future__ import annotations import typing as T +from itertools import zip_longest if T.TYPE_CHECKING: from .. import mparser @@ -32,10 +33,10 @@ def visit_StringNode(self, node: mparser.StringNode) -> None: def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: self.visit_default_func(node) - def visit_MultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: + def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: self.visit_default_func(node) - def visit_FormatMultilineStringNode(self, node: mparser.FormatStringNode) -> None: + def visit_FormatMultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: self.visit_default_func(node) def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: @@ -159,3 +160,181 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: self.visit_default_func(node) node.inner.accept(self) + +class FullAstVisitor(AstVisitor): + """Visit all nodes, including Symbol and Whitespaces""" + + def enter_node(self, node: mparser.BaseNode) -> None: + pass + + def exit_node(self, node: mparser.BaseNode) -> None: + if node.whitespaces: + node.whitespaces.accept(self) + + def visit_default_func(self, node: mparser.BaseNode) -> None: + self.enter_node(node) + self.exit_node(node) + + def visit_UnaryOperatorNode(self, node: mparser.UnaryOperatorNode) -> None: + self.enter_node(node) + node.operator.accept(self) + node.value.accept(self) + self.exit_node(node) + + def visit_BinaryOperatorNode(self, node: mparser.BinaryOperatorNode) -> None: + self.enter_node(node) + node.left.accept(self) + node.operator.accept(self) + node.right.accept(self) + self.exit_node(node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self.enter_node(node) + node.lbracket.accept(self) + node.args.accept(self) + node.rbracket.accept(self) + self.exit_node(node) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self.enter_node(node) + node.lcurl.accept(self) + node.args.accept(self) + node.rcurl.accept(self) + self.exit_node(node) + + def visit_OrNode(self, node: mparser.OrNode) -> None: + self.visit_BinaryOperatorNode(node) + + def visit_AndNode(self, node: mparser.AndNode) -> None: + self.visit_BinaryOperatorNode(node) + + def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: + self.visit_BinaryOperatorNode(node) + + def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: + self.visit_BinaryOperatorNode(node) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + self.visit_UnaryOperatorNode(node) + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + self.enter_node(node) + if node.pre_whitespaces: + node.pre_whitespaces.accept(self) + for i in node.lines: + i.accept(self) + self.exit_node(node) + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + self.enter_node(node) + node.iobject.accept(self) + node.lbracket.accept(self) + node.index.accept(self) + node.rbracket.accept(self) + self.exit_node(node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self.enter_node(node) + node.source_object.accept(self) + node.dot.accept(self) + node.name.accept(self) + node.lpar.accept(self) + node.args.accept(self) + node.rpar.accept(self) + self.exit_node(node) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self.enter_node(node) + node.func_name.accept(self) + node.lpar.accept(self) + node.args.accept(self) + node.rpar.accept(self) + self.exit_node(node) + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + self.enter_node(node) + node.var_name.accept(self) + node.operator.accept(self) + node.value.accept(self) + self.exit_node(node) + + def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: + self.visit_AssignmentNode(node) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + self.enter_node(node) + node.foreach_.accept(self) + for varname, comma in zip_longest(node.varnames, node.commas): + varname.accept(self) + if comma is not None: + comma.accept(self) + node.colon.accept(self) + node.items.accept(self) + node.block.accept(self) + node.endforeach.accept(self) + self.exit_node(node) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + self.enter_node(node) + for i in node.ifs: + i.accept(self) + node.elseblock.accept(self) + node.endif.accept(self) + self.exit_node(node) + + def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: + self.visit_UnaryOperatorNode(node) + + def visit_IfNode(self, node: mparser.IfNode) -> None: + self.enter_node(node) + node.if_.accept(self) + node.condition.accept(self) + node.block.accept(self) + self.exit_node(node) + + def visit_ElseNode(self, node: mparser.ElseNode) -> None: + self.enter_node(node) + node.else_.accept(self) + node.block.accept(self) + self.exit_node(node) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + self.enter_node(node) + node.condition.accept(self) + node.questionmark.accept(self) + node.trueblock.accept(self) + node.colon.accept(self) + node.falseblock.accept(self) + self.exit_node(node) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + self.enter_node(node) + commas_iter = iter(node.commas) + + for arg in node.arguments: + arg.accept(self) + try: + comma = next(commas_iter) + comma.accept(self) + except StopIteration: + pass + + assert len(node.colons) == len(node.kwargs) + for (key, val), colon in zip(node.kwargs.items(), node.colons): + key.accept(self) + colon.accept(self) + val.accept(self) + try: + comma = next(commas_iter) + comma.accept(self) + except StopIteration: + pass + + self.exit_node(node) + + def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: + self.enter_node(node) + node.lpar.accept(self) + node.inner.accept(self) + node.rpar.accept(self) + self.exit_node(node) From 2a962ffd63ae0ae8c45f53c3cdd88663be03b794 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 22 Sep 2023 15:42:34 -0400 Subject: [PATCH 763/855] visit full ast for AstConditionLevel Use the new `FullAstVisitor` for `AstConditionLevel`. This will allow proper formatting of `if / else / endif` and `foreach / endforeach` blocks. --- mesonbuild/ast/postprocess.py | 41 +++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/mesonbuild/ast/postprocess.py b/mesonbuild/ast/postprocess.py index e9f251345184..7acfc03a08a1 100644 --- a/mesonbuild/ast/postprocess.py +++ b/mesonbuild/ast/postprocess.py @@ -5,7 +5,7 @@ # or an interpreter-based tool from __future__ import annotations -from .visitor import AstVisitor +from .visitor import AstVisitor, FullAstVisitor import typing as T if T.TYPE_CHECKING: @@ -78,32 +78,41 @@ def visit_default_func(self, node: mparser.BaseNode) -> None: node.ast_id = name + '#' + str(self.counter[name]) self.counter[name] += 1 -class AstConditionLevel(AstVisitor): +class AstConditionLevel(FullAstVisitor): def __init__(self) -> None: self.condition_level = 0 - def visit_default_func(self, node: mparser.BaseNode) -> None: + def enter_node(self, node: mparser.BaseNode) -> None: node.condition_level = self.condition_level def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: - self.visit_default_func(node) - self.condition_level += 1 + self.enter_node(node) + node.foreach_.accept(self) + for varname in node.varnames: + varname.accept(self) + for comma in node.commas: + comma.accept(self) + node.colon.accept(self) node.items.accept(self) + self.condition_level += 1 node.block.accept(self) self.condition_level -= 1 - - def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: - self.visit_default_func(node) - for i in node.ifs: - i.accept(self) - if node.elseblock: - self.condition_level += 1 - node.elseblock.accept(self) - self.condition_level -= 1 + node.endforeach.accept(self) + self.exit_node(node) def visit_IfNode(self, node: mparser.IfNode) -> None: - self.visit_default_func(node) - self.condition_level += 1 + self.enter_node(node) + node.if_.accept(self) node.condition.accept(self) + self.condition_level += 1 + node.block.accept(self) + self.condition_level -= 1 + self.exit_node(node) + + def visit_ElseNode(self, node: mparser.ElseNode) -> None: + self.enter_node(node) + node.else_.accept(self) + self.condition_level += 1 node.block.accept(self) self.condition_level -= 1 + self.exit_node(node) From 0bc51d5221f437b6e182063157e10e3d89d9326b Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 14 Sep 2023 15:17:26 -0400 Subject: [PATCH 764/855] simplify RawPrinter using FullAstVisitor --- mesonbuild/ast/printer.py | 217 +++++--------------------------------- 1 file changed, 27 insertions(+), 190 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 4fa120c5aa50..736cf8c3037e 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -6,9 +6,8 @@ from __future__ import annotations from .. import mparser -from .visitor import AstVisitor +from .visitor import AstVisitor, FullAstVisitor -from itertools import zip_longest import re import typing as T @@ -239,223 +238,61 @@ def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: else: self.result = re.sub(r', $', '', self.result) -class RawPrinter(AstVisitor): +class RawPrinter(FullAstVisitor): def __init__(self) -> None: self.result = '' def visit_default_func(self, node: mparser.BaseNode) -> None: - # XXX: this seems like it could never actually be reached... - self.result += node.value # type: ignore[attr-defined] - if node.whitespaces: - node.whitespaces.accept(self) + self.enter_node(node) + assert hasattr(node, 'value') + self.result += node.value + self.exit_node(node) - def visit_unary_operator(self, node: mparser.UnaryOperatorNode) -> None: - node.operator.accept(self) - node.value.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_binary_operator(self, node: mparser.BinaryOperatorNode) -> None: - node.left.accept(self) - node.operator.accept(self) - node.right.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) + def visit_EmptyNode(self, node: mparser.EmptyNode) -> None: + self.enter_node(node) + self.exit_node(node) def visit_BooleanNode(self, node: mparser.BooleanNode) -> None: + self.enter_node(node) self.result += 'true' if node.value else 'false' - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.enter_node(node) self.result += node.raw_value - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) def visit_StringNode(self, node: mparser.StringNode) -> None: + self.enter_node(node) self.result += f"'{node.raw_value}'" - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: + self.enter_node(node) self.result += f"'''{node.value}'''" - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: - self.result += 'f' - self.visit_StringNode(node) + self.enter_node(node) + self.result += f"f'{node.raw_value}'" + self.exit_node(node) def visit_MultilineFormatStringNode(self, node: mparser.MultilineFormatStringNode) -> None: - self.result += 'f' - self.visit_MultilineStringNode(node) + self.enter_node(node) + self.result += f"f'''{node.value}'''" + self.exit_node(node) def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: + self.enter_node(node) self.result += 'continue' - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.enter_node(node) self.result += 'break' - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: - node.lbracket.accept(self) - node.args.accept(self) - node.rbracket.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_DictNode(self, node: mparser.DictNode) -> None: - node.lcurl.accept(self) - node.args.accept(self) - node.rcurl.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: - node.lpar.accept(self) - node.inner.accept(self) - node.rpar.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_OrNode(self, node: mparser.OrNode) -> None: - self.visit_binary_operator(node) - - def visit_AndNode(self, node: mparser.AndNode) -> None: - self.visit_binary_operator(node) - - def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: - self.visit_binary_operator(node) - - def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: - self.visit_binary_operator(node) - - def visit_NotNode(self, node: mparser.NotNode) -> None: - self.visit_unary_operator(node) - - def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: - if node.pre_whitespaces: - node.pre_whitespaces.accept(self) - for i in node.lines: - i.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_IndexNode(self, node: mparser.IndexNode) -> None: - node.iobject.accept(self) - node.lbracket.accept(self) - node.index.accept(self) - node.rbracket.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_MethodNode(self, node: mparser.MethodNode) -> None: - node.source_object.accept(self) - node.dot.accept(self) - node.name.accept(self) - node.lpar.accept(self) - node.args.accept(self) - node.rpar.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: - node.func_name.accept(self) - node.lpar.accept(self) - node.args.accept(self) - node.rpar.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: - node.var_name.accept(self) - node.operator.accept(self) - node.value.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_PlusAssignmentNode(self, node: mparser.PlusAssignmentNode) -> None: - node.var_name.accept(self) - node.operator.accept(self) - node.value.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: - node.foreach_.accept(self) - for varname, comma in zip_longest(node.varnames, node.commas): - varname.accept(self) - if comma is not None: - comma.accept(self) - node.colon.accept(self) - node.items.accept(self) - node.block.accept(self) - node.endforeach.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: - for i in node.ifs: - i.accept(self) - if not isinstance(node.elseblock, mparser.EmptyNode): - node.elseblock.accept(self) - node.endif.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_UMinusNode(self, node: mparser.UMinusNode) -> None: - self.visit_unary_operator(node) - - def visit_IfNode(self, node: mparser.IfNode) -> None: - node.if_.accept(self) - node.condition.accept(self) - node.block.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_ElseNode(self, node: mparser.ElseNode) -> None: - node.else_.accept(self) - node.block.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) + self.exit_node(node) - def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: - node.condition.accept(self) - node.questionmark.accept(self) - node.trueblock.accept(self) - node.colon.accept(self) - node.falseblock.accept(self) - if node.whitespaces: - node.whitespaces.accept(self) - - def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: - commas_iter = iter(node.commas) - - for arg in node.arguments: - arg.accept(self) - try: - comma = next(commas_iter) - comma.accept(self) - except StopIteration: - pass - - assert len(node.colons) == len(node.kwargs) - for (key, val), colon in zip(node.kwargs.items(), node.colons): - key.accept(self) - colon.accept(self) - val.accept(self) - try: - comma = next(commas_iter) - comma.accept(self) - except StopIteration: - pass - - if node.whitespaces: - node.whitespaces.accept(self) class AstJSONPrinter(AstVisitor): def __init__(self) -> None: From 728fcdaab312020fe3ebea40e942f23ee620ed6c Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 14 Sep 2023 15:20:33 -0400 Subject: [PATCH 765/855] simplify astprinter by using operator value --- mesonbuild/ast/printer.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 736cf8c3037e..004a64953c3b 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -11,13 +11,6 @@ import re import typing as T -arithmic_map = { - 'add': '+', - 'sub': '-', - 'mod': '%', - 'mul': '*', - 'div': '/' -} class AstPrinter(AstVisitor): def __init__(self, indent: int = 2, arg_newline_cutoff: int = 5, update_ast_line_nos: bool = False): @@ -126,7 +119,7 @@ def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: node.left.accept(self) - self.append_padded(arithmic_map[node.operation], node) + self.append_padded(node.operator.value, node) node.lineno = self.curr_line or node.lineno node.right.accept(self) @@ -379,7 +372,7 @@ def visit_ComparisonNode(self, node: mparser.ComparisonNode) -> None: def visit_ArithmeticNode(self, node: mparser.ArithmeticNode) -> None: self._accept('left', node.left) self._accept('right', node.right) - self.current['op'] = arithmic_map[node.operation] + self.current['op'] = node.operator.value self.setbase(node) def visit_NotNode(self, node: mparser.NotNode) -> None: From bd4fd9073081bcc9f4505b9604c5cb1e8cdc300f Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 28 Sep 2023 09:08:18 -0400 Subject: [PATCH 766/855] parser: revert to single StringNode type this will allow transforming string types in the formater --- mesonbuild/ast/interpreter.py | 6 +-- mesonbuild/ast/introspection.py | 10 ++-- mesonbuild/ast/printer.py | 46 +++++-------------- mesonbuild/ast/visitor.py | 9 ---- mesonbuild/coredata.py | 2 +- mesonbuild/interpreter/interpreter.py | 2 +- mesonbuild/interpreterbase/helpers.py | 4 +- mesonbuild/interpreterbase/interpreterbase.py | 17 +++---- mesonbuild/mintro.py | 4 +- mesonbuild/mparser.py | 34 +++++--------- mesonbuild/optinterpreter.py | 5 +- mesonbuild/rewriter.py | 28 +++++------ unittests/allplatformstests.py | 1 - 13 files changed, 62 insertions(+), 106 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 0887fa2ebab1..53ddc1052147 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -207,8 +207,8 @@ def func_subdir(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str def method_call(self, node: BaseNode) -> bool: return True - def evaluate_fstring(self, node: mparser.FormatStringNode) -> str: - assert isinstance(node, mparser.FormatStringNode) + def evaluate_fstring(self, node: mparser.StringNode) -> str: + assert isinstance(node, mparser.StringNode) return node.value def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> TYPE_var: @@ -231,7 +231,7 @@ def evaluate_ternary(self, node: TernaryNode) -> None: def evaluate_dictstatement(self, node: mparser.DictNode) -> TYPE_nkwargs: def resolve_key(node: mparser.BaseNode) -> str: - if isinstance(node, mparser.BaseStringNode): + if isinstance(node, mparser.StringNode): return node.value return '__AST_UNKNOWN__' arguments, kwargs = self.reduce_arguments(node.args, key_resolver=resolve_key) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 17eb1d5b9669..5bf7e051a168 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -16,7 +16,7 @@ from ..compilers import detect_compiler_for from ..interpreterbase import InvalidArguments, SubProject from ..mesonlib import MachineChoice, OptionKey -from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, BaseStringNode +from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode from .interpreter import AstInterpreter if T.TYPE_CHECKING: @@ -118,7 +118,7 @@ def func_project(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[st if not self.is_subproject() and 'subproject_dir' in kwargs: spdirname = kwargs['subproject_dir'] - if isinstance(spdirname, BaseStringNode): + if isinstance(spdirname, StringNode): assert isinstance(spdirname.value, str) self.subproject_dir = spdirname.value if not self.is_subproject(): @@ -165,7 +165,7 @@ def _add_languages(self, raw_langs: T.List[TYPE_var], required: bool, for_machin for l in self.flatten_args(raw_langs): if isinstance(l, str): langs.append(l) - elif isinstance(l, BaseStringNode): + elif isinstance(l, StringNode): langs.append(l.value) for lang in sorted(langs, key=compilers.sort_clink): @@ -254,7 +254,7 @@ def traverse_nodes(inqueue: T.List[BaseNode]) -> T.List[BaseNode]: # Pop the first element if the function is a build target function if isinstance(curr, FunctionNode) and curr.func_name.value in BUILD_TARGET_FUNCTIONS: arg_nodes.pop(0) - elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, BaseStringNode))] + elementary_nodes = [x for x in arg_nodes if isinstance(x, (str, StringNode))] inqueue += [x for x in arg_nodes if isinstance(x, (FunctionNode, ArrayNode, IdNode, ArithmeticNode))] if elementary_nodes: res += [curr] @@ -369,6 +369,6 @@ def extract_subproject_dir(self) -> T.Optional[str]: assert isinstance(kw, IdNode), 'for mypy' if kw.value == 'subproject_dir': # mypy does not understand "and isinstance" - if isinstance(val, BaseStringNode): + if isinstance(val, StringNode): return val.value return None diff --git a/mesonbuild/ast/printer.py b/mesonbuild/ast/printer.py index 004a64953c3b..4ce3b3f1eec1 100644 --- a/mesonbuild/ast/printer.py +++ b/mesonbuild/ast/printer.py @@ -61,22 +61,13 @@ def escape(self, val: str) -> str: def visit_StringNode(self, node: mparser.StringNode) -> None: assert isinstance(node.value, str) - self.append("'" + self.escape(node.value) + "'", node) - node.lineno = self.curr_line or node.lineno - - def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: - assert isinstance(node.value, str) - self.append("f'" + self.escape(node.value) + "'", node) - node.lineno = self.curr_line or node.lineno - def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: - assert isinstance(node.value, str) - self.append("'''" + node.value + "'''", node) - node.lineno = self.curr_line or node.lineno - - def visit_FormatMultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: - assert isinstance(node.value, str) - self.append("f'''" + node.value + "'''", node) + if node.is_fstring: + self.append('f', node) + if node.is_multiline: + self.append("'''" + node.value + "'''", node) + else: + self.append("'" + self.escape(node.value) + "'", node) node.lineno = self.curr_line or node.lineno def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: @@ -258,22 +249,12 @@ def visit_NumberNode(self, node: mparser.NumberNode) -> None: def visit_StringNode(self, node: mparser.StringNode) -> None: self.enter_node(node) - self.result += f"'{node.raw_value}'" - self.exit_node(node) - - def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: - self.enter_node(node) - self.result += f"'''{node.value}'''" - self.exit_node(node) - - def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: - self.enter_node(node) - self.result += f"f'{node.raw_value}'" - self.exit_node(node) - - def visit_MultilineFormatStringNode(self, node: mparser.MultilineFormatStringNode) -> None: - self.enter_node(node) - self.result += f"f'''{node.value}'''" + if node.is_fstring: + self.result += 'f' + if node.is_multiline: + self.result += f"'''{node.value}'''" + else: + self.result += f"'{node.raw_value}'" self.exit_node(node) def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: @@ -342,9 +323,6 @@ def visit_NumberNode(self, node: mparser.NumberNode) -> None: def visit_StringNode(self, node: mparser.StringNode) -> None: self.gen_ElementaryNode(node) - def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: - self.gen_ElementaryNode(node) - def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: self._accept('args', node.args) self.setbase(node) diff --git a/mesonbuild/ast/visitor.py b/mesonbuild/ast/visitor.py index e75755ae3f44..57a60bb44dd2 100644 --- a/mesonbuild/ast/visitor.py +++ b/mesonbuild/ast/visitor.py @@ -30,15 +30,6 @@ def visit_NumberNode(self, node: mparser.NumberNode) -> None: def visit_StringNode(self, node: mparser.StringNode) -> None: self.visit_default_func(node) - def visit_FormatStringNode(self, node: mparser.FormatStringNode) -> None: - self.visit_default_func(node) - - def visit_MultilineStringNode(self, node: mparser.MultilineStringNode) -> None: - self.visit_default_func(node) - - def visit_FormatMultilineStringNode(self, node: mparser.MultilineFormatStringNode) -> None: - self.visit_default_func(node) - def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: self.visit_default_func(node) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index b12ec8203b27..eeeb8d1fedc1 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1142,7 +1142,7 @@ def _parse_section(self, s: str) -> T.Dict[str, T.Union[str, bool, int, T.List[s return section def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, T.List[str]]: - if isinstance(node, (mparser.BaseStringNode)): + if isinstance(node, (mparser.StringNode)): return node.value elif isinstance(node, mparser.BooleanNode): return node.value diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f88f407de636..6e38c5722592 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -529,7 +529,7 @@ def handle_meson_version_from_ast(self) -> None: assert isinstance(kw, mparser.IdNode), 'for mypy' if kw.value == 'meson_version': # mypy does not understand "and isinstance" - if isinstance(val, mparser.BaseStringNode): + if isinstance(val, mparser.StringNode): self.handle_meson_version(val.value, val) def get_build_def_files(self) -> mesonlib.OrderedSet[str]: diff --git a/mesonbuild/interpreterbase/helpers.py b/mesonbuild/interpreterbase/helpers.py index 0ded85b0e604..3942f2c9f4c4 100644 --- a/mesonbuild/interpreterbase/helpers.py +++ b/mesonbuild/interpreterbase/helpers.py @@ -15,7 +15,7 @@ from .baseobjects import TYPE_var, TYPE_kwargs, SubProject def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var']: - if isinstance(args, mparser.BaseStringNode): + if isinstance(args, mparser.StringNode): assert isinstance(args.value, str) return [args.value] if not isinstance(args, collections.abc.Sequence): @@ -25,7 +25,7 @@ def flatten(args: T.Union['TYPE_var', T.List['TYPE_var']]) -> T.List['TYPE_var'] if isinstance(a, list): rest = flatten(a) result = result + rest - elif isinstance(a, mparser.BaseStringNode): + elif isinstance(a, mparser.StringNode): result.append(a.value) else: result.append(a) diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index 47dd46f328bd..ccc33497e7c9 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -198,11 +198,12 @@ def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[InterpreterObj self.assignment(cur) elif isinstance(cur, mparser.MethodNode): return self.method_call(cur) - elif isinstance(cur, mparser.BaseStringNode): - if isinstance(cur, mparser.MultilineFormatStringNode): - return self.evaluate_multiline_fstring(cur) - elif isinstance(cur, mparser.FormatStringNode): - return self.evaluate_fstring(cur) + elif isinstance(cur, mparser.StringNode): + if cur.is_fstring: + if cur.is_multiline: + return self.evaluate_multiline_fstring(cur) + else: + return self.evaluate_fstring(cur) else: return self._holderify(cur.value) elif isinstance(cur, mparser.BooleanNode): @@ -256,7 +257,7 @@ def evaluate_arraystatement(self, cur: mparser.ArrayNode) -> InterpreterObject: @FeatureNew('dict', '0.47.0') def evaluate_dictstatement(self, cur: mparser.DictNode) -> InterpreterObject: def resolve_key(key: mparser.BaseNode) -> str: - if not isinstance(key, mparser.BaseStringNode): + if not isinstance(key, mparser.StringNode): FeatureNew.single_use('Dictionary entry using non literal key', '0.53.0', self.subproject) key_holder = self.evaluate_statement(key) if key_holder is None: @@ -424,11 +425,11 @@ def evaluate_ternary(self, node: mparser.TernaryNode) -> T.Optional[InterpreterO return self.evaluate_statement(node.falseblock) @FeatureNew('multiline format strings', '0.63.0') - def evaluate_multiline_fstring(self, node: mparser.MultilineFormatStringNode) -> InterpreterObject: + def evaluate_multiline_fstring(self, node: mparser.StringNode) -> InterpreterObject: return self.evaluate_fstring(node) @FeatureNew('format strings', '0.58.0') - def evaluate_fstring(self, node: T.Union[mparser.FormatStringNode, mparser.MultilineFormatStringNode]) -> InterpreterObject: + def evaluate_fstring(self, node: mparser.StringNode) -> InterpreterObject: def replace(match: T.Match[str]) -> str: var = str(match.group(1)) try: diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index 81b15d27e8fb..bdbb59e3a18d 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -26,7 +26,7 @@ from . import environment from .interpreterbase import ObjectHolder from .mesonlib import OptionKey -from .mparser import FunctionNode, ArrayNode, ArgumentNode, BaseStringNode +from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode if T.TYPE_CHECKING: import argparse @@ -185,7 +185,7 @@ def nodes_to_paths(node_list: T.List[BaseNode]) -> T.List[Path]: elif isinstance(n, ArgumentNode): args = n.arguments for j in args: - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): assert isinstance(j.value, str) res += [Path(j.value)] elif isinstance(j, str): diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index c1bceb294a76..0e26b9ed9fbc 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -298,31 +298,25 @@ def __init__(self, token: Token[str]): self.value = int(token.value, base=0) self.bytespan = token.bytespan -class BaseStringNode(ElementaryNode[str]): - pass - @dataclass(unsafe_hash=True) -class StringNode(BaseStringNode): +class StringNode(ElementaryNode[str]): raw_value: str = field(hash=False) + is_multiline: bool + is_fstring: bool def __init__(self, token: Token[str], escape: bool = True): super().__init__(token) - self.value = ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, token.value) if escape else token.value - self.raw_value = token.value -class FormatStringNode(StringNode): - pass - -@dataclass(unsafe_hash=True) -class MultilineStringNode(BaseStringNode): + self.is_multiline = 'multiline' in token.tid + self.is_fstring = 'fstring' in token.tid + self.raw_value = token.value - def __init__(self, token: Token[str]): - super().__init__(token) - self.value = token.value + if escape and not self.is_multiline: + self.value = self.escape() -class MultilineFormatStringNode(MultilineStringNode): - pass + def escape(self) -> str: + return ESCAPE_SEQUENCE_SINGLE_RE.sub(decode_match, self.raw_value) class ContinueNode(ElementaryNode): pass @@ -930,14 +924,8 @@ def e9(self) -> BaseNode: return self.create_node(IdNode, t) if self.accept('number'): return self.create_node(NumberNode, t) - if self.accept('string'): + if self.accept_any(('string', 'fstring', 'multiline_string', 'multiline_fstring')): return self.create_node(StringNode, t) - if self.accept('fstring'): - return self.create_node(FormatStringNode, t) - if self.accept('multiline_string'): - return self.create_node(MultilineStringNode, t) - if self.accept('multiline_fstring'): - return self.create_node(MultilineFormatStringNode, t) return EmptyNode(self.current.lineno, self.current.colno, self.current.filename) def key_values(self) -> ArgumentNode: diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 9da355a514e6..980dadd092f9 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -105,15 +105,14 @@ def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> 'TYPE_var': return arg if isinstance(arg, mparser.ParenthesizedNode): return self.reduce_single(arg.inner) - elif isinstance(arg, (mparser.BaseStringNode, mparser.BooleanNode, - mparser.NumberNode)): + elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode, mparser.NumberNode)): return arg.value elif isinstance(arg, mparser.ArrayNode): return [self.reduce_single(curarg) for curarg in arg.args.arguments] elif isinstance(arg, mparser.DictNode): d = {} for k, v in arg.args.kwargs.items(): - if not isinstance(k, mparser.BaseStringNode): + if not isinstance(k, mparser.StringNode): raise OptionException('Dictionary keys must be a string literal') d[k.value] = self.reduce_single(v) return d diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py index fd5413ac1c0f..0a40a711c4ea 100644 --- a/mesonbuild/rewriter.py +++ b/mesonbuild/rewriter.py @@ -13,7 +13,7 @@ from mesonbuild.mesonlib import MesonException, setup_vsenv from . import mlog, environment from functools import wraps -from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, BaseStringNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, StringNode, SymbolNode +from .mparser import Token, ArrayNode, ArgumentNode, AssignmentNode, StringNode, BooleanNode, ElementaryNode, IdNode, FunctionNode, SymbolNode import json, os, re, sys import typing as T @@ -142,7 +142,7 @@ def __init__(self, node: T.Optional[BaseNode] = None): def new_node(cls, value=None): if value is None: value = '' - return StringNode(Token('', '', 0, 0, 0, None, str(value))) + return StringNode(Token('string', '', 0, 0, 0, None, str(value))) @classmethod def supported_nodes(cls): @@ -259,17 +259,17 @@ def __init__(self, node: T.Optional[BaseNode] = None): @classmethod def _new_element_node(cls, value): - return StringNode(Token('', '', 0, 0, 0, None, str(value))) + return StringNode(Token('string', '', 0, 0, 0, None, str(value))) @staticmethod def _check_is_equal(node, value) -> bool: - if isinstance(node, BaseStringNode): + if isinstance(node, StringNode): return node.value == value return False @staticmethod def _check_regex_matches(node, regex: str) -> bool: - if isinstance(node, BaseStringNode): + if isinstance(node, StringNode): return re.match(regex, node.value) is not None return False @@ -293,7 +293,7 @@ def _check_is_equal(node, value) -> bool: @staticmethod def _check_regex_matches(node, regex: str) -> bool: - if isinstance(node, BaseStringNode): + if isinstance(node, StringNode): return re.match(regex, node.value) is not None return False @@ -657,7 +657,7 @@ def arg_list_from_node(n): src_list = [] for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): src_list += [j.value] # Generate the new String nodes @@ -691,7 +691,7 @@ def arg_list_from_node(n): def find_node(src): for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): if j.value == src: return i, j return None, None @@ -750,7 +750,7 @@ def find_node(src): extra_files_list = [] for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): extra_files_list += [j.value] # Generate the new String nodes @@ -781,7 +781,7 @@ def find_node(src): def find_node(src): for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): if j.value == src: return i, j return None, None @@ -850,12 +850,12 @@ def find_node(src): src_list = [] for i in target['sources']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): src_list += [j.value] extra_files_list = [] for i in target['extra_files']: for j in arg_list_from_node(i): - if isinstance(j, BaseStringNode): + if isinstance(j, StringNode): extra_files_list += [j.value] test_data = { 'name': target['name'], @@ -870,8 +870,8 @@ def find_node(src): alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)] path_sorter = lambda key: ([(key.count('/') <= idx, alphanum_key(x)) for idx, x in enumerate(key.split('/'))]) - unknown = [x for x in i.arguments if not isinstance(x, BaseStringNode)] - sources = [x for x in i.arguments if isinstance(x, BaseStringNode)] + unknown = [x for x in i.arguments if not isinstance(x, StringNode)] + sources = [x for x in i.arguments if isinstance(x, StringNode)] sources = sorted(sources, key=lambda x: path_sorter(x.value)) i.arguments = unknown + sources diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 0e563758798c..60a3a8aea82e 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -3583,7 +3583,6 @@ def accept_kwargs(kwargs): 'IdNode': [('value', None, str)], 'NumberNode': [('value', None, int)], 'StringNode': [('value', None, str)], - 'FormatStringNode': [('value', None, str)], 'ContinueNode': [], 'BreakNode': [], 'ArgumentNode': [('positional', accept_node_list), ('kwargs', accept_kwargs)], From 2b37101998c82b8c4d3985d9b0695be38ec4cf76 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Fri, 15 Sep 2023 10:19:02 -0400 Subject: [PATCH 767/855] meson format command --- docs/markdown/Commands.md | 79 ++ docs/markdown/snippets/meson_format_cmd.md | 4 + mesonbuild/mesonmain.py | 4 +- mesonbuild/mformat.py | 979 ++++++++++++++++++ mesonbuild/mparser.py | 3 + run_format_tests.py | 1 + run_mypy.py | 1 + run_project_tests.py | 4 +- .../format/1 default/crazy_comments.meson | 47 + test cases/format/1 default/indentation.meson | 73 ++ test cases/format/1 default/meson.build | 14 + test cases/format/2 muon/crazy_comments.meson | 47 + test cases/format/2 muon/indentation.meson | 71 ++ test cases/format/2 muon/meson.build | 14 + test cases/format/2 muon/muon.ini | 15 + .../format/3 editorconfig/.editorconfig | 8 + .../3 editorconfig/crazy_comments.meson | 47 + .../format/3 editorconfig/indentation.meson | 73 ++ test cases/format/3 editorconfig/meson.build | 31 + test cases/format/3 editorconfig/options.ini | 1 + .../format/4 config/crazy_comments.meson | 47 + test cases/format/4 config/indentation.meson | 73 ++ test cases/format/4 config/meson.build | 19 + test cases/format/4 config/meson.format | 11 + .../format/5 transform/default.expected.meson | 69 ++ test cases/format/5 transform/default.ini | 15 + test cases/format/5 transform/file_compare.py | 7 + test cases/format/5 transform/genexpected.cmd | 7 + test cases/format/5 transform/meson.build | 29 + test cases/format/5 transform/meson.options | 1 + .../format/5 transform/muon.expected.meson | 69 ++ test cases/format/5 transform/muon.ini | 15 + .../format/5 transform/options.expected.meson | 48 + test cases/format/5 transform/options.ini | 15 + test cases/format/5 transform/source.meson | 37 + test cases/format/5 transform/test.json | 11 + unittests/allplatformstests.py | 1 + unittests/platformagnostictests.py | 43 + 38 files changed, 2031 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/meson_format_cmd.md create mode 100644 mesonbuild/mformat.py create mode 100644 test cases/format/1 default/crazy_comments.meson create mode 100644 test cases/format/1 default/indentation.meson create mode 100644 test cases/format/1 default/meson.build create mode 100644 test cases/format/2 muon/crazy_comments.meson create mode 100644 test cases/format/2 muon/indentation.meson create mode 100644 test cases/format/2 muon/meson.build create mode 100644 test cases/format/2 muon/muon.ini create mode 100644 test cases/format/3 editorconfig/.editorconfig create mode 100644 test cases/format/3 editorconfig/crazy_comments.meson create mode 100644 test cases/format/3 editorconfig/indentation.meson create mode 100644 test cases/format/3 editorconfig/meson.build create mode 100644 test cases/format/3 editorconfig/options.ini create mode 100644 test cases/format/4 config/crazy_comments.meson create mode 100644 test cases/format/4 config/indentation.meson create mode 100644 test cases/format/4 config/meson.build create mode 100644 test cases/format/4 config/meson.format create mode 100644 test cases/format/5 transform/default.expected.meson create mode 100644 test cases/format/5 transform/default.ini create mode 100644 test cases/format/5 transform/file_compare.py create mode 100644 test cases/format/5 transform/genexpected.cmd create mode 100644 test cases/format/5 transform/meson.build create mode 100644 test cases/format/5 transform/meson.options create mode 100644 test cases/format/5 transform/muon.expected.meson create mode 100644 test cases/format/5 transform/muon.ini create mode 100644 test cases/format/5 transform/options.expected.meson create mode 100644 test cases/format/5 transform/options.ini create mode 100644 test cases/format/5 transform/source.meson create mode 100644 test cases/format/5 transform/test.json diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index 831cba85d489..542f1b269d40 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -396,3 +396,82 @@ format should be used. There are currently 3 formats supported: seems to be properly supported by vscode. {{ devenv_arguments.inc }} + + +### format + +*(since 1.5.0)* + +{{ format_usage.inc }} + +Format specified `meson.build` documents. For compatibility with `muon`, `fmt` +is an alias to `format`. + +{{ format_arguments.inc }} + +The configuration file is a `.ini` file. If a `meson.format` file exists +beside the provided build file to analyze, and no configuration file is +provided on the command line, the `meson.format` file is automatically used. + +If no build file is provided on the command line, the `meson.build` file in +current directory is analyzed. + +The following options are recognized: + +- max_line_length (int): When an array, a dict, a function or a method + would be longer that this, it is formatted one argument per line + (Default is 80). +- indent_by (str): Indentation to use (Default is four spaces `' '`). +- space_array (bool): Whether to add spaces between `[]` and array + arguments (default is false). +- kwargs_force_multiline (bool): If true, arguments are formatted one per + line as soon as there is a keyword argument (default is false). +- wide_colon (bool): If true, a space is placed before colon in dict + and in keyword arguments (default is false). +- no_single_comma_function (bool): If true, a comma is never appended + to function arguments if there is only one argument, even if + using multiline arguments (default is false). +- end_of_line ('cr', 'lf', 'crlf', 'native'): Line ending to use + (applied when using `--output` or `--inline` argument) (default + is 'native). +- indent_before_comments (str): Indentation to use before inline comments + (default is two spaces `' '`). +- simplify_string_literals (bool): When true, multiline strings are + converted to single line strings if they don't contain newlines. + Formatted strings are converted to normal strings if they don't + contain substitutions (default is true). +- insert_final_newline (bool): If true, force the `meson.build` file + to end with a newline character (default is true). +- tab_width (int): Width of tab stops, used to compute line length + when `indent_by` uses tab characters (default is 4). +- sort_files (bool): When true, arguments of `files()` function are + sorted alphabetically (default is false). +- group_arg_value (bool): When true, string argument with `--` prefix + followed by string argument without `--` prefix are grouped on the + same line, in multiline arguments (default is false). +- use_editor_config (bool): When true, also uses config from .editorconfig . + +The first six options are the same than for the `muon fmt` command. + +It is also possible to use a `.editorconfig` file, by providing +the `--editor-config` option on the command line, or with the +`use_editor_config` option in the config file. + +When `--recursive` option is specified, `meson.build` files from +`subdir` are also analyzed (must be used in conjunction with `--inplace` +or `--check-only` option). + + +#### Differences with `muon fmt` + +The `meson format` command should be compatible with the `muon fmt` command. +However, it has more features, and some differences: + +- By default, `meson format` put two spaces before inline comments, + while `muon fmt` only puts one. +- `muon fmt` can potentially mix crlf and lf end-of-lines, as it is not aware + of them. `meson format` will always be consistent in the output it produces. +- `muon fmt` only recognize the `indent_by` option from .editorconfig files. + `meson format` also recognizes `max_line_length`, `end_of_line`, + `insert_final_newline` and `tab_width` options. +- `meson format` has many additional format rules (see option list above). diff --git a/docs/markdown/snippets/meson_format_cmd.md b/docs/markdown/snippets/meson_format_cmd.md new file mode 100644 index 000000000000..390f15d581c7 --- /dev/null +++ b/docs/markdown/snippets/meson_format_cmd.md @@ -0,0 +1,4 @@ +## New meson format command + +This command is similar to `muon fmt` and allows to format a `meson.build` +document. diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index c01be49e59da..62ed8918cd2a 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -61,7 +61,7 @@ def errorhandler(e: Exception, command: str) -> int: class CommandLineParser: def __init__(self) -> None: # only import these once we do full argparse processing - from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv + from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv, mformat from .scripts import env2mfile from .wrap import wraptool import shutil @@ -100,6 +100,8 @@ def __init__(self) -> None: help_msg='Run commands in developer environment') self.add_command('env2mfile', env2mfile.add_arguments, env2mfile.run, help_msg='Convert current environment to a cross or native file') + self.add_command('format', mformat.add_arguments, mformat.run, aliases=['fmt'], + help_msg='Format meson source file') # Add new commands above this line to list them in help command self.add_command('help', self.add_help_arguments, self.run_help_command, help_msg='Print help of a subcommand') diff --git a/mesonbuild/mformat.py b/mesonbuild/mformat.py new file mode 100644 index 000000000000..49ece4f034a4 --- /dev/null +++ b/mesonbuild/mformat.py @@ -0,0 +1,979 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2024 The Meson development team + +from __future__ import annotations + +import argparse +import re +import typing as T +from configparser import ConfigParser, MissingSectionHeaderError +from copy import deepcopy +from dataclasses import dataclass, field, fields, asdict +from pathlib import Path + +from . import mparser +from .mesonlib import MesonException +from .ast.postprocess import AstConditionLevel +from .ast.printer import RawPrinter +from .ast.visitor import FullAstVisitor +from .environment import build_filename + +if T.TYPE_CHECKING: + from typing_extensions import Literal + + +class DefaultConfigParser(ConfigParser): + + def __init__(self, delimiters: T.Tuple[str, ...] = ('=', ':')): + super().__init__(delimiters=delimiters, interpolation=None) + + def read_default(self, filename: Path) -> None: + if not filename.exists(): + raise MesonException(f'Configuration file {filename} not found') + try: + super().read(filename, encoding='utf-8') + except MissingSectionHeaderError: + self.read_string(f'[{self.default_section}]\n' + filename.read_text(encoding='utf-8')) + + def getstr(self, section: str, key: str, fallback: T.Optional[str] = None) -> T.Optional[str]: + value: T.Optional[str] = self.get(section, key, fallback=fallback) + if value: + value = value.strip('"').strip("'") + return value + + +def match_path(filename: str, pattern: str) -> bool: + '''recursive glob match for editorconfig sections''' + index = 0 + num_ranges: T.List[T.Tuple[int, int]] = [] + + def curl_replace(m: re.Match) -> str: + nonlocal index + + if '\\.\\.' in m[1]: + index += 1 + low, high = m[1].split('\\.\\.') + num_ranges.append((int(low), int(high))) + return f'(?P-?[0-9]+)' + else: + return T.cast(str, m[1].replace(',', '|')) + + pattern_re = pattern.replace('.', '\\.') + pattern_re = re.sub(r'(? . + pattern_re = re.sub(r'(? ([^/]*) + pattern_re = re.sub(r'(? (.*) + pattern_re = re.sub(r'(? [^name] + pattern_re = re.sub(r'(? FormatterConfig: + defaults = {f.name: f.metadata['default'] for f in fields(cls)} + return cls(**defaults) + + def update(self, config: FormatterConfig) -> FormatterConfig: + """Returns copy of self updated with other config""" + new_config = deepcopy(self) + for key, value in asdict(config).items(): + if value is not None: + setattr(new_config, key, value) + return new_config + + def with_editorconfig(self, editorconfig: EditorConfig) -> FormatterConfig: + """Returns copy of self updated with editorconfig""" + config = deepcopy(self) + + if editorconfig.indent_style == 'space': + indent_size = editorconfig.indent_size or 4 + config.indent_by = indent_size * ' ' + elif editorconfig.indent_style == 'tab': + config.indent_by = '\t' + elif editorconfig.indent_size: + config.indent_by = editorconfig.indent_size * ' ' + + if editorconfig.max_line_length == 'off': + config.max_line_length = 0 + elif editorconfig.max_line_length: + config.max_line_length = int(editorconfig.max_line_length) + + if editorconfig.end_of_line: + config.end_of_line = editorconfig.end_of_line + if editorconfig.insert_final_newline: + config.insert_final_newline = editorconfig.insert_final_newline + if editorconfig.tab_width: + config.tab_width = editorconfig.tab_width + + return config + + @property + def newline(self) -> T.Optional[str]: + if self.end_of_line == 'crlf': + return '\r\n' + if self.end_of_line == 'lf': + return '\n' + if self.end_of_line == 'cr': + return '\r' + return None + + +class MultilineArgumentDetector(FullAstVisitor): + + def __init__(self, config: FormatterConfig): + self.config = config + self.is_multiline = False + + def enter_node(self, node: mparser.BaseNode) -> None: + if node.whitespaces and '#' in node.whitespaces.value: + self.is_multiline = True + + elif isinstance(node, mparser.StringNode) and node.is_multiline: + self.is_multiline = True + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + if node.is_multiline: + self.is_multiline = True + + if self.is_multiline: + return + + if self.config.kwargs_force_multiline and node.kwargs: + self.is_multiline = True + + super().visit_ArgumentNode(node) + + +class TrimWhitespaces(FullAstVisitor): + + def __init__(self, config: FormatterConfig): + self.config = config + + self.in_block_comments = False + self.in_arguments = 0 + self.indent_comments = '' + + def visit_default_func(self, node: mparser.BaseNode) -> None: + self.enter_node(node) + node.whitespaces.accept(self) + + def enter_node(self, node: mparser.BaseNode) -> None: + if isinstance(node, mparser.WhitespaceNode): + return + if not node.whitespaces: + # Ensure every node has a whitespace node + node.whitespaces = mparser.WhitespaceNode(mparser.Token('whitespace', node.filename, 0, 0, 0, (0, 0), '')) + node.whitespaces.condition_level = node.condition_level + + def exit_node(self, node: mparser.BaseNode) -> None: + pass + + 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 + from_node.whitespaces = None + to_node.whitespaces.accept(self) + + def add_space_after(self, node: mparser.BaseNode) -> None: + if not node.whitespaces.value: + node.whitespaces.value = ' ' + + def add_nl_after(self, node: mparser.BaseNode, force: bool = False) -> None: + if not node.whitespaces.value: + node.whitespaces.value = '\n' + elif force and not node.whitespaces.value.endswith('\n'): + node.whitespaces.value += '\n' + + def dedent(self, value: str) -> str: + if value.endswith(self.config.indent_by): + value = value[:-len(self.config.indent_by)] + return value + + def sort_arguments(self, node: mparser.ArgumentNode) -> None: + # TODO: natsort + def sort_key(arg: mparser.BaseNode) -> str: + if isinstance(arg, mparser.StringNode): + return arg.raw_value + return getattr(node, 'value', '') + + node.arguments.sort(key=sort_key) + + def visit_EmptyNode(self, node: mparser.EmptyNode) -> None: + self.enter_node(node) + self.in_block_comments = True + node.whitespaces.accept(self) + self.in_block_comments = False + + def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: + lines = node.value.splitlines(keepends=True) + node.value = '' + in_block_comments = self.in_block_comments + with_comments = ['#' in line for line in lines] + [False] + for i, line in enumerate(lines): + has_nl = line.endswith('\n') + line = line.strip() + if line.startswith('#'): + if not in_block_comments: + node.value += self.config.indent_before_comments + else: + node.value += self.indent_comments + node.value += line + if has_nl and (line or with_comments[i+1] or not self.in_arguments): + node.value += '\n' + in_block_comments = True + if node.value.endswith('\n'): + node.value += self.indent_comments + + def visit_SymbolNode(self, node: mparser.SymbolNode) -> None: + super().visit_SymbolNode(node) + if node.value in "([{" and node.whitespaces.value == '\n': + node.whitespaces.value = '' + + 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: + node.is_multiline = False + node.value = node.escape() + + if node.is_fstring and '@' not in node.value: + node.is_fstring = False + + self.exit_node(node) + + def visit_UnaryOperatorNode(self, node: mparser.UnaryOperatorNode) -> None: + super().visit_UnaryOperatorNode(node) + self.move_whitespaces(node.value, node) + + def visit_NotNode(self, node: mparser.NotNode) -> None: + super().visit_UnaryOperatorNode(node) + if not node.operator.whitespaces.value: + node.operator.whitespaces.value = ' ' + self.move_whitespaces(node.value, node) + + def visit_BinaryOperatorNode(self, node: mparser.BinaryOperatorNode) -> None: + super().visit_BinaryOperatorNode(node) + self.add_space_after(node.left) + self.add_space_after(node.operator) + self.move_whitespaces(node.right, node) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + super().visit_ArrayNode(node) + self.move_whitespaces(node.rbracket, node) + + if node.lbracket.whitespaces.value: + node.args.is_multiline = True + 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) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + super().visit_DictNode(node) + self.move_whitespaces(node.rcurl, node) + + if node.lcurl.whitespaces.value: + node.args.is_multiline = True + + def visit_CodeBlockNode(self, node: mparser.CodeBlockNode) -> None: + self.enter_node(node) + if node.pre_whitespaces: + self.in_block_comments = True + node.pre_whitespaces.accept(self) + self.in_block_comments = False + else: + node.pre_whitespaces = mparser.WhitespaceNode(mparser.Token('whitespace', node.filename, 0, 0, 0, (0, 0), '')) + + for i in node.lines: + i.accept(self) + self.exit_node(node) + + if node.lines: + self.move_whitespaces(node.lines[-1], node) + else: + node.whitespaces.accept(self) + + if node.condition_level == 0 and self.config.insert_final_newline: + self.add_nl_after(node, force=True) + + indent = node.condition_level * self.config.indent_by + if indent and node.lines: + node.pre_whitespaces.value += indent + for line in node.lines[:-1]: + line.whitespaces.value += indent + + def visit_IndexNode(self, node: mparser.IndexNode) -> None: + super().visit_IndexNode(node) + self.move_whitespaces(node.rbracket, node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + super().visit_MethodNode(node) + self.move_whitespaces(node.rpar, node) + + if node.lpar.whitespaces.value: + node.args.is_multiline = True + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + if node.func_name.value == 'files': + if self.config.sort_files: + self.sort_arguments(node.args) + + if len(node.args.arguments) == 1 and not node.args.kwargs: + arg = node.args.arguments[0] + if isinstance(arg, mparser.ArrayNode): + if not arg.lbracket.whitespaces or not arg.lbracket.whitespaces.value.strip(): + # files([...]) -> files(...) + node.args = arg.args + + super().visit_FunctionNode(node) + self.move_whitespaces(node.rpar, node) + + if node.lpar.whitespaces.value: + node.args.is_multiline = True + + def visit_AssignmentNode(self, node: mparser.AssignmentNode) -> None: + super().visit_AssignmentNode(node) + self.add_space_after(node.var_name) + self.add_space_after(node.operator) + self.move_whitespaces(node.value, node) + + def visit_ForeachClauseNode(self, node: mparser.ForeachClauseNode) -> None: + super().visit_ForeachClauseNode(node) + self.add_space_after(node.foreach_) + self.add_space_after(node.varnames[-1]) + for comma in node.commas: + self.add_space_after(comma) + self.add_space_after(node.colon) + + node.block.whitespaces.value += node.condition_level * self.config.indent_by + + self.move_whitespaces(node.endforeach, node) + + def visit_IfClauseNode(self, node: mparser.IfClauseNode) -> None: + super().visit_IfClauseNode(node) + self.move_whitespaces(node.endif, node) + + if isinstance(node.elseblock, mparser.ElseNode): + node.elseblock.whitespaces.value += node.condition_level * self.config.indent_by + else: + node.ifs[-1].whitespaces.value += node.condition_level * self.config.indent_by + + def visit_IfNode(self, node: mparser.IfNode) -> None: + super().visit_IfNode(node) + self.add_space_after(node.if_) + self.move_whitespaces(node.block, node) + + def visit_ElseNode(self, node: mparser.ElseNode) -> None: + super().visit_ElseNode(node) + self.move_whitespaces(node.block, node) + + def visit_TernaryNode(self, node: mparser.TernaryNode) -> None: + super().visit_TernaryNode(node) + self.add_space_after(node.condition) + self.add_space_after(node.questionmark) + self.add_space_after(node.trueblock) + self.add_space_after(node.colon) + self.move_whitespaces(node.falseblock, node) + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + if not node.is_multiline: + ml_detector = MultilineArgumentDetector(self.config) + node.accept(ml_detector) + if ml_detector.is_multiline: + node.is_multiline = True + + self.in_arguments += 1 + super().visit_ArgumentNode(node) + self.in_arguments -= 1 + + if not node.arguments and not node.kwargs: + node.whitespaces.accept(self) + return + + last_node: mparser.BaseNode + has_trailing_comma = len(node.commas) == len(node.arguments) + len(node.kwargs) + if has_trailing_comma: + last_node = node.commas[-1] + elif node.kwargs: + for last_node in node.kwargs.values(): + pass + else: + last_node = node.arguments[-1] + + self.move_whitespaces(last_node, node) + + if not node.is_multiline and '#' not in node.whitespaces.value: + node.whitespaces.value = '' + + def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: + self.enter_node(node) + + is_multiline = node.lpar.whitespaces and '#' in node.lpar.whitespaces.value + if is_multiline: + self.indent_comments += self.config.indent_by + + node.lpar.accept(self) + node.inner.accept(self) + + if is_multiline: + node.inner.whitespaces.value = self.dedent(node.inner.whitespaces.value) + self.indent_comments = self.dedent(self.indent_comments) + self.add_nl_after(node.inner) + + node.rpar.accept(self) + self.move_whitespaces(node.rpar, node) + + +class ArgumentFormatter(FullAstVisitor): + + def __init__(self, config: FormatterConfig): + self.config = config + self.level = 0 + self.indent_after = False + self.is_function_arguments = False + + def add_space_after(self, node: mparser.BaseNode) -> None: + if not node.whitespaces.value: + node.whitespaces.value = ' ' + + def add_nl_after(self, node: mparser.BaseNode, indent: int) -> None: + if not node.whitespaces.value or node.whitespaces.value == ' ': + node.whitespaces.value = '\n' + indent_by = (node.condition_level + indent) * self.config.indent_by + if indent_by: + node.whitespaces.value += indent_by + + 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) + self.is_function_arguments = False + node.args.accept(self) + if node.args.is_multiline: + self.level -= 1 + 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) + self.is_function_arguments = False + node.args.accept(self) + if node.args.is_multiline: + self.level -= 1 + self.exit_node(node) + + def visit_MethodNode(self, node: mparser.MethodNode) -> None: + self.enter_node(node) + node.source_object.accept(self) + if node.args.is_multiline: + self.level += 1 + self.add_nl_after(node.lpar, indent=self.level) + self.is_function_arguments = True + node.args.accept(self) + if node.args.is_multiline: + self.level -= 1 + self.exit_node(node) + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + self.enter_node(node) + if node.args.is_multiline: + self.level += 1 + self.add_nl_after(node.lpar, indent=self.level) + self.is_function_arguments = True + node.args.accept(self) + if node.args.is_multiline: + self.level -= 1 + self.exit_node(node) + + 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:]: + if '#' in line and not line.startswith(indent): + node.value += indent + node.value += line + if self.indent_after and node.value.endswith(('\n', self.config.indent_by)): + node.value += indent + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + is_function_arguments = self.is_function_arguments # record it, because it may change when visiting children + super().visit_ArgumentNode(node) + + for colon in node.colons: + self.add_space_after(colon) + + if self.config.wide_colon: + for key in node.kwargs: + self.add_space_after(key) + + arguments_count = len(node.arguments) + len(node.kwargs) + has_trailing_comma = node.commas and len(node.commas) == arguments_count + if node.is_multiline: + need_comma = True + if arguments_count == 1 and is_function_arguments: + need_comma = not self.config.no_single_comma_function + + if need_comma and not has_trailing_comma: + comma = mparser.SymbolNode(mparser.Token('comma', node.filename, 0, 0, 0, (0, 0), ',')) + comma.condition_level = node.condition_level + node.commas.append(comma) + elif has_trailing_comma and not need_comma: + node.commas.pop(-1) + + arg_index = 0 + if self.config.group_arg_value: + for arg in node.arguments[:-1]: + group_args = False + if isinstance(arg, mparser.StringNode) and arg.value.startswith('--'): + next_arg = node.arguments[arg_index + 1] + if isinstance(next_arg, mparser.StringNode) and not next_arg.value.startswith('--'): + group_args = True + if group_args: + # keep '--arg', 'value' on same line + self.add_space_after(node.commas[arg_index]) + elif arg_index < len(node.commas): + self.add_nl_after(node.commas[arg_index], self.level) + arg_index += 1 + + for comma in node.commas[arg_index:-1]: + self.add_nl_after(comma, self.level) + 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): + node.commas.pop(-1) + + for comma in node.commas: + self.add_space_after(comma) + + self.exit_node(node) + + def visit_ParenthesizedNode(self, node: mparser.ParenthesizedNode) -> None: + self.enter_node(node) + is_multiline = '\n' in node.lpar.whitespaces.value + if is_multiline: + current_indent_after = self.indent_after + self.indent_after = True + node.lpar.accept(self) + node.inner.accept(self) + if is_multiline: + self.indent_after = current_indent_after + node.rpar.accept(self) + self.exit_node(node) + + +class ComputeLineLengths(FullAstVisitor): + + def __init__(self, config: FormatterConfig, level: int): + self.config = config + self.lengths: T.List[int] = [] + self.length = 0 + self.argument_stack: T.List[mparser.ArgumentNode] = [] + self.level = level + self.need_regenerate = False + + def visit_default_func(self, node: mparser.BaseNode) -> None: + self.enter_node(node) + assert hasattr(node, 'value') + self.length += len(str(node.value)) + self.exit_node(node) + + def len(self, line: str) -> int: + '''Compute line length, including tab stops''' + parts = line.split('\t') + line_length = len(parts[0]) + for p in parts[1:]: + tab_length = ((self.length + line_length) % self.config.tab_width) or self.config.tab_width + line_length += tab_length + len(p) + return line_length + + def count_multiline(self, value: str) -> None: + lines = value.splitlines(keepends=True) + for line in lines: + if line.endswith('\n'): + self.lengths.append(self.length + self.len(line) - 1) + self.length = 0 + else: + self.length += self.len(line) + + def visit_WhitespaceNode(self, node: mparser.WhitespaceNode) -> None: + self.count_multiline(node.value) + + def visit_EmptyNode(self, node: mparser.EmptyNode) -> None: + self.enter_node(node) + self.exit_node(node) + + def visit_NumberNode(self, node: mparser.NumberNode) -> None: + self.enter_node(node) + self.length += len(node.raw_value) + self.exit_node(node) + + def visit_StringNode(self, node: mparser.StringNode) -> None: + self.enter_node(node) + if node.is_fstring: + self.length += 1 + + if node.is_multiline: + self.length += 3 + self.count_multiline(node.value) + self.length += 3 + else: + self.length += self.len(node.raw_value) + 2 + + self.exit_node(node) + + def visit_ContinueNode(self, node: mparser.ContinueNode) -> None: + self.enter_node(node) + self.length += len('continue') + self.exit_node(node) + + def visit_BreakNode(self, node: mparser.BreakNode) -> None: + self.enter_node(node) + self.length += len('break') + 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: + 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 + + def visit_ArgumentNode(self, node: mparser.ArgumentNode) -> None: + self.argument_stack.append(node) + super().visit_ArgumentNode(node) + self.split_if_needed(node) + self.argument_stack.pop(-1) + + def visit_ArrayNode(self, node: mparser.ArrayNode) -> None: + self.enter_node(node) + node.lbracket.accept(self) + node.args.accept(self) + node.rbracket.accept(self) + self.split_if_needed(node.args) # split if closing bracket is too far + self.exit_node(node) + + def visit_DictNode(self, node: mparser.DictNode) -> None: + self.enter_node(node) + node.lcurl.accept(self) + node.args.accept(self) + node.rcurl.accept(self) + self.split_if_needed(node.args) # split if closing bracket is too far + self.exit_node(node) + + +class SubdirFetcher(FullAstVisitor): + + def __init__(self, current_dir: Path): + self.current_dir = current_dir + self.subdirs: T.List[Path] = [] + + def visit_FunctionNode(self, node: mparser.FunctionNode) -> None: + if node.func_name.value == 'subdir': + if node.args.arguments and isinstance(node.args.arguments[0], mparser.StringNode): + subdir = node.args.arguments[0].value + self.subdirs.append(self.current_dir / subdir) + super().visit_FunctionNode(node) + + +class Formatter: + + def __init__(self, configuration_file: T.Optional[Path], use_editor_config: bool, fetch_subdirs: bool): + self.fetch_subdirs = fetch_subdirs + self.use_editor_config = use_editor_config + self.config = self.load_configuration(configuration_file) + self.current_config = self.config + + self.current_dir = Path() + self.subdirs: T.List[Path] = [] + + def load_editor_config(self, source_file: Path) -> EditorConfig: + # See https://editorconfig.org/ + config = EditorConfig() + + for p in source_file.parents: + editorconfig_file = p / '.editorconfig' + if not editorconfig_file.exists(): + continue + + cp = DefaultConfigParser(delimiters=('=',)) + cp.read_default(editorconfig_file) + + sections = [section for section in cp.sections() if match_path(source_file.as_posix(), section)] + for f in fields(config): + if getattr(cp, f.name, None) is not None: + continue # value already set from higher file + + getter = f.metadata['getter'] + for section in sections: + value = getter(cp, section, f.name, fallback=None) + if value is not None: + setattr(config, f.name, value) + + if cp.getboolean(cp.default_section, 'root'): + break + + return config + + def load_configuration(self, configuration_file: T.Optional[Path]) -> FormatterConfig: + config = FormatterConfig() + if configuration_file: + cp = DefaultConfigParser() + cp.read_default(configuration_file) + + for f in fields(config): + getter = f.metadata['getter'] + value = getter(cp, cp.default_section, f.name, fallback=None) + if value is not None: + setattr(config, f.name, value) + + if config.use_editor_config: + self.use_editor_config = True + + return config + + def format(self, code: str, source_file: Path) -> str: + self.current_dir = source_file.parent + self.current_config = FormatterConfig.default() + if self.use_editor_config: + self.current_config = self.current_config.with_editorconfig(self.load_editor_config(source_file)) + self.current_config = self.current_config.update(self.config) + + ast = mparser.Parser(code, source_file.as_posix()).parse() + if self.fetch_subdirs: + subdir_fetcher = SubdirFetcher(self.current_dir) + ast.accept(subdir_fetcher) + self.subdirs = subdir_fetcher.subdirs + + ast.accept(AstConditionLevel()) + for level in range(5): + ast.accept(TrimWhitespaces(self.current_config)) + ast.accept(ArgumentFormatter(self.current_config)) + + cll = ComputeLineLengths(self.current_config, level) + ast.accept(cll) + if not cll.need_regenerate: + break + + printer = RawPrinter() + ast.accept(printer) + return printer.result + + +def add_arguments(parser: argparse.ArgumentParser) -> None: + inplace_group = parser.add_mutually_exclusive_group() + inplace_group.add_argument( + '-q', '--check-only', + action='store_true', + help='exit with 1 if files would be modified by meson format' + ) + inplace_group.add_argument( + '-i', '--inplace', + action='store_true', + help='format files in-place' + ) + parser.add_argument( + '-r', '--recursive', + action='store_true', + help='recurse subdirs (requires --check-only or --inplace option)', + ) + parser.add_argument( + '-c', '--configuration', + metavar='meson.format', + type=Path, + help='read configuration from meson.format' + ) + parser.add_argument( + '-e', '--editor-config', + action='store_true', + default=False, + help='try to read configuration from .editorconfig' + ) + parser.add_argument( + '-o', '--output', + type=Path, + help='output file (implies having exactly one input)' + ) + parser.add_argument( + 'sources', + nargs='*', + type=Path, + help='meson source files' + ) + +def run(options: argparse.Namespace) -> int: + if options.output and len(options.sources) != 1: + raise MesonException('--output argument implies having exactly one source file') + if options.recursive and not (options.inplace or options.check_only): + raise MesonException('--recursive argument requires either --inplace or --check-only option') + + sources: T.List[Path] = options.sources.copy() or [Path(build_filename)] + if not options.configuration: + default_config_path = sources[0].parent / 'meson.format' + if default_config_path.exists(): + options.configuration = default_config_path + formatter = Formatter(options.configuration, options.editor_config, options.recursive) + + while sources: + src_file = sources.pop(0) + if src_file.is_dir(): + src_file = src_file / build_filename + + try: + code = src_file.read_text(encoding='utf-8') + except IOError as e: + raise MesonException(f'Unable to read from {src_file}') from e + + formatted = formatter.format(code, src_file) + if options.recursive: + sources.extend(formatter.subdirs) + + if options.inplace: + try: + with src_file.open('w', encoding='utf-8', newline=formatter.current_config.newline) as sf: + sf.write(formatted) + except IOError as e: + raise MesonException(f'Unable to write to {src_file}') from e + elif options.check_only: + # TODO: add verbose output showing diffs + if code != formatted: + return 1 + elif options.output: + try: + with options.output.open('w', encoding='utf-8', newline=formatter.current_config.newline) as of: + of.write(formatted) + except IOError as e: + raise MesonException(f'Unable to write to {src_file}') from e + else: + print(formatted, end='') + + return 0 + +# 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 comments +# TODO: move comments on long lines + +# Differences from muon format: +# - By default, uses two spaces before comment, and added option for that +# - Muon will mix CRLF and LF on Windows files... +# - Support for end_of_line char +# - Support for max_line_length, end_of_line, insert_final_newline, tab_width in .editorconfig +# - Option to simplify string literals +# - Option to recognize and parse meson.build in subdirs +# - Correctly compute line length when using tabs +# - By default, arguments in files() are sorted alphabetically +# - Option to group '--arg', 'value' on same line in multiline arguments diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index 0e26b9ed9fbc..ec08ccfb2583 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -343,6 +343,9 @@ def __init__(self, token: Token[TV_TokenTypes]): self.kwargs = {} self.order_error = False + # Attributes for the visitors + self.is_multiline = False + def prepend(self, statement: BaseNode) -> None: if self.num_kwargs() > 0: self.order_error = True diff --git a/run_format_tests.py b/run_format_tests.py index 9be8549dfcfb..719b76b5ac21 100755 --- a/run_format_tests.py +++ b/run_format_tests.py @@ -52,6 +52,7 @@ def check_format() -> None: '.eggs', '_cache', # e.g. .mypy_cache 'venv', # virtualenvs have DOS line endings '120 rewrite', # we explicitly test for tab in meson.build file + '3 editorconfig', } for (root, _, filenames) in os.walk('.'): if any([x in root for x in skip_dirs]): diff --git a/run_mypy.py b/run_mypy.py index c57a75c12276..f1976226b753 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -45,6 +45,7 @@ 'mesonbuild/utils/universal.py', 'mesonbuild/mconf.py', 'mesonbuild/mdist.py', + 'mesonbuild/mformat.py', 'mesonbuild/minit.py', 'mesonbuild/minstall.py', 'mesonbuild/mintro.py', diff --git a/run_project_tests.py b/run_project_tests.py index b159b3d6e02a..ce88170d09ad 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -76,7 +76,8 @@ class ArgumentType(CompilerArgumentType): ALL_TESTS = ['cmake', 'common', 'native', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', 'keyval', 'platform-osx', 'platform-windows', 'platform-linux', 'java', 'C#', 'vala', 'cython', 'rust', 'd', 'objective c', 'objective c++', - 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', 'wayland' + 'fortran', 'swift', 'cuda', 'python3', 'python', 'fpga', 'frameworks', 'nasm', 'wasm', 'wayland', + 'format', ] @@ -1125,6 +1126,7 @@ def __init__(self, category: str, subdir: str, skip: bool = False, stdout_mandat TestCategory('nasm', 'nasm'), TestCategory('wasm', 'wasm', shutil.which('emcc') is None or backend is not Backend.ninja), TestCategory('wayland', 'wayland', should_skip_wayland()), + TestCategory('format', 'format'), ] categories = [t.category for t in all_tests] diff --git a/test cases/format/1 default/crazy_comments.meson b/test cases/format/1 default/crazy_comments.meson new file mode 100644 index 000000000000..f391ca28c263 --- /dev/null +++ b/test cases/format/1 default/crazy_comments.meson @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Stone Tickle +# SPDX-License-Identifier: GPL-3.0-only + +project('a') + +if ( + # comment + false # in a weird +) # place! # test +else +endif # test2 + +foreach a : ( + # test 7 + b # test 4 +) # test 6 # test 3 +endforeach +# test 5 + +a = [ + 1, + # inner + 2, # between comma + # between comma 2 +] # trailing + +( + # hello + a() +) +( + # comment 1 + # comment 2 + # comment 3 + a # comment 4 + # comment 5 + # comment 6 + = ( + # comment 7 + 1 # comment 8 + # comment 9 + + 2 # comment 10 + ) # comment 11 + # comment 12 +) # comment 13 + +# trailing comment diff --git a/test cases/format/1 default/indentation.meson b/test cases/format/1 default/indentation.meson new file mode 100644 index 000000000000..31a809abff51 --- /dev/null +++ b/test cases/format/1 default/indentation.meson @@ -0,0 +1,73 @@ +project( + 'indentation', + default_options: { + 'buildtype': 'release', + 'default_library': 'shared', + 'prefer_static': false, + 'unity': 'off', + }, + meson_version: '>= 1.5.0', + version: '1.2.3', +) + +a = [ + 1, + 2, + 3, + [ + 4, + 5, + 6, + [ + 7, + 8, + 9, + [ + 10, # 10 + 11, # 11 + 12, # 12 + ], + 13, + 14, + 15, + ], + ], +] +d = {} + +if meson.project_version().version_compare('>1.2') + if meson.version().version_compare('>1.0') + foreach i : a + e = { + 'a': 'a', + 'b': 'b', + 'c': 'c', + 'd': [ + 1, + 2, + 3, + { + 'e': 'e', + 'f': 'f', + 'g': 'g', + 'h': { + 'i': ( + # a + 1 + # b + + + # c + 2 + ), + 'j': [ + 1, # 1 + 2, # 2 + 3, # 3 + ], + }, + }, + ], + } + endforeach + endif +endif diff --git a/test cases/format/1 default/meson.build b/test cases/format/1 default/meson.build new file mode 100644 index 000000000000..5b5b1152af5e --- /dev/null +++ b/test cases/format/1 default/meson.build @@ -0,0 +1,14 @@ +# This file is for testing meson format with default options + +project('default format') + +meson_cmd = find_program('meson') +meson_files = { + 'self': files('meson.build'), + 'comments': files('crazy_comments.meson'), + 'indentation': files('indentation.meson'), +} + +foreach name, f : meson_files + test(name, meson_cmd, args: ['format', '--check-only', f]) +endforeach diff --git a/test cases/format/2 muon/crazy_comments.meson b/test cases/format/2 muon/crazy_comments.meson new file mode 100644 index 000000000000..5ebda7d63655 --- /dev/null +++ b/test cases/format/2 muon/crazy_comments.meson @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Stone Tickle +# SPDX-License-Identifier: GPL-3.0-only + +project('a') + +if ( + # comment + false # in a weird +) # place! # test +else +endif # test2 + +foreach a : ( + # test 7 + b # test 4 +) # test 6 # test 3 +endforeach +# test 5 + +a = [ + 1, + # inner + 2, # between comma + # between comma 2 +] # trailing + +( + # hello + a() +) +( + # comment 1 + # comment 2 + # comment 3 + a # comment 4 + # comment 5 + # comment 6 + = ( + # comment 7 + 1 # comment 8 + # comment 9 + + 2 # comment 10 + ) # comment 11 + # comment 12 +) # comment 13 + +# trailing comment diff --git a/test cases/format/2 muon/indentation.meson b/test cases/format/2 muon/indentation.meson new file mode 100644 index 000000000000..8f891d57cebf --- /dev/null +++ b/test cases/format/2 muon/indentation.meson @@ -0,0 +1,71 @@ +project( + 'indentation', + default_options: { + 'buildtype': 'release', + 'default_library': 'shared', + 'prefer_static': false, + 'unity': 'off', + }, + meson_version: '>= 1.5.0', + version: '1.2.3', +) + +a = [ + 1, + 2, + 3, + [ + 4, + 5, + 6, + [ + 7, + 8, + 9, + [ + 10, # 10 + 11, # 11 + 12, # 12 + ], + 13, + 14, + 15, + ], + ], +] +d = {} + +if meson.project_version().version_compare('>1.2') + if meson.version().version_compare('>1.0') + foreach i : a + e = { + 'a': 'a', + 'b': 'b', + 'c': 'c', + 'd': [ + 1, + 2, + 3, + { + 'e': 'e', + 'f': 'f', + 'g': 'g', + 'h': { + 'i': ( + # a + 1 # b + # c + + 2 + ), + 'j': [ + 1, # 1 + 2, # 2 + 3, # 3 + ], + }, + }, + ], + } + endforeach + endif +endif diff --git a/test cases/format/2 muon/meson.build b/test cases/format/2 muon/meson.build new file mode 100644 index 000000000000..165e38a5f4aa --- /dev/null +++ b/test cases/format/2 muon/meson.build @@ -0,0 +1,14 @@ +# This file is for testing meson format is compatible with muon format + +project('default format') + +meson_cmd = find_program('meson') +meson_files = { + 'self': files('meson.build'), + 'comments': files('crazy_comments.meson'), + 'indentation': files('indentation.meson'), +} + +foreach name, f : meson_files + test(name, meson_cmd, args: ['fmt', '-q', '-c', files('muon.ini'), f]) +endforeach diff --git a/test cases/format/2 muon/muon.ini b/test cases/format/2 muon/muon.ini new file mode 100644 index 000000000000..f35fa3a234ff --- /dev/null +++ b/test cases/format/2 muon/muon.ini @@ -0,0 +1,15 @@ +; This config should behave like muon default config + +; max_line_length = 80 +; indent_by = ' ' +; space_array = false +; kwargs_force_multiline = false +; wide_colon = false +; no_single_comma_function = false + +indent_before_comments = ' ' +end_of_line = lf +simplify_string_literals = false +; insert_final_newline = true +sort_files = false +; group_arg_value = false diff --git a/test cases/format/3 editorconfig/.editorconfig b/test cases/format/3 editorconfig/.editorconfig new file mode 100644 index 000000000000..5229226002c4 --- /dev/null +++ b/test cases/format/3 editorconfig/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] + +indent_style = tab +indent_size = 1 +tab_width = 4 +max_line_length = 60 diff --git a/test cases/format/3 editorconfig/crazy_comments.meson b/test cases/format/3 editorconfig/crazy_comments.meson new file mode 100644 index 000000000000..788ea1c88dff --- /dev/null +++ b/test cases/format/3 editorconfig/crazy_comments.meson @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Stone Tickle +# SPDX-License-Identifier: GPL-3.0-only + +project('a') + +if ( + # comment + false # in a weird +) # place! # test +else +endif # test2 + +foreach a : ( + # test 7 + b # test 4 +) # test 6 # test 3 +endforeach +# test 5 + +a = [ + 1, + # inner + 2, # between comma + # between comma 2 +] # trailing + +( + # hello + a() +) +( + # comment 1 + # comment 2 + # comment 3 + a # comment 4 + # comment 5 + # comment 6 + = ( + # comment 7 + 1 # comment 8 + # comment 9 + + 2 # comment 10 + ) # comment 11 + # comment 12 +) # comment 13 + +# trailing comment diff --git a/test cases/format/3 editorconfig/indentation.meson b/test cases/format/3 editorconfig/indentation.meson new file mode 100644 index 000000000000..2f348b08f6bc --- /dev/null +++ b/test cases/format/3 editorconfig/indentation.meson @@ -0,0 +1,73 @@ +project( + 'indentation', + default_options: { + 'buildtype': 'release', + 'default_library': 'shared', + 'prefer_static': false, + 'unity': 'off', + }, + meson_version: '>= 1.5.0', + version: '1.2.3', +) + +a = [ + 1, + 2, + 3, + [ + 4, + 5, + 6, + [ + 7, + 8, + 9, + [ + 10, # 10 + 11, # 11 + 12, # 12 + ], + 13, + 14, + 15, + ], + ], +] +d = {} + +if meson.project_version().version_compare('>1.2') + if meson.version().version_compare('>1.0') + foreach i : a + e = { + 'a': 'a', + 'b': 'b', + 'c': 'c', + 'd': [ + 1, + 2, + 3, + { + 'e': 'e', + 'f': 'f', + 'g': 'g', + 'h': { + 'i': ( + # a + 1 + # b + + + # c + 2 + ), + 'j': [ + 1, # 1 + 2, # 2 + 3, # 3 + ], + }, + }, + ], + } + endforeach + endif +endif diff --git a/test cases/format/3 editorconfig/meson.build b/test cases/format/3 editorconfig/meson.build new file mode 100644 index 000000000000..b32974cb9e8e --- /dev/null +++ b/test cases/format/3 editorconfig/meson.build @@ -0,0 +1,31 @@ +# This file is for testing meson format with editor config + +project('default format') + +meson_cmd = find_program('meson') +meson_files = { + 'self': files('meson.build'), + 'comments': files('crazy_comments.meson'), + 'indentation': files('indentation.meson'), +} + +foreach name, f : meson_files + test( + name, + meson_cmd, + args: ['format', '-e', '--check-only', f], + ) + + # Test that .editorconfig can also be loaded from options file + test( + name + '-fromconfig', + meson_cmd, + args: [ + 'format', + '-c', + files('options.ini'), + '--check-only', + f, + ], + ) +endforeach diff --git a/test cases/format/3 editorconfig/options.ini b/test cases/format/3 editorconfig/options.ini new file mode 100644 index 000000000000..d9f9f338bae8 --- /dev/null +++ b/test cases/format/3 editorconfig/options.ini @@ -0,0 +1 @@ +use_editor_config = true diff --git a/test cases/format/4 config/crazy_comments.meson b/test cases/format/4 config/crazy_comments.meson new file mode 100644 index 000000000000..557d5d409f65 --- /dev/null +++ b/test cases/format/4 config/crazy_comments.meson @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Stone Tickle +# SPDX-License-Identifier: GPL-3.0-only + +project('a') + +if ( + # comment + false # in a weird +) # place! # test +else +endif # test2 + +foreach a : ( + # test 7 + b # test 4 +) # test 6 # test 3 +endforeach +# test 5 + +a = [ + 1, + # inner + 2, # between comma + # between comma 2 +] # trailing + +( + # hello + a() +) +( + # comment 1 + # comment 2 + # comment 3 + a # comment 4 + # comment 5 + # comment 6 + = ( + # comment 7 + 1 # comment 8 + # comment 9 + + 2 # comment 10 + ) # comment 11 + # comment 12 +) # comment 13 + +# trailing comment diff --git a/test cases/format/4 config/indentation.meson b/test cases/format/4 config/indentation.meson new file mode 100644 index 000000000000..816b5f3026a1 --- /dev/null +++ b/test cases/format/4 config/indentation.meson @@ -0,0 +1,73 @@ +project( + 'indentation', + default_options : { + 'buildtype' : 'release', + 'default_library' : 'shared', + 'prefer_static' : false, + 'unity' : 'off', + }, + meson_version : '>= 1.5.0', + version : '1.2.3', +) + +a = [ + 1, + 2, + 3, + [ + 4, + 5, + 6, + [ + 7, + 8, + 9, + [ + 10, # 10 + 11, # 11 + 12, # 12 + ], + 13, + 14, + 15, + ], + ], +] +d = {} + +if meson.project_version().version_compare('>1.2') + if meson.version().version_compare('>1.0') + foreach i : a + e = { + 'a' : 'a', + 'b' : 'b', + 'c' : 'c', + 'd' : [ + 1, + 2, + 3, + { + 'e' : 'e', + 'f' : 'f', + 'g' : 'g', + 'h' : { + 'i' : ( + # a + 1 + # b + + + # c + 2 + ), + 'j' : [ + 1, # 1 + 2, # 2 + 3, # 3 + ], + }, + }, + ], + } + endforeach + endif +endif diff --git a/test cases/format/4 config/meson.build b/test cases/format/4 config/meson.build new file mode 100644 index 000000000000..7b49145dc115 --- /dev/null +++ b/test cases/format/4 config/meson.build @@ -0,0 +1,19 @@ +# This file is for testing meson format with custom options. +# It ensures 'meson.format' file is automatically loaded. + +project('default format') + +meson_cmd = find_program('meson') +meson_files = { + 'self' : files('meson.build'), + 'comments' : files('crazy_comments.meson'), + 'indentation' : files('indentation.meson'), +} + +foreach name, f : meson_files + test( + name, + meson_cmd, + args : [ 'format', '--check-only', f ], + ) +endforeach diff --git a/test cases/format/4 config/meson.format b/test cases/format/4 config/meson.format new file mode 100644 index 000000000000..91f9143ec76b --- /dev/null +++ b/test cases/format/4 config/meson.format @@ -0,0 +1,11 @@ +; Different options for config + +max_line_length = 120 +indent_by = ' ' +space_array = true +kwargs_force_multiline = true +wide_colon = true +no_single_comma_function = true + +indent_before_comments = ' ' +; end_of_line = 'native' diff --git a/test cases/format/5 transform/default.expected.meson b/test cases/format/5 transform/default.expected.meson new file mode 100644 index 000000000000..4201053e1f18 --- /dev/null +++ b/test cases/format/5 transform/default.expected.meson @@ -0,0 +1,69 @@ +project('a') # should be on one line + + +# List should be removed, and should be on one line +options_ini = 'options.ini' +f = files(options_ini, 'expected.meson', 'source.meson') + +# This array should fit on one line +a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + +# This array is too long and should be splitted +a2 = [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, +] + +# space array +a3 = [1, 2, 3] + +# no single comma function +fct = files( + 'meson.build', # force multiline +) + +# wide colon +d = {'a': 1, 'b': 2, 'c': 3} + +# string conversion +'This is not a multiline' +'This is not a fstring' + +# group arg value +arguments = [ + 'a', + '--opt_a', + 'opt_a_value', + 'b', + 'c', + '--opt_d', + '--opt_e', + 'opt_e_value', + '--opt_f', + '--opt_g', + 'opt_g_value', + 'other_value', + 'again', + '--x', +] + +# no final endline diff --git a/test cases/format/5 transform/default.ini b/test cases/format/5 transform/default.ini new file mode 100644 index 000000000000..a0ff816fedf8 --- /dev/null +++ b/test cases/format/5 transform/default.ini @@ -0,0 +1,15 @@ +; Use default values for config + +; max_line_length = 80 +; indent_by = ' ' +; space_array = false +; kwargs_force_multiline = false +; wide_colon = false +; no_single_comma_function = false + +; indent_before_comments = ' ' +; end_of_line = 'native' +; simplify_string_literals = true +; insert_final_newline = true +; sort_files = true +; group_arg_value = false diff --git a/test cases/format/5 transform/file_compare.py b/test cases/format/5 transform/file_compare.py new file mode 100644 index 000000000000..7b0d1b85668f --- /dev/null +++ b/test cases/format/5 transform/file_compare.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 + +import sys + +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') diff --git a/test cases/format/5 transform/genexpected.cmd b/test cases/format/5 transform/genexpected.cmd new file mode 100644 index 000000000000..de3699ddebc7 --- /dev/null +++ b/test cases/format/5 transform/genexpected.cmd @@ -0,0 +1,7 @@ +@echo off +REM This script generates the expected files +REM Please double-check the contents of those files before commiting them!!! + +python ../../../meson.py format -o default.expected.meson source.meson +python ../../../meson.py format -c muon.ini -o muon.expected.meson source.meson +python ../../../meson.py format -c options.ini -o options.expected.meson source.meson diff --git a/test cases/format/5 transform/meson.build b/test cases/format/5 transform/meson.build new file mode 100644 index 000000000000..d15fd1866517 --- /dev/null +++ b/test cases/format/5 transform/meson.build @@ -0,0 +1,29 @@ +project('format') + +fs = import('fs') + +meson_cmd = find_program('meson') +file_compare = find_program(files('file_compare.py')) +config = get_option('fmt_config') + +source = files('source.meson') +config_file = files(config + '.ini') +expected = files(config + '.expected.meson') + +transform = custom_target( + input: [config_file, source], + output: 'transformed.meson', + command: [ + meson_cmd, + 'format', + '--output', '@OUTPUT@', + '--configuration', '@INPUT@', + ], +) + + +test( + 'transform', + file_compare, + args: [transform, expected], +) diff --git a/test cases/format/5 transform/meson.options b/test cases/format/5 transform/meson.options new file mode 100644 index 000000000000..16927831a880 --- /dev/null +++ b/test cases/format/5 transform/meson.options @@ -0,0 +1 @@ +option('fmt_config', type: 'string', value: 'default') diff --git a/test cases/format/5 transform/muon.expected.meson b/test cases/format/5 transform/muon.expected.meson new file mode 100644 index 000000000000..871ce27d722d --- /dev/null +++ b/test cases/format/5 transform/muon.expected.meson @@ -0,0 +1,69 @@ +project('a') # should be on one line + + +# List should be removed, and should be on one line +options_ini = 'options.ini' +f = files('expected.meson', 'source.meson', options_ini) + +# This array should fit on one line +a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + +# This array is too long and should be splitted +a2 = [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, +] + +# space array +a3 = [1, 2, 3] + +# no single comma function +fct = files( + 'meson.build', # force multiline +) + +# wide colon +d = {'a': 1, 'b': 2, 'c': 3} + +# string conversion +'''This is not a multiline''' +f'This is not a fstring' + +# group arg value +arguments = [ + 'a', + '--opt_a', + 'opt_a_value', + 'b', + 'c', + '--opt_d', + '--opt_e', + 'opt_e_value', + '--opt_f', + '--opt_g', + 'opt_g_value', + 'other_value', + 'again', + '--x', +] + +# no final endline diff --git a/test cases/format/5 transform/muon.ini b/test cases/format/5 transform/muon.ini new file mode 100644 index 000000000000..9bf765948c81 --- /dev/null +++ b/test cases/format/5 transform/muon.ini @@ -0,0 +1,15 @@ +; This config should behave like muon default config + +; max_line_length = 80 +; indent_by = ' ' +; space_array = false +; kwargs_force_multiline = false +; wide_colon = false +; no_single_comma_function = false + +indent_before_comments = ' ' +end_of_line = lf +simplify_string_literals = false +; insert_final_newline = true +sort_files = false +; group_arg_value = false \ No newline at end of file diff --git a/test cases/format/5 transform/options.expected.meson b/test cases/format/5 transform/options.expected.meson new file mode 100644 index 000000000000..f7f45658d5c3 --- /dev/null +++ b/test cases/format/5 transform/options.expected.meson @@ -0,0 +1,48 @@ +project('a') # should be on one line + + +# List should be removed, and should be on one line +options_ini = 'options.ini' +f = files(options_ini, 'expected.meson', 'source.meson') + +# This array should fit on one line +a1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 ] + +# This array is too long and should be splitted +a2 = [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ] + +# space array +a3 = [ 1, 2, 3 ] + +# no single comma function +fct = files( + 'meson.build' # force multiline +) + +# wide colon +d = { + 'a' : 1, + 'b' : 2, + 'c' : 3, +} + +# string conversion +'This is not a multiline' +'This is not a fstring' + +# group arg value +arguments = [ + 'a', + '--opt_a', 'opt_a_value', + 'b', + 'c', + '--opt_d', + '--opt_e', 'opt_e_value', + '--opt_f', + '--opt_g', 'opt_g_value', + 'other_value', + 'again', + '--x', +] + +# no final endline \ No newline at end of file diff --git a/test cases/format/5 transform/options.ini b/test cases/format/5 transform/options.ini new file mode 100644 index 000000000000..823400b8c0cd --- /dev/null +++ b/test cases/format/5 transform/options.ini @@ -0,0 +1,15 @@ +; Different options for config + +max_line_length = 120 +indent_by = ' ' +space_array = true +kwargs_force_multiline = true +wide_colon = true +no_single_comma_function = true + +indent_before_comments = ' ' +; end_of_line = 'native' +; simplify_string_literals = true +insert_final_newline = false +; sort_files = true +group_arg_value = true diff --git a/test cases/format/5 transform/source.meson b/test cases/format/5 transform/source.meson new file mode 100644 index 000000000000..7274d4802699 --- /dev/null +++ b/test cases/format/5 transform/source.meson @@ -0,0 +1,37 @@ +project( + 'a' +) # should be on one line + + +# List should be removed, and should be on one line +options_ini = 'options.ini' +f = files( + [ + 'expected.meson', 'source.meson', options_ini]) + +# This array should fit on one line +a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + +# This array is too long and should be splitted +a2 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22] + +# space array +a3 = [ 1, 2, 3 ] + +# no single comma function +fct = files( + 'meson.build', # force multiline +) + +# wide colon +d = {'a': 1, 'b': 2, 'c': 3} + +# string conversion +'''This is not a multiline''' +f'This is not a fstring' + +# group arg value +arguments = ['a', '--opt_a', 'opt_a_value', 'b', 'c', '--opt_d', '--opt_e', 'opt_e_value', +'--opt_f', '--opt_g', 'opt_g_value', 'other_value', 'again', '--x'] + +# no final endline \ No newline at end of file diff --git a/test cases/format/5 transform/test.json b/test cases/format/5 transform/test.json new file mode 100644 index 000000000000..fe05a52b3926 --- /dev/null +++ b/test cases/format/5 transform/test.json @@ -0,0 +1,11 @@ +{ + "matrix": { + "options": { + "fmt_config": [ + { "val": "default"}, + { "val": "muon"}, + { "val": "options"} + ] + } + } +} diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 60a3a8aea82e..c334d9e5461e 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -3945,6 +3945,7 @@ def test_commands_documented(self): cmndstr = cmndline.split('{')[1] self.assertIn('}', cmndstr) help_commands = set(cmndstr.split('}')[0].split(',')) + help_commands.remove('fmt') # Remove the alias self.assertTrue(len(help_commands) > 0, 'Must detect some command names.') self.assertEqual(md_commands | {'help'}, help_commands, f'Doc file: `{doc_path}`') diff --git a/unittests/platformagnostictests.py b/unittests/platformagnostictests.py index ba3f5013c55e..ffc4b47ad2d3 100644 --- a/unittests/platformagnostictests.py +++ b/unittests/platformagnostictests.py @@ -16,6 +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.optinterpreter import OptionInterpreter, OptionException from run_tests import Backend @@ -291,6 +292,48 @@ def test_cmake_openssl_not_found_bug(self): out = self.init(testdir, allow_fail=True) self.assertNotIn('Unhandled python exception', out) + def test_editorconfig_match_path(self): + '''match_path function used to parse editorconfig in meson format''' + cases = [ + ('a.txt', '*.txt', True), + ('a.txt', '?.txt', True), + ('a.txt', 'a.t?t', True), + ('a.txt', '*.build', False), + + ('/a.txt', '*.txt', True), + ('/a.txt', '/*.txt', True), + ('a.txt', '/*.txt', False), + + ('a/b/c.txt', 'a/b/*.txt', True), + ('a/b/c.txt', 'a/*/*.txt', True), + ('a/b/c.txt', '*/*.txt', True), + ('a/b/c.txt', 'b/*.txt', True), + ('a/b/c.txt', 'a/*.txt', False), + + ('a/b/c/d.txt', 'a/**/*.txt', True), + ('a/b/c/d.txt', 'a/*', False), + ('a/b/c/d.txt', 'a/**', True), + + ('a.txt', '[abc].txt', True), + ('a.txt', '[!xyz].txt', True), + ('a.txt', '[xyz].txt', False), + ('a.txt', '[!abc].txt', False), + + ('a.txt', '{a,b,c}.txt', True), + ('a.txt', '*.{txt,tex,cpp}', True), + ('a.hpp', '*.{txt,tex,cpp}', False), + + ('a1.txt', 'a{0..9}.txt', True), + ('a001.txt', 'a{0..9}.txt', True), + ('a-1.txt', 'a{-10..10}.txt', True), + ('a99.txt', 'a{0..9}.txt', False), + ('a099.txt', 'a{0..9}.txt', False), + ('a-1.txt', 'a{0..10}.txt', False), + ] + + for filename, pattern, expected in cases: + self.assertTrue(match_path(filename, pattern) is expected, f'{filename} -> {pattern}') + 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 7ebbce207247e367f6d77ed98306fb10e97ba439 Mon Sep 17 00:00:00 2001 From: Matthijs Velsink Date: Sun, 7 Apr 2024 22:55:40 +0200 Subject: [PATCH 768/855] gnome: Fix indentation of mkenums_simple generated code Commit 83facb39593fbfa4d9cd68e86f5f56f86f1fe1eb switched to using `textwrap.dedent` for the code templates for `gnome.mkenums_simple`. That changed indentation, however, making the generated code harder to understand. We improve this by properly indenting the multiline strings before dedenting them. For optional parameters `decl_decorator` and `header_prefix`, we add a newline if they are set to keep separation between generated code blocks. --- mesonbuild/modules/gnome.py | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 9d6c1320991a..4c015074e31c 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1874,20 +1874,21 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn GType {func_prefix}@enum_name@_get_type (void) {{ - static gsize gtype_id = 0; - static const G@Type@Value values[] = {{''')) + static gsize gtype_id = 0; + static const G@Type@Value values[] = {{''')) - c_cmd.extend(['--vprod', ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },']) + c_cmd.extend(['--vprod', ' { C_@TYPE@ (@VALUENAME@), "@VALUENAME@", "@valuenick@" },']) c_cmd.append('--vtail') c_cmd.append(textwrap.dedent( - ''' { 0, NULL, NULL } - }; - if (g_once_init_enter (>ype_id)) { - GType new_type = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - g_once_init_leave (>ype_id, new_type); - } - return (GType) gtype_id; + '''\ + { 0, NULL, NULL } + }; + if (g_once_init_enter (>ype_id)) { + GType new_type = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (>ype_id, new_type); + } + return (GType) gtype_id; }''')) c_cmd.append('@INPUT@') @@ -1896,13 +1897,16 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn # .h file generation h_cmd = cmd.copy() + if header_prefix and not header_prefix.endswith('\n'): + header_prefix += '\n' # Extra trailing newline for style + h_cmd.append('--fhead') h_cmd.append(textwrap.dedent( - f'''#pragma once + f'''\ + #pragma once #include {header_prefix} - G_BEGIN_DECLS ''')) @@ -1912,9 +1916,13 @@ def mkenums_simple(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'MkEn /* enumerations from "@basename@" */ ''')) + extra_newline = '' + if decl_decorator: + extra_newline = '\n' # Extra leading newline for style + h_cmd.append('--vhead') - h_cmd.append(textwrap.dedent( - f''' + h_cmd.append(extra_newline + textwrap.dedent( + f'''\ {decl_decorator} GType {func_prefix}@enum_name@_get_type (void); #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({func_prefix}@enum_name@_get_type())''')) From ef2b164f1f6b6597b48ea34ef897f6a303499620 Mon Sep 17 00:00:00 2001 From: Matthijs Velsink Date: Sun, 7 Apr 2024 23:01:04 +0200 Subject: [PATCH 769/855] gnome: Actually run all mkenums_simple tests and fix numbering Some tests for `gnome.mkenums_simple` were only compiled, but not run. Most bugs will be caught by compilation alone, but it's better to run the generated binary too in case there are runtime issues in the generated code. The naming of all enum tests is now unified as well. --- test cases/frameworks/7 gnome/mkenums/meson.build | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test cases/frameworks/7 gnome/mkenums/meson.build b/test cases/frameworks/7 gnome/mkenums/meson.build index 2886be91ab23..284231f2f83c 100644 --- a/test cases/frameworks/7 gnome/mkenums/meson.build +++ b/test cases/frameworks/7 gnome/mkenums/meson.build @@ -121,6 +121,7 @@ test('enum test 3', enumexe3) enums4 = gnome.mkenums_simple('enums4', sources : files('meson-sample.h'), function_prefix : '_') enumexe4 = executable('enumprog4', 'main4.c', enums4, dependencies : gobj) +test('enum test 4', enumexe4) enums5 = gnome.mkenums_simple('enums5', sources : 'meson-sample.h', install_header : true, @@ -135,6 +136,7 @@ main = configure_file( configuration : conf) enumexe5 = executable('enumprog5', main, enums5, dependencies : gobj) +test('enum test 5', enumexe5) # Generate template then use as input to mkenums @@ -161,7 +163,7 @@ main = configure_file( enumexe6 = executable('enumprog6', main, enums_c2, enums_h6, dependencies : gobj) -test('enum test 4', enumexe6) +test('enum test 6', enumexe6) # Test with headers coming from other directories # https://github.com/mesonbuild/meson/pull/10855 @@ -169,6 +171,8 @@ subdir('subdir') enums7 = gnome.mkenums_simple('enums7', sources: ['meson-sample.h', h2, h3]) main = configure_file( input : 'main.c', - output : 'mai7.c', + output : 'main7.c', configuration : {'ENUM_FILE': 'enums7.h'}) -test('enums7 test', executable('enumprog7', main, enums7, dependencies : gobj)) + +enumexe7 = executable('enumprog7', main, enums7, dependencies : gobj) +test('enum test 7', enumexe7) From d617dc6869bcd5afcd784ff39cc5b6597b1912a2 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 9 Apr 2024 09:50:13 -0700 Subject: [PATCH 770/855] modules: rename qt.py -> _qt.py Since it's an implementation detail, and shouldn't be exposed. This also helps give better error messages when a user writes `import('qt')`, since otherwise you get an error about `qt doesn't have an initialize method`, and now you get `qt module doesn't exist`. --- mesonbuild/modules/{qt.py => _qt.py} | 0 mesonbuild/modules/qt4.py | 2 +- mesonbuild/modules/qt5.py | 2 +- mesonbuild/modules/qt6.py | 2 +- run_mypy.py | 2 +- unittests/datatests.py | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename mesonbuild/modules/{qt.py => _qt.py} (100%) diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/_qt.py similarity index 100% rename from mesonbuild/modules/qt.py rename to mesonbuild/modules/_qt.py diff --git a/mesonbuild/modules/qt4.py b/mesonbuild/modules/qt4.py index 354b4a5cf131..47eb007781a3 100644 --- a/mesonbuild/modules/qt4.py +++ b/mesonbuild/modules/qt4.py @@ -4,7 +4,7 @@ from __future__ import annotations import typing as T -from .qt import QtBaseModule +from ._qt import QtBaseModule from . import ModuleInfo if T.TYPE_CHECKING: diff --git a/mesonbuild/modules/qt5.py b/mesonbuild/modules/qt5.py index 11958c981beb..f950c0944edb 100644 --- a/mesonbuild/modules/qt5.py +++ b/mesonbuild/modules/qt5.py @@ -4,7 +4,7 @@ from __future__ import annotations import typing as T -from .qt import QtBaseModule +from ._qt import QtBaseModule from . import ModuleInfo if T.TYPE_CHECKING: diff --git a/mesonbuild/modules/qt6.py b/mesonbuild/modules/qt6.py index b23204678420..bf23305d6bf6 100644 --- a/mesonbuild/modules/qt6.py +++ b/mesonbuild/modules/qt6.py @@ -4,7 +4,7 @@ from __future__ import annotations import typing as T -from .qt import QtBaseModule +from ._qt import QtBaseModule from . import ModuleInfo if T.TYPE_CHECKING: diff --git a/run_mypy.py b/run_mypy.py index f1976226b753..35a90e8e9f35 100755 --- a/run_mypy.py +++ b/run_mypy.py @@ -62,7 +62,7 @@ 'mesonbuild/modules/keyval.py', 'mesonbuild/modules/modtest.py', 'mesonbuild/modules/pkgconfig.py', - 'mesonbuild/modules/qt.py', + 'mesonbuild/modules/_qt.py', 'mesonbuild/modules/qt4.py', 'mesonbuild/modules/qt5.py', 'mesonbuild/modules/qt6.py', diff --git a/unittests/datatests.py b/unittests/datatests.py index 4f9d52032fa4..b14bbac5a29a 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -201,7 +201,7 @@ def test_modules_in_navbar(self): html = f.read().lower() self.assertIsNotNone(html) for f in Path('mesonbuild/modules').glob('*.py'): - if f.name in {'modtest.py', 'qt.py', '__init__.py'}: + if f.name.startswith('_') or f.name == 'modtest.py': continue name = f'{f.stem}-module.html' name = name.replace('unstable_', '') From d6a0b7a6ecde30d44fb1960866385d8f5a6e30f3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 9 Apr 2024 09:53:48 -0700 Subject: [PATCH 771/855] interpreter: never expose implementation details of the modules package When a user writes `import'foo')`, Meson checks the `mesonbuild/modules/` directory for a package called `foo.py`, and attempts to import it. We don't want to expose any implementation detail packages like `_qt.py`, so if someone write `import('_qt')`, we should immediately give a "doesn't exist" error. --- mesonbuild/interpreter/interpreter.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 6e38c5722592..de8f24d2c9b7 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -608,6 +608,10 @@ def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], if disabled: return NotFoundExtensionModule(modname) + # Always report implementation detail modules don't exist + if modname.startswith('_'): + raise InvalidArguments(f'Module "{modname}" does not exist') + expect_unstable = False # Some tests use "unstable_" instead of "unstable-", and that happens to work because # of implementation details From 7b77fa01745171bed238b4c40a6b485c67d6b060 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 25 Apr 2023 21:36:38 +0000 Subject: [PATCH 772/855] nasm, yasm: Fix debug flags for Windows and macOS --- mesonbuild/compilers/asm.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index d04fbd2938fb..0cf8cffd37ed 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -27,6 +27,7 @@ class NasmCompiler(Compiler): language = 'nasm' id = 'nasm' + links_with_msvc = False # https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features crt_args: T.Dict[str, T.List[str]] = { @@ -44,6 +45,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, super().__init__(ccache, exelist, version, for_machine, info, linker, full_version, is_cross) if 'link' in self.linker.id: self.base_options.add(OptionKey('b_vscrt')) + self.links_with_msvc = True def needs_static_linker(self) -> bool: return True @@ -83,9 +85,7 @@ def get_optimization_args(self, optimization_level: str) -> T.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]: if is_debug: - if self.info.is_windows(): - return [] - return ['-g', '-F', 'dwarf'] + return ['-g'] return [] def get_depfile_suffix(self) -> str: @@ -138,9 +138,12 @@ def get_exelist(self, ccache: bool = True) -> T.List[str]: def get_debug_args(self, is_debug: bool) -> T.List[str]: if is_debug: - if self.info.is_windows(): + if self.info.is_windows() and self.links_with_msvc: + return ['-g', 'cv8'] + elif self.info.is_darwin(): return ['-g', 'null'] - return ['-g', 'dwarf2'] + else: + return ['-g', 'dwarf2'] return [] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: From c0696889ff4fdde18a1ea3cbfba727f1a4b7a137 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 25 Apr 2023 11:33:43 -0300 Subject: [PATCH 773/855] backends: Add Nasm support to Xcode through a custom build rule --- mesonbuild/backend/backends.py | 39 ++++++++++++----- mesonbuild/backend/xcodebackend.py | 68 +++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index af730f88ef22..0db5c79af705 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -2013,6 +2013,34 @@ def get_devenv(self) -> mesonlib.EnvironmentVariables: env.prepend('PATH', list(extra_paths)) return env + def compiler_to_generator_args(self, target: build.BuildTarget, + compiler: 'Compiler', output: str = '@OUTPUT@', + depfile: T.Union[str, None] = '@DEPFILE@', + extras: T.Union[T.List[str], None] = None, + input: str = '@INPUT@') -> CompilerArgs: + ''' + The VS and Xcode backends need the full set of arguments for making a + custom build rule. This is a convenience method to convert a Compiler + to its arguments, for later concatenation. + ''' + # FIXME: There are many other args missing + commands = self.generate_basic_compiler_args(target, compiler) + if depfile: + commands += compiler.get_dependency_gen_args(output, depfile) + commands += compiler.get_output_args(output) + commands += self.get_source_dir_include_args(target, compiler) + commands += self.get_build_dir_include_args(target, compiler) + commands += compiler.get_compile_only_args() + # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these + # near the end since these are supposed to override everything else. + commands += self.escape_extra_args(target.get_extra_args(compiler.get_language())) + # Do not escape this one, it is interpreted by the build system + # (Xcode considers these as variables to expand at build time) + if extras is not None: + commands += extras + commands += [input] + return commands + def compiler_to_generator(self, target: build.BuildTarget, compiler: 'Compiler', sources: _ALL_SOURCES_TYPE, @@ -2026,16 +2054,7 @@ def compiler_to_generator(self, target: build.BuildTarget, exelist = compiler.get_exelist() exe = programs.ExternalProgram(exelist[0]) args = exelist[1:] - # FIXME: There are many other args missing - commands = self.generate_basic_compiler_args(target, compiler) - commands += compiler.get_dependency_gen_args('@OUTPUT@', '@DEPFILE@') - commands += compiler.get_output_args('@OUTPUT@') - commands += compiler.get_compile_only_args() + ['@INPUT@'] - commands += self.get_source_dir_include_args(target, compiler) - commands += self.get_build_dir_include_args(target, compiler) - # Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these - # near the end since these are supposed to override everything else. - commands += self.escape_extra_args(target.get_extra_args(compiler.get_language())) + commands = self.compiler_to_generator_args(target, compiler) generator = build.Generator(exe, args + commands.to_native(), [output_templ], depfile='@PLAINNAME@.d', depends=depends) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index abdac0cc6964..2d151297756c 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -10,9 +10,12 @@ from .. import build from .. import mesonlib from .. import mlog +from ..arglist import CompilerArgs from ..mesonlib import MesonBugException, MesonException, OptionKey if T.TYPE_CHECKING: + from ..build import BuildTarget + from ..compilers import Compiler from ..interpreter import Interpreter INDENT = '\t' @@ -33,10 +36,12 @@ 'dylib': 'compiled.mach-o.dylib', 'o': 'compiled.mach-o.objfile', 's': 'sourcecode.asm', - 'asm': 'sourcecode.asm', + 'asm': 'sourcecode.nasm', 'metal': 'sourcecode.metal', 'glsl': 'sourcecode.glsl', } +NEEDS_CUSTOM_RULES = {'nasm': 'sourcecode.nasm', + } LANGNAMEMAP = {'c': 'C', 'cpp': 'CPLUSPLUS', 'objc': 'OBJC', @@ -271,6 +276,7 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: self.generate_native_target_map() self.generate_native_frameworks_map() self.generate_custom_target_map() + self.generate_native_target_build_rules_map() self.generate_generator_target_map() self.generate_source_phase_map() self.generate_target_dependency_map() @@ -288,6 +294,9 @@ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: objects_dict.add_comment(PbxComment('Begin PBXBuildFile section')) self.generate_pbx_build_file(objects_dict) objects_dict.add_comment(PbxComment('End PBXBuildFile section')) + objects_dict.add_comment(PbxComment('Begin PBXBuildRule section')) + self.generate_pbx_build_rule(objects_dict) + objects_dict.add_comment(PbxComment('End PBXBuildRule section')) objects_dict.add_comment(PbxComment('Begin PBXBuildStyle section')) self.generate_pbx_build_style(objects_dict) objects_dict.add_comment(PbxComment('End PBXBuildStyle section')) @@ -401,6 +410,16 @@ def generate_native_target_map(self) -> None: for t in self.build_targets: self.native_targets[t] = self.gen_id() + def generate_native_target_build_rules_map(self) -> None: + self.build_rules = {} + for name, target in self.build_targets.items(): + languages = {} + for language in target.compilers: + if language not in NEEDS_CUSTOM_RULES: + continue + languages[language] = self.gen_id() + self.build_rules[name] = languages + def generate_custom_target_map(self) -> None: self.shell_targets = {} self.custom_target_output_buildfile = {} @@ -720,6 +739,48 @@ def generate_pbx_build_style(self, objects_dict: PbxDict) -> None: settings_dict.add_item('COPY_PHASE_STRIP', 'NO') styledict.add_item('name', f'"{name}"') + def to_shell_script(self, args: CompilerArgs) -> str: + quoted_cmd = [] + for c in args: + quoted_cmd.append(c.replace('"', chr(92) + '"')) + cmd = ' '.join(quoted_cmd) + return f"\"#!/bin/sh\\n{cmd}\\n\"" + + def generate_pbx_build_rule(self, objects_dict: PbxDict) -> None: + for name, languages in self.build_rules.items(): + target: BuildTarget = self.build_targets[name] + for language, idval in languages.items(): + compiler: Compiler = target.compilers[language] + buildrule = PbxDict() + buildrule.add_item('isa', 'PBXBuildRule') + buildrule.add_item('compilerSpec', 'com.apple.compilers.proxy.script') + if compiler.get_id() != 'yasm': + # Yasm doesn't generate escaped build rules + buildrule.add_item('dependencyFile', '"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).d"') + buildrule.add_item('fileType', NEEDS_CUSTOM_RULES[language]) + inputfiles = PbxArray() + buildrule.add_item('inputFiles', inputfiles) + buildrule.add_item('isEditable', '0') + outputfiles = PbxArray() + outputfiles.add_item('"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).o"') + buildrule.add_item('outputFiles', outputfiles) + # Do NOT use this parameter. Xcode will accept it from the UI, + # but the parser will break down inconsistently upon next + # opening. rdar://FB12144055 + # outputargs = PbxArray() + # args = self.generate_basic_compiler_args(target, compiler) + # outputargs.add_item(self.to_shell_script(args)) + # buildrule.add_item('outputFilesCompilerFlags', outputargs) + commands = CompilerArgs(compiler) + commands += compiler.get_exelist() + if compiler.get_id() == 'yasm': + # Yasm doesn't generate escaped build rules + commands += self.compiler_to_generator_args(target, compiler, output='"$SCRIPT_OUTPUT_FILE_0"', input='"$SCRIPT_INPUT_FILE"', depfile=None) + else: + commands += self.compiler_to_generator_args(target, compiler, output='"$SCRIPT_OUTPUT_FILE_0"', input='"$SCRIPT_INPUT_FILE"', depfile='"$(dirname "$SCRIPT_OUTPUT_FILE_0")/$(basename "$SCRIPT_OUTPUT_FILE_0" .o).d"', extras=['$OTHER_INPUT_FILE_FLAGS']) + buildrule.add_item('script', self.to_shell_script(commands)) + objects_dict.add_item(idval, buildrule, 'PBXBuildRule') + def generate_pbx_container_item_proxy(self, objects_dict: PbxDict) -> None: for t in self.build_targets: proxy_dict = PbxDict() @@ -1115,7 +1176,10 @@ def generate_pbx_native_target(self, objects_dict: PbxDict) -> None: generator_id += 1 for bpname, bpval in t.buildphasemap.items(): buildphases_array.add_item(bpval, f'{bpname} yyy') - ntarget_dict.add_item('buildRules', PbxArray()) + build_rules = PbxArray() + for language, build_rule_idval in self.build_rules[tname].items(): + build_rules.add_item(build_rule_idval, f'{language}') + ntarget_dict.add_item('buildRules', build_rules) dep_array = PbxArray() ntarget_dict.add_item('dependencies', dep_array) dep_array.add_item(self.regen_dependency_id) From af40f98d87caafee65b9189b89f8858b518dc2b3 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 25 Apr 2023 21:35:44 +0000 Subject: [PATCH 774/855] nasm test: Set the correct supported OSes for the tests --- test cases/nasm/1 configure file/meson.build | 18 ++++++++++-------- test cases/nasm/2 asm language/meson.build | 6 ++---- test cases/nasm/3 nasm only/meson.build | 4 ++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/test cases/nasm/1 configure file/meson.build b/test cases/nasm/1 configure file/meson.build index 85ecaf1c4489..fac46a687331 100644 --- a/test cases/nasm/1 configure file/meson.build +++ b/test cases/nasm/1 configure file/meson.build @@ -1,15 +1,17 @@ project('nasm config file', 'c') -if host_machine.cpu_family() == 'x86' and host_machine.system() == 'windows' - asm_format = 'win32' -elif host_machine.cpu_family() == 'x86_64' and host_machine.system() == 'windows' - asm_format = 'win64' -elif host_machine.cpu_family() == 'x86' and host_machine.system() == 'linux' +if not host_machine.cpu_family().startswith('x86') + error('MESON_SKIP_TEST: nasm only supported for x86 and x86_64') +endif + +if host_machine.system() != 'linux' + error('MESON_SKIP_TEST: this test asm is made for Linux') +endif + +if host_machine.cpu_family() == 'x86' asm_format = 'elf32' -elif host_machine.cpu_family() == 'x86_64' and host_machine.system() == 'linux' - asm_format = 'elf64' else - error('MESON_SKIP_TEST: skipping test on this platform') + asm_format = 'elf64' endif nasm = find_program('nasm', required: false) diff --git a/test cases/nasm/2 asm language/meson.build b/test cases/nasm/2 asm language/meson.build index d025d43ea9b7..d5a2ba3eaeb2 100644 --- a/test cases/nasm/2 asm language/meson.build +++ b/test cases/nasm/2 asm language/meson.build @@ -5,10 +5,8 @@ if not host_machine.cpu_family().startswith('x86') error('MESON_SKIP_TEST: nasm only supported for x86 and x86_64') endif -if host_machine.system() == 'windows' - error('MESON_SKIP_TEST: this test asm is not made for Windows') -elif host_machine.system() == 'sunos' - error('MESON_SKIP_TEST: this test asm is not made for Solaris or illumos') +if host_machine.system() != 'linux' + error('MESON_SKIP_TEST: this test asm is made for Linux') endif if meson.backend().startswith('vs') diff --git a/test cases/nasm/3 nasm only/meson.build b/test cases/nasm/3 nasm only/meson.build index 9777291f5a4e..18b980da531a 100644 --- a/test cases/nasm/3 nasm only/meson.build +++ b/test cases/nasm/3 nasm only/meson.build @@ -4,6 +4,10 @@ if not add_languages('nasm', required: false) error('MESON_SKIP_TEST: nasm not found') endif +if not ['linux', 'windows'].contains(host_machine.system()) + error('MESON_SKIP_TEST: this test asm is made for Windows and Linux') +endif + if meson.backend().startswith('vs') error('MESON_SKIP_TEST: VS backend does not recognise NASM yet') endif From 53ec050e3606d26f847209bd2b4703cd0b23289a Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 25 Apr 2023 21:39:40 +0000 Subject: [PATCH 775/855] nasm test: Add a test for validating the Xcode backend --- .../nasm/4 through configure/dummy.asm.in | 4 +++ test cases/nasm/4 through configure/dummy.def | 2 ++ .../nasm/4 through configure/meson.build | 30 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 test cases/nasm/4 through configure/dummy.asm.in create mode 100644 test cases/nasm/4 through configure/dummy.def create mode 100644 test cases/nasm/4 through configure/meson.build diff --git a/test cases/nasm/4 through configure/dummy.asm.in b/test cases/nasm/4 through configure/dummy.asm.in new file mode 100644 index 000000000000..5be150e44c9d --- /dev/null +++ b/test cases/nasm/4 through configure/dummy.asm.in @@ -0,0 +1,4 @@ +global dummy +section .rodata align=16 +dummy: + dd 0x00010203 diff --git a/test cases/nasm/4 through configure/dummy.def b/test cases/nasm/4 through configure/dummy.def new file mode 100644 index 000000000000..8f8eb995993d --- /dev/null +++ b/test cases/nasm/4 through configure/dummy.def @@ -0,0 +1,2 @@ +EXPORTS + dummy diff --git a/test cases/nasm/4 through configure/meson.build b/test cases/nasm/4 through configure/meson.build new file mode 100644 index 000000000000..373810f5f858 --- /dev/null +++ b/test cases/nasm/4 through configure/meson.build @@ -0,0 +1,30 @@ +project('through configure') + +if not add_languages('nasm', required: false) + error('MESON_SKIP_TEST: nasm not found') +endif + +if not host_machine.cpu_family().startswith('x86') + assert(not add_languages('nasm', required: false)) + error('MESON_SKIP_TEST: nasm only supported for x86 and x86_64') +endif + +if meson.backend().startswith('vs') + error('MESON_SKIP_TEST: VS backend does not recognise NASM yet') +endif + +section = host_machine.system() == 'macos' ? '.rodata' : '.rdata' + +sources = configure_file( + input: 'dummy.asm.in', + output: 'dummy.asm', + configuration: { + 'section': section + } +) + +dummy = library( + 'dummy', + sources, + vs_module_defs: 'dummy.def', +) From 5e10033eb5aebeaa835a2eab800defad68916ce5 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 9 Apr 2024 22:08:59 -0300 Subject: [PATCH 776/855] backends: Add Nasm support to Xcode through a custom build rule --- mesonbuild/backend/xcodebackend.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 2d151297756c..467cd1a6dc0b 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -777,7 +777,12 @@ def generate_pbx_build_rule(self, objects_dict: PbxDict) -> None: # Yasm doesn't generate escaped build rules commands += self.compiler_to_generator_args(target, compiler, output='"$SCRIPT_OUTPUT_FILE_0"', input='"$SCRIPT_INPUT_FILE"', depfile=None) else: - commands += self.compiler_to_generator_args(target, compiler, output='"$SCRIPT_OUTPUT_FILE_0"', input='"$SCRIPT_INPUT_FILE"', depfile='"$(dirname "$SCRIPT_OUTPUT_FILE_0")/$(basename "$SCRIPT_OUTPUT_FILE_0" .o).d"', extras=['$OTHER_INPUT_FILE_FLAGS']) + commands += self.compiler_to_generator_args(target, + compiler, + output='"$SCRIPT_OUTPUT_FILE_0"', + input='"$SCRIPT_INPUT_FILE"', + depfile='"$(dirname "$SCRIPT_OUTPUT_FILE_0")/$(basename "$SCRIPT_OUTPUT_FILE_0" .o).d"', + extras=['$OTHER_INPUT_FILE_FLAGS']) buildrule.add_item('script', self.to_shell_script(commands)) objects_dict.add_item(idval, buildrule, 'PBXBuildRule') From 6c090cab510368e5a678ac3d3b1c59fba1b182f5 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 9 Apr 2024 22:09:11 -0300 Subject: [PATCH 777/855] nasm, yasm: Fix debug flags for Windows and macOS --- 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 0cf8cffd37ed..bfe436b0b256 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -27,7 +27,6 @@ class NasmCompiler(Compiler): language = 'nasm' id = 'nasm' - links_with_msvc = False # https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features crt_args: T.Dict[str, T.List[str]] = { @@ -43,6 +42,7 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, linker: T.Optional['DynamicLinker'] = None, full_version: T.Optional[str] = None, is_cross: bool = False): super().__init__(ccache, exelist, version, for_machine, info, linker, full_version, is_cross) + self.links_with_msvc = False if 'link' in self.linker.id: self.base_options.add(OptionKey('b_vscrt')) self.links_with_msvc = True From 230097fb171faa1e4c0cd5d6a81b570d09af6293 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 9 Apr 2024 22:19:31 +0300 Subject: [PATCH 778/855] Do not use verbose mode in unittests. --- run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_tests.py b/run_tests.py index 20765321981e..186893f6acc2 100755 --- a/run_tests.py +++ b/run_tests.py @@ -397,7 +397,7 @@ def main(): else: print(mlog.bold('Running unittests.')) print(flush=True) - cmd = mesonlib.python_command + ['run_unittests.py', '-v'] + backend_flags + cmd = mesonlib.python_command + ['run_unittests.py'] + backend_flags if options.failfast: cmd += ['--failfast'] returncode += subprocess_call(cmd, env=env) From db1b8947f01667ca106510f8c7ff60d1e0d0c702 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 9 Apr 2024 22:51:49 +0300 Subject: [PATCH 779/855] Add a verbose output option to run_project_tests and default it to off. --- run_project_tests.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index ce88170d09ad..37f428b7d0dc 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -72,6 +72,7 @@ class ArgumentType(CompilerArgumentType): failfast: bool no_unittests: bool only: T.List[str] + v: bool ALL_TESTS = ['cmake', 'common', 'native', 'warning-meson', 'failing-meson', 'failing-build', 'failing-test', 'keyval', 'platform-osx', 'platform-windows', 'platform-linux', @@ -89,6 +90,7 @@ class BuildStep(Enum): clean = 5 validate = 6 +verbose_output = False class TestResult(BaseException): def __init__(self, cicmds: T.List[str]) -> None: @@ -1178,8 +1180,9 @@ def result(self) -> T.Optional[TestResult]: return self.future.result() if self.future else None def log(self) -> None: - without_install = '' if install_commands else '(without install)' - safe_print(self.status.value, without_install, *self.testdef.display_name()) + if verbose_output or self.status.value != TestStatus.OK.value: + without_install = '' if install_commands else '(without install)' + safe_print(self.status.value, without_install, *self.testdef.display_name()) def update_log(self, new_status: TestStatus) -> None: self.status = new_status @@ -1606,10 +1609,13 @@ def setup_symlinks() -> None: help='Not used, only here to simplify run_tests.py') parser.add_argument('--only', default=[], help='name of test(s) to run, in format "category[/name]" where category is one of: ' + ', '.join(ALL_TESTS), nargs='+') + parser.add_argument('-v', default=False, action='store_true', + help='Verbose mode') parser.add_argument('--cross-file', action='store', help='File describing cross compilation environment.') parser.add_argument('--native-file', action='store', help='File describing native compilation environment.') parser.add_argument('--use-tmpdir', action='store_true', help='Use tmp directory for temporary files.') options = T.cast('ArgumentType', parser.parse_args()) + verbose_output = options.v if options.cross_file: options.extra_args += ['--cross-file', options.cross_file] From e25b61b5c2e8c0451558d022a759290d14c1b916 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 9 Apr 2024 23:02:46 +0300 Subject: [PATCH 780/855] Do not even submit test suites that are skipped completely. --- run_project_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run_project_tests.py b/run_project_tests.py index 37f428b7d0dc..e545a8d6dd71 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -1235,6 +1235,7 @@ def _run_tests(all_tests: T.List[T.Tuple[str, T.List[TestDef], bool]], current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))}) if skipped: futures += [LogRunFuture(['\n', bold(f'Not running {name} tests.'), '\n'])] + continue else: futures += [LogRunFuture(['\n', bold(f'Running {name} tests.'), '\n'])] From bf00ca69b5eb8c836ba76402bb94ccf52660d724 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Tue, 9 Apr 2024 23:14:20 +0300 Subject: [PATCH 781/855] Document a probable cause for test failures. --- test cases/frameworks/4 qt/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index 759e6cc176b5..54cd7cb9bac3 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -48,7 +48,7 @@ foreach qt : ['qt4', 'qt5', 'qt6'] qtdep = dependency(qt, modules : qt_modules, main : true, private_headers: true, required : required, method : get_option('method')) if qtdep.found() qtmodule = import(qt) - assert(qtmodule.has_tools()) + assert(qtmodule.has_tools(), 'You may be missing a devel package. (qttools5-dev-tools on Debian based systems)') # Test that fetching a variable works and yields a non-empty value assert(qtdep.get_variable('prefix', configtool: 'QT_INSTALL_PREFIX') != '') From bcb82b390a382e10b6dd5a8e27727b31ada811b1 Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 8 Mar 2024 11:57:35 +0100 Subject: [PATCH 782/855] cmake: best-effort build type propagation --- mesonbuild/cmake/interpreter.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 68cbea497887..eae2c17f247a 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -67,6 +67,14 @@ 'CMP0102', ] +# CMake is a bit more averse to debugging, but in spirit the build types match +buildtype_map = { + 'debug': 'Debug', + 'debugoptimized': 'RelWithDebInfo', # CMake sets NDEBUG + 'release': 'Release', + 'minsize': 'MinSizeRel', # CMake leaves out debug information immediately +} + target_type_map = { 'STATIC_LIBRARY': 'static_library', 'MODULE_LIBRARY': 'shared_module', @@ -819,6 +827,11 @@ def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: cmake_args += cmake_get_generator_args(self.env) cmake_args += [f'-DCMAKE_INSTALL_PREFIX={self.install_prefix}'] cmake_args += extra_cmake_options + if not any(arg.startswith('-DCMAKE_BUILD_TYPE=') for arg in cmake_args): + # Our build type is favored over any CMAKE_BUILD_TYPE environment variable + buildtype = T.cast('str', self.env.coredata.get_option(OptionKey('buildtype'))) + if buildtype in buildtype_map: + cmake_args += [f'-DCMAKE_BUILD_TYPE={buildtype_map[buildtype]}'] trace_args = self.trace.trace_args() cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in disable_policy_warnings] From b6d7a7a5b72e708a0f6480bb6f143c95cdbe3cde Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 10 Apr 2024 10:32:15 -0700 Subject: [PATCH 783/855] dependencies/llvm: Try to make warning about CMake better We have seen a number of bugs from people confused by warning that the need both a C and C++ compiler to use the CMake method. This attempts to provide a more helpful error message. --- mesonbuild/dependencies/dev.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 72dbb4522a81..89761f24f379 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -393,7 +393,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> compilers = env.coredata.compilers.build else: compilers = env.coredata.compilers.host - if not compilers or not all(x in compilers for x in ('c', 'cpp')): + if not compilers or not {'c', 'cpp'}.issubset(compilers): # Initialize basic variables ExternalDependency.__init__(self, DependencyTypeName('cmake'), env, kwargs) @@ -401,8 +401,29 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> self.found_modules: T.List[str] = [] self.name = name - # Warn and return - mlog.warning('The LLVM dependency was not found via CMake since both a C and C++ compiler are required.') + langs: T.List[str] = [] + if not compilers: + langs = ['c', 'cpp'] + else: + if 'c' not in compilers: + langs.append('c') + if 'cpp' not in compilers: + langs.append('cpp') + + mlog.warning( + 'The LLVM dependency was not found via CMake, as this method requires', + 'both a C and C++ compiler to be enabled, but', + 'only' if langs else 'neither', + 'a', + " nor ".join(l.upper() for l in langs), + 'compiler is enabled for the', + f"{self.for_machine}.", + "Consider adding {0} to your project() call or using add_languages({0}, native : {1})".format( + ', '.join(f"'{l}'" for l in langs), + 'true' if self.for_machine is mesonlib.MachineChoice.BUILD else 'false', + ), + 'before the LLVM dependency lookup.' + ) return super().__init__(name, env, kwargs, language='cpp', force_use_global_compilers=True) From f44541e1c74bcddcb6cf0dafdefe63f00048859f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 10 Apr 2024 10:33:59 -0700 Subject: [PATCH 784/855] dependencies/dev: make the warning about LLVM's CMake non-fatal This isn't case where fatal is appropriate, as the end user has no control over this, and it may not be hit in all configurations of a project. --- mesonbuild/dependencies/dev.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index 89761f24f379..de85516feb64 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -413,16 +413,17 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> mlog.warning( 'The LLVM dependency was not found via CMake, as this method requires', 'both a C and C++ compiler to be enabled, but', - 'only' if langs else 'neither', + 'only' if len(langs) == 1 else 'neither', 'a', - " nor ".join(l.upper() for l in langs), + " nor ".join(l.upper() for l in langs).replace('CPP', 'C++'), 'compiler is enabled for the', f"{self.for_machine}.", - "Consider adding {0} to your project() call or using add_languages({0}, native : {1})".format( + 'Consider adding "{0}" to your project() call or using add_languages({0}, native : {1})'.format( ', '.join(f"'{l}'" for l in langs), 'true' if self.for_machine is mesonlib.MachineChoice.BUILD else 'false', ), - 'before the LLVM dependency lookup.' + 'before the LLVM dependency lookup.', + fatal=False, ) return From 4e6bed6eb0ab1fe7ae93c7f99176be0cd17d8b22 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 11 Apr 2024 20:37:21 -0700 Subject: [PATCH 785/855] docs: Howto exclude file from unity build Adds a howto section describing how to put files in a separate build target and override the unity build setting, and why you might want to do this. Closes: #13031 --- docs/markdown/howtox.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md index 8b56c807e592..4a57e8569137 100644 --- a/docs/markdown/howtox.md +++ b/docs/markdown/howtox.md @@ -323,3 +323,24 @@ executable( deps : [my_dep] ) ``` + +## Exclude a file from unity builds + +If your project supports unity builds, you should fix any bugs that crop up when +source files are concatenated together. +Sometimes this isn't possible, though, for example if the source files are +generated. + +In this case, you can put them in a separate static library build target and +override the unity setting. + +```meson +generated_files = ... +unityproof_lib = static_library('unityproof', generated_files, + override_options : ['unity=off']) + +main_exe = executable('main', main_sources, link_with : unityproof_lib) +``` + +To link the static library into another library target, you may need to use +`link_whole` instead of `link_with`. From 9f02d0a3e5a5ffc82256391c244b1af38e41ef78 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 5 Apr 2024 08:55:20 -0700 Subject: [PATCH 786/855] Clarify mutable objects usage Only Environment and ConfigurationData are mutable. However, only ConfigurationData becomes immutable after first use which is inconsistent. This deprecates modification after first use of Environment object and clarify documentation. --- 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, 102 insertions(+), 36 deletions(-) create mode 100755 test cases/common/113 interpreter copy mutable var on assignment/check_env.py delete mode 100644 test cases/failing/70 configuration immutable/input delete mode 100644 test cases/failing/70 configuration immutable/meson.build delete mode 100644 test cases/failing/70 configuration immutable/test.json diff --git a/docs/markdown/Configuration.md b/docs/markdown/Configuration.md index 48f071e6c9e4..b5875e55e6d9 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. -Copy of immutable `configuration_data` is still immutable. +*Since 1.5.0* Copy of immutable `configuration_data` is however mutable. 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 03abb170970e..069cadbf6eb1 100644 --- a/docs/yaml/objects/cfg_data.yaml +++ b/docs/yaml/objects/cfg_data.yaml @@ -1,10 +1,14 @@ 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 wiki - page](Configuration.md). + 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. methods: - name: set diff --git a/docs/yaml/objects/env.yaml b/docs/yaml/objects/env.yaml index 714da4fe422a..3b2e2a851b24 100644 --- a/docs/yaml/objects/env.yaml +++ b/docs/yaml/objects/env.yaml @@ -9,6 +9,11 @@ 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() @@ -18,6 +23,14 @@ 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 5f712a57348f..edf785c0d855 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -284,6 +284,7 @@ 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, @@ -308,12 +309,14 @@ 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) @@ -321,6 +324,7 @@ 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) @@ -328,6 +332,7 @@ 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']) @@ -338,6 +343,7 @@ 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, @@ -349,32 +355,31 @@ def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'): }) def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder': - return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter) - - def is_used(self) -> bool: - return self.held_object.used - - def __check_used(self) -> None: + obj = ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter) if self.is_used(): - raise InterpreterException("Can not set values on configuration object that has been 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 @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.check_used(self.interpreter) 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.check_used(self.interpreter) 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.check_used(self.interpreter) # 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. @@ -437,6 +442,7 @@ 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 c62aafe8e97b..e32b77fc7d4b 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 +from .baseobjects import InterpreterObject, MesonInterpreterObject, ObjectHolder, HoldableTypes, MutableInterpreterObject from .exceptions import InvalidArguments from ..mesonlib import HoldableObject, MesonBugException @@ -13,6 +13,8 @@ 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 9a119a98a75d..c6864a4788c5 100644 --- a/mesonbuild/interpreterbase/baseobjects.py +++ b/mesonbuild/interpreterbase/baseobjects.py @@ -120,6 +120,27 @@ 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 new file mode 100755 index 000000000000..034d2924331b --- /dev/null +++ b/test cases/common/113 interpreter copy mutable var on assignment/check_env.py @@ -0,0 +1,7 @@ +#!/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 d414bfc74e0c..3d4f3b039c76 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') +project('foo', meson_version: '>=1.5') a = configuration_data() a.set('HELLO', 1) @@ -10,6 +10,15 @@ 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) @@ -17,3 +26,26 @@ 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 deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test cases/failing/70 configuration immutable/meson.build b/test cases/failing/70 configuration immutable/meson.build deleted file mode 100644 index b6cac41265e0..000000000000 --- a/test cases/failing/70 configuration immutable/meson.build +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index fc735fa38ece..000000000000 --- a/test cases/failing/70 configuration immutable/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "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 1b9eb6f3134d61c5ea0026ac95d807aab812c414 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 14 Apr 2024 20:46:42 +0300 Subject: [PATCH 787/855] Fix builds with Ninja 12 and remove a 5 year old workaround. --- run_project_tests.py | 3 +-- run_tests.py | 35 ++++++++++------------------------ unittests/baseplatformtests.py | 5 +---- 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/run_project_tests.py b/run_project_tests.py index e545a8d6dd71..23561d97357a 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -45,7 +45,7 @@ from mesonbuild.modules.python import PythonExternalProgram from run_tests import ( get_fake_options, run_configure, get_meson_script, get_backend_commands, - get_backend_args_for_dir, Backend, ensure_backend_detects_changes, + get_backend_args_for_dir, Backend, guess_backend, handle_meson_skip_test, ) @@ -723,7 +723,6 @@ def build_step() -> None: # Touch the meson.build file to force a regenerate def force_regenerate() -> None: - ensure_backend_detects_changes(backend) os.utime(str(test.path / 'meson.build')) # just test building diff --git a/run_tests.py b/run_tests.py index 186893f6acc2..6d33dd99e145 100755 --- a/run_tests.py +++ b/run_tests.py @@ -39,29 +39,27 @@ if T.TYPE_CHECKING: from mesonbuild.coredata import SharedCMDOptions -NINJA_1_9_OR_NEWER = False +NINJA_1_12_OR_NEWER = False NINJA_CMD = None # If we're on CI, detecting ninja for every subprocess unit test that we run is slow # Optimize this by respecting $NINJA and skipping detection, then exporting it on # first run. try: - NINJA_1_9_OR_NEWER = bool(int(os.environ['NINJA_1_9_OR_NEWER'])) + NINJA_1_12_OR_NEWER = bool(int(os.environ['NINJA_1_12_OR_NEWER'])) NINJA_CMD = [os.environ['NINJA']] except (KeyError, ValueError): - # Look for 1.9 to see if https://github.com/ninja-build/ninja/issues/1219 - # is fixed - NINJA_CMD = detect_ninja('1.9') + # Look for 1.12, which removes -w dupbuild=err + NINJA_CMD = detect_ninja('1.12') if NINJA_CMD is not None: - NINJA_1_9_OR_NEWER = True + NINJA_1_12_OR_NEWER = True else: - mlog.warning('Found ninja <1.9, tests will run slower', once=True) NINJA_CMD = detect_ninja() if NINJA_CMD is not None: - os.environ['NINJA_1_9_OR_NEWER'] = str(int(NINJA_1_9_OR_NEWER)) + os.environ['NINJA_1_12_OR_NEWER'] = str(int(NINJA_1_12_OR_NEWER)) os.environ['NINJA'] = NINJA_CMD[0] else: - raise RuntimeError('Could not find Ninja v1.7 or newer') + raise RuntimeError('Could not find Ninja.') # Emulate running meson with -X utf8 by making sure all open() calls have a # sane encoding. This should be a python default, but PEP 540 considered it not @@ -271,7 +269,9 @@ def get_backend_commands(backend: Backend, debug: bool = False) -> \ test_cmd = cmd + ['-target', 'RUN_TESTS'] elif backend is Backend.ninja: global NINJA_CMD - cmd = NINJA_CMD + ['-w', 'dupbuild=err', '-d', 'explain'] + cmd = NINJA_CMD + ['-d', 'explain'] + if not NINJA_1_12_OR_NEWER: + cmd += ['-w', 'dupbuild=err'] if debug: cmd += ['-v'] clean_cmd = cmd + ['clean'] @@ -282,21 +282,6 @@ def get_backend_commands(backend: Backend, debug: bool = False) -> \ raise AssertionError(f'Unknown backend: {backend!r}') return cmd, clean_cmd, test_cmd, install_cmd, uninstall_cmd -def ensure_backend_detects_changes(backend: Backend) -> None: - global NINJA_1_9_OR_NEWER - if backend is not Backend.ninja: - return - need_workaround = False - # We're using ninja >= 1.9 which has QuLogic's patch for sub-1s resolution - # timestamps - if not NINJA_1_9_OR_NEWER: - mlog.warning('Don\'t have ninja >= 1.9, enabling timestamp resolution workaround', once=True) - need_workaround = True - # Increase the difference between build.ninja's timestamp and the timestamp - # of whatever you changed: https://github.com/ninja-build/ninja/issues/371 - if need_workaround: - time.sleep(1) - def run_mtest_inprocess(commandlist: T.List[str]) -> T.Tuple[int, str, str]: out = StringIO() with mock.patch.object(sys, 'stdout', out), mock.patch.object(sys, 'stderr', out): diff --git a/unittests/baseplatformtests.py b/unittests/baseplatformtests.py index 7c8543d0629d..e94a2baac210 100644 --- a/unittests/baseplatformtests.py +++ b/unittests/baseplatformtests.py @@ -31,7 +31,7 @@ from run_tests import ( - Backend, ensure_backend_detects_changes, get_backend_commands, + Backend, get_backend_commands, get_builddir_target_args, get_meson_script, run_configure_inprocess, run_mtest_inprocess, handle_meson_skip_test, ) @@ -294,8 +294,6 @@ def setconf(self, arg: T.Sequence[str], will_build: bool = True) -> None: arg = [arg] else: arg = list(arg) - if will_build: - ensure_backend_detects_changes(self.backend) self._run(self.mconf_command + arg + [self.builddir]) def getconf(self, optname: str): @@ -309,7 +307,6 @@ def wipe(self): windows_proof_rmtree(self.builddir) def utime(self, f): - ensure_backend_detects_changes(self.backend) os.utime(f) def get_compdb(self): From 886836a69bab1e0af8942d3f86171c462a802ff4 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Sat, 16 Mar 2024 19:28:53 -0400 Subject: [PATCH 788/855] Don't sanitize a None path when checking for, but could not find, unsupported cl clones. --- mesonbuild/compilers/detect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index aed03391889d..dade20402e32 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -287,8 +287,8 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin # practice, Meson will block waiting for Watcom's cl.exe to # exit, which requires user input and thus will never exit. if 'WATCOM' in os.environ: - def sanitize(p: str) -> str: - return os.path.normcase(os.path.abspath(p)) + def sanitize(p: T.Optional[str]) -> T.Optional[str]: + return os.path.normcase(os.path.abspath(p)) if p else None watcom_cls = [sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl')), sanitize(os.path.join(os.environ['WATCOM'], 'BINNT', 'cl.exe')), From 2d3954efac61d37bdcf5c27204163e60d2932290 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 24 Jan 2024 11:36:33 -0600 Subject: [PATCH 789/855] Add bztar support to meson dist Some projects, like Postgres, distribute code in this format. --- data/shell-completions/zsh/_meson | 2 +- docs/markdown/snippets/bztar_support.md | 4 ++++ mesonbuild/mdist.py | 13 ++++++++++--- unittests/allplatformstests.py | 14 +++++++++++++- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/bztar_support.md diff --git a/data/shell-completions/zsh/_meson b/data/shell-completions/zsh/_meson index bd71a31dab21..e6f50f1af923 100644 --- a/data/shell-completions/zsh/_meson +++ b/data/shell-completions/zsh/_meson @@ -32,7 +32,7 @@ local -i ret local __meson_backends="(ninja xcode ${(j. .)${:-vs{,2010,2015,2017}}})" local __meson_build_types="(plain debug debugoptimized minsize release)" local __meson_wrap_modes="(WrapMode.{default,nofallback,nodownload,forcefallback})" -local __meson_dist_formats=("xztar" "gztar" "zip") +local __meson_dist_formats=("xztar" "bztar" "gztar" "zip") local __meson_cd='-C[change into this directory before running]:target dir:_directories' local -a __meson_common=( '--prefix=[installation prefix]: :_directories' diff --git a/docs/markdown/snippets/bztar_support.md b/docs/markdown/snippets/bztar_support.md new file mode 100644 index 000000000000..3ee4a91add30 --- /dev/null +++ b/docs/markdown/snippets/bztar_support.md @@ -0,0 +1,4 @@ +## 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/mesonbuild/mdist.py b/mesonbuild/mdist.py index faaf1bfddff7..1ae0f5916343 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -33,9 +33,10 @@ from ._typing import ImmutableListProtocol from .mesonlib import ExecutableSerialisation -archive_choices = ['gztar', 'xztar', 'zip'] +archive_choices = ['bztar', 'gztar', 'xztar', 'zip'] -archive_extension = {'gztar': '.tar.gz', +archive_extension = {'bztar': '.tar.bz2', + 'gztar': '.tar.gz', 'xztar': '.tar.xz', 'zip': '.zip'} @@ -47,7 +48,7 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('--allow-dirty', action='store_true', help='Allow even when repository contains uncommitted changes.') parser.add_argument('--formats', default='xztar', - help='Comma separated list of archive types to create. Supports xztar (default), gztar, and zip.') + help='Comma separated list of archive types to create. Supports xztar (default), bztar, gztar, and zip.') parser.add_argument('--include-subprojects', action='store_true', help='Include source code of subprojects that have been used for the build.') parser.add_argument('--no-tests', action='store_true', @@ -230,6 +231,7 @@ def create_dist(self, archives: T.List[str]) -> T.List[str]: os.makedirs(self.dist_sub, exist_ok=True) tarname = os.path.join(self.dist_sub, self.dist_name + '.tar') xzname = tarname + '.xz' + bz2name = tarname + '.bz2' gzname = tarname + '.gz' zipname = os.path.join(self.dist_sub, self.dist_name + '.zip') # Note that -X interprets relative paths using the current working @@ -248,6 +250,11 @@ def create_dist(self, archives: T.List[str]) -> T.List[str]: with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf: shutil.copyfileobj(tf, xf) output_names.append(xzname) + if 'bztar' in archives: + import bz2 + with bz2.open(bz2name, 'wb') as bf, open(tarname, 'rb') as tf: + shutil.copyfileobj(tf, bf) + output_names.append(bz2name) if 'gztar' in archives: with gzip.open(gzname, 'wb') as zf, open(tarname, 'rb') as tf: shutil.copyfileobj(tf, zf) diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index c334d9e5461e..86ffa92f95e1 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1505,6 +1505,8 @@ def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): ''')) xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') xz_checksumfile = xz_distfile + '.sha256sum' + bz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.bz2') + bz_checksumfile = bz_distfile + '.sha256sum' gz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.gz') gz_checksumfile = gz_distfile + '.sha256sum' zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') @@ -1520,10 +1522,16 @@ def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): self.build('dist') self.assertPathExists(xz_distfile) self.assertPathExists(xz_checksumfile) + self.assertPathDoesNotExist(bz_distfile) + self.assertPathDoesNotExist(bz_checksumfile) self.assertPathDoesNotExist(gz_distfile) self.assertPathDoesNotExist(gz_checksumfile) self.assertPathDoesNotExist(zip_distfile) self.assertPathDoesNotExist(zip_checksumfile) + self._run(self.meson_command + ['dist', '--formats', 'bztar'], + workdir=self.builddir) + self.assertPathExists(bz_distfile) + self.assertPathExists(bz_checksumfile) self._run(self.meson_command + ['dist', '--formats', 'gztar'], workdir=self.builddir) self.assertPathExists(gz_distfile) @@ -1534,14 +1542,18 @@ def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): self.assertPathExists(zip_checksumfile) os.remove(xz_distfile) os.remove(xz_checksumfile) + os.remove(bz_distfile) + os.remove(bz_checksumfile) os.remove(gz_distfile) os.remove(gz_checksumfile) os.remove(zip_distfile) os.remove(zip_checksumfile) - self._run(self.meson_command + ['dist', '--formats', 'xztar,gztar,zip'], + self._run(self.meson_command + ['dist', '--formats', 'xztar,bztar,gztar,zip'], workdir=self.builddir) self.assertPathExists(xz_distfile) self.assertPathExists(xz_checksumfile) + self.assertPathExists(bz_distfile) + self.assertPathExists(bz_checksumfile) self.assertPathExists(gz_distfile) self.assertPathExists(gz_checksumfile) self.assertPathExists(zip_distfile) From 39f6d117926c78d3505525e6798d71a6e9bf7d74 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 18 Mar 2024 23:13:45 -0400 Subject: [PATCH 790/855] micro-optimize iteration of evaluated set It is generally accepted practice to convert dict.keys() to a list before iterating over it and e.g. deleting values, as keys returns a live-action view. In this case, we use the difference of *two* dict keys, which returns a regular non-view set and doesn't need protecting. Iteration order doesn't matter (the set already randomizes it anyway). Avoid the cost of converting to a list. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index eeeb8d1fedc1..f6eb659896e9 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -923,7 +923,7 @@ def update_project_options(self, options: 'MutableKeyedOptionDictType', subproje fatal=False) # Find any extranious keys for this project and remove them - for key in list(self.options.keys() - options.keys()): + for key in self.options.keys() - options.keys(): if key.is_project() and key.subproject == subproject: del self.options[key] From c99fc40bb7bacfed4ea79b4b83bec46fdc5018f3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 24 Mar 2024 00:01:38 -0400 Subject: [PATCH 791/855] compilers: fix crash when compiler check returns None output Popen_safe_logged has a small inefficiency. It evaluates the stripped version of stdout/stderr before checking if it exists, for logging purposes. This would sometimes crash, if it was None instead of ''. Fixes #12979 --- mesonbuild/utils/universal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index edb309f0d000..324fb94b073b 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1587,7 +1587,7 @@ def Popen_safe_logged(args: T.List[str], msg: str = 'Called', **kwargs: T.Any) - mlog.debug(f'{msg}: `{join_args(args)}` -> {excp}') raise - rc, out, err = p.returncode, o.strip(), e.strip() + rc, out, err = p.returncode, o.strip() if o else None, e.strip() if e else None mlog.debug('-----------') mlog.debug(f'{msg}: `{join_args(args)}` -> {rc}') if out: From f9eef40982ba2715aa4ca1d925aca423646c48f3 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 26 Mar 2024 21:26:31 -0400 Subject: [PATCH 792/855] allow any alternative python freeze tool to work with meson Any code that needs to know mesonlib.python_command currently assumes the PyInstaller bundle reference is added to the sys module, which means that it assumes the only freeze tool used is PyInstaller. Really, all we need to check is sys.frozen as it's never normally set, but always set for a freeze. We don't care if it was PyInstaller specifically, and we don't need its bundle directory. See https://github.com/mesonbuild/meson/discussions/13007 --- mesonbuild/utils/universal.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index 324fb94b073b..ce9afd96be27 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -168,8 +168,11 @@ class _VerPickleLoadable(Protocol): from glob import glob -if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): - # using a PyInstaller bundle, e.g. the MSI installed executable +if getattr(sys, 'frozen', False): + # Using e.g. a PyInstaller bundle, such as the MSI installed executable. + # It is conventional for freeze programs to set this attribute to indicate + # that the program is self hosted, and for example there is no associated + # "python" executable. python_command = [sys.executable, 'runpython'] else: python_command = [sys.executable] From 1baabbc7f6729d2a94feb277054184233eae87d7 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 28 Mar 2024 23:48:20 -0400 Subject: [PATCH 793/855] tests: fix missing dependency causing flaky build failure We have two copies of other.h, one of which is generated. If we don't include the include/ directory then building fails unless the custom_target which copies it over, happens to run early enough. On parallel builds this may fall on its face. --- test cases/rust/12 bindgen/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index f31040ec7808..09cb02a6d319 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -105,9 +105,9 @@ if prog_bindgen.version().version_compare('>= 0.65') input : 'src/header3.h', output : 'header3.rs', output_inline_wrapper : 'header3.c', - include_directories : 'include', + include_directories : inc, ) - c_inline_wrapper = static_library('c_wrapper', gen3[1]) + c_inline_wrapper = static_library('c_wrapper', gen3[1], include_directories: inc) f = configure_file( input : 'src/main3.rs', From 46b3c1c30df60f00c3505c802039407ebfb6f381 Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Tue, 16 Apr 2024 09:38:09 -0500 Subject: [PATCH 794/855] python: Fix header check for system method Fixes https://github.com/mesonbuild/meson/issues/12862 --- mesonbuild/dependencies/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index b9b17f854cde..a0a22c1a54ad 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -221,7 +221,7 @@ def __init__(self, name: str, environment: 'Environment', if mesonlib.is_windows() and self.get_windows_python_arch().endswith('64') and mesonlib.version_compare(self.version, '<3.12'): self.compile_args += ['-DMS_WIN64='] - if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args): + if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args)[0]: self.is_found = False def find_libpy(self, environment: 'Environment') -> None: From 9e3b3db7054c7dedecd14db3e6061ff7e2227faf Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 18 Apr 2024 11:40:50 -0700 Subject: [PATCH 795/855] backend/ninja: Fix cases where None is passed when unexpected When getting debug file arguments we can sometimes pass None, where a None is unexpected. This becomes a particular problem in the Cuda compiler, where the output will unconditionally be concatenated with a static string, resulting in an uncaught exception. This is really easy to spot once we annotate the functions in question, where a static type checker like mypy easily spots the issue. This commit adds those annotations, and then fixes the resulting error. Fixes: #12997 --- mesonbuild/backend/ninjabackend.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index acd401e2f754..bb03f0199087 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2017 The Meson development team -# Copyright © 2023 Intel Corporation +# Copyright © 2023-2024 Intel Corporation from __future__ import annotations @@ -2767,11 +2767,17 @@ def get_compile_debugfile_args(self, compiler, target, objfile): else: return compiler.get_compile_debugfile_args(objfile, pch=False) - def get_link_debugfile_name(self, linker, target) -> T.Optional[str]: - return linker.get_link_debugfile_name(self.get_target_debug_filename(target)) + def get_link_debugfile_name(self, linker: T.Union[Compiler, StaticLinker], target: build.BuildTarget) -> T.Optional[str]: + filename = self.get_target_debug_filename(target) + if filename: + return linker.get_link_debugfile_name(filename) + return None - def get_link_debugfile_args(self, linker, target): - return linker.get_link_debugfile_args(self.get_target_debug_filename(target)) + def get_link_debugfile_args(self, linker: T.Union[Compiler, StaticLinker], target: build.BuildTarget) -> T.List[str]: + filename = self.get_target_debug_filename(target) + if filename: + return linker.get_link_debugfile_args(filename) + return [] def generate_llvm_ir_compile(self, target, src: mesonlib.FileOrString): base_proxy = target.get_options() From 0cec1c03d8f0d294027a954c5f350ab2911c5b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Sun, 21 Apr 2024 20:49:33 +0200 Subject: [PATCH 796/855] coredata: Fix is_per_machine_option() for builtins The keys in BUILTIN_OPTIONS_PER_MACHINE are OptionKey values, not strings. This fixes a regression introduced in 71db6b0. --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index f6eb659896e9..3cf873fee740 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -886,7 +886,7 @@ def _set_others_from_buildtype(self, value: str) -> bool: @staticmethod def is_per_machine_option(optname: OptionKey) -> bool: - if optname.name in BUILTIN_OPTIONS_PER_MACHINE: + if optname.as_host() in BUILTIN_OPTIONS_PER_MACHINE: return True return optname.lang is not None From 286898219ba8d511b56bc11fe8938e6529cf931b Mon Sep 17 00:00:00 2001 From: Momtchil Momtchev Date: Fri, 15 Mar 2024 14:22:17 +0100 Subject: [PATCH 797/855] add an error message for targets that are not dependencies --- mesonbuild/modules/cmake.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index cd5c5f66af9e..b9161021d917 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -136,6 +136,8 @@ def dependency(self, state: ModuleState, args: T.List[str], kwargs: T.Dict[str, info = self._args_to_info(args) if info['func'] == 'executable': raise InvalidArguments(f'{args[0]} is an executable and does not support the dependency() method. Use target() instead.') + if info['dep'] is None: + raise InvalidArguments(f'{args[0]} does not support the dependency() method. Use target() instead.') orig = self.get_variable(state, [info['dep']], {}) assert isinstance(orig, dependencies.Dependency) actual = orig.include_type From 0ed78cf6fa6d87c0738f67ae43525e661b50a8a2 Mon Sep 17 00:00:00 2001 From: "Wu, Zhenyu" Date: Sat, 20 Apr 2024 16:25:27 +0800 Subject: [PATCH 798/855] docs: fix a typo of path Refer https://github.com/mesonbuild/meson/blob/master/docs/markdown/Machine-files.md?plain=1#L285 --- docs/markdown/Machine-files.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index a3e876d23f2d..42f288f17951 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -273,7 +273,7 @@ list of strings. [cmake] CMAKE_C_COMPILER = '/usr/bin/gcc' -CMAKE_CXX_COMPILER = 'C:\\user\\bin\\g++' +CMAKE_CXX_COMPILER = 'C:\\usr\\bin\\g++' CMAKE_SOME_VARIABLE = ['some', 'value with spaces'] ``` From be62df7fc72b02f7a7c5a4c513299458b45374f5 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 8 Apr 2024 10:38:11 -0400 Subject: [PATCH 799/855] Add a few more notes to the style guide - Mention 2 space indent seems to be the most idiomatic - Mention trailing commas are good - Update example to use trailing commas --- docs/markdown/Style-guide.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/markdown/Style-guide.md b/docs/markdown/Style-guide.md index f204a9a7055e..da827c9baff0 100644 --- a/docs/markdown/Style-guide.md +++ b/docs/markdown/Style-guide.md @@ -9,7 +9,11 @@ Meson build files. ## Tabs or spaces? -Always spaces. +Always spaces. Two spaces is the most common. + +## Trailing commas? + +Yes, where possible. They help make nicer diffs in version control systems. ## Naming Variable @@ -70,7 +74,7 @@ normal files. This rule also applies recursively for subdirectories. The following example shows correct source list definition: ```meson -sources = files([ +sources = files( 'aaa/a1.c', 'aaa/a2.c', 'bbb/subdir1/b1.c', @@ -82,6 +86,6 @@ sources = files([ 'f1.c', 'f2.c', 'f10.c', - 'f20.c' -]) + 'f20.c', +) ``` From 05e107832da49050f9f9e92ce9486e593c699bba Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Mon, 22 Apr 2024 17:06:33 -0500 Subject: [PATCH 800/855] Pass --quiet to glib-genmarshal No need to spam about reading the input file. Fixes: #13119 --- mesonbuild/modules/gnome.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 4c015074e31c..410bf7411a36 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1996,7 +1996,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') - cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-genmarshal')] + cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-genmarshal'), '--quiet'] if kwargs['prefix']: cmd.extend(['--prefix', kwargs['prefix']]) if kwargs['extra_args']: From ffa235213cf8b45569abdde84cd1c9aa4e63d6a3 Mon Sep 17 00:00:00 2001 From: Ben Corby Date: Mon, 22 Apr 2024 12:10:12 +1000 Subject: [PATCH 801/855] Fix compile.links for vala Fixes issue #12959 compiler.links command for vala crashes --- mesonbuild/compilers/vala.py | 40 +++++++++++++++++++ test cases/vala/29 compiler.links/meson.build | 24 +++++++++++ 2 files changed, 64 insertions(+) create mode 100644 test cases/vala/29 compiler.links/meson.build diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 52097c94e973..839d544150e7 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -7,13 +7,17 @@ import typing as T from .. import mlog +from .. import mesonlib from ..mesonlib import EnvironmentException, version_compare, LibType, OptionKey from .compilers import CompileCheckMode, Compiler +from ..arglist import CompilerArgs if T.TYPE_CHECKING: + from ..coredata import KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment from ..mesonlib import MachineChoice + from ..dependencies import Dependency class ValaCompiler(Compiler): @@ -25,6 +29,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic super().__init__([], exelist, version, for_machine, info, is_cross=is_cross) self.version = version self.base_options = {OptionKey('b_colorout')} + self.force_link = False def needs_static_linker(self) -> bool: return False # Because compiles into C. @@ -41,6 +46,20 @@ def get_output_args(self, outputname: str) -> T.List[str]: def get_compile_only_args(self) -> T.List[str]: return [] # Because compiles into C. + def get_compiler_args_for_mode(self, mode: CompileCheckMode) -> T.List[str]: + args: T.List[str] = [] + if mode is CompileCheckMode.LINK and self.force_link: + return args + args += self.get_always_args() + if mode is CompileCheckMode.COMPILE: + args += self.get_compile_only_args() + elif mode is CompileCheckMode.PREPROCESS: + args += self.get_preprocess_only_args() + return args + + def get_preprocess_only_args(self) -> T.List[str]: + return [] + def get_pic_args(self) -> T.List[str]: return [] @@ -119,3 +138,24 @@ def thread_flags(self, env: 'Environment') -> T.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]: return [] + + def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: + return [] + + def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, + compiler: T.Optional['Compiler'] = None, + extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, + dependencies: T.Optional[T.List['Dependency']] = None, + disable_cache: bool = False) -> T.Tuple[bool, bool]: + self.force_link = True + if compiler: + with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: + objfile = mesonlib.File.from_absolute_file(r.output_name) + result = self.compiles(objfile, env, extra_args=extra_args, + dependencies=dependencies, mode=CompileCheckMode.LINK, disable_cache=True) + self.force_link = False + return result + result = self.compiles(code, env, extra_args=extra_args, + dependencies=dependencies, mode=CompileCheckMode.LINK, disable_cache=disable_cache) + self.force_link = False + return result diff --git a/test cases/vala/29 compiler.links/meson.build b/test cases/vala/29 compiler.links/meson.build new file mode 100644 index 000000000000..f21d5955a6dd --- /dev/null +++ b/test cases/vala/29 compiler.links/meson.build @@ -0,0 +1,24 @@ +project('link-test', ['c', 'vala'], version: '0.1') + +valac = meson.get_compiler('vala') + +code = '''void main() { + const double PI3 = 1.047197551196597746154214461093167628; + var a = GLib.Math.cos (PI3); + stdout.printf ("%f\n", a); }''' + +# test 1; code should link +code_links = valac.links( + code, + args: '--Xcc=-lm', + name: 'links with math library? == YES', +) +assert (code_links, 'Math library should link successfully.') + +# test 2; code should not link +code_links = valac.links( + code, + args: '--Xcc=-lfake_library_90DFE450330A', + name: 'links with fake library? == NO', +) +assert (not code_links, 'Fake library should not link successfully.') From 4f94284013d257bf361b18da6c6d8c80e64cf24f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 8 Apr 2024 10:21:22 -0700 Subject: [PATCH 802/855] interpreter: implement the `name()` method for `ExternalLibraryHolder` This allows `cc.find_library().name()` to work, just like `dependency().name()`. Fixes: #13053 --- docs/markdown/snippets/find_library_name.md | 3 +++ docs/yaml/objects/dep.yaml | 3 +++ mesonbuild/interpreter/interpreterobjects.py | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 docs/markdown/snippets/find_library_name.md diff --git a/docs/markdown/snippets/find_library_name.md b/docs/markdown/snippets/find_library_name.md new file mode 100644 index 000000000000..ffb18eb85a57 --- /dev/null +++ b/docs/markdown/snippets/find_library_name.md @@ -0,0 +1,3 @@ +## dependencies created by compiler.find_library implement the `name()` method + +Which would previously result in Meson crashing. diff --git a/docs/yaml/objects/dep.yaml b/docs/yaml/objects/dep.yaml index 52e28faca2d2..76543d2c1ab9 100644 --- a/docs/yaml/objects/dep.yaml +++ b/docs/yaml/objects/dep.yaml @@ -15,6 +15,9 @@ methods: Returns `'internal'` for dependencies created with [[declare_dependency]]. + NOTE: This was not implemented for dep objects returned by + [[compiler.find_library]] until Meson 1.5.0 + - name: get_pkgconfig_variable since: 0.36.0 deprecated: 0.56.0 diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index edf785c0d855..0360e4450fb8 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -644,6 +644,7 @@ def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'): self.methods.update({'found': self.found_method, 'type_name': self.type_name_method, 'partial_dependency': self.partial_dependency_method, + 'name': self.name_method, }) @noPosargs @@ -663,6 +664,13 @@ def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.Dep pdep = self.held_object.get_partial_dependency(**kwargs) return pdep + @FeatureNew('name', '1.5.0') + @noPosargs + @noKwargs + def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: + return self.held_object.name + + # A machine that's statically known from the cross file class MachineHolder(ObjectHolder['MachineInfo']): def __init__(self, machine_info: 'MachineInfo', interpreter: 'Interpreter'): From 344a97e08a695af40ec77e439582ffdc06154f21 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 19 Apr 2024 16:01:48 +0200 Subject: [PATCH 803/855] Add meson test --interactive This is very similar to --gdb, except it doesn't spawn GDB, but connects stdin/stdout/stderr directly to the test itself. This allows interacting with integration tests that spawn a shell in a container or virtual machine when the test fails. In systemd we're migrating our integration tests to run using the meson test runner. We want to allow interactive debugging of failed tests directly in the virtual machine or container that is spawned to run the test. To make this possible, we need meson test to connect stdin/stdout/stderr of the test directly to the user's terminal, just like is done with the --gdb option. --- data/shell-completions/bash/meson | 1 + data/shell-completions/zsh/_meson | 1 + docs/markdown/Unit-tests.md | 10 +++++++ docs/markdown/snippets/test_interactive.md | 6 ++++ mesonbuild/mtest.py | 32 +++++++++++++--------- 5 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 docs/markdown/snippets/test_interactive.md diff --git a/data/shell-completions/bash/meson b/data/shell-completions/bash/meson index 55c9c008d98c..dc437f10fd66 100644 --- a/data/shell-completions/bash/meson +++ b/data/shell-completions/bash/meson @@ -566,6 +566,7 @@ _meson-test() { no-rebuild gdb gdb-path + interactive list wrapper suite diff --git a/data/shell-completions/zsh/_meson b/data/shell-completions/zsh/_meson index e6f50f1af923..402539f1ba3a 100644 --- a/data/shell-completions/zsh/_meson +++ b/data/shell-completions/zsh/_meson @@ -181,6 +181,7 @@ local -a meson_commands=( '--no-rebuild[do not rebuild before running tests]' '--gdb[run tests under gdb]' '--gdb-path=[program to run for gdb (can be wrapper or compatible program)]:program:_path_commands' + '(--interactive -i)'{'--interactive','-i'}'[run tests with interactive input/output]' '--list[list available tests]' '(--wrapper --wrap)'{'--wrapper=','--wrap='}'[wrapper to run tests with]:wrapper program:_path_commands' "$__meson_cd" diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index dc509a8189b3..73e58dc68ab6 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -256,6 +256,16 @@ $ meson test --gdb --gdb-path /path/to/gdb testname $ meson test --print-errorlogs ``` +Running tests interactively can be done with the `--interactive` option. +`meson test --interactive` invokes tests with stdout, stdin and stderr +connected directly to the calling terminal. This can be useful if your test is +an integration test running in a container or virtual machine where a debug +shell is spawned if it fails *(added 1.5.0)*: + +```console +$ meson test --interactive testname +``` + Meson will report the output produced by the failing tests along with other useful information as the environmental variables. This is useful, for example, when you run the tests on Travis-CI, Jenkins and diff --git a/docs/markdown/snippets/test_interactive.md b/docs/markdown/snippets/test_interactive.md new file mode 100644 index 000000000000..907147fd9ca9 --- /dev/null +++ b/docs/markdown/snippets/test_interactive.md @@ -0,0 +1,6 @@ +## 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/mesonbuild/mtest.py b/mesonbuild/mtest.py index b9f72fac7dab..311274f37191 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -127,6 +127,8 @@ def add_arguments(parser: argparse.ArgumentParser) -> None: help='Run test under gdb.') parser.add_argument('--gdb-path', default='gdb', dest='gdb_path', help='Path to the gdb binary (default: gdb).') + parser.add_argument('-i', '--interactive', default=False, dest='interactive', + action='store_true', help='Run tests with interactive input/output.') parser.add_argument('--list', default=False, dest='list', action='store_true', help='List available tests.') parser.add_argument('--wrapper', default=None, dest='wrapper', type=split_args, @@ -233,8 +235,8 @@ class ConsoleUser(enum.Enum): # the logger can use the console LOGGER = 0 - # the console is used by gdb - GDB = 1 + # the console is used by gdb or the user + INTERACTIVE = 1 # the console is used to write stdout/stderr STDOUT = 2 @@ -1417,7 +1419,7 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, if ('MSAN_OPTIONS' not in env or not env['MSAN_OPTIONS']): env['MSAN_OPTIONS'] = 'halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' - if self.options.gdb or self.test.timeout is None or self.test.timeout <= 0: + if self.options.interactive or self.test.timeout is None or self.test.timeout <= 0: timeout = None elif self.options.timeout_multiplier is None: timeout = self.test.timeout @@ -1426,12 +1428,12 @@ def __init__(self, test: TestSerialisation, env: T.Dict[str, str], name: str, else: timeout = self.test.timeout * self.options.timeout_multiplier - is_parallel = test.is_parallel and self.options.num_processes > 1 and not self.options.gdb + is_parallel = test.is_parallel and self.options.num_processes > 1 and not self.options.interactive verbose = (test.verbose or self.options.verbose) and not self.options.quiet self.runobj = TestRun(test, env, name, timeout, is_parallel, verbose) - if self.options.gdb: - self.console_mode = ConsoleUser.GDB + if self.options.interactive: + self.console_mode = ConsoleUser.INTERACTIVE elif self.runobj.direct_stdout: self.console_mode = ConsoleUser.STDOUT else: @@ -1499,13 +1501,13 @@ async def _run_subprocess(self, args: T.List[str], *, stdout: T.Optional[int], stderr: T.Optional[int], env: T.Dict[str, str], cwd: T.Optional[str]) -> TestSubprocess: # Let gdb handle ^C instead of us - if self.options.gdb: + if self.options.interactive: previous_sigint_handler = signal.getsignal(signal.SIGINT) # Make the meson executable ignore SIGINT while gdb is running. signal.signal(signal.SIGINT, signal.SIG_IGN) def preexec_fn() -> None: - if self.options.gdb: + if self.options.interactive: # Restore the SIGINT handler for the child process to # ensure it can handle it. signal.signal(signal.SIGINT, signal.SIG_DFL) @@ -1516,7 +1518,7 @@ def preexec_fn() -> None: os.setsid() def postwait_fn() -> None: - if self.options.gdb: + if self.options.interactive: # Let us accept ^C again signal.signal(signal.SIGINT, previous_sigint_handler) @@ -1530,7 +1532,7 @@ def postwait_fn() -> None: postwait_fn=postwait_fn if not is_windows() else None) async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: - if self.console_mode is ConsoleUser.GDB: + if self.console_mode is ConsoleUser.INTERACTIVE: stdout = None stderr = None else: @@ -1591,7 +1593,7 @@ def __init__(self, options: argparse.Namespace): self.ninja: T.List[str] = None self.logfile_base: T.Optional[str] = None - if self.options.logbase and not self.options.gdb: + if self.options.logbase and not self.options.interactive: namebase = None self.logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase) @@ -1691,6 +1693,7 @@ def merge_setup_options(self, options: argparse.Namespace, test: TestSerialisati if not options.gdb: options.gdb = current.gdb if options.gdb: + options.interactive = True options.verbose = True if options.timeout_multiplier is None: options.timeout_multiplier = current.timeout_multiplier @@ -2143,7 +2146,7 @@ def convert_path_to_target(path: str) -> str: return True def run(options: argparse.Namespace) -> int: - if options.benchmark: + if options.benchmark or options.interactive: options.num_processes = 1 if options.verbose and options.quiet: @@ -2152,12 +2155,15 @@ def run(options: argparse.Namespace) -> int: check_bin = None if options.gdb: - options.verbose = True + options.interactive = True if options.wrapper: print('Must not specify both a wrapper and gdb at the same time.') return 1 check_bin = 'gdb' + if options.interactive: + options.verbose = True + if options.wrapper: check_bin = options.wrapper[0] From d68306c9c8641bfd200d77cd1afa0d032648c365 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 21 Apr 2024 16:07:53 +0200 Subject: [PATCH 804/855] mtest: Connect /dev/null to stdin when not running in interactive mode This allows tests to check whether stdin is a tty to figure out if they're running in interactive mode or not. It also makes sure that tests that are not running in interactive mode don't inadvertendly try to read from stdin. --- mesonbuild/mtest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index 311274f37191..460a44c49da8 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1497,7 +1497,7 @@ async def run(self, harness: 'TestHarness') -> TestRun: await self._run_cmd(harness, cmd) return self.runobj - async def _run_subprocess(self, args: T.List[str], *, + async def _run_subprocess(self, args: T.List[str], *, stdin: T.Optional[int], stdout: T.Optional[int], stderr: T.Optional[int], env: T.Dict[str, str], cwd: T.Optional[str]) -> TestSubprocess: # Let gdb handle ^C instead of us @@ -1523,6 +1523,7 @@ def postwait_fn() -> None: signal.signal(signal.SIGINT, previous_sigint_handler) p = await asyncio.create_subprocess_exec(*args, + stdin=stdin, stdout=stdout, stderr=stderr, env=env, @@ -1533,9 +1534,11 @@ def postwait_fn() -> None: async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: if self.console_mode is ConsoleUser.INTERACTIVE: + stdin = None stdout = None stderr = None else: + stdin = asyncio.subprocess.DEVNULL stdout = asyncio.subprocess.PIPE stderr = asyncio.subprocess.STDOUT \ if not self.options.split and not self.runobj.needs_parsing \ @@ -1549,6 +1552,7 @@ async def _run_cmd(self, harness: 'TestHarness', cmd: T.List[str]) -> None: extra_cmd.append(f'--gtest_output=xml:{gtestname}.xml') p = await self._run_subprocess(cmd + extra_cmd, + stdin=stdin, stdout=stdout, stderr=stderr, env=self.runobj.env, From 44c279a92063ad01ad26ef47b126fe180bc0947b Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Tue, 23 Apr 2024 17:36:07 -0500 Subject: [PATCH 805/855] Use dl instead of zlib for checking an external dependency Fedora has switched to zlib-ng, which has a version of `1.3.0.zlib-ng`, causing AllPlatformTests.test_summary to fail. dl is much less likely to change format. --- test cases/unit/71 summary/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/unit/71 summary/meson.build b/test cases/unit/71 summary/meson.build index 76fc545f4b88..6f16191e2346 100644 --- a/test cases/unit/71 summary/meson.build +++ b/test cases/unit/71 summary/meson.build @@ -13,7 +13,7 @@ summary({'Some boolean': false, summary({'missing prog': find_program('xyzzy', required: false), 'existing prog': find_program(get_option('python')).full_path(), 'missing dep': dependency('', required: false), - 'external dep': dependency('zlib', required: false), + 'external dep': dependency('dl', required: false), 'internal dep': declare_dependency(), 'disabler': disabler(), }, section: 'Stuff') From 7a6b7ba14776f937149180330d080882627fd7e9 Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 12 Apr 2024 19:04:18 +0200 Subject: [PATCH 806/855] cmake/interpreter: Annotate and style module-level constants --- mesonbuild/cmake/interpreter.py | 48 +++++++++++++++++---------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index eae2c17f247a..4c42dbb095f3 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -54,7 +54,7 @@ # Disable all warnings automatically enabled with --trace and friends # See https://cmake.org/cmake/help/latest/variable/CMAKE_POLICY_WARNING_CMPNNNN.html -disable_policy_warnings = [ +DISABLE_POLICY_WARNINGS: T.Collection[str] = [ 'CMP0025', 'CMP0047', 'CMP0056', @@ -68,14 +68,14 @@ ] # CMake is a bit more averse to debugging, but in spirit the build types match -buildtype_map = { +BUILDTYPE_MAP: T.Mapping[str, str] = { 'debug': 'Debug', 'debugoptimized': 'RelWithDebInfo', # CMake sets NDEBUG 'release': 'Release', 'minsize': 'MinSizeRel', # CMake leaves out debug information immediately } -target_type_map = { +TARGET_TYPE_MAP: T.Mapping[str, str] = { 'STATIC_LIBRARY': 'static_library', 'MODULE_LIBRARY': 'shared_module', 'SHARED_LIBRARY': 'shared_library', @@ -84,9 +84,9 @@ 'INTERFACE_LIBRARY': 'header_only' } -skip_targets = ['UTILITY'] +SKIP_TARGETS: T.Collection[str] = ['UTILITY'] -blacklist_compiler_flags = [ +BLACKLIST_COMPILER_FLAGS: T.Collection[str] = [ '-Wall', '-Wextra', '-Weverything', '-Werror', '-Wpedantic', '-pedantic', '-w', '/W1', '/W2', '/W3', '/W4', '/Wall', '/WX', '/w', '/O1', '/O2', '/Ob', '/Od', '/Og', '/Oi', '/Os', '/Ot', '/Ox', '/Oy', '/Ob0', @@ -94,15 +94,17 @@ '/Z7', '/Zi', '/ZI', ] -blacklist_link_flags = [ +BLACKLIST_LINK_FLAGS: T.Collection[str] = [ '/machine:x64', '/machine:x86', '/machine:arm', '/machine:ebc', '/debug', '/debug:fastlink', '/debug:full', '/debug:none', '/incremental', ] -blacklist_clang_cl_link_flags = ['/GR', '/EHsc', '/MDd', '/Zi', '/RTC1'] +BLACKLIST_CLANG_CL_LINK_FLAGS: T.Collection[str] = [ + '/GR', '/EHsc', '/MDd', '/Zi', '/RTC1', +] -blacklist_link_libs = [ +BLACKLIST_LINK_LIBS: T.Collection[str] = [ 'kernel32.lib', 'user32.lib', 'gdi32.lib', @@ -115,7 +117,7 @@ 'advapi32.lib' ] -transfer_dependencies_from = ['header_only'] +TRANSFER_DEPENDENCIES_FROM: T.Collection[str] = ['header_only'] _cmake_name_regex = re.compile(r'[^_a-zA-Z0-9]') def _sanitize_cmake_name(name: str) -> str: @@ -325,7 +327,7 @@ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, su # corresponding custom target is run.2 self.generated_raw += [Path(j)] temp += [j] - elif j in blacklist_compiler_flags: + elif j in BLACKLIST_COMPILER_FLAGS: pass else: temp += [j] @@ -445,13 +447,13 @@ def rel_path(x: Path, is_header: bool, is_generated: bool) -> T.Optional[Path]: # Remove blacklisted options and libs def check_flag(flag: str) -> bool: - if flag.lower() in blacklist_link_flags or flag in blacklist_compiler_flags + blacklist_clang_cl_link_flags: + if flag.lower() in BLACKLIST_LINK_FLAGS or flag in BLACKLIST_COMPILER_FLAGS or flag in BLACKLIST_CLANG_CL_LINK_FLAGS: return False if flag.startswith('/D'): return False return True - self.link_libraries = [x for x in self.link_libraries if x.lower() not in blacklist_link_libs] + self.link_libraries = [x for x in self.link_libraries if x.lower() not in BLACKLIST_LINK_LIBS] self.link_flags = [x for x in self.link_flags if check_flag(x)] # Handle OSX frameworks @@ -542,13 +544,13 @@ def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]': return res def process_inter_target_dependencies(self) -> None: - # Move the dependencies from all transfer_dependencies_from to the target + # Move the dependencies from all TRANSFER_DEPENDENCIES_FROM to the target to_process = list(self.depends) processed = [] new_deps = [] for i in to_process: processed += [i] - if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from: + if isinstance(i, ConverterTarget) and i.meson_func() in TRANSFER_DEPENDENCIES_FROM: to_process += [x for x in i.depends if x not in processed] else: new_deps += [i] @@ -556,11 +558,11 @@ def process_inter_target_dependencies(self) -> None: def cleanup_dependencies(self) -> None: # Clear the dependencies from targets that where moved from - if self.meson_func() in transfer_dependencies_from: + if self.meson_func() in TRANSFER_DEPENDENCIES_FROM: self.depends = [] def meson_func(self) -> str: - return target_type_map.get(self.type.upper()) + return TARGET_TYPE_MAP.get(self.type.upper()) def log(self) -> None: mlog.log('Target', mlog.bold(self.name), f'({self.cmake_name})') @@ -737,13 +739,13 @@ def ensure_absolute(x: Path) -> Path: self.inputs += [ctgt_ref] def process_inter_target_dependencies(self) -> None: - # Move the dependencies from all transfer_dependencies_from to the target + # Move the dependencies from all TRANSFER_DEPENDENCIES_FROM to the target to_process = list(self.depends) processed = [] new_deps = [] for i in to_process: processed += [i] - if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from: + if isinstance(i, ConverterTarget) and i.meson_func() in TRANSFER_DEPENDENCIES_FROM: to_process += [x for x in i.depends if x not in processed] else: new_deps += [i] @@ -830,10 +832,10 @@ def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: if not any(arg.startswith('-DCMAKE_BUILD_TYPE=') for arg in cmake_args): # Our build type is favored over any CMAKE_BUILD_TYPE environment variable buildtype = T.cast('str', self.env.coredata.get_option(OptionKey('buildtype'))) - if buildtype in buildtype_map: - cmake_args += [f'-DCMAKE_BUILD_TYPE={buildtype_map[buildtype]}'] + if buildtype in BUILDTYPE_MAP: + cmake_args += [f'-DCMAKE_BUILD_TYPE={BUILDTYPE_MAP[buildtype]}'] trace_args = self.trace.trace_args() - cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in disable_policy_warnings] + cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in DISABLE_POLICY_WARNINGS] self.fileapi.setup_request() @@ -847,7 +849,7 @@ def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor: mlog.log(mlog.bold(' - toolchain file: '), toolchain_file.as_posix()) mlog.log(mlog.bold(' - preload file: '), preload_file.as_posix()) mlog.log(mlog.bold(' - trace args: '), ' '.join(trace_args)) - mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(disable_policy_warnings))) + mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(DISABLE_POLICY_WARNINGS))) mlog.log() self.build_dir.mkdir(parents=True, exist_ok=True) os_env = environ.copy() @@ -910,7 +912,7 @@ def analyse(self) -> None: for k_0 in j_0.targets: # Avoid duplicate targets from different configurations and known # dummy CMake internal target types - if k_0.type not in skip_targets and k_0.name not in added_target_names: + if k_0.type not in SKIP_TARGETS and k_0.name not in added_target_names: added_target_names += [k_0.name] self.targets += [ConverterTarget(k_0, self.env, self.for_machine)] From 8e9be88f6967465473d4fdc9c32a046bbfb60daa Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Fri, 12 Apr 2024 19:44:17 +0200 Subject: [PATCH 807/855] docs: Add CMake build type release note snippet --- docs/markdown/snippets/cmake_build_type.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/markdown/snippets/cmake_build_type.md diff --git a/docs/markdown/snippets/cmake_build_type.md b/docs/markdown/snippets/cmake_build_type.md new file mode 100644 index 000000000000..af9e84dc8e85 --- /dev/null +++ b/docs/markdown/snippets/cmake_build_type.md @@ -0,0 +1,15 @@ +## 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. From fb5a0b4b61651e8ec5adb656a2957a792ae5d2d7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 18 Apr 2024 13:55:55 -0700 Subject: [PATCH 808/855] backend/ninja: add typing annotations to NinjaRule --- mesonbuild/backend/ninjabackend.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bb03f0199087..885a97e0063b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -199,7 +199,9 @@ def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg: # shell constructs shouldn't be shell quoted return NinjaCommandArg(c, Quoting.notShell) if c.startswith('$'): - var = re.search(r'\$\{?(\w*)\}?', c).group(1) + varp = re.search(r'\$\{?(\w*)\}?', c) + assert varp is not None, 'for mypy' + var: str = varp.group(1) if var not in raw_names: # ninja variables shouldn't be ninja quoted, and their value # is already shell quoted @@ -227,26 +229,25 @@ def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg: self.depfile += '_UNQUOTED' @staticmethod - def _quoter(x, qf = quote_func): - if isinstance(x, NinjaCommandArg): - if x.quoting == Quoting.none: - return x.s - elif x.quoting == Quoting.notNinja: - return qf(x.s) - elif x.quoting == Quoting.notShell: - return ninja_quote(x.s) - # fallthrough + def _quoter(x: NinjaCommandArg, qf: T.Callable[[str], str] = quote_func) -> str: + if x.quoting == Quoting.none: + return x.s + elif x.quoting == Quoting.notNinja: + return qf(x.s) + elif x.quoting == Quoting.notShell: + return ninja_quote(x.s) return ninja_quote(qf(str(x))) def write(self, outfile: T.TextIO) -> None: rspfile_args = self.args + rspfile_quote_func: T.Callable[[str], str] if self.rspfile_quote_style is RSPFileSyntax.MSVC: rspfile_quote_func = cmd_quote rspfile_args = [NinjaCommandArg('$in_newline', arg.quoting) if arg.s == '$in' else arg for arg in rspfile_args] else: rspfile_quote_func = gcc_rsp_quote - def rule_iter(): + def rule_iter() -> T.Iterable[str]: if self.refcount: yield '' if self.rsprefcount: @@ -272,13 +273,14 @@ def rule_iter(): outfile.write('\n') outfile.write('\n') - def length_estimate(self, infiles, outfiles, elems): + def length_estimate(self, infiles: str, outfiles: str, + elems: T.List[T.Tuple[str, T.List[str]]]) -> int: # determine variables # this order of actions only approximates ninja's scoping rules, as # documented at: https://ninja-build.org/manual.html#ref_scope - ninja_vars = {} + ninja_vars: T.Dict[str, T.Union[T.List[str], T.Optional[str]]] = {} for e in elems: - (name, value) = e + name, value = e ninja_vars[name] = value ninja_vars['deps'] = self.deps ninja_vars['depfile'] = self.depfile From cf0fecfcef77235257546a43811559aa08b6c5de Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 18 Apr 2024 14:20:07 -0700 Subject: [PATCH 809/855] backend/ninja: Fix bug in NinjaRule.length_estimate The code would create a dictionary that was of type `str : list[str] | str | None`. Then would later try to call `len(' '.join(dict[key]))`. This would result in two different bugs: 1. If the value is `None` it would except, since None isn't iterable and cannot be converted to a string 2. If the value was a string, then it would double the length of the actual string and return that, by adding a space between each character --- mesonbuild/backend/ninjabackend.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 885a97e0063b..32a36a9ba6a5 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -278,14 +278,13 @@ def length_estimate(self, infiles: str, outfiles: str, # determine variables # this order of actions only approximates ninja's scoping rules, as # documented at: https://ninja-build.org/manual.html#ref_scope - ninja_vars: T.Dict[str, T.Union[T.List[str], T.Optional[str]]] = {} - for e in elems: - name, value = e - ninja_vars[name] = value - ninja_vars['deps'] = self.deps - ninja_vars['depfile'] = self.depfile - ninja_vars['in'] = infiles - ninja_vars['out'] = outfiles + ninja_vars = dict(elems) + if self.deps is not None: + ninja_vars['deps'] = [self.deps] + if self.depfile is not None: + ninja_vars['depfile'] = [self.depfile] + ninja_vars['in'] = [infiles] + ninja_vars['out'] = [outfiles] # expand variables in command command = ' '.join([self._quoter(x) for x in self.command + self.args]) From f603a266eca1d8138c37946a7f4ae3f3903c7e45 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 18 Apr 2024 14:35:39 -0700 Subject: [PATCH 810/855] backend: fix type annotation of Backend.generate `func(value: dict = None)` is invalid, it must be `func(value: dict | None = None)`, or in our older syntax: `T.Optional[T.Dict] = None` --- mesonbuild/backend/backends.py | 2 +- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/backend/nonebackend.py | 3 ++- mesonbuild/backend/vs2010backend.py | 2 +- mesonbuild/backend/xcodebackend.py | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 0db5c79af705..a45de70ddd63 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -287,7 +287,7 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional['Inte # 'vslite_ctx' is only provided when # we expect this backend setup/generation to make use of previously captured # compile args (as is the case when using '--genvslite'). - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) -> T.Optional[T.Dict]: raise RuntimeError(f'generate is not implemented in {type(self).__name__}') def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], *, warn_multi_output: bool = True) -> str: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 32a36a9ba6a5..228312d550bb 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -581,7 +581,7 @@ def detect_prefix(out): raise MesonException(f'Could not determine vs dep dependency prefix string. output: {stderr} {stdout}') - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> T.Optional[dict]: + def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) -> T.Optional[T.Dict]: if vslite_ctx: # We don't yet have a use case where we'd expect to make use of this, # so no harm in catching and reporting something unexpected. diff --git a/mesonbuild/backend/nonebackend.py b/mesonbuild/backend/nonebackend.py index fa3f553f415f..ab11e8d4034d 100644 --- a/mesonbuild/backend/nonebackend.py +++ b/mesonbuild/backend/nonebackend.py @@ -2,6 +2,7 @@ # Copyright 2022 The Meson development team from __future__ import annotations +import typing as T from .backends import Backend from .. import mlog @@ -12,7 +13,7 @@ class NoneBackend(Backend): name = 'none' - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: + def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) -> None: # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect the none backend to generate with \'capture = True\'') diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 20ad266f0f52..9c23571bd7d8 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -221,7 +221,7 @@ def generate_custom_generator_commands(self, target, parent_node): def generate(self, capture: bool = False, - vslite_ctx: dict = None) -> T.Optional[dict]: + vslite_ctx: T.Optional[T.Dict] = None) -> T.Optional[T.Dict]: # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect any vs backend to generate with \'capture = True\'') diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 467cd1a6dc0b..c801b5aae260 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -255,7 +255,7 @@ def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]: result.append(os.path.join(self.environment.get_build_dir(), self.get_target_dir(l))) return result - def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None: + def generate(self, capture: bool = False, vslite_ctx: T.Optional[T.Dict] = None) -> None: # Check for (currently) unexpected capture arg use cases - if capture: raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'') From 27dc1bcacb24b190a9afd767fa49a1161202fc6b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 23 Apr 2024 09:35:37 -0700 Subject: [PATCH 811/855] backend/ninja: use re.match instead of re.search Since we've already determined that the first character is the start of the expression anyway. --- 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 228312d550bb..2b4a0cf97351 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -199,7 +199,7 @@ def strToCommandArg(c: T.Union[NinjaCommandArg, str]) -> NinjaCommandArg: # shell constructs shouldn't be shell quoted return NinjaCommandArg(c, Quoting.notShell) if c.startswith('$'): - varp = re.search(r'\$\{?(\w*)\}?', c) + varp = re.match(r'\$\{?(\w*)\}?', c) assert varp is not None, 'for mypy' var: str = varp.group(1) if var not in raw_names: From 3a94aef38dd5e0b044836e37c432fc897d38e405 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 24 Apr 2024 09:59:52 -0400 Subject: [PATCH 812/855] rust: Fix warning_level=everything case Fixes: #13100 --- mesonbuild/compilers/rust.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 0dc65bf33235..ce1079190d98 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -43,6 +43,7 @@ class RustCompiler(Compiler): '1': [], '2': [], '3': ['-W', 'warnings'], + 'everything': ['-W', 'warnings'], } # Those are static libraries, but we use dylib= here as workaround to avoid From 869bb7bc423db0bd176eab6d0c8662bfe7be74bf Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 09:42:09 -0700 Subject: [PATCH 813/855] CI/MacOS: switch the Qt4 job to run on an Intel Mac Qt4 doesn't seem to work on Apple Silicon because OpenSSL 1.0 (a requirement for Qt4) doesn't build on it correctly, trying to use X86 assembly. --- .github/workflows/macos.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index cd58f9d455b3..4eb1870ed29a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -126,7 +126,9 @@ jobs: verbose: true Qt4macos: - runs-on: macos-latest + # This job only works on Intel Macs, because OpenSSL 1.0 doesn't build on + # Apple ARM + runs-on: macos-13 env: HOMEBREW_NO_AUTO_UPDATE: 1 steps: From 274445d247afd44afc408af5a8d130ae9a7c270c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 09:15:02 -0700 Subject: [PATCH 814/855] CI/MacOS: Fix paths that have changed from /usr/local to /opt/homebrew homebrew installs to /usr/local on Intel based macs, but has moved to /opt/homebrew for those using Apple Silicon. --- .github/workflows/macos.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 4eb1870ed29a..6cf032d79405 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -40,16 +40,16 @@ jobs: python -m pip install pytest pytest-xdist pytest-subtests fastjsonschema coverage - run: brew install pkg-config ninja llvm qt@5 - env: - CPPFLAGS: "-I/usr/local/include" - LDFLAGS: "-L/usr/local/lib" + CPPFLAGS: "-I/opt/homebrew/include" + LDFLAGS: "-L/opt/homebrew/lib" MESON_CI_JOBNAME: unittests-appleclang MESON_UNIT_TEST_BACKEND: ninja HOMEBREW_NO_AUTO_UPDATE: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | export SDKROOT="$(xcodebuild -version -sdk macosx Path)" - export PATH="$HOME/tools:/usr/local/opt/qt@5/bin:$PATH:$(brew --prefix llvm)/bin" - export PKG_CONFIG_PATH="/usr/local/opt/qt@5/lib/pkgconfig:$PKG_CONFIG_PATH" + export PATH="$HOME/tools:/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/llvm/bin:$PATH" + export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig:$PKG_CONFIG_PATH" ./tools/run_with_cov.py ./run_unittests.py - name: Aggregate coverage reports @@ -93,7 +93,7 @@ jobs: # Delete nonsensical PEP 668 breakage. It is the wrong solution to the problem and isn't designed to be # productive -- only victim blaming -- however it bites particularly badly because this is a container/VM # See commit 5c479d7a13a518c18ccb4dc3b6bdd7bfc2a9bdb5 for a more thorough analysis. - find /usr/local/Cellar/python* -name EXTERNALLY-MANAGED -print0 | xargs -0 rm -vf + 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 @@ -102,16 +102,16 @@ jobs: python3 -m pip install --upgrade pip python3 -m pip install cython coverage - env: - CPPFLAGS: "-I/usr/local/include" - LDFLAGS: "-L/usr/local/lib" + CPPFLAGS: "-I/opt/homebrew/include" + LDFLAGS: "-L/opt/homebrew/lib" MESON_ARGS: --unity=${{ matrix.unity }} CI: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | export SDKROOT="$(xcodebuild -version -sdk macosx Path)" - export PATH="$HOME/tools:/usr/local/opt/qt@5/bin:$PATH:$(brew --prefix llvm)/bin" - export PKG_CONFIG_PATH="/usr/local/opt/qt@5/lib/pkgconfig:$PKG_CONFIG_PATH" - export XML_CATALOG_FILES="/usr/local/etc/xml/catalog" + export PATH="$HOME/tools:/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/llvm/bin:$PATH" + export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig:/opt/homebrew/opt/lapack/lib/pkgconfig:/opt/homebrew/opt/ncurses/lib/pkgconfig:$PKG_CONFIG_PATH" + export XML_CATALOG_FILES="/opt/homebrew/etc/xml/catalog" ./tools/run_with_cov.py ./run_project_tests.py --backend=ninja - name: Aggregate coverage reports From d40e679c4798b4d3ae90e09ee376ddc0df0a0054 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 09:37:45 -0700 Subject: [PATCH 815/855] CI/MacOS: add missing packages There are some additional packages that seem to be needed on Apple based Silicon. --- .github/workflows/macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6cf032d79405..772d4ff96852 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 + - run: brew install pkg-config ninja llvm qt@5 boost ldc hdf5 openmpi lapack scalapack sdl2 boost-python3 gtk-doc zstd ncurses - run: | python3 -m pip install --upgrade setuptools python3 -m pip install --upgrade pip @@ -109,7 +109,7 @@ jobs: # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | export SDKROOT="$(xcodebuild -version -sdk macosx Path)" - export PATH="$HOME/tools:/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/llvm/bin:$PATH" + export PATH="$HOME/tools:/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/ncurses/bin:$PATH" export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig:/opt/homebrew/opt/lapack/lib/pkgconfig:/opt/homebrew/opt/ncurses/lib/pkgconfig:$PKG_CONFIG_PATH" export XML_CATALOG_FILES="/opt/homebrew/etc/xml/catalog" ./tools/run_with_cov.py ./run_project_tests.py --backend=ninja From b732070a642e7cdbf95886ef23a4e5b8d4737042 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 09:58:06 -0700 Subject: [PATCH 816/855] CI/MacOS: move some things out of the run script into the env key --- .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 772d4ff96852..0e68d241e967 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -105,13 +105,13 @@ jobs: CPPFLAGS: "-I/opt/homebrew/include" LDFLAGS: "-L/opt/homebrew/lib" MESON_ARGS: --unity=${{ matrix.unity }} + XML_CATALOG_FILES: "/opt/homebrew/etc/xml/catalog" CI: 1 # These cannot evaluate anything, so we cannot set PATH or SDKROOT here run: | export SDKROOT="$(xcodebuild -version -sdk macosx Path)" export PATH="$HOME/tools:/opt/homebrew/opt/qt@5/bin:/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/ncurses/bin:$PATH" export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig:/opt/homebrew/opt/lapack/lib/pkgconfig:/opt/homebrew/opt/ncurses/lib/pkgconfig:$PKG_CONFIG_PATH" - export XML_CATALOG_FILES="/opt/homebrew/etc/xml/catalog" ./tools/run_with_cov.py ./run_project_tests.py --backend=ninja - name: Aggregate coverage reports From ff95c7d08393a24d60a8b53bb1c2bee76300e822 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 10:13:50 -0700 Subject: [PATCH 817/855] tests: bump C++ requirement of has_header_symbol Boost now requires C++ 14, as of 1.82 --- test cases/common/103 has header symbol/meson.build | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test cases/common/103 has header symbol/meson.build b/test cases/common/103 has header symbol/meson.build index 4f493e8409e3..ecba2c58f828 100644 --- a/test cases/common/103 has header symbol/meson.build +++ b/test cases/common/103 has header symbol/meson.build @@ -1,7 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2024 Intel Corporation + project( 'has header symbol', 'c', 'cpp', - default_options : ['cpp_std=c++11'], + default_options : ['cpp_std=c++14'], ) cc = meson.get_compiler('c') From 80b9b125f47ff2cffa9f603fb86e6e237a039881 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Apr 2024 10:19:22 -0700 Subject: [PATCH 818/855] dependencies/boost: Add new homebrew root On Apple Silicon the default search path is /opt/homebrew instead of /usr/local. --- mesonbuild/dependencies/boost.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 32932853c0c1..cccc0c3bde47 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -665,8 +665,9 @@ def detect_roots(self) -> None: inc_paths = [x.resolve() for x in inc_paths] roots += inc_paths + m = self.env.machines[self.for_machine] # Add system paths - if self.env.machines[self.for_machine].is_windows(): + if m.is_windows(): # Where boost built from source actually installs it c_root = Path('C:/Boost') if c_root.is_dir(): @@ -688,8 +689,12 @@ def detect_roots(self) -> None: tmp: T.List[Path] = [] # Add some default system paths + if m.is_darwin(): + tmp.extend([ + Path('/opt/homebrew/'), # for Apple Silicon MacOS + Path('/usr/local/opt/boost'), # for Intel Silicon MacOS + ]) tmp += [Path('/opt/local')] - tmp += [Path('/usr/local/opt/boost')] tmp += [Path('/usr/local')] tmp += [Path('/usr')] From a2ac3bc453c22c89ed7343f16b2848f81b73cb85 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Apr 2024 16:19:40 -0400 Subject: [PATCH 819/855] find_library: improve the docs and FeatureNew to fully describe the change The docs didn't really explain what the issue was with using it. And it's not actually a "crash" either way. The FeatureNew mentions that "name" is new, but it is standard for these warnings to tell you both the type of object you're operating on and the name of the method that is an issue. This omitted the former, and was very confusing. --- docs/markdown/snippets/find_library_name.md | 4 +++- mesonbuild/interpreter/interpreterobjects.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/markdown/snippets/find_library_name.md b/docs/markdown/snippets/find_library_name.md index ffb18eb85a57..2ee60b106177 100644 --- a/docs/markdown/snippets/find_library_name.md +++ b/docs/markdown/snippets/find_library_name.md @@ -1,3 +1,5 @@ ## dependencies created by compiler.find_library implement the `name()` method -Which would previously result in Meson crashing. +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/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 0360e4450fb8..8cd9a2be6286 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -664,7 +664,7 @@ def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.Dep pdep = self.held_object.get_partial_dependency(**kwargs) return pdep - @FeatureNew('name', '1.5.0') + @FeatureNew('dependency.name', '1.5.0') @noPosargs @noKwargs def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: From cb1068a28807687853934bb78ecc30746ebf8ea9 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 25 Apr 2024 14:37:05 -0500 Subject: [PATCH 820/855] Catch Python exception in the event alignment can't be converted to int The user almost certainly has to be using a compiler wrapper script that doesn't actually work if we land here. Fixes: #12982 --- mesonbuild/compilers/mixins/clike.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index ac2344bf857e..d273015bcae7 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -625,9 +625,17 @@ def alignment(self, typename: str, prefix: str, env: 'Environment', *, raise mesonlib.EnvironmentException('Could not compile alignment test.') if res.returncode != 0: raise mesonlib.EnvironmentException('Could not run alignment test binary.') - align = int(res.stdout) + + align: int + try: + align = int(res.stdout) + except ValueError: + # If we get here, the user is most likely using a script that is + # pretending to be a compiler. + raise mesonlib.EnvironmentException('Could not run alignment test binary.') if align == 0: raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.') + return align, res.cached def get_define(self, dname: str, prefix: str, env: 'Environment', From 16ed01555d7181f82e689a1571e1f36fdc01723b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 17:28:03 -0700 Subject: [PATCH 821/855] docs: fix bad link in snippet --- docs/markdown/snippets/find_library_name.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/snippets/find_library_name.md b/docs/markdown/snippets/find_library_name.md index 2ee60b106177..e7b0e1a5bab2 100644 --- a/docs/markdown/snippets/find_library_name.md +++ b/docs/markdown/snippets/find_library_name.md @@ -1,5 +1,5 @@ ## dependencies created by compiler.find_library implement the `name()` method -Previously, for a [[dep]] that might be returned by either [[dependency]] or +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. From 53f18fe5054967e02715b4d086237e41884d41ac Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Apr 2024 18:10:19 -0400 Subject: [PATCH 822/855] CI: gentoo: fix profile 23.0 migration dropping default fortran We need this for scalapack -> virtual/mpi -> openmpi See https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=a1b86025be85171281811eaced7b342fbdfdb591 We now get an immediate, very nicely readable error that the USE flag is necessary. For our use cases, there's no reason not to globally enable it. --- ci/ciimage/gentoo/install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/ciimage/gentoo/install.sh b/ci/ciimage/gentoo/install.sh index dc6383c1441a..58749bc40037 100755 --- a/ci/ciimage/gentoo/install.sh +++ b/ci/ciimage/gentoo/install.sh @@ -114,6 +114,9 @@ cat <<-EOF >> /etc/portage/make.conf EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --autounmask-write --autounmask-continue --autounmask-keep-keywords=y --autounmask-use=y" EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --binpkg-respect-use=y" + # Fortran is no longer enabled by default in 23.0, but we do need and use it. + USE="\${USE} fortran" + FEATURES="\${FEATURES} parallel-fetch parallel-install -merge-sync" FEATURES="\${FEATURES} getbinpkg binpkg-request-signature" From d22bb528c56c22c1a0c0855ff221f3a9594d1964 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Thu, 25 Apr 2024 18:26:59 -0400 Subject: [PATCH 823/855] CI: ubuntu-rolling: fix configuration for sources after format change ``` # Ubuntu sources have moved to the /etc/apt/sources.list.d/ubuntu.sources # file, which uses the deb822 format. Use deb822-formatted .sources files # to manage package sources in the /etc/apt/sources.list.d/ directory. # See the sources.list(5) manual page for details. ``` Adapt to the new format. --- ci/ciimage/ubuntu-rolling/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ciimage/ubuntu-rolling/install.sh b/ci/ciimage/ubuntu-rolling/install.sh index 35a0b0ea286c..e1747034fe36 100755 --- a/ci/ciimage/ubuntu-rolling/install.sh +++ b/ci/ciimage/ubuntu-rolling/install.sh @@ -29,7 +29,7 @@ pkgs=( openjdk-11-jre ) -sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" +sed -i '/^Types: deb/s/deb/deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources apt-get -y update apt-get -y upgrade apt-get -y install eatmydata From e4d2aac988925d1f7b8eae762ec24f6af63569df Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 25 Apr 2024 12:18:48 -0700 Subject: [PATCH 824/855] tests/d/10: Fix condition with clang++ and gdc Which just checked for clang++ and aborted, instead of for the combination it claimed. --- test cases/d/10 d cpp/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test cases/d/10 d cpp/meson.build b/test cases/d/10 d cpp/meson.build index eecb151f48d5..fd6b63b0fbaa 100644 --- a/test cases/d/10 d cpp/meson.build +++ b/test cases/d/10 d cpp/meson.build @@ -1,8 +1,9 @@ project('d and c++', 'd', 'cpp') cpp = meson.get_compiler('cpp') +dc = meson.get_compiler('d') -if cpp.get_id() == 'clang' +if cpp.get_id() == 'clang' and dc.get_id() == 'gcc' error('MESON_SKIP_TEST combining Clang C++ with GDC produces broken executables.') endif From 6a1732a29d315aeef2d0a81394b2846c97df42c0 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 8 Jun 2023 08:13:40 -0400 Subject: [PATCH 825/855] nasm: Fallback to native compiler when cross compiling If nasm is not defined in cross file binaries we can fallback to build machine nasm. When cross compiling C code we need a different gcc binary for native and cross targets, e.g. `gcc` and `x86_64-w64-mingw32-gcc`. But when cross compiling NASM code the compiler is the same, it is the source code that has to be made for the target platform. We can thus use nasm from build machine's PATH to cross compile for Windows on Linux for example. The difference is the arguments Meson will pass when invoking nasm e.g. `-fwin64`. That is already handled by NasmCompiler class. --- mesonbuild/compilers/detect.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index dade20402e32..08727285a0c5 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -115,7 +115,8 @@ def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoic # Helpers # ======= -def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str]]: +def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice, + allow_build_machine: bool = False) -> T.Tuple[T.List[T.List[str]], T.List[str]]: ''' The list of compilers is detected in the exact same way for C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. @@ -127,7 +128,9 @@ def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice) -> compilers = [comp] else: if not env.machines.matches_build_machine(for_machine): - raise EnvironmentException(f'{lang!r} compiler binary not defined in cross or native file') + if allow_build_machine: + return _get_compilers(env, lang, MachineChoice.BUILD) + raise EnvironmentException(f'{lang!r} compiler binary not defined in cross file [binaries] section') compilers = [[x] for x in defaults[lang]] ccache = BinaryTable.detect_compiler_cache() @@ -1230,9 +1233,12 @@ def detect_swift_compiler(env: 'Environment', for_machine: MachineChoice) -> Com def detect_nasm_compiler(env: 'Environment', for_machine: MachineChoice) -> Compiler: from .asm import NasmCompiler, YasmCompiler, MetrowerksAsmCompilerARM, MetrowerksAsmCompilerEmbeddedPowerPC - compilers, _ = _get_compilers(env, 'nasm', for_machine) is_cross = env.is_cross_build(for_machine) + # When cross compiling and nasm is not defined in the cross file we can + # fallback to the build machine nasm. + compilers, _ = _get_compilers(env, 'nasm', for_machine, allow_build_machine=True) + # We need a C compiler to properly detect the machine info and linker cc = detect_c_compiler(env, for_machine) if not is_cross: From f8d957febfd6be465074c244b871fd940e79bb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dr=2E=20Vedran=20Mileti=C4=87?= Date: Tue, 16 Apr 2024 12:41:44 +0200 Subject: [PATCH 826/855] Added NumPy to users NumPy is built with Meson since version 1.26. --- docs/markdown/Users.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index b0cc949ee9e7..fe353a05977a 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -119,6 +119,7 @@ format files - [Nautilus](https://gitlab.gnome.org/GNOME/nautilus), the GNOME file manager - [Nemo](https://github.com/linuxmint/nemo), the file manager for the Cinnamon desktop environment - [NetPanzer](https://github.com/netpanzer/netpanzer), a 2D online multiplayer tactical warfare game designed for fast action combat + - [NumPy](https://numpy.org/), a Python package for scientific computing - [nvme-cli](https://github.com/linux-nvme/nvme-cli), NVMe management command line interface - [OcherBook](https://github.com/ccoffing/OcherBook), an open source book reader for Kobo devices - [oomd](https://github.com/facebookincubator/oomd), a userspace Out-Of-Memory (OOM) killer for Linux systems From 1684259f10cc129c922e38e4f1325aef876773d6 Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Fri, 12 Apr 2024 05:05:08 +0900 Subject: [PATCH 827/855] backend/ninja: use generate_basic_compiler_args() for C#, Java, Swift C#, Java, and Swift targets were manually collecting compiler arguments rather than using the helper function for this purpose. This caused each target type to add arguments in a different order, and to forget to add some arguments respectively: C#: /nologo, -warnaserror Java: warning level (-nowarn, -Xlint:all, -Xdoclint:all), debug arguments (-g, -g:none), -Werror Swift: -warnings-as-errors Fix this. Also fix up some no-longer-unused argument processing in the Compiler implementations. --- mesonbuild/backend/ninjabackend.py | 18 +++++------------- mesonbuild/compilers/cs.py | 7 +++++++ mesonbuild/compilers/swift.py | 8 +++++++- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2b4a0cf97351..e394c60fcc30 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1480,9 +1480,8 @@ def generate_cs_target(self, target: build.BuildTarget): compiler = target.compilers['cs'] rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list] deps = [] - commands = compiler.compiler_args(target.extra_args['cs']) - commands += compiler.get_optimization_args(target.get_option(OptionKey('optimization'))) - commands += compiler.get_debug_args(target.get_option(OptionKey('debug'))) + commands = self.generate_basic_compiler_args(target, compiler) + commands += target.extra_args['cs'] if isinstance(target, build.Executable): commands.append('-target:exe') elif isinstance(target, build.SharedLibrary): @@ -1510,8 +1509,6 @@ def generate_cs_target(self, target: build.BuildTarget): for dep in target.get_external_deps(): commands.extend_direct(dep.get_link_args()) - commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) - commands += self.build.get_global_args(compiler, target.for_machine) elem = NinjaBuildElement(self.all_outputs, outputs, self.compiler_to_rule_name(compiler), rel_srcs + generated_rel_srcs) elem.add_dep(deps) @@ -1522,9 +1519,7 @@ def generate_cs_target(self, target: build.BuildTarget): self.create_target_source_introspection(target, compiler, commands, rel_srcs, generated_rel_srcs) def determine_single_java_compile_args(self, target, compiler): - args = [] - args += self.build.get_global_args(compiler, target.for_machine) - args += self.build.get_project_args(compiler, target.subproject, target.for_machine) + args = self.generate_basic_compiler_args(target, compiler) args += target.get_java_args() args += compiler.get_output_args(self.get_target_private_dir(target)) args += target.get_classpath_args() @@ -2195,12 +2190,9 @@ def generate_swift_target(self, target): else: raise InvalidArguments(f'Swift target {target.get_basename()} contains a non-swift source file.') os.makedirs(self.get_target_private_dir_abs(target), exist_ok=True) - compile_args = swiftc.get_compile_only_args() - compile_args += swiftc.get_optimization_args(target.get_option(OptionKey('optimization'))) - compile_args += swiftc.get_debug_args(target.get_option(OptionKey('debug'))) + compile_args = self.generate_basic_compiler_args(target, swiftc) + compile_args += swiftc.get_compile_only_args() compile_args += swiftc.get_module_args(module_name) - compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine) - compile_args += self.build.get_global_args(swiftc, target.for_machine) for i in reversed(target.get_include_dirs()): basedir = i.get_curdir() for d in i.get_incdirs(): diff --git a/mesonbuild/compilers/cs.py b/mesonbuild/compilers/cs.py index 3a6365f42611..38bb3386672b 100644 --- a/mesonbuild/compilers/cs.py +++ b/mesonbuild/compilers/cs.py @@ -14,6 +14,7 @@ from .mixins.islinker import BasicLinkerIsCompilerMixin if T.TYPE_CHECKING: + from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment from ..mesonlib import MachineChoice @@ -60,6 +61,12 @@ def get_werror_args(self) -> T.List[str]: def get_pic_args(self) -> T.List[str]: return [] + def get_dependency_compile_args(self, dep: Dependency) -> T.List[str]: + # Historically we ignored all compile args. Accept what we can, but + # filter out -I arguments, which are in some pkg-config files and + # aren't accepted by mcs. + return [a for a in dep.get_compile_args() if not a.startswith('-I')] + def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]: for idx, i in enumerate(parameter_list): diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index e200276e2646..a2525f927f28 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -40,11 +40,17 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic linker=linker) self.version = version + def get_pic_args(self) -> T.List[str]: + return [] + + def get_pie_args(self) -> T.List[str]: + return [] + def needs_static_linker(self) -> bool: return True def get_werror_args(self) -> T.List[str]: - return ['--fatal-warnings'] + return ['-warnings-as-errors'] def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return ['-emit-dependencies'] From 2004b7c24dbc4a3ff3d333df9456e1e1223e9c8b Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Sun, 21 Apr 2024 16:17:26 -0500 Subject: [PATCH 828/855] compilers/fortran: fix werror options for Intel compilers Unlike in the Intel C compiler, -Werror and /WX are not accepted. --- mesonbuild/compilers/fortran.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 2cdff36de441..428251560535 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -300,6 +300,9 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] def get_preprocess_only_args(self) -> T.List[str]: return ['-cpp', '-EP'] + def get_werror_args(self) -> T.List[str]: + return ['-warn', 'errors'] + def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: # TODO: needs default search path added return ['-lifcore', '-limf'] @@ -349,6 +352,9 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] args.append('/stand:' + stds[std.value]) return args + def get_werror_args(self) -> T.List[str]: + return ['/warn:errors'] + def get_module_outdir_args(self, path: str) -> T.List[str]: return ['/module:' + path] From c9aa4aff66ebbbcd3eed3da8fbc3af0e0a8b90a2 Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Sat, 27 Apr 2024 03:06:41 -0500 Subject: [PATCH 829/855] mdist: gracefully handle stale Git index Running `touch` on a tracked file in Git, to update its timestamp, and then running `meson dist` would cause dist to fail: ERROR: Repository has uncommitted changes that will not be included in the dist tarball Use --allow-dirty to ignore the warning and proceed anyway Unlike `git status` and `git diff`, `git diff-index` doesn't refresh the index before comparing, so stat changes are assumed to imply content changes. Run `git update-index -q --refresh` first to refresh the index. Fixes: #12985 --- mesonbuild/mdist.py | 1 + unittests/allplatformstests.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py index 1ae0f5916343..e4606306b6d2 100644 --- a/mesonbuild/mdist.py +++ b/mesonbuild/mdist.py @@ -140,6 +140,7 @@ 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']) ret = subprocess.call(['git', '-C', self.src_root, 'diff-index', '--quiet', 'HEAD']) return ret == 1 diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 86ffa92f95e1..9c9f61678609 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1494,7 +1494,8 @@ def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): subproject('tarballsub', required : false) subproject('samerepo', required : false) ''')) - with open(os.path.join(project_dir, 'distexe.c'), 'w', encoding='utf-8') as ofile: + distexe_c = os.path.join(project_dir, 'distexe.c') + with open(distexe_c, 'w', encoding='utf-8') as ofile: ofile.write(textwrap.dedent('''\ #include @@ -1528,6 +1529,8 @@ def dist_impl(self, vcs_init, vcs_add_all=None, include_subprojects=True): self.assertPathDoesNotExist(gz_checksumfile) self.assertPathDoesNotExist(zip_distfile) self.assertPathDoesNotExist(zip_checksumfile) + # update a source file timestamp; dist should succeed anyway + os.utime(distexe_c) self._run(self.meson_command + ['dist', '--formats', 'bztar'], workdir=self.builddir) self.assertPathExists(bz_distfile) From 205f09e1b022a71a64eb48e22bb52f76e0da21ef Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Thu, 11 Apr 2024 01:44:58 +0200 Subject: [PATCH 830/855] Prefer Clang over GCC for Objective-C(++) GCC only has very limited support for Objective-C and doesn't support any of the modern features, so whenever Clang is available, it should be used instead. Essentially, the only reason to ever use GCC for Objective-C is that Clang simply does not support the target system. --- mesonbuild/compilers/detect.py | 9 ++++----- test cases/cmake/24 mixing languages/meson.build | 5 ++++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 08727285a0c5..6e35e7d39f11 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -46,9 +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'] - # Clang and clang++ are valid, but currently unsupported. - defaults['objc'] = ['cc', 'gcc'] - defaults['objcpp'] = ['c++', 'g++'] + defaults['objc'] = ['clang-cl', 'gcc'] + defaults['objcpp'] = ['clang-cl', 'g++'] defaults['cs'] = ['csc', 'mcs'] else: if platform.machine().lower() == 'e2k': @@ -59,8 +58,8 @@ else: defaults['c'] = ['cc', 'gcc', 'clang', 'nvc', 'pgcc', 'icc', 'icx'] defaults['cpp'] = ['c++', 'g++', 'clang++', 'nvc++', 'pgc++', 'icpc', 'icpx'] - defaults['objc'] = ['cc', 'gcc', 'clang'] - defaults['objcpp'] = ['c++', 'g++', 'clang++'] + defaults['objc'] = ['clang', 'gcc'] + defaults['objcpp'] = ['clang++', 'g++'] defaults['fortran'] = ['gfortran', 'flang', 'nvfortran', 'pgfortran', 'ifort', 'ifx', 'g95'] defaults['cs'] = ['mcs', 'csc'] defaults['d'] = ['ldc2', 'ldc', 'gdc', 'dmd'] diff --git a/test cases/cmake/24 mixing languages/meson.build b/test cases/cmake/24 mixing languages/meson.build index 4ab1d8542007..55d7a7d68bc9 100644 --- a/test cases/cmake/24 mixing languages/meson.build +++ b/test cases/cmake/24 mixing languages/meson.build @@ -1,4 +1,7 @@ -project('CMake mix', ['c', 'cpp']) +# Explicitly require PIE so that mixing compilers with different defaults for +# whether to use PIE works. +project('CMake mix', ['c', 'cpp'], + default_options: ['b_pie=true']) if not add_languages('objc', required : false) error('MESON_SKIP_TEST: No ObjC compiler') From 6c6529337e72812a64ff4a193d1888cc7822de58 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Thu, 11 Apr 2024 01:46:27 +0200 Subject: [PATCH 831/855] Add support for depending on ObjFW This uses objfw-config to get to the flags, however, there's still several todos that can only be addressed once dependencies can have per-language flags. --- docs/markdown/Dependencies.md | 42 +++++++++++++++++--- docs/markdown/snippets/objfw_dep.md | 24 +++++++++++ mesonbuild/dependencies/__init__.py | 1 + mesonbuild/dependencies/misc.py | 26 ++++++++++++ test cases/objc/5 objfw/SimpleTest.m | 10 +++++ test cases/objc/5 objfw/TestApplication.m | 12 ++++++ test cases/objc/5 objfw/meson.build | 14 +++++++ test cases/objcpp/3 objfw/SimpleTest.mm | 10 +++++ test cases/objcpp/3 objfw/TestApplication.mm | 12 ++++++ test cases/objcpp/3 objfw/meson.build | 14 +++++++ 10 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 docs/markdown/snippets/objfw_dep.md create mode 100644 test cases/objc/5 objfw/SimpleTest.m create mode 100644 test cases/objc/5 objfw/TestApplication.m create mode 100644 test cases/objc/5 objfw/meson.build create mode 100644 test cases/objcpp/3 objfw/SimpleTest.mm create mode 100644 test cases/objcpp/3 objfw/TestApplication.mm create mode 100644 test cases/objcpp/3 objfw/meson.build diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 88e6575a7825..d91582523d44 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -266,11 +266,12 @@ DC="dmd" meson setup builddir ## Config tool -[CUPS](#cups), [LLVM](#llvm), [pcap](#pcap), [WxWidgets](#wxwidgets), -[libwmf](#libwmf), [GCrypt](#libgcrypt), [GPGME](#gpgme), and GnuStep either do not provide pkg-config -modules or additionally can be detected via a config tool -(cups-config, llvm-config, libgcrypt-config, etc). Meson has native support for these -tools, and they can be found like other dependencies: +[CUPS](#cups), [LLVM](#llvm), [ObjFW](#objfw), [pcap](#pcap), +[WxWidgets](#wxwidgets), [libwmf](#libwmf), [GCrypt](#libgcrypt), +[GPGME](#gpgme), and GnuStep either do not provide pkg-config modules or +additionally can be detected via a config tool (cups-config, llvm-config, +libgcrypt-config, etc). Meson has native support for these tools, and they can +be found like other dependencies: ```meson pcap_dep = dependency('pcap', version : '>=1.0') @@ -278,6 +279,7 @@ cups_dep = dependency('cups', version : '>=1.4') llvm_dep = dependency('llvm', version : '>=4.0') libgcrypt_dep = dependency('libgcrypt', version: '>= 1.8') gpgme_dep = dependency('gpgme', version: '>= 1.0') +objfw_dep = dependency('objfw', version: '>= 1.0') ``` *Since 0.55.0* Meson won't search $PATH any more for a config tool @@ -637,6 +639,36 @@ language-specific, you must specify the requested language using the Meson uses pkg-config to find NetCDF. +## ObjFW + +*(added 1.5.0)* + +Meson has native support for ObjFW, including support for ObjFW packages. + +In order to use ObjFW, simply create the dependency: + +```meson +objfw_dep = dependency('objfw') +``` + +In order to also use ObjFW packages, simply specify them as modules: + +```meson +objfw_dep = dependency('objfw', modules: ['SomePackage']) +``` + +If you need a dependency with and without packages, e.g. because your tests +want to use ObjFWTest, but you don't want to link your application against the +tests, simply get two dependencies and use them as appropriate: + +```meson +objfw_dep = dependency('objfw', modules: ['SomePackage']) +objfwtest_dep = dependency('objfw', modules: ['ObjFWTest']) +``` + +Then use `objfw_dep` for your library and only `objfwtest_dep` (not both) for +your tests. + ## OpenMP *(added 0.46.0)* diff --git a/docs/markdown/snippets/objfw_dep.md b/docs/markdown/snippets/objfw_dep.md new file mode 100644 index 000000000000..e65da2885b4a --- /dev/null +++ b/docs/markdown/snippets/objfw_dep.md @@ -0,0 +1,24 @@ +## 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/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index abc2e22b2d86..89d2285ba3a6 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -223,6 +223,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. 'openssl': 'misc', 'libcrypto': 'misc', 'libssl': 'misc', + 'objfw': 'misc', # From platform: 'appleframeworks': 'platform', diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index b255813b60b9..fd5965233dc6 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -474,6 +474,30 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): self.link_args.extend(sublib) +class ObjFWDependency(ConfigToolDependency): + + tools = ['objfw-config'] + tool_name = 'objfw-config' + + def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]): + super().__init__('objfw', environment, kwargs) + self.feature_since = ('1.5.0', '') + if not self.is_found: + return + + # TODO: Expose --reexport + # TODO: Expose --framework-libs + extra_flags = [] + + for module in mesonlib.stringlistify(mesonlib.extract_as_list(kwargs, 'modules')): + extra_flags.append('--package') + extra_flags.append(module) + + # TODO: Once Meson supports adding flags per language, only add --objcflags to ObjC + self.compile_args = self.get_config_value(['--cppflags', '--cflags', '--objcflags'] + extra_flags, 'compile_args') + self.link_args = self.get_config_value(['--ldflags', '--libs'] + extra_flags, 'link_args') + + @factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CONFIG_TOOL, DependencyMethods.SYSTEM}) def curses_factory(env: 'Environment', for_machine: 'mesonlib.MachineChoice', @@ -616,3 +640,5 @@ def shaderc_factory(env: 'Environment', system_class=OpensslSystemDependency, cmake_class=CMakeDependencyFactory('OpenSSL', modules=['OpenSSL::SSL']), ) + +packages['objfw'] = ObjFWDependency diff --git a/test cases/objc/5 objfw/SimpleTest.m b/test cases/objc/5 objfw/SimpleTest.m new file mode 100644 index 000000000000..a1604d3bcc44 --- /dev/null +++ b/test cases/objc/5 objfw/SimpleTest.m @@ -0,0 +1,10 @@ +#import +#import + +@interface SimpleTest: OTTestCase +@end + +@implementation SimpleTest +- (void)testMeson { +} +@end diff --git a/test cases/objc/5 objfw/TestApplication.m b/test cases/objc/5 objfw/TestApplication.m new file mode 100644 index 000000000000..ed6fac1e9265 --- /dev/null +++ b/test cases/objc/5 objfw/TestApplication.m @@ -0,0 +1,12 @@ +#import + +@interface TestApplication: OFObject +@end + +OF_APPLICATION_DELEGATE(TestApplication) + +@implementation TestApplication +- (void)applicationDidFinishLaunching: (OFNotification *)notification { + [OFApplication terminate]; +} +@end diff --git a/test cases/objc/5 objfw/meson.build b/test cases/objc/5 objfw/meson.build new file mode 100644 index 000000000000..40ddb7968db4 --- /dev/null +++ b/test cases/objc/5 objfw/meson.build @@ -0,0 +1,14 @@ +project('objfw build tests', 'objc') + +objfw_dep = dependency('objfw', required: false) +objfwtest_dep = dependency('objfw', modules: ['ObjFWTest'], required: false) + +if not objfw_dep.found() or not objfwtest_dep.found() + error('MESON_SKIP_TEST: Need objfw dependency') +endif + +executable('TestApplication', 'TestApplication.m', + dependencies: [objfw_dep]) + +executable('SimpleTest', 'SimpleTest.m', + dependencies: [objfwtest_dep]) diff --git a/test cases/objcpp/3 objfw/SimpleTest.mm b/test cases/objcpp/3 objfw/SimpleTest.mm new file mode 100644 index 000000000000..a1604d3bcc44 --- /dev/null +++ b/test cases/objcpp/3 objfw/SimpleTest.mm @@ -0,0 +1,10 @@ +#import +#import + +@interface SimpleTest: OTTestCase +@end + +@implementation SimpleTest +- (void)testMeson { +} +@end diff --git a/test cases/objcpp/3 objfw/TestApplication.mm b/test cases/objcpp/3 objfw/TestApplication.mm new file mode 100644 index 000000000000..ed6fac1e9265 --- /dev/null +++ b/test cases/objcpp/3 objfw/TestApplication.mm @@ -0,0 +1,12 @@ +#import + +@interface TestApplication: OFObject +@end + +OF_APPLICATION_DELEGATE(TestApplication) + +@implementation TestApplication +- (void)applicationDidFinishLaunching: (OFNotification *)notification { + [OFApplication terminate]; +} +@end diff --git a/test cases/objcpp/3 objfw/meson.build b/test cases/objcpp/3 objfw/meson.build new file mode 100644 index 000000000000..da14681ebf1a --- /dev/null +++ b/test cases/objcpp/3 objfw/meson.build @@ -0,0 +1,14 @@ +project('objfw build tests', 'objcpp') + +objfw_dep = dependency('objfw', required: false) +objfwtest_dep = dependency('objfw', modules: ['ObjFWTest'], required: false) + +if not objfw_dep.found() or not objfwtest_dep.found() + error('MESON_SKIP_TEST: Need objfw dependency') +endif + +executable('TestApplication', 'TestApplication.mm', + dependencies: [objfw_dep]) + +executable('SimpleTest', 'SimpleTest.mm', + dependencies: [objfwtest_dep]) From 538abcf8b130932c05b9bf4c1d9e185183c95f73 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Mon, 22 Apr 2024 23:49:10 +0200 Subject: [PATCH 832/855] Install ObjFW on macOS, Fedora and MSYS2 CI --- .github/workflows/macos.yml | 2 +- .github/workflows/msys2.yml | 1 + ci/ciimage/fedora/install.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0e68d241e967..449504096a77 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 + - run: brew install pkg-config ninja llvm qt@5 boost ldc hdf5 openmpi lapack scalapack sdl2 boost-python3 gtk-doc zstd ncurses objfw - run: | python3 -m pip install --upgrade setuptools python3 -m pip install --upgrade pip diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index fe28a67edbad..278954c393d6 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -85,6 +85,7 @@ jobs: mingw-w64-${{ matrix.MSYS2_ARCH }}-python-setuptools mingw-w64-${{ matrix.MSYS2_ARCH }}-python-pip mingw-w64-${{ matrix.MSYS2_ARCH }}-python-fastjsonschema + mingw-w64-${{ matrix.MSYS2_ARCH }}-objfw mingw-w64-${{ matrix.MSYS2_ARCH }}-${{ matrix.TOOLCHAIN }} - name: Install dependencies diff --git a/ci/ciimage/fedora/install.sh b/ci/ciimage/fedora/install.sh index 2191a707ed9a..65b2012d5000 100755 --- a/ci/ciimage/fedora/install.sh +++ b/ci/ciimage/fedora/install.sh @@ -12,7 +12,7 @@ pkgs=( boost-python3-devel itstool gtk3-devel java-latest-openjdk-devel gtk-doc llvm-devel clang-devel SDL2-devel graphviz-devel zlib zlib-devel zlib-static #hdf5-openmpi-devel hdf5-devel netcdf-openmpi-devel netcdf-devel netcdf-fortran-openmpi-devel netcdf-fortran-devel scalapack-openmpi-devel - doxygen vulkan-devel vulkan-validation-layers-devel openssh mercurial gtk-sharp2-devel libpcap-devel gpgme-devel + doxygen vulkan-devel vulkan-validation-layers-devel openssh objfw mercurial gtk-sharp2-devel libpcap-devel gpgme-devel qt5-qtbase-devel qt5-qttools-devel qt5-linguist qt5-qtbase-private-devel libwmf-devel valgrind cmake openmpi-devel nasm gnustep-base-devel gettext-devel ncurses-devel libxml2-devel libxslt-devel libyaml-devel glib2-devel json-glib-devel libgcrypt-devel wayland-devel wayland-protocols-devel From e9363e1677194d737f454dcefa9e5c91cd30fa91 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Sun, 28 Apr 2024 00:40:01 +0200 Subject: [PATCH 833/855] Explicitly set OBJC=cc OBJCXX=c++ for bitcode test OBJC=clang / OBJCXX=clang++ can pick up a newer Clang that no longer supports bitcode. --- test cases/osx/7 bitcode/test.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 test cases/osx/7 bitcode/test.json diff --git a/test cases/osx/7 bitcode/test.json b/test cases/osx/7 bitcode/test.json new file mode 100644 index 000000000000..5d063117040a --- /dev/null +++ b/test cases/osx/7 bitcode/test.json @@ -0,0 +1,6 @@ +{ + "env": { + "OBJC": "cc", + "OBJCXX": "c++" + } +} From 4f3a3e2efeb415fe83f9e858b010a36baf72b455 Mon Sep 17 00:00:00 2001 From: kkz Date: Mon, 15 Jan 2024 13:40:59 +0800 Subject: [PATCH 834/855] add punctuation mark to make log more understandable --- mesonbuild/dependencies/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 29a60b774ad8..930dbe7f369d 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -426,7 +426,7 @@ def _check_version(self) -> None: self.is_found = False found_msg: mlog.TV_LoggableList = [] found_msg += ['Dependency', mlog.bold(self.name), 'found:'] - found_msg += [mlog.red('NO'), 'unknown version, but need:', self.version_reqs] + found_msg += [str(mlog.red('NO')) + '.', 'Unknown version, but need:', self.version_reqs] mlog.log(*found_msg) if self.required: @@ -438,8 +438,8 @@ def _check_version(self) -> None: version_compare_many(self.version, self.version_reqs) if not self.is_found: found_msg = ['Dependency', mlog.bold(self.name), 'found:'] - found_msg += [mlog.red('NO'), - 'found', mlog.normal_cyan(self.version), 'but need:', + found_msg += [str(mlog.red('NO')) + '.', + 'Found', mlog.normal_cyan(self.version), 'but need:', mlog.bold(', '.join([f"'{e}'" for e in not_found]))] if found: found_msg += ['; matched:', From e5f32b74144b9f4a43304fa167899e202c5912b5 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Sun, 28 Apr 2024 12:14:06 -0400 Subject: [PATCH 835/855] catch build files that cannot be opened in utf8 mode and emit useful error Previously, if a junked meson.build or native.ini was used we got a lengthy traceback ending in UnicodeDecodeError. Fixes: #13154 Fixes: #13156 --- mesonbuild/ast/interpreter.py | 4 +--- mesonbuild/coredata.py | 20 +++++++++++-------- mesonbuild/interpreter/interpreter.py | 4 +--- mesonbuild/interpreterbase/interpreterbase.py | 11 ++++++++-- mesonbuild/optinterpreter.py | 6 +++++- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 53ddc1052147..15d279350eaa 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -189,9 +189,7 @@ def func_subdir(self, node: BaseNode, args: T.List[TYPE_var], kwargs: T.Dict[str if not os.path.isfile(absname): sys.stderr.write(f'Unable to find build file {buildfilename} --> Skipping\n') return - with open(absname, encoding='utf-8') as f: - code = f.read() - assert isinstance(code, str) + code = self.read_buildfile(absname, buildfilename) try: codeblock = mparser.Parser(code, absname).parse() except mesonlib.MesonException as me: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 3cf873fee740..7213115603a2 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1102,14 +1102,18 @@ def __init__(self, filenames: T.List[str], sourcedir: str) -> None: self.sections: T.Dict[str, T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = {} for fname in filenames: - with open(fname, encoding='utf-8') as f: - content = f.read() - content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir) - content = content.replace('@DIRNAME@', os.path.dirname(fname)) - try: - self.parser.read_string(content, fname) - except configparser.Error as e: - raise EnvironmentException(f'Malformed machine file: {e}') + try: + with open(fname, encoding='utf-8') as f: + content = f.read() + except UnicodeDecodeError as e: + raise EnvironmentException(f'Malformed machine file {fname!r} failed to parse as unicode: {e}') + + content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir) + content = content.replace('@DIRNAME@', os.path.dirname(fname)) + try: + self.parser.read_string(content, fname) + except configparser.Error as e: + raise EnvironmentException(f'Malformed machine file: {e}') # Parse [constants] first so they can be used in other sections if self.parser.has_section('constants'): diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index de8f24d2c9b7..f6b4cf4abd1f 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2425,9 +2425,7 @@ def func_subdir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: 'kwtyp if not os.path.isfile(absname): self.subdir = prev_subdir raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'") - with open(absname, encoding='utf-8') as f: - code = f.read() - assert isinstance(code, str) + code = self.read_buildfile(absname, buildfilename) try: codeblock = mparser.Parser(code, absname).parse() except mesonlib.MesonException as me: diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index ccc33497e7c9..525d5d6c54a0 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -93,12 +93,19 @@ def handle_meson_version_from_ast(self, strict: bool = True) -> None: # do nothing in an AST interpreter return + def read_buildfile(self, fname: str, errname: str) -> str: + try: + with open(fname, encoding='utf-8') as f: + return f.read() + except UnicodeDecodeError as e: + node = mparser.BaseNode(1, 1, errname) + raise InvalidCode.from_node(f'Build file failed to parse as unicode: {e}', node=node) + def load_root_meson_file(self) -> None: mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) if not os.path.isfile(mesonfile): raise InvalidArguments(f'Missing Meson file in {mesonfile}') - with open(mesonfile, encoding='utf-8') as mf: - code = mf.read() + code = self.read_buildfile(mesonfile, mesonfile) if code.isspace(): raise InvalidCode('Builder file is empty.') assert isinstance(code, str) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 980dadd092f9..599da65d3273 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -78,7 +78,11 @@ def __init__(self, subproject: 'SubProject') -> None: def process(self, option_file: str) -> None: try: with open(option_file, encoding='utf-8') as f: - ast = mparser.Parser(f.read(), option_file).parse() + code = f.read() + except UnicodeDecodeError as e: + raise mesonlib.MesonException(f'Malformed option file {option_file!r} failed to parse as unicode: {e}') + try: + ast = mparser.Parser(code, option_file).parse() except mesonlib.MesonException as me: me.file = option_file raise me From bb088c50b455eb877dd6fde311d60690f20c8518 Mon Sep 17 00:00:00 2001 From: Nhalrath Date: Mon, 29 Apr 2024 17:44:41 +0800 Subject: [PATCH 836/855] fix typos and grammars in Build-options.md --- docs/markdown/Build-options.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md index 93e3326a780d..56b2693b8401 100644 --- a/docs/markdown/Build-options.md +++ b/docs/markdown/Build-options.md @@ -6,7 +6,7 @@ short-description: Build options to configure project properties Most non-trivial builds require user-settable options. As an example a program may have two different data backends that are selectable at -build time. Meson provides for this by having a option definition +build time. Meson provides for this by having an option definition file. Its name is `meson.options` and it is placed at the root of your source tree. For versions of meson before 1.1, this file was called `meson_options.txt`. @@ -46,7 +46,7 @@ value is supplied then `true` will be used as the default. ### Combos A combo allows any one of the values in the `choices` parameter to be -selected. If no default value is set then the first value will be the +selected. If no default value is set then the first value will be the default. ### Integers @@ -60,7 +60,7 @@ This type is available since Meson version 0.45.0. ### Arrays Arrays represent an array of strings. By default the array can contain -arbitrary strings. To limit the possible values that can used set the +arbitrary strings. To limit the possible values that can be used set the `choices` parameter. Meson will then only allow the value array to contain strings that are in the given list. The array may be empty. The `value` parameter specifies the default value of the option @@ -75,7 +75,7 @@ This type is available since version 0.44.0 ### Features A `feature` option has three states: `enabled`, `disabled` or `auto`. -It is intended to be passed as value for the `required` keyword +It is intended to be passed as a value for the `required` keyword argument of most functions. Currently supported in [[add_languages]], [[compiler.find_library]], From bd149f8bca0c39cb39116deddd5d8fd2dc55d5e3 Mon Sep 17 00:00:00 2001 From: Ben Corby Date: Tue, 30 Apr 2024 11:19:00 +1000 Subject: [PATCH 837/855] Fix dependencies for vala.links #13158 Using the keyword argument dependencies with compiler.links() for vala doesn't work as the library being linked to needs to be prefixed with --pkg= before being passed to valac. --- mesonbuild/compilers/vala.py | 44 +++++++++++++ .../meson.build | 64 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 test cases/vala/30 dependencies for compiler.links/meson.build diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 839d544150e7..2e35db109560 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -142,6 +142,50 @@ def thread_link_flags(self, env: 'Environment') -> T.List[str]: def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] + def build_wrapper_args(self, env: 'Environment', + extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], + dependencies: T.Optional[T.List['Dependency']], + mode: CompileCheckMode = CompileCheckMode.COMPILE) -> CompilerArgs: + if callable(extra_args): + extra_args = extra_args(mode) + if extra_args is None: + extra_args = [] + if dependencies is None: + dependencies = [] + + # Collect compiler arguments + args = self.compiler_args(self.get_compiler_check_args(mode)) + for d in dependencies: + # Add compile flags needed by dependencies + if mode is CompileCheckMode.LINK and self.force_link: + # As we are passing the parameter to valac we don't need the dependent libraries. + a = d.get_compile_args() + if a: + p = a[0] + n = p[max(p.rfind('/'), p.rfind('\\'))+1:] + if not n == d.get_name(): + args += ['--pkg=' + d.get_name()] # This is used by gio-2.0 among others. + else: + args += ['--pkg=' + n] + else: + args += ['--Xcc=-l' + d.get_name()] # This is used by the maths library(-lm) among others. + else: + args += d.get_compile_args() + if mode is CompileCheckMode.LINK: + # Add link flags needed to find dependencies + if not self.force_link: # There are no need for link dependencies when linking with valac. + args += d.get_link_args() + + if mode is CompileCheckMode.COMPILE: + # Add DFLAGS from the env + args += env.coredata.get_external_args(self.for_machine, self.language) + elif mode is CompileCheckMode.LINK: + # Add LDFLAGS from the env + args += env.coredata.get_external_link_args(self.for_machine, self.language) + # extra_args must override all other arguments, so we add them last + args += extra_args + return args + def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, compiler: T.Optional['Compiler'] = None, extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, diff --git a/test cases/vala/30 dependencies for compiler.links/meson.build b/test cases/vala/30 dependencies for compiler.links/meson.build new file mode 100644 index 000000000000..569cf409c315 --- /dev/null +++ b/test cases/vala/30 dependencies for compiler.links/meson.build @@ -0,0 +1,64 @@ +project('dependency-link-test', ['c', 'vala'], version: '0.1') + +valac = meson.get_compiler('vala') +gee_dep = dependency('gee-0.8', required : false) + +code = '''void main() { + var a=new Gee.ArrayList (); + a.add (42); + stdout.printf("%i",a[0]);}''' + +if gee_dep.found() + # test 1; code should link + code_links = valac.links( + code, + dependencies : [gee_dep], + name: 'links with gee-0.8 library? == YES', + ) + assert (code_links, 'gee-0.8 library should link successfully.') +endif + +# test 2; code should not link +code_links = valac.links( + code, + name: 'links with gee library? == NO', +) +assert (not code_links, 'gee-0.8 library should not link successfully.') + +math_dep = meson.get_compiler('c').find_library('m', required : false) +glib_dep = dependency('glib-2.0', required : false) + +code = '''void main() { + var a=GLib.Math.cos (GLib.Math.PI / 3); + stdout.printf("%f",a);}''' + +if math_dep.found() and glib_dep.found() + # test 3; code should link + code_links = valac.links( + code, + dependencies : [math_dep, glib_dep], + name: 'links with math & glib-2.0 library? == YES', + ) + assert (code_links, 'Math library and glib-2.0 library should link successfully.') +endif + +gio_dep = dependency('gio-2.0', required : false) + +code = '''void main() {var s = new GLib.Settings ("test");}''' + +if gio_dep.found() + # test 4; code should link + code_links = valac.links( + code, + dependencies : [gio_dep], + name: 'links with gio-2.0? == YES', + ) + assert (code_links, 'gio-2.0 library should link successfully.') +endif + +# test 5; code should not link + code_links = valac.links( + code, + name: 'links with gio-2.0? == NO', +) +assert (not code_links, 'gio-2.0 library should not link successfully.') From f38a8269f812c57b1884419a67bb5ce9e9f8983f Mon Sep 17 00:00:00 2001 From: "Michael Gene Brockus (Dreamer)" <55331536+dreamer-coding-555@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:34:08 -0500 Subject: [PATCH 838/855] Updating Continuous-Integration.md (#13161) --- docs/markdown/Continuous-Integration.md | 244 ++++++++++++++---------- 1 file changed, 141 insertions(+), 103 deletions(-) diff --git a/docs/markdown/Continuous-Integration.md b/docs/markdown/Continuous-Integration.md index 0d787d27f73f..1e93fa57febf 100644 --- a/docs/markdown/Continuous-Integration.md +++ b/docs/markdown/Continuous-Integration.md @@ -40,7 +40,7 @@ script: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) meson setup builddir && meson test -C builddir; fi ``` -## CircleCi for Linux (with Docker) +## CircleCI for Linux host (with custom Docker images) [CircleCi](https://circleci.com/) can work for spinning all of the Linux images you wish. Here's a sample `yml` file for use with that. @@ -68,25 +68,43 @@ jobs: executor: meson_ubuntu_builder steps: - checkout - - run: meson setup builddir --backend ninja - - run: meson compile -C builddir - - run: meson test -C builddir + - run: + name: Configure Project + command: meson setup builddir --backend ninja + - run: + name: Compile Project + command: meson compile -C builddir + - run: + name: Run Tests + command: meson test -C builddir meson_debian_build: executor: meson_debian_builder steps: - checkout - - run: meson setup builddir --backend ninja - - run: meson compile -C builddir - - run: meson test -C builddir + - run: + name: Configure Project + command: meson setup builddir --backend ninja + - run: + name: Compile Project + command: meson compile -C builddir + - run: + name: Run Tests + command: meson test -C builddir meson_fedora_build: executor: meson_fedora_builder steps: - checkout - - run: meson setup builddir --backend ninja - - run: meson compile -C builddir - - run: meson test -C builddir + - run: + name: Configure Project + command: meson setup builddir --backend ninja + - run: + name: Compile Project + command: meson compile -C builddir + - run: + name: Run Tests + command: meson test -C builddir workflows: version: 2 @@ -95,6 +113,71 @@ workflows: - meson_ubuntu_build - meson_debian_build - meson_fedora_build + +``` + +## CircleCI for Linux host (without custom Docker images) + +This CircleCI configuration defines two jobs, `build-linux` and `build-macos`, +within a workflow named `build`. The `build-linux` job utilizes a Docker image +with Python 3.12.3, while `build-macos` runs on macOS with Xcode 15.3.0. Each +job involves checking out the code, installing Meson and Ninja, configuring the +project, compiling it, and running tests using Meson. + +```yaml +version: 2.1 + +jobs: + build-linux: + docker: + - image: cimg/python:3.12.3 + steps: + - checkout + - run: + name: Install Meson and Ninja + command: | + python -m pip install --user meson ninja + - run: + name: Configure Project + command: | + meson setup builddir + - run: + name: Compile Project + command: | + meson compile -C builddir + - run: + name: Run Tests + command: | + meson test -C builddir + + build-macos: + macos: + xcode: 15.3.0 + steps: + - checkout + - run: + name: Install Meson and Ninja + command: | + python -m pip install meson ninja + - run: + name: Configure Project + command: | + meson setup builddir + - run: + name: Compile Project + command: | + meson compile -C builddir + - run: + name: Run Tests + command: | + meson test -C builddir + +workflows: + version: 2.1 + build: + jobs: + - build-linux + - build-macos ``` ## AppVeyor for Windows @@ -106,45 +189,25 @@ AppVeyor also has [MacOS](https://www.appveyor.com/docs/macos-images-software/) and [Linux](https://www.appveyor.com/docs/linux-images-software/) CI images. This is a sample `appveyor.yml` file for Windows with Visual -Studio 2015 and 2017. +Studio 2017, 2019, and 2022. ```yaml -image: Visual Studio 2017 - -environment: - matrix: - - arch: x86 - compiler: msvc2015 - - arch: x64 - compiler: msvc2015 - - arch: x86 - compiler: msvc2017 - - arch: x64 - compiler: msvc2017 - -platform: - - x64 +version: 1.0.{build} +image: +- Visual Studio 2022 +- Visual Studio 2019 +- Visual Studio 2017 install: - # Set paths to dependencies (based on architecture) - - cmd: if %arch%==x86 (set PYTHON_ROOT=C:\python37) else (set PYTHON_ROOT=C:\python37-x64) - # Print out dependency paths - - cmd: echo Using Python at %PYTHON_ROOT% - # Add necessary paths to PATH variable - - cmd: set PATH=%cd%;%PYTHON_ROOT%;%PYTHON_ROOT%\Scripts;%PATH% - # Install meson and ninja - - cmd: pip install ninja meson - # Set up the build environment - - cmd: if %compiler%==msvc2015 ( call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %arch% ) - - cmd: if %compiler%==msvc2017 ( call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %arch% ) +- cmd: python -m pip install meson ninja build_script: - - cmd: echo Building on %arch% with %compiler% - - cmd: meson --backend=ninja builddir - - cmd: meson compile -C builddir +- cmd: >- + meson setup builddir + meson compile -C builddir test_script: - - cmd: meson test -C builddir +- cmd: meson test -C builddir ``` ### Qt @@ -199,16 +262,17 @@ script: ## GitHub Actions -GitHub Actions are distinct from Azure Pipelines in their workflow -syntax. It can be easier to setup specific CI tasks in Actions than -Pipelines, depending on the particular task. This is an example file: -.github/workflows/ci_meson.yml supposing the project is C-based, using -GCC on Linux, Mac and Windows. The optional `on:` parameters only run -this CI when the C code is changed--corresponding ci_python.yml might -run only on "**.py" file changes. +GitHub Actions provides a versatile platform for continuous integration +(CI). This example workflow file, `ci_meson.yml`, is tailored for C-based +projects utilizing GCC on Linux, macOS, and Windows. Triggered by changes +to C code files, it automates building and testing processes using different +versions of Meson (1.0.0, 1.1.0, 1.2.0, 1.3.0, 1.4.0) across various operating +systems. Each job in the workflow handles checkout, dependency installation, +project configuration, test execution, and optional test log uploads upon +failure. ```yaml -name: ci_meson +name: CI Meson on: push: @@ -221,59 +285,33 @@ on: - "**.h" jobs: - - linux: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 - with: - python-version: '3.x' - - run: pip install meson ninja - - run: meson setup builddir/ - env: - CC: gcc - - run: meson test -C builddir/ -v - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: Linux_Meson_Testlog - path: builddir/meson-logs/testlog.txt - - macos: - runs-on: macos-latest + build: + name: Build and Test on ${{ matrix.os }} with Meson v${{ matrix.meson_version }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + meson_version: ["1.2.0", "1.3.0", "1.4.0"] steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 - with: - python-version: '3.x' - - run: brew install gcc - - run: pip install meson ninja - - run: meson setup builddir/ - env: - CC: gcc - - run: meson test -C builddir/ -v - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: MacOS_Meson_Testlog - path: builddir/meson-logs/testlog.txt - - windows: - runs-on: windows-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 - with: - python-version: '3.x' - - run: pip install meson ninja - - run: meson setup builddir/ - env: - CC: gcc - - run: meson test -C builddir/ -v - - uses: actions/upload-artifact@v1 - if: failure() - with: - name: Windows_Meson_Testlog - path: builddir/meson-logs/testlog.txt + - name: Checkout code + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install dependencies + run: python -m pip install meson==${{ matrix.meson_version }} ninja + - name: Configure Project + run: meson setup builddir/ + env: + CC: gcc + - name: Run Tests + run: meson test -C builddir/ -v + - name: Upload Test Log + uses: actions/upload-artifact@v4 + if: failure() + with: + name: ${{ matrix.os }}_Meson_Testlog + path: builddir/meson-logs/testlog.txt + ``` From e3db7af0ea41ea120f9d2dfedba309522575c5e7 Mon Sep 17 00:00:00 2001 From: matyalatte Date: Sun, 7 Apr 2024 20:58:43 +0900 Subject: [PATCH 839/855] vs2010backend: fix an error when using /MANIFEST:NO --- mesonbuild/backend/vs2010backend.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 9c23571bd7d8..2e8100884cc7 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -129,6 +129,14 @@ def get_non_primary_lang_intellisense_fields(vslite_ctx: dict, defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = Vs2010Backend._extract_nmake_fields(args_list) return defs_paths_opts_per_lang_and_buildtype +# Returns if a target generates a manifest or not. +def get_gen_manifest(target): + if isinstance(target, build.BuildTarget): + upper_args = [arg.upper() for arg in target.link_args] + manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')] + return len(manifest_args) == 0 or manifest_args[-1] != '/MANIFEST:NO' + return True + class Vs2010Backend(backends.Backend): name = 'vs2010' @@ -616,7 +624,8 @@ def create_basic_project(self, target_name, *, guid, conftype='Utility', target_ext=None, - target_platform=None) -> T.Tuple[ET.Element, ET.Element]: + target_platform=None, + gen_manifest=True) -> T.Tuple[ET.Element, ET.Element]: root = ET.Element('Project', {'DefaultTargets': "Build", 'ToolsVersion': '4.0', 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}) @@ -688,13 +697,16 @@ def create_basic_project(self, target_name, *, ET.SubElement(direlem, 'TargetExt').text = target_ext ET.SubElement(direlem, 'EmbedManifest').text = 'false' + if not gen_manifest: + ET.SubElement(direlem, 'GenerateManifest').text = 'false' return (root, type_config) def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str) -> None: (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), - guid=guid) + guid=guid, + gen_manifest=get_gen_manifest(target)) depend_files = self.get_target_depend_files(target) if not target.command: @@ -729,7 +741,8 @@ def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, gui (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), guid=guid, - target_platform=platform) + target_platform=platform, + gen_manifest=get_gen_manifest(target)) # We need to always use absolute paths because our invocation is always # from the target dir, not the build root. target.absolute_paths = True @@ -769,7 +782,8 @@ def gen_compile_target_vcxproj(self, target: build.CompileTarget, ofname: str, g (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), guid=guid, - target_platform=platform) + target_platform=platform, + gen_manifest=get_gen_manifest(target)) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') target.generated = [self.compile_target_to_generator(target)] target.sources = [] @@ -1601,7 +1615,8 @@ def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ guid=guid, conftype=conftype, target_ext=tfilename[1], - target_platform=platform) + target_platform=platform, + gen_manifest=get_gen_manifest(target)) generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands( target, root) From f1f24816a912bacbb32931bfbd034be36138e3e4 Mon Sep 17 00:00:00 2001 From: matyalatte Date: Thu, 11 Apr 2024 23:46:29 +0900 Subject: [PATCH 840/855] use a for loop, check more linker options --- mesonbuild/backend/vs2010backend.py | 38 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 2e8100884cc7..91275c77e7b9 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -129,14 +129,6 @@ def get_non_primary_lang_intellisense_fields(vslite_ctx: dict, defs_paths_opts_per_lang_and_buildtype[src_lang][buildtype] = Vs2010Backend._extract_nmake_fields(args_list) return defs_paths_opts_per_lang_and_buildtype -# Returns if a target generates a manifest or not. -def get_gen_manifest(target): - if isinstance(target, build.BuildTarget): - upper_args = [arg.upper() for arg in target.link_args] - manifest_args = [arg for arg in upper_args if arg == '/MANIFEST' or arg.startswith('/MANIFEST:')] - return len(manifest_args) == 0 or manifest_args[-1] != '/MANIFEST:NO' - return True - class Vs2010Backend(backends.Backend): name = 'vs2010' @@ -706,7 +698,7 @@ def gen_run_target_vcxproj(self, target: build.RunTarget, ofname: str, guid: str (root, type_config) = self.create_basic_project(target.name, temp_dir=target.get_id(), guid=guid, - gen_manifest=get_gen_manifest(target)) + gen_manifest=self.get_gen_manifest(target)) depend_files = self.get_target_depend_files(target) if not target.command: @@ -742,7 +734,7 @@ def gen_custom_target_vcxproj(self, target: build.CustomTarget, ofname: str, gui temp_dir=target.get_id(), guid=guid, target_platform=platform, - gen_manifest=get_gen_manifest(target)) + gen_manifest=self.get_gen_manifest(target)) # We need to always use absolute paths because our invocation is always # from the target dir, not the build root. target.absolute_paths = True @@ -783,7 +775,7 @@ def gen_compile_target_vcxproj(self, target: build.CompileTarget, ofname: str, g temp_dir=target.get_id(), guid=guid, target_platform=platform, - gen_manifest=get_gen_manifest(target)) + gen_manifest=self.get_gen_manifest(target)) ET.SubElement(root, 'Import', Project=r'$(VCTargetsPath)\Microsoft.Cpp.targets') target.generated = [self.compile_target_to_generator(target)] target.sources = [] @@ -1616,7 +1608,7 @@ def gen_vcxproj(self, target: build.BuildTarget, ofname: str, guid: str, vslite_ conftype=conftype, target_ext=tfilename[1], target_platform=platform, - gen_manifest=get_gen_manifest(target)) + gen_manifest=self.get_gen_manifest(target)) generated_files, custom_target_output_files, generated_files_include_dirs = self.generate_custom_generator_commands( target, root) @@ -2095,3 +2087,25 @@ def add_regen_dependency(self, root: ET.Element) -> None: def generate_lang_standard_info(self, file_args: T.Dict[str, CompilerArgs], clconf: ET.Element) -> None: pass + + # Returns if a target generates a manifest or not. + def get_gen_manifest(self, target): + if not isinstance(target, build.BuildTarget): + return True + + compiler = self._get_cl_compiler(target) + link_args = compiler.compiler_args() + if not isinstance(target, build.StaticLibrary): + link_args += self.build.get_project_link_args(compiler, target.subproject, target.for_machine) + link_args += self.build.get_global_link_args(compiler, target.for_machine) + link_args += self.environment.coredata.get_external_link_args( + target.for_machine, compiler.get_language()) + link_args += target.link_args + + for arg in reversed(link_args): + arg = arg.upper() + if arg == '/MANIFEST:NO': + return False + if arg == '/MANIFEST' or arg.startswith('/MANIFEST:'): + break + return True From a0ff14551266c87919f5b4b1469b7be0ef0a052e Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Wed, 24 Apr 2024 19:51:35 -0500 Subject: [PATCH 841/855] Add required kwarg to compiler.{compiles,links,run} This is a similar commit to the one that added required to all the compiler.has* functions. --- ...requires_kwarg_on_more_compiler_methods.md | 21 +++++++++ docs/yaml/objects/compiler.yaml | 10 ++++ mesonbuild/interpreter/compiler.py | 47 +++++++++++++++---- .../invalid.c | 7 +++ .../meson.build | 41 ++++++++++++++++ .../meson_options.txt | 1 + .../valid.c | 5 ++ 7 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md create mode 100644 test cases/common/275 required keyword in compiles functions/invalid.c create mode 100644 test cases/common/275 required keyword in compiles functions/meson.build create mode 100644 test cases/common/275 required keyword in compiles functions/meson_options.txt create mode 100644 test cases/common/275 required keyword in compiles functions/valid.c diff --git a/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md b/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md new file mode 100644 index 000000000000..693313c31413 --- /dev/null +++ b/docs/markdown/snippets/requires_kwarg_on_more_compiler_methods.md @@ -0,0 +1,21 @@ +## 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/yaml/objects/compiler.yaml b/docs/yaml/objects/compiler.yaml index c86ef7f4ccb0..cd988a6834cd 100644 --- a/docs/yaml/objects/compiler.yaml +++ b/docs/yaml/objects/compiler.yaml @@ -121,6 +121,16 @@ methods: - name: _compiles returns: void description: You have found a bug if you can see this! + kwargs: + required: + type: bool | feature + default: false + since: 1.5.0 + description: + When set to `true`, Meson will halt if the check fails. + + When set to a [`feature`](Build-options.md#features) option, the feature + will control if it is searched and whether to fail if not found. kwargs_inherit: - compiler._args - compiler._include_directories diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index fb43035a565f..50a850af4482 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -15,7 +15,7 @@ from .. import dependencies from .. import mesonlib from .. import mlog -from ..compilers import SUFFIX_TO_LANG +from ..compilers import SUFFIX_TO_LANG, RunResult from ..compilers.compilers import CompileCheckMode from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs, FeatureNew, FeatureNewKwargs, disablerIfNotFound, @@ -27,7 +27,7 @@ if T.TYPE_CHECKING: from ..interpreter import Interpreter - from ..compilers import Compiler, RunResult + from ..compilers import Compiler from ..interpreterbase import TYPE_var, TYPE_kwargs from .kwargs import ExtractRequired, ExtractSearchDirs from .interpreter import SourceOutputs @@ -50,7 +50,7 @@ class BaseCompileKW(TypedDict): include_directories: T.List[build.IncludeDirs] args: T.List[str] - class CompileKW(BaseCompileKW): + class CompileKW(BaseCompileKW, ExtractRequired): name: str dependencies: T.List[dependencies.Dependency] @@ -178,7 +178,8 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str: # Common methods of compiles, links, runs, and similar _COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW, - _WERROR_KW] + _WERROR_KW, + REQUIRED_KW.evolve(since='1.5.0', default=False)] _HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS] _HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.3.0', default=False) @@ -306,15 +307,25 @@ def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW' FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language', '1.5.0', self.subproject, location=self.current_node) code = args[0] + testname = kwargs['name'] + + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + if testname: + mlog.log('Checking if', mlog.bold(testname, True), 'runs:', 'skipped: feature', mlog.bold(feature), 'disabled') + return RunResult(compiled=True, returncode=0, stdout='', stderr='', cached=False) + if isinstance(code, mesonlib.File): self.interpreter.add_build_def_file(code) code = mesonlib.File.from_absolute_file( code.rel_to_builddir(self.environment.source_dir)) - testname = kwargs['name'] extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False, endl=None) result = self.compiler.run(code, self.environment, extra_args=extra_args, dependencies=deps) + if required and result.returncode != 0: + raise InterpreterException(f'Could not run {testname if testname else "code"}') + if testname: if not result.compiled: h = mlog.red('DID NOT COMPILE') @@ -510,6 +521,14 @@ def has_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool: @typed_kwargs('compiler.compiles', *_COMPILES_KWS) def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: code = args[0] + testname = kwargs['name'] + + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + if testname: + mlog.log('Checking if', mlog.bold(testname, True), 'compiles:', 'skipped: feature', mlog.bold(feature), 'disabled') + return False + if isinstance(code, mesonlib.File): if code.is_built: FeatureNew.single_use('compiler.compiles with file created at setup time', '1.2.0', self.subproject, @@ -517,12 +536,14 @@ def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'Compi self.interpreter.add_build_def_file(code) code = mesonlib.File.from_absolute_file( code.absolute_path(self.environment.source_dir, self.environment.build_dir)) - testname = kwargs['name'] extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None) result, cached = self.compiler.compiles(code, self.environment, extra_args=extra_args, dependencies=deps) + if required and not result: + raise InterpreterException(f'Could not compile {testname}') + if testname: if result: h = mlog.green('YES') @@ -536,6 +557,14 @@ def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'Compi @typed_kwargs('compiler.links', *_COMPILES_KWS) def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool: code = args[0] + testname = kwargs['name'] + + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + if testname: + mlog.log('Checking if', mlog.bold(testname, True), 'links:', 'skipped: feature', mlog.bold(feature), 'disabled') + return False + compiler = None if isinstance(code, mesonlib.File): if code.is_built: @@ -556,19 +585,21 @@ def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileK else: compiler = clist[SUFFIX_TO_LANG[suffix]] - testname = kwargs['name'] extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) result, cached = self.compiler.links(code, self.environment, compiler=compiler, extra_args=extra_args, dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' + if required and not result: + raise InterpreterException(f'Could not link {testname if testname else "code"}') + if testname: if result: h = mlog.green('YES') else: h = mlog.red('NO') + cached_msg = mlog.blue('(cached)') if cached else '' mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg) return result diff --git a/test cases/common/275 required keyword in compiles functions/invalid.c b/test cases/common/275 required keyword in compiles functions/invalid.c new file mode 100644 index 000000000000..d255a36aa376 --- /dev/null +++ b/test cases/common/275 required keyword in compiles functions/invalid.c @@ -0,0 +1,7 @@ +// The error in this file is an homage to the xz incident :) +// +int +main(void) +{ +. return 0; +} diff --git a/test cases/common/275 required keyword in compiles functions/meson.build b/test cases/common/275 required keyword in compiles functions/meson.build new file mode 100644 index 000000000000..d0f5b7f4a9b4 --- /dev/null +++ b/test cases/common/275 required keyword in compiles functions/meson.build @@ -0,0 +1,41 @@ +project('required keyword in compiles functions', 'c') + +cc = meson.get_compiler('c') +opt = get_option('opt') + +valid = files('valid.c') +invalid = files('invalid.c') + +cc.compiles(valid, name: 'valid', required : true) +cc.links(valid, name: 'valid', required : true) +if meson.can_run_host_binaries() + cc.run(valid, name: 'valid', required : true) +endif + +assert(not cc.compiles(valid, name: 'valid', required : opt)) +assert(not cc.links(valid, name: 'valid', required : opt)) +if meson.can_run_host_binaries() + res = cc.run(valid, name: 'valid', required : opt) + assert(res.compiled()) + assert(res.returncode() == 0) + assert(res.stdout() == '') + assert(res.stderr() == '') +endif + +testcase expect_error('''compiler.compiles keyword argument 'required' was of type str but should have been one of: bool, UserFeatureOption''') + cc.compiles(valid, name: 'valid', required : 'not a bool') +endtestcase + +testcase expect_error('''Could not compile invalid''') + cc.compiles(invalid, name: 'invalid', required : true) +endtestcase + +testcase expect_error('''Could not link invalid''') + cc.links(invalid, name: 'invalid', required : true) +endtestcase + +if meson.can_run_host_binaries() + testcase expect_error('''Could not run invalid''') + cc.run(invalid, name: 'invalid', required : true) + endtestcase +endif diff --git a/test cases/common/275 required keyword in compiles functions/meson_options.txt b/test cases/common/275 required keyword in compiles functions/meson_options.txt new file mode 100644 index 000000000000..53175afec478 --- /dev/null +++ b/test cases/common/275 required keyword in compiles functions/meson_options.txt @@ -0,0 +1 @@ +option('opt', type: 'feature', value: 'disabled') diff --git a/test cases/common/275 required keyword in compiles functions/valid.c b/test cases/common/275 required keyword in compiles functions/valid.c new file mode 100644 index 000000000000..8479e67d1090 --- /dev/null +++ b/test cases/common/275 required keyword in compiles functions/valid.c @@ -0,0 +1,5 @@ +int +main(void) +{ + return 0; +} From 23eb7ba700cd6c53d5491cc4f99c532629efa1e2 Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Thu, 2 May 2024 00:01:25 -0500 Subject: [PATCH 842/855] Use correct subdir when generating processed file path We need the subdir of where the output file will actually be created, not the current subdir of the interpreter. Fixes: #13168 --- mesonbuild/build.py | 6 +---- .../include/meson.build | 4 ++++ .../meson.build | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 test cases/common/276 generator custom_tgt subdir/include/meson.build create mode 100644 test cases/common/276 generator custom_tgt subdir/meson.build diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 6f0d6a2ddaac..da4c4373d551 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1818,13 +1818,9 @@ def process_files(self, files: T.Iterable[T.Union[str, File, 'CustomTarget', 'Cu env=env if env is not None else EnvironmentVariables()) for e in files: - if isinstance(e, CustomTarget): - output.depends.add(e) - if isinstance(e, CustomTargetIndex): - output.depends.add(e.target) if isinstance(e, (CustomTarget, CustomTargetIndex)): output.depends.add(e) - fs = [File.from_built_file(state.subdir, f) for f in e.get_outputs()] + fs = [File.from_built_file(e.get_subdir(), f) for f in e.get_outputs()] elif isinstance(e, GeneratedList): if preserve_path_from: raise InvalidArguments("generator.process: 'preserve_path_from' is not allowed if one input is a 'generated_list'.") diff --git a/test cases/common/276 generator custom_tgt subdir/include/meson.build b/test cases/common/276 generator custom_tgt subdir/include/meson.build new file mode 100644 index 000000000000..251e0ed0c771 --- /dev/null +++ b/test cases/common/276 generator custom_tgt subdir/include/meson.build @@ -0,0 +1,4 @@ +test_header = custom_target( + output: 'test_header.h', + command: [python, args, '@OUTPUT@'], +) diff --git a/test cases/common/276 generator custom_tgt subdir/meson.build b/test cases/common/276 generator custom_tgt subdir/meson.build new file mode 100644 index 000000000000..38e9635b6f15 --- /dev/null +++ b/test cases/common/276 generator custom_tgt subdir/meson.build @@ -0,0 +1,24 @@ +project('276 generator custom_tgt subdir') + +python = find_program('python3', required: true) +args = [ + '-c', + 'import sys; open(sys.argv[1], "w")', + '@OUTPUT0@', +] + +subdir('include') + +gen = generator( + python, + arguments: args + ['@OUTPUT@'], + output: '@PLAINNAME@.t', +) + +custom_target( + 'check-headers.stamp', + command: [python, args, '@INPUT@'], + input: gen.process(test_header), + output: 'check-headers.stamp', + build_by_default: true, +) From 8cb16b2d6a97514bf17aa8ca2f6bf098cfc5bcbf Mon Sep 17 00:00:00 2001 From: Tristan Partin Date: Tue, 7 May 2024 14:51:40 -0500 Subject: [PATCH 843/855] Add support for GCC's null_terminated_string_arg function attribute This is new as of 14.1. --- docs/markdown/Reference-tables.md | 99 ++++++++++--------- .../snippets/null_terminated_string_arg.md | 13 +++ mesonbuild/compilers/c_function_attributes.py | 2 + .../197 function attributes/meson.build | 6 ++ 4 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 docs/markdown/snippets/null_terminated_string_arg.md diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index d30d22a50096..2357ff459af4 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -272,54 +272,55 @@ These values are supported using the GCC style `__attribute__` annotations, which are supported by GCC, Clang, and other compilers. -| Name | -|--------------------------| -| alias | -| aligned | -| alloc_size | -| always_inline | -| artificial | -| cold | -| const | -| constructor | -| constructor_priority | -| deprecated | -| destructor | -| error | -| externally_visible | -| fallthrough | -| flatten | -| format | -| format_arg | -| force_align_arg_pointer³ | -| gnu_inline | -| hot | -| ifunc | -| malloc | -| noclone | -| noinline | -| nonnull | -| noreturn | -| nothrow | -| optimize | -| packed | -| pure | -| retain⁴ | -| returns_nonnull | -| section⁵ | -| sentinel⁵ | -| unused | -| used | -| vector_size⁶ | -| visibility* | -| visibility:default† | -| visibility:hidden† | -| visibility:internal† | -| visibility:protected† | -| warning | -| warn_unused_result | -| weak | -| weakref | +| Name | +|-----------------------------| +| alias | +| aligned | +| alloc_size | +| always_inline | +| artificial | +| cold | +| const | +| constructor | +| constructor_priority | +| deprecated | +| destructor | +| error | +| externally_visible | +| fallthrough | +| flatten | +| format | +| format_arg | +| force_align_arg_pointer³ | +| gnu_inline | +| hot | +| ifunc | +| malloc | +| noclone | +| noinline | +| nonnull | +| noreturn | +| nothrow | +| null_terminated_string_arg⁷ | +| optimize | +| packed | +| pure | +| retain⁴ | +| returns_nonnull | +| section⁵ | +| sentinel⁵ | +| unused | +| used | +| vector_size⁶ | +| visibility* | +| visibility:default† | +| visibility:hidden† | +| visibility:internal† | +| visibility:protected† | +| warning | +| warn_unused_result | +| weak | +| weakref | \* *Changed in 0.52.0* the "visibility" target no longer includes "protected", which is not present in Apple's clang. @@ -335,6 +336,8 @@ which are supported by GCC, Clang, and other compilers. ⁶ *New in 1.1.0* +⁷ *New in 1.5.0* + ### MSVC __declspec These values are supported using the MSVC style `__declspec` annotation, diff --git a/docs/markdown/snippets/null_terminated_string_arg.md b/docs/markdown/snippets/null_terminated_string_arg.md new file mode 100644 index 000000000000..2ba1755758f8 --- /dev/null +++ b/docs/markdown/snippets/null_terminated_string_arg.md @@ -0,0 +1,13 @@ +## 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/mesonbuild/compilers/c_function_attributes.py b/mesonbuild/compilers/c_function_attributes.py index eec872b5f0b1..a7258a1cae5b 100644 --- a/mesonbuild/compilers/c_function_attributes.py +++ b/mesonbuild/compilers/c_function_attributes.py @@ -80,6 +80,8 @@ 'int foo(void) __attribute__((noreturn));', 'nothrow': 'int foo(void) __attribute__((nothrow));', + 'null_terminated_string_arg': + 'int foo(const char * p) __attribute__((null_terminated_string_arg(1)));', 'optimize': '__attribute__((optimize(3))) int foo(void) { return 0; }', 'packed': diff --git a/test cases/common/197 function attributes/meson.build b/test cases/common/197 function attributes/meson.build index 530db9313329..db7e3af32be3 100644 --- a/test cases/common/197 function attributes/meson.build +++ b/test cases/common/197 function attributes/meson.build @@ -117,6 +117,12 @@ if ['gcc', 'intel'].contains(c.get_id()) endif endif +if c.get_id() == 'gcc' + if c.version().version_compare('>= 14.1') + attributes += 'null_terminated_string_arg' + endif +endif + if get_option('mode') == 'single' foreach a : attributes x = c.has_function_attribute(a) From 33adc420f318acfa80b6d6bceb79084eded0d3a0 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 8 May 2024 00:55:03 +0200 Subject: [PATCH 844/855] cuda: pull in libdir when linking C/C++ * In `CudaDependency._detect_language`, the first detected language is considered the linking one. Since `nvcc`/`cuda` implicitly know where the cuda dependency lives, this leads to situations where `cpp` as linking language is erroneously detected as `cuda` and then misses the `-L` argument. --- mesonbuild/dependencies/cuda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py index 1a7b3caceb4d..a38e325b8741 100644 --- a/mesonbuild/dependencies/cuda.py +++ b/mesonbuild/dependencies/cuda.py @@ -24,7 +24,7 @@ class CudaDependency(SystemDependency): - supported_languages = ['cuda', 'cpp', 'c'] # see also _default_language + supported_languages = ['cpp', 'c', 'cuda'] # see also _default_language def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: compilers = environment.coredata.compilers[self.get_for_machine_from_kwargs(kwargs)] From c55ca8272c536d439253d38600f3c9e445b1edf7 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 8 May 2024 00:55:04 +0200 Subject: [PATCH 845/855] cuda: add test for C++ linking of dependency('cuda') --- test cases/cuda/12 cuda dependency (mixed)/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test cases/cuda/12 cuda dependency (mixed)/meson.build b/test cases/cuda/12 cuda dependency (mixed)/meson.build index 5df4f846e44d..44a49db70f05 100644 --- a/test cases/cuda/12 cuda dependency (mixed)/meson.build +++ b/test cases/cuda/12 cuda dependency (mixed)/meson.build @@ -1,4 +1,4 @@ project('cuda dependency', 'cpp', 'cuda') -exe = executable('prog', 'prog.cpp', 'kernel.cu', dependencies: dependency('cuda', modules: ['cublas'])) +exe = executable('prog', 'prog.cpp', 'kernel.cu', dependencies: dependency('cuda', modules: ['cublas']), link_language: 'cpp') test('cudatest', exe) From 89a5bde9d98ecc96bb462872bb2d83ac762ffc08 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 8 May 2024 00:55:05 +0200 Subject: [PATCH 846/855] cuda: pass static archives to nvcc without -Xlinker= prefix --- mesonbuild/backend/backends.py | 9 +++++++++ mesonbuild/compilers/cuda.py | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index a45de70ddd63..740f349e4433 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1080,6 +1080,15 @@ def build_target_link_arguments(self, compiler: 'Compiler', deps: T.List[build.T continue if compiler.get_language() == 'd': arg = '-Wl,' + arg + elif compiler.get_linker_id() == 'nvlink' and arg.endswith('.a'): + # We need to pass static archives without -Xlinker= to nvcc, + # since they may contain relocatable device code. When passing + # the static archive to nvcc with -Xlinker=, we bypass the + # frontend which means we lose the opportunity to perform device + # linking. We only need to do this for static archives, since + # nvcc doesn't support device linking with dynamic libraries: + # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#libraries + pass else: arg = compiler.get_linker_lib_prefix() + arg args.append(arg) diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 7f7ad74951a8..3761019b9945 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -382,8 +382,11 @@ def _to_host_flags(self, flags: T.List[str], phase: _Phase = _Phase.COMPILER) -> # This is ambiguously either an MVSC-style /switch or an absolute path # to a file. For some magical reason the following works acceptably in # both cases. + # We only want to prefix arguments that are NOT static archives, since + # the latter could contain relocatable device code (-dc/-rdc=true). + prefix = '' if flag.endswith('.a') else f'-X{phase.value}=' wrap = '"' if ',' in flag else '' - xflags.append(f'-X{phase.value}={wrap}{flag}{wrap}') + xflags.append(f'{prefix}{wrap}{flag}{wrap}') continue elif len(flag) >= 2 and flag[0] == '-' and flag[1] in 'IDULlmOxmte': # This is a single-letter short option. These options (with the From b6e5683764c5b296a98b67c0a2ec11fbd9f59c71 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 8 May 2024 00:55:06 +0200 Subject: [PATCH 847/855] cuda: disable thin archives when 'cuda' is enabled globally Bug: mesonbuild/meson/pull/9453 Bug: mesonbuild/meson/issues/9479#issuecomment-953485040 --- mesonbuild/backend/ninjabackend.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index e394c60fcc30..28f5d532fca8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -496,6 +496,19 @@ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Inter self.rust_crates: T.Dict[str, RustCrate] = {} self.implicit_meson_outs = [] self._uses_dyndeps = False + # nvcc chokes on thin archives: + # nvlink fatal : Could not open input file 'libfoo.a.p' + # nvlink fatal : elfLink internal error + # hence we disable them if 'cuda' is enabled globally. See also + # - https://github.com/mesonbuild/meson/pull/9453 + # - https://github.com/mesonbuild/meson/issues/9479#issuecomment-953485040 + self._allow_thin_archives = PerMachine[bool]( + 'cuda' not in self.environment.coredata.compilers.build, + 'cuda' not in self.environment.coredata.compilers.host) if self.environment else PerMachine[bool](True, True) + if not self._allow_thin_archives.build: + mlog.debug('cuda enabled globally, disabling thin archives for build machine, since nvcc/nvlink cannot handle thin archives natively') + if not self._allow_thin_archives.host: + mlog.debug('cuda enabled globally, disabling thin archives for host machine, since nvcc/nvlink cannot handle thin archives natively') def create_phony_target(self, dummy_outfile: str, rulename: str, phony_infilename: str) -> NinjaBuildElement: ''' @@ -3255,7 +3268,8 @@ def get_target_type_link_args(self, target, linker): if target.import_filename: commands += linker.gen_import_library_args(self.get_import_filename(target)) elif isinstance(target, build.StaticLibrary): - commands += linker.get_std_link_args(self.environment, not target.should_install()) + produce_thin_archive = self._allow_thin_archives[target.for_machine] and not target.should_install() + commands += linker.get_std_link_args(self.environment, produce_thin_archive) else: raise RuntimeError('Unknown build target type.') return commands From 14de8ac5a9e04490a67e3ddcbd44b31915aed1b9 Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 8 May 2024 00:55:07 +0200 Subject: [PATCH 848/855] cuda: add test for device linking --- .../cuda/17 separate compilation linking/b.cu | 5 +++ .../cuda/17 separate compilation linking/b.h | 5 +++ .../17 separate compilation linking/main.cu | 44 +++++++++++++++++++ .../meson.build | 19 ++++++++ 4 files changed, 73 insertions(+) create mode 100644 test cases/cuda/17 separate compilation linking/b.cu create mode 100644 test cases/cuda/17 separate compilation linking/b.h create mode 100644 test cases/cuda/17 separate compilation linking/main.cu create mode 100644 test cases/cuda/17 separate compilation linking/meson.build diff --git a/test cases/cuda/17 separate compilation linking/b.cu b/test cases/cuda/17 separate compilation linking/b.cu new file mode 100644 index 000000000000..33ff561e21c4 --- /dev/null +++ b/test cases/cuda/17 separate compilation linking/b.cu @@ -0,0 +1,5 @@ +#include "b.h" + +__device__ int g[N]; + +__device__ void bar(void) { g[threadIdx.x]++; } diff --git a/test cases/cuda/17 separate compilation linking/b.h b/test cases/cuda/17 separate compilation linking/b.h new file mode 100644 index 000000000000..d8a0efcd9ca4 --- /dev/null +++ b/test cases/cuda/17 separate compilation linking/b.h @@ -0,0 +1,5 @@ +#define N 8 + +extern __device__ int g[N]; + +extern __device__ void bar(void); diff --git a/test cases/cuda/17 separate compilation linking/main.cu b/test cases/cuda/17 separate compilation linking/main.cu new file mode 100644 index 000000000000..b07d01bda018 --- /dev/null +++ b/test cases/cuda/17 separate compilation linking/main.cu @@ -0,0 +1,44 @@ +#include + +#include "b.h" + +__global__ void foo(void) +{ + __shared__ int a[N]; + a[threadIdx.x] = threadIdx.x; + + __syncthreads(); + + g[threadIdx.x] = a[blockDim.x - threadIdx.x - 1]; + + bar(); +} + +int main(void) +{ + unsigned int i; + int *dg, hg[N]; + int sum = 0; + + foo<<<1, N>>>(); + + if (cudaGetSymbolAddress((void**)&dg, g)) { + printf("couldn't get the symbol addr\n"); + return 1; + } + if (cudaMemcpy(hg, dg, N * sizeof(int), cudaMemcpyDeviceToHost)) { + printf("couldn't memcpy\n"); + return 1; + } + + for (i = 0; i < N; i++) { + sum += hg[i]; + } + if (sum == 36) { + printf("PASSED\n"); + } else { + printf("FAILED (%d)\n", sum); + } + + return 0; +} diff --git a/test cases/cuda/17 separate compilation linking/meson.build b/test cases/cuda/17 separate compilation linking/meson.build new file mode 100644 index 000000000000..ee86123eb40d --- /dev/null +++ b/test cases/cuda/17 separate compilation linking/meson.build @@ -0,0 +1,19 @@ +# example here is inspired by Nvidia's blog post: +# https://developer.nvidia.com/blog/separate-compilation-linking-cuda-device-code/ +# code: +# https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#examples + +project('device linking', ['cpp', 'cuda'], version : '1.0.0') + +nvcc = meson.get_compiler('cuda') +cuda = import('unstable-cuda') + +arch_flags = cuda.nvcc_arch_flags(nvcc.version(), 'Auto', detected : ['8.0']) + +message('NVCC version: ' + nvcc.version()) +message('NVCC flags: ' + ' '.join(arch_flags)) + +# test device linking with -dc (which is equivalent to `--relocatable-device-code true`) +lib = static_library('devicefuncs', ['b.cu'], cuda_args : ['-dc'] + arch_flags) +exe = executable('app', 'main.cu', cuda_args : ['-dc'] + arch_flags, link_with : lib, link_args : arch_flags) +test('cudatest', exe) From bcaab91bf61327bb7c2a0259292c2a336ad6513a Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 3 May 2024 10:05:24 +0200 Subject: [PATCH 849/855] mtest: Set MESON_TEST_ITERATION to the current iteration of the test When running our integration tests in systemd we depend on each test having a unique name. This is always the case unless --repeat is used, in which case multiple tests with the same name run concurrently which causes issues when allocating resources that use the test name as the identifier. Let's set MESON_TEST_ITERATION to the current iteration of the test so we can use $TEST_NAME-$TEST_ITERATION as our test identifiers which will avoid these issues. --- docs/markdown/Unit-tests.md | 3 +++ docs/markdown/snippets/test_iteration.md | 5 +++++ mesonbuild/mtest.py | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/test_iteration.md diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md index 73e58dc68ab6..6fda0f5f6861 100644 --- a/docs/markdown/Unit-tests.md +++ b/docs/markdown/Unit-tests.md @@ -208,6 +208,9 @@ Sometimes you need to run the tests multiple times, which is done like this: $ meson test --repeat=10 ``` +Meson will set the `MESON_TEST_ITERATION` environment variable to the +current iteration of the test *(added 1.5.0)*. + Invoking tests via a helper executable such as Valgrind can be done with the `--wrap` argument diff --git a/docs/markdown/snippets/test_iteration.md b/docs/markdown/snippets/test_iteration.md new file mode 100644 index 000000000000..67daf278129d --- /dev/null +++ b/docs/markdown/snippets/test_iteration.md @@ -0,0 +1,5 @@ +## 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/mesonbuild/mtest.py b/mesonbuild/mtest.py index 460a44c49da8..03d2eb254df0 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -1709,7 +1709,7 @@ def merge_setup_options(self, options: argparse.Namespace, test: TestSerialisati sys.exit('Conflict: both test setup and command line specify an exe wrapper.') return current.env.get_env(os.environ.copy()) - def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner: + def get_test_runner(self, test: TestSerialisation, iteration: int) -> SingleTestRunner: name = self.get_pretty_suite(test) options = deepcopy(self.options) if self.options.setup: @@ -1721,6 +1721,7 @@ def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner: if (test.is_cross_built and test.needs_exe_wrapper and test.exe_wrapper and test.exe_wrapper.found()): env['MESON_EXE_WRAPPER'] = join_args(test.exe_wrapper.get_command()) + env['MESON_TEST_ITERATION'] = str(iteration + 1) return SingleTestRunner(test, env, name, options) def process_test_result(self, result: TestRun) -> None: @@ -1822,7 +1823,7 @@ def doit(self) -> int: os.chdir(self.options.wd) runners: T.List[SingleTestRunner] = [] for i in range(self.options.repeat): - runners.extend(self.get_test_runner(test) for test in tests) + runners.extend(self.get_test_runner(test, i) for test in tests) if i == 0: self.duration_max_len = max(len(str(int(runner.timeout or 99))) for runner in runners) From c0e877e53d0ad0eef21e316a443ab1ce0f55aa7c Mon Sep 17 00:00:00 2001 From: Axel Ricard Date: Thu, 14 Mar 2024 10:52:58 +0100 Subject: [PATCH 850/855] fix broken link --- docs/markdown/D.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/D.md b/docs/markdown/D.md index 03d4047b719f..b80910329c1d 100644 --- a/docs/markdown/D.md +++ b/docs/markdown/D.md @@ -139,6 +139,6 @@ DUB is a fully integrated build system for D, but it is also a way to provide dependencies. Adding dependencies from the [D package registry](https://code.dlang.org/) is pretty straight forward. You can find how to do this in -[Dependencies](Dependencies.md#some-notes-on-dub). You can also +[Dependencies](Dependencies.md#dub). You can also automatically generate a `dub.json` file as explained in [Dlang](Dlang-module.md#generate_dub_file). From f8aefe20703e3d64710fa675d511f9bef77dc32a Mon Sep 17 00:00:00 2001 From: sammyj85 Date: Tue, 7 May 2024 12:20:37 +0930 Subject: [PATCH 851/855] In Builtin-options documentation, clarify warning_level=0. warning_level=0 is not 'none' but 'compiler default'. --- docs/markdown/Builtin-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 7cdf6e8d33d5..64d16aba255a 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -91,7 +91,7 @@ machine](#specifying-options-per-machine) section for details. | strip | false | Strip targets on install | no | no | | unity {on, off, subprojects} | off | Unity build | no | no | | unity_size {>=2} | 4 | Unity file block size | no | no | -| warning_level {0, 1, 2, 3, everything} | 1 | Set the warning level. From 0 = none to everything = highest | no | yes | +| warning_level {0, 1, 2, 3, everything} | 1 | Set the warning level. From 0 = compiler default to everything = highest | no | yes | | werror | false | Treat warnings as errors | no | yes | | wrap_mode {default, nofallback,
nodownload, forcefallback, nopromote} | default | Wrap mode to use | no | no | | force_fallback_for | [] | Force fallback for those dependencies | no | no | From cfd57180eef9036c7167c5682b9f3055a540fccc Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Tue, 7 May 2024 21:46:55 +0300 Subject: [PATCH 852/855] implement @PLAINNAME0@ and @BASENAME0@ @PLAINNAME@ and @BASENAME@ cannot be used in custom_target() with multiple inputs. For those, similar macros are needed with an index. Fixes #13164 --- docs/markdown/snippets/pln_bsn_support.md | 11 +++++++++++ docs/yaml/functions/configure_file.yaml | 4 +++- docs/yaml/functions/custom_target.yaml | 2 ++ mesonbuild/interpreter/interpreter.py | 10 ++++++++-- mesonbuild/utils/universal.py | 5 +++++ unittests/internaltests.py | 11 ++++++++++- 6 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 docs/markdown/snippets/pln_bsn_support.md diff --git a/docs/markdown/snippets/pln_bsn_support.md b/docs/markdown/snippets/pln_bsn_support.md new file mode 100644 index 000000000000..394339f1499d --- /dev/null +++ b/docs/markdown/snippets/pln_bsn_support.md @@ -0,0 +1,11 @@ +## 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/yaml/functions/configure_file.yaml b/docs/yaml/functions/configure_file.yaml index 34cb3c1bd8b3..20b96aa6e62d 100644 --- a/docs/yaml/functions/configure_file.yaml +++ b/docs/yaml/functions/configure_file.yaml @@ -123,7 +123,9 @@ kwargs: type: str description: | The output file name. *(since 0.41.0)* may contain - `@PLAINNAME@` or `@BASENAME@` substitutions. In configuration mode, + `@PLAINNAME@` or `@BASENAME@` substitutions, as well as *(since 1.5.0)* + their indexed versions, like `@PLAINNAME0@` or `@BASENAME0@`. + In configuration mode, the permissions of the input file (if it is specified) are copied to the output file. diff --git a/docs/yaml/functions/custom_target.yaml b/docs/yaml/functions/custom_target.yaml index cd5c60e2e7bf..585d2602aff7 100644 --- a/docs/yaml/functions/custom_target.yaml +++ b/docs/yaml/functions/custom_target.yaml @@ -31,7 +31,9 @@ description: | - `@OUTDIR@`: the full path to the directory where the output(s) must be written - `@DEPFILE@`: the full path to the dependency file passed to `depfile` - `@PLAINNAME@`: the input filename, without a path + - `@PLAINNAME0@` `@PLAINNAME1@` `...` *(since 1.5.0)*: the input filename without a path, with the specified array index in `input` - `@BASENAME@`: the input filename, with extension removed + - `@BASENAME0@` `@BASENAME1@` `...` *(since 1.5.0)*: the input filename with extension removed, with the specified array index in `input` - `@PRIVATE_DIR@` *(since 0.50.1)*: path to a directory where the custom target must store all its intermediate files. - `@SOURCE_ROOT@`: the path to the root of the source tree. Depending on the backend, this may be an absolute or a relative to current workdir path. diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f6b4cf4abd1f..08bd054f20f0 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1983,17 +1983,23 @@ def func_vcs_tag(self, node: mparser.BaseNode, args: T.List['TYPE_var'], kwargs: def func_subdir_done(self, node: mparser.BaseNode, args: TYPE_var, kwargs: TYPE_kwargs) -> T.NoReturn: raise SubdirDoneRequest() - @staticmethod - def _validate_custom_target_outputs(has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None: + def _validate_custom_target_outputs(self, has_multi_in: bool, outputs: T.Iterable[str], name: str) -> None: """Checks for additional invalid values in a custom_target output. This cannot be done with typed_kwargs because it requires the number of inputs. """ + inregex: T.List[str] = ['@PLAINNAME[0-9]+@', '@BASENAME[0-9]+@'] + from ..utils.universal import iter_regexin_iter for out in outputs: + match = iter_regexin_iter(inregex, [out]) if has_multi_in and ('@PLAINNAME@' in out or '@BASENAME@' in out): raise InvalidArguments(f'{name}: output cannot contain "@PLAINNAME@" or "@BASENAME@" ' 'when there is more than one input (we can\'t know which to use)') + elif match: + FeatureNew.single_use( + f'{match} in output', '1.5.0', + self.subproject) @typed_pos_args('custom_target', optargs=[str]) @typed_kwargs( diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index ce9afd96be27..c831169c523d 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -1744,6 +1744,8 @@ def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T If there is more than one input file, the following keys are also created: @INPUT0@, @INPUT1@, ... one for each input file + @PLAINNAME0@, @PLAINNAME1@, ... one for each input file + @BASENAME0@, @BASENAME1@, ... one for each input file If there is more than one output file, the following keys are also created: @@ -1757,6 +1759,9 @@ def get_filenames_templates_dict(inputs: T.List[str], outputs: T.List[str]) -> T for (ii, vv) in enumerate(inputs): # Write out @INPUT0@, @INPUT1@, ... values[f'@INPUT{ii}@'] = vv + plain = os.path.basename(vv) + values[f'@PLAINNAME{ii}@'] = plain + values[f'@BASENAME{ii}@'] = os.path.splitext(plain)[0] if len(inputs) == 1: # Just one value, substitute @PLAINNAME@ and @BASENAME@ values['@PLAINNAME@'] = plain = os.path.basename(inputs[0]) diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 0f2622e35bbe..411c97b36036 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -287,6 +287,7 @@ def test_string_templates_substitution(self): outputs = [] ret = dictfunc(inputs, outputs) d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c', '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c'} # Check dictionary self.assertEqual(ret, d) @@ -309,6 +310,7 @@ def test_string_templates_substitution(self): outputs = ['out.c'] ret = dictfunc(inputs, outputs) d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c', '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': '.'} # Check dictionary @@ -330,6 +332,7 @@ def test_string_templates_substitution(self): outputs = ['dir/out.c'] ret = dictfunc(inputs, outputs) d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], + '@PLAINNAME0@': 'foo.c.in', '@BASENAME0@': 'foo.c', '@PLAINNAME@': 'foo.c.in', '@BASENAME@': 'foo.c', '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} # Check dictionary @@ -339,7 +342,9 @@ def test_string_templates_substitution(self): inputs = ['bar/foo.c.in', 'baz/foo.c.in'] outputs = [] ret = dictfunc(inputs, outputs) - d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1]} + d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in', + '@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c'} # Check dictionary self.assertEqual(ret, d) # Check substitutions @@ -376,6 +381,8 @@ def test_string_templates_substitution(self): outputs = ['dir/out.c'] ret = dictfunc(inputs, outputs) d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in', + '@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c', '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTDIR@': 'dir'} # Check dictionary self.assertEqual(ret, d) @@ -402,6 +409,8 @@ def test_string_templates_substitution(self): outputs = ['dir/out.c', 'dir/out2.c'] ret = dictfunc(inputs, outputs) d = {'@INPUT@': inputs, '@INPUT0@': inputs[0], '@INPUT1@': inputs[1], + '@PLAINNAME0@': 'foo.c.in', '@PLAINNAME1@': 'foo.c.in', + '@BASENAME0@': 'foo.c', '@BASENAME1@': 'foo.c', '@OUTPUT@': outputs, '@OUTPUT0@': outputs[0], '@OUTPUT1@': outputs[1], '@OUTDIR@': 'dir'} # Check dictionary From 8f88bbef7ca849d56c1cace942ee730ae9be3cfe Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 14 May 2024 18:57:53 -0400 Subject: [PATCH 853/855] CI: gentoo: explicitly install gdbus-codegen It is now getting uninstalled instead of updated, due to blockers on old glib. In fact, we explicitly need it... --- ci/ciimage/gentoo/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/ciimage/gentoo/install.sh b/ci/ciimage/gentoo/install.sh index 58749bc40037..6698ed565f30 100755 --- a/ci/ciimage/gentoo/install.sh +++ b/ci/ciimage/gentoo/install.sh @@ -24,6 +24,7 @@ pkgs_stable=( #dev-util/bindgen dev-libs/elfutils + dev-util/gdbus-codegen dev-libs/gobject-introspection dev-util/itstool dev-libs/protobuf From bfb9ca04529aea96c1c997a8d881ddc7df7d6c84 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 14 May 2024 19:56:04 -0400 Subject: [PATCH 854/855] CI: gentoo: make logs shorter by reducing progressbar --- ci/ciimage/gentoo/install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/ciimage/gentoo/install.sh b/ci/ciimage/gentoo/install.sh index 6698ed565f30..b2a697fcbc1e 100755 --- a/ci/ciimage/gentoo/install.sh +++ b/ci/ciimage/gentoo/install.sh @@ -115,6 +115,9 @@ cat <<-EOF >> /etc/portage/make.conf EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --autounmask-write --autounmask-continue --autounmask-keep-keywords=y --autounmask-use=y" EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --binpkg-respect-use=y" + # prevent painfully verbose Github Actions logs. + FETCHCOMMAND='wget --no-show-progress -t 3 -T 60 --passive-ftp -O "\\\${DISTDIR}/\\\${FILE}" "\\\${URI}"' + # Fortran is no longer enabled by default in 23.0, but we do need and use it. USE="\${USE} fortran" From 7d28ff29396f9d7043204de8ddc52226b9903811 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Wed, 15 May 2024 21:41:19 -0400 Subject: [PATCH 855/855] docs: fix description of cpp_eh=none We changed the behavior in #6116 but did not change the docs as well. Fixes #8233 --- docs/markdown/Builtin-options.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 64d16aba255a..b4039d646926 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -280,11 +280,11 @@ All these `_*` options are specified per machine. See below in the [specifying options per machine](#specifying-options-per-machine) section on how to do this in cross builds. -When using MSVC, `cpp_eh=none` will result in no exception flags being -passed, while the `cpp_eh=[value]` will result in `/EH[value]`. Since -*0.51.0* `cpp_eh=default` will result in `/EHsc` on MSVC. When using -gcc-style compilers, nothing is passed (allowing exceptions to work), -while `cpp_eh=none` passes `-fno-exceptions`. +When using MSVC, `cpp_eh=[value]` will result in `/EH[value]` being passed. +The magic value `none` translates to `s-c-` to disable exceptions. *Since +0.51.0* `default` translates to `sc`. When using gcc-style compilers, nothing +is passed (allowing exceptions to work), while `cpp_eh=none` passes +`-fno-exceptions`. Since *0.54.0* The `_thread_count` option can be used to control the value passed to `-s PTHREAD_POOL_SIZE` when using emcc. No other