summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xclaessens@netflix.com>2025-06-06 08:03:15 -0400
committerDylan Baker <dylan@pnwbakers.com>2025-08-01 07:55:49 -0700
commit56e84d35deef8aea2b0beda2ec14ca22334a7f0f (patch)
tree210aac22e3b450363c4cfd4538b6754f3a6fa6f7
parent095c852ef3cb93c5fb01ca44b1632d9dd2dae207 (diff)
downloadmeson-56e84d35deef8aea2b0beda2ec14ca22334a7f0f.tar.gz
wrap: wraps from subprojects can replace directories found with no wrap
If main project finds a directory subprojects/foo with no corresponding foo.wrap, it creates a dummy PackageDefinition for it. If we later find a subproject that has foo.wrap, replace the dummy wrap with it. This happens for example when wrap-redirect have been deleted. It also happens for subprojects downloaded from some Cargo.lock which does not create a wrap-redirect. Avoid loading the same location twice, which can happen when preparing cargo subprojects.
-rw-r--r--mesonbuild/wrap/wrap.py23
-rw-r--r--test cases/common/282 wrap override/meson.build8
-rw-r--r--test cases/common/282 wrap override/subprojects/sub/meson.build7
-rw-r--r--test cases/common/282 wrap override/subprojects/sub/subprojects/subsub.wrap5
-rw-r--r--test cases/common/282 wrap override/subprojects/subsub/meson.build5
5 files changed, 42 insertions, 6 deletions
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index a9d1b7bf6..1cc2cee61 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -354,6 +354,7 @@ class Resolver:
self.wrapdb: T.Dict[str, T.Any] = {}
self.wrapdb_provided_deps: T.Dict[str, str] = {}
self.wrapdb_provided_programs: T.Dict[str, str] = {}
+ self.loaded_dirs: T.Set[str] = set()
self.load_wraps()
self.load_netrc()
self.load_wrapdb()
@@ -395,6 +396,7 @@ class Resolver:
# Add provided deps and programs into our lookup tables
for wrap in self.wraps.values():
self.add_wrap(wrap)
+ self.loaded_dirs.add(self.subdir)
def add_wrap(self, wrap: PackageDefinition) -> None:
for k in wrap.provided_deps.keys():
@@ -439,16 +441,25 @@ class Resolver:
def _merge_wraps(self, other_resolver: 'Resolver') -> None:
for k, v in other_resolver.wraps.items():
- self.wraps.setdefault(k, v)
- for k, v in other_resolver.provided_deps.items():
- self.provided_deps.setdefault(k, v)
- for k, v in other_resolver.provided_programs.items():
- self.provided_programs.setdefault(k, v)
+ prev_wrap = self.wraps.get(v.directory)
+ if prev_wrap and prev_wrap.type is None and v.type is not None:
+ # This happens when a subproject has been previously downloaded
+ # using a wrap from another subproject and the wrap-redirect got
+ # deleted. In that case, the main project created a bare wrap
+ # for the download directory, but now we have a proper wrap.
+ # It also happens for wraps coming from Cargo.lock files, which
+ # don't create wrap-redirect.
+ del self.wraps[v.directory]
+ del self.provided_deps[v.directory]
+ if k not in self.wraps:
+ self.wraps[k] = v
+ self.add_wrap(v)
def load_and_merge(self, subdir: str, subproject: SubProject) -> None:
- if self.wrap_mode != WrapMode.nopromote:
+ if self.wrap_mode != WrapMode.nopromote and subdir not in self.loaded_dirs:
other_resolver = Resolver(self.source_dir, subdir, subproject, self.wrap_mode, self.wrap_frontend, self.allow_insecure, self.silent)
self._merge_wraps(other_resolver)
+ self.loaded_dirs.add(subdir)
def find_dep_provider(self, packagename: str) -> T.Tuple[T.Optional[str], T.Optional[str]]:
# Python's ini parser converts all key values to lowercase.
diff --git a/test cases/common/282 wrap override/meson.build b/test cases/common/282 wrap override/meson.build
new file mode 100644
index 000000000..76c84d6a1
--- /dev/null
+++ b/test cases/common/282 wrap override/meson.build
@@ -0,0 +1,8 @@
+project('wrap override')
+
+
+subproject('sub')
+
+# sub has subsub.wrap that provides subsub-1.0 dependency. Even if sub itself
+# does not use it, that dependency should now be available.
+dependency('subsub-1.0')
diff --git a/test cases/common/282 wrap override/subprojects/sub/meson.build b/test cases/common/282 wrap override/subprojects/sub/meson.build
new file mode 100644
index 000000000..abefb30fc
--- /dev/null
+++ b/test cases/common/282 wrap override/subprojects/sub/meson.build
@@ -0,0 +1,7 @@
+project('sub')
+
+# Simulate an optional feature that requires subsub.wrap, but that feature is
+# not enabled.
+if false
+ dependency('subsub-1.0')
+endif
diff --git a/test cases/common/282 wrap override/subprojects/sub/subprojects/subsub.wrap b/test cases/common/282 wrap override/subprojects/sub/subprojects/subsub.wrap
new file mode 100644
index 000000000..85a1a7c51
--- /dev/null
+++ b/test cases/common/282 wrap override/subprojects/sub/subprojects/subsub.wrap
@@ -0,0 +1,5 @@
+[wrap-file]
+
+
+[provide]
+dependency_names = subsub-1.0
diff --git a/test cases/common/282 wrap override/subprojects/subsub/meson.build b/test cases/common/282 wrap override/subprojects/subsub/meson.build
new file mode 100644
index 000000000..668dcb3b0
--- /dev/null
+++ b/test cases/common/282 wrap override/subprojects/subsub/meson.build
@@ -0,0 +1,5 @@
+project('sub')
+
+# This simulates a subproject we previously downloaded using
+# subproject/sub/subproject/subsub.wrap
+meson.override_dependency('subsub-1.0', declare_dependency())