Android.mk 之 常用变量

一个Android.mk文件可以编译多个模块,每个模块属下列类型之一:

  1. APK程序-- 一般的Android程序,编译打包生成apk文件
  2. JAVA库 -- java类库,编译打包生成jar文件
  3. C\C++应用程序-- 可执行的C\C++应用程序
  4. C\C++静态库-- 编译生成C\C++静态库,并打包成.a文件
  5. C\C++共享库-- 编译生成共享库(动态链接库),并打包成.so文,有且只有共享库才能被安装/复制到您的应用软件(APK)包中。

可以在每一个Android.mk file 中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。 编译系统为你处理许多细节问题。例如,你不需要在你的 Android.mk 中列出头文件和依赖文件。编译系统将会为你自动处理这些问题。这也意味着,在升级 NDK 后,你应该得到新的toolchain/platform支持,而且不需要改变你的 Android.mk 文件。

 

‘:=’是赋值的意思;'+='是追加的意思;‘$’表示引用某变量的值

 

自定义变量:

 以下是在 Android.mk中依赖或定义的变量列表, 可以定义其他变量为自己使用,但是NDK编译系统保留下列变量名:

 -以 LOCAL_开头的名字(例如 LOCAL_MODULE)

 -以 PRIVATE_, NDK_ 或 APP_开头的名字(内部使用)

 -小写名字(内部使用,例如‘my-dir’)

  如果为了方便在 Android.mk 中定义自己的变量,建议使用 MY_前缀,一个小例子:

MY_SOURCES := foo.c

ifneq ($(MY_CONFIG_BAR),)

 MY_SOURCES += bar.c

endif

LOCAL_SRC_FILES += $(MY_SOURCES)

 

GNU Make系统变量

include $( CLEAR_VARS) CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的;

include $(BUILD_EXECUTABLE)编译应用程序;

include $(BUILD_STATIC_LIBRARY)编译静态库,静态库不会被复制到APK包中,但是能够用于编译共享库。这将会生成一个名为 lib$(LOCAL_MODULE).a的文件;

include $(BUILD_SHARED_LIBRARY)编译动态库,根据所有的在 LOCAL_XXX 变量把列出的源代码文件编译成一个共享库。注意,必须至少在包含这个文件之前定义 LOCAL_MODULE 和 LOCAL_SRC_FILES;

include $(BUILD_PACKAGE)编译应用程序APK;

include $(BUILD_PREBUILT)预编译应用程序;

TARGET_ARCH: 目标 CPU平台的名字;

TARGET_PLATFORM: Android.mk 解析的时候,目标 Android 平台的名字;

TARGET_ARCH_ABI:  暂时只支持两个 value,armeabi 和 armeabi-v7a;

TARGET_ABI: 目标平台和 ABI 的组合。

 

NDK提供的函数宏:

GNU Make函数宏,必须通过使用'$(call  )'来调用,返回值是文本化的信息。

my-dir:返回当前 Android.mk 所在的目录的路径,相对于 NDK 编译系统的顶层。这是有用的,在 Android.mk 文件的开头如此定义:

LOCAL_PATH := $(call my-dir)

all-subdir-makefiles: 返回一个位于当前'my-dir'路径的子目录中的所有Android.mk的列表。

例如,某一子项目的目录层次如下:

src/foo/Android.mk

src/foo/lib1/Android.mk

src/foo/lib2/Android.mk

 

如果 src/foo/Android.mk 包含一行:include $(call all-subdir-makefiles) 那么它就会自动包含 src/foo/lib1/Android.mk 和 src/foo/lib2/Android.mk。

这项功能用于向编译系统提供深层次嵌套的代码目录层次。

 

注意,在默认情况下,NDK 将会只搜索在 src/*/Android.mk 中的文件。

  1. all-makefiles-under: 获取某个目录下及子目录的所有Android.mk。$(1):需要提取Android.mk的目录
  2. this-makefile:  返回当前Makefile 的路径(即这个函数调用的地方)
  3. parent-makefile:  返回调用树中父 Makefile 路径。即包含当前Makefile的Makefile 路径。
  4. grand-parent-makefile:返回调用树中父Makefile的父Makefile的路径

 

注意:在写Android.mk文件时,call all-subdir-makefiles和call all-makefiles-under,$(LOCAL_PATH)是有区别的。前者表示“当前目录下没有需要编译的文件,请向子目录深入”,是告诉编译器继续向目录深处递归的一种规定写法。后者从字面上理解也应该是同一个意思。

但是,请考虑这样一种情况:如果当前目录下有文件需要编译,而且在当前目录下还有子目录,子目录中也有文件需要编译,那么当前目录下的Android.mk除了要包含编译当前目录下文件的语句,同样也要包含告诉编译器在编译完当前目录下的文件后,继续向子目录深入的语句。这里就有一个问题,后面这个语句该如何写呢?是call all-subdir-makefiles,还是call all-makefiles-under,$(LOCAL_PATH)呢?写前者是不行的,编译器会在编译完当前目录下的文件后不再进入子目录编译,而写成后者则可以达到我们的期望。

 

常用模块描述变量:

每个模块都是以include $(CLEAR_VARS)开始,并且以include $(BUILD_XXX)结束(应用程序,静态库,动态库等)。

每个Android.mk文件以定义LOCAL_PATH为开始,它用于在开发tree中查找源文件LOCAL_PATH := $(call my-dir) my-dir宏是系统用来返回包含当前Android.mk的目录路径;

如果有多个module需要编译,可以放置多个目录,在每个目录编写一个Android.mk,然后在根目录的Android.mk中添加一行include $(call all-subdir-makefiles);

LOCAL_PATH:=当前文件的路径

LOCAL_MODULE:=这个模块的名字,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'xxx'的共享库模块,将会生成'libxxx.so'文件。

LOCAL_MODULE_CLASS:=决定编译时的中间文件存放的位置;

LOCAL_MODULE_SUFFIX:=预编译程序模块的后缀;

LOCAL_MODULE_TAGS:= user/eng/tests/optional默认为optional:

  1. user: 指该模块只在user版本下才编译
  2. eng: 指该模块只在eng版本下才编译
  3. tests: 指该模块只在tests版本下才编译
  4. optional:指该模块在所有版本下都编译

如果两次make之间选了不同的编译模式,则需要运行一下make installclean,确保本次make不会用到上次install的文件,也可以运行make clean,不过耗时较长。

LOCAL_SRC_FILES:=要编译的源代码文件列表,多个文件见用空格或Tab间隔,换行用\,追加用LOCAL_SRC_FILES+=.变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。可以LOCAL_SRC_FILES := $(call all-subdir-java-files)这种形式来包含LOCAL_PATH目录下的所有java文件;

LOCAL_PRELINK_MODULE:= 是否需要预连接处理(默认需要,用来做动态库优化);

LOCAL_REQUIRED_MODULES:= 指定模块运行所依赖的模块(模块安装时将会同步安装它所依赖的模块); 

LOCAL_CERTIFICATE:=签名认证类型,默认为testkey。如果需要系统签名就等于platform,如果不需要就等于PRESIGNED;

LOCAL_C_INCLUDES:  可选变量,表示头文件的搜索路径。默认的头文件的搜索路径是LOCAL_PATH目录;

LOCAL_STATIC_LIBRARIES:= 该模块需要使用的静态链接库(*.a)的名字;

LOCAL_SHARED_LIBRARIES:= 模块在运行时需要用到的动态链接库(*.so)的名称;

LOCAL_COPY_HEADERS:= 安装应用程序时需要复制的头文件,必须同时定义LOCAL_COPY_HEADERS_TO;

LOCAL_COPY_HEADERS_TO:= 安装应用程序时复制头文件的目的路径;

LOCAL_OVERRIDES_PACKAGES:=使其他的模块不加入编译:

如:DeskClock模块的源码中的android.mk有

LOCAL_OVERRIDES_PACKAGES := AlarmClock

使AlarmClock不会加入到编译系统中,不会生成 AlarmClock.apk。(如果两个模块互相override对方,结果会怎样?应该是先编译到的模块屏蔽另一个模块);

LOCAL_BUILT_MODULE :=表示编译链接后的目标文件(文件路径+文件名);

LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM);

LOCAL_BUILT_MODULE_STEM:= 表示编译链接后的目标文件的文件名,带后缀;

LOCAL_PACKAGE_NAME :=应用程序APK的名字;

LOCAL_MODULE_PATH和LOCAL_UNSTRIPPED_PATH来指定最后的目标安装路径。不同的文件系统路径用以下的宏进行选择:

  1. TARGET_ROOT_OUT:表示根文件系统out/target/product/xxxxx/root。

  2. TARGET_OUT:表示system文件系统out/target/product/xxxx/system。

  3. TARGET_OUT_DATA:表示data文件系统out/target/product/xxxx/data。

  4. TARGET_OUT_SHARED_LIBRARIES:表示out/target/product/xxxx/system/lib

  5. TARGET_OUT_APPS:表示out/target/product/xxxx/system/app

  6. ANDROID_PRODUCT_OUT:out/target/product/xxxx/

  7. TARGET_OUT_JAVA_LIBRARIES:out/target/product/xxxx/system/framework

 

用法如:

LOCAL_MODULE_PATH:=$(TARGET_ROOT_OUT)

  1. LOCAL_JNI_SHARED_LIBRARIES:定义了要包含的so库文件的名字,如果程序没有采用jni,不需要
    LOCAL_JNI_SHARED_LIBRARIES := libxxx
     这样在编译的时候,NDK自动会把这个libxxx打包进apk; 放在apk/lib/目录下
  2. LOCAL_CFLAGS:=  可选的编译器选项,在编译 C 代码文件的时候使用。这可能是有用的,指定一个附加的包含路径(相对于NDK的顶层目录),宏定义,或者编译选项。注意:不要在 Android.mk 中改变 optimization/debugging 级别,只要在 Application.mk 中指定合适的信息,就会自动地为你处理这个问题,在调试期间,会让NDK自动生成有用的数据文件。LOCAL_CFLAGS += -Dxxx这个就是你在源码定义的宏,需要定义的话就在这个参数上加上-Dxxx,前面加"-D",后面就是宏的名称了。
  3. LOCAL_LDLIBS:=  编译模块时要使用的附加的链接器选项。这对于使用‘-l’前缀传递指定库的名字是有用的。

例如,LOCAL_LDLIBS := -lz表示告诉链接器生成的模块要在加载时刻链接到/system/lib/libz.so(z是mk中定义的module name)

  1. LOCAL_INSTALLED_MODULE:= 表示模块的安装路径+文件名,存放的安装目录
  2. LOCAL_PRIVILEGED_MODULE := true,以声明app需要放在/system/priv-app下。

 

示例:

#编译静态库

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE = libhellos

LOCAL_CFLAGS = $(L_CFLAGS)

LOCAL_SRC_FILES = hellos.c

LOCAL_C_INCLUDES = $(INCLUDES)

LOCAL_SHARED_LIBRARIES := libcutils

LOCAL_COPY_HEADERS_TO := libhellos

LOCAL_COPY_HEADERS := hellos.h

include $(BUILD_STATIC_LIBRARY)

#编译动态库
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE = libhellod

LOCAL_CFLAGS = $(L_CFLAGS)

LOCAL_SRC_FILES = hellod.c

LOCAL_C_INCLUDES = $(INCLUDES)

LOCAL_SHARED_LIBRARIES := libcutils

LOCAL_COPY_HEADERS_TO := libhellod

LOCAL_COPY_HEADERS := hellod.h

include $(BUILD_SHARED_LIBRARY)

#使用静态库

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hellos

LOCAL_STATIC_LIBRARIES := libhellos

LOCAL_LDLIBS += -ldl

LOCAL_CFLAGS := $(L_CFLAGS)

LOCAL_SRC_FILES := mains.c

LOCAL_C_INCLUDES := $(INCLUDES)

include $(BUILD_EXECUTABLE)

#使用动态库
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hellod

LOCAL_MODULE_TAGS := debug

LOCAL_SHARED_LIBRARIES := libc libcutils libhellod

LOCAL_LDLIBS += -ldl

LOCAL_CFLAGS := $(L_CFLAGS)

LOCAL_SRC_FILES := maind.c

LOCAL_C_INCLUDES := $(INCLUDES)

include $(BUILD_EXECUTABLE)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值