metadata.pl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. #!/usr/bin/perl
  2. use FindBin;
  3. use lib "$FindBin::Bin";
  4. use strict;
  5. use metadata;
  6. my %board;
  7. sub confstr($) {
  8. my $conf = shift;
  9. $conf =~ tr#/\.\-/#___#;
  10. return $conf;
  11. }
  12. sub parse_target_metadata() {
  13. my $file = shift @ARGV;
  14. my ($target, @target, $profile);
  15. open FILE, "<$file" or do {
  16. warn "Can't open file '$file': $!\n";
  17. return;
  18. };
  19. while (<FILE>) {
  20. chomp;
  21. /^Target:\s*(.+)\s*$/ and do {
  22. $target = {
  23. id => $1,
  24. conf => confstr($1),
  25. profiles => []
  26. };
  27. push @target, $target;
  28. };
  29. /^Target-Board:\s*(.+)\s*$/ and do {
  30. $target->{board} = $1;
  31. $target->{boardconf} = confstr($1);
  32. };
  33. /^Target-Kernel:\s*(\d+\.\d+)\s*$/ and $target->{kernel} = $1;
  34. /^Target-Name:\s*(.+)\s*$/ and $target->{name} = $1;
  35. /^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1;
  36. /^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;
  37. /^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ];
  38. /^Target-Description:/ and $target->{desc} = get_multiline(*FILE);
  39. /^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1;
  40. /^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1;
  41. /^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1;
  42. /^Default-Packages:\s*(.+)\s*$/ and $target->{packages} = [ split(/\s+/, $1) ];
  43. /^Target-Profile:\s*(.+)\s*$/ and do {
  44. $profile = {
  45. id => $1,
  46. name => $1,
  47. packages => []
  48. };
  49. push @{$target->{profiles}}, $profile;
  50. };
  51. /^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;
  52. /^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ];
  53. /^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE);
  54. /^Target-Profile-Config:/ and $profile->{config} = get_multiline(*FILE, "\t");
  55. /^Target-Profile-Kconfig:/ and $profile->{kconfig} = 1;
  56. }
  57. close FILE;
  58. foreach my $target (@target) {
  59. @{$target->{profiles}} > 0 or $target->{profiles} = [
  60. {
  61. id => 'Default',
  62. name => 'Default',
  63. packages => []
  64. }
  65. ];
  66. }
  67. return @target;
  68. }
  69. sub gen_kconfig_overrides() {
  70. my %config;
  71. my %kconfig;
  72. my $package;
  73. my $pkginfo = shift @ARGV;
  74. my $cfgfile = shift @ARGV;
  75. # parameter 2: build system config
  76. open FILE, "<$cfgfile" or return;
  77. while (<FILE>) {
  78. /^(CONFIG_.+?)=(.+)$/ and $config{$1} = 1;
  79. }
  80. close FILE;
  81. # parameter 1: package metadata
  82. open FILE, "<$pkginfo" or return;
  83. while (<FILE>) {
  84. /^Package:\s*(.+?)\s*$/ and $package = $1;
  85. /^Kernel-Config:\s*(.+?)\s*$/ and do {
  86. my @config = split /\s+/, $1;
  87. foreach my $config (@config) {
  88. my $val = 'm';
  89. my $override;
  90. if ($config =~ /^(.+?)=(.+)$/) {
  91. $config = $1;
  92. $override = 1;
  93. $val = $2;
  94. }
  95. if ($config{"CONFIG_PACKAGE_$package"} and ($config ne 'n')) {
  96. $kconfig{$config} = $val;
  97. } elsif (!$override) {
  98. $kconfig{$config} or $kconfig{$config} = 'n';
  99. }
  100. }
  101. };
  102. };
  103. close FILE;
  104. foreach my $kconfig (sort keys %kconfig) {
  105. if ($kconfig{$kconfig} eq 'n') {
  106. print "# $kconfig is not set\n";
  107. } else {
  108. print "$kconfig=$kconfig{$kconfig}\n";
  109. }
  110. }
  111. }
  112. sub merge_package_lists($$) {
  113. my $list1 = shift;
  114. my $list2 = shift;
  115. my @l = ();
  116. my %pkgs;
  117. foreach my $pkg (@$list1, @$list2) {
  118. $pkgs{$pkg} = 1;
  119. }
  120. foreach my $pkg (keys %pkgs) {
  121. push @l, $pkg unless ($pkg =~ /^-/ or $pkgs{"-$pkg"});
  122. }
  123. return sort(@l);
  124. }
  125. sub target_config_features(@) {
  126. my $ret;
  127. while ($_ = shift @_) {
  128. /broken/ and $ret .= "\tdepends BROKEN\n";
  129. /pci/ and $ret .= "\tselect PCI_SUPPORT\n";
  130. /usb/ and $ret .= "\tselect USB_SUPPORT\n";
  131. /pcmcia/ and $ret .= "\tselect PCMCIA_SUPPORT\n";
  132. /squashfs/ and $ret .= "\tselect USES_SQUASHFS\n";
  133. /jffs2/ and $ret .= "\tselect USES_JFFS2\n";
  134. /ext2/ and $ret .= "\tselect USES_EXT2\n";
  135. /tgz/ and $ret .= "\tselect USES_TGZ\n";
  136. }
  137. return $ret;
  138. }
  139. sub gen_target_config() {
  140. my @target = parse_target_metadata();
  141. @target = sort {
  142. $a->{name} cmp $b->{name}
  143. } @target;
  144. print <<EOF;
  145. choice
  146. prompt "Target System"
  147. default TARGET_brcm_2_4
  148. reset if !DEVEL
  149. EOF
  150. foreach my $target (@target) {
  151. my $features = target_config_features(@{$target->{features}});
  152. my $help = $target->{desc};
  153. my $kernel = $target->{kernel};
  154. $kernel =~ tr/./_/;
  155. chomp $features;
  156. $features .= "\n";
  157. if ($help =~ /\w+/) {
  158. $help =~ s/^\s*/\t /mg;
  159. $help = "\thelp\n$help";
  160. } else {
  161. undef $help;
  162. }
  163. print <<EOF;
  164. config TARGET_$target->{conf}
  165. bool "$target->{name}"
  166. select $target->{arch}
  167. select LINUX_$kernel
  168. EOF
  169. if ($target->{id} ne $target->{board}) {
  170. print "\tselect TARGET_".$target->{boardconf}."\n";
  171. }
  172. print "$features$help\n\n"
  173. }
  174. print <<EOF;
  175. endchoice
  176. config TARGET_BOARD
  177. string
  178. EOF
  179. foreach my $target (@target) {
  180. print "\t\tdefault \"".$target->{board}."\" if TARGET_".$target->{conf}."\n";
  181. }
  182. # add hidden target config options
  183. foreach my $target (@target) {
  184. next if $board{$target->{board}};
  185. if ($target->{id} ne $target->{board}) {
  186. print "\nconfig TARGET_".$target->{boardconf}."\n\tbool\n";
  187. $board{$target->{board}} = 1;
  188. }
  189. }
  190. print <<EOF;
  191. choice
  192. prompt "Target Profile"
  193. EOF
  194. foreach my $target (@target) {
  195. my $profiles = $target->{profiles};
  196. foreach my $profile (@$profiles) {
  197. print <<EOF;
  198. config TARGET_$target->{conf}_$profile->{id}
  199. bool "$profile->{name}"
  200. depends TARGET_$target->{conf}
  201. $profile->{config}
  202. EOF
  203. $profile->{kconfig} and print "\tselect PROFILE_KCONFIG\n";
  204. my @pkglist = merge_package_lists($target->{packages}, $profile->{packages});
  205. foreach my $pkg (@pkglist) {
  206. print "\tselect DEFAULT_$pkg\n";
  207. }
  208. print "\n";
  209. }
  210. }
  211. print "endchoice\n";
  212. }
  213. my %dep_check;
  214. sub __find_package_dep($$) {
  215. my $pkg = shift;
  216. my $name = shift;
  217. my $deps = ($pkg->{vdepends} or $pkg->{depends});
  218. return 0 unless defined $deps;
  219. foreach my $dep (@{$deps}) {
  220. next if $dep_check{$dep};
  221. $dep_check{$dep} = 1;
  222. return 1 if $dep eq $name;
  223. return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
  224. }
  225. return 0;
  226. }
  227. # wrapper to avoid infinite recursion
  228. sub find_package_dep($$) {
  229. my $pkg = shift;
  230. my $name = shift;
  231. %dep_check = ();
  232. return __find_package_dep($pkg, $name);
  233. }
  234. sub package_depends($$) {
  235. my $a = shift;
  236. my $b = shift;
  237. my $ret;
  238. return 0 if ($a->{submenu} ne $b->{submenu});
  239. if (find_package_dep($a, $b->{name}) == 1) {
  240. $ret = 1;
  241. } elsif (find_package_dep($b, $a->{name}) == 1) {
  242. $ret = -1;
  243. } else {
  244. return 0;
  245. }
  246. return $ret;
  247. }
  248. sub mconf_depends($$) {
  249. my $depends = shift;
  250. my $only_dep = shift;
  251. my $res;
  252. $depends or return;
  253. my @depends = @$depends;
  254. foreach my $depend (@depends) {
  255. my $m = "depends";
  256. $depend =~ s/^([@\+]+)//;
  257. my $flags = $1;
  258. my $vdep;
  259. if ($vdep = $package{$depend}->{vdepends}) {
  260. $depend = join("||", map { "PACKAGE_".$_ } @$vdep);
  261. } else {
  262. $flags =~ /\+/ and do {
  263. next if $only_dep;
  264. $m = "select";
  265. # Menuconfig will not treat 'select FOO' as a real dependency
  266. # thus if FOO depends on other config options, these dependencies
  267. # will not be checked. To fix this, we simply emit all of FOO's
  268. # depends here as well.
  269. $package{$depend} and $res .= mconf_depends($package{$depend}->{depends}, 1);
  270. };
  271. $flags =~ /@/ or $depend = "PACKAGE_$depend";
  272. }
  273. $res .= "\t\t$m $depend\n";
  274. }
  275. return $res;
  276. }
  277. sub print_package_config_category($) {
  278. my $cat = shift;
  279. my %menus;
  280. my %menu_dep;
  281. return unless $category{$cat};
  282. print "menu \"$cat\"\n\n";
  283. my %spkg = %{$category{$cat}};
  284. foreach my $spkg (sort {uc($a) cmp uc($b)} keys %spkg) {
  285. foreach my $pkg (@{$spkg{$spkg}}) {
  286. my $menu = $pkg->{submenu};
  287. if ($menu) {
  288. $menu_dep{$menu} or $menu_dep{$menu} = $pkg->{submenudep};
  289. } else {
  290. $menu = 'undef';
  291. }
  292. $menus{$menu} or $menus{$menu} = [];
  293. push @{$menus{$menu}}, $pkg;
  294. print "\tconfig DEFAULT_".$pkg->{name}."\n";
  295. print "\t\tbool\n\n";
  296. }
  297. }
  298. my @menus = sort {
  299. ($a eq 'undef' ? 1 : 0) or
  300. ($b eq 'undef' ? -1 : 0) or
  301. ($a cmp $b)
  302. } keys %menus;
  303. foreach my $menu (@menus) {
  304. my @pkgs = sort {
  305. package_depends($a, $b) or
  306. ($a->{name} cmp $b->{name})
  307. } @{$menus{$menu}};
  308. if ($menu ne 'undef') {
  309. $menu_dep{$menu} and print "if $menu_dep{$menu}\n";
  310. print "menu \"$menu\"\n";
  311. }
  312. foreach my $pkg (@pkgs) {
  313. my $title = $pkg->{name};
  314. my $c = (72 - length($pkg->{name}) - length($pkg->{title}));
  315. if ($c > 0) {
  316. $title .= ("." x $c). " ". $pkg->{title};
  317. }
  318. print "\t";
  319. $pkg->{menu} and print "menu";
  320. print "config PACKAGE_".$pkg->{name}."\n";
  321. print "\t\t".($pkg->{tristate} ? 'tristate' : 'bool')." \"$title\"\n";
  322. print "\t\tdefault y if DEFAULT_".$pkg->{name}."\n";
  323. foreach my $default (split /\s*,\s*/, $pkg->{default}) {
  324. print "\t\tdefault $default\n";
  325. }
  326. print mconf_depends($pkg->{depends}, 0);
  327. print "\t\thelp\n";
  328. print $pkg->{description};
  329. print "\n";
  330. $pkg->{config} and print $pkg->{config}."\n";
  331. }
  332. if ($menu ne 'undef') {
  333. print "endmenu\n";
  334. $menu_dep{$menu} and print "endif\n";
  335. }
  336. }
  337. print "endmenu\n\n";
  338. undef $category{$cat};
  339. }
  340. sub gen_package_config() {
  341. parse_package_metadata($ARGV[0]) or exit 1;
  342. print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n";
  343. foreach my $preconfig (keys %preconfig) {
  344. foreach my $cfg (keys %{$preconfig{$preconfig}}) {
  345. my $conf = $preconfig{$preconfig}->{$cfg}->{id};
  346. $conf =~ tr/\.-/__/;
  347. print <<EOF
  348. config UCI_PRECONFIG_$conf
  349. string "$preconfig{$preconfig}->{$cfg}->{label}" if UCI_PRECONFIG
  350. depends PACKAGE_$preconfig
  351. default "$preconfig{$preconfig}->{$cfg}->{default}"
  352. EOF
  353. }
  354. }
  355. print_package_config_category 'Base system';
  356. foreach my $cat (keys %category) {
  357. print_package_config_category $cat;
  358. }
  359. }
  360. sub gen_package_mk() {
  361. my %conf;
  362. my %dep;
  363. my $line;
  364. parse_package_metadata($ARGV[0]) or exit 1;
  365. foreach my $name (sort {uc($a) cmp uc($b)} keys %package) {
  366. my $config;
  367. my $pkg = $package{$name};
  368. next if defined $pkg->{vdepends};
  369. if ($ENV{SDK}) {
  370. $conf{$pkg->{src}} or do {
  371. $config = 'm';
  372. $conf{$pkg->{src}} = 1;
  373. };
  374. } else {
  375. $config = "\$(CONFIG_PACKAGE_$name)"
  376. }
  377. if ($config) {
  378. print "package-$config += $pkg->{subdir}$pkg->{src}\n";
  379. $pkg->{prereq} and print "prereq-$config += $pkg->{subdir}$pkg->{src}\n";
  380. }
  381. my $hasdeps = 0;
  382. my $depline = "";
  383. foreach my $dep (@{$pkg->{depends}}, @{$pkg->{builddepends}}) {
  384. next if $dep =~ /@/;
  385. $dep =~ s/\+//;
  386. my $idx;
  387. my $pkg_dep = $package{$dep};
  388. next if defined $pkg_dep->{vdepends};
  389. if (defined $pkg_dep->{src}) {
  390. ($pkg->{src} ne $pkg_dep->{src}) and $idx = $pkg_dep->{subdir}.$pkg_dep->{src};
  391. } elsif (defined($srcpackage{$dep})) {
  392. $idx = $subdir{$dep}.$dep;
  393. }
  394. undef $idx if $idx =~ /^(kernel)|(base-files)$/;
  395. if ($idx) {
  396. next if $dep{$pkg->{src}."->".$idx};
  397. $depline .= " \$(curdir)/$idx/compile";
  398. $dep{$pkg->{src}."->".$idx} = 1;
  399. }
  400. }
  401. if ($depline) {
  402. $line .= "\$(curdir)/".$pkg->{subdir}."$pkg->{src}/compile += $depline\n";
  403. }
  404. }
  405. if ($line ne "") {
  406. print "\n$line";
  407. }
  408. foreach my $preconfig (keys %preconfig) {
  409. my $cmds;
  410. foreach my $cfg (keys %{$preconfig{$preconfig}}) {
  411. my $conf = $preconfig{$preconfig}->{$cfg}->{id};
  412. $conf =~ tr/\.-/__/;
  413. $cmds .= "\techo \"uci set '$preconfig{$preconfig}->{$cfg}->{id}=\$(subst \",,\$(CONFIG_UCI_PRECONFIG_$conf))'\"; \\\n";
  414. }
  415. next unless $cmds;
  416. print <<EOF
  417. \$(TARGET_DIR)/etc/uci-defaults/$preconfig: FORCE
  418. ( \\
  419. $cmds \\
  420. ) > \$@
  421. ifneq (\$(UCI_PRECONFIG)\$(CONFIG_UCI_PRECONFIG),)
  422. package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig
  423. endif
  424. EOF
  425. }
  426. }
  427. sub parse_command() {
  428. my $cmd = shift @ARGV;
  429. for ($cmd) {
  430. /^target_config$/ and return gen_target_config();
  431. /^package_mk$/ and return gen_package_mk();
  432. /^package_config$/ and return gen_package_config();
  433. /^kconfig/ and return gen_kconfig_overrides();
  434. }
  435. print <<EOF
  436. Available Commands:
  437. $0 target_config [file] Target metadata in Kconfig format
  438. $0 package_mk [file] Package metadata in makefile format
  439. $0 package_config [file] Package metadata in Kconfig format
  440. $0 kconfig [file] [config] Kernel config overrides
  441. EOF
  442. }
  443. parse_command();