a7239166f7b1ffb5d411bafeedc0b79d33d1373d
[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         }
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
207 EOF
208         foreach my $target (@target) {
209                 my $profile = $target->{profiles}->[0];
210                 $profile or next;
211                 print <<EOF;
212         default TARGET_$target->{conf}_$profile->{id} if TARGET_$target->{conf}
213 EOF
214         }
215
216         print <<EOF;
217
218 config TARGET_MULTI_PROFILE
219         bool "Multiple devices"
220         depends on HAS_DEVICES
221
222 EOF
223
224         foreach my $target (@target) {
225                 my $profiles = $target->{profiles};
226                 foreach my $profile (@{$target->{profiles}}) {
227                         print <<EOF;
228 config TARGET_$target->{conf}_$profile->{id}
229         bool "$profile->{name}"
230         depends on TARGET_$target->{conf}
231 EOF
232                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
233                         foreach my $pkg (@pkglist) {
234                                 print "\tselect DEFAULT_$pkg\n";
235                                 $defaults{$pkg} = 1;
236                         }
237                         my $help = $profile->{desc};
238                         if ($help =~ /\w+/) {
239                                 $help =~ s/^\s*/\t  /mg;
240                                 $help = "\thelp\n$help";
241                         } else {
242                                 undef $help;
243                         }
244                         print "$help\n";
245                 }
246         }
247
248         print <<EOF;
249 endchoice
250
251 menu "Target Devices"
252         depends on TARGET_MULTI_PROFILE
253
254         config TARGET_ALL_PROFILES
255                 bool "Enable all profiles by default"
256
257         config TARGET_PER_DEVICE_ROOTFS
258                 bool "Use a per-device root filesystem that adds profile packages"
259
260 EOF
261         foreach my $target (@target) {
262                 my $profiles = $target->{profiles};
263                 foreach my $profile (@{$target->{profiles}}) {
264                         next unless $profile->{id} =~ /^DEVICE_/;
265                         print <<EOF;
266 config TARGET_DEVICE_$target->{conf}_$profile->{id}
267         bool "$profile->{name}"
268         depends on TARGET_$target->{conf}
269         default y if TARGET_ALL_PROFILES
270 EOF
271                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
272                         foreach my $pkg (@pkglist) {
273                                 print "\tselect DEFAULT_$pkg if !TARGET_PER_DEVICE_ROOTFS\n";
274                                 print "\tselect MODULE_DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n";
275                                 $defaults{$pkg} = 1;
276                         }
277                 }
278         }
279
280         print <<EOF;
281
282 endmenu
283
284 config HAS_SUBTARGETS
285         bool
286
287 config HAS_DEVICES
288         bool
289
290 config TARGET_BOARD
291         string
292
293 EOF
294         foreach my $target (@target) {
295                 $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
296         }
297         print <<EOF;
298 config TARGET_SUBTARGET
299         string
300         default "generic" if !HAS_SUBTARGETS
301
302 EOF
303
304         foreach my $target (@target) {
305                 foreach my $subtarget (@{$target->{subtargets}}) {
306                         print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
307                 }
308         }
309         print <<EOF;
310 config TARGET_PROFILE
311         string
312 EOF
313         foreach my $target (@target) {
314                 my $profiles = $target->{profiles};
315                 foreach my $profile (@$profiles) {
316                         print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
317                 }
318         }
319
320         print <<EOF;
321
322 config TARGET_ARCH_PACKAGES
323         string
324         
325 EOF
326         foreach my $target (@target) {
327                 next if @{$target->{subtargets}} > 0;
328                 print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
329         }
330         print <<EOF;
331
332 config DEFAULT_TARGET_OPTIMIZATION
333         string
334 EOF
335         foreach my $target (@target) {
336                 next if @{$target->{subtargets}} > 0;
337                 print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
338         }
339         print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
340         print <<EOF;
341
342 config CPU_TYPE
343         string
344 EOF
345         foreach my $target (@target) {
346                 next if @{$target->{subtargets}} > 0;
347                 print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
348         }
349         print "\tdefault \"\"\n";
350
351         my %kver;
352         foreach my $target (@target) {
353                 my $v = kver($target->{version});
354                 next if $kver{$v};
355                 $kver{$v} = 1;
356                 print <<EOF;
357
358 config LINUX_$v
359         bool
360
361 EOF
362         }
363         foreach my $def (sort keys %defaults) {
364                 print <<EOF;
365         config DEFAULT_$def
366                 bool
367
368         config MODULE_DEFAULT_$def
369                 tristate
370                 depends on TARGET_PER_DEVICE_ROOTFS
371                 depends on m
372                 default m if DEFAULT_$def
373                 select PACKAGE_$def
374
375 EOF
376         }
377 }
378
379 sub gen_profile_mk() {
380         my $file = shift @ARGV;
381         my $target = shift @ARGV;
382         my @targets = parse_target_metadata($file);
383         foreach my $cur (@targets) {
384                 next unless $cur->{id} eq $target;
385                 print "PROFILE_NAMES = ".join(" ", map { $_->{id} } @{$cur->{profiles}})."\n";
386                 foreach my $profile (@{$cur->{profiles}}) {
387                         print $profile->{id}.'_NAME:='.$profile->{name}."\n";
388                         print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n";
389                 }
390         }
391 }
392
393 sub parse_command() {
394         GetOptions("ignore=s", \@ignore);
395         my $cmd = shift @ARGV;
396         for ($cmd) {
397                 /^config$/ and return gen_target_config();
398                 /^profile_mk$/ and return gen_profile_mk();
399         }
400         die <<EOF
401 Available Commands:
402         $0 config [file]                        Target metadata in Kconfig format
403         $0 profile_mk [file] [target]           Profile metadata in makefile format
404
405 EOF
406 }
407
408 parse_command();