mediatek: fix IPv4-only corner case and commit in 99-net-ps
[oweals/openwrt.git] / scripts / target-metadata.pl
1 #!/usr/bin/env perl
2 use FindBin;
3 use lib "$FindBin::Bin";
4 use strict;
5 use metadata;
6 use Getopt::Long;
7
8 sub target_config_features(@) {
9         my $ret;
10
11         while ($_ = shift @_) {
12                 /^arm_v(\w+)$/ and $ret .= "\tselect arm_v$1\n";
13                 /^broken$/ and $ret .= "\tdepends on BROKEN\n";
14                 /^audio$/ and $ret .= "\tselect AUDIO_SUPPORT\n";
15                 /^display$/ and $ret .= "\tselect DISPLAY_SUPPORT\n";
16                 /^dt$/ and $ret .= "\tselect USES_DEVICETREE\n";
17                 /^gpio$/ and $ret .= "\tselect GPIO_SUPPORT\n";
18                 /^pci$/ and $ret .= "\tselect PCI_SUPPORT\n";
19                 /^pcie$/ and $ret .= "\tselect PCIE_SUPPORT\n";
20                 /^usb$/ and $ret .= "\tselect USB_SUPPORT\n";
21                 /^usbgadget$/ and $ret .= "\tselect USB_GADGET_SUPPORT\n";
22                 /^pcmcia$/ and $ret .= "\tselect PCMCIA_SUPPORT\n";
23                 /^rtc$/ and $ret .= "\tselect RTC_SUPPORT\n";
24                 /^squashfs$/ and $ret .= "\tselect USES_SQUASHFS\n";
25                 /^jffs2$/ and $ret .= "\tselect USES_JFFS2\n";
26                 /^jffs2_nand$/ and $ret .= "\tselect USES_JFFS2_NAND\n";
27                 /^ext4$/ and $ret .= "\tselect USES_EXT4\n";
28                 /^targz$/ and $ret .= "\tselect USES_TARGZ\n";
29                 /^cpiogz$/ and $ret .= "\tselect USES_CPIOGZ\n";
30                 /^minor$/ and $ret .= "\tselect USES_MINOR\n";
31                 /^ubifs$/ and $ret .= "\tselect USES_UBIFS\n";
32                 /^fpu$/ and $ret .= "\tselect HAS_FPU\n";
33                 /^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n";
34                 /^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n";
35                 /^powerpc64$/ and $ret .= "\tselect powerpc64\n";
36                 /^nommu$/ and $ret .= "\tselect NOMMU\n";
37                 /^mips16$/ and $ret .= "\tselect HAS_MIPS16\n";
38                 /^rfkill$/ and $ret .= "\tselect RFKILL_SUPPORT\n";
39                 /^low_mem$/ and $ret .= "\tselect LOW_MEMORY_FOOTPRINT\n";
40                 /^small_flash$/ and $ret .= "\tselect SMALL_FLASH\n";
41                 /^nand$/ and $ret .= "\tselect NAND_SUPPORT\n";
42                 /^virtio$/ and $ret .= "\tselect VIRTIO_SUPPORT\n";
43                 /^rootfs-part$/ and $ret .= "\tselect USES_ROOTFS_PART\n";
44                 /^boot-part$/ and $ret .= "\tselect USES_BOOT_PART\n";
45                 /^testing-kernel$/ and $ret .= "\tselect HAS_TESTING_KERNEL\n";
46         }
47         return $ret;
48 }
49
50 sub target_name($) {
51         my $target = shift;
52         my $parent = $target->{parent};
53         if ($parent) {
54                 return $target->{parent}->{name}." - ".$target->{name};
55         } else {
56                 return $target->{name};
57         }
58 }
59
60 sub kver($) {
61         my $v = shift;
62         $v =~ tr/\./_/;
63         if (substr($v,0,2) eq "2_") {
64                 $v =~ /(\d+_\d+_\d+)(_\d+)?/ and $v = $1;
65         } else {
66                 $v =~ /(\d+_\d+)(_\d+)?/ and $v = $1;
67         }
68         return $v;
69 }
70
71 sub print_target($) {
72         my $target = shift;
73         my $features = target_config_features(@{$target->{features}});
74         my $help = $target->{desc};
75         my $confstr;
76
77         chomp $features;
78         $features .= "\n";
79         if ($help =~ /\w+/) {
80                 $help =~ s/^\s*/\t  /mg;
81                 $help = "\thelp\n$help";
82         } else {
83                 undef $help;
84         }
85
86         my $v = kver($target->{version});
87         my $tv = kver($target->{testing_version});
88         $tv or $tv = $v;
89         if (@{$target->{subtargets}} == 0) {
90         $confstr = <<EOF;
91 config TARGET_$target->{conf}
92         bool "$target->{name}"
93         select LINUX_$v if !TESTING_KERNEL
94         select LINUX_$tv if TESTING_KERNEL
95 EOF
96         }
97         else {
98                 $confstr = <<EOF;
99 config TARGET_$target->{conf}
100         bool "$target->{name}"
101 EOF
102         }
103         if ($target->{subtarget}) {
104                 $confstr .= "\tdepends on TARGET_$target->{boardconf}\n";
105         }
106         if (@{$target->{subtargets}} > 0) {
107                 $confstr .= "\tselect HAS_SUBTARGETS\n";
108                 grep { /broken/ } @{$target->{features}} and $confstr .= "\tdepends on BROKEN\n";
109         } else {
110                 $confstr .= $features;
111                 if ($target->{arch} =~ /\w/) {
112                         $confstr .= "\tselect $target->{arch}\n";
113                 }
114                 if ($target->{has_devices}) {
115                         $confstr .= "\tselect HAS_DEVICES\n";
116                 }
117         }
118
119         foreach my $dep (@{$target->{depends}}) {
120                 my $mode = "depends on";
121                 my $flags;
122                 my $name;
123
124                 $dep =~ /^([@\+\-]+)(.+)$/;
125                 $flags = $1;
126                 $name = $2;
127
128                 next if $name =~ /:/;
129                 $flags =~ /-/ and $mode = "deselect";
130                 $flags =~ /\+/ and $mode = "select";
131                 $flags =~ /@/ and $confstr .= "\t$mode $name\n";
132         }
133         $confstr .= "$help\n\n";
134         print $confstr;
135 }
136
137 sub merge_package_lists($$) {
138         my $list1 = shift;
139         my $list2 = shift;
140         my @l = ();
141         my %pkgs;
142
143         foreach my $pkg (@$list1, @$list2) {
144                 $pkgs{$pkg} = 1;
145         }
146         foreach my $pkg (keys %pkgs) {
147                 push @l, $pkg unless ($pkg =~ /^-/ or $pkgs{"-$pkg"});
148         }
149         return sort(@l);
150 }
151
152 sub gen_target_config() {
153         my $file = shift @ARGV;
154         my @target = parse_target_metadata($file);
155         my %defaults;
156
157         my @target_sort = sort {
158                 target_name($a) cmp target_name($b);
159         } @target;
160
161         foreach my $target (@target_sort) {
162                 next if @{$target->{subtargets}} > 0;
163                 print <<EOF;
164 config DEFAULT_TARGET_$target->{conf}
165         bool
166         depends on TARGET_PER_DEVICE_ROOTFS
167         default y if TARGET_$target->{conf}
168 EOF
169                 foreach my $pkg (@{$target->{packages}}) {
170                         print "\tselect DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n";
171                 }
172         }
173
174         print <<EOF;
175 choice
176         prompt "Target System"
177         default TARGET_ath79
178         reset if !DEVEL
179         
180 EOF
181
182         foreach my $target (@target_sort) {
183                 next if $target->{subtarget};
184                 print_target($target);
185         }
186
187         print <<EOF;
188 endchoice
189
190 choice
191         prompt "Subtarget" if HAS_SUBTARGETS
192 EOF
193         foreach my $target (@target) {
194                 next unless $target->{def_subtarget};
195                 print <<EOF;
196         default TARGET_$target->{conf}_$target->{def_subtarget} if TARGET_$target->{conf}
197 EOF
198         }
199         print <<EOF;
200
201 EOF
202         foreach my $target (@target) {
203                 next unless $target->{subtarget};
204                 print_target($target);
205         }
206
207 print <<EOF;
208 endchoice
209
210 choice
211         prompt "Target Profile"
212         default TARGET_MULTI_PROFILE if BUILDBOT
213
214 EOF
215         foreach my $target (@target) {
216                 my $profile = $target->{profiles}->[0];
217                 $profile or next;
218                 print <<EOF;
219         default TARGET_$target->{conf}_$profile->{id} if TARGET_$target->{conf} && !BUILDBOT
220 EOF
221         }
222
223         print <<EOF;
224
225 config TARGET_MULTI_PROFILE
226         bool "Multiple devices"
227         depends on HAS_DEVICES
228         help
229         Instead of only building a single image, or all images, this allows you
230         to select images to be built for multiple devices in one build.
231
232 EOF
233
234         foreach my $target (@target) {
235                 my $profiles = $target->{profiles};
236                 foreach my $profile (@{$target->{profiles}}) {
237                         print <<EOF;
238 config TARGET_$target->{conf}_$profile->{id}
239         bool "$profile->{name}"
240         depends on TARGET_$target->{conf}
241 EOF
242                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
243                         foreach my $pkg (@pkglist) {
244                                 print "\tselect DEFAULT_$pkg\n";
245                                 $defaults{$pkg} = 1;
246                         }
247                         my $help = $profile->{desc};
248                         if ($help =~ /\w+/) {
249                                 $help =~ s/^\s*/\t  /mg;
250                                 $help = "\thelp\n$help";
251                         } else {
252                                 undef $help;
253                         }
254                         print "$help\n";
255                 }
256         }
257
258         print <<EOF;
259 endchoice
260
261 menu "Target Devices"
262         depends on TARGET_MULTI_PROFILE
263
264         config TARGET_ALL_PROFILES
265                 bool "Enable all profiles by default"
266                 default BUILDBOT
267
268         config TARGET_PER_DEVICE_ROOTFS
269                 bool "Use a per-device root filesystem that adds profile packages"
270                 default BUILDBOT
271                 help
272                 When disabled, all device packages from all selected devices
273                 will be included in all images by default. (Marked as <*>) You will
274                 still be able to manually deselect any/all packages.
275                 When enabled, each device builds it's own image, including only the
276                 profile packages for that device.  (Marked as {M}) You will be able
277                 to change a package to included in all images by marking as {*}, but
278                 will not be able to disable a profile package completely.
279                 
280                 To get the most use of this setting, you must set in a .config stub
281                 before calling "make defconfig".  Selecting TARGET_MULTI_PROFILE and
282                 then manually selecting (via menuconfig for instance) this option
283                 will have pre-defaulted all profile packages to included, making this
284                 option appear to have had no effect.
285
286 EOF
287         foreach my $target (@target) {
288                 my @profiles = sort {
289                         my $x = $a->{name};
290                         my $y = $b->{name};
291                         "\L$x" cmp "\L$y";
292                 } @{$target->{profiles}};
293                 foreach my $profile (@profiles) {
294                         next unless $profile->{id} =~ /^DEVICE_/;
295                         print <<EOF;
296 menuconfig TARGET_DEVICE_$target->{conf}_$profile->{id}
297         bool "$profile->{name}"
298         depends on TARGET_$target->{conf}
299         default $profile->{default}
300 EOF
301                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
302                         foreach my $pkg (@pkglist) {
303                                 print "\tselect DEFAULT_$pkg if !TARGET_PER_DEVICE_ROOTFS\n";
304                                 print "\tselect MODULE_DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n";
305                                 $defaults{$pkg} = 1;
306                         }
307
308                         print <<EOF;
309
310
311         config TARGET_DEVICE_PACKAGES_$target->{conf}_$profile->{id}
312                 string "$profile->{name} additional packages"
313                 default ""
314                 depends on TARGET_PER_DEVICE_ROOTFS
315                 depends on TARGET_DEVICE_$target->{conf}_$profile->{id}
316
317 EOF
318                 }
319         }
320
321         print <<EOF;
322
323 endmenu
324
325 config HAS_SUBTARGETS
326         bool
327
328 config HAS_DEVICES
329         bool
330
331 config TARGET_BOARD
332         string
333
334 EOF
335         foreach my $target (@target) {
336                 $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
337         }
338         print <<EOF;
339 config TARGET_SUBTARGET
340         string
341         default "generic" if !HAS_SUBTARGETS
342
343 EOF
344
345         foreach my $target (@target) {
346                 foreach my $subtarget (@{$target->{subtargets}}) {
347                         print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
348                 }
349         }
350         print <<EOF;
351 config TARGET_PROFILE
352         string
353 EOF
354         foreach my $target (@target) {
355                 my $profiles = $target->{profiles};
356                 foreach my $profile (@$profiles) {
357                         print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
358                 }
359         }
360
361         print <<EOF;
362
363 config TARGET_ARCH_PACKAGES
364         string
365         
366 EOF
367         foreach my $target (@target) {
368                 next if @{$target->{subtargets}} > 0;
369                 print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
370         }
371         print <<EOF;
372
373 config DEFAULT_TARGET_OPTIMIZATION
374         string
375 EOF
376         foreach my $target (@target) {
377                 next if @{$target->{subtargets}} > 0;
378                 print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
379         }
380         print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
381         print <<EOF;
382
383 config CPU_TYPE
384         string
385 EOF
386         foreach my $target (@target) {
387                 next if @{$target->{subtargets}} > 0;
388                 print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
389         }
390         print "\tdefault \"\"\n";
391
392         my %kver;
393         foreach my $target (@target) {
394                 foreach my $tv ($target->{version}, $target->{testing_version}) {
395                         next unless $tv;
396                         my $v = kver($tv);
397                         next if $kver{$v};
398                         $kver{$v} = 1;
399                         print <<EOF;
400
401 config LINUX_$v
402         bool
403
404 EOF
405                 }
406         }
407         foreach my $def (sort keys %defaults) {
408                 print <<EOF;
409         config DEFAULT_$def
410                 bool
411
412         config MODULE_DEFAULT_$def
413                 tristate
414                 depends on TARGET_PER_DEVICE_ROOTFS
415                 depends on m
416                 default m if DEFAULT_$def
417                 select PACKAGE_$def
418
419 EOF
420         }
421 }
422
423 sub gen_profile_mk() {
424         my $file = shift @ARGV;
425         my $target = shift @ARGV;
426         my @targets = parse_target_metadata($file);
427         foreach my $cur (@targets) {
428                 next unless $cur->{id} eq $target;
429                 print "PROFILE_NAMES = ".join(" ", map { $_->{id} } @{$cur->{profiles}})."\n";
430                 foreach my $profile (@{$cur->{profiles}}) {
431                         print $profile->{id}.'_NAME:='.$profile->{name}."\n";
432                         print $profile->{id}.'_HAS_IMAGE_METADATA:='.$profile->{has_image_metadata}."\n";
433                         if (defined($profile->{supported_devices}) and @{$profile->{supported_devices}} > 0) {
434                                 print $profile->{id}.'_SUPPORTED_DEVICES:='.join(' ', @{$profile->{supported_devices}})."\n";
435                         }
436                         print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n";
437                 }
438         }
439 }
440
441 sub parse_command() {
442         GetOptions("ignore=s", \@ignore);
443         my $cmd = shift @ARGV;
444         for ($cmd) {
445                 /^config$/ and return gen_target_config();
446                 /^profile_mk$/ and return gen_profile_mk();
447         }
448         die <<EOF
449 Available Commands:
450         $0 config [file]                        Target metadata in Kconfig format
451         $0 profile_mk [file] [target]           Profile metadata in makefile format
452
453 EOF
454 }
455
456 parse_command();