01-05 NDK开发必知必会3⃣️MakeFile详解

栏目: Android · 发布时间: 7年前

内容简介:C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。Android.mk 的文件配置详解,能够读懂Android.mk;为何Google推荐使用cmake,而不在使用Android.mk?Android.mk存在哪些缺陷?如何生成静态库与动态库(在上几篇文章中讲过)?

C/C++语言基础 –> JNI编程 –> NDK编程 –> 音视频处理 –> 图像处理等等 ,从零到一 , 零基础学习NDK开发 。学习本专题 , 你需要具备一定的Android开发知识 C/C++基础, 知道如何创建一个Android工程 , 有一定的开发经验更佳 。

前言

Android.mk 的文件配置详解,能够读懂Android.mk;为何Google推荐使用cmake,而不在使用Android.mk?Android.mk存在哪些缺陷?

如何生成静态库与动态库(在上几篇文章中讲过)?

Android.mk 如何配置动态库(.so文件)、配置静态库(.a文件)?

静态库与动态库的区别?

带着这些问题,思考,往下看。

环境:

AS 3.1.0 版本

NDK 16 版本

命令行: Mac 自带的命令行

通过命令来生成动态库和静态库

这里用mac的终端来演示,通过vim 命令来生成一个.c文件,这个就不必细说了吧。 在NDK 开发必知必会1⃣️CC++编译器配置,中有详细的讲解

输入: vim a.c

01-05 NDK开发必知必会3⃣️MakeFile详解

然后配置一个临时的变量:

export CC="/Users/prim/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc --sysroot=/Users/prim/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm -isystem /Users/prim/Library/Android/sdk/ndk-bundle/sysroot/usr/include -isystem /Users/prim/Library/Android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi"

输入 :echo $CC 验证变量是否配置成功

输入 :$CC -fPIC -shared a.c -o libA.so 生成libA.so文件,这里便生成了一个动态库

输入:$CC -fPIC -c a.c -o a.o 生成a.o 文件,用于生成静态库

输入 : /Users/prim/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar r libA.a a.o

会生成libA.a 静态库文件。

将得到的libA.so libA.a copy到项目的cpp 文件夹下( cpp可参照如何配置NDK开发环境 )。

配置依赖动态库

NDK 环境的配置,这里就不再细说了,配置完成如下图:

01-05 NDK开发必知必会3⃣️MakeFile详解

gradle 配置

01-05 NDK开发必知必会3⃣️MakeFile详解

下面是重点,Android.mk文件如何配置动态库

LOCAL_PATH := $(call my-dir)

# 预编译库引入(提前编译好的库)
include $(CLEAR_VARS)
LOCAL_MODULE := A
LOCAL_SRC_FILES := libA.so
# 构建动态库
include $(PREBUILT_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE := holle-jni
LOCAL_SRC_FILES := holle-jni.c
# 编译holle-jni模块 需要连接A模块
# A模块是一个预编译库模块 动态库
LOCAL_SHARED_LIBRARIES := A
# 动态库配置
include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)表示:源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。

include $(CLEAR_VARS):引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量

不会清理 LOCAL_PATH 变量

LOCAL_MODULE := hello-jni:存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格

#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。

LOCAL_SRC_FILES := hello-jni.c:包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开

构建动态库 include $(BUILD_SHARED_LIBRARY)

这样便配置好了动态库,build一下看cpp文件有没有变亮,如果变亮则动态库配置成功。

会生成两个so包libholle-jni.so libA.so

01-05 NDK开发必知必会3⃣️MakeFile详解

如何使用libA.so中的函数呢?

编辑 holle-jni.c

#include <jni.h>
//libA.so 中的方法
extern int test1();



JNIEXPORT void JNICALL
Java_ndk_config_com_configndk_MainActivity_useLibAMoudle(JNIEnv *env, jobject instance) {

    // TODO
    test1();
}

Activity 中代码

static {
        System.loadLibrary("holle-jni");
    }

这样就可以调用动态库中的函数了。

Android.mk 配置动态库的缺陷

在4.4上 如果load一个动态库 ,需要先将这个动态库的依赖的其他动态库load进来

比如:在Android 4.4 先要load holle-jni 链接的动态库,要在load holle-jni 之前load进来

System.loadLibrary("A");
 System.loadLibrary("holle-jni");

从6.0开始 使用Android.mk 如果来引入一个预编译动态库 有问题

在6.0以下 System.loadLibrary 不会自动为我们加载依赖的动态库

6.0以上 System.loadLibrary 会自动为我们加载依赖的动态库

那么在6.0 以上就不能使用,如下方法loadlibary,否则项目会报错:

System.loadLibrary("A");
 System.loadLibrary("holle-jni");

改成,因为6.0以上会自动加载依赖的动态库。

System.loadLibrary("holle-jni");

这里并没有太好的解决方法,或许是因为这个原因,Google才推荐使用cmake的方式,现在的ndk对mk的支持已经接近放弃阶段了。

配置依赖静态库

LOCAL_PATH := $(call my-dir)

# 预编译库引入(提前编译好的库)
include $(CLEAR_VARS)
LOCAL_MODULE := A
LOCAL_SRC_FILES := libA.a
# 构建静态库
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := holle-jni
LOCAL_SRC_FILES := holle-jni.c
# 构建静态库
LOCAL_STATIC_LIBRARIES := A

# 动态库配置
include $(BUILD_SHARED_LIBRARY)

调用静态库的函数和调用动态库的函数方式一致。

同时Activity只需要,便可以,静态库不需要动态的加载依赖,在打包时已经将静态库打进去了。

System.loadLibrary("holle-jni");

使用静态库会生成一个so文件,很显然apk会小很多

01-05 NDK开发必知必会3⃣️MakeFile详解

静态库与动态库的区别

静态库节省时间:不需要再进行动态链接,需要调用的代码直接就在代码内部

动态库节省空间:如果一个动态库被两个程序调用,那么这个动态库只需要在内存中

Java中在不经过封装的情况下只能直接使用动态库。

我们可以这样比喻两个库的区别:

jar包 =》 a.java b.java c.java

app: app.java(a.java),app.java 调用jar包的 a.java

假设jar包是静态库,那么打包的apk 只包含 app.java + a.java 而没有将 b.java c. java 打进apk包中。

app.apk –> app.java+a.java

假设jar包是动态库,直接将整个jar包打入到apk包中。

app.apk: app.java+ jar包(a.java b.java c.java)

显然,如果我们使用静态库(.a)打的apk包要比动态库(.so)打的apk包小很多。

MakeFile 配置详解

变量和宏

定义自己的任意变量。在定义变量时请注意,NDK 构建系统会预留以下变量名称:

以 LOCAL_ 开头的名称,例如 LOCAL_MODULE。

以 PRIVATE_、NDK_ 或 APP 开头的名称。构建系统在内部使用这些变量。

小写名称,例如 my-dir。构建系统也是在内部使用这些变量。

如果为了方便而需要在 Android.mk 文件中定义自己的变量,建议在名称前附加 MY_。

常用内置变量

变量名 含义 示例
BUILD_STATIC_LIBRARY 构建静态库的Makefile脚本 include $(BUILD_STATIC_LIBRARY)
PREBUILT_SHARED_LIBRARY 预编译共享库的Makeifle脚本 include $(PREBUILT_SHARED_LIBRARY)
PREBUILT_STATIC_LIBRARY 预编译静态库的Makeifle脚本 include $(PREBUILT_STATIC_LIBRARY)
TARGET_PLATFORM Android API 级别号 TARGET_PLATFORM := android-22
TARGET_ARCH CUP架构 arm arm64 x86 x86_64
TARGET_ARCH_ABI CPU架构 armeabi armeabi-v7a arm64-v8a

模块描述变量

变量名 描述
LOCAL_MODULE_FILENAME 覆盖构建系统默认用于其生成的文件的名称 LOCAL_MODULE := foo LOCAL_MODULE_FILENAME := libnewfoo
LOCAL_CPP_FEATURES 特定 C++ 功能 支持异常:LOCAL_CPP_FEATURES := exceptions
LOCAL_C_INCLUDES 头文件目录查找路径 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS 构建 C 和 C++ 的编译参数 LOCAL_CPPFLAGS c++
LOCAL_STATIC_LIBRARIES 当前模块依赖的静态库模块列表 LOCAL_SHARED_LIBRARIES
LOCAL_WHOLE_STATIC_LIBRARIES –whole-archive 将未使用的函数符号也加入编译进入这个模块
LOCAL_LDLIBS 依赖 系统库 LOCAL_LDLIBS := -lz

导出给引入模块的模块使用:

LOCAL_EXPORT_CFLAGS

LOCAL_EXPORT_CPPFLAGS

LOCAL_EXPORT_C_INCLUDES

LOCAL_EXPORT_LDLIBS

引入其他模块

#将一个新的路径加入NDK_MODULE_PATH变量
#NDK_MODULE_PATH 变量是系统环境变量
$(call import-add-path,$(LOCAL_PATH)/platform/third_party/android/prebuilt)
#包含CocosDenshion/android目录下的mk文件
$(call import-module,CocosDenshion/android)

#这里即为 我需要引入 CocosDenshion/android 下面的Android.mk
#CocosDenshion/android 的路径会从 $(LOCAL_PATH)/platform/third_party/android/prebuilt 去查找

以上所述就是小编给大家介绍的《01-05 NDK开发必知必会3⃣️MakeFile详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Writing Windows VxDs and Device Drivers, Second Edition

Writing Windows VxDs and Device Drivers, Second Edition

Karen Hazzah / CMP / 1996-01-12 / USD 54.95

Software developer and author Karen Hazzah expands her original treatise on device drivers in the second edition of "Writing Windows VxDs and Device Drivers." The book and companion disk include the a......一起来看看 《Writing Windows VxDs and Device Drivers, Second Edition》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具