概述
Android.mk这个文件可以放在Android的某一个目录下,就可以使用mm或者其他一些命令来对它进行编译。
Android.mk的作用
对于 C/C++ 来说,可以编译二进制的可执行文件、静态库、动态库;
对于 Java 来说,可以编译生成Jar包、APK。
分析第一个Android.mk LOCAL_PATH := $(call my-dir) //环境变量(定义当前模块的相对路径) include $(CLEAR_VARS) //清除变量(清空当前环境变量,除了LOCAL_PATH) LOCAL_MODULE := test //生成目标文件(编译生成的目标名称) LOCAL_SRC_FILES := test.c //源文件(编译该模块需要的源文件) include $(BUILD_EXECUTABLE) //编译生成的目标文件格式
1. 在第一行中配置了我们的LOCAL_PATH,LOCAL_PATH在什么地方定义的呢?
在 /build/make/core/definitions.mk 文件里,来看一下my-dir函数。 # Figure out where we are. define my-dir $(strip \ #拿到一个环境变量LOCAL_MODULE_MAKEFILE,它所取的是MAKEFILE_LIST里面的最后一行。 #我们在做编译的时候,会把我们当前目录下的Android.mk加到MAKEFILE_LIST里面,而取lastword,就是取最后一个makefile。 $(eval LOCAL_MODULE_MAKEFILE := $$(lastword $$(MAKEFILE_LIST))) \ #判断编译环境中是否包含LOCAL_MODULE_MAKEFILE这个文件。 $(if $(filter $(BUILD_SYSTEM)/% $(OUT_DIR)/%,$(LOCAL_MODULE_MAKEFILE)), \ #如果有这个文件,就认为这个Android.mk是有问题的, $(error my-dir must be called before including any other makefile.) \ , \ #如果没有错的话,会把Android.mk所在的目录返回,所以,我们可以得到LOCAL_PATH; #LOCAL_PATH就是Android.mk所在的目录。 $(patsubst %/,%,$(dir $(LOCAL_MODULE_MAKEFILE))) \ ) \ ) endef
先来看看 /build/make/core/config.mk 这个文件。 # ############################################################### # Build system internal files # ############################################################### BUILD_COMBOS:= $(BUILD_SYSTEM)/combo #CLEAR_VERS在下面这句话被定义 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mk
那么上面代码中的 $(BUILD_SYSTEM) 是在哪被定义的哪,我们找到 /build/make/core/main.mk 。 # Absolute path of the present working direcotry. # This overrides the shell variable $PWD, which does not necessarily points to # the top of the source tree, for example when "make -C" is used in m/mm/mmm. PWD := $(shell pwd) TOP := . TOPDIR := BUILD_SYSTEM := $(TOPDIR)build/core
########################################################### ## Clear out values of all variables used by rule templates. ########################################################### # '',true LOCAL_32_BIT_ONLY:= LOCAL_AAPT_FLAGS:= LOCAL_AAPT_INCLUDE_ALL_RESOURCES:= LOCAL_ADDITIONAL_CERTIFICATES:= LOCAL_ADDITIONAL_DEPENDENCIES:= LOCAL_ADDITIONAL_HTML_DIR:= LOCAL_ADDITIONAL_JAVA_DIR:= LOCAL_AIDL_INCLUDES:= LOCAL_ALLOW_UNDEFINED_SYMBOLS:= LOCAL_APK_LIBRARIES:= LOCAL_ARM_MODE:= LOCAL_ASFLAGS:= LOCAL_ASSET_DIR:= LOCAL_BUILT_MODULE:= LOCAL_BUILT_MODULE_STEM:= LOCAL_CC:= LOCAL_CERTIFICATE:= LOCAL_CFLAGS:= LOCAL_CHECKED_MODULE:= LOCAL_C_INCLUDES:= LOCAL_CLANG:= LOCAL_CLANG_ASFLAGS:= LOCAL_CLANG_CFLAGS:= LOCAL_CLANG_CONLYFLAGS:= LOCAL_CLANG_CPPFLAGS:= LOCAL_CLANG_LDFLAGS:= LOCAL_CLASSPATH:= LOCAL_COMPATIBILITY_SUITE:= LOCAL_COMPATIBILITY_SUPPORT_FILES:= LOCAL_CONLYFLAGS:= LOCAL_COPY_HEADERS:= LOCAL_COPY_HEADERS_TO:=
3. 代码是否可以调换顺序:先CLEAR_VARS,再设置LOCAL_PATH? include $(CLEAR_VARS) LOCAL_PATH := $(call my-dir)
这是坚决不可以的。
因为在LOCAL_PATH的定义中的相对路径是取的最后一个Android.mk,这时候是可以取得项目所在的路径,如果首先就把CLEAR_VARS给添加进来的话,那么clear_vars.mk就会被添加到MAKEFILE_LIST中,这样的话,就把我们的相对路径给确认成了build/make/core/这个路径。
所以,必须先写LOCAL_PATH,再清空所有环境变量。
4. 编译生成的 test 是默认放在out目录下,如果我想修改它的路径,比如说想编译生成的结果放在当前的目录下,应该怎么办?
需要在后面追加一句 LOCAL_MODULE_PATH,像这样: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := test LOCAL_SRC_FILES := test.c LOCAL_MODULE_PATH := $(LOCAL_PATH) //设置编译生成目录 include $(BUILD_EXECUTABLE)
5. 如果我们的源码文件不止一个,那该怎么一起编译进去呢?
在 LOCAL_SRC_FILES 中可以使用连接符 " \ "来连接文件,这样就能把两个文件(test.c和test1.c)全都编译上。 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := test LOCAL_SRC_FILES := test.c \ test1.c LOCAL_MODULE_PATH := $(LOCAL_PATH) include $(BUILD_EXECUTABLE)