ea6462c94fea62d1b64e8ebe0f4954c163260234
[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                 /ubifs/ and $ret .= "\tselect USES_UBIFS\n";
31                 /fpu/ and $ret .= "\tselect HAS_FPU\n";
32                 /spe_fpu/ and $ret .= "\tselect HAS_SPE_FPU\n";
33                 /ramdisk/ and $ret .= "\tselect USES_INITRAMFS\n";
34                 /powerpc64/ and $ret .= "\tselect powerpc64\n";
35                 /nommu/ and $ret .= "\tselect NOMMU\n";
36                 /mips16/ and $ret .= "\tselect HAS_MIPS16\n";
37                 /rfkill/ and $ret .= "\tselect RFKILL_SUPPORT\n";
38                 /low_mem/ and $ret .= "\tselect LOW_MEMORY_FOOTPRINT\n";
39                 /small_flash/ and $ret .= "\tselect SMALL_FLASH\n";
40                 /nand/ and $ret .= "\tselect NAND_SUPPORT\n";
41         }
42         return $ret;
43 }
44
45 sub target_name($) {
46         my $target = shift;
47         my $parent = $target->{parent};
48         if ($parent) {
49                 return $target->{parent}->{name}." - ".$target->{name};
50         } else {
51                 return $target->{name};
52         }
53 }
54
55 sub kver($) {
56         my $v = shift;
57         $v =~ tr/\./_/;
58         if (substr($v,0,2) eq "2_") {
59                 $v =~ /(\d+_\d+_\d+)(_\d+)?/ and $v = $1;
60         } else {
61                 $v =~ /(\d+_\d+)(_\d+)?/ and $v = $1;
62         }
63         return $v;
64 }
65
66 sub print_target($) {
67         my $target = shift;
68         my $features = target_config_features(@{$target->{features}});
69         my $help = $target->{desc};
70         my $confstr;
71
72         chomp $features;
73         $features .= "\n";
74         if ($help =~ /\w+/) {
75                 $help =~ s/^\s*/\t  /mg;
76                 $help = "\thelp\n$help";
77         } else {
78                 undef $help;
79         }
80
81         my $v = kver($target->{version});
82         if (@{$target->{subtargets}} == 0) {
83         $confstr = <<EOF;
84 config TARGET_$target->{conf}
85         bool "$target->{name}"
86         select LINUX_$v
87 EOF
88         }
89         else {
90                 $confstr = <<EOF;
91 config TARGET_$target->{conf}
92         bool "$target->{name}"
93 EOF
94         }
95         if ($target->{subtarget}) {
96                 $confstr .= "\tdepends on TARGET_$target->{boardconf}\n";
97         }
98         if (@{$target->{subtargets}} > 0) {
99                 $confstr .= "\tselect HAS_SUBTARGETS\n";
100                 grep { /broken/ } @{$target->{features}} and $confstr .= "\tdepends on BROKEN\n";
101         } else {
102                 $confstr .= $features;
103                 if ($target->{arch} =~ /\w/) {
104                         $confstr .= "\tselect $target->{arch}\n";
105                 }
106                 if ($target->{has_devices}) {
107                         $confstr .= "\tselect HAS_DEVICES\n";
108                 }
109         }
110
111         foreach my $dep (@{$target->{depends}}) {
112                 my $mode = "depends on";
113                 my $flags;
114                 my $name;
115
116                 $dep =~ /^([@\+\-]+)(.+)$/;
117                 $flags = $1;
118                 $name = $2;
119
120                 next if $name =~ /:/;
121                 $flags =~ /-/ and $mode = "deselect";
122                 $flags =~ /\+/ and $mode = "select";
123                 $flags =~ /@/ and $confstr .= "\t$mode $name\n";
124         }
125         $confstr .= "$help\n\n";
126         print $confstr;
127 }
128
129 sub merge_package_lists($$) {
130         my $list1 = shift;
131         my $list2 = shift;
132         my @l = ();
133         my %pkgs;
134
135         foreach my $pkg (@$list1, @$list2) {
136                 $pkgs{$pkg} = 1;
137         }
138         foreach my $pkg (keys %pkgs) {
139                 push @l, $pkg unless ($pkg =~ /^-/ or $pkgs{"-$pkg"});
140         }
141         return sort(@l);
142 }
143
144 sub gen_target_config() {
145         my $file = shift @ARGV;
146         my @target = parse_target_metadata($file);
147         my %defaults;
148
149         my @target_sort = sort {
150                 target_name($a) cmp target_name($b);
151         } @target;
152
153
154         print <<EOF;
155 choice
156         prompt "Target System"
157         default TARGET_ar71xx
158         reset if !DEVEL
159         
160 EOF
161
162         foreach my $target (@target_sort) {
163                 next if $target->{subtarget};
164                 print_target($target);
165         }
166
167         print <<EOF;
168 endchoice
169
170 choice
171         prompt "Subtarget" if HAS_SUBTARGETS
172 EOF
173         foreach my $target (@target) {
174                 next unless $target->{def_subtarget};
175                 print <<EOF;
176         default TARGET_$target->{conf}_$target->{def_subtarget} if TARGET_$target->{conf}
177 EOF
178         }
179         print <<EOF;
180
181 EOF
182         foreach my $target (@target) {
183                 next unless $target->{subtarget};
184                 print_target($target);
185         }
186
187 print <<EOF;
188 endchoice
189
190 choice
191         prompt "Target Profile"
192
193 EOF
194         foreach my $target (@target) {
195                 my $profile = $target->{profiles}->[0];
196                 $profile or next;
197                 print <<EOF;
198         default TARGET_$target->{conf}_$profile->{id} if TARGET_$target->{conf}
199 EOF
200         }
201
202         print <<EOF;
203
204 config TARGET_MULTI_PROFILE
205         bool "Multiple devices"
206         depends on HAS_DEVICES
207
208 EOF
209
210         foreach my $target (@target) {
211                 my $profiles = $target->{profiles};
212                 foreach my $profile (@{$target->{profiles}}) {
213                         print <<EOF;
214 config TARGET_$target->{conf}_$profile->{id}
215         bool "$profile->{name}"
216         depends on TARGET_$target->{conf}
217 EOF
218                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
219                         foreach my $pkg (@pkglist) {
220                                 print "\tselect DEFAULT_$pkg\n";
221                                 $defaults{$pkg} = 1;
222                         }
223                         my $help = $profile->{desc};
224                         if ($help =~ /\w+/) {
225                                 $help =~ s/^\s*/\t  /mg;
226                                 $help = "\thelp\n$help";
227                         } else {
228                                 undef $help;
229                         }
230                         print "$help\n";
231                 }
232         }
233
234         print <<EOF;
235 endchoice
236
237 menu "Target Devices"
238         depends on TARGET_MULTI_PROFILE
239
240 EOF
241         foreach my $target (@target) {
242                 my $profiles = $target->{profiles};
243                 foreach my $profile (@{$target->{profiles}}) {
244                         next unless $profile->{id} =~ /^DEVICE_/;
245                         print <<EOF;
246 config TARGET_DEVICE_$target->{conf}_$profile->{id}
247         bool "$profile->{name}"
248         depends on TARGET_$target->{conf}
249 EOF
250                         my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
251                         foreach my $pkg (@pkglist) {
252                                 print "\tselect DEFAULT_$pkg\n";
253                                 $defaults{$pkg} = 1;
254                         }
255                 }
256         }
257
258         print <<EOF;
259
260 endmenu
261
262 config HAS_SUBTARGETS
263         bool
264
265 config HAS_DEVICES
266         bool
267
268 config TARGET_BOARD
269         string
270
271 EOF
272         foreach my $target (@target) {
273                 $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
274         }
275         print <<EOF;
276 config TARGET_SUBTARGET
277         string
278         default "generic" if !HAS_SUBTARGETS
279
280 EOF
281
282         foreach my $target (@target) {
283                 foreach my $subtarget (@{$target->{subtargets}}) {
284                         print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
285                 }
286         }
287         print <<EOF;
288 config TARGET_PROFILE
289         string
290 EOF
291         foreach my $target (@target) {
292                 my $profiles = $target->{profiles};
293                 foreach my $profile (@$profiles) {
294                         print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
295                 }
296         }
297
298         print <<EOF;
299
300 config TARGET_ARCH_PACKAGES
301         string
302         
303 EOF
304         foreach my $target (@target) {
305                 next if @{$target->{subtargets}} > 0;
306                 print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
307         }
308         print <<EOF;
309
310 config DEFAULT_TARGET_OPTIMIZATION
311         string
312 EOF
313         foreach my $target (@target) {
314                 next if @{$target->{subtargets}} > 0;
315                 print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
316         }
317         print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
318         print <<EOF;
319
320 config CPU_TYPE
321         string
322 EOF
323         foreach my $target (@target) {
324                 next if @{$target->{subtargets}} > 0;
325                 print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
326         }
327         print "\tdefault \"\"\n";
328
329         my %kver;
330         foreach my $target (@target) {
331                 my $v = kver($target->{version});
332                 next if $kver{$v};
333                 $kver{$v} = 1;
334                 print <<EOF;
335
336 config LINUX_$v
337         bool
338
339 EOF
340         }
341         foreach my $def (sort keys %defaults) {
342                 print "\tconfig DEFAULT_".$def."\n";
343                 print "\t\tbool\n\n";
344         }
345 }
346
347 sub gen_profile_mk() {
348         my $file = shift @ARGV;
349         my $target = shift @ARGV;
350         my @targets = parse_target_metadata($file);
351         foreach my $cur (@targets) {
352                 next unless $cur->{id} eq $target;
353                 print "PROFILE_NAMES = ".join(" ", map { $_->{id} } @{$cur->{profiles}})."\n";
354                 foreach my $profile (@{$cur->{profiles}}) {
355                         print $profile->{id}.'_NAME:='.$profile->{name}."\n";
356                         print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n";
357                 }
358         }
359 }
360
361 sub parse_command() {
362         GetOptions("ignore=s", \@ignore);
363         my $cmd = shift @ARGV;
364         for ($cmd) {
365                 /^config$/ and return gen_target_config();
366                 /^profile_mk$/ and return gen_profile_mk();
367         }
368         die <<EOF
369 Available Commands:
370         $0 config [file]                        Target metadata in Kconfig format
371         $0 profile_mk [file] [target]           Profile metadata in makefile format
372
373 EOF
374 }
375
376 parse_command();