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