#!/usr/bin/env perl use FindBin; use lib "$FindBin::Bin"; use strict; use metadata; use Getopt::Long; sub target_config_features(@) { my $ret; while ($_ = shift @_) { /^arm_v(\w+)$/ and $ret .= "\tselect arm_v$1\n"; /^audio$/ and $ret .= "\tselect AUDIO_SUPPORT\n"; /^boot-part$/ and $ret .= "\tselect USES_BOOT_PART\n"; /^broken$/ and $ret .= "\tdepends on BROKEN\n"; /^cpiogz$/ and $ret .= "\tselect USES_CPIOGZ\n"; /^display$/ and $ret .= "\tselect DISPLAY_SUPPORT\n"; /^dt$/ and $ret .= "\tselect USES_DEVICETREE\n"; /^dt-overlay$/ and $ret .= "\tselect HAS_DT_OVERLAY_SUPPORT\n"; /^emmc$/ and $ret .= "\tselect EMMC_SUPPORT\n"; /^ext4$/ and $ret .= "\tselect USES_EXT4\n"; /^fpu$/ and $ret .= "\tselect HAS_FPU\n"; /^gpio$/ and $ret .= "\tselect GPIO_SUPPORT\n"; /^jffs2$/ and $ret .= "\tselect USES_JFFS2\n"; /^jffs2_nand$/ and $ret .= "\tselect USES_JFFS2_NAND\n"; /^legacy-sdcard$/ and $ret .= "\tselect LEGACY_SDCARD_SUPPORT\n"; /^low_mem$/ and $ret .= "\tselect LOW_MEMORY_FOOTPRINT\n"; /^minor$/ and $ret .= "\tselect USES_MINOR\n"; /^mips16$/ and $ret .= "\tselect HAS_MIPS16\n"; /^nand$/ and $ret .= "\tselect NAND_SUPPORT\n"; /^nommu$/ and $ret .= "\tselect NOMMU\n"; /^pci$/ and $ret .= "\tselect PCI_SUPPORT\n"; /^pcie$/ and $ret .= "\tselect PCIE_SUPPORT\n"; /^pcmcia$/ and $ret .= "\tselect PCMCIA_SUPPORT\n"; /^powerpc64$/ and $ret .= "\tselect powerpc64\n"; /^pwm$/ and $ret .= "\select PWM_SUPPORT\n"; /^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n"; /^rfkill$/ and $ret .= "\tselect RFKILL_SUPPORT\n"; /^rootfs-part$/ and $ret .= "\tselect USES_ROOTFS_PART\n"; /^rtc$/ and $ret .= "\tselect RTC_SUPPORT\n"; /^separate_ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n\tselect USES_SEPARATE_INITRAMFS\n"; /^small_flash$/ and $ret .= "\tselect SMALL_FLASH\n"; /^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n"; /^squashfs$/ and $ret .= "\tselect USES_SQUASHFS\n"; /^targz$/ and $ret .= "\tselect USES_TARGZ\n"; /^testing-kernel$/ and $ret .= "\tselect HAS_TESTING_KERNEL\n"; /^ubifs$/ and $ret .= "\tselect USES_UBIFS\n"; /^usb$/ and $ret .= "\tselect USB_SUPPORT\n"; /^usbgadget$/ and $ret .= "\tselect USB_GADGET_SUPPORT\n"; /^virtio$/ and $ret .= "\tselect VIRTIO_SUPPORT\n"; } return $ret; } sub target_name($) { my $target = shift; my $parent = $target->{parent}; if ($parent) { return $target->{parent}->{name}." - ".$target->{name}; } else { return $target->{name}; } } sub kver($) { my $v = shift; $v =~ tr/\./_/; if (substr($v,0,2) eq "2_") { $v =~ /(\d+_\d+_\d+)(_\d+)?/ and $v = $1; } else { $v =~ /(\d+_\d+)(_\d+)?/ and $v = $1; } return $v; } sub print_target($) { my $target = shift; my $features = target_config_features(@{$target->{features}}); my $help = $target->{desc}; my $confstr; chomp $features; $features .= "\n"; if ($help =~ /\w+/) { $help =~ s/^\s*/\t /mg; $help = "\thelp\n$help"; } else { undef $help; } my $v = kver($target->{version}); my $tv = kver($target->{testing_version}); $tv or $tv = $v; if (@{$target->{subtargets}} == 0) { $confstr = <{conf} bool "$target->{name}" select LINUX_$v if !TESTING_KERNEL select LINUX_$tv if TESTING_KERNEL EOF } else { $confstr = <{conf} bool "$target->{name}" EOF } if ($target->{subtarget}) { $confstr .= "\tdepends on TARGET_$target->{boardconf}\n"; } if (@{$target->{subtargets}} > 0) { $confstr .= "\tselect HAS_SUBTARGETS\n"; grep { /broken/ } @{$target->{features}} and $confstr .= "\tdepends on BROKEN\n"; } else { $confstr .= $features; if ($target->{arch} =~ /\w/) { $confstr .= "\tselect $target->{arch}\n"; } if ($target->{has_devices}) { $confstr .= "\tselect HAS_DEVICES\n"; } } foreach my $dep (@{$target->{depends}}) { my $mode = "depends on"; my $flags; my $name; $dep =~ /^([@\+\-]+)(.+)$/; $flags = $1; $name = $2; next if $name =~ /:/; $flags =~ /-/ and $mode = "deselect"; $flags =~ /\+/ and $mode = "select"; $flags =~ /@/ and $confstr .= "\t$mode $name\n"; } $confstr .= "$help\n\n"; print $confstr; } sub merge_package_lists($$) { my $list1 = shift; my $list2 = shift; my @l = (); my %pkgs; foreach my $pkg (@$list1, @$list2) { $pkgs{$pkg =~ s/^~//r} = 1; } foreach my $pkg (keys %pkgs) { push @l, $pkg unless ($pkg =~ /^-/ or $pkgs{"-$pkg"}); } return sort(@l); } sub gen_target_config() { my $file = shift @ARGV; my @target = parse_target_metadata($file); my %defaults; my @target_sort = sort { target_name($a) cmp target_name($b); } @target; foreach my $target (@target_sort) { next if @{$target->{subtargets}} > 0; print <{conf} bool depends on TARGET_PER_DEVICE_ROOTFS default y if TARGET_$target->{conf} EOF foreach my $pkg (@{$target->{packages}}) { print "\tselect DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n"; } } print <{subtarget}; print_target($target); } print <{def_subtarget}; print <{conf}_$target->{def_subtarget} if TARGET_$target->{conf} EOF } print <{subtarget}; print_target($target); } print <{profiles}->[0]; foreach my $p (@{$target->{profiles}}) { last unless $target->{default_profile}; my $name = $p->{id}; $name =~ s/^DEVICE_//; next unless $name eq $target->{default_profile}; $profile = $p; last; } $profile or next; print <{conf}_$profile->{id} if TARGET_$target->{conf} && !BUILDBOT EOF } print <{profiles}; foreach my $profile (@{$target->{profiles}}) { print <{conf}_$profile->{id} bool "$profile->{name}" depends on TARGET_$target->{conf} EOF $profile->{broken} and print "\tdepends on BROKEN\n"; my @pkglist = merge_package_lists($target->{packages}, $profile->{packages}); foreach my $pkg (@pkglist) { print "\tselect DEFAULT_$pkg\n"; $defaults{$pkg} = 1; } my $help = $profile->{desc}; if ($help =~ /\w+/) { $help =~ s/^\s*/\t /mg; $help = "\thelp\n$help"; } else { undef $help; } print "$help\n"; } } print <) You will still be able to manually deselect any/all packages. When enabled, each device builds it's own image, including only the profile packages for that device. (Marked as {M}) You will be able to change a package to included in all images by marking as {*}, but will not be able to disable a profile package completely. To get the most use of this setting, you must set in a .config stub before calling "make defconfig". Selecting TARGET_MULTI_PROFILE and then manually selecting (via menuconfig for instance) this option will have pre-defaulted all profile packages to included, making this option appear to have had no effect. EOF foreach my $target (@target) { my @profiles = sort { my $x = $a->{name}; my $y = $b->{name}; "\L$x" cmp "\L$y"; } @{$target->{profiles}}; foreach my $profile (@profiles) { next unless $profile->{id} =~ /^DEVICE_/; print <{conf}_$profile->{id} bool "$profile->{name}" depends on TARGET_$target->{conf} default $profile->{default} EOF $profile->{broken} and print "\tdepends on BROKEN\n"; my @pkglist = merge_package_lists($target->{packages}, $profile->{packages}); foreach my $pkg (@pkglist) { print "\tselect DEFAULT_$pkg if !TARGET_PER_DEVICE_ROOTFS\n"; print "\tselect MODULE_DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n"; $defaults{$pkg} = 1; } print <{conf}_$profile->{id} string "$profile->{name} additional packages" default "" depends on TARGET_PER_DEVICE_ROOTFS depends on TARGET_DEVICE_$target->{conf}_$profile->{id} EOF } } print <{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n"; } print <{subtargets}}) { print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n"; } } print <{profiles}; foreach my $profile (@$profiles) { print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n"; } } print <{subtargets}} > 0; print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n"; } print <{subtargets}} > 0; print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n"; } print "\tdefault \"-Os -pipe -funit-at-a-time\"\n"; print <{subtargets}} > 0; print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n"; } print "\tdefault \"\"\n"; my %kver; foreach my $target (@target) { foreach my $tv ($target->{version}, $target->{testing_version}) { next unless $tv; my $v = kver($tv); next if $kver{$v}; $kver{$v} = 1; print <{id} eq $target; my @profile_ids_unique = do { my %seen; grep { !$seen{$_}++} map { $_->{id} } @{$cur->{profiles}}}; print "PROFILE_NAMES = ".join(" ", @profile_ids_unique)."\n"; foreach my $profile (@{$cur->{profiles}}) { print $profile->{id}.'_NAME:='.$profile->{name}."\n"; print $profile->{id}.'_HAS_IMAGE_METADATA:='.$profile->{has_image_metadata}."\n"; if (defined($profile->{supported_devices}) and @{$profile->{supported_devices}} > 0) { print $profile->{id}.'_SUPPORTED_DEVICES:='.join(' ', @{$profile->{supported_devices}})."\n"; } print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n"; } } } sub parse_command() { GetOptions("ignore=s", \@ignore); my $cmd = shift @ARGV; for ($cmd) { /^config$/ and return gen_target_config(); /^profile_mk$/ and return gen_profile_mk(); } die <