AS使用ndkbuild创建cpp工程记录

AS使用ndkbuild创建cpp工程记录

由于需要使用c++和.so库,所以必须要使用ndk方式,记录下过程。

现状是,我们得到第三方的.so和一些头文件类,需要使用这些类和函数来完成我们的功能,比如说机器学习算法运算库,但如何使用这些在.so内的函数呢?需要把.so和头文件加载到项目中,这就需要使用Android.mkApplication.mk文件来编译了,==需要注意的是这仅限于使用ndk-build命令编译的项目==,因为现在AS2.2后默认使用了cmake来编译native项目。

官网对Android.mk文件介绍这个文件的编写之后会讲到。

.so文件和头文件放在哪?

应该统一放在app/src/main/jni路径下,包括需要的jni接口文件,也应该放在jni目录下,保持统一。

Android.mk和Application.mk文件

  • LOCAL_PATH:表示文件在当前项目中的位置my-dir是一个函数,由构建系统提供的。
  • CLEAR_VARS:也是由构建系统提供的变量,指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量,例如 LOCAL_MODULE、LOCAL_SRC_FILES 和 LOCAL_STATIC_LIBRARIES,==但是不会清除LOCAL_PATH变量==
  • LOCAL_MODULE:存储你需要编译模块的名字,比如native-lib,最后打出的.so库名字便是libnative-lib.so(会默认在名字前加上lib字段)
  • LOCAL_SRC_FILES: 指定文件在哪,比如目前例子上就是native-lib.cpp
  • include $(BUILD_SHARED_LIBRARY):帮助系统将所有内容连接到一起

其他内容可以参考Google官方文档;我这里说下需要注意的点。

需要注意的问题

  1. 如果是第三方库和jni接口文件都在jni目录下(这也是开头提到的推荐目录),此时就可以只写一个Android.mk文件,这个文件包括了添加第三方.so库和.hpp头文件,和编译自己的jni cpp函数库。不然就需要写两个Android.mk文件,一个用于加载第三方.so到项目中,另一个用于编译生成自己写的jni接口cpp库(即libnative-lib.so)。
  2. 两个Android.mk文件的区别:
    • 添加.so库的Android.mk需要指定
      mkinclude $(CLEAR_VARS)LOCAL_MODULE := nnLOCAL_SRC_FILES := $(LOCAL_PATH)/armeabi-v7a/lib/libnn.soLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/armeabi-v7a/include# 需要指定是预编译的库,加如下标识include $(PREBUILT_SHARED_LIBRARY)
    • 编译自己的jni接口cpp文件
      mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := native-libLOCAL_SRC_FILES := native-lib.cppLOCAL_LDLIBS := -llog -landroidLOCAL_CFLAGS += -std=c++11# 此处即上述所编译好的第三方库,这里引用一下LOCAL_SHARED_LIBRARIES := nninclude $(BUILD_SHARED_LIBRARY)
  3. 两个文件如果写在一个Android.mk文件中,顺序应该是先写自己jni接口库mk,再写第三方.so的预编译库mk。
  4. Application.mk文件比较统一,一般大家的都差不多,可以直接拿来用,不需要修改什么地方,需要注意的点可能有如下几点:
    mkAPP_PLATFORM := android-15APP_ABI := armeabi-v7aNDK_TOOLCHAIN_VERSION=4.9APP_PIE := falseAPP_STL := gnustl_staticAPP_CFLAGS := -O3 -Wall -pipe \ -ffast-math \ -fstrict-aliasing -Werror=strict-aliasing \ -Wno-psabi -Wa,--noexecstack \ -DANDROID -DNDEBUG \ -std=c++11
    • APP_PLATFORM版本需要和在AndroidManifest.xml中的对应,比如说我这里指定是15,则需要在xml中也指定至少15版本:
      xml<uses-sdkandroid:minSdkVersion="15"android:targetSdkVersion="26" />
    • 尽量使用APP_STL := gnustl_static该版本的c++支持最好,不会有标准库找不到问题
    • 如果还需要有支持c++11,则需要指定APP_CFLAGS := -std=c++11,该句话在Android.mk中最好也加上,可以保证不会有c++11库函数找不到问题。

Gradle文件的调整

由于现在AS创建native项目默认都使用cmake了,Gradle也是按照cmake配置的,如果要使用ndk-build也需要修改一下Gradle。

  1. 把原来cmake的地方换成ndkBuild,对是ndkBuild,这个和执行的命令不一样,是一个配置函数。

            externalNativeBuild {            ndkBuild {                // Sets optional flags for the C compiler.                cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"
    
                // Sets a flag to enable format macro constants for the C++ compiler.            cppFlags "-D__STDC_FORMAT_MACROS"        }    }

  2. android{}下添加如下,指定makefile文件路径,这是必须的:

        externalNativeBuild {        ndkBuild {            path "src/main/jni/Android.mk"        }    }
  3. 需要指定编译的版本,由于Android真机通常只需要armeabi-v7a,所以只编译该版本即可,不需要编译arm64版本,可以在android{}下的buildTypes{}下指定编译版本使用abiFilter函数:
        buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘            ndk {                abiFilter "armeabi-v7a"            }        }
    
        debug {        minifyEnabled false        ndk {            abiFilter "armeabi-v7a"        }    }}

  4. 如果出现More than one file was found with OS independent path问题,需要去除如下指定,可以看我的这篇文章AS中ndk-build方式cpp问题集锦
    gradle// 注释掉如下代码 sourceSets.main {// jniLibs.srcDir(‘src/main/libs‘)}

原文地址:https://www.cnblogs.com/zhcnick/p/8907123.html

时间: 2024-10-10 17:48:58

AS使用ndkbuild创建cpp工程记录的相关文章

使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引擎之前,我们可以不那么方便地在我们创建的工程里调试Cocos2d-x的代码,当我们使用了整合后的Cocos引擎,调试Cocos2d-x的代码就变得更加,非常不方便了! 使用Cocos2d-x创建的项目,在最先的版本必须是在Cocos2d-x引擎的目录下,放到其他的位置需要进行各种麻烦的设置,诸如头文

bat文件自动创建cocos2dx 工程

1. 写在开头 本人写了一个自动创建cocos2dx工程的脚本..bat文件,会修正Application.mk 文件,并且在桌面创建打开项目目录的快捷方式. 使用条件:1. 在本地计算机中已安装python 2.7.6 版本,并将python安装目录加入到 PATH环境变量中. 2. 根据自己的cocos2dx与ndk安装目录,更改脚本最初COCOS2DX_DIR.NDK_DIR变量. 3.本脚本只创建c++语言的cocos2dx工程,创建成功后仍需手动配置c++ build目录. 个人写的脚

git使用(一):如何创建一个工程、提交代码

1. 在git server端如何创建一个工程 (1) su git (2) mkdir linux-git.git (3) cd linux-git.git (4) git init --bare (5) exit 2. 在clinet端如何clone.提交代码 (1) git clone [email protected]:/home/prj_git/linux-git.git (2) cd linux-git (3) cp ../linux-3.18.3 ./ -rf (4) git ad

创建Android工程

一个Android项目包含了这个App里面的所有源代码. 这篇文章展示了怎么通过AndroidStudio或者SDKTool里面的命令行,来创建一个全新的项目. Note: 你应该已经安装了AndroidStudio或者AndroidSDK,没有的话去上一篇文章里看吧. 使用Android Studio创建项目 1.使用Android Studio创建新项目: 如果没有已经打开的项目,那么在欢迎界面,点击Start a new Android Studio project. 如果已经有项目打开了

eclipse 创建Makefile工程生成多个执行文件

1.创建Makefile工程 2.创建inc src Debug 目录 用于存放头文件源文件 3.编写Makefile 需要在有源文件的目标天剑Makefile文件,如下给出一个生成两个target的模板 ###################################### # ####################################### #source file #源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件 SOURCE := $(wildcar

设置通过Maven创建的工程的JDK的版本,更改conf/settings.xml

eclipse提示警告如下: Build path specifies execution environment J2SE-1.5. There are no JREs installed in the workspace that are strictly compatible with this environment. 1.打开settings.xml文件 2.找到profiles标签 3.加入如下配置: <profile> <id>jdk1.8</id> &l

提高Intellij创建Maven工程的速度

按照默认的方式创建Maven工程的时候会发现Maven插件加载的很慢如下 解决方法:在创建的过程中,在Properties中添加一个参数archetypeCatalog=internal . 因为archetypeCatalog表示插件使用的archetype元数据,不加这个参数时默认为remote,local, 即中央仓库archetype元数据,由于中央仓库的archetype太多了,所以导致很慢,指定internal来表示仅使用内部元数据.

maven创建web工程Spring配置文件找不到问题解决方案

使用maven创建web工程,将Spring配置文件applicationContext.xml放在src/resource下,用eclipse编译时提示class path resource [applicationContext.xml] cannot be opened because it does not exist错误.但是用mvn clean package命令编译时成功的.web.xml配置的如下 <context-param><param-name>context

DuiVision开发教程(1)-创建DuiVision工程

DuiVision的源代码工程有两种类型:主程序和插件工程,可以通过人工方式创建DuiVision工程,也可以通过Visual Studio向导自动创建工程. 人工创建主程序的方法 1.创建一个基于DuiVision的界面程序是比较简单的,在VC中创建一个MFC对话框工程,注意工程要使用Unicode库: 工程创建之后,需要将默认对话框资源中的几个按钮和文字都删除,变成一个干净的对话框资源: 2.设置DuiVision的头文件和lib文件目录 将DuiVision的头文件和lib文件放在某个位置