cmake: tolerate an unreadable $HOME when probing the user package registry

CMakeDependency._preliminary_find_check looks for ~/.cmake/packages/<Name>
with Path.exists(), which only swallows ENOENT/ENOTDIR/EBADF/ELOOP. On a
host where the build user's home directory exists but is not traversable
(CI service accounts, a root-owned 0700 $HOME, HOME pointing at another
user's directory) the probe raises PermissionError and meson setup dies
with "Unhandled python OSError" on the first dependency() that reaches the
CMake finder.

CMake itself silently ignores an unreadable user package registry. Do the
same: route the check through the existing _cached_isdir helper, which
already turns OSError into "not found".

The path is built with os.path.expanduser() rather than Path.home().
Path.home() raises RuntimeError when the home directory cannot be
determined (HOME unset and no passwd entry for the uid, as in containers
running under an arbitrary uid), so it would have needed its own handler
for a case that should also just mean "not registered".
os.path.expanduser() returns the string unchanged in that case, and a
path starting with '~' is never an existing directory, so no extra
handling is needed.
This commit is contained in:
Christian Häggström authored and Paolo Bonzini committed 2026-10-13 12:38:20 +02:00
1 parent 3e4cc8d237
commit b3efc56536
2 files changed
+18 -5

No files matched your search

+5 -5
View File
@@ -331,12 +331,12 @@ class CMakeDependency(ExternalDependency):
return True
# Check the Linux CMake registry
linux_reg = Path.home() / '.cmake' / 'packages'
for p in [linux_reg / name, linux_reg / lname]:
if p.exists():
return True
return self._in_cmake_user_registry(name, lname)
return False
@staticmethod
def _in_cmake_user_registry(name: str, lname: str) -> bool:
# Like CMake, treat an unreadable or unresolvable home as "not registered".
return any(CMakeDependency._cached_isdir(os.path.expanduser(f'~/.cmake/packages/{n}')) for n in (name, lname))
def _detect_dep(self, name: str, package_version: str, modules: T.List[T.Tuple[str, bool]], components: T.List[T.Tuple[str, bool]], args: T.List[str]) -> None:
# Detect a dependency with CMake using the '--find-package' mode
+13
View File
@@ -65,6 +65,19 @@ from .helpers import IS_CI, chdir, skipIfNoPkgconfig
class InternalTests(unittest.TestCase):
@unittest.skipIf(is_windows() or is_cygwin() or os.geteuid() == 0, 'needs a directory the test user cannot traverse')
def test_cmake_user_registry_unreadable_home(self):
from mesonbuild.dependencies.cmake import CMakeDependency
with tempfile.TemporaryDirectory() as tmpdir:
home = Path(tmpdir) / 'home'
(home / '.cmake' / 'packages' / 'Foo').mkdir(parents=True)
with mock.patch.dict(os.environ, {'HOME': str(home)}):
self.assertTrue(CMakeDependency._in_cmake_user_registry('Foo', 'foo'))
self.assertFalse(CMakeDependency._in_cmake_user_registry('Bar', 'bar'))
home.chmod(0)
CMakeDependency._cached_isdir.cache_clear()
self.assertFalse(CMakeDependency._in_cmake_user_registry('Foo', 'foo'))
def test_cmake_skip_compiler_test_invalid(self):
properties = mesonbuild.envconfig.Properties({'cmake_skip_compiler_test': True})
with self.assertRaisesRegex(