From: George Sapkin Date: Thu, 25 Dec 2025 13:32:29 +0000 (+0200) Subject: build: add support for virtual provides X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=5ed650acbfd9cfbfd6a381df7db060c9153bacfc;p=openwrt%2Fopenwrt.git build: add support for virtual provides Allow defining virtual provides using the PROVIDES field by prefixing them with @, e.g.: PROVIDES:=@ca-certs Virtual provides don't own the provided name and multiple packages with the same virtual provides can be installed side-by-side. Packages must still take care not to override each other's files. Add an implicit self-provide to packages. apk can't handle self provides, be it versioned or virtual, so opt for a suffix instead. This allows several variants to provide the same virtual package without adding extra provides to the default one, e.g. wget implicitly provides wget-any and is marked as default, so wget-ssl can explicitly provide @wget-any as well. Filter out virtual provides when generating metadata. Filter out virtual provides prefix and self provide where appropriate. Signed-off-by: George Sapkin Link: https://github.com/openwrt/openwrt/pull/21288 Signed-off-by: Robert Marko --- diff --git a/include/package-pack.mk b/include/package-pack.mk index 7080b8362b..853832d90f 100644 --- a/include/package-pack.mk +++ b/include/package-pack.mk @@ -78,6 +78,25 @@ define FixupDependencies $(call AddDependency,$(1),$$(DEPS)) endef +# Format provide and add ABI and version if it's not a virtual provide marked +# with an @. +# +# 1: provide name +# 2: provide version +# 3: (optional) ABI preformatted by FormatABISuffix +define AddProvide +$(if $(filter @%,$(1)),$(patsubst @%,%,$(1)),$(1)$(3)=$(2)) +endef + +# Remove virtual provides prefix and self. apk doesn't like it when packages +# specify a redundant provide pointing to self. +# +# 1: package name +# 2: list of provides +define SanitizeProvides +$(filter-out $(1),$(patsubst @%,%,$(2))) +endef + # Format provides both for apk and control # # - If ABI version is defined: @@ -108,16 +127,33 @@ endef # this implies that only one version of a provide can be installed at the # same time # +# - Both with and without an ABI, if a provide starts with an @, treat it as a +# virtual provide, that doesn't own the name by not appending version. +# Multiple packages with the same virtual provides can be installed +# side-by-side. +# +# - apk doesn't like it when packages specify a redundant provide pointing to +# self. Filter it out, but keep virtual self provides, in the form of +# @${package_name}-any. +# +# - Packages implicitly add a virtual @${package_name}-any provide in Package. +# # 1: package name # 2: package version # 3: list of provides # 4: list of alternatives define FormatProvides $(strip $(if $(ABIV_$(1)), \ - $(1) $(foreach provide,$(3), $(provide)$(ABIV_$(1))=$(2)), \ + $(1) $(foreach provide, \ + $(filter-out $(1),$(3)), \ + $(call AddProvide,$(provide),$(2),$(ABIV_$(1))) \ + ), \ $(if $(4), \ - $(3), \ - $(foreach provide,$(3), $(provide)=$(2)) \ + $(filter-out $(1),$(3)), \ + $(foreach provide, \ + $(filter-out $(1),$(3)), \ + $(call AddProvide,$(provide),$(2)) \ + ) \ ) \ )) endef @@ -237,7 +273,7 @@ endif $(if $(ABI_VERSION),echo '$(ABI_VERSION)' | cmp -s - $(PKG_INFO_DIR)/$(1).version || { \ mkdir -p $(PKG_INFO_DIR); \ echo '$(ABI_VERSION)' > $(PKG_INFO_DIR)/$(1).version; \ - $(foreach pkg,$(filter-out $(1),$(PROVIDES)), \ + $(foreach pkg,$(call SanitizeProvides,$(1),$(PROVIDES)), \ cp $(PKG_INFO_DIR)/$(1).version $(PKG_INFO_DIR)/$(pkg).version; \ ) \ } ) @@ -336,7 +372,7 @@ endif fi; \ done; $(Package/$(1)/extra_provides) \ ) | sort -u > $(PKG_INFO_DIR)/$(1).provides - $(if $(PROVIDES),@for pkg in $(filter-out $(1),$(PROVIDES)); do cp $(PKG_INFO_DIR)/$(1).provides $(PKG_INFO_DIR)/$$$$pkg.provides; done) + $(if $(PROVIDES),@for pkg in $(call SanitizeProvides,$(1),$(PROVIDES)); do cp $(PKG_INFO_DIR)/$(1).provides $(PKG_INFO_DIR)/$$$$pkg.provides; done) $(CheckDependencies) $(RSTRIP) $$(IDIR_$(1)) diff --git a/include/package.mk b/include/package.mk index 5392bdf465..087e374ea9 100644 --- a/include/package.mk +++ b/include/package.mk @@ -332,6 +332,13 @@ define BuildPackage $(eval $(Package/Default)) $(eval $(Package/$(1))) + # Add an implicit self-provide. apk can't handle self provides, be it + # versioned or virtual, so opt for a suffix instead. This allows several + # variants to provide the same virtual package without adding extra provides + # to the default one, e.g. wget implicitly provides wget-any and is marked as + # default, so wget-ssl can explicitly provide @wget-any as well. + PROVIDES+=@$(1)-any + ifdef DESCRIPTION $$(error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description) endif diff --git a/scripts/metadata.pm b/scripts/metadata.pm index dec9e62dff..6cb63608d2 100644 --- a/scripts/metadata.pm +++ b/scripts/metadata.pm @@ -263,6 +263,9 @@ sub parse_package_metadata($) { /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; /^Provides: \s*(.+)\s*$/ and do { my @vpkg = split /\s+/, $1; + foreach (@vpkg) { + s/^@//; + } @{$pkg->{provides}} = ($pkg->{name}, @vpkg); foreach my $vpkg (@vpkg) { next if ($vpkg eq $pkg->{name});