官方文档-ndk相关的都在这个网站上
https://developer.android.google.cn/ndk/guides/android_mk.html
问题
1 为什么会有Android.mk 和Application.mk 这两个分别是什么?
2 nkd怎样运行hello C语言程序?自己试了好久没有好使。
3 ndk-build 参数选项都有什么
ndk-build NDK_PROJECT_PATH=iu456_library/build/ NDK_APPLICATION_MK=Application.mk APP_DIR:=${APP_DIR}
NDK_PROJECT_PATH 指定了需要编译的代码的工程目录,这里给出的是当前目录,
APP_BUILD_SCRIPT给出的是Android makefile文件的路径
Application.mk详解
Application.mk简介
要将C/C++代码编译为so文件,光有Android.mk文件还不行,还需要一个Application.mk文件。本文将对Application.mk进行非常详细介绍。
1.作用
Application.mk是用来确定一些编译规则的,它规定的不是某一个文件某一行代码,而是所有文件相关
2.存放位置
Application.mk和Android.mk是放在同一个目录下的。一般是放在src/main/jni/下jni是新建的文件夹,用于存放C/C++相关的代码,jni文件夹和java文件夹是同级目录,如果生成的.so也是在/main下创建文件夹jniLibs,把.so放在jniLibs文件夹下。
Application.mk写法用法
Application.mk的写法:
key1 := value1
key2 := value2
key3 := value3
Application.mk文件中里面全都是标签key和值value来定义一些属性的,所有我们只需要看懂里面标签的意义就知道整个Application.mk的用法了。比如APP_ABI,是用来确定编译成什么样处理器平台下的so文件。
1.最简单的文件格式:
#注释:注解*****
APP_ABI := arm64-v8a # APP_ABI :=后面接的是需要生成的.so平台文件,正常手机使用arm64处理器的即可。
APP_PLATFORM := android-21 # APP_PLATFORM :=后面接的是使用SDK的最低等级
Application.mk的所有标签详解
标签书写的次序是无序的。
APP_PLATFORM(必选项)
作用:定义使用的ndk库函数版本号。
属性值可以是: android-,其中是ndk的版本。
一般和SDK的版本(minSdkVersion 21)相对应,NDK版本的各个版本在NDK目录(sdk\ndk-bundle\)下的platforms文件夹中
APP_ABI (必选项)
作用:编译成什么类型的cpu的so,
拥有三个属性值armeabi armeabi-v7a x86,可以只用一个,也可以可以全选,如果全选也可以使用all.
写法可以是:
中间要变成的多个so版本用空格间隔开即可
生成两种格式
APP_ABI := armeabi-v7a arm64-v8a
APP_ABI := all 全选
关于三种cpu处理器的介绍:
目前主流的Android设备是armeabi-v7a架构的,然后就是x86和armeabi了。
如果同时包含了 armeabi,armeabi-v7a和x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的so,这是较为完美的一种解决方案,但是同时也会导致包变大。
armeabi-v7a是可以兼容armeabi的,而v7a的CPU支持硬件浮点运算,目前绝大对数设备已经是armeabi-v7a了,所以为了性能上的更优,就不要为了兼容放到armeabi下了。
x86也是可以兼容armeabi平台运行的,另外需要指出的是,打出包的x86的so,总会比armeabi平台的体积更小,对于性能有洁癖的童鞋们,还是建议在打包so的时候支持x86。
#####关于使用哪种cup的问题
如果功能简单,并且希望自己的apk小一点,编一个x86版本的so即可。
如果想为了适应所有机型可以添加一下armeabi-v7a的版本。
一般来说正常手机使用x86版本的即可,
对于模拟器的话,就要看创建模拟器设置的cpu类型了。如果不确定模拟器的cpu类型,就生成多个so库即可。
APP_STL (非必选项)
作用:如何连接c++标准库 。
属性值:
stlport_static 静态链接
stlport_shared 动态链接
system 系统默认
如果生成的so库包含静态.a文件,这个属性要写成stlport_static,否则可以不用写。
APP_OPTIM (非必选项)
编译版本,如果是DEBUG版本就会带上调试信息。可以使用gdb-server进行动态断点低调试。
debug 调试版本 so中带调试信息,
release(默认) 发布版本 so不带调试信息
正常情况不用写这个属性就可以了,如果需要进行断点调试的情况可以设置为debug。
代码详解
APP_PLATFORM := android-24 # 定义使用的ndk库函数版本号。
APP_OPTIM := release # release(默认) 发布版本 so不带调试信息
APP_STL := c++_static
NDK_TOOLCHAIN_VERSION := clang
APP_BUILD_SCRIPT := Android.mk
# the buildsystem and validation is only done on these architectures
APP_ABI := armeabi-v7a arm64-v8a
# needed because VNKD needs liblog declared but in NDK it is implicit
APP_ALLOW_MISSING_DEPS := true
其他标签
它是Android NDK构建系统使用的一个可选的构建文件,也是一个GNU Makefile片段下面是Application.mk构建文件支持的变量:
APP_MODULES:默认情况下,Android NDK构建系统构建Android.mk文件声明的所有模块。
该变量可以覆盖上述行为并提供一个空格分开的,需要被构建的模块列表
APP_OPTIM:该变量可以设置为release和debug来改变生成的二进制文件的优化级别,
默认为release模式。
APP_CLAGS:列出编译器标识,在编译任何模块的C和C++源文件时这些标志都会被传给编译器
APP_CPPFLAGS:列出编译器标识,在编译任何模块的C++源文件时这些标志都会被传给编译器
APP_BUILD_SCRIPT:默认情况下,Android NDK构建系统在项目的JNI子目录下查找Android.mk构建文件。
APP_CFLAGS
编译选项
可以在Application.mk文件中修改此编译选项参数,此参数可以覆盖Android.mk文件中的相同定义,从而不必去Android.mk文件中修改.
需要注意地是,这个选项里的路径必须是以顶层NDK目录为相对路径,如存在以下两个文件:
sources/foo/Android.mk
sources/bar/Android.mk
如果在foo/Android.mk文件中想要添加bar目录,那么得这样便用:
APP_CFLAGS += -Isources/bar
如果这样使用:**
**
APP_CFLAGS += -I$(LOCAL_PATH)/../bar
将会变成’-I$NDK_ROOT/…/bar’,从而出现并不是你想要的结果.
在android-ndk-1.5_r1时,此选项中只在C代码中被支持,而C++不支持,不过现在已经被纠正了.
**
**
之前的是项目中遇到的一些知识点,下面的是我整理的比较全面的application.mk知识点。
在Application.mk文件内定义了一些变量:
(1)APP_PROJECT_PATH(非必须)
此变量值必须是你工程根目录的绝对路径.这用于指定JNI生成的.so文件安装路径或拷贝路径.
(2)APP_MODULES
此变量是可选的,如果没有在此文件中定义,则默认由Android.mk文件决定.
如果在Application.mk文件中定义此变量,那么它必须是一串由空格相隔的模块名列表,并且与Android.mk文件中的LOCAL_MODULE变量定义保持一致.需要注意地是,NDK会自动计算模块所需要的依赖文件。
注:此变量在NDK R4版本之前是在Application.mk中是必须的,所有模块必须显式地列出.
(3)APP_CXXFLAGS
APP_CPPFLAGS的别名,将来此变量将会被抛弃。
(4)APP_CPPFLAGS
C++代码的编译选项。在android-ndk-1.5_r1版本中,此变量只适用于C++,但是现在可以同时适用于C和C++。
(5)APP_BUILD_SCRIPT
在默认情况下,NDK会在jni目录下查找Android.mk文件并使用它,如果你想修改它,那么在此变量中你可以指定一个你自己的脚本来执行,路径还是以工程顶层目录为相对路径.
(6)APP_GNUSTL_FORCE_CPP_FEATURES
在先前的NDK版本中,当使用GNU libstdc++ runtime运行库(通过设置APP_STL变量为gnustl_static或gnustl_shared)都会强制支持异常和RTTI,在有些极少情况下可能会出现问题,同时会使生成的机器码包含不必须的内容。
这种问题在NDK r7b中得到解决,但是这也意味着如果你真的需要支持异常和RTTI 的话,则必须显式声明。要么通过APP_CPPFLAGS,要么通过LOCAL_CPPFLAGS,或LOCAL_CPP_FEATURES。本变量就是为了解决此问题的.
有两个选项供选择,也可同时都选择.
官方文档
https://developer.android.google.cn/ndk/guides/application_mk
Application.mk文件
简介:
-----------------------------
要将C\C++代码编译为SO文件,光有Android.mk文件还不行,还需要一个Application.mk文件。
本文档是描述你的Android应用程序中需要的本地模块的Application.mk的语法使用,要明白如下。
Application.mk目的:
是描述在你的应用程序中所需要的模块(即静态库或动态库)。
Application.mk文件通常被放置在 P R O J E C T / j n i / A p p l i c a t i o n . m k 下 , PROJECT/jni/Application.mk下, PROJECT/jni/Application.mk下,PROJECT指的是您的项目。
另一种方法是将其放在顶层的子目录下:
$NDK/apps目录下,例如:
$NDK/apps/<myapp>/Application.mk
<myapp>是一个简称,用于描述你的NDK编译系统的应用程序(这个名字不会生成共享库或者最终的包)
下面是Application.mk中定义的几个变量。
APP_PROJECT_PATH
这个变量是强制性的,并且会给出应用程序工程的根目录的一个绝对路径。这是用来复制或者安装一个没有任何版本限制的JNI库,从而给APK生成工具一个详细的路径。
APP_MODULES
这个变量是可选的,如果没有定义,NDK将由在Android.mk中声明的默认的模块编译,并且包含所有的子文件(makefile文件)
如果APP_MODULES定义了,它不许是一个空格分隔的模块列表,这个模块名字被定义在Android.mk文件中的LOCAL_MODULE中。注意NDK会自动计算模块的依赖
注意:NDK在R4开始改变了这个变量的行为,再次之前:
- 在您的Application.mk中,该变量是强制的
- 必须明确列出所有需要的模块
APP_OPTIM–
这个变量是可选的,用来定义“release”或"debug"。在编译您的应用程序模块的时候,可以用来改变优先级。
“release”模式是默认的,并且会生成高度优化的二进制代码。"debug"模式生成的是未优化的二进制代码,但可以检测出很多的BUG,可以用于调试。
注意:如果你的应用程序是可调试的(即,如果你的清单文件中设置了android:debuggable的属性是"true")。默认的是"debug"而不是"release"。这可以通过设置APP_OPTIM为"release"来将其覆盖。
注意:可以在"release"和"debug"模式下一起调试,但是"release"模式编译后将会提供更少的BUG信息。在我们清楚BUG的过程中,有一些变量被优化了,或者根本就无法被检测出来,代码的重新排序会让这些带阿弥变得更加难以阅读,并且让这些轨迹更加不可靠。
APP_CFLAGS
当编译模块中有任何C文件或者C++文件的时候,C编译器的信号就会被发出。这里可以在你的应用中需要这些模块时,进行编译的调整,这样就不许要直接更改Android.mk为文件本身了
重要警告:+++++++++++++++++++++++++++++++++++++++++++++++ + +
+
+ 在这些编制中,所有的路径都需要于最顶层的NDK目录相对应。
+ 例如,如果您有以下设置:
+
+sources/foo/Android.mk
+sources/bar/ Android.mk
+ 编译过程中,若要在foo/Android.mk中指定你要添加的路径到bar源代码中,
+ 你应该使用
+ APP_CFLAGS += -Isources/bar
+ 或者交替:
+ APP_CFLAGS += -I KaTeX parse error: Undefined control sequence: \+ at position 24: …ATH )/../bar + \̲+̲ 使用'-l../bar/'将…NDK_ROOT/…/bar"
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++
注意:在Android的NDK 1.5_r1,只适用于C源文件,而不适合C++。
这已得到纠正,以建立完整相匹配的Android系统。
APP_CXXFLAGS
APP_CPPFLAGS的别名,已经考虑在将在未来的版本中废除了
APP_CPPFLAGS
当编译的只有C++源文件的时候,可以通过这个C++编译器来设置
注意:在Android NDK-1.5_r1中,这个标志可以应用于C和C++源文件中。并且得到了纠正,以建立完整的与系统相匹配的Android编译系统。你先可也可以使用APP_CFLAGS来应用于C或者C++源文件中。
建议使用APP_CFLAGS
APP_BUILD_SCRIPT–
默认情况下,NDK编译系统会在$(APP_PROJECT_PATH)/jni目录下寻找名为Android.mk文件:
$(APP_PROJECT_PATH)/jni/Android.mk
如果你想覆盖此行为,你可以定义APP_BUILD_SCRIPT来指定一个备用的编译脚本。一个非绝对路径总是被解释为相对于NDK的顶层的目录。
APP_ABI–
默认情况下,NDK的编译系统回味"armeabi"ABI生成机器代码。喜爱哪个相当于一个基于CPU可以进行浮点运算的ARMv5TE。你可以使用APP_ABI来选择一个不同的ABI。
比如:为了在ARMv7的设备上支持硬件FPU指令。可以使用
APP_ABI := armeabi-v7a
或者为了支持IA-32指令集,可以使用
APP_ABI := x86
或者为了同时支持这三种,可以使用
APP_ABI := armeabi armeabi-v7a x86
APP_STL–
默认情况下,NDK的编译系统为最小的C++运行时库(/system/lib/libstdc++.so)提供C++头文件。
然而,NDK的C++的实现,可以让你使用或着链接在自己的应用程序中。
例如:
APP_STL := stlport_static --> static STLport library
APP_STL := stlport_shared --> shared STLport library
APP_STL := system --> default C++ runtime library
下面是一个Application.mk文件的示例:
APP_PROJECT_PATH :=
android.mk
一个Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一个或多个模块,你也可以在几个模块中使用同一个源代码文件。编译系统为你处理许多细节问题。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile 文件是许多编译器–包括 Windows NT 下的编译器–维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。
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 := HcSyncml
LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包 含任何空格。注意编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'HcSyncml'的共享库模块,将会生成'libHcSyncml.so'文件。
LOCAL_C_INCLUDES := $(LOCAL_PATH)/extra_inc$(LOCAL_PATH)/main_inc
LOCAL_C_INCLUDES 中加入所需要包含的头文件路径
LOCAL_SRC_FILES
LOCAL_SRC_FILES中加入源文件路径(需要编译的文件),多个文件用 ‘\’ 隔开
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib –llog
表示允许打印Log
在Android.mk里面打印一句话:
$(warning 'hehe fuck=================')