2009-12-12 13:51:07 +00:00
|
|
|
# This script runs `make config' to generate a Linux kernel
|
|
|
|
# configuration file. For each question (i.e. kernel configuration
|
|
|
|
# option), unless an override is provided, it answers "m" if possible,
|
|
|
|
# and otherwise uses the default answer (as determined by the default
|
|
|
|
# config for the architecture). Overrides are read from the file
|
|
|
|
# $KERNEL_CONFIG, which on each line contains an option name and an
|
|
|
|
# answer, e.g. "EXT2_FS_POSIX_ACL y". The script warns about ignored
|
|
|
|
# options in $KERNEL_CONFIG, and barfs if `make config' selects
|
|
|
|
# another answer for an option than the one provided in
|
|
|
|
# $KERNEL_CONFIG.
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use IPC::Open2;
|
2014-01-01 14:21:25 +00:00
|
|
|
use Cwd;
|
|
|
|
|
2018-01-28 18:50:18 +00:00
|
|
|
# exported via nix
|
2009-12-12 13:51:07 +00:00
|
|
|
my $debug = $ENV{'DEBUG'};
|
2010-02-16 19:27:51 +00:00
|
|
|
my $autoModules = $ENV{'AUTO_MODULES'};
|
2017-03-23 00:03:37 +00:00
|
|
|
my $preferBuiltin = $ENV{'PREFER_BUILTIN'};
|
2018-01-28 18:50:18 +00:00
|
|
|
my $ignoreConfigErrors = $ENV{'ignoreConfigErrors'};
|
|
|
|
my $buildRoot = $ENV{'BUILD_ROOT'};
|
2021-07-12 04:55:40 +00:00
|
|
|
my $makeFlags = $ENV{'MAKE_FLAGS'};
|
2009-12-12 13:51:07 +00:00
|
|
|
$SIG{PIPE} = 'IGNORE';
|
|
|
|
|
|
|
|
# Read the answers.
|
|
|
|
my %answers;
|
2009-12-14 09:27:15 +00:00
|
|
|
my %requiredAnswers;
|
2018-01-28 18:50:18 +00:00
|
|
|
open ANSWERS, "<$ENV{KERNEL_CONFIG}" or die "Could not open answer file";
|
2009-12-12 13:51:07 +00:00
|
|
|
while (<ANSWERS>) {
|
|
|
|
chomp;
|
|
|
|
s/#.*//;
|
2019-08-11 21:01:51 +00:00
|
|
|
if (/^\s*([A-Za-z0-9_]+)(\?)?\s+(.*\S)\s*$/) {
|
2009-12-14 09:27:15 +00:00
|
|
|
$answers{$1} = $3;
|
2010-08-14 09:18:57 +00:00
|
|
|
$requiredAnswers{$1} = !(defined $2);
|
2009-12-14 09:27:15 +00:00
|
|
|
} elsif (!/^\s*$/) {
|
|
|
|
die "invalid config line: $_";
|
|
|
|
}
|
2009-12-12 13:51:07 +00:00
|
|
|
}
|
|
|
|
close ANSWERS;
|
|
|
|
|
|
|
|
sub runConfig {
|
|
|
|
|
|
|
|
# Run `make config'.
|
2021-07-12 04:55:40 +00:00
|
|
|
my $pid = open2(\*IN, \*OUT, "make -C $ENV{SRC} O=$buildRoot config SHELL=bash ARCH=$ENV{ARCH} CC=$ENV{CC} HOSTCC=$ENV{HOSTCC} HOSTCXX=$ENV{HOSTCXX} $makeFlags");
|
2009-12-12 13:51:07 +00:00
|
|
|
|
|
|
|
# Parse the output, look for questions and then send an
|
|
|
|
# appropriate answer.
|
|
|
|
my $line = ""; my $s;
|
|
|
|
my %choices = ();
|
|
|
|
|
|
|
|
my ($prevQuestion, $prevName);
|
|
|
|
|
|
|
|
while (!eof IN) {
|
|
|
|
read IN, $s, 1 or next;
|
|
|
|
$line .= $s;
|
|
|
|
|
|
|
|
#print STDERR "LINE: $line\n";
|
|
|
|
|
|
|
|
if ($s eq "\n") {
|
|
|
|
print STDERR "GOT: $line" if $debug;
|
|
|
|
|
2013-08-05 17:59:43 +00:00
|
|
|
# Remember choice alternatives ("> 1. bla (FOO)" or " 2. bla (BAR) (NEW)").
|
|
|
|
if ($line =~ /^\s*>?\s*(\d+)\.\s+.*?\(([A-Za-z0-9_]+)\)(?:\s+\(NEW\))?\s*$/) {
|
2009-12-12 13:51:07 +00:00
|
|
|
$choices{$2} = $1;
|
2020-12-19 00:44:46 +00:00
|
|
|
} else {
|
|
|
|
# The list of choices has ended without us being
|
|
|
|
# asked. This happens for options where only one value
|
|
|
|
# is valid, for instance. The results can foul up
|
|
|
|
# later options, so forget about it.
|
|
|
|
%choices = ();
|
2009-12-12 13:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$line = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ($line =~ /###$/) {
|
|
|
|
# The config program is waiting for an answer.
|
|
|
|
|
|
|
|
# Is this a regular question? ("bla bla (OPTION_NAME) [Y/n/m/...] ")
|
|
|
|
if ($line =~ /(.*) \(([A-Za-z0-9_]+)\) \[(.*)\].*###$/) {
|
|
|
|
my $question = $1; my $name = $2; my $alts = $3;
|
|
|
|
my $answer = "";
|
|
|
|
# Build everything as a module if possible.
|
linux.configfile: fix alts containing "/m"
generate-config.pl's auto modules feature answers "m" to any Kconfig
question it thinks supports being a module. It detected this by
seeing if the help shown by make config (called "alts" by the script)
contained the string "/m", which it would in the case of e.g a
tristate option, where alts would be "N/m/y/?".
But then along came CONFIG_MODPROBE_PATH in Linux 5.13, with a default
value, shown in the make config help, of "/sbin/modprobe".
generate-config.pl would see the "/m" substring, and answer "m" to the
question, meaning (I think) that the built kernel would expect the
modprobe binary to be at /m. This broke the (non-NixOS) VM images I
build with Nix. NixOS was unaffected because it uses a different
mechanism to set the modprobe path.
With the current architecture, we can't 100% determine whether a
Kconfig option is a string or a tristate, but we can get a lot closer
by using a better regex. My new regex only accepts single word
characters, separated by slashes, with a "/?" at the end. This is
much less likely to ever end up as the default value of a string
option.
Tested by building linux_latest.configfile before and after my
changes, and checking the only difference is the correct default for
CONFIG_MODPROBE_PATH.
2022-03-03 13:04:49 +00:00
|
|
|
$answer = "m" if $autoModules && $alts =~ qr{\A(\w/)+m/(\w/)*\?\z} && !($preferBuiltin && $alts =~ /Y/);
|
2009-12-12 13:51:07 +00:00
|
|
|
$answer = $answers{$name} if defined $answers{$name};
|
|
|
|
print STDERR "QUESTION: $question, NAME: $name, ALTS: $alts, ANSWER: $answer\n" if $debug;
|
|
|
|
print OUT "$answer\n";
|
|
|
|
die "repeated question: $question" if $prevQuestion && $prevQuestion eq $question && $name eq $prevName;
|
|
|
|
$prevQuestion = $question;
|
|
|
|
$prevName = $name;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Is this a choice? ("choice[1-N]: ")
|
|
|
|
elsif ($line =~ /choice\[(.*)\]: ###$/) {
|
|
|
|
my $answer = "";
|
|
|
|
foreach my $name (keys %choices) {
|
|
|
|
$answer = $choices{$name} if ($answers{$name} || "") eq "y";
|
|
|
|
}
|
|
|
|
print STDERR "CHOICE: $1, ANSWER: $answer\n" if $debug;
|
|
|
|
print OUT "$answer\n" if $1 =~ /-/;
|
|
|
|
}
|
2016-09-13 00:18:07 +00:00
|
|
|
|
2009-12-12 13:51:07 +00:00
|
|
|
# Some questions lack the option name ("bla bla [Y/n/m/...] ").
|
|
|
|
elsif ($line =~ /(.*) \[(.*)\] ###$/) {
|
|
|
|
print OUT "\n";
|
|
|
|
}
|
2016-09-13 00:18:07 +00:00
|
|
|
|
2009-12-12 13:51:07 +00:00
|
|
|
else {
|
2010-01-27 15:43:27 +00:00
|
|
|
warn "don't know how to answer this question: $line\n";
|
|
|
|
print OUT "\n";
|
2009-12-12 13:51:07 +00:00
|
|
|
}
|
2016-09-13 00:18:07 +00:00
|
|
|
|
2009-12-12 13:51:07 +00:00
|
|
|
$line = "";
|
|
|
|
%choices = ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close IN;
|
|
|
|
waitpid $pid, 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Run `make config' several times to converge on the desired result.
|
|
|
|
# (Some options may only become available after other options are
|
|
|
|
# set in a previous run.)
|
|
|
|
runConfig;
|
|
|
|
runConfig;
|
|
|
|
|
|
|
|
# Read the final .config file and check that our answers are in
|
|
|
|
# there. `make config' often overrides answers if later questions
|
|
|
|
# cause options to be selected.
|
|
|
|
my %config;
|
2018-01-28 18:50:18 +00:00
|
|
|
open CONFIG, "<$buildRoot/.config" or die "Could not read .config";
|
2009-12-12 13:51:07 +00:00
|
|
|
while (<CONFIG>) {
|
|
|
|
chomp;
|
2016-09-13 10:52:07 +00:00
|
|
|
if (/^CONFIG_([A-Za-z0-9_]+)="(.*)"$/) {
|
|
|
|
# String options have double quotes, e.g. 'CONFIG_NLS_DEFAULT="utf8"' and allow escaping.
|
|
|
|
($config{$1} = $2) =~ s/\\([\\"])/$1/g;
|
|
|
|
} elsif (/^CONFIG_([A-Za-z0-9_]+)=(.*)$/) {
|
2009-12-12 13:51:07 +00:00
|
|
|
$config{$1} = $2;
|
|
|
|
} elsif (/^# CONFIG_([A-Za-z0-9_]+) is not set$/) {
|
|
|
|
$config{$1} = "n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close CONFIG;
|
|
|
|
|
2019-12-05 10:02:16 +00:00
|
|
|
my $ret = 0;
|
2009-12-12 13:51:07 +00:00
|
|
|
foreach my $name (sort (keys %answers)) {
|
2018-01-28 18:50:18 +00:00
|
|
|
my $f = $requiredAnswers{$name} && $ignoreConfigErrors ne "1"
|
2019-12-05 10:02:16 +00:00
|
|
|
? sub { warn "error: " . $_[0]; $ret = -1; } : sub { warn "warning: " . $_[0]; };
|
2009-12-14 09:27:15 +00:00
|
|
|
&$f("unused option: $name\n") unless defined $config{$name};
|
2016-09-13 00:18:07 +00:00
|
|
|
&$f("option not set correctly: $name (wanted '$answers{$name}', got '$config{$name}')\n")
|
2009-12-12 13:51:07 +00:00
|
|
|
if $config{$name} && $config{$name} ne $answers{$name};
|
|
|
|
}
|
2019-12-05 10:02:16 +00:00
|
|
|
exit $ret;
|