关于android.mk文件编写

关于Android.mk文件编写


常用LOCAL变量,构建系统变量介绍

LOCAL_PATH ,Android.mk文件的路径,它不会被$(CLEAR_VARS)清除

LOCAL_MODULE ,编译后的模块名,唯一

LOCAL_MODULE_FILENAME ,模块文件名,可选,用来重新定义生成的输出文件名称,可以覆盖LOCAL_MODULE的值

LOCAL_LDLIBS ,链接标志的可选列表,常用来添加系统库,党对目标文件进行链接以生成输出文件时该标志将被传送给链接器,如-llog 引入NDK提供的动态库

LOCAL_CPPFLAGS ,如-DEBUG 为cpp源文件定义了一个宏,打开log开关

LOCAL_CPP_EXTENSION ,C++源文件的默认扩展名是.cpp,这个变量可以用来为C++源码指定一个或多个文件扩展名

LOCAL_CPP_EXTENSION := .cpp .cxx

LOCAL_CPP_FEATURES ,可选变量,用来指明模块所依赖的具体C++特性,如RTTI、execptions等

LOCAL_CPP_FEATURES := rtti

LOCAL_C_INCLUDES ,可选目录列表,默认NDK安装目录的相对路径,用来搜索头文件。

LOCAL_C_INCLUDES := sources/shared-module

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include

LOCAL_CFLAGS ,一组可选的编辑器标志,在编译C和C++源文件的时候会被传送给编译器

LOCAL_CFLAGS := -DNDEBUG -DPORT=1234

LOCAL_CFLAGS := -l //指定include目录,这个方法比使用LOCAL_C_INCLUDES好

LOCAL_SRC_FILES

LOCAL_ARM_MODE ,ARM机器体系结构特有变量,用于指定要生成的ARM二进制类型,默认情况下,构建系统的拇指模式下用16位指令,可以改为arm来指定使用32位指令

LOCAL_ARM_NEON ,可选参数,设置为true时,会将浮点编译成neon指令,极大加快浮点运算(前提硬件支持,只有target为armeabi-v7a才可以)

LOCAL_STATIC_LIBRARIES ,在将第三方代码模块生成静态库之后,其他模块就可以通过将它的模块名添加到该变量中来使用该静态库

LOCAL_WHOLE_STATIC_LIBRARIES ,用来指明应该被包含在生成的共享库中的所有静态库内容,用在当几个静态库之间循环依赖时

LOCAL_SHARED_LIBRARIES ,在将第三方代码模块生成共享库之后,其他模块就可以通过它的模块名添加到该变量中来使用该共享库

LOCAL_EXPORT_CFLAGS ,该变量记录一组编译器标志,这些编译器标志会被添加到通过变量LOCAL_STATIC_LIBRARIES或LOCAL_SHARED_LIBRARIES使用本模块的其他模块的LOCAL_CFLAGS定义中

LOCAL_EXPORT_CPPFLAGS ,和LOCAL_EXPORT_CFLAGS一样

LOCAL_EXPORT_LDFLAGS ,和LOCAL_EXPORT_CFLAGS一样,用作链接器标志

TARGET_ARCH ,目标Cpu体系结构的名称,如arm

TARGET_PLATFORM ,目标Android平台的名称,如android-3

TARGET_ARCH_ABI ,目标Cpu体系结构和ABI的名称,如armeabi-v7a

TARGET_ABI ,目标平台和ABI的串联,如android-3-armeabi-v7a

自定义变量

NDK系统保留以下变量名:

  • LOCAL_开头的
  • PRIVATE_ or APP_开头的
  • 小写名字,如my-dir

需要注意的地方:

  • = 是最基本的赋值,make会将整个makefile展开后,再决定变量的值,也就是说,变量的值将会是整个makefile中最后被指定的值
  • := 是覆盖之前的值,取决于它在makefile中的位置,而不是整个makefile展开后的最终值
  • ?= 是如果没有被赋值过就赋予等号后面的值
  • += 是添加等号后面的值

NDK中函数宏

$(call import-module, 目录)

import-module函数宏需要先定位共享模块,然后再将它导入NDK项目中,默认情况下,该宏只搜索/sources目录,为了搜索其他目录,可以定义一个名为 NDK_MODULE_PATH 的环境变量,并将它设置为共享模块的根目录。

include $(call all-subdir-makefiles)

例子:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)

每个android子项目中都会存在一个或多个mk文件,如果需要编译整个工程,只需要在根目录放置一个Android.mk文件,加上如下内容

this-makefile

返回当前Android.mk构建文件的路径

parent-makefile

返回包含当前构建文件的父Android.mk构建文件的路径

grand-parent-makefile

用于祖父目录

Android.mk的使用,构建系统

  1. 构建共享库

    include $(BUILD_SHARED_LIBRARY)
    
  2. 构建多个共享库

    一个单独的Android.mk文档可以产生多个共享库模块

    LOCAL_PATH := $(call my-dir)
    ##模块1
    include $(CLEAR_VARS)
    ...
    include $(BUILD_SHARED_LIBRARY)
    ##模块2
    include $(CLEAR_VARS)
    ...
    include $(BUILD_SHARED_LIBRARY)
    
  3. 构建静态库

    在将第三方代码添加到自己NDK项目中时,不用直接将第三方源代码包括在NDK项目,而是将第三方代码编译成静态库然后并入共享库

    LOCAL_PATH := $(call my-dir)
    #第三方库
    ...
    include $(BUILD_STATIC_LIBRARY)
    #原生模块
    ...
    LOCAL_STATIC_LIBRARIES := moduleName
    include $(BUILD_SHARED_LIBRARY)
    
  4. 用共享库共享通用模块

    LOCAL_PATH := $(call my-dir)
    #第三方库
    ...
    include $(BUILD_SHARED_LIBRARY)
    #原生模块
    ...
    LOCAL_SHARED_LIBRARIES := moduleName
    include $(BUILD_SHARED_LIBRARY)
    
  5. 在多个NDK项目间共享模块

    首先将第三方源码移动到NDK项目以外的位置,作为共享模块,需要为它提供自己的Android.mk文件。为了在自己的NDK项目中使用它,将以下函数宏添加至构建文档的末尾。

    #原生模块
    include $(CLEAR_VARS)
    ...
    include $(BUILD_SHARED_LIBRARY)
    
    $(call import-module, 目录名(相对于NDK_MODULE_PATH变量))
    
  6. Prebuilt库

    想在不发布源码的情况下将你的模块发布给他人,想使用共享模块的预建版来加速构建过程,可以使用Prebuilt库
    尽管已经被编译好了,但预建仍需要一个Android.mk文件,如下:

    LOCAL_PATH := $(call my-dir)
    #第三方预建库
    include $(CLEAR_VARS)
    LOCAL_MODULE := avilib
    LOCAL_SRC_FILES := libavilib.so (实际Prebuilt库相对于LOCAL_PATH的位置)
    
    include $(PREBUILT_SHARED_LIBRARY)
    

    **注意:**Prebuilt库定义不包含任何关于该库所构建的实际机器体系结构的信息,我们需要确保Prebuilt库是为与NDK项目相同的机器体系而构建的。

  7. 构建独立的可执行文件

    独立可执行文件是不用打包成Apk文件就可以复制到Android设备上的常规Linux应用程序,而且它们可以直接执行,不用通过Java应用程序加载。生成独立可执行文件需要在Android.mk文件中导入BUILD_EXECUTABLE变量。

Application.mk文件

它的目的是描述应用程序需要哪些模块,它也定义所有模块的通用变量,以下是它所支持的变量:

APP_MODULES ,默认情况下,NDK构建系统构建Android.mk文件声明的所有模块,该变量可以覆盖上述行为并提供一个用空格分开的、需要被构建的所有模块

APP_OPTIM ,该变量可以被设置为release或debug以改变生成的二进制文件的优化级别,默认情况下使用release模式,并且此时生成的二进制文件被高度优化

APP_CLAGS ,该变量列出了一些编译器标志,在编译任何模块的C和C++源文件时这些标志都会被传给编译器

APP_CPPFLAGS ,同上,只针对C++源码

APP_BUILD_SCRIPT ,默认情况下,NDK系统构建在项目的jni子目录下查找.mk文件,该变量可以改变上述行为

APP_ABI ,默认NDK构建系统为armeabi,可以修改,如

APP_ABI := armeabi mips

APP_STL ,NDK构建系统使用最小STL运行库,也被称为system库,可以用该变量选择不同的STL实现

APP_STL := stlport_shared

APP_STL := stlport_static

NDK_TOOLCHAIN_VERSION ,编译器版本,xcode使用clang(支持c++11特性,如auto), android ndk默认使用gcc

NDK_TOOLCHAIN_VERSION := clang

NDK-BUild脚本

-C 参数可以用于指定命令行中NDK项目的位置

-B 强制重构建源代码

ndk-build clean

ndk-build -j 4 并行构建命令

ndk-build NDK_LOG=1 启用NDK构建系统内部状态日志功能

ndk-build V=1 只显示构建命令

其他注意的地方

  1. 平台兼容性

原生库只能运行在指定的最小Android平台版本

原生代码使用的CPU架构 兼容的Android平台
ARM, ARM-NEON Android1.5 (API 3)
x86 Android2.3 (API 9)
MIPS Android2.3 (API 9)

如果NDK项目使用了OpenGL ES API,则需要Android2.0以上(API 5以上),并且可以在标签下,添加最小的OpenGL ES 版本,

Makefile常用命令

  1. wildcard : 扩展通配符,用于查找一个目录下的所有符合条件的文件
  2. notdir : 去除路径,仅保留文件名
  3. patsubst :替换通配符,也可以是任意文本替换

完整的一个例子

首先是Application.mk文件:

APP_OPTIM := release
APP_PLATFORM := android-19
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DANDROID
APP_ABI := armeabi-v7a-hard
APP_MODULES := NAtiveLib
NDK_TOOLCHAIN_VERSION := clang

接着是Android.mk文件:

TARGET_PLATFORM := android-19
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := NativeLib
LOCAL_SRC_FILES += Wrappers.cpp
LOCAL_ARM_MODE := arm
COMMON_CFLAGS := -Werror -DANDROID -DDISABLE_IMPORTGL
ifeq($(TARGET_ARCH),x86)
    LOCAL_CFLAGS :=$(COMMON_CFLAGS)
else
    LOCAL_CFLAGS := -mfpu=vfp -mfloat-abi=hard -mhard-float -fno-short-enums
        -D_NDK_MATH_NO_SOFTFP=1 $(COMMON_CFLAGS)
endif
LOCAL_LDLIBS := -llog -lGLESv2 -Wl, -s
LOCAL_CPPFLAGS += -std=gnu++11
include $(BUILD_SHARED_LIBRARY)

你可能感兴趣的:(Android)