Kconfig symbol visibility
I managed to get bit by the same issue twice in about 24 hours so I guess it’s
time for a blog post. If you’ve ever compiled a kernel, you have dealt with
kconfig symbols (CONFIG_FOO
) which are used to enable various options in the
kernel. You can’t select every symbol out that exists in the kernel since that
would be a nightmare. Configuration options may be limited by adding depends
e.g.
config FOO
depends on BAR
depends on BAZ if HAS_BAZ
Something like depends on BAR
is statically defined and isn’t going to vary
across systems. It turns out, you can do some interesting tricks and have
your Kconfig symbol depend on the output of a script. The first time I got bit
by this was with CONFIG_GCC_PLUGINS
:
menuconfig GCC_PLUGINS
bool "GCC plugins"
depends on HAVE_GCC_PLUGINS
depends on PLUGIN_HOSTCC != ""
config PLUGIN_HOSTCC
string
default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")" if CC_IS_GCC
Because of the way gcc plugins work, you need to have an external package installed to do anything useful so it makes sense to only show the symbol if the package is properly installed.
As a distro maintainer, I’m responsible for looking at new symbols as they are
added to the kernel. The easiest way to do this is to take the existing config
file and run make listnewconfig
. A side effect of the dynamic nature of
CONFIG_GCC_PLUGINS
is that if you take a .config generated on a system that
doesn’t have the plugin devel package installed and then use it to run
listnewconfig on a system that does have the package installed it will
show up as a new symbol:
$ make defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#
$ make listnewconfig
scripts/kconfig/conf --listnewconfig Kconfig
$ sudo dnf install gcc-plugin-devel
..various installation messages..
$ make listnewconfig
scripts/kconfig/conf --listnewconfig Kconfig
CONFIG_GCC_PLUGINS=n
We have some scripts that expect a clean listnewconfig (i.e. we’ve set values
for all configuraiton options) so this led to some confusion about why things
were not working on my system which had gcc-plugin-devel
installed (“But this
worked when we built it last week!”)
The other case of dynamic configuration options happened with powerpc. Distros
support multiple architectures but almost all development is done on our x86
workstations (until the year arm64 on the desktop happens of course). We can
generate configuration files by setting the ARCH=blah
option on the command
line. Today I discovered that there’s a dynamic config option in powerpc:
config MPROFILE_KERNEL
depends on PPC64 && CPU_LITTLE_ENDIAN
def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__)
This results in CONFIG_MPROFILE_KERNEL
not being visible unless you have the
appropriate compiler installed which means, again, different behavior for
listnewconfig
.
Obviously the system environment makes a difference when building the kernel but it’s a bit surprising where this shows up. The moral I have learned is to think a little bit more closely about how exactly kernel configuration files are generated.