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;