build: add elecom-product-header for ELECOM devices
[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 /^pwm$/ and $ret .= "\select PWM_SUPPORT\n";
24 /^rtc$/ and $ret .= "\tselect RTC_SUPPORT\n";
25 /^squashfs$/ and $ret .= "\tselect USES_SQUASHFS\n";
26 /^jffs2$/ and $ret .= "\tselect USES_JFFS2\n";
27 /^jffs2_nand$/ and $ret .= "\tselect USES_JFFS2_NAND\n";
28 /^ext4$/ and $ret .= "\tselect USES_EXT4\n";
29 /^targz$/ and $ret .= "\tselect USES_TARGZ\n";
30 /^cpiogz$/ and $ret .= "\tselect USES_CPIOGZ\n";
31 /^minor$/ and $ret .= "\tselect USES_MINOR\n";
32 /^ubifs$/ and $ret .= "\tselect USES_UBIFS\n";
33 /^fpu$/ and $ret .= "\tselect HAS_FPU\n";
34 /^spe_fpu$/ and $ret .= "\tselect HAS_SPE_FPU\n";
35 /^ramdisk$/ and $ret .= "\tselect USES_INITRAMFS\n";
36 /^powerpc64$/ and $ret .= "\tselect powerpc64\n";
37 /^nommu$/ and $ret .= "\tselect NOMMU\n";
38 /^mips16$/ and $ret .= "\tselect HAS_MIPS16\n";
39 /^rfkill$/ and $ret .= "\tselect RFKILL_SUPPORT\n";
40 /^low_mem$/ and $ret .= "\tselect LOW_MEMORY_FOOTPRINT\n";
41 /^small_flash$/ and $ret .= "\tselect SMALL_FLASH\n";
42 /^nand$/ and $ret .= "\tselect NAND_SUPPORT\n";
43 /^virtio$/ and $ret .= "\tselect VIRTIO_SUPPORT\n";
44 /^rootfs-part$/ and $ret .= "\tselect USES_ROOTFS_PART\n";
45 /^boot-part$/ and $ret .= "\tselect USES_BOOT_PART\n";
46 /^testing-kernel$/ and $ret .= "\tselect HAS_TESTING_KERNEL\n";
47 }
48 return $ret;
49 }
50
51 sub target_name($) {
52 my $target = shift;
53 my $parent = $target->{parent};
54 if ($parent) {
55 return $target->{parent}->{name}." - ".$target->{name};
56 } else {
57 return $target->{name};
58 }
59 }
60
61 sub kver($) {
62 my $v = shift;
63 $v =~ tr/\./_/;
64 if (substr($v,0,2) eq "2_") {
65 $v =~ /(\d+_\d+_\d+)(_\d+)?/ and $v = $1;
66 } else {
67 $v =~ /(\d+_\d+)(_\d+)?/ and $v = $1;
68 }
69 return $v;
70 }
71
72 sub print_target($) {
73 my $target = shift;
74 my $features = target_config_features(@{$target->{features}});
75 my $help = $target->{desc};
76 my $confstr;
77
78 chomp $features;
79 $features .= "\n";
80 if ($help =~ /\w+/) {
81 $help =~ s/^\s*/\t /mg;
82 $help = "\thelp\n$help";
83 } else {
84 undef $help;
85 }
86
87 my $v = kver($target->{version});
88 my $tv = kver($target->{testing_version});
89 $tv or $tv = $v;
90 if (@{$target->{subtargets}} == 0) {
91 $confstr = <<EOF;
92 config TARGET_$target->{conf}
93 bool "$target->{name}"
94 select LINUX_$v if !TESTING_KERNEL
95 select LINUX_$tv if TESTING_KERNEL
96 EOF
97 }
98 else {
99 $confstr = <<EOF;
100 config TARGET_$target->{conf}
101 bool "$target->{name}"
102 EOF
103 }
104 if ($target->{subtarget}) {
105 $confstr .= "\tdepends on TARGET_$target->{boardconf}\n";
106 }
107 if (@{$target->{subtargets}} > 0) {
108 $confstr .= "\tselect HAS_SUBTARGETS\n";
109 grep { /broken/ } @{$target->{features}} and $confstr .= "\tdepends on BROKEN\n";
110 } else {
111 $confstr .= $features;
112 if ($target->{arch} =~ /\w/) {
113 $confstr .= "\tselect $target->{arch}\n";
114 }
115 if ($target->{has_devices}) {
116 $confstr .= "\tselect HAS_DEVICES\n";
117 }
118 }
119
120 foreach my $dep (@{$target->{depends}}) {
121 my $mode = "depends on";
122 my $flags;
123 my $name;
124
125 $dep =~ /^([@\+\-]+)(.+)$/;
126 $flags = $1;
127 $name = $2;
128
129 next if $name =~ /:/;
130 $flags =~ /-/ and $mode = "deselect";
131 $flags =~ /\+/ and $mode = "select";
132 $flags =~ /@/ and $confstr .= "\t$mode $name\n";
133 }
134 $confstr .= "$help\n\n";
135 print $confstr;
136 }
137
138 sub merge_package_lists($$) {
139 my $list1 = shift;
140 my $list2 = shift;
141 my @l = ();
142 my %pkgs;
143
144 foreach my $pkg (@$list1, @$list2) {
145 $pkgs{$pkg} = 1;
146 }
147 foreach my $pkg (keys %pkgs) {
148 push @l, $pkg unless ($pkg =~ /^-/ or $pkgs{"-$pkg"});
149 }
150 return sort(@l);
151 }
152
153 sub gen_target_config() {
154 my $file = shift @ARGV;
155 my @target = parse_target_metadata($file);
156 my %defaults;
157
158 my @target_sort = sort {
159 target_name($a) cmp target_name($b);
160 } @target;
161
162 foreach my $target (@target_sort) {
163 next if @{$target->{subtargets}} > 0;
164 print <<EOF;
165 config DEFAULT_TARGET_$target->{conf}
166 bool
167 depends on TARGET_PER_DEVICE_ROOTFS
168 default y if TARGET_$target->{conf}
169 EOF
170 foreach my $pkg (@{$target->{packages}}) {
171 print "\tselect DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n";
172 }
173 }
174
175 print <<EOF;
176 choice
177 prompt "Target System"
178 default TARGET_ath79
179 reset if !DEVEL
180
181 EOF
182
183 foreach my $target (@target_sort) {
184 next if $target->{subtarget};
185 print_target($target);
186 }
187
188 print <<EOF;
189 endchoice
190
191 choice
192 prompt "Subtarget" if HAS_SUBTARGETS
193 EOF
194 foreach my $target (@target) {
195 next unless $target->{def_subtarget};
196 print <<EOF;
197 default TARGET_$target->{conf}_$target->{def_subtarget} if TARGET_$target->{conf}
198 EOF
199 }
200 print <<EOF;
201
202 EOF
203 foreach my $target (@target) {
204 next unless $target->{subtarget};
205 print_target($target);
206 }
207
208 print <<EOF;
209 endchoice
210
211 choice
212 prompt "Target Profile"
213 default TARGET_MULTI_PROFILE if BUILDBOT
214
215 EOF
216 foreach my $target (@target) {
217 my $profile = $target->{profiles}->[0];
218 $profile or next;
219 print <<EOF;
220 default TARGET_$target->{conf}_$profile->{id} if TARGET_$target->{conf} && !BUILDBOT
221 EOF
222 }
223
224 print <<EOF;
225
226 config TARGET_MULTI_PROFILE
227 bool "Multiple devices"
228 depends on HAS_DEVICES
229 help
230 Instead of only building a single image, or all images, this allows you
231 to select images to be built for multiple devices in one build.
232
233 EOF
234
235 foreach my $target (@target) {
236 my $profiles = $target->{profiles};
237 foreach my $profile (@{$target->{profiles}}) {
238 print <<EOF;
239 config TARGET_$target->{conf}_$profile->{id}
240 bool "$profile->{name}"
241 depends on TARGET_$target->{conf}
242 EOF
243 $profile->{broken} and print "\tdepends on BROKEN\n";
244 my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
245 foreach my $pkg (@pkglist) {
246 print "\tselect DEFAULT_$pkg\n";
247 $defaults{$pkg} = 1;
248 }
249 my $help = $profile->{desc};
250 if ($help =~ /\w+/) {
251 $help =~ s/^\s*/\t /mg;
252 $help = "\thelp\n$help";
253 } else {
254 undef $help;
255 }
256 print "$help\n";
257 }
258 }
259
260 print <<EOF;
261 endchoice
262
263 menu "Target Devices"
264 depends on TARGET_MULTI_PROFILE
265
266 config TARGET_ALL_PROFILES
267 bool "Enable all profiles by default"
268 default BUILDBOT
269
270 config TARGET_PER_DEVICE_ROOTFS
271 bool "Use a per-device root filesystem that adds profile packages"
272 default BUILDBOT
273 help
274 When disabled, all device packages from all selected devices
275 will be included in all images by default. (Marked as <*>) You will
276 still be able to manually deselect any/all packages.
277 When enabled, each device builds it's own image, including only the
278 profile packages for that device. (Marked as {M}) You will be able
279 to change a package to included in all images by marking as {*}, but
280 will not be able to disable a profile package completely.
281
282 To get the most use of this setting, you must set in a .config stub
283 before calling "make defconfig". Selecting TARGET_MULTI_PROFILE and
284 then manually selecting (via menuconfig for instance) this option
285 will have pre-defaulted all profile packages to included, making this
286 option appear to have had no effect.
287
288 EOF
289 foreach my $target (@target) {
290 my @profiles = sort {
291 my $x = $a->{name};
292 my $y = $b->{name};
293 "\L$x" cmp "\L$y";
294 } @{$target->{profiles}};
295 foreach my $profile (@profiles) {
296 next unless $profile->{id} =~ /^DEVICE_/;
297 print <<EOF;
298 menuconfig TARGET_DEVICE_$target->{conf}_$profile->{id}
299 bool "$profile->{name}"
300 depends on TARGET_$target->{conf}
301 default $profile->{default}
302 EOF
303 $profile->{broken} and print "\tdepends on BROKEN\n";
304 my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
305 foreach my $pkg (@pkglist) {
306 print "\tselect DEFAULT_$pkg if !TARGET_PER_DEVICE_ROOTFS\n";
307 print "\tselect MODULE_DEFAULT_$pkg if TARGET_PER_DEVICE_ROOTFS\n";
308 $defaults{$pkg} = 1;
309 }
310
311 print <<EOF;
312
313
314 config TARGET_DEVICE_PACKAGES_$target->{conf}_$profile->{id}
315 string "$profile->{name} additional packages"
316 default ""
317 depends on TARGET_PER_DEVICE_ROOTFS
318 depends on TARGET_DEVICE_$target->{conf}_$profile->{id}
319
320 EOF
321 }
322 }
323
324 print <<EOF;
325
326 endmenu
327
328 config HAS_SUBTARGETS
329 bool
330
331 config HAS_DEVICES
332 bool
333
334 config TARGET_BOARD
335 string
336
337 EOF
338 foreach my $target (@target) {
339 $target->{subtarget} or print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
340 }
341 print <<EOF;
342 config TARGET_SUBTARGET
343 string
344 default "generic" if !HAS_SUBTARGETS
345
346 EOF
347
348 foreach my $target (@target) {
349 foreach my $subtarget (@{$target->{subtargets}}) {
350 print "\t\tdefault \"$subtarget\" if TARGET_".$target->{conf}."_$subtarget\n";
351 }
352 }
353 print <<EOF;
354 config TARGET_PROFILE
355 string
356 EOF
357 foreach my $target (@target) {
358 my $profiles = $target->{profiles};
359 foreach my $profile (@$profiles) {
360 print "\tdefault \"$profile->{id}\" if TARGET_$target->{conf}_$profile->{id}\n";
361 }
362 }
363
364 print <<EOF;
365
366 config TARGET_ARCH_PACKAGES
367 string
368
369 EOF
370 foreach my $target (@target) {
371 next if @{$target->{subtargets}} > 0;
372 print "\t\tdefault \"".($target->{arch_packages} || $target->{board})."\" if TARGET_".$target->{conf}."\n";
373 }
374 print <<EOF;
375
376 config DEFAULT_TARGET_OPTIMIZATION
377 string
378 EOF
379 foreach my $target (@target) {
380 next if @{$target->{subtargets}} > 0;
381 print "\tdefault \"".$target->{cflags}."\" if TARGET_".$target->{conf}."\n";
382 }
383 print "\tdefault \"-Os -pipe -funit-at-a-time\"\n";
384 print <<EOF;
385
386 config CPU_TYPE
387 string
388 EOF
389 foreach my $target (@target) {
390 next if @{$target->{subtargets}} > 0;
391 print "\tdefault \"".$target->{cputype}."\" if TARGET_".$target->{conf}."\n";
392 }
393 print "\tdefault \"\"\n";
394
395 my %kver;
396 foreach my $target (@target) {
397 foreach my $tv ($target->{version}, $target->{testing_version}) {
398 next unless $tv;
399 my $v = kver($tv);
400 next if $kver{$v};
401 $kver{$v} = 1;
402 print <<EOF;
403
404 config LINUX_$v
405 bool
406
407 EOF
408 }
409 }
410 foreach my $def (sort keys %defaults) {
411 print <<EOF;
412 config DEFAULT_$def
413 bool
414
415 config MODULE_DEFAULT_$def
416 tristate
417 depends on TARGET_PER_DEVICE_ROOTFS
418 depends on m
419 default m if DEFAULT_$def
420 select PACKAGE_$def
421
422 EOF
423 }
424 }
425
426 sub gen_profile_mk() {
427 my $file = shift @ARGV;
428 my $target = shift @ARGV;
429 my @targets = parse_target_metadata($file);
430 foreach my $cur (@targets) {
431 next unless $cur->{id} eq $target;
432 my @profile_ids_unique = do { my %seen; grep { !$seen{$_}++} map { $_->{id} } @{$cur->{profiles}}};
433 print "PROFILE_NAMES = ".join(" ", @profile_ids_unique)."\n";
434 foreach my $profile (@{$cur->{profiles}}) {
435 print $profile->{id}.'_NAME:='.$profile->{name}."\n";
436 print $profile->{id}.'_HAS_IMAGE_METADATA:='.$profile->{has_image_metadata}."\n";
437 if (defined($profile->{supported_devices}) and @{$profile->{supported_devices}} > 0) {
438 print $profile->{id}.'_SUPPORTED_DEVICES:='.join(' ', @{$profile->{supported_devices}})."\n";
439 }
440 print $profile->{id}.'_PACKAGES:='.join(' ', @{$profile->{packages}})."\n";
441 }
442 }
443 }
444
445 sub parse_command() {
446 GetOptions("ignore=s", \@ignore);
447 my $cmd = shift @ARGV;
448 for ($cmd) {
449 /^config$/ and return gen_target_config();
450 /^profile_mk$/ and return gen_profile_mk();
451 }
452 die <<EOF
453 Available Commands:
454 $0 config [file] Target metadata in Kconfig format
455 $0 profile_mk [file] [target] Profile metadata in makefile format
456
457 EOF
458 }
459
460 parse_command();