OpenWrt – Rev 3

Subversion Repositories:
Rev:
#!/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";
                /^broken$/ and $ret .= "\tdepends on BROKEN\n";
                /^audio$/ and $ret .= "\tselect AUDIO_SUPPORT\n";
                /^display$/ and $ret .= "\tselect DISPLAY_SUPPORT\n";
                /^dt$/ and $ret .= "\tselect USES_DEVICETREE\n";
                /^gpio$/ and $ret .= "\tselect GPIO_SUPPORT\n";
                /^pci$/ and $ret .= "\tselect PCI_SUPPORT\n";
                /^pcie$/ and $ret .= "\tselect PCIE_SUPPORT\n";
                /^usb$/ and $ret .= "\tselect USB_SUPPORT\n";
                /^usbgadget$/ and $ret .= "\tselect USB_GADGET_SUPPORT\n";
                /^pcmcia$/ and $ret .= "\tselect PCMCIA_SUPPORT\n";
                /^rtc$/ and $ret .= "\tselect RTC_SUPPORT\n";
                /^squashfs$/ and $ret .= "\tselect USES_SQUASHFS\n";
                /^jffs2$/ and $ret .= "\tselect USES_JFFS2\n";
                /^jffs2_nand$/ and $ret .= "\tselect USES_JFFS2_NAND\n";
                /^ext4$/ and $ret .= "\tselect USES_EXT4\n";
                /^targz$/ and $ret .= "\tselect USES_TARGZ\n";
                /^cpiogz$/ and $ret .= "\tselect USES_CPIOGZ\n";
                /^minor$/ and $ret .= "\tselect USES_MINOR\n";
                /^ubifs$/ and $ret .= "\tselect USES_UBIFS\n";
                /^fpu$/ and $ret .= "\tselect HAS_FPU\n";
                /^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n";
                /^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n";
                /^powerpc64$/ and $ret .= "\tselect powerpc64\n";
                /^nommu$/ and $ret .= "\tselect NOMMU\n";
                /^mips16$/ and $ret .= "\tselect HAS_MIPS16\n";
                /^rfkill$/ and $ret .= "\tselect RFKILL_SUPPORT\n";
                /^low_mem$/ and $ret .= "\tselect LOW_MEMORY_FOOTPRINT\n";
                /^small_flash$/ and $ret .= "\tselect SMALL_FLASH\n";
                /^nand$/ and $ret .= "\tselect NAND_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});
        if (@{$target->{subtargets}} == 0) {
        $confstr = <<EOF;
config TARGET_$target->{conf}
        bool "$target->{name}"
        select LINUX_$v
EOF
        }
        else {
                $confstr = <<EOF;
config TARGET_$target->{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} = 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 <<EOF;
config DEFAULT_TARGET_$target->{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 <<EOF;
choice
        prompt "Target System"
        default TARGET_ar71xx
        reset if !DEVEL
        
EOF

        foreach my $target (@target_sort) {
                next if $target->{subtarget};
                print_target($target);
        }

        print <<EOF;
endchoice

choice
        prompt "Subtarget" if HAS_SUBTARGETS
EOF
        foreach my $target (@target) {
                next unless $target->{def_subtarget};
                print <<EOF;
        default TARGET_$target->{conf}_$target->{def_subtarget} if TARGET_$target->{conf}
EOF
        }
        print <<EOF;

EOF
        foreach my $target (@target) {
                next unless $target->{subtarget};
                print_target($target);
        }

print <<EOF;
endchoice

choice
        prompt "Target Profile"
        default TARGET_MULTI_PROFILE if BUILDBOT

EOF
        foreach my $target (@target) {
                my $profile = $target->{profiles}->[0];
                $profile or next;
                print <<EOF;
        default TARGET_$target->{conf}_$profile->{id} if TARGET_$target->{conf} && !BUILDBOT
EOF
        }

        print <<EOF;

config TARGET_MULTI_PROFILE
        bool "Multiple devices"
        depends on HAS_DEVICES
        help
        Instead of only building a single image, or all images, this allows you
        to select images to be built for multiple devices in one build.

EOF

        foreach my $target (@target) {
                my $profiles = $target->{profiles};
                foreach my $profile (@{$target->{profiles}}) {
                        print <<EOF;
config TARGET_$target->{conf}_$profile->{id}
        bool "$profile->{name}"
        depends on TARGET_$target->{conf}
EOF
                        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 <<EOF;
endchoice

menu "Target Devices"
        depends on TARGET_MULTI_PROFILE

        config TARGET_ALL_PROFILES
                bool "Enable all profiles by default"
                default BUILDBOT

        config TARGET_PER_DEVICE_ROOTFS
                bool "Use a per-device root filesystem that adds profile packages"
                default BUILDBOT
                help
                When disabled, all device packages from all selected devices
                will be included in all images by default. (Marked as <*>) 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 <<EOF;
menuconfig TARGET_DEVICE_$target->{conf}_$profile->{id}
        bool "$profile->{name}"
        depends on TARGET_$target->{conf}
        default y if TARGET_ALL_PROFILES
EOF
                        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 <<EOF;


        config TARGET_DEVICE_PACKAGES_$target->{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 <<EOF;

endmenu

config HAS_SUBTARGETS
        bool

config HAS_DEVICES
        bool

config TARGET_BOARD
        string

EOF
        foreach my $target (@target) {
                $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
        }
        print <<EOF;
config TARGET_SUBTARGET
        string
        default "generic" if !HAS_SUBTARGETS

EOF

        foreach my $target (@target) {
                foreach my $subtarget (@{$target->{subtargets}}) {
                        print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
                }
        }
        print <<EOF;
config TARGET_PROFILE
        string
EOF
        foreach my $target (@target) {
                my $profiles = $target->{profiles};
                foreach my $profile (@$profiles) {
                        print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
                }
        }

        print <<EOF;

config TARGET_ARCH_PACKAGES
        string
        
EOF
        foreach my $target (@target) {
                next if @{$target->{subtargets}} > 0;
                print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
        }
        print <<EOF;

config DEFAULT_TARGET_OPTIMIZATION
        string
EOF
        foreach my $target (@target) {
                next if @{$target->{subtargets}} > 0;
                print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
        }
        print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
        print <<EOF;

config CPU_TYPE
        string
EOF
        foreach my $target (@target) {
                next if @{$target->{subtargets}} > 0;
                print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
        }
        print "\tdefault \"\"\n";

        my %kver;
        foreach my $target (@target) {
                my $v = kver($target->{version});
                next if $kver{$v};
                $kver{$v} = 1;
                print <<EOF;

config LINUX_$v
        bool

EOF
        }
        foreach my $def (sort keys %defaults) {
                print <<EOF;
        config DEFAULT_$def
                bool

        config MODULE_DEFAULT_$def
                tristate
                depends on TARGET_PER_DEVICE_ROOTFS
                depends on m
                default m if DEFAULT_$def
                select PACKAGE_$def

EOF
        }
}

sub gen_profile_mk() {
        my $file = shift @ARGV;
        my $target = shift @ARGV;
        my @targets = parse_target_metadata($file);
        foreach my $cur (@targets) {
                next unless $cur->{id} eq $target;
                print "PROFILE_NAMES = ".join(" ", map { $_->{id} } @{$cur->{profiles}})."\n";
                foreach my $profile (@{$cur->{profiles}}) {
                        print $profile->{id}.'_NAME:='.$profile->{name}."\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 <<EOF
Available Commands:
        $0 config [file]                        Target metadata in Kconfig format
        $0 profile_mk [file] [target]           Profile metadata in makefile format

EOF
}

parse_command();

Generated by GNU Enscript 1.6.5.90.