Linux 内核的 `make defconfig` 究竟做了什么?
What exactly does Linux kernel's `make defconfig` do?
我可以使用以下命令根据自定义 ARM 板的指定体系结构默认值创建 Linux 内核 .config
文件:
ARCH=arm make defconfig KBUILD_DEFCONFIG=var_som_mx6_android_defconfig
我认为这个命令或多或少复制了./arch/arm/configs/var_som_mx6_android_defconfig
到./.config
。但是生成的 .config
文件并不完全是一个副本:
$ diff --unified arch/arm/configs/var_som_mx6_android_defconfig .config
--- arch/arm/configs/var_som_mx6_android_defconfig 2017-01-20 12:10:51.891515984 -0800
+++ .config 2017-01-26 15:31:29.000000000 -0800
@@ -407,6 +407,7 @@
CONFIG_ARM_ERRATA_751472=y
CONFIG_ARM_ERRATA_794072=y
CONFIG_ARM_ERRATA_761320=y
+CONFIG_ARM_ERRATA_845369=y
# CONFIG_ARM_ERRATA_753970 is not set
CONFIG_ARM_ERRATA_754322=y
# CONFIG_ARM_ERRATA_754327 is not set
@@ -2683,7 +2684,6 @@
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
# CONFIG_CUSE is not set
-CONFIG_AUFS_FS=y
#
# Caches
@@ -2759,6 +2759,21 @@
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+CONFIG_AUFS_SBILIST=y
+# CONFIG_AUFS_HNOTIFY is not set
+# CONFIG_AUFS_RDU is not set
+# CONFIG_AUFS_PROC_MAP is not set
+# CONFIG_AUFS_SP_IATTR is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+# CONFIG_AUFS_BR_FUSE is not set
+CONFIG_AUFS_BDEV_LOOP=y
+# CONFIG_AUFS_DEBUG is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
我不明白额外的行是从哪里来的,而且我一直觉得内核配置、makefile 和构建脚本的内部工作原理很难理解。谁能解释 .config
中的那些行可能来自哪里?
动机
.config
文件并非简单地从您的 defconfig
文件复制而来。接下来以这种格式存储 defconfig
的动机是:在 defconfig
中,我们只能指定具有 non-default 值的选项(即我们为我们的板更改的选项)。这样我们就可以保持小而清晰。每个新内核版本都会带来一堆新选项,这样我们就不需要在每次内核发布时都更新 defconfig
文件。此外,应该提到内核构建系统在 defconfig
文件中保留非常特定的选项顺序,因此最好避免手动修改它。相反,您应该使用 make savedefconfig
规则。
简化说明
当生成 .config
文件时,内核构建系统遍历所有 Kconfig
文件(来自所有子目录),检查这些 Kconfig
文件中的所有选项:
- 如果选项在
defconfig
中被提及,构建系统将该选项放入 .config
并在 defconfig
中选择值
- 如果
defconfig
中未提及选项,构建系统使用其默认值将该选项放入 .config
,在相应的 Kconfig
中指定
检查 scripts/kconfig/Makefile and scripts/kconfig/conf.c 个文件以了解它是如何实际完成的。
更准确详细的解释
来自 "Kbuild: the Linux Kernel Build System" by Javier Martinez:
Defining Configuration Symbols: Kconfig
Files
Configuration symbols are defined in files known as Kconfig
files. Each Kconfig
file can describe an arbitrary number of symbols and can also include (source) other Kconfig
files. Compilation targets that construct configuration menus of kernel compile options, such as make menuconfig
, read these files to build the tree-like structure. Every directory in the kernel has one Kconfig
that includes the Kconfig
files of its subdirectories. On top of the kernel source code directory, there is a Kconfig
file that is the root of the options tree. The menuconfig
(scripts/kconfig/mconf
), gconfig
(scripts/kconfig/gconf
) and other compile targets invoke programs that start at this root Kconfig
and recursively read the Kconfig
files located in each subdirectory to build their menus. Which subdirectory to visit also is defined in each Kconfig
file and also depends on the config symbol values chosen by the user.
Storing Symbol Values: .config
File
All config symbol values are saved in a special file called .config
. Every time you want to change a kernel compile configuration, you execute a make target, such as menuconfig
or xconfig
. These read the Kconfig
files to create the menus and update the config symbols' values using the values defined in the .config
file. Additionally, these tools update the .config
file with the new options you chose and also can generate one if it didn't exist before.
Because the .config
file is plain text, you also can change it without needing any specialized tool. It is very convenient for saving and restoring previous kernel compilation configurations as well.
有用的命令
您可以对 make defconfig
使用更简单的语法,例如:
$ make ARCH=arm your_board_defconfig
查看可用 defconfig 的完整列表:
$ make ARCH=arm help | grep defconfig
如果您需要执行反向操作(即从广泛的 .config
创建一个整洁的小 defconfig
),您可以使用 savedefconfig
规则:
$ make ARCH=arm savedefconfig
此外,正如 0andriy 提到的,您可以使用 diffconfig
脚本查看从一个 .config
到另一个
的变化:
$ scripts/diffconfig .config_old .config_new
它还会生成include/generated/autoconf.h
。
此头文件包含在 C 源文件中。另一方面,.config
用于 Makefile 系统。
构建系统生成两个文件,并保持一致。
我可以使用以下命令根据自定义 ARM 板的指定体系结构默认值创建 Linux 内核 .config
文件:
ARCH=arm make defconfig KBUILD_DEFCONFIG=var_som_mx6_android_defconfig
我认为这个命令或多或少复制了./arch/arm/configs/var_som_mx6_android_defconfig
到./.config
。但是生成的 .config
文件并不完全是一个副本:
$ diff --unified arch/arm/configs/var_som_mx6_android_defconfig .config
--- arch/arm/configs/var_som_mx6_android_defconfig 2017-01-20 12:10:51.891515984 -0800
+++ .config 2017-01-26 15:31:29.000000000 -0800
@@ -407,6 +407,7 @@
CONFIG_ARM_ERRATA_751472=y
CONFIG_ARM_ERRATA_794072=y
CONFIG_ARM_ERRATA_761320=y
+CONFIG_ARM_ERRATA_845369=y
# CONFIG_ARM_ERRATA_753970 is not set
CONFIG_ARM_ERRATA_754322=y
# CONFIG_ARM_ERRATA_754327 is not set
@@ -2683,7 +2684,6 @@
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
# CONFIG_CUSE is not set
-CONFIG_AUFS_FS=y
#
# Caches
@@ -2759,6 +2759,21 @@
# CONFIG_PSTORE is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+CONFIG_AUFS_SBILIST=y
+# CONFIG_AUFS_HNOTIFY is not set
+# CONFIG_AUFS_RDU is not set
+# CONFIG_AUFS_PROC_MAP is not set
+# CONFIG_AUFS_SP_IATTR is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+# CONFIG_AUFS_BR_FUSE is not set
+CONFIG_AUFS_BDEV_LOOP=y
+# CONFIG_AUFS_DEBUG is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
我不明白额外的行是从哪里来的,而且我一直觉得内核配置、makefile 和构建脚本的内部工作原理很难理解。谁能解释 .config
中的那些行可能来自哪里?
动机
.config
文件并非简单地从您的 defconfig
文件复制而来。接下来以这种格式存储 defconfig
的动机是:在 defconfig
中,我们只能指定具有 non-default 值的选项(即我们为我们的板更改的选项)。这样我们就可以保持小而清晰。每个新内核版本都会带来一堆新选项,这样我们就不需要在每次内核发布时都更新 defconfig
文件。此外,应该提到内核构建系统在 defconfig
文件中保留非常特定的选项顺序,因此最好避免手动修改它。相反,您应该使用 make savedefconfig
规则。
简化说明
当生成 .config
文件时,内核构建系统遍历所有 Kconfig
文件(来自所有子目录),检查这些 Kconfig
文件中的所有选项:
- 如果选项在
defconfig
中被提及,构建系统将该选项放入.config
并在defconfig
中选择值
- 如果
defconfig
中未提及选项,构建系统使用其默认值将该选项放入.config
,在相应的Kconfig
中指定
检查 scripts/kconfig/Makefile and scripts/kconfig/conf.c 个文件以了解它是如何实际完成的。
更准确详细的解释
来自 "Kbuild: the Linux Kernel Build System" by Javier Martinez:
Defining Configuration Symbols:
Kconfig
FilesConfiguration symbols are defined in files known as
Kconfig
files. EachKconfig
file can describe an arbitrary number of symbols and can also include (source) otherKconfig
files. Compilation targets that construct configuration menus of kernel compile options, such asmake menuconfig
, read these files to build the tree-like structure. Every directory in the kernel has oneKconfig
that includes theKconfig
files of its subdirectories. On top of the kernel source code directory, there is aKconfig
file that is the root of the options tree. Themenuconfig
(scripts/kconfig/mconf
),gconfig
(scripts/kconfig/gconf
) and other compile targets invoke programs that start at this rootKconfig
and recursively read theKconfig
files located in each subdirectory to build their menus. Which subdirectory to visit also is defined in eachKconfig
file and also depends on the config symbol values chosen by the user.Storing Symbol Values:
.config
FileAll config symbol values are saved in a special file called
.config
. Every time you want to change a kernel compile configuration, you execute a make target, such asmenuconfig
orxconfig
. These read theKconfig
files to create the menus and update the config symbols' values using the values defined in the.config
file. Additionally, these tools update the.config
file with the new options you chose and also can generate one if it didn't exist before.Because the
.config
file is plain text, you also can change it without needing any specialized tool. It is very convenient for saving and restoring previous kernel compilation configurations as well.
有用的命令
您可以对 make defconfig
使用更简单的语法,例如:
$ make ARCH=arm your_board_defconfig
查看可用 defconfig 的完整列表:
$ make ARCH=arm help | grep defconfig
如果您需要执行反向操作(即从广泛的 .config
创建一个整洁的小 defconfig
),您可以使用 savedefconfig
规则:
$ make ARCH=arm savedefconfig
此外,正如 0andriy 提到的,您可以使用 diffconfig
脚本查看从一个 .config
到另一个
$ scripts/diffconfig .config_old .config_new
它还会生成include/generated/autoconf.h
。
此头文件包含在 C 源文件中。另一方面,.config
用于 Makefile 系统。
构建系统生成两个文件,并保持一致。