Android手机游戏开发设计实践活动之NDK与JNI开发设
摘要: 3.1 ndk-build使用方法cd $PROJECT_PATH $ ndk /ndk-build使用方法:在新项目的网站根目录下,实行ndk-build脚本制作指令。比如:进入hello-jni的新项目网站根目录实行ndk-build,ANDROID_NDK_ROOT是在Cygwin中...
cd $PROJECT_PATH $ ndk /ndk-build
使用方法:在新项目的网站根目录下,实行ndk-build脚本制作指令。
比如:
进入hello-jni的新项目网站根目录实行ndk-build,ANDROID_NDK_ROOT是在Cygwin中配备NDK自然环境自变量的名字。
$ ndk /ndk-build -C PROJECT_PATH
使用方法:在随意文件目录下实行ndk-build,用-C来特定要编译程序的新项目的文件目录。
比如:
具体上:实行ndk-build非常于实行了下列指令:
$GNUMAKE -f ndk /build/core/build-local.mk parameters
比如:
$ ndk-build clean 消除编译程序转化成的二进制文档。 $ ndk-build -C project 特定新项目相对路径 $ ndk-build NDK_DEBUG=0 NDK_DEBUG为0是编译程序为release版,为debug版。
大量的ndk-build的主要参数详细介绍,请参照上边贴出来的ndk-build的官方网手册。
4、Android.mkAndroid.mk是用于向编译程序系统软件特定新项目中C/C++源码文档编译程序、连接标准的一种叙述文档。它是GUN makefile文档的一小一部分。那麼,简易来讲,便是用于起特定编译程序引入的头文档文件目录、编译程序出的so的姓名、必须编译程序的源代码或库等功效。了解makefile英语的语法的,毫无疑问了解这类使用方法。Android.mk文档在$project-path/jni/Android.mk相对路径下。
Android.mk官方网表明文本文档详细地址为:
ndk/
最先,仍以hello-jni为例子,看一下都界定了什么內容。开启 ndk-path /samples/hello-jni/jni/Android.mk文档。
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)
表明:
LOCAL_PATH := $(call my-dir):
Android.mk务必最先界定LOCAL_PATH,它用于在开发设计的树文档夹中精准定位文档的。my-dir是由编译程序系统软件出示的宏,用于回到当今文件目录的相对路径。(留意:这一相对路径是包括了Android.mk的相对路径)
include $(CLEAR_VARS):
CLEAR_VARS自变量也是由编译程序系统软件出示的,include $(CLEAR_VARS)是引入一个独特的GUN makefile文档,这一makefile文档所做的便是消除界定了许多LOCAL_XXX(比如: LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES等)这类文件格式的自变量,但这儿不容易消除LOCAL_PATH自变量。那么做是很必须的,由于编译程序系统软件分析这种编译程序操纵文档全是在单一的GUN make左右文自然环境中,分析出去的LOCAL_XXX自变量全是全局性的。
LOCAL_MODULE := hello-jni:
LOCAL_MODULE务必是唯一的,且不可以包括空格符。编译程序系统软件会依据这一姓名转化成相对的共享资源库,并全自动加上作为前缀和后缀名。本例中,最后转化成的共享资源库的名字为libhello-jni.so。
留意:编译程序转化成的共享资源库全是lib开始的,假如,你申明的名字早已包括lib(libhello-jni),那麼,最后转化成的共享资源库名字也不加上lib作为前缀了,转化成的仍为libhello-jni.so。
LOCAL_SRC_FILES := hello-jni.c:
LOCAL_SRC_FILES用于指出要编进共享资源库(.so)的C/C++源代码的目录。
留意:这儿只必须特定要编译程序的.c或是.cpp等源代码就可以,不用特定.h头文档。
include $(BUILD_SHARED_LIBRARY):
BUILD_SHARED_LIBRARY自变量是由系统软件出示,include $(BUILD_SHARED_LIBRARY)会引入一个Gun makefile脚本制作,用于搜集你界定的LOCAL_XXX文件格式的自变量。同时,决策什么要编译程序,怎样编译程序等。
留意:显而易见BUILD_SHARED_LIBRARY是用于编译程序出共享资源库.so文档的,同样,还可以应用BUILD_STATIC_LIBRARY来编译程序出静态数据库.a文档。
之上就是撰写一个简易的Android.mk文档的全部原素。根据上边的叙述发觉,假如大家要撰写一个自身的Android.mk文档,沒有独特要求得话,能够立即将hello-jni工程项目中的Android.mk文档复制,随后,改动库的名字(LOCAL_MODULE)和要编译程序的源代码目录(LOCAL_SRC_FILES)自变量就可以。
4.2 Android.mk高級这儿来详尽掌握下Android.mk别的的一些自变量及英语的语法标准。
(1)NDK自变量与宏
在Android.mk中也有一些别的自变量,是做为NDK编译程序系统软件的保存自变量,你只有依靠它或是界定它。这种自变量的标准以下:
假如你必须在Android.mk中界定自身的自变量,强烈推荐用MY_做为作为前缀。
(2)NDK界定的自变量
CLEAR_VARS:
上边早已详细介绍已过,这儿也不在过多阐释。记牢一点,在界定LOCAL_XXX前,务必引入这一脚本制作。使用方法:
include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY:
该自变量偏向了一个脚本制作,这一脚本制作会搜集你一直在每一个控制模块界定的LOCAL_XXX自变量信息内容,而且这一自变量还明确了如何应用你的源代码去编译程序一个共享资源库。留意,应用这一自变量必须你最少早已界定了LOCAL_MODULE和LOCAL_SRC_FILES。该自变量会使编译程序系统软件转化成一个以.so末尾的库。使用方法:
include $(BUILD_SHARED_LIBRARY)
BUILD_STATIC_LIBRARY:
该自变量是BUILD_SHARED_LIBRARY的一个变体,是用于转化成一个静态数据库。搭建系统软件其实不会把静态数据库包括进你的工程项目里边,可是能够运用静态数据库转化成共享资源库。该自变量会使编译程序系统软件转化成一个以.a末尾的库。
include $(BUILD_STATIC_LIBRARY)
PREBUILT_SHARED_LIBRARY:
偏向一个脚本制作,这一脚本制作被用于特定一个预搭建的共享资源库。与BUILD_SHARED_LIBRARY和BUILD_STATIC_LIBRARY不一样,LOCAL_SRC_FILES的值不可以是一个源代码,它务必是一个独立的偏向预搭建的共享资源库的相对路径,比如:foo/libfoo.so。使用方法:
PREBUILT_STATIC_LIBRARY:
该自变量与PREBUILT_SHARED_LIBRARY同样,仅仅偏向的一个预搭建的静态数据库。
TARGET_ARCH:
这一自变量是总体目标CPU构架的姓名,如同Android Open Source Project里边特定了总体目标CPU构架。这一自变量用以随意的ARM适配的搭建,或是ARM,或是是单独于CPU构造的修定,或是ABI。
TARGET_PLATFORM:
编译程序到总体目标服务平台的api级别。比如,Android5.1相匹配的是Android api22。使用方法:
TARGET_PLATFORM := android-22
TARGET_ARCH_ABI:
当编译程序系统软件分析Android.mk文档的情况下,这一自变量储存CPU和构架的姓名。你可以以特定一个或是好几个下边列举的姓名,应用空格符隔开2个姓名
使用方法:
TARGET_ARCH_ABI := arm64-v8a
留意:android-ndk-1.6_r1以前这一这一自变量被界定为arm。
TARGET_ABI:
该自变量将API的级別和ABI联络在一起,如果你在真机上涨试系统软件的情况下非常有效。使用方法:
TARGET_ABI := android-22-arm64-v8a
LOCAL_MODULE_FILENAME:
它是一个可选择自变量。容许你再次特定一个自变量的名字来遮盖默认设置转化成的名字。比如:强制性转化成libnewfoo.so
LOCAL_MODULE := foo LOCAL_MODULE_FILENAME := libnewfoo
LOCAL_MODULE_FILENAME不用特定文档相对路径或拓展名
LOCAL_SRC_FILES:
该自变量用于特定要编译程序的源代码目录。这儿强烈推荐应用相对性相对路径。使用方法:
LOCAL_SRC_FILES := foo1.c \ ../Module2/foo2.c
留意:应用Unix设计风格的/,好几个文档应用\换行,留意\后边沒有空格符。
LOCAL_CPP_EXTENSION:
一样,LOCAL_CPP_EXTENSION也是一个可选择自变量。用于特定C++源代码的拓展名。默认设置是.cpp。从NDK r7版本号后,能够特定一系列产品的拓展名。使用方法:
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CPP_FEATURES:
一样,LOCAL_CPP_FEATURES也是一个可选择自变量。假如,你采用了C++的一些独特作用(比如:RTTI,出现异常适用等),而且恰当的编译程序和连接,可使用该自变量来申明。使用方法:
LOCAL_CPP_FEATURES := rtti exceptions
提议应用该自变量来替代LOCAL_CPPFLAGS中立即界定-frtti、-fexceptions这类使用方法
LOCAL_C_INCLUDES:
可选择自变量,能够根据该自变量来特定一个相对性于NDK网站根目录的相对路径目录,并在编译程序C/C++时加上到检索相对路径中。使用方法:
LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
留意:该申明要放到LOCAL_CFLAGS和LOCAL_CPPFLAGS的申明前边。
LOCAL_CFLAGS:
可选择自变量,在编译程序C/C++源码时,能给编译程序器传送一个编译程序标示结合。用于特定额外宏的界定和编译程序选择项是很有效的。
LOCAL_CPPFLAGS:
可选择自变量,在编译程序C++源码时(只编译程序C++),能给编译程序器传送一个编译程序标示结合。
LOCAL_STATIC_LIBRARIES:
该自变量界定了本控制模块编译程序连接全过程选用到的静态数据库目录。
LOCAL_SHARED_LIBRARIES:
该自变量界定了本控制模块编译程序连接全过程选用到的共享资源库目录。
LOCAL_WHOLE_STATIC_LIBRARIES:
该自变量跟LOCAL_STATIC_LIBRARIES相近,不一样的是在编译程序连接全过程时会加载静态数据库的全部源码总体目标文档。这在处理好多个库中间循环系统引入时,十分有效。能够根据GUN的--whole-archive标示来查询有关表明。
LOCAL_LDLIBS:
该自变量用于界定本控制模块编译程序时要到的额外的连接器选择项。用-l作为前缀特定。比如:要连接/system/lib/libz.so
LOCAL_LDLIBS := -lz
留意:假如,你编译程序一个静态数据库是界定了该自变量,编译程序系统软件会忽视它,而且ndk-build会复印一个警示。
LOCAL_LDFLAGS:
该自变量界定了在编译程序给编译程序系统软件传送一些别的的连接标示。使用方法:
LOCAL_LDFLAGS += -fuse-ld=bfd
留意:假如,你编译程序一个静态数据库是界定了该自变量,编译程序系统软件会忽视它,而且ndk-build会复印一个警示。
LOCAL_ALLOW_UNDEFINED_SYMBOLS:
默认设置状况下,在编译程序一个共享资源库的情况下,一切待定义的引入,可能抛出去 标记待定义(undefined symbol) 的不正确。该自变量能协助你捕获编码中的bug。假如,要禁止使用此项查验能够把该自变量设定为true。那么设定
留意:假如,你编译程序一个静态数据库是界定了该自变量,编译程序系统软件会忽视它,而且ndk-build会复印一个警示。
LOCAL_ARM_MODE:
默认设置状况下,编译程序系统软件会在ARM服务平台 thumb 方式下转化成16位的二进制文档。界定该自变量则强制性转化成32位 arm 方式下的目标文档。比如:
LOCAL_ARM_MODE := arm
你还可以再加.arm后缀名来告知编译程序系统软件,只为对某一源代码应用arm命令。比如:
LOCAL_SRC_FILES := foo.c bar.c.arm
LOCAL_ARM_NEON:
仅有当总体目标服务平台为armeabi-v7a命令集时,才界定它。它容许你的C/C++编码中应用ARM高級命令。还可以在选编文档中应用NEON命令。你可以令其用.neon后缀名来特定编译程序器适用NEON命令编译程序。比如:
LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon
留意:并不是全部的ARMv7构架的CPU都适用NEON拓展。
LOCAL_DISABLE_NO_EXECUTE:
Android NDK r4版本号刚开始适用这类 NX bit 的安全性作用。默认设置是开启的,你还可以设定该自变量的数值true来禁止使用它。但不强烈推荐那么做。该作用不容易改动ABI,只在ARMv6+CPU的机器设备核心上开启。
LOCAL_DISABLE_RELRO:
默认设置状况下,NDK编译程序编码是写保护重精准定位和GOT维护的。这一会标示运作时连接器标识特殊的运行内存区是写保护的,在移动部位以后。那样会促使一些安全性系统漏洞(如GOT遮盖)更难实行。默认设置是开启的,你还可以把该自变量的值设成true来禁止使用。但不强烈推荐那么做。
LOCAL_DISABLE_FORMAT_STRING_CHECKS:
默认设置状况下,编译程序系统软件编译程序编码时候查验文件格式化标识符串,假如printf款式的涵数应用了十分严苛的标识符串,那麼编译程序错误。默认设置是打开的,你还可以根据设定该自变量的数值true来禁止使用。但不强烈推荐那么做。
LOCAL_EXPORT_CFLAGS:
该自变量是用于纪录C/C++编译程序器标示结合,这种编译程序器标示会被加上到根据自变量LOCAL_STATIC_LIBRARIES或LOCAL_SHARED_LIBRARIES应用本控制模块的别的控制模块的LOCAL_CFLAGS自变量中。比如:
include $(CLEAR_VARS) LOCAL_MODULE := foo LOCAL_SRC_FILES := foo/foo.c LOCAL_EXPORT_CFLAGS := -DFOO=1 include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bar LOCAL_SRC_FILES := bar.c LOCAL_CFLAGS := -DBAR=2 LOCAL_STATIC_LIBRARIES := foo include $(BUILD_SHARED_LIBRARY)
编译程序bar控制模块时, -DFOO=1 -DBAR=2 标示将一起传送给编译程序器。
LOCAL_EXPORT_CPPFLAGS:
该自变量与LOCAL_EXPORT_CFLAGS相近,但只可用于C++。
LOCAL_EXPORT_C_INCLUDES:
该自变量与LOCAL_EXPORT_CFLAGS相近,可是该自变量用于包括相对路径的。比如,上例中bar.c必须包括foo控制模块的头文档。
LOCAL_EXPORT_LDFLAGS:
该自变量与LOCAL_EXPORT_CFLAGS相近,可是它作为连接器标示。
LOCAL_EXPORT_LDLIBS:
该自变量与LOCAL_EXPORT_CFLAGS一样,该自变量的值可能被加上到其他控制模块引入到本控制模块的其他控制模块的LOCAL_LDLIBS自变量中。比如:
include $(CLEAR_VARS) LOCAL_MODULE := foo LOCAL_SRC_FILES := foo/foo.c LOCAL_EXPORT_LDLIBS := -llog include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := bar LOCAL_SRC_FILES := bar.c LOCAL_STATIC_LIBRARIES := foo include $(BUILD_SHARED_LIBRARY)
编译程序bar的情况下,会在连接log的系统软件系统日志库。
LOCAL_SHORT_COMMANDS:
如果你的控制模块有许多源码文档或依靠许多静态数据库或是共享资源库时,设定为true。。
留意:这一作用在Windows上很有效,由于Windows上的指令行适用的较大标识符数为819一个,这针对繁杂的新项目来讲很小。默认设置不是强烈推荐开启这一作用,由于它会使编译程序越来越比较慢。
LOCAL_THIN_ARCHIVE:
编译程序静态数据库是,假如该自变量值设成true,会转化成一个较小的存档文档。其实不包括总体目标文档,只是用总体目标文档的相对路径取代。合理值是true,false和空。
留意:假如该控制模块并不是编译程序为静态数据块,或是预编译程序静态数据库,该值将被忽视。
LOCAL_FILTER_ASM:
该自变量的值将做为一个Shell指令,它会过虑从LOCAL_SRC_FILES转化成的文档或选编文档。界定该自变量可能产生下边的状况:
NDK出示的涵数宏
NDK出示了GNU Make的涵数宏。应用$(call function )的方法启用,他们会回到相对的文字信息内容。
my-dir:
该宏回到的是最终包括的makefile文档相对路径,通常为当今Android.mk的相对路径。my-dir针对Android.mk开始界定的LOCAL_PATH自变量很有效。比如:
LOCAL_PATH := $(call my-dir)
因为GNU Make的工作中方法,这一宏回到的是搭建系统软件在分析搭建脚本制作时包括的最终一个makefile的相对路径。因而,你没应当在include别的的文档以后再再次应用my-dir。比如:
LOCAL_PATH := $(call my-dir) # ... declare one module include $(LOCAL_PATH)/foo/`Android.mk` LOCAL_PATH := $(call my-dir) # ... declare another module
这儿的难题取决于第二个my-dir的启用将LOCAL_PATH的值设定以便$PATH/foo,由于$PATH/foo才算是近期包括的相对路径。你可以以根据在Android.mk文档中置放附加的包括来防止这一难题。比如:
LOCAL_PATH := $(call my-dir) # ... declare one module LOCAL_PATH := $(call my-dir) # ... declare another module # extra includes at the end of the Android.mk file include $(LOCAL_PATH)/foo/Android.mk
假如这类方法不能行,那麼能够将第一次启用my-dir的值存有此外一个自变量里边,比如:
MY_LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(MY_LOCAL_PATH) # ... declare one module include $(LOCAL_PATH)/foo/`Android.mk` LOCAL_PATH := $(MY_LOCAL_PATH) # ... declare another module
all-subdir-makefiles:
该宏回到的是当今my-dir相对路径下的全部根目录中的Android.mk文档的目录。你可以令其用此涵数向搭建系统软件出示深层次嵌套循环的源文件目录层级构造。默认设置状况下,NDK仅搜索包括Android.mk文档的文件目录中的文档。
this-makefile:
该宏回到的是当今makefile文档的相对路径(从搭建系统软件启用这一涵数中)。
parent-makefile:
该宏回到当今文件目录树中的父makefile的相对路径(包括当今makefile的makefile相对路径)。
grand-parent-makefile:
该宏回到包括树中的祖父类makefile的相对路径(包括当今makefile的makefile的相对路径)。
import-module:
该宏容许你根据控制模块的名字寻找并包括控制模块的Android.mk文档。比如:
$(call import-module, name )
在这里个实例中,搭建系统软件会依据NDK_MODULE_PATH这一自然环境自变量特指示的文件目录里边找寻名叫 name 的控制模块,随后全自动给你include相匹配的Android.mk文档。
5、Application.mk根据上边的详细介绍,大致掌握了Android.mk文档的使用方法及标准。但一般编译程序当地C/C++编码光有Android.mk还不足,还得必须Application.mk文档。Application.mk也是一种makefile文档,跟Android.mk有类似的地方。假如说,Android.mk用于叙述独立某一控制模块的编译程序标准的叙述文档,那麼Application.mk则是叙述全部运用程序的控制模块的叙述文档。Application.mk文档一般在$project-path/jni/Application.mk下($project-path是新项目网站根目录)。自然,还可以放到$NDK/apps/ myapp /Application.mk相对路径下。这二种方法,导致Application.mk也是有微小的差别。
(1)自变量
APP_PROJECT_PATH:
该自变量用于特定新项目网站根目录的肯定相对路径。
留意:倘若Application.mk文档的相对路径是$NDK/apps/ myapp /Application.mk,那麼该自变量为强制性界定的。假如,Application.mk文档在$project-path/jni/Application.mk相对路径下,则是可选择自变量。
APP_OPTIM:
该自变量为可选择自变量,数值release或debug。编译程序运用功能模块的时,能够用于更改提升级別。默认设置是release方式,而且会转化成高宽比提升的二进制文档。debug方式转化成的是未提升的二进制编码,但更非常容易调节。
APP_CFLAGS:
在编译程序一切控制模块的一切C/C++编码时,搭建系统软件会根据该自变量给编译程序器传送一个C编译程序标示结合。你可以令其用该自变量依据运用程序中给定的控制模块的必须来更改其搭建,而不用改动Android.mk文档自身了。
这种标示的全部相对路径务必相对性于NDK的顶尖文件目录。比如:假如给你下列设定:
sources/foo/Android.mk sources/bar/Android.mk
在编译程序期内,你必须在foo/Android.mk中特定你需要加上的foo的源相对路径,你应当应用:
APP_CFLAGS += -Isources/bar
或是:
APP_CFLAGS += -I$(LOCAL_PATH)/../bar
应用-I../bar将不可以一切正常工作中,由于它等额的于-I$NDK_ROOT/../bar。
留意:在android-ndk-1.5_r1版本号中,该自变量只可用于C,不可以功效于C++。以后的全部的版本号,该自变量可可用C/C++源代码上。
APP_CPPFLAGS:
该自变量包括一组C++编译程序器标示,搭建系统软件仅在搭建C++源码时传送给编译程序器。
APP_LDFLAGS:
在连接的情况下,搭建系统软件系统软件会想连接器传送一组连接标示。该自变量仅在搭建系统软件搭建共享资源库和exe文件的情况下才起效,当搭建静态数据库时,将被忽视。
APP_BUILD_SCRIPT:
默认设置状况下,NDK搭建系统软件会在$project-path/jni/文件目录下搜索Android.mk文档。假如你要改动此番为,你可以以界定APP_BUILD_SCRIPT自变量,并偏向预留的搭建脚本制作。编译程序系统软件一直将一个非肯定相对路径表述为NDK的顶尖文件目录。
APP_ABI:
默认设置状况下,编译程序系统软件会依据armeabi ABI转化成设备码。该设备码根据ARMv5TE而且适用浮点计算的CPU。你可以令其用APP_ABI主要参数来特定不一样的ABI。不一样的命令集的APP_ABI设定以下:
留意:all是android-ndk-r7版本号刚开始适用的。
你还可以特定好几个值,将他们放到同一行,正中间用空格符分隔。比如:
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM:
此自变量包括总体目标Android的名字。比如:android-3相匹配的是Android1.5的系统软件镜像系统。
APP_STL:
默认设置状况下,NDK搭建系统软件只求最少的C++运作库(/system/lib/libstdc++.so)出示C++头文档。另外,你要能够在自身的运用程序中应用或连接别的C++完成。可使用APP_STL来挑选在其中的一个。比如:
APP_STL := stlport_static APP_STL := stlport_shared APP_STL := system
APP_SHORT_COMMANDS:
该自变量非常于全部新项目的Android.mk中界定了LOCAL_SHORT_COMMANDS。
NDK_TOOLCHAIN_VERSION:
将此自变量界定为4.9版本号的GCC编译程序器。在android-ndk-r13默认设置是Clang编译程序器。
APP_PIE:
从Android 4.1(API级別16)刚开始,Android的动态性连接器适用部位不相干exe文件(PIE)。从Android 5.0(API级別21),exe文件必须PIE。要应用PIE搭建exe文件,需设定-fPIE标示。这一标示会促使根据任意编码的部位来搜索运行内存毁坏的bug更为艰难。默认设置状况下,假如您的新项目总体目标为Android-16或高些版本号,ndk-build会全自动将此值设定为true。您能够将其手动式设定为true或false。
留意:此标示仅可用于exe文件。它在搭建共享资源或静态数据库时沒有一切功效。
APP_THIN_ARCHIVE:
非常于在Android.mk文档中因此新项目中的全部静态数据库控制模块设定LOCAL_THIN_ARCHIVE的默认设置值。
之上內容将会不一定彻底恰当,大部分份内容是依据Android官方网文本文档,根据自身的了解转述的。并沒有每一个自变量在.mk文档中有实践活动过。因此,假如碰到你感觉不太好的地区,热烈欢迎与我沟通交流。
网页链接(选填)
认证(*)
文章正文(*)(留言板留言最多篇幅:1000)
记牢我,下一次回应时无需再次键入本人信息内容