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