[LEDE-DEV,v2] scripts: metadata: always resolve dependencies through provides list

Message ID 9bcf023216b3cf79d242d9501d13128d6b27aeec.1499541369.git.mschiffer@universe-factory.net
State Not Applicable
Delegated to: Matthias Schiffer
Headers show

Commit Message

Matthias Schiffer July 8, 2017, 7:18 p.m.
Instead of adding virtual packages to the normal package list, keep a
separate list for provides, make each package provide itself, and resolve
all dependencies through this list. This allows to use PROVIDES to replace
existing packages.

A side effect of the changes in the makefile dependency logic is that
build dependencies are now always interpreted as source package names,
instead of putting build and runtime dependencies into the same list.

Fixes FS#837.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---

v2: Fixed an issue that caused syntax errors in .config-package.in for
dependencies on on-existing packages (the new version will generate an
unsatisfiable dependency, which is probably the best way we can handle
this)


 scripts/feeds               |   3 --
 scripts/metadata.pm         |  17 +++----
 scripts/package-metadata.pl | 121 +++++++++++++++++++++-----------------------
 3 files changed, 67 insertions(+), 74 deletions(-)

Comments

Matthias Schiffer July 8, 2017, 8:07 p.m. | #1
On 07/08/2017 09:18 PM, Matthias Schiffer wrote:
> Instead of adding virtual packages to the normal package list, keep a
> separate list for provides, make each package provide itself, and resolve
> all dependencies through this list. This allows to use PROVIDES to replace
> existing packages.
> 
> A side effect of the changes in the makefile dependency logic is that
> build dependencies are now always interpreted as source package names,
> instead of putting build and runtime dependencies into the same list.
> 
> Fixes FS#837.
> 
> Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
> ---
> 
> v2: Fixed an issue that caused syntax errors in .config-package.in for
> dependencies on on-existing packages (the new version will generate an
I meant to write *non-existing*.

> unsatisfiable dependency, which is probably the best way we can handle
> this)
> 
> 
>  scripts/feeds               |   3 --
>  scripts/metadata.pm         |  17 +++----
>  scripts/package-metadata.pl | 121 +++++++++++++++++++++-----------------------
>  3 files changed, 67 insertions(+), 74 deletions(-)
> 
> diff --git a/scripts/feeds b/scripts/feeds
> index 55c294ad0a..a38eb45458 100755
> --- a/scripts/feeds
> +++ b/scripts/feeds
> @@ -252,7 +252,6 @@ sub search_feed {
>  		my $substr;
>  		my $pkgmatch = 1;
>  
> -		next if $pkg->{vdepends};
>  		foreach my $substr (@substr) {
>  			my $match;
>  			foreach my $key (qw(name title description src)) {
> @@ -306,7 +305,6 @@ sub list_feed {
>  	get_feed($feed);
>  	foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
>  		my $pkg = $feed_package->{$name};
> -		next if $pkg->{vdepends};
>  		if($pkg->{name}) {
>  			printf "\%-32s\t\%s\n", $pkg->{name}, $pkg->{title};
>  		}
> @@ -588,7 +586,6 @@ sub install {
>  				get_feed($f->[1]);
>  				foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
>  					my $p = $feed_package->{$name};
> -					next if $p->{vdepends};
>  					if( $p->{name} ) {
>  						install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1;
>  						get_feed($f->[1]);
> diff --git a/scripts/metadata.pm b/scripts/metadata.pm
> index d446892e2b..8f5af40f14 100644
> --- a/scripts/metadata.pm
> +++ b/scripts/metadata.pm
> @@ -2,9 +2,10 @@ package metadata;
>  use base 'Exporter';
>  use strict;
>  use warnings;
> -our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore %usernames %groupnames);
> +our @EXPORT = qw(%package %vpackage %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore %usernames %groupnames);
>  
>  our %package;
> +our %vpackage;
>  our %preconfig;
>  our %srcpackage;
>  our %category;
> @@ -181,6 +182,7 @@ sub clear_packages() {
>  	%subdir = ();
>  	%preconfig = ();
>  	%package = ();
> +	%vpackage = ();
>  	%srcpackage = ();
>  	%category = ();
>  	%features = ();
> @@ -238,6 +240,9 @@ sub parse_package_metadata($) {
>  			$pkg->{override} = $override;
>  			$package{$1} = $pkg;
>  			push @{$srcpackage{$src}}, $pkg;
> +
> +			$vpackage{$1} or $vpackage{$1} = [];
> +			unshift @{$vpackage{$1}}, $1;
>  		};
>  		/^Feature:\s*(.+?)\s*$/ and do {
>  			undef $pkg;
> @@ -269,14 +274,8 @@ sub parse_package_metadata($) {
>  		/^Provides: \s*(.+)\s*$/ and do {
>  			my @vpkg = split /\s+/, $1;
>  			foreach my $vpkg (@vpkg) {
> -				$package{$vpkg} or $package{$vpkg} = {
> -					name => $vpkg,
> -					vdepends => [],
> -					src => $src,
> -					subdir => $subdir,
> -					makefile => $makefile
> -				};
> -				push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
> +				$vpackage{$vpkg} or $vpackage{$vpkg} = [];
> +				push @{$vpackage{$vpkg}}, $pkg->{name};
>  			}
>  		};
>  		/^Menu-Depends: \s*(.+)\s*$/ and $pkg->{mdepends} = [ split /\s+/, $1 ];
> diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl
> index d4100c1726..902f7807bd 100755
> --- a/scripts/package-metadata.pl
> +++ b/scripts/package-metadata.pl
> @@ -101,14 +101,16 @@ my %dep_check;
>  sub __find_package_dep($$) {
>  	my $pkg = shift;
>  	my $name = shift;
> -	my $deps = ($pkg->{vdepends} or $pkg->{depends});
> +	my $deps = $pkg->{depends};
>  
>  	return 0 unless defined $deps;
> -	foreach my $dep (@{$deps}) {
> -		next if $dep_check{$dep};
> -		$dep_check{$dep} = 1;
> -		return 1 if $dep eq $name;
> -		return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
> +	foreach my $vpkg (@{$deps}) {
> +		foreach my $dep (@{$vpackage{$vpkg}}) {
> +			next if $dep_check{$dep};
> +			$dep_check{$dep} = 1;
> +			return 1 if $dep eq $name;
> +			return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
> +		}
>  	}
>  	return 0;
>  }
> @@ -156,7 +158,6 @@ sub mconf_depends {
>  		my $m = "depends on";
>  		my $flags = "";
>  		$depend =~ s/^([@\+]+)// and $flags = $1;
> -		my $vdep;
>  		my $condition = $parent_condition;
>  
>  		next if $condition eq $depend;
> @@ -173,9 +174,9 @@ sub mconf_depends {
>  			}
>  			$depend = $2;
>  		}
> -		next if $package{$depend} and $package{$depend}->{buildonly};
>  		if ($flags =~ /\+/) {
> -			if ($vdep = $package{$depend}->{vdepends}) {
> +			my $vdep = $vpackage{$depend};
> +			if ($vdep and @$vdep > 0) {
>  				my @vdeps;
>  				$depend = undef;
>  
> @@ -209,7 +210,8 @@ sub mconf_depends {
>  
>  			$flags =~ /@/ or $depend = "PACKAGE_$depend";
>  		} else {
> -			if ($vdep = $package{$depend}->{vdepends}) {
> +			my $vdep = $vpackage{$depend};
> +			if ($vdep and @$vdep > 0) {
>  				$depend = join("||", map { "PACKAGE_".$_ } @$vdep);
>  			} else {
>  				$flags =~ /@/ or $depend = "PACKAGE_$depend";
> @@ -413,7 +415,6 @@ sub get_conditional_dep($$) {
>  
>  sub gen_package_mk() {
>  	my %conf;
> -	my %dep;
>  	my %done;
>  	my $line;
>  
> @@ -423,8 +424,6 @@ sub gen_package_mk() {
>  		my $pkg = $package{$name};
>  		my @srcdeps;
>  
> -		next if defined $pkg->{vdepends};
> -
>  		$config = "\$(CONFIG_PACKAGE_$name)";
>  		if ($config) {
>  			$pkg->{buildonly} and $config = "";
> @@ -445,16 +444,7 @@ sub gen_package_mk() {
>  			print "buildtypes-$pkg->{subdir}$pkg->{src} = ".join(' ', @{$pkg->{buildtypes}})."\n";
>  		}
>  
> -		foreach my $spkg (@{$srcpackage{$pkg->{src}}}) {
> -			foreach my $dep (@{$spkg->{depends}}, @{$spkg->{builddepends}}) {
> -				$dep =~ /@/ or do {
> -					$dep =~ s/\+//g;
> -					push @srcdeps, $dep;
> -				};
> -			}
> -		}
>  		foreach my $type (@{$pkg->{buildtypes}}) {
> -			my @extra_deps;
>  			my %deplines;
>  
>  			next unless $pkg->{"builddepends/$type"};
> @@ -492,63 +482,70 @@ sub gen_package_mk() {
>  			}
>  		}
>  
> -		my $hasdeps = 0;
>  		my %deplines;
> -		foreach my $deps (@srcdeps) {
> -			my $idx;
> -			my $condition;
> -			my $prefix = "";
> -			my $suffix = "";
> -
> -			if ($deps =~ /^(.+):(.+)/) {
> -				$condition = $1;
> -				$deps = $2;
> -			}
> -			if ($deps =~ /^(.+)(\/.+)/) {
> -				$deps = $1;
> -				$suffix = $2;
> -			}
> +		foreach my $spkg (@{$srcpackage{$pkg->{src}}}) {
> +			foreach my $bdep (@{$spkg->{builddepends}}) {
> +				my $condition;
> +				my $suffix = "";
>  
> -			my $pkg_dep = $package{$deps};
> -			my @deps;
> +				if ($bdep =~ /^(.+):(.+)/) {
> +					$condition = $1;
> +					$bdep = $2;
> +				}
> +				if ($bdep =~ /^(.+)(\/.+)/) {
> +					$bdep = $1;
> +					$suffix = $2;
> +				}
>  
> -			if ($pkg_dep->{vdepends}) {
> -				@deps = @{$pkg_dep->{vdepends}};
> -			} else {
> -				@deps = ($deps);
> +				next unless $subdir{$bdep};
> +				my $idx = $subdir{$bdep}.$bdep.$suffix;
> +
> +				my $depline = get_conditional_dep($condition, "\$(curdir)/$idx/compile");
> +				if ($depline) {
> +					$deplines{$depline}++;
> +				}
>  			}
>  
> -			foreach my $dep (@deps) {
> -				$pkg_dep = $package{$deps};
> -				if (defined $pkg_dep->{src}) {
> -					($pkg->{src} ne $pkg_dep->{src}.$suffix) and $idx = $pkg_dep->{subdir}.$pkg_dep->{src};
> -				} elsif (defined($srcpackage{$dep})) {
> -					$idx = $subdir{$dep}.$dep;
> +			foreach my $dep (@{$spkg->{depends}}) {
> +				my $condition;
> +				my $suffix = "";
> +
> +				next if $dep =~ /@/;
> +				$dep =~ s/\+//g;
> +
> +				if ($dep =~ /^(.+):(.+)/) {
> +					$condition = $1;
> +					$dep = $2;
>  				}
> -				undef $idx if $idx eq 'base-files';
> -				if ($idx) {
> -					$idx .= $suffix;
> +				if ($dep =~ /^(.+)(\/.+)/) {
> +					$dep = $1;
> +					$suffix = $2;
> +				}
> +
> +				next unless $vpackage{$dep};
> +
> +				my @vdeps = @{$vpackage{$dep}};
> +				foreach my $vdep (@vdeps) {
> +					my $pkg_dep = $package{$vdep};
>  
> -					my $depline;
> +					next unless $pkg_dep;
>  					next if $pkg->{src} eq $pkg_dep->{src}.$suffix;
> -					next if $dep{$condition.":".$pkg->{src}."->".$idx};
> -					next if $dep{$pkg->{src}."->($dep)".$idx} and $pkg_dep->{vdepends};
> -					my $depstr;
>  
> -					if ($pkg_dep->{vdepends}) {
> -						$depstr = "\$(if \$(CONFIG_PACKAGE_$dep),\$(curdir)/$idx/compile)";
> -						$dep{$pkg->{src}."->($dep)".$idx} = 1;
> +					my $idx = $pkg_dep->{subdir}.$pkg_dep->{src}.$suffix;
> +					my $depstr;
> +					if (@vdeps > 1) {
> +						$depstr = "\$(if \$(CONFIG_PACKAGE_$vdep),\$(curdir)/$idx/compile)";
>  					} else {
>  						$depstr = "\$(curdir)/$idx/compile";
> -						$dep{$pkg->{src}."->".$idx} = 1;
>  					}
> -					$depline = get_conditional_dep($condition, $depstr);
> +					my $depline = get_conditional_dep($condition, $depstr);
>  					if ($depline) {
>  						$deplines{$depline}++;
>  					}
>  				}
>  			}
>  		}
> +
>  		my $depline = join(" ", sort keys %deplines);
>  		if ($depline) {
>  			$line .= "\$(curdir)/".$pkg->{subdir}."$pkg->{src}/compile += $depline\n";
> @@ -573,7 +570,7 @@ ifndef DUMP_TARGET_DB
>  	( \\
>  $cmds \\
>  	) > \$@
> -	
> +
>  ifneq (\$(IMAGEOPT)\$(CONFIG_IMAGEOPT),)
>    package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig
>  endif
>
Matthias Schiffer July 20, 2017, 7:52 p.m. | #2
On 07/08/2017 09:18 PM, Matthias Schiffer wrote:
> Instead of adding virtual packages to the normal package list, keep a
> separate list for provides, make each package provide itself, and resolve
> all dependencies through this list. This allows to use PROVIDES to replace
> existing packages.
> 
> A side effect of the changes in the makefile dependency logic is that
> build dependencies are now always interpreted as source package names,
> instead of putting build and runtime dependencies into the same list.
> 
> Fixes FS#837.
> 
> Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>

The patch has been tested in Gluon for a while now and it seems to work
correctly. It may break some feed packages that are incorrectly specifying
binary instead of source package names in PKG_BUILD_DEPENDS; these packages
will need to be fixed when we notice them.

If nobody vetoes, I'd like to push it to master soon. The patch is also in
my staging tree for everybody to test.

Matthias

Patch

diff --git a/scripts/feeds b/scripts/feeds
index 55c294ad0a..a38eb45458 100755
--- a/scripts/feeds
+++ b/scripts/feeds
@@ -252,7 +252,6 @@  sub search_feed {
 		my $substr;
 		my $pkgmatch = 1;
 
-		next if $pkg->{vdepends};
 		foreach my $substr (@substr) {
 			my $match;
 			foreach my $key (qw(name title description src)) {
@@ -306,7 +305,6 @@  sub list_feed {
 	get_feed($feed);
 	foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
 		my $pkg = $feed_package->{$name};
-		next if $pkg->{vdepends};
 		if($pkg->{name}) {
 			printf "\%-32s\t\%s\n", $pkg->{name}, $pkg->{title};
 		}
@@ -588,7 +586,6 @@  sub install {
 				get_feed($f->[1]);
 				foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) {
 					my $p = $feed_package->{$name};
-					next if $p->{vdepends};
 					if( $p->{name} ) {
 						install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1;
 						get_feed($f->[1]);
diff --git a/scripts/metadata.pm b/scripts/metadata.pm
index d446892e2b..8f5af40f14 100644
--- a/scripts/metadata.pm
+++ b/scripts/metadata.pm
@@ -2,9 +2,10 @@  package metadata;
 use base 'Exporter';
 use strict;
 use warnings;
-our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore %usernames %groupnames);
+our @EXPORT = qw(%package %vpackage %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore %usernames %groupnames);
 
 our %package;
+our %vpackage;
 our %preconfig;
 our %srcpackage;
 our %category;
@@ -181,6 +182,7 @@  sub clear_packages() {
 	%subdir = ();
 	%preconfig = ();
 	%package = ();
+	%vpackage = ();
 	%srcpackage = ();
 	%category = ();
 	%features = ();
@@ -238,6 +240,9 @@  sub parse_package_metadata($) {
 			$pkg->{override} = $override;
 			$package{$1} = $pkg;
 			push @{$srcpackage{$src}}, $pkg;
+
+			$vpackage{$1} or $vpackage{$1} = [];
+			unshift @{$vpackage{$1}}, $1;
 		};
 		/^Feature:\s*(.+?)\s*$/ and do {
 			undef $pkg;
@@ -269,14 +274,8 @@  sub parse_package_metadata($) {
 		/^Provides: \s*(.+)\s*$/ and do {
 			my @vpkg = split /\s+/, $1;
 			foreach my $vpkg (@vpkg) {
-				$package{$vpkg} or $package{$vpkg} = {
-					name => $vpkg,
-					vdepends => [],
-					src => $src,
-					subdir => $subdir,
-					makefile => $makefile
-				};
-				push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
+				$vpackage{$vpkg} or $vpackage{$vpkg} = [];
+				push @{$vpackage{$vpkg}}, $pkg->{name};
 			}
 		};
 		/^Menu-Depends: \s*(.+)\s*$/ and $pkg->{mdepends} = [ split /\s+/, $1 ];
diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl
index d4100c1726..902f7807bd 100755
--- a/scripts/package-metadata.pl
+++ b/scripts/package-metadata.pl
@@ -101,14 +101,16 @@  my %dep_check;
 sub __find_package_dep($$) {
 	my $pkg = shift;
 	my $name = shift;
-	my $deps = ($pkg->{vdepends} or $pkg->{depends});
+	my $deps = $pkg->{depends};
 
 	return 0 unless defined $deps;
-	foreach my $dep (@{$deps}) {
-		next if $dep_check{$dep};
-		$dep_check{$dep} = 1;
-		return 1 if $dep eq $name;
-		return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
+	foreach my $vpkg (@{$deps}) {
+		foreach my $dep (@{$vpackage{$vpkg}}) {
+			next if $dep_check{$dep};
+			$dep_check{$dep} = 1;
+			return 1 if $dep eq $name;
+			return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
+		}
 	}
 	return 0;
 }
@@ -156,7 +158,6 @@  sub mconf_depends {
 		my $m = "depends on";
 		my $flags = "";
 		$depend =~ s/^([@\+]+)// and $flags = $1;
-		my $vdep;
 		my $condition = $parent_condition;
 
 		next if $condition eq $depend;
@@ -173,9 +174,9 @@  sub mconf_depends {
 			}
 			$depend = $2;
 		}
-		next if $package{$depend} and $package{$depend}->{buildonly};
 		if ($flags =~ /\+/) {
-			if ($vdep = $package{$depend}->{vdepends}) {
+			my $vdep = $vpackage{$depend};
+			if ($vdep and @$vdep > 0) {
 				my @vdeps;
 				$depend = undef;
 
@@ -209,7 +210,8 @@  sub mconf_depends {
 
 			$flags =~ /@/ or $depend = "PACKAGE_$depend";
 		} else {
-			if ($vdep = $package{$depend}->{vdepends}) {
+			my $vdep = $vpackage{$depend};
+			if ($vdep and @$vdep > 0) {
 				$depend = join("||", map { "PACKAGE_".$_ } @$vdep);
 			} else {
 				$flags =~ /@/ or $depend = "PACKAGE_$depend";
@@ -413,7 +415,6 @@  sub get_conditional_dep($$) {
 
 sub gen_package_mk() {
 	my %conf;
-	my %dep;
 	my %done;
 	my $line;
 
@@ -423,8 +424,6 @@  sub gen_package_mk() {
 		my $pkg = $package{$name};
 		my @srcdeps;
 
-		next if defined $pkg->{vdepends};
-
 		$config = "\$(CONFIG_PACKAGE_$name)";
 		if ($config) {
 			$pkg->{buildonly} and $config = "";
@@ -445,16 +444,7 @@  sub gen_package_mk() {
 			print "buildtypes-$pkg->{subdir}$pkg->{src} = ".join(' ', @{$pkg->{buildtypes}})."\n";
 		}
 
-		foreach my $spkg (@{$srcpackage{$pkg->{src}}}) {
-			foreach my $dep (@{$spkg->{depends}}, @{$spkg->{builddepends}}) {
-				$dep =~ /@/ or do {
-					$dep =~ s/\+//g;
-					push @srcdeps, $dep;
-				};
-			}
-		}
 		foreach my $type (@{$pkg->{buildtypes}}) {
-			my @extra_deps;
 			my %deplines;
 
 			next unless $pkg->{"builddepends/$type"};
@@ -492,63 +482,70 @@  sub gen_package_mk() {
 			}
 		}
 
-		my $hasdeps = 0;
 		my %deplines;
-		foreach my $deps (@srcdeps) {
-			my $idx;
-			my $condition;
-			my $prefix = "";
-			my $suffix = "";
-
-			if ($deps =~ /^(.+):(.+)/) {
-				$condition = $1;
-				$deps = $2;
-			}
-			if ($deps =~ /^(.+)(\/.+)/) {
-				$deps = $1;
-				$suffix = $2;
-			}
+		foreach my $spkg (@{$srcpackage{$pkg->{src}}}) {
+			foreach my $bdep (@{$spkg->{builddepends}}) {
+				my $condition;
+				my $suffix = "";
 
-			my $pkg_dep = $package{$deps};
-			my @deps;
+				if ($bdep =~ /^(.+):(.+)/) {
+					$condition = $1;
+					$bdep = $2;
+				}
+				if ($bdep =~ /^(.+)(\/.+)/) {
+					$bdep = $1;
+					$suffix = $2;
+				}
 
-			if ($pkg_dep->{vdepends}) {
-				@deps = @{$pkg_dep->{vdepends}};
-			} else {
-				@deps = ($deps);
+				next unless $subdir{$bdep};
+				my $idx = $subdir{$bdep}.$bdep.$suffix;
+
+				my $depline = get_conditional_dep($condition, "\$(curdir)/$idx/compile");
+				if ($depline) {
+					$deplines{$depline}++;
+				}
 			}
 
-			foreach my $dep (@deps) {
-				$pkg_dep = $package{$deps};
-				if (defined $pkg_dep->{src}) {
-					($pkg->{src} ne $pkg_dep->{src}.$suffix) and $idx = $pkg_dep->{subdir}.$pkg_dep->{src};
-				} elsif (defined($srcpackage{$dep})) {
-					$idx = $subdir{$dep}.$dep;
+			foreach my $dep (@{$spkg->{depends}}) {
+				my $condition;
+				my $suffix = "";
+
+				next if $dep =~ /@/;
+				$dep =~ s/\+//g;
+
+				if ($dep =~ /^(.+):(.+)/) {
+					$condition = $1;
+					$dep = $2;
 				}
-				undef $idx if $idx eq 'base-files';
-				if ($idx) {
-					$idx .= $suffix;
+				if ($dep =~ /^(.+)(\/.+)/) {
+					$dep = $1;
+					$suffix = $2;
+				}
+
+				next unless $vpackage{$dep};
+
+				my @vdeps = @{$vpackage{$dep}};
+				foreach my $vdep (@vdeps) {
+					my $pkg_dep = $package{$vdep};
 
-					my $depline;
+					next unless $pkg_dep;
 					next if $pkg->{src} eq $pkg_dep->{src}.$suffix;
-					next if $dep{$condition.":".$pkg->{src}."->".$idx};
-					next if $dep{$pkg->{src}."->($dep)".$idx} and $pkg_dep->{vdepends};
-					my $depstr;
 
-					if ($pkg_dep->{vdepends}) {
-						$depstr = "\$(if \$(CONFIG_PACKAGE_$dep),\$(curdir)/$idx/compile)";
-						$dep{$pkg->{src}."->($dep)".$idx} = 1;
+					my $idx = $pkg_dep->{subdir}.$pkg_dep->{src}.$suffix;
+					my $depstr;
+					if (@vdeps > 1) {
+						$depstr = "\$(if \$(CONFIG_PACKAGE_$vdep),\$(curdir)/$idx/compile)";
 					} else {
 						$depstr = "\$(curdir)/$idx/compile";
-						$dep{$pkg->{src}."->".$idx} = 1;
 					}
-					$depline = get_conditional_dep($condition, $depstr);
+					my $depline = get_conditional_dep($condition, $depstr);
 					if ($depline) {
 						$deplines{$depline}++;
 					}
 				}
 			}
 		}
+
 		my $depline = join(" ", sort keys %deplines);
 		if ($depline) {
 			$line .= "\$(curdir)/".$pkg->{subdir}."$pkg->{src}/compile += $depline\n";
@@ -573,7 +570,7 @@  ifndef DUMP_TARGET_DB
 	( \\
 $cmds \\
 	) > \$@
-	
+
 ifneq (\$(IMAGEOPT)\$(CONFIG_IMAGEOPT),)
   package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig
 endif