diff options
| author | Felix Fietkau | 2026-01-13 09:31:22 +0000 |
|---|---|---|
| committer | Felix Fietkau | 2026-01-22 10:20:17 +0000 |
| commit | 6d5c71f7485da47e5c2a0318dafd47ba50311dd4 (patch) | |
| tree | 2315a6392573920396a8bbda8307c0d8ef0cc0c9 | |
| parent | 46129bbbf5a423fd44a21b2f80f27a5a579fbb56 (diff) | |
| download | openwrt-6d5c71f7485da47e5c2a0318dafd47ba50311dd4.tar.gz | |
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@nbd.name>
| -rwxr-xr-x | scripts/package-metadata.pl | 47 |
1 files changed, 47 insertions, 0 deletions
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") { |