#!/usr/bin/env perl use FindBin; use lib "$FindBin::Bin"; use strict; use metadata; use Getopt::Long; my %board; sub version_to_num($) { my $str = shift; my $num = 0; if (defined($str) && $str =~ /^\d+(?:\.\d+)+$/) { my @n = (split(/\./, $str), 0, 0, 0, 0); $num = ($n[0] << 24) | ($n[1] << 16) | ($n[2] << 8) | $n[3]; } return $num; } sub version_filter_list(@) { my $cmpver = version_to_num(shift @_); my @items; foreach my $item (@_) { if ($item =~ s/@(lt|le|gt|ge|eq|ne)(\d+(?:\.\d+)+)\b//) { my $op = $1; my $symver = version_to_num($2); if ($symver > 0 && $cmpver > 0) { next unless (($op eq 'lt' && $cmpver < $symver) || ($op eq 'le' && $cmpver <= $symver) || ($op eq 'gt' && $cmpver > $symver) || ($op eq 'ge' && $cmpver >= $symver) || ($op eq 'eq' && $cmpver == $symver) || ($op eq 'ne' && $cmpver != $symver)); } } push @items, $item; } return @items; } sub gen_kconfig_overrides() { my %config; my %kconfig; my $package; my $pkginfo = shift @ARGV; my $cfgfile = shift @ARGV; my $patchver = shift @ARGV; # parameter 2: build system config open FILE, "<$cfgfile" or return; while () { /^(CONFIG_.+?)=(.+)$/ and $config{$1} = 1; } close FILE; # parameter 1: package metadata open FILE, "<$pkginfo" or return; while () { /^Package:\s*(.+?)\s*$/ and $package = $1; /^Kernel-Config:\s*(.+?)\s*$/ and do { my @config = split /\s+/, $1; foreach my $config (version_filter_list($patchver, @config)) { my $val = 'm'; my $override; if ($config =~ /^(.+?)=(.+)$/) { $config = $1; $override = 1; $val = $2; } if ($config{"CONFIG_PACKAGE_$package"} and ($config ne 'n')) { next if $kconfig{$config} eq 'y'; $kconfig{$config} = $val; } elsif (!$override) { $kconfig{$config} or $kconfig{$config} = 'n'; } } }; }; close FILE; foreach my $kconfig (sort keys %kconfig) { if ($kconfig{$kconfig} eq 'n') { print "# $kconfig is not set\n"; } else { print "$kconfig=$kconfig{$kconfig}\n"; } } } 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 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"; /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"; /nand/ and $ret .= "\tselect NAND_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 = <{conf} bool "$target->{name}" select LINUX_$v 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"; } } foreach my $dep (@{$target->{depends}}) { my $mode = "depends on"; my $flags; my
#
# Copyright (C) 2007 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

# debug flags:
#
# d: show subdirectory tree
# t: show added targets
# l: show legacy targets
# r: show autorebuild messages
# v: verbose (no .SILENCE for common targets)

ifeq ($(DUMP),)
  ifeq ($(DEBUG),all)
    build_debug:=dltvr
  else
    build_debug:=$(DEBUG)
  endif
endif

ifneq ($(DEBUG),)

define debug
$$(findstring $(2),$$(if $$(DEBUG_SCOPE_DIR),$$(if $$(filter $$(DEBUG_SCOPE_DIR)%,$(1)),$(build_debug)),$(build_debug)))
endef

define warn
$$(if $(call debug,$(1),$(2)),$$(warning $(3)))
endef

define debug_eval
$$(if $(call debug,$(1),$(2)),$(3))
endef

define warn_eval
$(call warn,$(1),$(2),$(3)	$(4))
$(4)
endef

else

debug:=
warn:=
debug_eval:=
warn_eval = $(4)

endif
n PACKAGE_$preconfig default "$preconfig{$preconfig}->{$cfg}->{default}" EOF } } print "source \"package/*/image-config.in\"\n"; if (scalar glob "package/feeds/*/*/image-config.in") { print "source \"package/feeds/*/*/image-config.in\"\n"; } print_package_features(); print_package_config_category 'Base system'; foreach my $cat (sort {uc($a) cmp uc($b)} keys %category) { print_package_config_category $cat; } print_package_overrides(); } sub get_conditional_dep($$) { my $condition = shift; my $depstr = shift; if ($condition) { if ($condition =~ /^!(.+)/) { return "\$(if \$(CONFIG_$1),,$depstr)"; } else { return "\$(if \$(CONFIG_$condition),$depstr)"; } } else { return $depstr; } } sub gen_package_mk() { my %conf; my %dep; my %done; my $line; parse_package_metadata($ARGV[0]) or exit 1; foreach my $name (sort {uc($a) cmp uc($b)} keys %package) { my $config; my $pkg = $package{$name}; my @srcdeps; next if defined $pkg->{vdepends}; $config = "\$(CONFIG_PACKAGE_$name)"; if ($config) { $pkg->{buildonly} and $config = ""; print "package-$config += $pkg->{subdir}$pkg->{src}\n"; if ($pkg->{variant}) { if (!defined($done{$pkg->{src}}) or $pkg->{variant_default}) { print "\$(curdir)/$pkg->{subdir}$pkg->{src}/default-variant := $pkg->{variant}\n"; } print "\$(curdir)/$pkg->{subdir}$pkg->{src}/variants += \$(if $config,$pkg->{variant})\n" } $pkg->{prereq} and print "prereq-$config += $pkg->{subdir}$pkg->{src}\n"; } next if $done{$pkg->{src}}; $done{$pkg->{src}} = 1; if (@{$pkg->{buildtypes}} > 0) { 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"}; foreach my $dep (@{$pkg->{"builddepends/$type"}}) { my $suffix = ""; my $condition; if ($dep =~ /^(.+):(.+)/) { $condition = $1; $dep = $2; } if ($dep =~ /^(.+)(\/.+)/) { $dep = $1; $suffix = $2; } my $idx = ""; my $pkg_dep = $package{$dep}; if (defined($pkg_dep) && defined($pkg_dep->{src})) { $idx = $pkg_dep->{subdir}.$pkg_dep->{src}; } elsif (defined($srcpackage{$dep})) { $idx = $subdir{$dep}.$dep; } else { next; } my $depstr = "\$(curdir)/$idx$suffix/compile"; 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}/$type/compile += $depline\n"; } } 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; } my $pkg_dep = $package{$deps}; my @deps; if ($pkg_dep->{vdepends}) { @deps = @{$pkg_dep->{vdepends}}; } else { @deps = ($deps); } 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; } undef $idx if $idx eq 'base-files'; if ($idx) { $idx .= $suffix; my $depline; 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; } else { $depstr = "\$(curdir)/$idx/compile"; $dep{$pkg->{src}."->".$idx} = 1; } $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"; } } if ($line ne "") { print "\n$line"; } foreach my $preconfig (keys %preconfig) { my $cmds; foreach my $cfg (keys %{$preconfig{$preconfig}}) { my $conf = $preconfig{$preconfig}->{$cfg}->{id}; $conf =~ tr/\.-/__/; $cmds .= "\techo \"uci set '$preconfig{$preconfig}->{$cfg}->{id}=\$(subst \",,\$(CONFIG_UCI_PRECONFIG_$conf))'\"; \\\n"; } next unless $cmds; print < \$@ ifneq (\$(IMAGEOPT)\$(CONFIG_IMAGEOPT),) package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig endif endif EOF } } sub gen_package_source() { parse_package_metadata($ARGV[0]) or exit 1; foreach my $name (sort {uc($a) cmp uc($b)} keys %package) { my $pkg = $package{$name}; if ($pkg->{name} && $pkg->{source}) { print "$pkg->{name}: "; print "$pkg->{source}\n"; } } } sub gen_package_subdirs() { parse_package_metadata($ARGV[0]) or exit 1; foreach my $name (sort {uc($a) cmp uc($b)} keys %package) { my $pkg = $package{$name}; if ($pkg->{name} && $pkg->{package_subdir}) { print "Package/$name/subdir = $pkg->{package_subdir}\n"; } } } sub gen_package_license($) { my $level = shift; parse_package_metadata($ARGV[0]) or exit 1; foreach my $name (sort {uc($a) cmp uc($b)} keys %package) { my $pkg = $package{$name}; if ($pkg->{name}) { if ($pkg->{license}) { print "$pkg->{name}: "; print "$pkg->{license}\n"; if ($pkg->{licensefiles} && $level == 0) { print "\tFiles: $pkg->{licensefiles}\n"; } } else { if ($level == 1) { print "$pkg->{name}: Missing license! "; print "Please fix $pkg->{makefile}\n"; } } } } } sub gen_version_filtered_list() { foreach my $item (version_filter_list(@ARGV)) { print "$item\n"; } } sub parse_command() { GetOptions("ignore=s", \@ignore); my $cmd = shift @ARGV; for ($cmd) { /^target_config$/ and return gen_target_config(); /^package_mk$/ and return gen_package_mk(); /^package_config$/ and return gen_package_config(); /^kconfig/ and return gen_kconfig_overrides(); /^package_source$/ and return gen_package_source(); /^package_subdirs$/ and return gen_package_subdirs(); /^package_license$/ and return gen_package_license(0); /^package_licensefull$/ and return gen_package_license(1); /^version_filter$/ and return gen_version_filtered_list(); } print < Ignore the source package EOF } parse_command();