Android DEX 预优化 & 编译常用变量速查表

Android DEX 预优化 & 编译常用变量速查表

全局编译变量 (命令行/全局配置)、模块级变量Android.mk / Android.bp)、常用组合命令场景选型四部分,适配传统 Make + Soong 双构建体系。


一、全局变量(make/m 命令行 / build 全局配置)

作用:本次编译所有模块统一生效,优先级:命令行 > 全局配置

变量 取值 说明 适用场景
WITH_DEXPREOPT true 全局开启 DEX 预优化(dex2oat),编译阶段生成 .odex/.oat user 正式版本、量产固件,加快开机
false 全局关闭预优化,只保留原始 dex,开机首次运行才做优化 调试、反复刷包、模块频繁修改,编译更快、镜像更小
DONT_DEXPREOPT_PREBUILTS true 不对预编译三方库/预装APK做预优化 调试第三方预编译包、缩减镜像体积
false 所有预装包统一预优化 量产版本
WITH_DEXPREOPT_BOOT_IMG_ONLY true 仅对 boot 镜像内 jar/dex 做预优化,系统应用不优化 折中方案:开机提速 + 控制镜像大小
DISABLE_DEXPREOPT true 强制全局禁用所有 dex 预优化(优先级高于 WITH_DEXPREOPT) 快速编译、排查 dex2oat 报错

补充默认规则

  1. lunch xxx-user:默认 WITH_DEXPREOPT=true
  2. lunch xxx-userdebug / eng:默认 WITH_DEXPREOPT=false
  3. 命令行传参可强制覆盖默认值

二、Android.mk 模块级变量(传统 Make 模块)

仅对当前单个模块生效,优先级高于全局变量

变量 取值 说明
LOCAL_DEX_PREOPT true 当前模块单独开启预优化
false 当前模块关闭预优化
LOCAL_DEX_PREOPT_JAR true/false 单独控制 JAR 包的预优化
LOCAL_NO_DEX true 模块不生成 DEX,自然也不会走预优化

示例片段:

makefile 复制代码
# 该模块单独开启预优化,不受全局开关影响
LOCAL_DEX_PREOPT := true

# 该模块强制关闭预优化
# LOCAL_DEX_PREOPT := false

三、Android.bp 模块级配置(Soong 新构建,Android 7.0+)

对应 mk 语法,Soong 体系专用,作用范围同样为单个模块

1. 普通 APK / App 模块

json 复制代码
android_app {
    name: "SettingsProvider",
    // 开启预优化
    dex_preopt: {
        enabled: true,
    },
    // 关闭预优化
    // dex_preopt: {
    //     enabled: false,
    // },
}

2. Java Library (jar) 模块

json 复制代码
java_library {
    name: "xxx-lib",
    dex_preopt: {
        enabled: true,
    },
}

全局 Soong 兜底配置

device/xxx/xxx/soong_config.mk 中可全局默认开关:

makefile 复制代码
SOONG_CONFIG_android_dex_preopt := true

四、高频实用编译命令(结合多线程 + 优化开关)

统一使用 m(推荐,任意目录执行),make 需在源码根目录

1. 标准用法(规范顺序:变量 → 线程 → 目标)

bash 复制代码
# 全局开启预优化,编译 SettingsProvider,CPU 满线程编译
m WITH_DEXPREOPT=true -j$(nproc) SettingsProvider

# 全局关闭预优化(调试首选,编译更快)
m WITH_DEXPREOPT=false -j$(nproc) SettingsProvider

# 强制全局禁用所有预优化(最高优先级)
m DISABLE_DEXPREOPT=true -j$(nproc) SettingsProvider

2. 仅优化 boot 镜像,其余不优化

bash 复制代码
m WITH_DEXPREOPT_BOOT_IMG_ONLY=true -j$(nproc) SettingsProvider

3. 编译整个系统 + 全局预优化(量产镜像)

bash 复制代码
m WITH_DEXPREOPT=true -j$(nproc)

4. 跳过预优化 + 跳过预编译包优化(极致提速调试)

bash 复制代码
m WITH_DEXPREOPT=false DONT_DEXPREOPT_PREBUILTS=true -j$(nproc)

五、场景选型 & 避坑指南

1. 该开还是关?

  • 量产/正式固件 :开 WITH_DEXPREOPT=true → 开机快、运行性能好,代价是镜像体积变大、编译变慢
  • 日常调试/迭代模块 :关 WITH_DEXPREOPT=false → 编译速度大幅提升,刷包测试更高效
  • 只改单个应用 :优先用模块级开关(LOCAL_DEX_PREOPT / dex_preopt),不要改全局

2. 常见问题

  1. 开启预优化后编译报错 dex2oat
    临时加 DISABLE_DEXPREOPT=true 跳过优化,先排查代码问题
  2. system.img 空间不足
    关闭全局预优化,或仅开启 boot 镜像优化
  3. 改了模块代码,生效异常
    预优化会缓存 odex 文件,建议编译前先清缓存:make clean-SettingsProvider

3. 优先级总结(从高到低)

模块级配置(Android.mk/bp) > 命令行全局变量 > 系统默认配置(lunch 类型)