Android.mk

一、基础认知
  1. 定位

    • Android NDK 构建系统的 GNU Makefile 片段,描述 NDK 项目结构
    • 可编译生成:APK、JAVA库、C/C++可执行程序、静态库(.a)、动态库(.so
    • 兼容性:新源码逐渐转向 Android.bp,但 Android.mk 仍被支持
  2. 文件结构

    LOCAL_PATH := $(call my-dir)        # 必选:定义当前路径
    include $(CLEAR_VARS)               # 必选:清除变量(除 LOCAL_PATH)
    LOCAL_SRC_FILES := file.cpp         # 源文件列表
    LOCAL_MODULE := my_module           # 模块名(唯一)
    include $(BUILD_SHARED_LIBRARY)    # 声明构建类型
    
二、核心变量解析
变量 作用 示例
LOCAL_SRC_FILES 指定源文件(C/C++/Java) LOCAL_SRC_FILES := main.c utils.c
LOCAL_MODULE 唯一模块名(自动加前缀:lib.so LOCAL_MODULE := audio_engine
LOCAL_MODULE_PATH 输出路径(system/lib64/, vendor/bin/等) LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib
LOCAL_STATIC_LIBRARIES 依赖的静态库 LOCAL_STATIC_LIBRARIES := libutils
LOCAL_SHARED_LIBRARIES 依赖的动态库 LOCAL_SHARED_LIBRARIES := liblog
LOCAL_CERTIFICATE 签名类型(系统级特权) LOCAL_CERTIFICATE := platform
LOCAL_PREBUILT_* 预编译库声明(JAR/AAR/SO) LOCAL_PREBUILT_JAVA_LIBRARIES := libfoo:path.jar

三、模块编译实战
  1. 生成动态库(.so

    include $(CLEAR_VARS)
    LOCAL_MODULE := native_lib
    LOCAL_SRC_FILES := native.cpp
    include $(BUILD_SHARED_LIBRARY)  # 关键:声明构建类型
    
  2. 生成APK

    include $(CLEAR_VARS)
    LOCAL_PACKAGE_NAME := MyApp
    LOCAL_SRC_FILES := $(call all-subdir-java-files)
    LOCAL_CERTIFICATE := platform  # 系统签名
    include $(BUILD_PACKAGE)       # 关键:构建APK
    
  3. 预编译库集成

    # 声明预编译库
    include $(CLEAR_VARS)
    LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libfoo:libs/foo.jar
    include $(BUILD_MULTI_PREBUILT)
    
    # 在APK中引用
    LOCAL_STATIC_JAVA_LIBRARIES := libfoo
    
四、高级技巧
  1. AAR 集成

    # 1. 声明AAR
    LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES += my_aar:libs/mylib.aar
    include $(BUILD_MULTI_PREBUILT)
    
    # 2. APK引用
    LOCAL_STATIC_JAVA_AAR_LIBRARIES := my_aar
    LOCAL_AAPT_FLAGS += --extra-packages com.example.mylib  # 导入资源
    
  2. SO 库打包

    include $(CLEAR_VARS)
    LOCAL_MODULE := lib_arm
    LOCAL_SRC_FILES := libs/armeabi-v7a/libfoo.so
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_TARGET_ARCH := arm
    include $(BUILD_PREBUILT)
    
    # APK引用
    LOCAL_JNI_SHARED_LIBRARIES := lib_arm
    
  3. 条件编译

    ifeq ($(TARGET_ARCH), arm64)
      LOCAL_SRC_FILES += arm64/optimized.c
    else
      LOCAL_SRC_FILES += generic.c
    endif
    
五、注意事项
  1. 变量污染

    • 每个模块前必须 include $(CLEAR_VARS)
    • 避免跨模块使用 LOCAL_XXX 变量
  2. 路径陷阱

    • 源文件路径:用 $(LOCAL_PATH)/file.ccall all-subdir-files
    • 避免硬编码:LOCAL_MODULE_PATH := $(TARGET_OUT)/custom_dir
  3. SO 库加载

    • 禁止预编译动态库直接打包进 APK
    • 解决方案:预置到 /system/lib64/ 并通过 LOCAL_JNI_SHARED_LIBRARIES 引用
  4. 与 Android.bp 互操作

    • Android.mk 可引用 Android.bp 模块
    • 反之不支持Android.bp 无法引用 Android.mk 模块
六、核心总结
场景 关键指令 输出文件
动态库 include $(BUILD_SHARED_LIBRARY) lib.so
静态库 include $(BUILD_STATIC_LIBRARY) lib.a
APK include $(BUILD_PACKAGE) .apk
可执行程序 include $(BUILD_EXECUTABLE) (无后缀)
预编译文件 include $(BUILD_PREBUILT) 按原文件类型输出

工作实践

  • 模块名全局唯一
  • 优先使用 call all-*-files 自动收集源文件
  • 系统级 APK 务必设置 LOCAL_CERTIFICATE := platform
  • 复杂项目采用 include $(call all-makefiles-under) 递归构建

你可能感兴趣的:(安卓,脚本文件,android)