说明
这只是笔记。。。。。。。。
从0开始搭建测试环境
下载android ndk ,然后配置ndk环境变量,使ndk-build
命令能在任意目录执行.
目录的规定
在任意目录创建一个Android.mk和Application.mk
然后切换命令行在此目录输入ndk-build
出现错误
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
D:\env\android_sdk\ndk-bundle\build\\..\build\core\build-local.mk:151: *** Android NDK: Aborting
百思不得其解,网上的文章没有几篇靠谱的,尝试把这个目录改名为jni,切换到此目录,竟然错误消失了,出现另外一个目录
解决警告
虽然这个错误没有出现了,但是又出现了2个警告,1是提示定义最小版本,二是定说没有模块.
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
D:/env/android_sdk/ndk-bundle/build//../build/core/build-all.mk:89: Android NDK: WARNING: There are no modules to build in this project!
-
定义版本号
在Application.mk定义如下内容:
APP_PLATFORM:=android-14
E:\cross-c\Androidmk\jni>ndk-build -B
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
D:/env/android_sdk/ndk-bundle/build//../build/core/build-all.mk:89: Android NDK: WARNING: There are no modules to build in this project!
make: Nothing to be done for `all'.
这种情况,关闭终端重启.
ndk-build命令帮助
ndk-build V=1
显示详细信息
ndk-build -B
强制编译
ndk-build NDK_APPLICATION_MK=My.mk
自定义Application.mk
ndk-build NDK_DEBUG
为1可以实现优化不优化的问题,有符号就能定位堆栈。
ndk-build NDK_HOST_32BIT=1
不根据操作系统的64位使用这个构建
<ndk>/toolchain/<name>/prebuilt/
下面的语法实际上是make命令的语法
E:\cross-c\Androidmk\jni>ndk-build --help
用例: make [选项] [目标] ...
Options:
-b, -m Ignored for compatibility.忽略兼容性
-B, --always-make Unconditionally make all targets.无条件完成所有target编译,感觉没啥变化
-C DIRECTORY, --directory=DIRECTORY
Change to DIRECTORY before doing anything. 做任意事情之前改变目录
-d Print lots of debugging information.
--debug[=FLAGS] debug模式,打印调试信息 Print various types of debugging information.
-e, --environment-overrides 覆盖makefiles的环境变量
Environment variables override makefiles.
-f FILE, --file=FILE, --makefile=FILE 自定义makefile文件
Read FILE as a makefile.
-h, --help 打印帮助信息and退出
-i, --ignore-errors Ignore errors from commands.忽略命令行错误
-I DIRECTORY, --include-dir=DIRECTORY
Search DIRECTORY for included makefiles. 定义包含的目录
-j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg. 次允许N个作业;没有参数则无限工作
-k, --keep-going Keep going when some targets can't be made.当一些目标无法达成时,继续前进。
-l [N], --load-average[=N], --max-load[=N] 指定平均加载任务
Don't start multiple jobs unless load is below N.除非负载小于N,否则不要启动多个作业。
-L, --check-symlink-times Use the latest mtime between symlinks and target. 用符号链接和目标之间的最新时间。
-n, --just-print, --dry-run, --recon
Don't actually run any commands; just print them.不运行实际的命令只是打印。
-o FILE, --old-file=FILE, --assume-old=FILE
Consider FILE to be very old and don't remake it. 认为文件很旧,不要重做。
-p, --print-data-base Print make's internal database.打印内部数据库
-q, --question Run no commands; exit status says if up to date. 退出状态表示是否是最新
-r, --no-builtin-rules Disable the built-in implicit rules.禁用内置的隐式规则。
-R, --no-builtin-variables 禁用内置变量 Disable the built-in variable settings.
-s, --silent, --quiet 静默模式,不输出信息 Don't echo commands.
-S, --no-keep-going, --stop
Turns off -k.
-t, --touch Touch targets instead of remaking them.
-v, --version 打印make版本号 Print the version number of make and exit.
-w, --print-directory 打印当前目录 Print the current directory.
--no-print-directory 不打印当前目录 Turn off -w, even if it was turned on implicitly. 隐式打开
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
Consider FILE to be infinitely new. 认为文件是无限新的
--warn-undefined-variables Warn when an undefined variable is referenced. 引用未定义变量时发出警告。
This program built for i686-w64-mingw32
Report bugs to <bug-make@gnu.org>
E:\cross-c\Androidmk\jni>
mk语法与AndroidMk的变量与宏
android 一般使用ndk-build
测试的,而不是单纯的玩make,
定义变量
变量名 := 变量值
判断变量是否存在
变量拼接
MY_VAR+=append........
打印字符串
这里在控制台打印HelloWorld
$(warning HelloWorld)
打印变量
MY_VAR:=I am var
$(warning $(MY_VAR))
打印拼接的变量
$(warning 33333$(MY_VAR))
- 控制台输出的效果
E:\cross-c\Androidmk\jni>ndk-build
E:/cross-c/Androidmk/jni/Application.mk:3: WellcomeUseAndroidMk
[armeabi-v7a] Compile++ thumb: png <= hello.cpp
[armeabi-v7a] SharedLibrary : libpng.so
[armeabi-v7a] Install : libpng.so => libs/armeabi-v7a/libpng.so
打印当前目录
$(warning currentPath:$(my-dir))
my-dir
变量是android的ndk-build环境才有的,纯make是没有的
打印CLEAR_VARS
$(CLEAR_VARS)
需要在Android.mk里面编写才能测试
$(warning currentPath:$(CLEAR_VARS))
$(warning ------------------)
输出结果
D:/env/android_sdk/ndk-bundle/build//../build/core/clear-vars.mk
语法错误的效果
:\cross-c\Androidmk\jni>ndk-build
:/cross-c/Androidmk/jni/Application.mk:3: *** missing separator. Stop.
注释
#
开头就是注释了。
逻辑分支
DEBUG:=1
NAME:=qssq
SEX:=man
EMPTY:=#定义空
SPACE:=$(EMPTY) $(EMPTY) #定义空格
ifeq ($(DEBUG),1)#关键字后面需要加空格,否则语法错误
$(warning 调试模式)
else
$(warning 非调试模式)
endif
#去掉收尾空格进行判断是否为空
ifeq ($(strip $(SPACE)),)
$(warning SPACE变量去掉首尾空格为空)
endif
# 如果不是空而是空格也是不匹配的。
ifneq ($(SPACE),)
$(warning 不去掉首尾,不是空)
endif
#----------------------------------------------
ifeq ($(DEBUG),qssq)
$(warning 输出了作者)
else
$(warning 不知道你输入了什么名字,名字是$(NAME))
endif
ifeq ($(SEX),man)
$(warning 是个男人)
endif
#是否SEX等于woman字符串
ifneq ($(SEX),woman)
$(warning 不是女人)
endif
#定义变量 (看上去是一个函数
define tempvar
$(warning 执行了temp定义)
endef
#判断是否定义了tempvar
ifdef tempvar
$(warning 即将执行tempvar)
$(call tempvar)
endif
#判断是否定义了tempvar3
ifdef tempvar3
$(warning 即将执行tempvar3)
$(call tempvar3)
endif
ifndef tempvar2
$(warning 没有定义tempvar2)
endif
定义多行
如果下一行要继续上一行,则上一行应该以\
结尾
Application.mk内嵌的变量
设置编译的架构
定义需要编译的架构 多个用空格隔开
APP_ABI :=arm64-v8a
或
APP_ABI:=armeabi-v7a x86 x86_64 arm64-v8a x86_64
或
APP_ABI:=all
和不填写的效果一样。
定义目标平台
APP_PLATFORM
接受的变量如 android-14
测试错误的结果
赋值为android-1433 提示这个1433大于最高的版本28,请选择一个支持的api级别,或者设置为latest
,latest
的意思就是最新的。
:/cross-c/Androidmk/jni/Application.mk:6: 33333I am var
ndroid NDK: android-1433 is above the maximum supported version android-28. Choose a supported API level or set APP_PLATFORM to "latest".
:/env/android_sdk/ndk-bundle/build//../build/core/setup-app-platform.mk:127: *** Android NDK: Aborting. . Stop.
设置最高版本APP_PLATFORM:=latest
Android NDK: Using latest available APP_PLATFORM: android-28.
设置最低版本
最低版本就是不指定APP_PLATFORM
变量。
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-14.
设置最小支持库
笔者在编译后找不到某些头文件,发现我们的c++大神把我的配置
gnustl_static
改为了stlport_static
如今记忆犹新哈。
APP_STL
libstdc++(默认) 默认最小系统 C++ 运行时库。 不适用
gabi++_static GAbi++ 运行时(静态)。 C++ 异常和 RTTI
gabi++_shared GAbi++ 运行时(共享)。 C++ 异常和 RTTI
stlport_static STLport 运行时(静态)。 C++ 异常和 RTTI;标准库
stlport_shared STLport 运行时(共享)。 C++ 异常和 RTTI;标准库
gnustl_static GNU STL(静态)。 C++ 异常和 RTTI;标准库
gnustl_shared GNU STL(共享)。 C++ 异常和 RTTI;标准库
c++_static LLVM libc++ 运行时(静态)。 C++ 异常和 RTTI;标准库
c++_shared LLVM libc++ 运行时(共享)。 C++ 异常和 RTTI;标准库
AndroidMk的执行顺序
先执行Application.mk
然后执行Android.mk
Application.mk官方说明
这里的配置相对于Android.mk比较少
本文档介绍 Application.mk 构建文件,此文件用于描述应用需要的原生模块。 模块可以是静态库、共享库或可执行文件。
建议在阅读本页之前先阅读概念和 Android.mk 页面。 这样有助于您最深入地了解本页的内容。
概览
Application.mk 文件实际上是定义要编译的多个变量的微小 GNU Makefile 片段。 它通常位于 PROJECT 指向应用的项目目录。 另一种方式是将其放在顶级 NDK/apps/<myapp>/Application.mk
这里的 <myapp> 是用于向 NDK 构建系统描述应用的短名称。它不会实际进入生成的共享库或最终软件包。
变量
APP_PROJECT_PATH
此变量用于存储应用项目根目录的绝对路径。构建系统使用此信息将生成的 JNI 共享库的简缩版放入 APK 生成工具已知的特定位置。
如果将 Application.mk 文件放在 PROJECT/jni/ 下,则此变量可选。
APP_OPTIM
将此可选变量定义为 release 或 debug。在构建应用的模块时可使用它来更改优化级别。
发行模式是默认模式,可生成高度优化的二进制文件。调试模式会生成未优化的二进制文件,更容易调试。
请注意,您可以调试发行或调试二进制文件。但发行二进制文件在调试时提供的信息较少。 例如,构建系统会选择某些合适的变量,您无需检查它们。 此外,代码重新排序可能增大单步调试代码的难度;堆叠追踪可能不可靠。
在应用清单的 <application> 标记中声明 android:debuggable 将导致此变量默认使用 debug而非 release。 将 APP_OPTIM 设置为 release 可替换此默认值。
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 += -INDK_ROOT/../bar 后不会运行。
注:此变量仅适用于 android-ndk-1.5_r1 中的 C 源文件,而不适用于 C++ 源文件。 在该版本后的所有版本中,APP_CFLAGS 匹配整个 Android 构建系统。
APP_CPPFLAGS
此变量包含构建系统在仅构建 C++ 源文件时传递到编译器的一组 C++ 编译器标志。
注:在 android-ndk-1.5_r1 中,此变量适用于 C 和 C++ 源文件。 在 NDK 的所有后续版本中,APP_CPPFLAGS 现在匹配整个 Android 构建系统。 对于适用于 C 和 C++ 源文件的标志,请使用 APP_CFLAGS。
APP_LDFLAGS
构建系统在链接应用时传递的一组链接器标志。此变量仅在构建系统构建共享库和可执行文件时才相关。 当构建系统构建静态库时,会忽略这些标志。
APP_BUILD_SCRIPT
默认情况下,NDK 构建系统在 jni/ 下查找名称为 Android.mk 的文件。
如果要改写此行为,可以定义 APP_BUILD_SCRIPT 指向替代构建脚本。 构建系统始终将非绝对路径解释为 NDK 顶级目录的相对路径。
APP_ABI
默认情况下,NDK 构建系统为 armeabi ABI 生成机器代码。 此机器代码对应于基于 ARMv5TE、采用软件浮点运算的 CPU。 您可以使用 APP_ABI 选择不同的 ABI。 表 1 所示为不同指令集的 APP_ABI 设置。
表 1. APP_ABI 不同指令集的设置。
指令集 值
基于 ARMv7 的设备上的硬件 FPU 指令 APP_ABI := armeabi-v7a
ARMv8 AArch64 APP_ABI := arm64-v8a
IA-32 APP_ABI := x86
Intel64 APP_ABI := x86_64
MIPS32 APP_ABI := mips
MIPS64 (r6) APP_ABI := mips64
所有支持的指令集 APP_ABI := all
注:all 从 NDKr7 开始可用。
您也可以指定多个值,将它们放在同一行上,中间用空格分隔。例如:
APP_ABI := armeabi armeabi-v7a x86 mips
如需了解所有支持的 ABI 列表及其用法和限制的详细信息,请参阅 ABI 管理。
APP_PLATFORM
此变量包含目标 Android 平台的名称。例如,android-3 指定 Android 1.5 系统映像。 如需平台名称和对应 Android 系统映像的完整列表,请参阅 Android NDK 原生 API。
APP_STL
默认情况下,NDK 构建系统为 Android 系统提供的最小 C++ 运行时库 (system/lib/libstdc++.so) 提供 C++ 标头。 此外,它随附您可以在自己的应用中使用或链接的替代 C++ 实现。请使用 APP_STL 选择其中一个。 如需了解有关支持的运行时及其功能的信息,请参阅 NDK 运行时和功能。
APP_SHORT_COMMANDS
相当于 Application.mk 中的 LOCAL_SHORT_COMMANDS,适用于整个项目。如需了解详细信息,请参阅 Android.mk 上此变量的相关文档。
NDK_TOOLCHAIN_VERSION
将此变量定义为 4.9 或 4.8 以选择 GCC 编译器的版本。 64 位 ABI 默认使用版本 4.9 ,32 位 ABI 默认使用版本 4.8。要选择 Clang 的版本,请将此变量定义为 clang3.4、clang3.5 或 clang。 指定 clang 会选择 Clang 的最新版本。
APP_PIE
从 Android 4.1(API 级别 16)开始,Android 的动态链接器支持位置独立的可执行文件 (PIE)。 从 Android 5.0(API 级别 21)开始,可执行文件需要 PIE。要使用 PIE 构建可执行文件,请设置 -fPIE 标志。 此标志增大了通过随机化代码位置来利用内存损坏缺陷的难度。 默认情况下,如果项目针对 android-16 或更高版本,ndk-build 会自动将此值设置为 true。您可以手动将其设置为 true 或 false。
此标志仅适用于可执行文件。它在构建共享或静态库时没有影响。
注:PIE 可执行文件无法在 4.1 版之前的 Android 上运行。
此限制仅适用于可执行文件。它在构建共享或静态库时没有影响。
APP_THIN_ARCHIVE
在 Android.mk 文件中为此项目中的所有静态库模块设置 LOCAL_THIN_ARCHIVE 的默认值。 如需了解详细信息,请参阅 Android.mk 文档中的 LOCAL_THIN_ARCHIVE。
Android.mk官方说明
基础知识
在详细了解语法之前,先了解 Android.mk 文件所含内容的基本信息很有用。 为此,本节使用 Hello-JNI 示例中的 Android.mk
文件,解释文件中的每行所起的作用。
Android.mk 文件必须首先定义 LOCAL_PATH
变量:
LOCAL_PATH := $(call my-dir)
此变量表示源文件在开发树中的位置。在这里,构建系统提供的宏函数 my-dir 将返回当前目录(包含 Android.mk 文件本身的目录)的路径。
下一行声明 CLEAR_VARS
变量,其值由构建系统提供。
include $(CLEAR_VARS)
CLEAR_VARS
变量指向特殊 GNU Makefile
,可为您清除许多 LOCAL_XXX
变量,例如 LOCAL_MODULE
、LOCAL_SRC_FILES
和 LOCAL_STATIC_LIBRARIES
。
请注意,它不会清除 LOCAL_PATH
。此变量必须保留其值,因为系统在单一 GNU Make 执行环境(其中所有变量都是全局的)中解析所有构建控制文件。 在描述每个模块之前,必须声明(重新声明)此变量。
接下来,LOCAL_MODULE
变量将存储您要构建的模块的名称。请在应用中每个模块使用一个此变量。
LOCAL_MODULE := hello-jni
每个模块名称必须唯一,且不含任何空格。构建系统在生成最终共享库文件时,会将正确的前缀和后缀自动添加到您分配给 LOCAL_MODULE
的名称。 例如,上述示例会导致生成一个名为 libhello-jni.so
的库。
注:如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。 因此,比如原来名为 libfoo.c 的源文件仍会生成名为 libfoo.so 的共享对象文件。
此行为是为了支持 Android 平台源文件从 Android.mk 文件生成的库;所有这些库的名称都以 lib 开头。
下一行枚举源文件,以空格分隔多个文件:
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES
变量必须包含要构建到模块中的 C 和/或 C++ 源文件列表。
最后一行帮助系统将所有内容连接到一起:
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY
变量指向 GNU Makefile 脚本,用于收集您自最近 include 后在 LOCAL_XXX
变量中定义的所有信息。 此脚本确定要构建的内容及其操作方法。
示例目录中有更复杂的示例,包括您可以查看的带注释的 Android.mk 文件。 此外,示例:native-activity 详细说明了该示例的 Android.mk 文件。 最后,变量和宏提供本节中变量的进一步信息。
变量和宏
构建系统提供许多可用于 Android.mk 文件中的变量。其中许多变量已预先赋值。 另一些变量由您赋值。
除了这些变量之外,您还可以定义自己的任意变量。在定义变量时请注意,NDK 构建
系统会预留以下变量名称:
-
以
LOCAL_
开头的名称,例如LOCAL_MODULE
。 -
以
PRIVATE_
、NDK_
或APP
开头的名称。构建系统在内部使用这些变量。 -
小写名称,例如 my-dir。构建系统也是在内部使用这些变量。
为了方便别人阅读而需要在 Android.mk 文件中定义自己的变量,建议在名称前附加 MY_
。
NDK 定义的变量
本节讨论构建系统在解析 Android.mk 文件之前定义的 GNU Make 变量。 在某些情况下,NDK 可能会多次解析 Android.mk 文件,每次使用其中某些变量的不同定义。
CLEAR_VARS
此变量指向的构建脚本用于取消定义下面“开发者定义的变量”一节中列出的几乎全部 LOCAL_XXX
变量。 在描述新模块之前,使用此变量包括此脚本。 使用它的语法为:
include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY
此变量指向的脚本用于收集您在 LOCAL_XXX
变量中提供的模块所有相关信息,以及确定如何从列出的源文件构建目标共享库。 请注意,使用此脚本要求您至少已为 LOCAL_MODULE
和LOCAL_SRC_FILES
赋值(如需了解有关这些变量的详细信息,请参阅模块描述变量)。
使用此变量的语法为:
include $(BUILD_SHARED_LIBRARY)
共享库变量导致构建系统生成具有 .so 扩展名的库文件。
BUILD_STATIC_LIBRARY
用于构建静态库的 BUILD_SHARED_LIBRARY
的变体。构建系统不会将静态库复制到您的项目/软件包,但可能使用它们构建共享库(请参阅下面的 LOCAL_STATIC_LIBRARIES
和 LOCAL_WHOLE_STATIC_LIBRARIES
)。 使用此变量的语法为:
include $(BUILD_STATIC_LIBRARY)
静态库变量导致构建系统生成扩展名为 .a 的库。
PREBUILT_SHARED_LIBRARY
指向用于指定预建共享库的构建脚本。与BUILD_SHARED_LIBRARY
和 BUILD_STATIC_LIBRARY
的情况不同,这里的 LOCAL_SRC_FILES
值不能是源文件, 而必须是指向预建共享库的单一路径,例如 foo/libfoo.so。 使用此变量的语法为:
include $(PREBUILT_SHARED_LIBRARY)
也可使用 LOCAL_PREBUILTS
变量引用另一个模块中的预建库。 如需了解有关使用预建库的详细信息,请参阅使用预建库。
PREBUILT_STATIC_LIBRARY
与 PREBUILT_SHARED_LIBRARY 相同,但用于预构建的静态库。如需了解有关使用预建库的详细信息,请参阅使用预建库。
TARGET_ARCH
Android 开放源代码项目所指定的目标 CPU 架构的名称。对于与 ARM 兼容的任何构建,请使用独立于 CPU 架构修订版或 ABI 的 arm(请参阅下面的 TARGET_ARCH_ABI
)。
此变量的值取自您在 Android.mk 文件中定义的 APP_ABI
变量,系统将在解析 Android.mk 文件前读取其值。(翻译:应该是Application.mk)
TARGET_PLATFORM
作为构建系统目标的 Android API 级别号。例如,Android 5.1 系统映像对应于 Android API 级别 22:android-22。如需平台名称及相应 Android 系统映像的完整列表,请参阅 Android NDK 原生 API。以下示例显示了使用此变量的语法:
TARGET_PLATFORM := android-22
TARGET_ARCH_ABI
当构建系统解析此 Android.mk 文件时,此变量将 CPU 和架构的名称存储到目标。 您可以指定以下一个或多个值,使用空格作为多个目标之间的分隔符。 表 1 显示了要用于每个支持的 CPU 和架构的 ABI 设置。
表 1. 不同 CPU 和架构的 ABI 设置。
CPU 和架构|设置的参数
ARMv5TE armeabi
ARMv7 armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64
mips32 (r1) mips
mips64 (r6) mips64
全部 all
以下示例显示如何将 ARMv8 AArch64 设置为目标 CPU 与 ABI 的组合:
TARGET_ARCH_ABI := arm64-v8a
注:在 Android NDK 1.6_r1 和以前的版本中,此变量定义为 arm。
如需了解架构 ABI 和相关兼容性问题的详细信息,请参阅 ABI 管理。
未来的新目标 ABI 将有不同的值。
TARGET_ABI
目标 Android API 级别与 ABI 的联接,特别适用于要针对实际设备测试特定目标系统映像的情况。 例如,要指定在 Android API 级别 22 上运行的 64 位 ARM 设备:
TARGET_ABI := android-22-arm64-v8a
注:在 Android NDK 1.6_r1 和以前的版本中,默认值为 android-3-arm
。
模块描述变量
本节中的变量向构建系统描述您的模块。每个模块描述应遵守以下基本流程:
使用 CLEAR_VARS 变量初始化或取消定义与模块相关的变量。
为用于描述模块的变量赋值。
使用 BUILD_XXX 变量设置 NDK 构建系统,以便为模块使用适当的构建脚本。
LOCAL_PATH
此变量用于指定当前文件的路径。必须在 Android.mk 文件的开头定义它。 以下示例向您展示如何操作:
LOCAL_PATH := $(call my-dir)
CLEAR_VARS
指向的脚本不会清除此变量。因此,即使您的 Android.mk 文件描述了多个模块,您也只需定义它一次。
LOCAL_MODULE
此变量用于存储模块的名称。它在所有模块名称之间必须唯一,并且不得包含任何空格。 必须在包含任何脚本(用于 CLEAR_VARS 的脚本除外)之前定义它。 无需添加 lib 前缀或者 .so 或 .a 文件扩展名;构建系统会自动进行这些修改。 在整个 Android.mk 和 Application.mk 文件中,请通过未修改的名称引用模块。 例如,以下行会导致生成名为 libfoo.so 的共享库模块:
LOCAL_MODULE := "foo"
如果希望生成的模块使用 lib 以外的名称和 LOCAL_MODULE 以外的值,可以使用 LOCAL_MODULE_FILENAME
变量为生成的模块指定自己选择的名称。
LOCAL_MODULE_FILENAME
此可选变量可让您覆盖构建系统默认用于其生成的文件的名称。 例如,如果 LOCAL_MODULE 的名称为 foo,您可以强制系统将它生成的文件命名为 libnewfoo。 以下示例显示如何完成此操作:
LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo
对于共享库模块,此示例将生成一个名为 libnewfoo.so 的文件。
注:无法替换文件路径或文件扩展名。
LOCAL_SRC_FILES
此变量包含构建系统用于生成模块的源文件列表。 只列出构建系统实际传递到编译器的文件,因为构建系统会自动计算所有关联的依赖关系。
请注意,可以使用相对文件路径(指向 LOCAL_PATH)和绝对文件路径。
建议避免使用绝对文件路径;相对路径会使 Android.mk 文件移植性更强。
注:在构建文件中务必使用 Unix 样式的正斜杠 (/)。构建系统无法正确处理 Windows 样式的反斜杠 ()。
LOCAL_CPP_EXTENSION
可以使用此可选变量为 C++ 源文件指明 .cpp 以外的文件扩展名。 例如,以下行会将扩展名改为 .cxx。(设置必须包含点。)
LOCAL_CPP_EXTENSION := .cxx
从 NDK r7 开始,您可以使用此变量指定多个扩展名。例如:
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CPP_FEATURES
可以使用此可选变量指明您的代码依赖于特定 C++ 功能。它在构建过程中启用正确的编译器和链接器标志。 对于预构建的库,此变量还可声明二进制文件依赖哪些功能,从而帮助确保最终关联正确工作。 建议使用此变量,而不要直接在 LOCAL_CPPFLAGS 定义中启用 -frtti 和 -fexceptions。
使用此变量可让构建系统对每个模块使用适当的标志。使用 LOCAL_CPPFLAGS 会导致编译器对所有模块使用所有指定的标志,而不管实际需求如何。
例如,要指示您的代码使用 RTTI(运行时类型信息),请编写:
LOCAL_CPP_FEATURES := rtti
要指示您的代码使用 C++ 异常,请编写:
LOCAL_CPP_FEATURES := exceptions
您还可为此变量指定多个值。例如:
LOCAL_CPP_FEATURES := rtti features
描述值的顺序不重要。
LOCAL_C_INCLUDES
可以使用此可选变量指定相对于 NDK root 目录的路径列表,以便在编译所有源文件(C、C++ 和 Assembly)时添加到 include 搜索路径。 例如:
LOCAL_C_INCLUDES := sources/foo
甚至:
LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
在通过 LOCAL_CFLAGS 或 LOCAL_CPPFLAGS 设置任何对应的 include 标志之前定义此变量。
在使用 ndk-gdb 启动本地调试时,构建系统也会自动使用 LOCAL_C_INCLUDES 路径。
LOCAL_CFLAGS
此可选变量为构建系统设置在构建 C 和 C++ 源文件时要传递的编译器标志。 此功能对于指定额外的宏定义或编译选项可能很有用。
尽量不要更改 Android.mk 文件中的优化/调试级别。构建系统可使用 Application.mk 文件中的相关信息自动为您处理此设置。 这样允许构建系统生成在调试时使用的有用数据文件。
注:在 android-ndk-1.5_r1 中,相应的标志只适用于 C 源文件,而不适用于 C++ 源文件。 它们现在与整个 Android 构建系统的行为匹配。(您现在可以使用 LOCAL_CPPFLAGS 只为 C++ 源文件指定标志。)
可通过编写以下代码指定其他 include 路径:
LOCAL_CFLAGS += -I<path>,
但使用 LOCAL_C_INCLUDES 更好,因为这样也可以通过 ndk-gdb 使用可用于本地调试的路径。
LOCAL_CPPFLAGS
仅当构建 C++ 源文件时才会传递一组可选的编译器标志。 它们将出现在编译器命令行中的 LOCAL_CFLAGS 后面。
注:在 android-ndk-1.5_r1 中,相应的标志适用于 C 和 C++ 源文件。 这已经更正,可与整个 Android 构建系统的行为匹配。要为 C 和 C++ 源文件指定标志,请使用 LOCAL_CFLAGS。
LOCAL_STATIC_LIBRARIES
此变量用于存储当前模块依赖的静态库模块列表。
如果当前模块是共享库或可执行文件,此变量将强制这些库链接到生成的二进制文件。
如果当前模块是静态库,此变量只是指示,依赖当前模块的模块也会依赖列出的库。
LOCAL_SHARED_LIBRARIES
此变量是此模块在运行时依赖的共享库模块列表。 此信息在链接时需要,并且会在生成的文件中嵌入相应的信息。
LOCAL_WHOLE_STATIC_LIBRARIES
此变量是 LOCAL_STATIC_LIBRARIES 的变体,表示链接器应将相关的库模块视为整个存档。 如需了解有关整个存档的详细信息,请参阅 GNU 链接器关于 --whole-archive 标志的文档。
当多个静态库之间具有循环相依关系时,此变量很有用。 使用此变量构建共享库时,将会强制构建系统将所有对象文件从静态库添加到最终二进制文件。 但在生成可执行文件时不会发生这样的情况。
LOCAL_LDLIBS
此变量包含在构建共享库或可执行文件时要使用的其他链接器标志列表。 它可让您使用 -l 前缀传递特定系统库的名称。 例如,以下示例指示链接器生成在加载时链接到 /system/lib/libz.so 的模块:
LOCAL_LDLIBS := -lz
如需了解此 NDK 版本中可以链接的已公开系统库列表,请参阅 Android NDK 原生 API。
注: 如果为静态库定义此变量,构建系统会忽略它,并且 ndk-build 会显示一则警告。
LOCAL_LDFLAGS
构建共享库或可执行文件时供构建系统使用的其他链接器标志列表。 例如,以下示例在 ARM/X86 GCC 4.6+ 上使用 ld.bfd 链接器,该系统上的默认链接器是 ld.gold
LOCAL_LDFLAGS += -fuse-ld=bfd
注:如果为静态库定义此变量,构建系统会忽略它,并且 ndk-build 会显示一则警告。
LOCAL_ALLOW_UNDEFINED_SYMBOLS
默认情况下,若构建系统在尝试构建共享库时遇到未定义的引用,将会引发“未定义的符号”错误。 此错误可帮助您捕获源代码中的缺陷。
要停用此检查,请将此变量设置为 true。请注意,此设置可能导致共享库在运行时加载。
注: 如果为静态库定义此变量,构建系统会忽略它,并且 ndk-build 会显示一则警告。
LOCAL_ARM_MODE
默认情况下,构建系统在 thumb 模式中生成 ARM 目标二进制文件,其中每个指令都是 16 位宽,并且与 thumb/ 目录中的 STL 库链接。将此变量定义为 arm 会强制构建系统在 32 位 arm 模式下生成模块的对象文件。 以下示例显示如何执行此操作:
LOCAL_ARM_MODE := arm
您也可以为源文件名附加 .arm 后缀,指示构建系统只在 arm 模式中构建特定的源文件。 例如,以下示例指示构建系统始终在 ARM 模式中编译 bar.c,但根据 LOCAL_ARM_MODE 的值构建 foo.c。
LOCAL_SRC_FILES := foo.c bar.c.arm
注:您也可以在 Application.mk 文件中将 APP_OPTIM 设置为 debug,强制构建系统生成 ARM 二进制文件。指定 debug 会强制构建 ARM,因为工具链调试程序无法正确处理 Thumb 代码。
LOCAL_ARM_NEON
此变量仅在您针对 armeabi-v7a ABI 时才重要。它允许在 C 和 C++ 源文件中使用 ARM Advanced SIMD (NEON) GCC 内联函数,以及在 Assembly 文件中使用 NEON 指令。
请注意,并非所有基于 ARMv7 的 CPU 都支持 NEON 指令集扩展。因此,必须执行运行时检测以便在运行时安全地使用此代码。 如需了解详细信息,请参阅 NEON 支持和 cpufeatures 库。
或者,您也可以使用 .neon 后缀指定构建系统只编译支持 NEON 的特定源文件。 在以下示例中,构建系统编译支持 thumb 和 neon 的 foo.c、支持 thumb 的 bar.c,以及支持 ARM 和 NEON 的 zoo.c。
LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon
如果您使用两个后缀,.arm 必须在 .neon 前面。
LOCAL_DISABLE_NO_EXECUTE
Android NDK r4 添加了对“NX 位”安全功能的支持。此支持默认启用,但您也可通过将此变量设置为 true 将其停用。 如果没有必要的原因,我们不建议停用。
此功能不会修改 ABI,并且仅在针对 ARMv6+ CPU 设备的内核上启用。 启用此功能的机器代码在运行较早 CPU 架构的设备上将不加修改而直接运行。
如需了解详细信息,请参阅 Wikipedia:NX 位和 GNU 栈快速入门。
LOCAL_DISABLE_RELRO
默认情况下,NDK 编译具有只读重定位和 GOT 保护的代码。 此变量指示运行时链接器在重定位后将某些内存区域标记为只读,增加了某些安全漏洞利用(例如 GOT 覆盖)的难度。 请注意,这些保护仅在 Android API 级别 16 和更高版本上有效。在较低的 API 级别上,该代码仍会运行,但没有内存保护。
此变量默认启用,但您也可通过将其值设置为 true 来停用它。 如果没有必要的原因,我们不建议停用。
如需了解详细信息,请参阅 RELRO:重定位只读和 RedHat Enterprise Linux 中的安全增强功能(第 6 节)。
LOCAL_DISABLE_FORMAT_STRING_CHECKS
默认情况下,构建系统编译具有格式字符串保护的代码。如果 printf 样式的函数中使用非常量的格式字符串,这样会强制编译器出错。
此保护默认启用,但您也可通过将此变量的值设置为 true 将其停用。 如果没有必要的原因,我们不建议停用。
LOCAL_EXPORT_CFLAGS
此变量用于记录一组 C/C++ 编译器标志,这将标志将添加到通过 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 变量使用它们的任何其他模块的 LOCAL_CFLAGS 定义。
例如,假设有以下模块对:foo 和 bar,分别依赖于 foo:
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.c 时会向编译器传递标志 -DFOO=1 和 -DBAR=2。 它还会在模块的 LOCAL_CFLAGS 前面加上导出的标志,以便您轻松替换它们。
此外,模块之间的关系也是可传递的:如果 zoo 依赖于 bar,后者又依赖于 foo,则 zoo 也会继承从 foo 导出的所有标志。
最后,构建系统在本地构建时不使用导出的标志(即,构建要导出其标志的模块)。 因此,在上面的示例中,构建 foo/foo.c 时不会将 -DFOO=1 传递到编译器。 要在本地构建,请改用 LOCAL_CFLAGS。
LOCAL_EXPORT_CPPFLAGS
此变量与 LOCAL_EXPORT_CFLAGS 相同,但仅适用于 C++ 标志。
LOCAL_EXPORT_C_INCLUDES
此变量与 LOCAL_EXPORT_CFLAGS 相同,但适用于 C include 路径。例如,当 bar.c 需要包含模块 foo 中的标头时很有用。
LOCAL_EXPORT_LDFLAGS
此变量与 LOCAL_EXPORT_CFLAGS 相同,但适用于链接器标志。
LOCAL_EXPORT_LDLIBS
此变量与 LOCAL_EXPORT_CFLAGS 相同,用于指示构建系统将特定系统库的名称传递到编译器。 在您指定的每个库名称前面附加 -l。
请注意,构建系统会将导入的链接器标志附加到模块的 LOCAL_LDLIBS 变量值。 其原因在于 Unix 链接器运行的方式。
当模块 foo 是静态库并且具有依赖于系统库的代码时,此变量通常很有用。 然后您可以使用 LOCAL_EXPORT_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)
在此示例中,构建系统在构建 libbar.so 时,将在链接器命令的末尾放置 -llog。 这样会告知链接器,由于 libbar.so 依赖于 foo,因此它也依赖于系统日志记录库。
LOCAL_SHORT_COMMANDS
当您的模块有很多源文件和/或相依的静态或共享库时,将此变量设置为 true。 这样会强制构建系统对包含中间对象文件或链接库的存档使用 @ 语法。
此功能在 Windows 上可能很有用,其中命令行最多只接受 8191 个字符,这对于复杂的项目可能太少。 它还会影响个别源文件的编译,而且将几乎所有编译器标志放在列表文件内。
请注意,true 以外的任何值都将恢复到默认行为。 您也可在 Application.mk 文件中定义 APP_SHORT_COMMANDS
,以强制对项目中的所有模块实施此行为。
不建议默认启用此功能,因为它会减慢构建的速度。
LOCAL_THIN_ARCHIVE
构建静态库时将此变量设置为 true。这样会生成一个瘦存档 ,即一个库文件,其中不含对象文件,而只包含它通常要包含的实际对象的文件路径。
这对于减小构建输出的大小非常有用。缺点是:这样的库无法移至不同的位置(其中的所有路径都是相对的)。
有效值为 true、false 或空白。可通过 APP_THIN_ARCHIVE 变量在 Application.mk 文件中设置默认值。
注:对于非静态库模块或预构建的静态库模块会忽略此变量。
LOCAL_FILTER_ASM
将此变量定义为构建系统要用于过滤从您为 LOCAL_SRC_FILES 指定的文件提取或生成的汇编文件的 shell 命令。
定义此变量会导致发生以下情况:
构建系统从任何 C 或 C++ 源文件生成临时汇编文件,而不是将它们编译到对象文件。
构建系统在任何临时汇编文件以及 LOCAL_SRC_FILES 中所列任何汇编文件的 LOCAL_FILTER_ASM 中执行 shell 命令,因此会生成另一个临时汇编文件。
构建系统将这些过滤的汇编文件编译到对象文件中。
例如:
LOCAL_SRC_FILES := foo.c bar.S
LOCAL_FILTER_ASM :=
foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
bar.S --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o
“1”对应编译器,“2”对应过滤器,“3”对应汇编程序。过滤器必须是采用输入文件名称作为其第一个参数、输出文件名称作为第二个参数的独立 shell 命令。 例如:
myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S
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 的路径。 因此,在包含另一个文件后不应调用 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,因为这是其最近 include 指向的位置。
在 Android.mk 文件中的任何其他内容后放置额外 include 可避免此问题。 例如:
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> 标记的模块,并且自动为您包含其Android.mk 文件。
纯make练习语法。
window使用cygwin64 把bin目录添加到环境变量中
make -f myfile.mk
测试一个mk文件。
make默认识别的文件是当前运行目录下的Makefile不带后缀文件。
myfile.mk内容如下
$(warning nihao)
LOCAL_PATH:= current_$(call my-dir)
$(warning $(LOCAL_PATH))
my-dir
没有输出任何东西,因为这要安卓的ndk-build才有。
测试这个文件的方法
make -f myfile.mk
或者在此目录创建Makefile然后输入include myfile.mk
执行make将自动执行.
定义Make target
语法格式与执行
target名:
TAB命令行名
如
aa:
gcc -o hello hello.c
./hello.exe
切记gcc前面是用tab隔开的,否则会报错误。
测试执行
make -f mymake.mk aa
如果不出意外会编译当前目录的hello.c并执行,前提是hello.c存在以及配置了gcc的环境变量。
完整示例:
#配置环境变量make,用法 输入 make -f test.mk
#图标是可以指定的,如果没有指定目标会找到第一个,如果传递了目标比如传递make -f test.mk run:则会执行后者,而不是前者。
VARIABLE1:= 555
$(param $(1))
$(info 2-$(VARIABLE1))
aa=$(call VARIABLE1,hello,world)#不用冒号也可以定义?/
$(warning 你可以输入make -f test.mk help执行菜单帮助)
$(info 2-$(aa))
help:
@echo 欢迎学习mk,你如果能执行本文件,那么你应该可以算和我一样已经找到了写make的感觉了。
@echo 输入make -f 文件 run 执行文件
@echo 输入make -f 文件 compile 编译文件
@echo 执行了all任务,
@echo 你好 你好 target下面的东西都需要用空格隔开,否则会出现语法错误。
@echo make语法中以艾特开头可以执行系统的命令,如echo就属于.
$(warning Wellcome Study write makefile)
TEMP:=HELLO
$(warning execcompile)#不执行..似乎不能连续输出多个
compile:bbb #这个值1:值2是必须写的,否则报错。
gcc -o foo hello.c
./foo.exe
@echo 执行编译完成
run:
@echo 执行了run
./foo.exe
网友评论