at master 160 lines 5.8 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 16# exported via nix 17my $debug = $ENV{'DEBUG'}; 18my $autoModules = $ENV{'AUTO_MODULES'}; 19my $preferBuiltin = $ENV{'PREFER_BUILTIN'}; 20my $ignoreConfigErrors = $ENV{'ignoreConfigErrors'}; 21my $buildRoot = $ENV{'BUILD_ROOT'}; 22my $makeFlags = $ENV{'MAKE_FLAGS'}; 23$SIG{PIPE} = 'IGNORE'; 24 25# Read the answers. 26my %answers; 27my %requiredAnswers; 28open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die "Could not open answer file"; 29while (<ANSWERS>) { 30 chomp; 31 s/#.*//; 32 if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(.*\S)\s*$/) { 33 $answers{$1} = $3; 34 $requiredAnswers{$1} = !(defined $2); 35 } elsif (!/^\s*$/) { 36 die "invalid config line: $_"; 37 } 38} 39close ANSWERS; 40 41sub runConfig { 42 43 # Run `make config'. 44 # 45 # We have to pass through the target toolchain, because `make config` checks them for versions. This is 46 # required to get clang LTO working, among other things. 47 my $pid = open2(\*IN, \*OUT, 48 "make -C $ENV{SRC} O=$buildRoot config" 49 . " SHELL=bash ARCH=$ENV{ARCH} CROSS_COMPILE=$ENV{CROSS_COMPILE}" 50 . " $makeFlags"); 51 52 # Parse the output, look for questions and then send an 53 # appropriate answer. 54 my $line = ""; my $s; 55 my %choices = (); 56 57 my ($prevQuestion, $prevName); 58 59 while (!eof IN) { 60 read IN, $s, 1 or next; 61 $line .= $s; 62 63 #print STDERR "LINE: $line\n"; 64 65 if ($s eq "\n") { 66 print STDERR "GOT: $line" if $debug; 67 68 # Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)"). 69 if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) { 70 $choices{$2} = $1; 71 } else { 72 # The list of choices has ended without us being 73 # asked. This happens for options where only one value 74 # is valid, for instance. The results can foul up 75 # later options, so forget about it. 76 %choices = (); 77 } 78 79 $line = ""; 80 } 81 82 elsif ($line =~ /###$/) { 83 # The config program is waiting for an answer. 84 85 # Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ") 86 if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) { 87 my $question = $1; my $name = $2; my $alts = $3; 88 my $answer = ""; 89 # Build everything as a module if possible. 90 $answer = "m" if $autoModules && $alts =~ qr{\A(\w/)+m/(\w/)*\?\z} && !($preferBuiltin && $alts =~ /Y/); 91 $answer = $answers{$name} if defined $answers{$name}; 92 print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug; 93 print OUT "$answer\n"; 94 die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName; 95 $prevQuestion = $question; 96 $prevName = $name; 97 } 98 99 # Is this a choice? ("choice[1-N]: ") 100 elsif ($line =~ /choice\[(.*)\]: ###$/) { 101 my $answer = ""; 102 foreach my $name (keys %choices) { 103 $answer = $choices{$name} if ($answers{$name} || "") eq "y"; 104 } 105 print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug; 106 print OUT "$answer\n" if $1 =~ /-/; 107 } 108 109 # Some questions lack the option name ("bla bla [Y/n/m/...] "). 110 elsif ($line =~ /(.*) \[(.*)\] ###$/) { 111 print OUT "\n"; 112 } 113 114 else { 115 warn "don't know how to answer this question: $line\n"; 116 print OUT "\n"; 117 } 118 119 $line = ""; 120 %choices = (); 121 } 122 } 123 124 close IN; 125 waitpid $pid, 0; 126} 127 128# Run `make config' several times to converge on the desired result. 129# (Some options may only become available after other options are 130# set in a previous run.) 131runConfig; 132runConfig; 133 134# Read the final .config file and check that our answers are in 135# there. `make config' often overrides answers if later questions 136# cause options to be selected. 137my %config; 138open CONFIG, "<$buildRoot/.config" or die "Could not read .config"; 139while (<CONFIG>) { 140 chomp; 141 if (/^CONFIG_([A-Za-z0-9_]+)="(.*)"$/) { 142 # String options have double quotes, e.g. 'CONFIG_NLS_DEFAULT="utf8"' and allow escaping. 143 ($config{$1} = $2) =~ s/\\([\\"])/$1/g; 144 } elsif (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) { 145 $config{$1} = $2; 146 } elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) { 147 $config{$1} = "n"; 148 } 149} 150close CONFIG; 151 152my $ret = 0; 153foreach my $name (sort (keys %answers)) { 154 my $f = $requiredAnswers{$name} && $ignoreConfigErrors ne "1" 155 ? sub { warn "error: " . $_[0]; $ret = -1; } : sub { warn "warning: " . $_[0]; }; 156 &$f("unused option: $name\n") unless defined $config{$name}; 157 &$f("option not set correctly: $name (wanted '$answers{$name}', got '$config{$name}')\n") 158 if $config{$name} && $config{$name} ne $answers{$name}; 159} 160exit $ret;