1package metadata; 2use base 'Exporter'; 3use strict; 4use warnings; 5our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore); 6 7our %package; 8our %preconfig; 9our %srcpackage; 10our %category; 11our %subdir; 12our %features; 13our %overrides; 14our @ignore; 15 16sub get_multiline { 17 my $fh = shift; 18 my $prefix = shift; 19 my $str; 20 while (<$fh>) { 21 last if /^@@/; 22 $str .= (($_ and $prefix) ? $prefix . $_ : $_); 23 } 24 25 return $str ? $str : ""; 26} 27 28sub confstr($) { 29 my $conf = shift; 30 $conf =~ tr#/\.\-/#___#; 31 return $conf; 32} 33 34sub parse_target_metadata($) { 35 my $file = shift; 36 my ($target, @target, $profile); 37 my %target; 38 my $makefile; 39 40 open FILE, "<$file" or do { 41 warn "Can't open file '$file': $!\n"; 42 return; 43 }; 44 while (<FILE>) { 45 chomp; 46 /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and $makefile = $1; 47 /^Target:\s*(.+)\s*$/ and do { 48 my $name = $1; 49 $target = { 50 id => $name, 51 board => $name, 52 makefile => $makefile, 53 boardconf => confstr($name), 54 conf => confstr($name), 55 profiles => [], 56 features => [], 57 depends => [], 58 subtargets => [] 59 }; 60 push @target, $target; 61 $target{$name} = $target; 62 if ($name =~ /([^\/]+)\/([^\/]+)/) { 63 push @{$target{$1}->{subtargets}}, $2; 64 $target->{board} = $1; 65 $target->{boardconf} = confstr($1); 66 $target->{subtarget} = 1; 67 $target->{parent} = $target{$1}; 68 } 69 }; 70 /^Target-Name:\s*(.+)\s*$/ and $target->{name} = $1; 71 /^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1; 72 /^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1; 73 /^Target-Arch-Packages:\s*(.+)\s*$/ and $target->{arch_packages} = $1; 74 /^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ]; 75 /^Target-Depends:\s*(.+)\s*$/ and $target->{depends} = [ split(/\s+/, $1) ]; 76 /^Target-Description:/ and $target->{desc} = get_multiline(*FILE); 77 /^Target-Optimization:\s*(.+)\s*$/ and $target->{cflags} = $1; 78 /^CPU-Type:\s*(.+)\s*$/ and $target->{cputype} = $1; 79 /^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1; 80 /^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1; 81 /^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1; 82 /^Default-Subtarget:\s*(.+)\s*$/ and $target->{def_subtarget} = $1; 83 /^Default-Packages:\s*(.+)\s*$/ and $target->{packages} = [ split(/\s+/, $1) ]; 84 /^Target-Profile:\s*(.+)\s*$/ and do { 85 $profile = { 86 id => $1, 87 name => $1, 88 packages => [] 89 }; 90 push @{$target->{profiles}}, $profile; 91 }; 92 /^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1; 93 /^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ]; 94 /^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE); 95 /^Target-Profile-Config:/ and $profile->{config} = get_multiline(*FILE, "\t"); 96 /^Target-Profile-Kconfig:/ and $profile->{kconfig} = 1; 97 } 98 close FILE; 99 foreach my $target (@target) { 100 if (@{$target->{subtargets}} > 0) { 101 $target->{profiles} = []; 102 next; 103 } 104 @{$target->{profiles}} > 0 or $target->{profiles} = [ 105 { 106 id => 'Default', 107 name => 'Default', 108 packages => [] 109 } 110 ]; 111 } 112 return @target; 113} 114 115sub clear_packages() { 116 %subdir = (); 117 %preconfig = (); 118 %package = (); 119 %srcpackage = (); 120 %category = (); 121 %features = (); 122 %overrides = (); 123} 124 125sub parse_package_metadata($) { 126 my $file = shift; 127 my $pkg; 128 my $feature; 129 my $makefile; 130 my $preconfig; 131 my $subdir; 132 my $src; 133 my $override; 134 my %ignore = map { $_ => 1 } @ignore; 135 136 open FILE, "<$file" or do { 137 warn "Cannot open '$file': $!\n"; 138 return undef; 139 }; 140 while (<FILE>) { 141 chomp; 142 /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do { 143 $makefile = $1; 144 $subdir = $2; 145 $src = $3; 146 $subdir =~ s/^package\///; 147 $subdir{$src} = $subdir; 148 $srcpackage{$src} = []; 149 $override = ""; 150 undef $pkg; 151 }; 152 /^Override: \s*(.+?)\s*$/ and do { 153 $override = $1; 154 $overrides{$src} = 1; 155 }; 156 next unless $src; 157 next if $ignore{$src}; 158 /^Package:\s*(.+?)\s*$/ and do { 159 undef $feature; 160 $pkg = {}; 161 $pkg->{src} = $src; 162 $pkg->{makefile} = $makefile; 163 $pkg->{name} = $1; 164 $pkg->{title} = ""; 165 $pkg->{depends} = []; 166 $pkg->{mdepends} = []; 167 $pkg->{builddepends} = []; 168 $pkg->{buildtypes} = []; 169 $pkg->{subdir} = $subdir; 170 $pkg->{tristate} = 1; 171 $pkg->{override} = $override; 172 $package{$1} = $pkg; 173 push @{$srcpackage{$src}}, $pkg; 174 }; 175 /^Feature:\s*(.+?)\s*$/ and do { 176 undef $pkg; 177 $feature = {}; 178 $feature->{name} = $1; 179 $feature->{priority} = 0; 180 }; 181 $feature and do { 182 /^Target-Name:\s*(.+?)\s*$/ and do { 183 $features{$1} or $features{$1} = []; 184 push @{$features{$1}}, $feature; 185 }; 186 /^Target-Title:\s*(.+?)\s*$/ and $feature->{target_title} = $1; 187 /^Feature-Priority:\s*(\d+)\s*$/ and $feature->{priority} = $1; 188 /^Feature-Name:\s*(.+?)\s*$/ and $feature->{title} = $1; 189 /^Feature-Description:/ and $feature->{description} = get_multiline(\*FILE, "\t\t\t"); 190 next; 191 }; 192 next unless $pkg; 193 /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1; 194 /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1; 195 /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1; 196 /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1; 197 /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1; 198 /^Source: \s*(.+)\s*$/ and $pkg->{source} = $1; 199 /^License: \s*(.+)\s*$/ and $pkg->{license} = $1; 200 /^LicenseFiles: \s*(.+)\s*$/ and $pkg->{licensefiles} = $1; 201 /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; 202 /^Provides: \s*(.+)\s*$/ and do { 203 my @vpkg = split /\s+/, $1; 204 foreach my $vpkg (@vpkg) { 205 $package{$vpkg} or $package{$vpkg} = { 206 name => $vpkg, 207 vdepends => [], 208 src => $src, 209 subdir => $subdir, 210 makefile => $makefile 211 }; 212 push @{$package{$vpkg}->{vdepends}}, $pkg->{name}; 213 } 214 }; 215 /^Menu-Depends: \s*(.+)\s*$/ and $pkg->{mdepends} = [ split /\s+/, $1 ]; 216 /^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ]; 217 /^Conflicts: \s*(.+)\s*$/ and $pkg->{conflicts} = [ split /\s+/, $1 ]; 218 /^Hidden: \s*(.+)\s*$/ and $pkg->{hidden} = 1; 219 /^Build-Variant: \s*([\w\-]+)\s*/ and $pkg->{variant} = $1; 220 /^Default-Variant: .*/ and $pkg->{variant_default} = 1; 221 /^Build-Only: \s*(.+)\s*$/ and $pkg->{buildonly} = 1; 222 /^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ]; 223 /^Build-Depends\/(\w+): \s*(.+)\s*$/ and $pkg->{"builddepends/$1"} = [ split /\s+/, $2 ]; 224 /^Build-Types:\s*(.+)\s*$/ and $pkg->{buildtypes} = [ split /\s+/, $1 ]; 225 /^Package-Subdir:\s*(.+?)\s*$/ and $pkg->{package_subdir} = $1; 226 /^Category: \s*(.+)\s*$/ and do { 227 $pkg->{category} = $1; 228 defined $category{$1} or $category{$1} = {}; 229 defined $category{$1}->{$src} or $category{$1}->{$src} = []; 230 push @{$category{$1}->{$src}}, $pkg; 231 }; 232 /^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline(*FILE, "\t\t "); 233 /^Type: \s*(.+)\s*$/ and do { 234 $pkg->{type} = [ split /\s+/, $1 ]; 235 undef $pkg->{tristate}; 236 foreach my $type (@{$pkg->{type}}) { 237 $type =~ /ipkg/ and $pkg->{tristate} = 1; 238 } 239 }; 240 /^Config:\s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE, "\t"); 241 /^Prereq-Check:/ and $pkg->{prereq} = 1; 242 /^Preconfig:\s*(.+)\s*$/ and do { 243 my $pkgname = $pkg->{name}; 244 $preconfig{$pkgname} or $preconfig{$pkgname} = {}; 245 if (exists $preconfig{$pkgname}->{$1}) { 246 $preconfig = $preconfig{$pkgname}->{$1}; 247 } else { 248 $preconfig = { 249 id => $1 250 }; 251 $preconfig{$pkgname}->{$1} = $preconfig; 252 } 253 }; 254 /^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1; 255 /^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1; 256 /^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1; 257 } 258 close FILE; 259 return 1; 260} 261 2621; 263