Browse Source

!14132 fix cmsis gesture of pooling opcoder

From: @zoloft
Reviewed-by: @wangchengyuan
Signed-off-by: @wangchengyuan
tags/v1.2.0
mindspore-ci-bot Gitee 5 years ago
parent
commit
bc76d35a42
12 changed files with 166 additions and 119 deletions
  1. +3
    -4
      mindspore/lite/micro/coder/generator/component/const_blocks/model.cc
  2. +1
    -1
      mindspore/lite/micro/coder/opcoders/cmsis-nn/int8/pooling_int8_coder.cc
  3. +2
    -1
      mindspore/lite/micro/coder/opcoders/nnacl/fp32/convolution_fp32_coder.cc
  4. +10
    -3
      mindspore/lite/micro/coder/opcoders/nnacl/int8/conv2d_int8_coder.cc
  5. +12
    -5
      mindspore/lite/micro/coder/opcoders/nnacl/int8/matmul_base_int8_coder.cc
  6. +2
    -0
      mindspore/lite/micro/coder/opcoders/nnacl/int8/matmul_base_int8_coder.h
  7. +3
    -2
      mindspore/lite/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_stream_utils.cc
  8. +8
    -0
      mindspore/lite/micro/coder/operator_library/wrapper/int8/matmul_int8_wrapper.c
  9. +2
    -0
      mindspore/lite/micro/example/mnist_stm32f746/README.md
  10. +2
    -1
      mindspore/lite/micro/example/mnist_x86/mnist.sh
  11. +2
    -2
      mindspore/lite/micro/example/mobilenetv2/README.md
  12. +119
    -100
      mindspore/lite/micro/example/mobilenetv2/mobilenetv2.sh

+ 3
- 4
mindspore/lite/micro/coder/generator/component/const_blocks/model.cc View File

@@ -20,7 +20,7 @@ namespace mindspore::lite::micro {

const char *model_header = R"RAW(
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,12 +66,11 @@ class MModel : public Model {

Model *Model::Import(const char *model_buf, size_t size) {
MS_NULLPTR_IF_NULL(model_buf);
MModel *model = new (std::nothrow) MModel();
MS_NULLPTR_IF_NULL(model);
if (size == 0) {
delete model;
return nullptr;
}
MModel *model = new (std::nothrow) MModel();
MS_NULLPTR_IF_NULL(model);
model->buf = reinterpret_cast<char *>(malloc(size));
if (model->buf == nullptr) {
delete model;


+ 1
- 1
mindspore/lite/micro/coder/opcoders/cmsis-nn/int8/pooling_int8_coder.cc View File

@@ -69,7 +69,7 @@ int PoolingInt8Coder::SetParameters() {
dim_src_height_ = input_tensor_->Height();
dim_src_width_ = input_tensor_->Width();
dim_dst_height_ = output_tensor_->DimensionSize(1);
dim_src_width_ = output_tensor_->DimensionSize(2);
dim_dst_width_ = output_tensor_->DimensionSize(2);
ch_src_ = input_tensor_->Channel();

stride_height_ = pooling_parameter_->stride_h_;


+ 2
- 1
mindspore/lite/micro/coder/opcoders/nnacl/fp32/convolution_fp32_coder.cc View File

@@ -117,7 +117,8 @@ int ConvolutionFP32Coder::DoCode(CoderContext *const context) {
"PreSum4x16Int8Peroc.S",
"PreSum4x16Int8Pert.S",
"IndirectGemmInt16to32_8x4.S",
"MatmulInt8.S"};
"MatmulInt8.S",
"MatmulFp32Opt12x4.S"};
} else if (target_ == kARM64) {
asmFiles = {"MatmulFp32.S", "MatmulFp32Opt.S", "PreSum4x16Int8Peroc.S", "MatVecMulFp32.S",
"PreSum4x16Int8Peroc.S", "PreSum4x16Int8Pert.S", "IndirectGemmInt16to32_8x4.S", "MatmulInt8.S"};


+ 10
- 3
mindspore/lite/micro/coder/opcoders/nnacl/int8/conv2d_int8_coder.cc View File

@@ -203,9 +203,16 @@ int Conv2DINT8Coder::DoCode(CoderContext *const context) {
code.CodeFunction("memset", matmul_packed_input_, 0, matmul_packed_input_size_);
code.CodeStruct("conv_param", *conv_param_);

code.CodeBaseStruct("ConvolutionInt8Args", kRunArgs, input_tensor_, packed_input_, matmul_packed_input_,
packed_weight_, bias_data_, output_tensor_, filter_zp_ptr_, input_sum_,
"(ConvParameter *)&conv_param", matmul_func_, "GetSupportOptFlag()");
if (target_ == kARM64) {
code.CodeBaseStruct("ConvolutionInt8Args", kRunArgs, input_tensor_, packed_input_, matmul_packed_input_,
packed_weight_, bias_data_, output_tensor_, filter_zp_ptr_, input_sum_,
"(ConvParameter *)&conv_param", matmul_func_, "GetSupportOptFlag()");
} else {
code.CodeBaseStruct("ConvolutionInt8Args", kRunArgs, input_tensor_, packed_input_, matmul_packed_input_,
packed_weight_, bias_data_, output_tensor_, filter_zp_ptr_, input_sum_,
"(ConvParameter *)&conv_param", matmul_func_, support_optimize_);
}

if (support_parallel_) {
code.CodeFunction(kParallelLaunch, gThreadPool, "ConvolutionInt8Run", kRunArgsAddr, gThreadNum);
} else {


+ 12
- 5
mindspore/lite/micro/coder/opcoders/nnacl/int8/matmul_base_int8_coder.cc View File

@@ -58,11 +58,11 @@ int MatMulBaseInt8Coder::InitTmpBuffer() {
MatMulBaseInt8Coder::~MatMulBaseInt8Coder() { FreeQuantParam(); }

void MatMulBaseInt8Coder::ResizeParameter() {
param_->row_align_ = UP_ROUND(param_->row_, C4NUM);
param_->col_align_ = UP_ROUND(param_->col_, C4NUM);
param_->row_align_ = UP_ROUND(param_->row_, row_tile_);
param_->col_align_ = UP_ROUND(param_->col_, col_tile_);
param_->deep_16_ = UP_ROUND(param_->deep_, C16NUM);
thread_count_ = MSMIN(param_->op_parameter_.thread_num_, UP_DIV(param_->col_align_, C4NUM));
thread_stride_ = UP_DIV(UP_DIV(param_->col_align_, C4NUM), thread_count_);
thread_count_ = MSMIN(param_->op_parameter_.thread_num_, UP_DIV(param_->col_align_, col_tile_));
thread_stride_ = UP_DIV(UP_DIV(param_->col_align_, col_tile_), thread_count_);
}

void MatMulBaseInt8Coder::FreeQuantParam() {
@@ -138,6 +138,12 @@ int MatMulBaseInt8Coder::InitQuantParam() {
void MatMulBaseInt8Coder::InitParameter() {
param_->a_const_ = (input_tensor_ != nullptr);
param_->b_const_ = (filter_tensor_ != nullptr);
row_tile_ = C4NUM;
if (target_ == kARM32A) {
col_tile_ = C2NUM;
} else {
col_tile_ = C4NUM;
}
}

int MatMulBaseInt8Coder::InitBias() {
@@ -189,6 +195,7 @@ int MatMulBaseInt8Coder::DoCode(CoderContext *const context) {
param_->deep_, param_->col_, param_->col_align_, param_->deep_16_, quant_.input_.zp_,
"init_filter_zp", bias_ptr_, param_->b_transpose_, filter_per_channel_);
} else {
code.CodeArray("init_filter_zp", quant_.filter_zp_, weight_quant_num_, false);
code.CodeFunction("InitInt8MatrixB", filter_tensor_, weight_bias_sums_, pack_b_ptr_, param_->batch, param_->deep_,
param_->col_, param_->col_align_, param_->deep_16_, quant_.input_.zp_, "init_filter_zp",
bias_ptr_, param_->b_transpose_, filter_per_channel_);
@@ -216,7 +223,7 @@ int MatMulBaseInt8Coder::DoCode(CoderContext *const context) {
std::string batch_b_ptr_str = pack_b_ptr_str + "+" + std::to_string(i * param_->col_align_ * param_->deep_16_);
std::string batch_c_ptr_str = c_ptr_str + "+" + std::to_string(i * param_->row_ * param_->col_);

int stride = thread_stride_ * C4NUM;
int stride = thread_stride_ * col_tile_;
int cur_stride = task_id * stride;
int res_stride = param_->col_ - cur_stride;
int cur_oc = MSMIN(stride, res_stride);


+ 2
- 0
mindspore/lite/micro/coder/opcoders/nnacl/int8/matmul_base_int8_coder.h View File

@@ -65,6 +65,8 @@ class MatMulBaseInt8Coder : public OperatorCoder {

private:
int weight_quant_num_{0};
int row_tile_{C4NUM};
int col_tile_{C4NUM};
};
} // namespace mindspore::lite::micro::nnacl
#endif // MINDSPORE_LITE_MICRO_CODER_OPCODERS_NNACL_INT8_MATMUL_BASE_INT8_CODER_H_

+ 3
- 2
mindspore/lite/micro/coder/opcoders/serializers/nnacl_serializer/nnacl_stream_utils.cc View File

@@ -31,9 +31,10 @@ std::ostream &operator<<(std::ostream &code, const ::QuantArg &quant_arg) {
return code;
}

std::ostream &operator<<(std::ostream &code, const OpParameter &tile) {
std::ostream &operator<<(std::ostream &code, const OpParameter &parameter) {
code << "{ \"\""
<< ", " << tile.type_ << ", " << gThreadNum << "}";
<< ", " << std::boolalpha << parameter.infer_flag_ << ", " << parameter.type_ << ", " << gThreadNum << ", "
<< parameter.quant_type_ << "}";
return code;
}



+ 8
- 0
mindspore/lite/micro/coder/operator_library/wrapper/int8/matmul_int8_wrapper.c View File

@@ -38,10 +38,18 @@ void InitInt8MatrixB(int8_t *weight_ptr, int32_t *weight_bias_sums_batch_, int8_
int8_t *cur_b_pack = dst_ptr + i * col_align * deep_16;
int32_t *cur_sums = weight_bias_sums_batch_ + i * col_align;
if (b_transpose) {
#ifdef ENABLE_ARM32
RowMajor2Row2x16MajorInt8(cur_b, cur_b_pack, col, deep);
#else
RowMajor2Row16x4MajorInt8(cur_b, cur_b_pack, col, deep);
#endif
CalcWeightBiasSums(cur_b, deep, col, input_zp, weight_zp, bias_ptr, cur_sums, ColMajor, filter_per_channel);
} else {
#ifdef ENABLE_ARM32
RowMajor2Col16x2MajorInt8(cur_b, cur_b_pack, deep, col);
#else
RowMajor2Col16x4MajorInt8(cur_b, deep, col, cur_b_pack);
#endif
CalcWeightBiasSums(cur_b, deep, col, input_zp, weight_zp, bias_ptr, cur_sums, RowMajor, false);
}
}


+ 2
- 0
mindspore/lite/micro/example/mnist_stm32f746/README.md View File

@@ -64,6 +64,8 @@
```

> 在使用过程中,我们注意到引入Softmax相关的CMSIS算子文件时,头文件中需要加入`arm_nnfunctions.h`,使用者可以稍作注意。

生成代码工程目录如下:

模型推理对外API头文件可由mindspore团队发布的[Release包](https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/downloads.html)中获取。


+ 2
- 1
mindspore/lite/micro/example/mnist_x86/mnist.sh View File

@@ -71,7 +71,7 @@ gen_mnist() {
${CODEGEN_PATH}/codegen --codePath=${BASEPATH}/build --modelPath=${BASEPATH}/build/${MNIST_FILE}
}

mkdir -p build
mkdir -p ${BASEPATH}/build

get_version
download_inference
@@ -85,6 +85,7 @@ if [[ "${GEN}" == "ON" ]]; then
fi

# 1. build benchmark
rm -rf ${BASEPATH}/build/benchmark
mkdir -p ${BASEPATH}/build/benchmark && cd ${BASEPATH}/build/benchmark || exit 1
cmake -DPKG_PATH=${PKG_PATH} ${BENCHMARK_PATH}
make


+ 2
- 2
mindspore/lite/micro/example/mobilenetv2/README.md View File

@@ -86,7 +86,7 @@ mkdir mobilenetv2/build && cd mobilenetv2/build

```bash
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="${ANDRIOD_NDK}/build/cmake/android.toolchain.cmake" \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_TOOLCHAIN_NAME="aarch64-linux-android-clang" \
-DANDROID_NATIVE_API_LEVEL="19" \
@@ -99,7 +99,7 @@ make

```bash
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="${ANDRIOD_NDK}/build/cmake/android.toolchain.cmake" \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="armeabi-v7a" \
-DANDROID_TOOLCHAIN_NAME="clang" \
-DANDROID_NATIVE_API_LEVEL="19" \


+ 119
- 100
mindspore/lite/micro/example/mobilenetv2/mobilenetv2.sh View File

@@ -15,111 +15,130 @@
# ============================================================================
set -e

CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
MINDSPORE_ROOT_DIR=${${CURRENT_DIR}%%/mindspore/lite/micro/example/mobilenetv2}
usage()
{
echo "Usage:"
echo "bash build.sh [-I arm64|arm32]"
echo "Options:"
echo " -I download and build for arm64 or arm32, default arm64"
}

OUTPUT_DIR=${1:-${MINDSPORE_ROOT_DIR}/output}
THREAD_NUM=${2:-32}
MODULE_NAME=mobilenetv2
OUTPUT_IR=Reshape-64.ir
CALIB_OUT=${CURRENT_DIR}/Reshape-64.out
LITE_PLATFORM="arm64"
while getopts 'I:' OPT
do
OPTARG=$(echo ${OPTARG} | tr '[A-Z]' '[a-z]')
case $OPT in
I)
if [[ "$OPTARG" == "arm64" ]]; then
LITE_PLATFORM="arm64"
elif [[ "$OPTARG" == "arm32" ]]; then
LITE_PLATFORM="arm32"
else
echo "-I parameter must be arm64 or arm32"
exit 1
fi
;;
*)
echo "Unknown option ${opt}!"
usage
exit 1
esac
done

echo "current dir is: ${CURRENT_DIR}"
echo "packed output dir is :${OUTPUT_DIR}"
BASEPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
MINDSPORE_ROOT_DIR=${BASEPATH%%/mindspore/lite/micro/example/mobilenetv2}

if [ ! -d "${OUTPUT_DIR}" ]; then
echo "folder ${OUTPUT_DIR} does not exist"
return 1
fi
echo "current dir is: ${BASEPATH}"

MOBILE_NAME=mobilenetv2
MOBILE_FILE=${MOBILE_NAME}.ms

get_version() {
local VERSION_HEADER=${MINDSPORE_ROOT_DIR}/mindspore/lite/include/version.h
local VERSION_MAJOR=$(grep "const int ms_version_major =" ${VERSION_HEADER} | tr -dc "[0-9]")
local VERSION_MINOR=$(grep "const int ms_version_minor =" ${VERSION_HEADER} | tr -dc "[0-9]")
local VERSION_REVISION=$(grep "const int ms_version_revision =" ${VERSION_HEADER} | tr -dc "[0-9]")
VERSION_STR=${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
}

download_inference() {
if [[ "${LITE_PLATFORM}" == "arm64" ]]; then
local ARM_NAME=aarch64
else
local ARM_NAME=aarch32
fi
MINDSPORE_FILE_NAME="mindspore-lite-${VERSION_STR}-inference-android-${ARM_NAME}"
local MINDSPORE_FILE="${MINDSPORE_FILE_NAME}.tar.gz"
local MINDSPORE_LITE_DOWNLOAD_URL="https://ms-release.obs.cn-north-4.myhuaweicloud.com/${VERSION_STR}/MindSpore/lite/release/linux/${MINDSPORE_FILE}"

# rm if already exist
WORKSPACE=${CURRENT_DIR}/build
rm -rf ${WORKSPACE}
mkdir ${WORKSPACE} || exit 1
PROJECT_DIR=${WORKSPACE}/${MODULE_NAME}

compare_output() {
local OUTPUT_FILE=$1
local CALIB_FILE=$2
if [[ ! -f "${OUTPUT_FILE}" || ! -f "${CALIB_FILE}" ]]; then
echo "file ${OUTPUT_FILE}, ${CALIB_FILE} does not exist, pwd $(pwd)"
exit 1
fi
lines=$(cat ${CALIB_FILE} | wc -l)
for ((i = 1; i <= $lines; i++)); do
line1=$(awk 'NR=="'${i}'"{print $0}' ${CALIB_FILE})
line2=$(awk 'NR=="'${i}'"{print $0}' ${OUTPUT_FILE})
if [[ "${line1}" != "${line2}" ]]; then
echo -e "file ${OUTPUT_FILE}, ${CALIB_FILE}, compare failed! line: ${i}"
exit 1
if [ ! -e ${BASEPATH}/build/${MINDSPORE_FILE} ]; then
wget -c -O ${BASEPATH}/build/${MINDSPORE_FILE} --no-check-certificate ${MINDSPORE_LITE_DOWNLOAD_URL}
fi
done
echo -e "compare success, ${OUTPUT_FILE}, ${CALIB_FILE}"

tar xzvf ${BASEPATH}/build/${MINDSPORE_FILE} -C ${BASEPATH}/build/ || exit 1
rm ${BASEPATH}/build/${MINDSPORE_FILE} || exit 1
PKG_PATH=${BASEPATH}/build/${MINDSPORE_FILE_NAME}
}

# cp oplib and codegen
cp ${OUTPUT_DIR}/mindspore-lite-*-codegen-linux-x64.tar.gz ${WORKSPACE}/ || exit 1
cd ${WORKSPACE} || exit 1
tar -zxf mindspore-lite-*-codegen-linux-x64.tar.gz || exit 1
cd mindspore-lite-*-codegen-linux-x64 || exit 1
mv operator_library/ ${WORKSPACE}/ || exit 1
mv codegen ${WORKSPACE}/ || exit 1
cd -
rm -r mindspore-lite-*-codegen-linux-x64 || exit 1
rm mindspore-lite-*-codegen-linux-x64.tar.gz || exit 1

# convert model
cp ${OUTPUT_DIR}/mindspore-lite-*-converter-linux-x64.tar.gz ${WORKSPACE}/ || exit 1
cd ${WORKSPACE} || exit 1
tar -zxf mindspore-lite-*-converter-linux-x64.tar.gz || exit 1
rm mindspore-lite-*-converter-linux-x64.tar.gz || exit 1
cd mindspore-lite-*-converter-linux-x64 || exit 1
export LD_LIBRARY_PATH=./lib/:./third_party/protobuf/lib:./third_party/flatbuffers/lib:./third_party/glog/lib
converter/converter_lite --fmk=TFLITE \
--modelFile=${CURRENT_DIR}/mobilenet_v2_1.0_224_quant.tflite \
--outputFile=${WORKSPACE}/mobilenet_v2
cd -
rm -rf mindspore-lite-*-converter-linux-x64 || exit 1

# generate code
${WORKSPACE}/codegen --modelPath=${WORKSPACE}/mobilenet_v2.ms \
--moduleName=${MODULE_NAME} \
--isWeightFile=true \
--debugMode=true
rm codegen

if [ ! -d "${PROJECT_DIR}" ]; then
echo "folder ${PROJECT_DIR} does not exist"
return 1
fi
cd ${PROJECT_DIR} || exit 1

# 1. build static lib.a
echo -e "building static library"
mkdir -p src/build && cd src/build || exit 1
OP_HEADER_PATH=${WORKSPACE}/operator_library/include
OP_LIB=${WORKSPACE}/operator_library/lib/x86/libops.a
echo "Head Path: ${OP_HEADER_PATH}"
echo "Lib Path: ${OP_LIB}"
cmake -DCMAKE_BUILD_TYPE=Debug \
-DOP_LIB=${OP_LIB} \
-DOP_HEADER_PATH=${OP_HEADER_PATH} ..
make -j${THREAD_NUM}

# 2. build benchmark
cd ${PROJECT_DIR}/benchmark && mkdir -p build && cd build || exit 1
cmake -DMODEL_LIB="${PROJECT_DIR}/src/build/libnet.a" ..
make -j${THREAD_NUM}

echo "net file: ${PROJECT_DIR}/src/${MODULE_NAME}.net"
# 3. run benchmark
./benchmark ${CURRENT_DIR}/input_1_224_224_3_uint8.bin ${PROJECT_DIR}/src/${MODULE_NAME}.net
compare_output ${OUTPUT_IR} ${CALIB_OUT}

RET=$?
if [[ "${RET}" -eq 0 ]]; then
echo -e "run benchmark success: ${MODULE_NAME}"
download_mobile() {
local MOBILE_DOWNLOAD_URL=https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_imagenet/r1.2/${MOBILE_FILE}

if [ ! -e ${BASEPATH}/build/${MOBILE_FILE} ]; then
wget -c -O ${BASEPATH}/build/${MOBILE_FILE} --no-check-certificate ${MOBILE_DOWNLOAD_URL}
fi
}

gen_mobile() {
local CODEGEN_FILE_NAME="mindspore-lite-${VERSION_STR}-inference-linux-x64"
local CODEGEN_FILE="${CODEGEN_FILE_NAME}.tar.gz"
local CODEGEN_LITE_DOWNLOAD_URL="https://ms-release.obs.cn-north-4.myhuaweicloud.com/${VERSION_STR}/MindSpore/lite/release/linux/${CODEGEN_FILE}"

if [ ! -e ${BASEPATH}/build/${CODEGEN_FILE} ]; then
wget -c -O ${BASEPATH}/build/${CODEGEN_FILE} --no-check-certificate ${CODEGEN_LITE_DOWNLOAD_URL}
fi

tar xzvf ${BASEPATH}/build/${CODEGEN_FILE} -C ${BASEPATH}/build/ || exit 1
rm ${BASEPATH}/build/${CODEGEN_FILE} || exit 1
CODEGEN_PATH=${BASEPATH}/build/${CODEGEN_FILE_NAME}/tools/codegen
if [[ "${LITE_PLATFORM}" == "arm64" ]]; then
local TARGET=ARM64
else
local TARGET=ARM32A
fi
${CODEGEN_PATH}/codegen --codePath=${BASEPATH}/build --modelPath=${BASEPATH}/build/${MOBILE_FILE} --target=${TARGET}
}

mkdir -p ${BASEPATH}/build

get_version
download_inference

echo "downloading ${MOBILE_FILE}!"
download_mobile
echo "generating mobilenetv2"
gen_mobile
BENCHMARK_PATH=${BASEPATH}/build/${MOBILE_NAME}

# build benchmark
rm -rf ${BASEPATH}/build/benchmark
mkdir -p ${BASEPATH}/build/benchmark && cd ${BASEPATH}/build/benchmark || exit 1

if [[ "${LITE_PLATFORM}" == "arm64" ]]; then
echo "making arm64"
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="arm64-v8a" \
-DANDROID_TOOLCHAIN_NAME="aarch64-linux-android-clang" \
-DANDROID_NATIVE_API_LEVEL="19" \
-DMICRO_BUILD_ARM64=ON \
-DPKG_PATH=${PKG_PATH} ${BENCHMARK_PATH}
else
echo -e "run benchmark failed: ${MODULE_NAME}"
exit 1
fi
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="armeabi-v7a" \
-DANDROID_TOOLCHAIN_NAME="clang" \
-DANDROID_NATIVE_API_LEVEL="19" \
-DMICRO_BUILD_ARM32=ON \
-DPKG_PATH=${PKG_PATH} ${BENCHMARK_PATH}
fi
make

Loading…
Cancel
Save