高通kernel顶层目录下的AndroidKernel.mk文件

本文详细介绍了高通Android Kernel编译流程中的关键配置文件AndroidKernel.mk的内容。包括变量定义、条件判断、目标和依赖设置等核心部分,以及如何通过这些设置来编译内核。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高通kernel顶层目录下的AndroidKernel.mk文件

高通kernel顶层目录下的AndroidKernel.mk文件是Android的编译系统的一部分,用来编译kernel。

它的位置是在aosp/kernel目录下。

文件层级结构


定义变量【第一处】

ifeq ($(TARGET_PREBUILT_KERNEL),)

    定义变量【第二处】

    ifeq ($(KERNEL_DEFCONFIG)$(wildcard $(KERNEL_CONFIG)),)
        $(error Kernel configuration not defined, cannot build kernel)
    else
        定义变量【第三处】
        定义一些目标和依赖
    endif

endif

文件具体内容(带注释)

定义变量【第一处】

PERL变量

#Android makefile to build kernel as a part of Android Build
PERL        = perl
KERNEL_TARGET 和 INSTALLED_KERNEL_TARGET 变量
KERNEL_TARGET := $(strip $(INSTALLED_KERNEL_TARGET))
ifeq ($(KERNEL_TARGET),)
INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
endif

在build/core/Makefile文件中,定义了INSTALLED_KERNEL_TARGET变量

ifneq ($(strip $(TARGET_NO_KERNEL)),true)
  INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
else
  INSTALLED_KERNEL_TARGET :=
endif

TARGET_NO_KERNEL是在device/厂商/产品名/BoardConfig.mk中定义的

TARGET_NO_KERNEL := false

Makefile中,
ifeq关键字用来判断参数是否相等,
ifneq的关键字是用来判断参数是否不相等,
格式为:

ifneq (ARG1, ARG2) / ifneq (ARG1, ARG2)
ifneq 'ARG1' 'ARG2' / ifneq 'ARG1' 'ARG2'
ifneq "ARG1" "ARG2" / ifneq "ARG1" "ARG2"
ifneq "ARG1" 'ARG2' / ifneq "ARG1" 'ARG2'
ifneq 'ARG1' "ARG2" / ifneq 'ARG1' "ARG2"

综上所述可知,不论TARGET_NO_KERNEL为false还是true,则KERNEL_TARGET和INSTALLED_KERNEL_TARGET的值都为$(PRODUCT_OUT)/kernel。

TARGET_KERNEL_ARCH 和 KERNEL_ARCH 变量
TARGET_KERNEL_ARCH := $(strip $(TARGET_KERNEL_ARCH))
ifeq ($(TARGET_KERNEL_ARCH),)
KERNEL_ARCH := arm
else
KERNEL_ARCH := $(TARGET_KERNEL_ARCH)
endif

TARGET_KERNEL_ARCH是在device/厂商/产品名/BoardConfig.mk中定义的。
如果已经定义为某值(如arm64),KERNEL_ARCH就设定为该值(如arm64)。
反之,则设定为默认值arm

TARGET_KERNEL_HEADER_ARCH 和 KERNEL_HEADER_ARCH 变量
TARGET_KERNEL_HEADER_ARCH := $(strip $(TARGET_KERNEL_HEADER_ARCH))
ifeq ($(TARGET_KERNEL_HEADER_ARCH),)
KERNEL_HEADER_ARCH := $(KERNEL_ARCH)
else
$(warning Forcing kernel header generation only for '$(TARGET_KERNEL_HEADER_ARCH)')
KERNEL_HEADER_ARCH := $(TARGET_KERNEL_HEADER_ARCH)
endif

TARGET_KERNEL_ARCH是在device/厂商/产品名/BoardConfig.mk中定义的。
如果TARGET_KERNEL_HEADER_ARCH为空,KERNEL_HEADER_ARCH就设定为KERNEL_ARCH的值。
反之,则警告并将KERNEL_HEADER_ARCH设定为TARGET_KERNEL_HEADER_ARCH

KERNEL_HEADER_DEFCONFIG 变量
KERNEL_HEADER_DEFCONFIG := $(strip $(KERNEL_HEADER_DEFCONFIG))
ifeq ($(KERNEL_HEADER_DEFCONFIG),)
KERNEL_HEADER_DEFCONFIG := $(KERNEL_DEFCONFIG)
endif

KERNEL_DEFCONFIG是在device/厂商/产品名/AndroidBoard.mk中定义的。
KERNEL_HEADER_DEFCONFIG未找到定义的地方。
当KERNEL_HEADER_DEFCONFIG为空,则被赋值为KERNEL_DEFCONFIG。

binder
# Force 32-bit binder IPC for 64bit kernel with 32bit userspace
ifeq ($(KERNEL_ARCH),arm64)
ifeq ($(TARGET_ARCH),arm)
KERNEL_CONFIG_OVERRIDE := CONFIG_ANDROID_BINDER_IPC_32BIT=y
endif
endif

通过条件判断,是否让32-bit的binder IPC(进程间通信机制) 强制运行于64bit的kernel的32bit用户空间。

TARGET_KERNEL_CROSS_COMPILE_PREFIX 和 KERNEL_CROSS_COMPILE 变量
TARGET_KERNEL_CROSS_COMPILE_PREFIX := $(strip $(TARGET_KERNEL_CROSS_COMPILE_PREFIX))
ifeq ($(TARGET_KERNEL_CROSS_COMPILE_PREFIX),)
KERNEL_CROSS_COMPILE := arm-eabi-
else
KERNEL_CROSS_COMPILE := $(TARGET_KERNEL_CROSS_COMPILE_PREFIX)
endif

TARGET_KERNEL_CROSS_COMPILE_PREFIX是在device/厂商/产品名/AndroidBoard.mk中定义的。
例:TARGET_KERNEL_CROSS_COMPILE_PREFIX := aarch64-linux-android-

定义变量【第二处】

KERNEL_CFLAGS变量
KERNEL_GCC_NOANDROID_CHK := $(shell (echo "int main() {return 0;}" | $(KERNEL_CROSS_COMPILE)gcc -E -mno-android - > /dev/null 2>&1 ; echo $$?))
ifeq ($(strip $(KERNEL_GCC_NOANDROID_CHK)),0)
KERNEL_CFLAGS := KCFLAGS=-mno-android
endif

KERNEL_GCC_NOANDROID_CHK 变量如果为0,则定义KERNEL_CFLAGS为KCFLAGS=-mno-android

mkfile_path变量
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))

获得mk文件路径

current_dir变量
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
TARGET_KERNEL_VERSION变量
ifeq ($(TARGET_KERNEL_VERSION),)
    TARGET_KERNEL_VERSION := 3.18
endif
TARGET_KERNEL变量
TARGET_KERNEL := msm-$(TARGET_KERNEL_VERSION)
通过TARGET_KERNEL变量,定义KERNEL_OUT等变量
ifeq ($(TARGET_KERNEL),$(current_dir))
    # New style, kernel/msm-version
    BUILD_ROOT_LOC := ../../
    TARGET_KERNEL_SOURCE := kernel/$(TARGET_KERNEL)
    KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/kernel/$(TARGET_KERNEL)
    KERNEL_SYMLINK := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
    KERNEL_USR := $(KERNEL_SYMLINK)/usr
else
    # Legacy style, kernel source directly under kernel
    KERNEL_LEGACY_DIR := true
    BUILD_ROOT_LOC := ../
    TARGET_KERNEL_SOURCE := kernel
    KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
endif
KERNEL_CONFIG变量
KERNEL_CONFIG := $(KERNEL_OUT)/.config

定义变量【第三处】

TARGET_PREBUILT_INT_KERNEL变量
ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
$(info Using uncompressed kernel)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image
else
ifeq ($(KERNEL_ARCH),arm64)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image.gz
else
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/zImage
endif
endif
依据TARGET_KERNEL_APPEND_DTB变量,定义TARGET_PREBUILT_INT_KERNEL变量
ifeq ($(TARGET_KERNEL_APPEND_DTB), true)
$(info Using appended DTB)
TARGET_PREBUILT_INT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)-dtb
endif
KERNEL_HEADERS_INSTALL变量
KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
KERNEL_MODULES_INSTALL变量
KERNEL_MODULES_INSTALL := system
KERNEL_MODULES_OUT变量
KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
TARGET_PREBUILT_KERNEL变量
TARGET_PREBUILT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)
宏mv-modules
define mv-modules
mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.dep`;\
if [ "$$mdpath" != "" ];then\
mpath=`dirname $$mdpath`;\
ko=`find $$mpath/kernel -type f -name *.ko`;\
for i in $$ko; do mv $$i $(KERNEL_MODULES_OUT)/; done;\
fi
endef
宏clean-module-folder
define clean-module-folder
mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.dep`;\
if [ "$$mdpath" != "" ];then\
mpath=`dirname $$mdpath`; rm -rf $$mpath;\
fi
endef

目标和依赖

ifneq ($(KERNEL_LEGACY_DIR),true)
$(KERNEL_USR): $(KERNEL_HEADERS_INSTALL)
    rm -rf $(KERNEL_SYMLINK)
    ln -s kernel/$(TARGET_KERNEL) $(KERNEL_SYMLINK)

$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_USR)
endif

$(KERNEL_OUT):
    mkdir -p $(KERNEL_OUT)

$(KERNEL_CONFIG): $(KERNEL_OUT)
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
    $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
            echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
            echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi

$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL)
    $(hide) echo "Building kernel..."
    $(hide) rm -rf $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/dts
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_CFLAGS)
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_CFLAGS) modules
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) INSTALL_MOD_PATH=$(BUILD_ROOT_LOC)../$(KERNEL_MODULES_INSTALL) INSTALL_MOD_STRIP=1 ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) modules_install
    $(mv-modules)
    $(clean-module-folder)

$(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT)
    $(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \
            rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_HEADER_DEFCONFIG); \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_HEADER_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) headers_install; fi
    $(hide) if [ "$(KERNEL_HEADER_DEFCONFIG)" != "$(KERNEL_DEFCONFIG)" ]; then \
            echo "Used a different defconfig for header generation"; \
            rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG); \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG); fi
    $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
            echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
            echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi

kerneltags: $(KERNEL_OUT) $(KERNEL_CONFIG)
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) tags

kernelconfig: $(KERNEL_OUT) $(KERNEL_CONFIG)
    env KCONFIG_NOTIMESTAMP=true \
         $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) menuconfig
    env KCONFIG_NOTIMESTAMP=true \
         $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) savedefconfig
    cp $(KERNEL_OUT)/defconfig $(TARGET_KERNEL_SOURCE)/arch/$(KERNEL_ARCH)/configs/$(KERNEL_DEFCONFIG)
<think>我们正在处理一个关于在Android.mk文件中复制文件到SD卡目录的问题。根据引用内容,我们可以得知以下几点:1.不同Android版本的SD卡路径可能不同(引用[1])2.Android构建系统中,我们可以通过Android.mk来定义编译和操作(引用[3]和[5])3.Android8.1MTK平台上,有预置文件到SD卡的例子(引用[4])但是请注意,直接通过Android.mk在编译时复制文件到SD卡目录可能并不合适,因为SD卡目录(通常是/storage/emulated/0/)在设备上是用户数据分区,而编译时生成的系统镜像(system.img,vendor.img等)并不包含这个分区的内容。通常,预置文件到系统分区(比如/system/etc/)可以在编译时通过Android.mk实现。但如果要预置到SD卡目录(即内部存储的模拟SD卡),则需要在设备首次启动时由系统服务完成复制。引用[4]提到了一种方法:使用一个服务(CopyService)来预置媒体文件。这通常是在设备第一次启动或重置后,系统将预置的文件从系统分区复制到内部存储(模拟SD卡)的相应目录。因此,我们可能需要两个步骤:1.将需要复制的文件预置到系统分区的某个目录(例如/system/etc/preload/)。2.在设备首次启动时,通过一个服务或脚本将这些文件复制到SD卡目录。但是,用户的问题是如何在Android.mk中实现。由于Android.mk主要用于编译和将文件打包到系统镜像,因此第一步(将文件放入系统分区)是可以在Android.mk中实现的。关于第二步,我们可以参考引用[4]的方法,使用一个服务来复制。但是,这个服务并不是在Android.mk中定义的,而是在Java代码中定义,并在AndroidManifest.xml中注册。因此,针对用户问题,我们可以在Android.mk中将文件复制到系统分区,然后通过系统服务在设备启动时将其复制到SD卡目录。这样,我们就需要两个部分:Android.mk部分和Java服务部分。但是,如果用户仅仅想在Android.mk中完成(即在编译时将文件直接放到SD卡目录),这是不可能的,因为SD卡目录(内部存储)是用户数据分区,编译时生成的是系统镜像,它们位于不同的分区。因此,我们只能按照上述两步走的方法。以下是如何在Android.mk中预置文件到系统分区的示例:```makefile#假设我们要将文件example.mp3预置到/system/etc/preload/LOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)#模块名LOCAL_MODULE:=example_mp3#指定为预编译文件LOCAL_MODULE_CLASS:=ETC#文件路径(相对于LOCAL_PATH)LOCAL_SRC_FILES:=example.mp3#安装路径,这里我们安装到/system/etc/preload/LOCAL_MODULE_PATH:=$(TARGET_OUT)/etc/preloadLOCAL_MODULE_TAGS:=optionalinclude$(BUILD_PREBUILT)```然后,我们还需要在设备启动时将这些文件复制到SD卡目录。这可以通过编写一个系统服务(如引用[4]中的CopyService)或通过init.rc脚本实现。由于用户的问题集中在Android.mk,我们先给出如何将文件放入系统分区。至于如何复制到SD卡,我们可以参考引用[4]的方法:1.创建一个服务(比如CopyService),在第一次启动时运行,将/system/etc/preload/下的文件复制到Environment.getExternalStorageDirectory()所对应的目录(即模拟SD卡的根目录)。但是,由于不同设备路径可能不同(引用[1]),我们应该使用AndroidAPI来获取外部存储目录,而不是硬编码路径。由于服务部分需要用Java编写,这里就不展开,但可以提供一个简化的思路:-在MediaProvider或自己的应用程序中创建一个服务。-在服务的onStartCommand中,检查目标目录是否存在文件,如果没有,则从系统分区复制。在AndroidManifest.xml中注册服务(如引用[4]所示):```xml<serviceandroid:name=".CopyService"android:enabled="true"android:exported="true"/>```在build.gradle中,确保有jniLibs的配置(引用[2])可能不需要,除非涉及本地库。总结:在Android.mk中只能将文件预置到系统分区,然后通过系统服务在设备启动后复制到SD卡目录。相关问题:1.如何在Android设备启动时运行一个服务?2.如何在Android中获取SD卡的正确路径?3.如何在Android中复制文件?</think> ### 如何通过 Android.mk文件复制到 SD 卡目录Android 构建系统中,通过 `Android.mk` 实现文件复制到 SD 卡目录需要结合以下步骤: #### 1. **确定 SD 卡目标路径** - 使用动态路径 `$(TARGET_OUT_DATA)` 或 `$(TARGET_OUT_DATA_MEDIA)` 作为基础路径 - 完整路径示例:`$(TARGET_OUT_DATA)/media/0/`(对应 `/data/media/0/`) - 不同 Android 版本路径可能变化(如早期版本可能是 `/sdcard/`),建议使用系统变量[^1][^4] #### 2. **在 Android.mk 中定义复制规则** ```makefile # 示例:复制 test.jpg 到 SD 卡 Pictures 目录 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # 声明要复制的文件 LOCAL_MODULE := test.jpg LOCAL_SRC_FILES := $(LOCAL_MODULE) LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/media/0/Pictures LOCAL_MODULE_TAGS := optional include $(BUILD_PREBUILT) # 声明目录复制(需创建对应目录结构) include $(CLEAR_VARS) LOCAL_MODULE := media_files LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_TAGS := optional LOCAL_POST_INSTALL_CMD := \ mkdir -p $(TARGET_OUT_DATA)/media/0/Music; \ cp -r $(LOCAL_PATH)/preload/* $(TARGET_OUT_DATA)/media/0/Music/ include $(BUILD_PHONY_PACKAGE) ``` #### 3. **关键参数说明** - `LOCAL_MODULE_PATH`:指定目标路径(使用 `$(TARGET_OUT_DATA)` 变量) - `LOCAL_POST_INSTALL_CMD`:执行复制命令(支持 shell 指令) - `BUILD_PREBUILT`:用于预置文件 - `BUILD_PHONY_PACKAGE`:用于执行操作但不会生成实际输出文件 #### 4. **在设备首次启动时复制** 对于更高版本(Android 8.1+),可在系统服务中实现复制逻辑[^4]: 1. 在 `MediaProvider` 中注册 `CopyService` ```xml <!-- AndroidManifest.xml --> <service android:name="com.android.providers.media.CopyService" android:enabled="true" android:exported="true"/> ``` 2. 在服务中实现从系统分区到 SD 卡的复制: ```java // CopyService.java public void copyPreloadFiles() { File systemDir = new File("/system/etc/preload/"); File sdcardDir = Environment.getExternalStorageDirectory(); // 执行文件复制操作... } ``` #### 5. **注意事项** 1. **路径兼容性** - 使用 `Environment.getExternalStorageDirectory()` 动态获取路径(Java 层) - 避免硬编码路径(如 `/sdcard/`)[^1] 2. **权限要求** - 在 `AndroidManifest.xml` 中添加权限: ```xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ``` 3. **执行时机** - 系统应用可在 `BOOT_COMPLETED` 广播触发后执行复制 - 预置文件操作应在第一次开机时完成(通过 `SharedPreferences` 记录状态) 4. **平台差异** - MTK 平台参考路径:`vendor/mediatek/proprietary/packages/providers/MediaProvider/[^4]` - 高通平台可能使用不同路径机制
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值