config: add a small_flash feature
[openwrt/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 /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();