Android.mk的用法和基础

来源:互联网 发布:苹果手机网络卡怎么办 编辑:程序博客网 时间:2024/05/20 06:05


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

 

先看一个简单的例子:一个简单的"hello world",比如下面的文件:
sources/helloworld/helloworld.c 
sources/helloworld/Android.mk
相应的Android.mk文件会象下面这样:
---------- cut here ------------------
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE
:= helloworld
LOCAL_SRC_FILES := helloworld.c
include $(BUILD_SHARED_LIBRARY)
---------- cut here ------------------
我们来解释一下这几行代码:
LOCAL_PATH := $(call my-dir) 
一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
include $( CLEAR_VARS)
CLEAR_VARS 由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
LOCAL_MODULE := helloworld
LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包 含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'foo'的共享库模块,将会生成'libfoo.so'文件。
LOCAL_SRC_FILES := helloworld.c 
LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这 里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。

 

在Android中增加本地程序或者库,这些程序和库与其所载路径没有任何关系,只和它们的Android.mk文件有关系。Android.mk和普通 的Makefile有所不同,它具有统一的写法,主要包含一些系统公共的宏。

 

在一个Android.mk中可以生成多个可执行程序、动态库和静态库。

 

1,编译应用程序的模板:
#Test Exe
LOCAL_PATH := $(call my-dir)
#include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main.c
LOCAL_MODULE:= test_exe
#LOCAL_C_INCLUDES :=
#LOCAL_STATIC_LIBRARIES :=
#LOCAL_SHARED_LIBRARIES :=
include $(BUILD_EXECUTABLE)
(菜鸟级别解 释::=是赋值的意思,$是引用某变量的值)LOCAL_SRC_FILES中加入源文件路径,LOCAL_C_INCLUDES 中加入所需要包含的头文件路径,LOCAL_STATIC_LIBRARIES加入所需要链接的静态库(*.a)的名 称,LOCAL_SHARED_LIBRARIES中加入所需要链接的动态库(*.so)的名称,LOCAL_MODULE表示模块最终的名 称,BUILD_EXECUTABLE表示以一个可执行程序的方式进行编译。

 

2,编译静态库的模板:
#Test Static Lib
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
helloworld.c
LOCAL_MODULE:= libtest_static
#LOCAL_C_INCLUDES :=
#LOCAL_STATIC_LIBRARIES :=
#LOCAL_SHARED_LIBRARIES :=
include $(BUILD_STATIC_LIBRARY) 

一般的和上面相似,BUILD_STATIC_LIBRARY表示编译一个静态库。

 

3,编译动态库的模板:
#Test Shared Lib
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
helloworld.c
LOCAL_MODULE:= libtest_shared
TARGET_PRELINK_MODULES := false
#LOCAL_C_INCLUDES :=
#LOCAL_STATIC_LIBRARIES :=
#LOCAL_SHARED_LIBRARIES :=
include $(BUILD_SHARED_LIBRARY)
一般的和上面相似,BUILD_SHARED_LIBRARY表示编译一个静态库。

 

以上三者的生成结果分别在如下,generic依具体target会变:
out/target/product/generic/obj/EXECUTABLE
out/target/product/generic/obj/STATIC_LIBRARY
out/target/product/generic/obj/SHARED_LIBRARY
每个模块的目标文件夹分别为:
可执行程序:XXX_intermediates
静态库:      XXX_static_intermediates
动态库:      XXX_shared_intermediates

 

另外,在Android.mk文件中,还可以指定最后的目标安装路径,用LOCAL_MODULE_PATH和 LOCAL_UNSTRIPPED_PATH来指定。不同的文件系统路径用以下的宏进行选择:
TARGET_ROOT_OUT:表示根文件系统。
TARGET_OUT: 表示system文件系统。
TARGET_OUT_DATA:表示data文件系统。
用法如:
CAL_MODULE_PATH:=$(TARGET_ROOT_OUT)



一个Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。每个模块属下列类型之一:
  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(packages/apps/Camera2/Android.mk)的文本:

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_STATIC_JAVA_LIBRARIES := android-support-v13LOCAL_STATIC_JAVA_LIBRARIES += xmp_toolkitLOCAL_SRC_FILES := $(call all-java-files-under, src)LOCAL_SRC_FILES += $(call all-java-files-under, src_pd)LOCAL_SRC_FILES += $(call all-java-files-under, src_pd_gcam)LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/resinclude $(LOCAL_PATH)/version.mkLOCAL_AAPT_FLAGS := /        --auto-add-overlay /        --version-name "$(version_name_package)" /        --version-code $(version_code_package) /LOCAL_PACKAGE_NAME := Camera2LOCAL_SDK_VERSION := currentLOCAL_PROGUARD_FLAG_FILES := proguard.flags# If this is an unbundled build (to install seprately) then include# the libraries in the APK, otherwise just put them in /system/lib and# leave them out of the APKifneq (,$(TARGET_BUILD_APPS))  LOCAL_JNI_SHARED_LIBRARIES := libjni_mosaic libjni_tinyplanetelse  LOCAL_REQUIRED_MODULES := libjni_mosaic libjni_tinyplanetendifinclude $(BUILD_PACKAGE)include $(call all-makefiles-under, $(LOCAL_PATH))

 我们来解释一下这几行代码:
1,LOCAL_PATH := $(call my-dir) ,一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。(菜鸟级别解释::=是赋值的意思,+=是追加的意思,$是引用某变量的值)
2,include $( CLEAR_VARS),CLEAR_VARS由编译系统提供((可以在 android 安装目录下的/build/core/config.mk 文件看到其定义,为 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk)),指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。
3,LOCAL_MODULE_TAGS :=user eng tests optional
user: 指该模块只在user版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译
4,LOCAL_STATIC_LIBRARIES: 表示该模块需要使用哪些静态库,以便在编译时进行链接。LOCAL_JAVA_LIBRARIES := platform core ext 依赖的共享jar。LOCAL_STATIC_JAVA_LIBRARIES := 依赖的静态jar包 (jar 包是使用 include $(BUILD_STATIC_JAVA_LIBRARY) 生成的。)

5,LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。

6,LOCAL_RESOURCE_DIR。默认product package和device package相应的res路径和$(LOCAL_PATH)/res.

include $(LOCAL_PATH)/version.mk。加入第三方库文件。

7,LOCAL_AAPT_FLAGS

AAPT(Android Asset Packaging Tool)   在SDK的tools/目录下. 该工具可以查看, 创建, 更新ZIP格式的文档附件(zip, jar, apk). 也可将资源文件编译成二进制文件,尽管你可能没有直接使用过aapt工具, 但是build scripts和IDE插件会使用这个工具打包apk文件构成一个Android 应用程序.

8, LOCAL_PACKAGE_NAME 表示了这个包的名字

9,Java的字节码一般是非常容易反编译的。为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理。ProGuard的主要作用就是混淆。当然它还能对字节码进行缩减体积、优化等,但那些对于我们来说都算是次要的功能。proguard在Android中的几种使用方法:

 (1).指定不需要混淆的native方法与变量的proguard.flags文件

           如:LOCAL_PROGUARD_FLAG_FILES := proguard.flags

  (2). 制定编译的工程,不要使用代码混淆的工具进行代码混淆

          如:LOCAL_PROGUARD_ENABLED := disabled

10, LOCAL_JNI_SHARED_LIBRARIES:

LOCAL_JNI_SHARED_LIBRARIES变量主要是用在JNI的编译中,如果你要在你的Java代码中引用JNI中的共享库*.so,此变量就是共享库的名字。
那么你要注意的一点是:在你的Project根目录下的Android.mk中要定义此变量用来引用你要使用的JNI中的共享库*.so。

定义了要包含的so库文件的名字,如果程序没有采用jni,不需要
        LOCAL_JNI_SHARED_LIBRARIES := libxxx 这样在编译的时候,NDK自动会把这个libxxx打包进apk; 放在youapk/lib/目录下

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

11, include $(BUILD_PACKAGE)则是编译出一个apk,include $(BUILD_STATIC_JAVA_LIBRARY)则是编译出jar包。

# Use the following include to make our test apk.

include $(call all-makefiles-under, $(LOCAL_PATH))





感谢: http://www.cnblogs.com/lilactutu/archive/2010/12/06/1897696.html
http://blog.csdn.net/edmond999/article/details/44680189
0 0