Resolved an issue where the LDF selected an incorrect library version // Resolve #4860

This commit is contained in:
Ivan Kravets
2024-02-13 19:32:57 +02:00
parent 2239616484
commit e1ff9a469d
4 changed files with 60 additions and 11 deletions

View File

@ -21,8 +21,9 @@ test-driven methodologies, and modern toolchains for unrivaled success.
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
* Broadened version support for the ``pyelftools`` dependency, enabling compatibility with lower versions and facilitating integration with a wider range of third-party tools (`issue #4834 <https://github.com/platformio/platformio-core/issues/4834>`_) * Broadened version support for the ``pyelftools`` dependency, enabling compatibility with lower versions and facilitating integration with a wider range of third-party tools (`issue #4834 <https://github.com/platformio/platformio-core/issues/4834>`_)
* Resolved an issue related to the relative package path in the `pio pkg publish <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_publish.html>`__ command
* Addressed an issue where passing a relative path (``--project-dir``) to the `pio project init <https://docs.platformio.org/en/latest/core/userguide/project/cmd_init.html>`__ command resulted in an error (`issue #4847 <https://github.com/platformio/platformio-core/issues/4847>`_) * Addressed an issue where passing a relative path (``--project-dir``) to the `pio project init <https://docs.platformio.org/en/latest/core/userguide/project/cmd_init.html>`__ command resulted in an error (`issue #4847 <https://github.com/platformio/platformio-core/issues/4847>`_)
* Resolved an issue related to the relative package path in the `pio pkg publish <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_publish.html>`__ command
* Resolved an issue where the |LDF| selected an incorrect library version (`issue #4860 <https://github.com/platformio/platformio-core/issues/4860>`_)
6.1.13 (2024-01-12) 6.1.13 (2024-01-12)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~

View File

@ -309,10 +309,10 @@ class LibBuilderBase:
if not self.dependencies or self._deps_are_processed: if not self.dependencies or self._deps_are_processed:
return return
self._deps_are_processed = True self._deps_are_processed = True
for item in self.dependencies: for dependency in self.dependencies:
found = False found = False
for lb in self.env.GetLibBuilders(): for lb in self.env.GetLibBuilders():
if item["name"] != lb.name: if not lb.is_dependency_compatible(dependency):
continue continue
found = True found = True
if lb not in self.depbuilders: if lb not in self.depbuilders:
@ -322,9 +322,20 @@ class LibBuilderBase:
if not found and self.verbose: if not found and self.verbose:
sys.stderr.write( sys.stderr.write(
"Warning: Ignored `%s` dependency for `%s` " "Warning: Ignored `%s` dependency for `%s` "
"library\n" % (item["name"], self.name) "library\n" % (dependency["name"], self.name)
) )
def is_dependency_compatible(self, dependency):
pkg = PackageItem(self.path)
qualifiers = {"name": self.name, "version": self.version}
if pkg.metadata:
qualifiers = {"name": pkg.metadata.name, "version": pkg.metadata.version}
if pkg.metadata.spec and pkg.metadata.spec.owner:
qualifiers["owner"] = pkg.metadata.spec.owner
return PackageCompatibility.from_dependency(dependency).is_compatible(
PackageCompatibility(**qualifiers)
)
def get_search_files(self): def get_search_files(self):
return [ return [
os.path.join(self.src_dir, item) os.path.join(self.src_dir, item)

View File

@ -99,7 +99,11 @@ class PackageManagerInstallMixin:
pkg = self.install_from_registry( pkg = self.install_from_registry(
spec, spec,
search_qualifiers=( search_qualifiers=(
compatibility.to_search_qualifiers() if compatibility else None compatibility.to_search_qualifiers(
["platforms", "frameworks", "authors"]
)
if compatibility
else None
), ),
) )

View File

@ -65,7 +65,14 @@ class PackageType:
class PackageCompatibility: class PackageCompatibility:
KNOWN_QUALIFIERS = ("platforms", "frameworks", "authors") KNOWN_QUALIFIERS = (
"owner",
"name",
"version",
"platforms",
"frameworks",
"authors",
)
@classmethod @classmethod
def from_dependency(cls, dependency): def from_dependency(cls, dependency):
@ -89,19 +96,45 @@ class PackageCompatibility:
def __repr__(self): def __repr__(self):
return "PackageCompatibility <%s>" % self.qualifiers return "PackageCompatibility <%s>" % self.qualifiers
def to_search_qualifiers(self): def to_search_qualifiers(self, fields=None):
return self.qualifiers result = {}
for name, value in self.qualifiers.items():
if not fields or name in fields:
result[name] = value
return result
def is_compatible(self, other): def is_compatible(self, other):
assert isinstance(other, PackageCompatibility) assert isinstance(other, PackageCompatibility)
for key, value in self.qualifiers.items(): for key, current_value in self.qualifiers.items():
other_value = other.qualifiers.get(key) other_value = other.qualifiers.get(key)
if not value or not other_value: if not current_value or not other_value:
continue continue
if not items_in_list(value, other_value): if any(isinstance(v, list) for v in (current_value, other_value)):
if not items_in_list(current_value, other_value):
return False
continue
if key == "version":
if not self._compare_versions(current_value, other_value):
return False
continue
if current_value != other_value:
return False return False
return True return True
def _compare_versions(self, current, other):
if current == other:
return True
try:
version = (
other
if isinstance(other, semantic_version.Version)
else cast_version_to_semver(other)
)
return version in semantic_version.SimpleSpec(current)
except ValueError:
pass
return False
class PackageOutdatedResult: class PackageOutdatedResult:
UPDATE_INCREMENT_MAJOR = "major" UPDATE_INCREMENT_MAJOR = "major"