From cdc4f8a5f5d880dfd1cefd639ce35a353e908e80 Mon Sep 17 00:00:00 2001
From: Andrew Dunstan <andrew@dunslane.net>
Date: Mon, 13 Jul 2026 10:50:54 -0400
Subject: [PATCH] meson: Avoid PATH bloat from NLS .mo targets in tmp_install
 test setup

On Windows, meson's test() 'depends:' kwarg feeds every listed target
unconditionally into determine_windows_extra_paths()
(mesonbuild/backend/backends.py), which adds each one's build directory
to the test's PATH so that any DLL it needs can be found at runtime
(Windows has no rpath equivalent). This isn't limited to targets that
actually produce a DLL - any target reachable through 'depends:' gets a
PATH entry, whether or not it's relevant to library loading.

The 'tmp_install' test setup depends on installed_targets, which
includes nls_mo_targets: one custom_target per locale/domain of compiled
.mo message catalogs. With NLS enabled, that's several hundred targets,
none of which are DLLs and none of which are ever looked up via PATH.
Each one still gets its own PATH entry, and the aggregate is large
enough (in local testing, around 39000 characters across 584 entries,
448 of them po/*/LC_MESSAGES directories) to exceed practical Windows
environment-variable/command-line length limits. The result is that the
'tmp_install' and 'initdb_cache' setup tests fail immediately with exit
status 1 and no diagnostic output at all, since the failure happens
before the child process can produce anything on stdout/stderr.

Fix this by depending on a trivial stamp custom_target instead of
installed_targets directly. Its own 'depends:' still forces
installed_targets to build before it runs, preserving correct ordering,
but because a custom_target is not a build.BuildTarget,
determine_windows_extra_paths() does not recurse into its dependencies
- it contributes at most its own single, harmless output directory to
PATH instead of hundreds of real ones.

alias_target() would achieve the same non-recursion (the function only
expands prospectives that are build.BuildTarget instances, and
AliasTarget isn't one), but test()'s 'depends:' kwarg is typechecked to
accept only BuildTarget | CustomTarget | CustomTargetIndex, and rejects
AliasTarget outright.
---
 meson.build | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index d88a7a7..659ee2a 100644
--- a/meson.build
+++ b/meson.build
@@ -3865,13 +3865,26 @@ meson_install_args = meson_args + ['install'] + {
 # setup tests should be run first,
 # so define priority for these
 setup_tests_priority = 100
+
+# Depend on a single stamp custom_target rather than the raw
+# installed_targets list directly, so that on Windows this test's PATH
+# doesn't get one entry per target in installed_targets (including the
+# hundreds of per-locale NLS .mo directories). This still forces
+# installed_targets to build first.
+installed_targets_stamp = custom_target('installed-targets-stamp',
+  output: 'installed-targets-stamp',
+  command: [python, '-c', 'pass'],
+  depends: installed_targets,
+  build_always_stale: true,
+)
+
 test('tmp_install',
     meson_bin, args: meson_install_args ,
     env: {'DESTDIR':test_install_destdir},
     priority: setup_tests_priority,
     timeout: 300,
     is_parallel: false,
-    depends: installed_targets,
+    depends: installed_targets_stamp,
     suite: ['setup'])
 
 test('install_test_files',
-- 
2.54.0.windows.1

