Android 整包编译至 Linux Kernel 时失败并提示 .config 配置错误的解决方法

Android 整包编译至 Linux Kernel 时失败并提示 .config 配置错误的解决方法


Qidi 2020.10.29 (Markdown & Haroopad)


【情况描述】
更新本地 Android 代码后,对 out/ 目录执行了 clean 操作,并重新编译整包。
编译到 Kernel 时失败,报错信息如下:

[  0% 49/14103] //hardware/interfaces/audiodsp/1.0:android.hardware.audiodsp@1.0 clang++ .intermediates/hardware/interfaces/audiodsp/1.0/android.hardware.audiodsp@1.0_genc++/gen/android/hardware/audiodsp/1.0/types.cpp
[  0% 50/14103] build /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check
FAILED: /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check
/bin/bash -c "([[ -e /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ]] && mv -f /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save ; true ) && (cat kernel/config-lts/v4.9/bxt/android/x86_64_defconfig > /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ) && (make -j28 SHELL=/bin/bash -C kernel/bxt O=/home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel ARCH=x86_64 INSTALL_MOD_PATH=. CROSS_COMPILE=\" /home/qihuang/Titan/out/host/linux-x86/poky/sysroots/x86_64-pokysdk-linux/usr/bin/x86_64-poky-linux/x86_64-poky-linux-\" CCACHE_SLOPPINESS= EXTRA_FW=\"cyttsp6_fw.bin i915/bxt_dmc_ver1.bin i915/bxt_dmc_ver1_04.bin i915/bxt_dmc_ver1_07.bin i915/bxt_guc_ver1.bin i915/bxt_guc_ver3.bin i915/bxt_guc_ver8.bin i915/bxt_guc_ver8_7.bin i915/bxt_huc_ver01_07_1398.bin i915/huc_gen9lp.bin ipu4_cpd_a0.bin ipu4_cpd_b0.bin\" EXTRA_FW_DIR=\"/home/qihuang/Titan/out/target/product/titan_fca_dv2/vendor/firmware\" olddefconfig ) && (kernel/bxt/scripts/diffconfig /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.old /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config > /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ) && ([[ -e /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save ]] && mv -f /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ; true ) && (if [[ -s /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ]] ; then        echo \"CHECK KERNEL DEFCONFIG FATAL ERROR :\" ;         echo \"Kernel config copied from kernel/config-lts/v4.9/bxt/android/x86_64_defconfig has some config issue.\" ;           echo \"Final '.config' and '.config.old' differ. This should never happen.\" ;       echo \"Observed diffs are :\" ;         cat /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ;          echo \"Root cause is probably that a dependancy declared in Kconfig is not respected\" ;     echo \"or config was added in Kconfig but value not explicitly added to defconfig.\" ;       echo \"Recommanded method to generate defconfig is menuconfig tool instead of manual edit.\" ;       exit 1;  fi )"
make: Entering directory '/home/qihuang/Titan/kernel/bxt'
make[1]: Entering directory '/home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel'
  GEN     ./Makefile
scripts/kconfig/conf  --olddefconfig Kconfig
.config:2069:warning: override: reassigning to symbol TOUCHSCREEN_ATMEL_MXT
.config:2079:warning: override: reassigning to symbol ENABLE_MOBIS_DISPLAY
#
# configuration written to .config
#
make[1]: Leaving directory '/home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel'
make: Leaving directory '/home/qihuang/Titan/kernel/bxt'
CHECK KERNEL DEFCONFIG FATAL ERROR :
Kernel config copied from kernel/config-lts/v4.9/bxt/android/x86_64_defconfig has some config issue.
Final '.config' and '.config.old' differ. This should never happen.
Observed diffs are :
+EFI_CUSTOM_SSDT_OVERLAYS y
+LOCK_DOWN_KERNEL n
+STATIC_USERMODEHELPER n
Root cause is probably that a dependancy declared in Kconfig is not respected
or config was added in Kconfig but value not explicitly added to defconfig.
Recommanded method to generate defconfig is menuconfig tool instead of manual edit.**
[  0% 51/14103] //hardware/interfaces/audiodsp/1.0:android.hardware.audiodsp@1.0 clang++ .intermediates/hardware/interfaces/audiodsp/1.0/android.hardware.audiodsp@1.0_genc++/gen/android/hardware/audiodsp/1.0/types.cpp [x86]
[  0% 52/14103] target  C: hostapd <= vendor/harman/external/cypress/wpa_supplicant/hostapd/src/drivers/driver_nl80211.c
ninja: build stopped: subcommand failed.
17:53:14 ninja failed with: exit status 1

#### failed to build some targets (01:26 (mm:ss)) ####

qihuang@CCM-Android-4:~/Titan$

花了一上午时间才解决问题。估计正在看这篇文章的朋友们也是被困扰很久了不得其法,才寻到这里来。所以先说编译失败的原因和解决方法吧,最后再写分析过程。


【编译失败原因】

  1. 默认配置文件.config 以及 .config.old 的配置内容不相同(比如 .config 中配的 xxx=y,但 .config.old 中配的 xxx=n);或者

  2. Kconfig 中的配置项数目和 默认配置文件中的配置项数目不同(比如 .config 中配置了 xxx=y,但 .config.old 中却没有 xxx 这一项)。

注意:这里说的 默认配置文件,在不同的平台上或者不同的公司里,其文件命名会有所不同。以我的默认配置文件为例,因为是 x86 平台,所以文件名为 x86_64_defconfig。但你可能会发现你的默认配置文件名叫 arm_xxx_defconfig 或别的名字。


【解决办法】

  1. 如果是各文件中的配置内容不同,那么修改各自内容为相同配置;

  2. 如果是各文件中配置项数目不同,在确认代码确实是最新版本的情况下,作为解决编译问题的临时方案,可以手动删除 Kconfig 中的多余项、或添加缺失项。

以我此次碰到的情形为例,属于第 2 种情况。其报错信息中有如下提示:

CHECK KERNEL DEFCONFIG FATAL ERROR :
Kernel config copied from kernel/config-lts/v4.9/bxt/android/x86_64_defconfig has some config issue.
Final '.config' and '.config.old' differ. This should never happen.
Observed diffs are :
+EFI_CUSTOM_SSDT_OVERLAYS y
+LOCK_DOWN_KERNEL n
+STATIC_USERMODEHELPER n

配置项名称前的 +号 含义为:相较于 .config.old 中的配置, .config 中多出了该项配置。所以我依次找到上述三项配置所在的 Kconfig 文件,手动将其删除(当然如果你看到的是 -号,相应地就应该添加上配置项)。改动如下:

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 8ebc6f8bf9b9..c981be17d3c0 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -129,17 +129,6 @@ config EFI_TEST
          Say Y here to enable the runtime services support via /dev/efi_test.
          If unsure, say N.

-config EFI_CUSTOM_SSDT_OVERLAYS
-       bool "Load custom ACPI SSDT overlay from an EFI variable"
-       depends on EFI_VARS && ACPI
-       default ACPI_TABLE_UPGRADE
-       help
-         Allow loading of an ACPI SSDT overlay from an EFI variable specified
-         by a kernel command line option.
-
-         See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
-         information.
-
 endmenu

 config UEFI_CPER
diff --git a/security/Kconfig b/security/Kconfig
index 82740d26de21..a27ec6fc6750 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -184,28 +184,6 @@ config FORTIFY_SOURCE
          Detect overflows of buffers in common string and memory functions
          where the compiler can determine and validate the buffer sizes.

-config STATIC_USERMODEHELPER
-       bool "Force all usermode helper calls through a single binary"
-       help
-         By default, the kernel can call many different userspace
-         binary programs through the "usermode helper" kernel
-         interface.  Some of these binaries are statically defined
-         either in the kernel code itself, or as a kernel configuration
-         option.  However, some of these are dynamically created at
-         runtime, or can be modified after the kernel has started up.
-         To provide an additional layer of security, route all of these
-         calls through a single executable that can not have its name
-         changed.
-
-         Note, it is up to this single binary to then call the relevant
-         "real" usermode helper binary, based on the first argument
-         passed to it.  If desired, this program can filter and pick
-         and choose what real programs are called.
-
-         If you wish for all usermode helper programs are to be
-         disabled, choose this option and then set
-         STATIC_USERMODEHELPER_PATH to an empty string.
-
 config STATIC_USERMODEHELPER_PATH
        string "Path to the static usermode helper binary"
        depends on STATIC_USERMODEHELPER
@@ -219,14 +197,6 @@ config STATIC_USERMODEHELPER_PATH
          If you wish for all usermode helper programs to be disabled,
          specify an empty string here (i.e. "").

-config LOCK_DOWN_KERNEL
-       bool "Allow the kernel to be 'locked down'"
-       help
-         Allow the kernel to be locked down under certain circumstances, for
-         instance if UEFI secure boot is enabled.  Locking down the kernel
-         turns off various features that might otherwise allow access to the
-         kernel image (eg. setting MSR registers).
-
 source security/selinux/Kconfig
 source security/smack/Kconfig
 source security/tomoyo/Kconfig

【分析过程】
先将原始报错信息进行截取,再整理格式,以便分析。整理后得到关键信息如下:

/bin/bash -c "
([[ -e /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ]] && 
mv -f /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save ; true ) && 
(cat kernel/config-lts/v4.9/bxt/android/x86_64_defconfig > /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ) && 

(make -j28 SHELL=/bin/bash -C kernel/bxt O=/home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel ARCH=x86_64 INSTALL_MOD_PATH=. CROSS_COMPILE=\" /home/qihuang/Titan/out/host/linux-x86/poky/sysroots/x86_64-pokysdk-linux/usr/bin/x86_64-poky-linux/x86_64-poky-linux-\" CCACHE_SLOPPINESS= EXTRA_FW=\"cyttsp6_fw.bin i915/bxt_dmc_ver1.bin i915/bxt_dmc_ver1_04.bin i915/bxt_dmc_ver1_07.bin i915/bxt_guc_ver1.bin i915/bxt_guc_ver3.bin i915/bxt_guc_ver8.bin i915/bxt_guc_ver8_7.bin i915/bxt_huc_ver01_07_1398.bin i915/huc_gen9lp.bin ipu4_cpd_a0.bin ipu4_cpd_b0.bin\" EXTRA_FW_DIR=\"/home/qihuang/Titan/out/target/product/titan_fca_dv2/vendor/firmware\" olddefconfig ) && 

(kernel/bxt/scripts/diffconfig /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.old /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config > /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ) && 
([[ -e /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save ]] && mv -f /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.save /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config ; true ) && 
(if [[ -s /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ]] ; then
        echo \"CHECK KERNEL DEFCONFIG FATAL ERROR :\" ;
		echo \"Kernel config copied from kernel/config-lts/v4.9/bxt/android/x86_64_defconfig has some config issue.\" ;
		echo \"Final '.config' and '.config.old' differ. This should never happen.\" ;
		echo \"Observed diffs are :\" ;
		cat /home/qihuang/Titan/out/target/product/titan_fca_dv2/obj/kernel/.config.check ;
		echo \"Root cause is probably that a dependancy declared in Kconfig is not respected\" ;
		echo \"or config was added in Kconfig but value not explicitly added to defconfig.\" ;
		echo \"Recommanded method to generate defconfig is menuconfig tool instead of manual edit.\" ;
		exit 1;  fi )"

可以看到编译出错前,脚本实际执行了四部分动作:

  1. 拷贝默认配置文件 x86_64_defconfig.config

  2. 编译 olddefconfig 目标;

  3. 调用脚本 diffconfig 对配置文件 .config.old.config 进行比对检查,并将结果输出到文件 .config.check 中;

  4. 如果 .config.check 文件内容不为空,输出报错信息。

其中较为关键的是第 2 和第 3 步。

因为在步骤 3 中,脚本 diffconfig 比较的是 .config.config.old 中的内容,所以我尝试过手动将默认配置文件 x86_64_defconfig 复制成 .config.config.old,试图以此消除检查到不同配置项的错误,但实际情况却是,即使如此修改,编译依然会报错。原因就在于步骤 2 中会根据各个 Kconfig 中的内容生成新的 .config 用于比对,所以必须修改 Kconfig 以达到配置内容一致。这一点也可以从报错信息的提示中得到印证

Root cause is probably that a dependancy declared in Kconfig is not respected
or config was added in Kconfig but value not explicitly added to defconfig.
Recommanded method to generate defconfig is menuconfig tool instead of manual edit.

另外,理解脚本 diffconfig 进行比对的方式、所生成的提示信息的具体含义,也是独自解决这个问题的基础。在此基础上,亦有益于解决类似的编译问题。

阅读脚本,可以发现其关键部分如下:

...
    try:
        a = readconfig(open(configa_filename))
        b = readconfig(open(configb_filename))
...
    # print items in a but not b (accumulate, sort and print)
    old = []
    for config in a:
        if config not in b:
            old.append(config)
    old.sort()
    for config in old:
        print_config("-", config, a[config], None)
        del a[config]

    # print items that changed (accumulate, sort, and print)
    changed = []
    for config in a:
        if a[config] != b[config]:
            changed.append(config)
        else:
            del b[config]
    changed.sort()
    for config in changed:
        print_config("->", config, a[config], b[config])
        del b[config]

    # now print items in b but not in a
    # (items from b that were in a were removed above)
    new = sorted(b.keys())
    for config in new:
        print_config("+", config, None, b[config])

即,脚本会将 .config.old 的内容读取到 变量a 中,将 .config 的内容读取到 变量b 中。如果有配置项存在于 .config.old 中却不存在于 .config 中,则会输出配置项名称,并在名称前加上 - 号;如果有配置项同时存在于 .config.old.config 中,但配置值不同,则会输出配置项名称,并在名称前加上 -> 符号;如果有配置项不存在于 .config.old 中,却存在于 .config 中,则会输出配置项名称,并在名称前加上 + 号。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值