文章目录
Bash Shell语法入门
- Bash Shell编程入门 https://www.jianshu.com/p/e1c8e5bfa45e
- Bash 脚本教程:基本语法 https://wangdoc.com/bash/grammar.html
交叉编译设置
基本配置
-
指定编译后的文件的安装目录
--prefix=$PREFIX
-
指定编译后使用文件的平台
--host=arm-linux # arm --host=x86-linux # x86
-
当前目录用
$(pwd)
表示 -
变量赋值时等号两边不能有空格
设置环境变量
-
对所有用户有效:用vim在文件/etc/profile文件中增加变量
sudo vi /etc/profile # 追加 export NDK="~/Downloads/android-ndk-r21b" export PATH=$PAHT:$ANDROID_NDK # 重启 source /etc/profile
-
对当前用户有效:
vi ~/.bashrc
其他同上 -
对当前shell窗口有效:
export var=value
常用的环境变量
这些变量都可以打印查看,比如
$ echo $PWD
BASH
Bash Shell的全路径CDPATH
用于快速进入某个目录。PATH
决定了shell将到哪些目录中寻找命令或程序HOME
当前用户主目录PWD
当前目录HISTSIZE
历史记录数LOGNAME
当前用户的登录名HOSTNAME
当前主机的名称SHELL
当前用户Shell类型LANGUGE
语言相关的环境变量,多语言可以修改此环境变量MAIL
当前用户的邮件存放目录
使用 ndk-build 编译C/C++代码
简述
什么是NDK?
Android官方为了方便应用层开发,将底层的交叉编译工具链进行了整理,同时,也对编译和链接整个过程进行了优化。这个交叉编译的工具集合就叫NDK。
NDK的全称是Native Development Kit, 是一套工具原生开发套件,使你能够在 Android 应用中使用 C 和 C++ 代码,并提供众多平台库,你可使用这些平台库管理原生 Activity 和访问物理设备组件,例如传感器和轻触输入。
为什么使用NDK?
当我们需要完成以下一个或多个事项,那么 NDK 就能派上用场:
- 提高应用的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
- 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
- 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
- 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
什么是JNI?
JNI的全称是Java Native Interface,是一个 Java 原生接口框架,它提供了若干的API实现了Java和其他语言的通信(主要是C和C++),Java 代码通过JNI框架就可以直接调用原生库中的函数。
so文件是什么?
so其实就是shared object的意思,so文件也是ELF格式文件,是类似于DLL的共享库(动态库),能够节约资源,加快速度,代码升级简化。在android的JNI中,要先将相应的C/C++语言打包成so库,然后导入到lib文件夹中供java调用。
.a文件是什么?
.a 就是archive(档案), 也就相当于windows的VC下编译的lib文件, 俗称静态库文件.
安装NDK
下载
- 最新的NDK下载路径:https://developer.android.google.cn/ndk/downloads/
- 历史版本路径: https://developer.android.google.cn/ndk/downloads/older_releases.html
配置环境变量
- 解压
- 添加path
sudo vi ~/.bashrc
export ANDROID_NDK="~/Downloads/android-ndk-r21b-linux-x86_64/android-ndk-r21b"
export PATH="${PATH}:platform-tools:$ANDROID_NDK"
source ~/.bashrc
- 验证配置是否成功
ndk-build -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
使用 ndk-build 编译C/C++代码
使用 NDK 编译代码主要有三种方法:
- 基于 Make 的 ndk-build
- CMake
- 独立工具链,用于与其他构建系统集成,或与基于 configure 的项目搭配使用
这里使用第一种
构建项目
demo_project/
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── include
│ │ ├── c_api.h
│ │ ├── c_api_internal.h
│ │ ├── common.h
│ │ ├── ...
│ ├── libs
│ │ ├── libc++_shared.so
│ │ ├── ...
│ └── main.cpp
├── libs
└── obj
这里是新建了一个项目demo_project
,必须包含jni
文件夹,其中有着Android.mk
, Application.mk
Android.mk
Android.mk 文件位于项目/jni/
目录中,用于向构建系统描述 源文件 和 共享库。
https://developer.android.google.cn/ndk/guides/android_mk
-
指定源文件的位置:宏函数 my-dir 将返回Android.mk 的所在目录,因此要把源文件
main.cpp
放在这个目录下LOCAL_PATH := $(call my-dir)
-
声明系统变量
include $(CLEAR_VARS)
-
指定构建模块的名称,唯一性,不含空格
LOCAL_MODULE := demo
-
列出需要包含的源文件,空格分隔多个文件
LOCAL_SRC_FILES := main.cpp
-
列出包含路径
LOCAL_C_INCLUDES := $(LOCAL_PATH)/modules
-
指定构建类型
include $(BUILD_EXECUTABLE) # 可执行文件 include $(BUILD_SHARED_LIBRARY) # .so 类似动态链接库dll include $(BUILD_STATIC_LIBRARY) # .a 类似静态库lib
示例代码:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := demo
LOCAL_SRC_FILES := main.cpp
include $(BUILD_EXECUTABLE)
Application.mk
Application.mk 也是位于/项目/jni/
目录,用于指定 ndk-build 的项目级设置
-
APP_ABI
指定目标目标指令集的 Application Binary Interface
-
APP_PLATFORM
指定所面向的 Android API 级别. 如API级别 android-22 对应了Android 5.1的系统映像android-22
Android 5.1系统映像android-29
Android 10 系统映像
-
APP_STL
指定使用的标准模板库c++_shared, c++static, none, or system
-
APP_CXXFLAGS
传给CXX编译器的FLAGfrtti
运行时类型识别(动态编联)fexceptions
异常支持-std=c++11
标准
编译
cd demo_project
ndk-build
ADB 常用命令
win 下 push
adb shell mkdir /sdcard/xxx/
adb push test224.png /sdcard/xxx/
adb push test448.png /sdcard/xxx/
adb push libxxxxx.so /data/local/tmp/
adb push run_demo /data/local/tmp/
adb shell chmod +x /data/local/tmp/run_demo
adb push run.sh /data/local/tmp/
adb shell chmod +x /data/local/tmp/run.sh
pause
执行Bash 命令
file name: run.sh
chmod +x /sdcard/CoreAI/run_demo
filesPath=$1
imageName=$2
modelName=$3
./run_demo $filesPath $imageName $modelName $(nproc)
#useage: /data/local/tmp/run.sh /sdcard/CoreAI/ test224.png YoloV3Tiny
一定要放在 /data/local/tmp/
目录才可以执行