at 17.09-beta 145 lines 4.9 kB view raw
1# This script runs `make config' to generate a Linux kernel 2# configuration file. For each question (i.e. kernel configuration 3# option), unless an override is provided, it answers "m" if possible, 4# and otherwise uses the default answer (as determined by the default 5# config for the architecture). Overrides are read from the file 6# $KERNEL_CONFIG, which on each line contains an option name and an 7# answer, e.g. "EXT2_FS_POSIX_ACL y". The script warns about ignored 8# options in $KERNEL_CONFIG, and barfs if `make config' selects 9# another answer for an option than the one provided in 10# $KERNEL_CONFIG. 11 12use strict; 13use IPC::Open2; 14use Cwd; 15 16my $wd = getcwd; 17 18my $debug = $ENV{'DEBUG'}; 19my $autoModules = $ENV{'AUTO_MODULES'}; 20my $preferBuiltin = $ENV{'PREFER_BUILTIN'}; 21 22$SIG{PIPE} = 'IGNORE'; 23 24# Read the answers. 25my %answers; 26my %requiredAnswers; 27open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die; 28while (<ANSWERS>) { 29 chomp; 30 s/#.*//; 31 if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(\S+)\s*$/) { 32 $answers{$1} = $3; 33 $requiredAnswers{$1} = !(defined $2); 34 } elsif (!/^\s*$/) { 35 die "invalid config line: $_"; 36 } 37} 38close ANSWERS; 39 40sub runConfig { 41 42 # Run `make config'. 43 my $pid = open2(\*IN, \*OUT, "make -C $ENV{SRC} O=$wd config SHELL=bash ARCH=$ENV{ARCH}"); 44 45 # Parse the output, look for questions and then send an 46 # appropriate answer. 47 my $line = ""; my $s; 48 my %choices = (); 49 50 my ($prevQuestion, $prevName); 51 52 while (!eof IN) { 53 read IN, $s, 1 or next; 54 $line .= $s; 55 56 #print STDERR "LINE: $line\n"; 57 58 if ($s eq "\n") { 59 print STDERR "GOT: $line" if $debug; 60 61 # Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)"). 62 if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) { 63 $choices{$2} = $1; 64 } 65 66 $line = ""; 67 } 68 69 elsif ($line =~ /###$/) { 70 # The config program is waiting for an answer. 71 72 # Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ") 73 if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) { 74 my $question = $1; my $name = $2; my $alts = $3; 75 my $answer = ""; 76 # Build everything as a module if possible. 77 $answer = "m" if $autoModules && $alts =~ /\/m/ && !($preferBuiltin && $alts =~ /Y/); 78 $answer = $answers{$name} if defined $answers{$name}; 79 print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug; 80 print OUT "$answer\n"; 81 die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName; 82 $prevQuestion = $question; 83 $prevName = $name; 84 } 85 86 # Is this a choice? ("choice[1-N]: ") 87 elsif ($line =~ /choice\[(.*)\]: ###$/) { 88 my $answer = ""; 89 foreach my $name (keys %choices) { 90 $answer = $choices{$name} if ($answers{$name} || "") eq "y"; 91 } 92 print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug; 93 print OUT "$answer\n" if $1 =~ /-/; 94 } 95 96 # Some questions lack the option name ("bla bla [Y/n/m/...] "). 97 elsif ($line =~ /(.*) \[(.*)\] ###$/) { 98 print OUT "\n"; 99 } 100 101 else { 102 warn "don't know how to answer this question: $line\n"; 103 print OUT "\n"; 104 } 105 106 $line = ""; 107 %choices = (); 108 } 109 } 110 111 close IN; 112 waitpid $pid, 0; 113} 114 115# Run `make config' several times to converge on the desired result. 116# (Some options may only become available after other options are 117# set in a previous run.) 118runConfig; 119runConfig; 120 121# Read the final .config file and check that our answers are in 122# there. `make config' often overrides answers if later questions 123# cause options to be selected. 124my %config; 125open CONFIG, "<.config" or die; 126while (<CONFIG>) { 127 chomp; 128 if (/^CONFIG_([A-Za-z0-9_]+)="(.*)"$/) { 129 # String options have double quotes, e.g. 'CONFIG_NLS_DEFAULT="utf8"' and allow escaping. 130 ($config{$1} = $2) =~ s/\\([\\"])/$1/g; 131 } elsif (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) { 132 $config{$1} = $2; 133 } elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) { 134 $config{$1} = "n"; 135 } 136} 137close CONFIG; 138 139foreach my $name (sort (keys %answers)) { 140 my $f = $requiredAnswers{$name} && $ENV{'ignoreConfigErrors'} ne "1" 141 ? sub { die "error: " . $_[0]; } : sub { warn "warning: " . $_[0]; }; 142 &$f("unused option: $name\n") unless defined $config{$name}; 143 &$f("option not set correctly: $name (wanted '$answers{$name}', got '$config{$name}')\n") 144 if $config{$name} && $config{$name} ne $answers{$name}; 145}