Android.mk介绍

1.简介

1.Android.mk是一个向Android NDK构建系统描述NDK项目的GNU makefile片段。主要用来编译生成一下几种:
	1.APK程序:一般的Android应用程序,系统级别的直接push即可。
	2.JAVA库:JAVA类库,编译打包生成jar文件。
	3.C\C++应用程序:可执行的C\C++应用程序。
	4.C\C++静态库:编译生成C\C++静态库,并打包成.a文件。
	5.C\C++共享库:编译生成共享库,并打包成.so文件。

2.案例

# 定义当前模块路径 (必须定义在文件开头,只需定义一次)
LOCAL_PATH := $(call my-dir)

# 清空当前环境变量 (LOCAL_PATH除外)
include $(CLEAR_VARS)

# 当前模块名 (这里会生成libhello-jni.so) 模块名必须唯一,不能包含空格
LOCAL_MODULE := hello-jni

# 当前模块包含的源代码文件 多个可以用空格隔开
LOCAL_SRC_FILES := hello-jni.c

# 生成一个动态库(表示当前模块被编译成一个共享库)
include $(BUILD_SHARED_LIBRARY)

3.编译多个共享库

一个Android.mk可能编译产生多个共享库模块,如下产生了libmodule1.so 和 libmodule2.so两个库
LOCAL_PATH := $(call my-dir)

#模块1
include $(CLEAR_VARS)
LOCAL_MODULE := module1
LOCAL_SRC_FILES := module1.c
include $(BUILD_SHARED_LIBRARY)

#模块2
include $(CLEAR_VARS)
LOCAL_MODULE := module2
LOCAL_SRC_FILES := module2.c
include $(BUILD_SHARED_LIBRARY)

4.编译静态库

Android应用程序不能直接使用静态库,但是静态库可以用来编译成动态库。比如在将第三方代码添加到原生项目中时,
可以不用直接将第三方源码包含在原生项目中,而是将第三方源码编译成静态库,然后并入共享库

LOCAL_PATH := $(call my-dir)

# 第三方库AVI
include $(CLEAR_VARS)
LOCAL_MODULE := AVI
LOCAL_SRC_FILES := AVI.c
include $(BUILD_STATIC_LIBRARY)

#原生模块
include $(CLEAR_VARS)
LOCAL_MODULE := module
LOCAL_SRC_FILES := module.c
#将静态库模块名添加到LOACAL_STATIC_LIBRARIES变量
LOCAL_STAITC_LIBRAYIES := AVI
include $(BUILD_SHARED_LIBRARY)

5.使用共享库共享通用模块

静态库可以保证源代码模块化,但是当静态库与共享库相连时,它就变成了共享库的一部分。在多个共享库的情况下,
多个共享库与静态库连接时,需要将通用模块的多个副本与不同的共享库重复相连,这样就增加了app的大小,这种
情况,可以将通用模块作为共享库。

LOCAL_PATH := $(call my-dir)

# 第三方库AVI
include $(CLEAR_VARS)
LOCAL_MODULE := AVI
LOCAL_SRC_FILES := AVI.c
include $(BUILD_SHARED_LIBRARY)

#原生模块1
include $(CLEAR_VARS)
LOCAL_MODULE := module1
LOCAL_SRC_FILES := module1.c
LOCAL_SHARED_LIBRARIES := AVI
include $(BUILD_SHARED_LIBRARY)

#原生模块2
include $(CLEAR_VARS)
LOCAL_MODULE := module2
LOCAL_SRC_FILES := module2.c
LOCAL_SHARED_LIBRARIES := AVI
include $(BUILD_SHARED_LIBRARY)

6.在多个NDK项目间共享模块

1.首先将AVI源代码移动到NDK项目以外的位置
2.作为共享模块,AVI需要有自己的Android.mk模块
3.以transcode/avilib为参数调用函数宏import-module添加到NDK项目的Android.mk文档末尾

#AVI模块自己的Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := AVI
LOCAL_SRC_FILES := AVI.c
include $(BUILD_SHARED_LIBRARY)

#使用共享模块的NDK项目1的Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := module1
LOCAL_SRC_FILES := module1.c
LOCAL_SAHRED_LIBRARIES := AVI
include $(BUILD_SHARED_LIBRARY)
$(call import-module, transcode/AVI)

#使用共享模块的NDK项目2的Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := module2
LOCAL_SRC_FILES := module2.c
LOCAL_SAHRED_LIBRARIES := AVI
include $(BUILD_SHARED_LIBRARY)
$(call import-module, transcode/AVI)

7.使用预编译库

1.想在不发布源代码的情况下降模块发布给他人
2.想使用共享模块的预编译版来加速编译过程

#使用预编译共享模块的Android.mk文件
LOCAL_PATH := $(call my-dir)
#第三方预编译库
include $(CLEAR_VARS)
LOCAL_MODULE := AVI
LOCAL_SRC_FILES := libAVI.so
include $(PREBUILD_SHARED_LIBRARY)

8.编译独立的可执行文件

1.为了方便测试和进行快速开发,可以编译成可执行文件。不用打包成apk就可以复制到Android设备上直接执行
#独立可执行模块的Andriod.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := module
LOCAL_SRC_FILES := module.c
LOCAL_STAITC_LIBRAYIES := AVI
include $(BUILD_EXECUTABLE)

9.注意事项

1.假如我们本地库libhello-jni.so依赖于libTest.so(可以使用NDK下的ndk-depends查看so的依赖关系)
2.在Android 6.0版本之前,需要在加载本地库前先加载被依赖的so
3.在Android6.0版本之后,不能再使用预编译的动态库(静态库没问题)

# Android 6.0版本之前:
System.loadLibrary("Test");
System.loadLibrary("hello-jni");

# Android 6.0版本之后:
System.loadLibrary("hello-jni");

实例:
step1: 在src/main目录下新建ndk目录
在这里插入图片描述
step2:编写hello-jni.c和Android.mk
hellojni.c

#include<jni.h>

int test() {
    return 123;
}

jint Java_com_lcj_ndktest_MainActivity_nativeTest() {
    return test();
}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hello-jni

LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

step3: 定义native方法

public class MainActivity extends AppCompatActivity {
	// 加载so
    {
        System.loadLibrary("hello-jni");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = findViewById(R.id.tv_text);
        textView.setText(nativeTest() + "");
    }
	// 定义native
    native int nativeTest();
}

step4: 配置app下的build.gradle

defaultConfig {
        applicationId "com.lcj.ndktest"
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        // 指定源文件的编译方式以及配置编译选项
        externalNativeBuild {
            ndkBuild {
                abiFilters "arm64-v8a","armeabi-v7a"
            }
        }
    }

    // 配置编译脚本路径
    externalNativeBuild {
        ndkBuild {
            path "src/main/ndk/Android.mk"
        }
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值