Android——编译安装Module的控制因素

本文详细解读了Android 4.2版本中Module的LOCAL_MODULE_TAGS控制过程及其与TARGET_BUILD_VARIANT的关系,同时阐述了PRODUCT_PACKAGES在Module安装中的关键作用。通过分析不同条件下Module的安装规则,帮助开发者更好地掌握Module控制与安装的细节。

 在前文Android——编译系统初始化设置中有解析编译的TARGET_BUILD_VARIANT的配置与基本区别,

其中的一些编译控制是对的但是Module的Android.mk中的LOCAL_MODULE_TAGS 控制并不全适用目前的android4.2,这里记录一下我对Module的控制过程。


                                                                  撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/39209341

一.LOCAL_MODULE_TAGS:

首先还是这个放在Android.mk中的变量,默认在/build/core/base_rules.mk 中:

LOCAL_MODULE_TAGS := $(sort $(LOCAL_MODULE_TAGS))
ifeq (,$(LOCAL_MODULE_TAGS))
  LOCAL_MODULE_TAGS := optional
endif

而且并不是 LOCAL_MODULE_TAGS :=optional 就会都安装进system.img !


LOCAL_MODULE_TAGS 在 android 4.2 能取的值有:

# Only the tags mentioned in this test are expected to be set by module
# makefiles. Anything else is either a typo or a source of unexpected
# behaviors.
ifneq ($(filter-out debug eng tests optional samples shell_ash shell_mksh,$(LOCAL_MODULE_TAGS)),)
$(warning unusual tags $(LOCAL_MODULE_TAGS) on $(LOCAL_MODULE) at $(LOCAL_PATH))
endif

debug eng tests optional samples shell_ash shell_mksh  这几个值,没有user ,这是跟之前的一个差别!


其中TARGET_BUILD_VARIANT 还是对应:


eng  : 

默认类型,安装 LOCAL_MODULE_TAGS 的类型为/build/core/main.mk:

ifeq ($(TARGET_BUILD_VARIANT),eng)
tags_to_install := debug eng

安装 PRODUCT_PACKAGES 中定义的Module


user   :

用于发行版,像之前描述的关闭log,shel,rootl,编译出odex Android——编译odex保护 

 LOCAL_MODULE_TAGS 的值不能为 user

安装哪些Module 只依赖与 PRODUCT_PACKAGES


userdebug   :

用于调试,安装 LOCAL_MODULE_TAGS 的类型为/build/core/main.mk:

  ifeq ($(user_variant),userdebug)
    # Pick up some extra useful tools
    tags_to_install += debug


安装 PRODUCT_PACKAGES 中定义的Module



symbols 目录 :

这里记录一种现象,不管 Module 是apk 还是 lib ,有的时候在单独 mmm 编译 的时候,

是可以安装到  /out 中的system对应位置的,最后能够打包进系统的system.img


但是 如果整体的 make -j* 编译系统,那么 对应的 apk .lib 就会生成在 /out 下的 symbols/system 对应的位置,

最后是不会打包进系统system.img 的!


这就是因为 Module 的LOCAL_MODULE_TAGS 和当前的编译的TARGET_BUILD_VARIANT 没有满足上面说到的规则,

Module 并不认定为需要 install 的!

可以按照上面的规则,修改Module的 LOCAL_MODULE_TAGS 或者 看下面的 在 PRODUCT_PACKAGES 中添加 Module !


这里只区分对Module的安装控制,可以看到在4.2 中 对Module的控制级别最高的是 PRODUCT_PACKAGES 这个变量!



二.PRODUCT_PACKAGES :

这个变量在很多.mk中都有赋值,比如在device中的 device.mk 中,而且都是 类似这样的:

# jscese add libusb and compat lib ,usb-modeswitch execute binary for 3G 
PRODUCT_PACKAGES += \
    rild \
    libusb \
    libusb-compat \
    usb_modeswitch 
#end

都是 += 累加操作!

这就代表这些Module 无论如何都会被编译安装进系统。

简单记录下PRODUCT_PACKAGES 的作用过程

首先在main.mk中的

product_MODULES 以及 product_FILES

  # The base list of modules to build for this product is specified
  # by the appropriate product definition file, which was included
  # by product_config.make.
  product_MODULES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
  # Filter out the overridden packages before doing expansion
  product_MODULES := $(filter-out $(foreach p, $(product_MODULES), \
      $(PACKAGES.$(p).OVERRIDES)), $(product_MODULES))
  $(call expand-required-modules,product_MODULES,$(product_MODULES))
  product_FILES := $(call module-installed-files, $(product_MODULES))


modules_to_install

modules_to_install := $(sort \
    $(ALL_DEFAULT_INSTALLED_MODULES) \
    $(product_FILES) \
    $(foreach tag,$(tags_to_install),$($(tag)_MODULES)) \
    $(call get-tagged-modules, shell_$(TARGET_SHELL)) \
    $(CUSTOM_MODULES) \
  )

这个就是需要安装的一个变量了,有用到上面说得到的变量 tags_to_install  还有 product_FILES

modules_to_install 还会经过一些过滤处理,具体可看main.mk中


ALL_DEFAULT_INSTALLED_MODULES

# build/core/Makefile contains extra stuff that we don't want to pollute this
# top-level makefile with.  It expects that ALL_DEFAULT_INSTALLED_MODULES
# contains everything that's built during the current make, but it also further
# extends ALL_DEFAULT_INSTALLED_MODULES.
ALL_DEFAULT_INSTALLED_MODULES := $(modules_to_install)
include $(BUILD_SYSTEM)/Makefile
modules_to_install := $(sort $(ALL_DEFAULT_INSTALLED_MODULES))
ALL_DEFAULT_INSTALLED_MODULES :=

再加载进Android的 Makefile 文件,其中根据 ALL_DEFAULT_INSTALLED_MODULES 进行安装!这里暂不深入。


make 编译的时候的依赖如下:

droid:

# Building a full system-- the default is to build droidcore
droid: droidcore dist_files
...
.PHONY: droid


droidcore :

# Build files and then package it into the rom formats
.PHONY: droidcore
droidcore: files \
    systemimage \
    $(INSTALLED_BOOTIMAGE_TARGET) \
    $(INSTALLED_RECOVERYIMAGE_TARGET) \
    $(INSTALLED_USERDATAIMAGE_TARGET) \
    $(INSTALLED_CACHEIMAGE_TARGET) \
    $(INSTALLED_FILES_FILE)


files :

# All the droid stuff, in directories
.PHONY: files
files: prebuilt \
        $(modules_to_install) \
        $(modules_to_check) \
        $(INSTALLED_ANDROID_INFO_TXT_TARGET)

 可以看到 依赖到了 上面分析到的 modules_to_install   !




<think>嗯,用户询问如何使用Android make命令编译apk。我需要从提供的参考文献中提取相关信息,同时结合Android编译系统的实际知识来回答。 用户引用了四篇资料:[^1]讨论了Android.mk和Android.bp编译apk、jar、so的方法;[^2]是关于android源码编译apk的,包含Android.mk文件的示例;[^3]涉及反编译apk;[^4]展示了apk编译过程的部分命令行。 用户的核心需求是了解make命令编译apk的具体步骤。根据[^1]和[^2],编译apk的关键是编写正确的Android.mk文件并执行make命令。需要强调几个要点:环境初始化(source build/envsetup.sh),选择目标设备(lunch),模块编译(make module_name)。模块名称可以通过mm命令或make全名指定。 在回答中,应该结构化地列出步骤:先说明准备工作(环境变量配置),再讲解Android.mk编写要点(参考[^2]的LOCAL_PATH等变量),最后说明编译命令(参考[^1]的make framework-minus-apex等示例)。需要提醒用户注意路径问题和编译类型(eng/userdebug)。 用户可能是Android系统开发者或ROM定制者,对源码编译有基础认知但需要具体指导。可以推测ta可能遇到的问题是不知道如何正确配置mk文件,或是找不到模块编译命令。因此在相关问题中可以延伸编译优化(如减少编译时间)、多模块编译等实用场景。 需要验证回答的可靠性:检查提供的make命令是否与最新AOSP兼容(mm命令仍有效),确认Android.mk基础语法未过时(虽然Google推荐bp,但mk仍广泛支持)。同时补充实用技巧,比如如何查找模块名(使用mmp快捷命令)——这是参考文献未提及但实际很有用的知识。 </think>以下是使用 Android `make` 命令编译 APK 的详细步骤和关键要点,基于 AOSP (Android Open Source Project) 源码环境: --- ### **步骤 1:初始化编译环境** 在 AOSP 源码根目录执行: ```bash source build/envsetup.sh # 加载环境变量和实用函数 lunch <target> # 选择目标设备,如 `aosp_arm64-eng` ``` - `<target>` 示例: `aosp_arm-eng` (32位模拟器) | `aosp_arm64-userdebug` (64位真机调试版) *执行 `lunch` 后按提示选择目标 [^1][^2]。* --- ### **步骤 2:编写编译配置文件** 在 APK 项目目录(如 `packages/apps/MyApp/`)创建 **`Android.mk`** ️ ```makefile LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PACKAGE_NAME := MyApp # APK 名称 LOCAL_SRC_FILES := $(call all-java-files-under, src) # 指定源码目录 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res # 资源目录 LOCAL_CERTIFICATE := platform # 使用系统签名(系统级 APK 需此配置) LOCAL_PRIVILEGED_MODULE := true # 安装到 /system/priv-app(可选) include $(BUILD_PACKAGE) # 声明编译 APK ``` *关键配置说明:* - `LOCAL_CERTIFICATE`: - `platform`:系统签名(需系统权限时使用) - `PRESIGNED`:使用预签名 APK(如预编译的第三方 APK)[^2] - 若需依赖库,添加: ```makefile LOCAL_STATIC_JAVA_LIBRARIES := lib1 lib2 # 静态库 LOCAL_JAVA_LIBRARIES := android.test.runner # 动态库[^1] ``` --- ### **步骤 3:执行编译命令** #### 方式一:编译单个模块(推荐) ```bash mmm packages/apps/MyApp/ # 仅编译指定目录下的模块 ``` - 编译输出路径:`out/target/product/<device>/system/app/MyApp/MyApp.apk` #### 方式二:全量编译(耗时较长) ```bash make MyApp # 根据 LOCAL_PACKAGE_NAME 编译 ``` > ⚠️ **注意**:若出现 `MyApp nothing to do` 错误,检查: > 1. `Android.mk` 是否在正确路径 > 2. 模块名是否通过 `lunch` 正确注册 [^1][^2] --- ### **步骤 4:推送 APK 到设备** ```bash adb root && adb remount # 获取 root 并挂载系统分区可写 adb push out/.../MyApp.apk /system/app/MyApp/ # 推送 APK adb reboot # 重启生效 ``` --- ### **常见问题解决** 1. **依赖缺失错误**: 在 `Android.mk` 中添加: ```makefile LOCAL_STATIC_JAVA_LIBRARIES := androidx.appcompat_appcompat ``` 2. **资源编译失败**: 检查 `LOCAL_RESOURCE_DIR` 路径是否正确,或执行: ```bash make clean-MyApp && mmm packages/apps/MyApp/ ``` 3. **签名冲突**: 系统 APK 必须使用 `LOCAL_CERTIFICATE := platform` [^1][^2]。 --- ### **编译流程示意图** ```mermaid graph LR A[source build/envsetup.sh] --> B[lunch 选择目标] B --> C[编写 Android.mk] C --> D[mmm 或 make 编译] D --> E[生成 APK] E --> F[adb 推送并重启] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值