diff options
| -rw-r--r-- | feeds.conf | 2 | ||||
| -rw-r--r-- | include/scan.mk | 20 | ||||
| -rw-r--r-- | include/toplevel.mk | 8 | ||||
| -rw-r--r-- | scripts/config/conf.c | 19 | ||||
| -rwxr-xr-x | scripts/feeds | 322 | ||||
| -rwxr-xr-x | scripts/metadata.pl | 130 | ||||
| -rw-r--r-- | scripts/metadata.pm | 113 | 
7 files changed, 484 insertions, 130 deletions
| diff --git a/feeds.conf b/feeds.conf new file mode 100644 index 000000000..31dbe5f0f --- /dev/null +++ b/feeds.conf @@ -0,0 +1,2 @@ +src-svn packages https://svn.openwrt.org/openwrt/packages +src-svn xwrt http://svn.berlios.de/svnroot/repos/xwrt/trunk/package diff --git a/include/scan.mk b/include/scan.mk index dfe80faba..28f526aa3 100644 --- a/include/scan.mk +++ b/include/scan.mk @@ -1,15 +1,15 @@  include $(TOPDIR)/include/verbose.mk  TMP_DIR:=$(TOPDIR)/tmp -all: tmp/.$(SCAN_TARGET) +all: $(TMP_DIR)/.$(SCAN_TARGET)  include $(TOPDIR)/include/host.mk  SCAN_TARGET ?= packageinfo  SCAN_NAME ?= package  SCAN_DIR ?= package -TARGET_STAMP:=tmp/info/.files-$(SCAN_TARGET).stamp -FILELIST:=tmp/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE) +TARGET_STAMP:=$(TMP_DIR)/info/.files-$(SCAN_TARGET).stamp +FILELIST:=$(TMP_DIR)/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)  ifeq ($(IS_TTY),1)    define progress @@ -22,8 +22,8 @@ else  endif  define PackageDir -  tmp/.$(SCAN_TARGET): tmp/info/.$(SCAN_TARGET)-$(1) -  tmp/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP)))) +  $(TMP_DIR)/.$(SCAN_TARGET): $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1) +  $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP))))  	{ \  		$$(call progress,Collecting $(SCAN_NAME) info: $(SCAN_DIR)/$(2)) \  		echo Source-Makefile: $(SCAN_DIR)/$(2)/Makefile; \ @@ -33,10 +33,10 @@ define PackageDir  endef  $(FILELIST): -	rm -f tmp/info/.files-$(SCAN_TARGET)-* +	rm -f $(TMP_DIR)/info/.files-$(SCAN_TARGET)-*  	$(call FIND_L, $(SCAN_DIR)) $(SCAN_EXTRA) -mindepth 1 $(if $(SCAN_DEPTH),-maxdepth $(SCAN_DEPTH)) -name Makefile | xargs grep -HE 'call (Build/DefaultTargets|Build(Package|Target)|.+Package)' | sed -e 's#^$(SCAN_DIR)/##' -e 's#/Makefile:.*##' | uniq > $@ -tmp/info/.files-$(SCAN_TARGET).mk: $(FILELIST) +$(TMP_DIR)/info/.files-$(SCAN_TARGET).mk: $(FILELIST)  	( \  		cat $< | awk '{print "$(SCAN_DIR)/" $$0 "/Makefile" }' | xargs grep -HE '^ *SCAN_DEPS *= *' | awk -F: '{ gsub(/^.*DEPS *= */, "", $$2); print "DEPS_" $$1 "=" $$2 }'; \  		awk -v deps="$$DEPS" '{ \ @@ -47,7 +47,7 @@ tmp/info/.files-$(SCAN_TARGET).mk: $(FILELIST)  		true; \  	) > $@ --include tmp/info/.files-$(SCAN_TARGET).mk +-include $(TMP_DIR)/info/.files-$(SCAN_TARGET).mk  $(TARGET_STAMP):  	( \ @@ -60,9 +60,9 @@ $(TARGET_STAMP):  		} \  	) -tmp/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP) +$(TMP_DIR)/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)  	$(call progress,Collecting $(SCAN_NAME) info: merging...) -	cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "tmp/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@ +	cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@  	$(call progress,Collecting $(SCAN_NAME) info: done)  	echo diff --git a/include/toplevel.mk b/include/toplevel.mk index 0a8bdedc3..a9ca3a280 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -30,15 +30,17 @@ endif  SCAN_COOKIE?=$(shell echo $$$$)  export SCAN_COOKIE +prepare-mk: FORCE ; +  prepare-tmpinfo: FORCE  	mkdir -p tmp/info  	+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk" SCAN_DEPTH=4 SCAN_EXTRA=""  	+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk" SCAN_DEPTH=2 SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"  	for type in package target; do \  		f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \ -		[ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config < "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \ +		[ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \  	done -	./scripts/metadata.pl package_mk < tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; } +	./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }  	touch $(TOPDIR)/tmp/.build  .config: ./scripts/config/conf prepare-tmpinfo @@ -64,7 +66,7 @@ defconfig: scripts/config/conf prepare-tmpinfo FORCE  	$< -D .config Config.in  oldconfig: scripts/config/conf prepare-tmpinfo FORCE -	$< -o Config.in +	$< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in  menuconfig: scripts/config/mconf prepare-tmpinfo FORCE  	if [ \! -f .config -a -e $(HOME)/.openwrt/defconfig ]; then \ diff --git a/scripts/config/conf.c b/scripts/config/conf.c index cb2093691..6589aee45 100644 --- a/scripts/config/conf.c +++ b/scripts/config/conf.c @@ -579,28 +579,11 @@ int main(int ac, char **av)  		}  	case ask_all:  	case ask_new: -		conf_read(NULL); -		break;  	case set_no:  	case set_mod:  	case set_yes:  	case set_random: -		name = getenv("KCONFIG_ALLCONFIG"); -		if (name && !stat(name, &tmpstat)) { -			conf_read_simple(name); -			break; -		} -		switch (input_mode) { -		case set_no:	 name = "allno.config"; break; -		case set_mod:	 name = "allmod.config"; break; -		case set_yes:	 name = "allyes.config"; break; -		case set_random: name = "allrandom.config"; break; -		default: break; -		} -		if (!stat(name, &tmpstat)) -			conf_read_simple(name); -		else if (!stat("all.config", &tmpstat)) -			conf_read_simple("all.config"); +		conf_read(NULL);  		break;  	default:  		break; diff --git a/scripts/feeds b/scripts/feeds new file mode 100755 index 000000000..d62e8e79d --- /dev/null +++ b/scripts/feeds @@ -0,0 +1,322 @@ +#!/usr/bin/perl +use Getopt::Std; +use FindBin; +use Cwd; +use lib "$FindBin::Bin"; +use metadata; +use warnings; +use strict; + +chdir "$FindBin::Bin/.."; +$ENV{TOPDIR}=getcwd(); + +my @feeds; +my %build_packages; +my %installed; + +sub parse_config() { +	my $line = 0; +	my %name; + +	open FEEDS, "feeds.conf"; +	while (<FEEDS>) { +		chomp; +		s/#.+$//; +		next unless /\S/; +		my @line = split /\s+/, $_, 3; +		$line++; + +		my $valid = 1; +		$line[0] =~ /^src-\w+$/ or $valid = 0; +		$line[1] =~ /^\w+$/ or $valid = 0; +		$line[2] =~ /\s/ and $valid = 0; +		$valid or die "Syntax error in feeds.list, line: $line\n"; + +		$name{$line[1]} and die "Duplicate feed name '$line[1]', line: $line\n"; +		$name{$line[1]} = 1; + +		push @feeds, [@line]; +	} +	close FEEDS; +} + +sub update_svn($$) { +	my $name = shift; +	my $src = shift; + +	system("svn co $src ./feeds/$name") == 0 or return 1; +	-d "./feeds/$name.tmp" or mkdir "./feeds/$name.tmp" or return 1; +	-d "./feeds/$name.tmp/info" or mkdir "./feeds/$name.tmp/info" or return 1; + +	system("make -s prepare-mk TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\""); +	system("make -s -f include/scan.mk IS_TTY=1 SCAN_TARGET=\"packageinfo\" SCAN_DIR=\"feeds/$name\" SCAN_NAME=\"package\" SCAN_DEPS=\"$ENV{TOPDIR}/include/package*.mk\" SCAN_DEPTH=4 SCAN_EXTRA=\"\" TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\""); +	system("ln -sf $name.tmp/.packageinfo ./feeds/$name.index"); + +	return 0; +} + +sub get_feed($) { +	my $feed = shift; + +	clear_packages(); +	parse_package_metadata("./feeds/$feed.index") or return; +	return { %package }; +} + +sub get_installed() { +	system("make -s prepare-tmpinfo"); +	clear_packages(); +	parse_package_metadata("./tmp/.packageinfo"); +	%installed = %package; +} + +sub search_feed { +	my $feed = shift; +	my @substr = @_; +	my $display; +	 +	return unless @substr > 0; +	get_feed($feed); +	foreach my $name (sort { lc($a) cmp lc($b) } keys %package) { +		my $pkg = $package{$name}; +		my $substr; +		my $pkgmatch = 1; + +		foreach my $substr (@substr) { +			my $match; +			foreach my $key (qw(name title description)) { +				$substr and $pkg->{$key} =~ m/$substr/i and $match = 1; +			} +			$match or undef $pkgmatch; +		}; +		$pkgmatch and do { +			$display or do { +				print "Search results in feed '$feed':\n"; +				$display = 1; +			}; +			printf "\%-25s\t\%s\n", $pkg->{name}, $pkg->{title}; +		}; +	} +	return 0; +} + + +sub search { +	my %opts; + +	getopt('r:', \%opts); +	foreach my $feed (@feeds) { +		search_feed($feed->[1], @ARGV) if (!defined($opts{r}) or $opts{r} eq $feed->[1]); +	} +} + +sub install_svn() { +	my $feed = shift; +	my $pkg = shift; +	my $path = $pkg->{makefile}; +	$path =~ s/\/Makefile$//; + +	-d "./package/feeds" or mkdir "./package/feeds"; +	-d "./package/feeds/$feed->[1]" or mkdir "./package/feeds/$feed->[1]"; +	system("ln -sf ../../../$path ./package/feeds/$feed->[1]/"); + +	return 0; +} + +my %install_method = ( +	'src-svn' => \&install_svn +); + +my %feed; + +sub lookup_package($$) { +	my $feed = shift; +	my $package = shift; + +	foreach my $feed ($feed, @feeds) { +		next unless $feed->[1]; +		next unless $feed{$feed->[1]}; +		$feed{$feed->[1]}->{$package} and return $feed; +	} +	return; +} + +sub install_package { +	my $feed = shift; +	my $name = shift; +	my $ret = 0; + +	$feed = lookup_package($feed, $name); +	$feed or do { +		$installed{$name} and return 0; +		warn "WARNING: Package '$name' is not available.\n"; +		return 1; +	}; + +	my $pkg = $feed{$feed->[1]}->{$name} or return 1; +	my $src = $pkg->{src}; +	my $type = $feed->[0]; +	$src or $src = $name; + +	# previously installed packages set the runtime package +	# newly installed packages set the source package +	$installed{$src} and return 0; + +	# install all dependencies +	foreach my $dep (@{$pkg->{depends}}) { +		next if $dep =~ /@/; +		$dep =~ s/^\+//; +		install_package($feed, $dep) == 0 or $ret = 1; +	} + +	# check previously installed packages +	$installed{$name} and return 0; +	$installed{$src} = 1; +	warn "Installing package '$src'\n"; + +	$install_method{$type} or do { +		warn "Unknown installation method: '$type'\n"; +		return 1; +	}; + +	&{$install_method{$type}}($feed, $pkg) == 0 or do { +		warn "failed.\n"; +		return 1; +	}; + +	return $ret; +} + +sub refresh_config { +	my $default = shift; +	$default or $default = "o"; + +	# workaround for timestamp check +	system("rm -f tmp/.packageinfo"); + +	# refresh the config  +	system("make oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null"); +} + +sub install { +	my $name; +	my %opts; +	my $feed; +	my $ret = 0; +	 +	getopt('p:d:', \%opts); +	get_installed(); + +	foreach my $f (@feeds) { +		# index all feeds +		$feed{$f->[1]} = get_feed($f->[1]); + +		# look up the preferred feed +		$opts{p} and $f->[1] eq $opts{p} and $feed = $f; +	} + +	while ($name = shift @ARGV) { +		install_package($feed, $name) == 0 or $ret = 1; +	} + +	# workaround for timestamp check +	 +	# set the defaults +	if ($opts{d} and $opts{d} =~ /^[ymn]$/) { +		refresh_config($opts{d}); +	} + +	return $ret; +} + +sub uninstall { +	my $name; +	my $uninstall; + +	if ($ARGV[0] eq '-a') { +		system("rm -rf ./package/feeds"); +		$uninstall = 1; +	} else { +		get_installed(); +		while ($name = shift @ARGV) { +			my $pkg = $installed{$name}; +			$pkg or do { +				warn "WARNING: $name not installed\n"; +				next; +			}; +			$pkg->{src} and $name = $pkg->{src}; +			warn "Uninstalling package '$name'\n"; +			system("rm -f ./package/feeds/*/$name"); +			$uninstall = 1; +		} +	} +	$uninstall and refresh_config(); +	return 0; +} + +sub usage() { +	print <<EOF; +Usage: $0 <command> [options] + +Commands: +	install [options] <package>: Install a package +	Options: +	    -p <feedname>: Prefer this feed when installing packages +	    -d <y|m|n>:    Set default for newly installed packages + +	search [options] <substring>: Search for a package +	Options: +	    -r <feedname>: Only search in this feed + +	uninstall -a|<package>: Uninstall a package +	    -a uninstalls all packages + +	update:	Update packages and lists of feeds in feeds.list +	clean: Remove downloaded/generated files + +EOF +	exit(1); +} + +my %update_method = ( +	'src-svn' => \&update_svn +); + +my %commands = ( +	'update' => sub { +		-d "feeds" or do { +			mkdir "feeds" or die "Unable to create the feeds directory"; +		}; +		$ENV{SCAN_COOKIE} = $$; +		$ENV{KBUILD_VERBOSE} = 99; +		foreach my $feed (@feeds) { +			my ($type, $name, $src) = @$feed; +			$update_method{$type} or do { +				warn "Unknown type '$type' in feed $name\n"; +				next; +			}; +			warn "Updating feed '$name'...\n"; +			&{$update_method{$type}}($name, $src) == 0 or do { +				warn "failed.\n"; +				return 1; +			}; +		} +		return 0; +	}, +	'install' => \&install, +	'search' => \&search, +	'uninstall' => \&uninstall, +	'clean' => sub { +		system("rm -rf feeds"); +	} +); + +my $arg = shift @ARGV; +$arg or usage(); +parse_config; +foreach my $cmd (keys %commands) { +	$arg eq $cmd and do { +		exit(&{$commands{$cmd}}()); +	}; +} +usage(); diff --git a/scripts/metadata.pl b/scripts/metadata.pl index 03041f97c..f3d6e9df2 100755 --- a/scripts/metadata.pl +++ b/scripts/metadata.pl @@ -1,23 +1,10 @@  #!/usr/bin/perl +use FindBin; +use lib "$FindBin::Bin";  use strict; -my %preconfig; -my %package; -my %srcpackage; -my %category; -my %subdir; -my %board; - -sub get_multiline { -	my $prefix = shift; -	my $str; -	while (<>) { -		last if /^@@/; -		s/^\s*//g; -		$str .= (($_ and $prefix) ? $prefix . $_ : $_); -	} +use metadata; -	return $str; -} +my %board;  sub confstr($) {  	my $conf = shift; @@ -26,8 +13,13 @@ sub confstr($) {  }  sub parse_target_metadata() { -	my ($target, @target, $profile);	 -	while (<>) { +	my $file = shift @ARGV; +	my ($target, @target, $profile); +	open FILE, "<$file" or do { +		warn "Can't open file '$file': $!\n"; +		return; +	}; +	while (<FILE>) {  		chomp;  		/^Target:\s*(.+)\s*$/ and do {  			$target = { @@ -46,7 +38,7 @@ sub parse_target_metadata() {  		/^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1;  		/^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;  		/^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ]; -		/^Target-Description:/ and $target->{desc} = get_multiline(); +		/^Target-Description:/ and $target->{desc} = get_multiline(*FILE);  		/^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1;  		/^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1;  		/^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1; @@ -61,10 +53,11 @@ sub parse_target_metadata() {  		};  		/^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;  		/^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ]; -		/^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(); -		/^Target-Profile-Config:/ and $profile->{config} = get_multiline("\t"); +		/^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE); +		/^Target-Profile-Config:/ and $profile->{config} = get_multiline(*FILE, "\t");  		/^Target-Profile-Kconfig:/ and $profile->{kconfig} = 1;  	} +	close FILE;  	foreach my $target (@target) {  		@{$target->{profiles}} > 0 or $target->{profiles} = [  			{ @@ -77,78 +70,6 @@ sub parse_target_metadata() {  	return @target;  } -sub parse_package_metadata() { -	my $pkg; -	my $makefile; -	my $preconfig; -	my $subdir; -	my $src; -	while (<>) { -		chomp; -		/^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do { -			$makefile = $1; -			$subdir = $2; -			$src = $3; -			$subdir =~ s/^package\///; -			$subdir{$src} = $subdir; -			$srcpackage{$src} = []; -			undef $pkg; -		}; -		/^Package:\s*(.+?)\s*$/ and do { -			$pkg = {}; -			$pkg->{src} = $src; -			$pkg->{makefile} = $makefile; -			$pkg->{name} = $1; -			$pkg->{default} = "m if ALL"; -			$pkg->{depends} = []; -			$pkg->{builddepends} = []; -			$pkg->{subdir} = $subdir; -			$package{$1} = $pkg; -			push @{$srcpackage{$src}}, $pkg; -		}; -		/^Version: \s*(.+)\s*$/ and $pkg->{version} = $1; -		/^Title: \s*(.+)\s*$/ and $pkg->{title} = $1; -		/^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1; -		/^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1; -		/^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1; -		/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; -		/^Provides: \s*(.+)\s*$/ and do { -			my @vpkg = split /\s+/, $1; -			foreach my $vpkg (@vpkg) { -				$package{$vpkg} or $package{$vpkg} = { vdepends => [] }; -				push @{$package{$vpkg}->{vdepends}}, $pkg->{name}; -			} -		}; -		/^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ]; -		/^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ]; -		/^Category: \s*(.+)\s*$/ and do { -			$pkg->{category} = $1; -			defined $category{$1} or $category{$1} = {}; -			defined $category{$1}->{$src} or $category{$1}->{$src} = []; -			push @{$category{$1}->{$src}}, $pkg; -		}; -		/^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline("\t\t "); -		/^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(); -		/^Prereq-Check:/ and $pkg->{prereq} = 1; -		/^Preconfig:\s*(.+)\s*$/ and do { -			my $pkgname = $pkg->{name}; -			$preconfig{$pkgname} or $preconfig{$pkgname} = {}; -			if (exists $preconfig{$pkgname}->{$1}) { -				$preconfig = $preconfig{$pkgname}->{$1}; -			} else { -				$preconfig = { -					id => $1 -				}; -				$preconfig{$pkgname}->{$1} = $preconfig; -			} -		}; -		/^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1; -		/^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1; -		/^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1; -	} -	return %category; -} -  sub gen_kconfig_overrides() {  	my %config;  	my %kconfig; @@ -318,20 +239,31 @@ EOF  	print "endchoice\n";  } - -sub find_package_dep($$) { +my %dep_check; +sub __find_package_dep($$) {  	my $pkg = shift;  	my $name = shift;  	my $deps = ($pkg->{vdepends} or $pkg->{depends});  	return 0 unless defined $deps;  	foreach my $dep (@{$deps}) { +		next if $dep_check{$dep}; +		$dep_check{$dep} = 1;  		return 1 if $dep eq $name; -		return 1 if ($package{$dep} and (find_package_dep($package{$dep},$name) == 1)); +		return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));  	}  	return 0;  } +# wrapper to avoid infinite recursion +sub find_package_dep($$) { +	my $pkg = shift; +	my $name = shift; + +	%dep_check = (); +	return __find_package_dep($pkg, $name); +} +  sub package_depends($$) {  	my $a = shift;  	my $b = shift; @@ -452,7 +384,7 @@ sub print_package_config_category($) {  }  sub gen_package_config() { -	parse_package_metadata(); +	parse_package_metadata($ARGV[0]) or exit 1;  	print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n";  	foreach my $preconfig (keys %preconfig) {  		foreach my $cfg (keys %{$preconfig{$preconfig}}) { @@ -478,7 +410,7 @@ sub gen_package_mk() {  	my %dep;  	my $line; -	parse_package_metadata(); +	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}; diff --git a/scripts/metadata.pm b/scripts/metadata.pm new file mode 100644 index 000000000..f90446298 --- /dev/null +++ b/scripts/metadata.pm @@ -0,0 +1,113 @@ +package metadata; +use base 'Exporter'; +use strict; +use warnings; +our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig clear_packages parse_package_metadata get_multiline); + +our %package; +our %preconfig; +our %srcpackage; +our %category; +our %subdir; + +sub get_multiline { +	my $fh = shift; +	my $prefix = shift; +	my $str; +	while (<$fh>) { +		last if /^@@/; +		s/^\s*//g; +		$str .= (($_ and $prefix) ? $prefix . $_ : $_); +	} + +	return $str ? $str : ""; +} + +sub clear_packages() { +	%subdir = (); +	%preconfig = (); +	%package = (); +	%srcpackage = (); +	%category = (); +} + +sub parse_package_metadata($) { +	my $file = shift; +	my $pkg; +	my $makefile; +	my $preconfig; +	my $subdir; +	my $src; + +	open FILE, "<$file" or do { +		warn "Cannot open '$file': $!\n"; +		return undef; +	}; +	while (<FILE>) { +		chomp; +		/^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do { +			$makefile = $1; +			$subdir = $2; +			$src = $3; +			$subdir =~ s/^package\///; +			$subdir{$src} = $subdir; +			$srcpackage{$src} = []; +			undef $pkg; +		}; +		/^Package:\s*(.+?)\s*$/ and do { +			$pkg = {}; +			$pkg->{src} = $src; +			$pkg->{makefile} = $makefile; +			$pkg->{name} = $1; +			$pkg->{default} = "m if ALL"; +			$pkg->{depends} = []; +			$pkg->{builddepends} = []; +			$pkg->{subdir} = $subdir; +			$package{$1} = $pkg; +			push @{$srcpackage{$src}}, $pkg; +		}; +		/^Version: \s*(.+)\s*$/ and $pkg->{version} = $1; +		/^Title: \s*(.+)\s*$/ and $pkg->{title} = $1; +		/^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1; +		/^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1; +		/^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1; +		/^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; +		/^Provides: \s*(.+)\s*$/ and do { +			my @vpkg = split /\s+/, $1; +			foreach my $vpkg (@vpkg) { +				$package{$vpkg} or $package{$vpkg} = { vdepends => [] }; +				push @{$package{$vpkg}->{vdepends}}, $pkg->{name}; +			} +		}; +		/^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ]; +		/^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ]; +		/^Category: \s*(.+)\s*$/ and do { +			$pkg->{category} = $1; +			defined $category{$1} or $category{$1} = {}; +			defined $category{$1}->{$src} or $category{$1}->{$src} = []; +			push @{$category{$1}->{$src}}, $pkg; +		}; +		/^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline(*FILE, "\t\t "); +		/^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE); +		/^Prereq-Check:/ and $pkg->{prereq} = 1; +		/^Preconfig:\s*(.+)\s*$/ and do { +			my $pkgname = $pkg->{name}; +			$preconfig{$pkgname} or $preconfig{$pkgname} = {}; +			if (exists $preconfig{$pkgname}->{$1}) { +				$preconfig = $preconfig{$pkgname}->{$1}; +			} else { +				$preconfig = { +					id => $1 +				}; +				$preconfig{$pkgname}->{$1} = $preconfig; +			} +		}; +		/^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1; +		/^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1; +		/^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1; +	} +	close FILE; +	return %category; +} + +1; | 
