07160dc4ea2c890886a2401a0ba1b597b0337afb
[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 /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 menuconfig 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 print <<EOF;
279
280
281 config TARGET_DEVICE_PACKAGES_$target->{conf}_$profile->{id}
282 string "$profile->{name} additional packages"
283 default ""
284 depends on TARGET_PER_DEVICE_ROOTFS
285 depends on TARGET_DEVICE_$target->{conf}_$profile->{id}
286
287 EOF
288 }
289 }
290
291 print <<EOF;
292
293 endmenu
294
295 config HAS_SUBTARGETS
296 bool
297
298 config HAS_DEVICES
299 bool
300
301 config TARGET_BOARD
302 string
303
304 EOF
305 foreach my $target (@target) {
306 $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
307 }
308 print <<EOF;
309 config TARGET_SUBTARGET
310 string
311 default "generic" if !HAS_SUBTARGETS
312
313 EOF
314
315 foreach my $target (@target) {
316 foreach my $subtarget (@{$target->{subtargets}}) {
317 print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
318 }
319 }
320 print <<EOF;
321 config TARGET_PROFILE
322 string
323 EOF
324 foreach my $target (@target) {
325 my $profiles = $target->{profiles};
326 foreach my $profile (@$profiles) {
327 print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
328 }
329 }
330
331 print <<EOF;
332
333 config TARGET_ARCH_PACKAGES
334 string
335
336 EOF
337 foreach my $target (@target) {
338 next if @{$target->{subtargets}} > 0;
339 print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
340 }
341 print <<EOF;
342
343 config DEFAULT_TARGET_OPTIMIZATION
344 string
345 EOF
346 foreach my $target (@target) {
347 next if @{$target->{subtargets}} > 0;
348 print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
349 }
350 print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
351 print <<EOF;
352
353 config CPU_TYPE
354 string
355 EOF
356 foreach my $target (@target) {
357 next if @{$target->{subtargets}} > 0;
358 print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
359 }
360 print "\tdefault \"\"\n";
361
362 my %kver;
363 foreach my $target (@target) {
364 my $v = kver($target->{version});
365 next if $kver{$v};
366 $kver{$v} = 1;
367 print <<EOF;
368
369 config LINUX_$v
370 bool
371
372 EOF
373 }
374 foreach my $def (sort keys %defaults) {
375 print <<EOF;
376 config DEFAULT_$def
377 bool
378
379 config MODULE_DEFAULT_$def
380 tristate
381 depends on TARGET_PER_DEVICE_ROOTFS
382 depends on m
383 default m if DEFAULT_$def
384 select PACKAGE_$def
385
386 EOF
387 }
388 }
389
390 sub gen_profile_mk() {
391 my $file = shift @ARGV;
392 my $target = shift @ARGV;
393 my @targets = parse_target_metadata($file);
394 foreach my $cur (@targets) {
395 next unless $cur->{id} eq $target;
396 print "PROFILE_NAMES = ".join(" ", map { $_->{id} } @{$cur->{profiles}})."\n";
397 foreach my $profile (@{$cur->{profiles}}) {
398 print $profile->{id}.'_NAME:='.$profile->{name}."\n";
399 print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n";
400 }
401 }
402 }
403
404 sub parse_command() {
405 GetOptions("ignore=s", \@ignore);
406 my $cmd = shift @ARGV;
407 for ($cmd) {
408 /^config$/ and return gen_target_config();
409 /^profile_mk$/ and return gen_profile_mk();
410 }
411 die <<EOF
412 Available Commands:
413 $0 config [file] Target metadata in Kconfig format
414 $0 profile_mk [file] [target] Profile metadata in makefile format
415
416 EOF
417 }
418
419 parse_command();