[转自百度文库]
NDK makefile说明
提示事项:
1.Ndkmakefile log用法
__ndk_info 打印普通信息
__ndk_warning 打印警告信息,不会终止makefile
__ndk_error 打印错误信息,会终止makefile
使用时直接调用$(call __ndk_info,PARAM1,PARAM2,PARAM3,PARAM4,PARAM5)
应该是只支持5个参数。
如果在makefile中定义了NDK_NO_WARNINGS,NDK_NO_ERRORS,将不会提示上面的警告和错误信息。
NDK_LOG:定义这个宏后,会打印出一些系统信息。具体用法一个是在mk文件中定义这个变量,或者是makeAPP=XXX NDK_LOG=YYY, YYY可取任何值。
2.在Andorid.mk中include$(CLEAR_VARS)调用以后会清楚所有的LOCAL_变量的值,所以在定义LOCAL_CFLAGS等变量之后不要调用include$(CLEAR_VARS)
被CLEAR_VARS置空的变量有:
LOCAL_MODULE \
LOCAL_SRC_FILES \
LOCAL_C_INCLUDES \
LOCAL_CFLAGS \
LOCAL_CXXFLAGS \
LOCAL_CPPFLAGS \
LOCAL_LDFLAGS \
LOCAL_LDLIBS \
LOCAL_ARFLAGS \
LOCAL_CPP_EXTENSION \
LOCAL_STATIC_LIBRARIES \
LOCAL_STATIC_WHOLE_LIBRARIES \
LOCAL_SHARED_LIBRARIES \
LOCAL_MAKEFILE \
LOCAL_NO_UNDEFINED_SYMBOLS \
LOCAL_ARM_MODE \
3.类似include $(BUILD_EXECUTABLE)这种命令会调用其他mk生成执行文件了。
4.可以在mk文件中加入伪目标,例如:
gpsinclude:
echo $(GPS_INCLUDE)/*
这样可以显示所有的文件,注意echo之前要用tab
5.编译时如果需要显示编译选项,可以使用
makeAPP=NF_Thread V=1
因为V=1会关闭hide变量置为空
6.LOCAL_C_INCLUDES这个选项会在definitions.mk被添加到编译选项中了
并且被替换为$$(LOCAL_C_INCLUDES:%=-I%),所以不需要手动在LOCAL_CFLAGS中自己添加。
本地目录页被添加到了编译选项中(-I$$(LOCAL_PATH))
7.ANDROID这个编译选项在build-binary.mk中已经有了,不需要自己加
LOCAL_CFLAGS:= -DANDROID $(LOCAL_CFLAGS)
我们在写程序时可以用ANDROID来判断是否为android程序。
main.mk 部分解析
definitions.mk这个mk文件中定义了很多其他mk要用到的函数。__ndk_info就定义在这里。
definitions.mk中定义了一系列的 makefile函数,其中也包括了c和c++的编译函数,ev-compile-cpp-source,ev-compile-c-source,这两个函数里编写了编译命令。
然后会去查找out/host/config.mk,如果没有这个文件,这个文件中定义了宿主机器的系统,体系结构等,后面会用到。就会提示无此文件,并调用build/host-setup.sh去创建这个文件
然后定义NDK_APP_OUT := $(NDK_OUT)/apps即out/app目录,定义NDK_HOST_OUT:= $(NDK_OUT)/host/$(HOST_TAG)即out\hostconfig.mk
并调用add-toolchain.mk,添加toolchain,在add-toolchain.mk中添加toolchain,在每个路径下都会去寻找build/toolchains/*/setup.mk文件,这个文件中包含了编译c,c++的方法,包括编译动态库,静态库,执行文件,以及编译选项,连接选项,还有系统目录等。
Application.mk中的APP_PROJECT_PATH 和APP_MODULES 被使用在definitions.mk
NDK_APP_VARS_REQUIRED中,最终被定义到NDK_APP_VARS中
在Application.mk中还可以定义APP_OPTIMAPP_CPPFLAGS APP_CFLAGS APP_CXXFLAGS APP_PLATFORM APP_BUILD_SCRIP这几个变量下面会讲解到。
然后main.mk开始搜索android平台,
搜索路径在build\platforms下,然后列出所有支持的平台,也就是文件夹名。如果在编译模块的时候调用加上NDK_LOG=1,会看到类似Foundsupported platforms:这个字样,然后列出可用平台。代码为:
NDK_PLATFORMS_ROOT:= $(BUILD_SYSTEM)/../platforms
NDK_ALL_PLATFORMS:= $(strip $(notdir $(wildcard $(NDK_PLATFORMS_ROOT)/android-*)))
$(callndk_log,Found supported platforms: $(NDK_ALL_PLATFORMS))
根据所有平台,会调用add-platform.mk文件,代码为:
$(foreach_platform,$(NDK_ALL_PLATFORMS),\
$(eval include$(BUILD_SYSTEM)/add-platform.mk)\
)
在add-platform.mk中会通过字符查找找到所有支持的体系结构(arm,x86等),然后为每个构架添加变量并显示每个构架的目录(NDK_LOG可以看到)。
然后开始读取应用的信息。搜索所有的Application.mk文件,并为每一个mk文件调用add-application.mk
Add-application.mk文件会找到模块的文件名,如果APP_MODILES中有lib作为前缀,会被去掉,然后判断你需要编译的版本是debug还是release,变量名为APP_OPTIM,如果没定义,默认为release(我们写的文件一般都没定义,所以都是release版本),如果想定义debug版本在Application.mk文件中加入:
APP_OPTIM:= debug
然后回去判断APP_PLATFORM是否定义,如果没有定义,就是用默认的定义,默认的定义在$(APP_PROJECT_PATH)/default.properties)路径中,如果找到这个文件,就按照这个文件定义平台,否则按照android-3定义,也就是说默认为android-3这个平台。
然后判断APP_BUILD_SCRIPT是否存在,这个变量可以定义我们自己的编译文件,也就是Android.mk文件,如果没有定义,就是用jni中默认的Android.mk文件,如果自己定义了,就是用自己的文件。
NDK_ALL_APPS变量会存储所有的APP
退出add-application.mk
然后会查找APP是否被定义,如果不定义,列出所有的APP,并abort。
接下来就开始编译程序了,首先为每一个APP调用setup-app.mk代码为:
$(foreach_app,$(NDK_APPS),\
$(eval include $(BUILD_SYSTEM)/setup-app.mk)\
)
setup-app.mk中会检查目标平台,为debug/release版本加入编译选项
然后调用setup-toolchain.mk文件
这个文件会准备好编译连接库等文件,比如crtbegin_static.o,crtbegin_dynamic.o,crtend_android.o,libc libstdc++libm等文件,然后再最后会调用我们自己写的Android.mk文件,根据我们设置好的编译头文件,库文件,源文件,然后再我们的mk文件里看是include什么类型的文件,以决定编译成执行文件,静态库还是动态库。
然后跳回到main.mk中。
根据选择的include文件,进入到相应的mk中。
BUILD_STATIC_LIBRARY :=$(BUILD_SYSTEM)/build-static-library.mk
BUILD_SHARED_LIBRARY :=$(BUILD_SYSTEM)/build-shared-library.mk
BUILD_EXECUTABLE :=$(BUILD_SYSTEM)/build-executable.mk
具体编译的东西也没有详细看,
比如BUILD_EXECUTABLE通过调用build-executable.mk,然后调用
$(LOCAL_BUILT_MODULE):$(LOCAL_OBJECTS)
@ mkdir -p $(dir $@)
@ echo "Executable : $(PRIVATE_NAME)"
$(hide) $(cmd-build-executable)
cmd-build-executable为真正的编译
这个变量在build\toolchains\arm-eabi-4.2.1中
definecmd-build-executable
$(TARGET_CC)\
-nostdlib -Bdynamic \
-Wl,-dynamic-linker,/system/bin/linker \
-Wl,--gc-sections \
-Wl,-z,nocopyreloc \
$(PRIVATE_SHARED_LIBRARIES) \
$(TARGET_CRTBEGIN_DYNAMIC_O) \
$(PRIVATE_OBJECTS) \
$(PRIVATE_STATIC_LIBRARIES) \
$(PRIVATE_LDFLAGS) \
$(PRIVATE_LDLIBS) \
$(TARGET_CRTEND_O) \
-o $@
endif