[openwrt/openwrt] build: auto-generate CONFLICTS for package variants sharing PROVIDES

LEDE Commits lede-commits at lists.infradead.org
Thu Jan 22 02:27:29 PST 2026


nbd pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/6d5c71f7485da47e5c2a0318dafd47ba50311dd4

commit 6d5c71f7485da47e5c2a0318dafd47ba50311dd4
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Tue Jan 13 09:31:22 2026 +0000

    build: auto-generate CONFLICTS for package variants sharing PROVIDES
    
    Packages using PROVIDES to declare virtual package alternatives (like
    tc-tiny, tc-bpf, tc-full all providing 'tc') could be simultaneously
    selected as =y, causing installation conflicts. The PROVIDES mechanism
    only handles dependency resolution, not mutual exclusion.
    
    Add add_implicit_provides_conflicts() to automatically generate CONFLICTS
    from default variants to non-default variants sharing the same PROVIDES.
    This ensures only one variant can be built-in (=y) at a time.
    
    Skip generating implicit conflicts when the non-default already has
    explicit CONFLICTS with the default, to avoid Kconfig dependency cycles
    with the select-based dependency resolution.
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 scripts/package-metadata.pl | 47 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl
index 82bd4360f3..518dae2dfd 100755
--- a/scripts/package-metadata.pl
+++ b/scripts/package-metadata.pl
@@ -255,6 +255,52 @@ sub mconf_conflicts {
 	return $res;
 }
 
+sub add_implicit_provides_conflicts {
+	foreach my $provide (keys %vpackage) {
+		next if $provide =~ /-any$/;
+
+		my $providers = $vpackage{$provide};
+		next unless $providers && @$providers > 1;
+
+		my $default_pkg;
+		my @non_defaults;
+
+		foreach my $pkg (@$providers) {
+			next if $pkg->{buildonly};
+			if ($pkg->{variant_default}) {
+				$default_pkg = $pkg;
+			} else {
+				push @non_defaults, $pkg;
+			}
+		}
+
+		next unless $default_pkg && @non_defaults;
+
+		my %existing_conflicts;
+		if ($default_pkg->{conflicts}) {
+			%existing_conflicts = map { $_ => 1 } @{$default_pkg->{conflicts}};
+		}
+
+		foreach my $non_default (@non_defaults) {
+			next if $existing_conflicts{$non_default->{name}};
+
+			my $already_conflicts = 0;
+			if ($non_default->{conflicts}) {
+				foreach my $c (@{$non_default->{conflicts}}) {
+					if ($c eq $default_pkg->{name}) {
+						$already_conflicts = 1;
+						last;
+					}
+				}
+			}
+			next if $already_conflicts;
+
+			$default_pkg->{conflicts} ||= [];
+			push @{$default_pkg->{conflicts}}, $non_default->{name};
+		}
+	}
+}
+
 sub print_package_config_category($) {
 	my $cat = shift;
 	my %menus;
@@ -350,6 +396,7 @@ sub print_package_overrides() {
 
 sub gen_package_config() {
 	parse_package_metadata($ARGV[0]) or exit 1;
+	add_implicit_provides_conflicts();
 	print "menuconfig IMAGEOPT\n\tbool \"Image configuration\"\n\tdefault n\n";
 	print "source \"package/*/image-config.in\"\n";
 	if (scalar glob "package/feeds/*/*/image-config.in") {




More information about the lede-commits mailing list