├── images └── cat.jpg ├── models └── classification │ └── ReadMe.md ├── ncnn_linux ├── lib │ └── libncnn.a └── include │ ├── platform.h │ ├── layer_type_enum.h │ ├── layer_type.h │ ├── blob.h │ ├── benchmark.h │ ├── modelbin.h │ ├── cpu.h │ ├── paramdict.h │ ├── help.h │ ├── layer.h │ ├── net.h │ ├── opencv.h │ └── mat.h ├── ncnn_android ├── lib │ └── libncnn.a └── include │ ├── platform.h │ ├── layer_type_enum.h │ ├── layer_type.h │ ├── blob.h │ ├── benchmark.h │ ├── modelbin.h │ ├── cpu.h │ ├── paramdict.h │ ├── help.h │ ├── layer.h │ ├── net.h │ ├── opencv.h │ └── mat.h ├── examples ├── CMakeLists.txt └── classify.cpp ├── CMakeLists.txt ├── README.md └── android.toolchain.cmake /images/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BUG1989/ncnn-benchmark/HEAD/images/cat.jpg -------------------------------------------------------------------------------- /models/classification/ReadMe.md: -------------------------------------------------------------------------------- 1 | # Benchmark classification models 2 | https://pan.baidu.com/s/1o8ssmHc 3 | -------------------------------------------------------------------------------- /ncnn_linux/lib/libncnn.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BUG1989/ncnn-benchmark/HEAD/ncnn_linux/lib/libncnn.a -------------------------------------------------------------------------------- /ncnn_android/lib/libncnn.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BUG1989/ncnn-benchmark/HEAD/ncnn_android/lib/libncnn.a -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(ANDROID) 2 | set(PLATFORM ${CMAKE_CURRENT_SOURCE_DIR}/../ncnn_android) 3 | else() 4 | set(PLATFORM ${CMAKE_CURRENT_SOURCE_DIR}/../ncnn_linux) 5 | endif() 6 | 7 | include_directories(${PLATFORM}/include) 8 | link_directories(${PLATFORM}/lib) 9 | 10 | add_executable(ncnn_classify classify.cpp) 11 | target_link_libraries(ncnn_classify ncnn) 12 | 13 | install(TARGETS ncnn_classify 14 | RUNTIME DESTINATION bin 15 | LIBRARY DESTINATION lib 16 | ARCHIVE DESTINATION lib) -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.10) 2 | 3 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 4 | set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory") 5 | endif() 6 | message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") 7 | 8 | PROJECT(examples_ncnn) 9 | 10 | set(CMAKE_BUILD_TYPE release) 11 | set(CMAKE_VERBOSE_MAKEFILE OFF) 12 | 13 | find_package(OpenMP) 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 16 | 17 | if(ANDROID) 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") 19 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fopenmp -fPIE -pie") 20 | endif() 21 | 22 | add_subdirectory(examples) 23 | -------------------------------------------------------------------------------- /ncnn_linux/include/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | #define NCNN_BENCHMARK 0 22 | 23 | #endif // NCNN_PLATFORM_H 24 | -------------------------------------------------------------------------------- /ncnn_android/include/platform.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PLATFORM_H 16 | #define NCNN_PLATFORM_H 17 | 18 | #define NCNN_STDIO 1 19 | #define NCNN_STRING 1 20 | #define NCNN_OPENCV 0 21 | #define NCNN_BENCHMARK 0 22 | 23 | #endif // NCNN_PLATFORM_H 24 | -------------------------------------------------------------------------------- /ncnn_android/include/layer_type_enum.h: -------------------------------------------------------------------------------- 1 | AbsVal = 0, 2 | ArgMax = 1, 3 | BatchNorm = 2, 4 | Bias = 3, 5 | BNLL = 4, 6 | Concat = 5, 7 | Convolution = 6, 8 | Crop = 7, 9 | Deconvolution = 8, 10 | Dropout = 9, 11 | Eltwise = 10, 12 | ELU = 11, 13 | Embed = 12, 14 | Exp = 13, 15 | Flatten = 14, 16 | InnerProduct = 15, 17 | Input = 16, 18 | Log = 17, 19 | LRN = 18, 20 | MemoryData = 19, 21 | MVN = 20, 22 | Pooling = 21, 23 | Power = 22, 24 | PReLU = 23, 25 | Proposal = 24, 26 | Reduction = 25, 27 | ReLU = 26, 28 | Reshape = 27, 29 | ROIPooling = 28, 30 | Scale = 29, 31 | Sigmoid = 30, 32 | Slice = 31, 33 | Softmax = 32, 34 | Split = 33, 35 | SPP = 34, 36 | TanH = 35, 37 | Threshold = 36, 38 | Tile = 37, 39 | RNN = 38, 40 | LSTM = 39, 41 | BinaryOp = 40, 42 | UnaryOp = 41, 43 | ConvolutionDepthWise = 42, 44 | Padding = 43, 45 | Squeeze = 44, 46 | ExpandDims = 45, 47 | Normalize = 46, 48 | Permute = 47, 49 | PriorBox = 48, 50 | DetectionOutput = 49, 51 | Interp = 50, 52 | DeconvolutionDepthWise = 51, 53 | ShuffleChannel = 52, 54 | -------------------------------------------------------------------------------- /ncnn_linux/include/layer_type_enum.h: -------------------------------------------------------------------------------- 1 | AbsVal = 0, 2 | ArgMax = 1, 3 | BatchNorm = 2, 4 | Bias = 3, 5 | BNLL = 4, 6 | Concat = 5, 7 | Convolution = 6, 8 | Crop = 7, 9 | Deconvolution = 8, 10 | Dropout = 9, 11 | Eltwise = 10, 12 | ELU = 11, 13 | Embed = 12, 14 | Exp = 13, 15 | Flatten = 14, 16 | InnerProduct = 15, 17 | Input = 16, 18 | Log = 17, 19 | LRN = 18, 20 | MemoryData = 19, 21 | MVN = 20, 22 | Pooling = 21, 23 | Power = 22, 24 | PReLU = 23, 25 | Proposal = 24, 26 | Reduction = 25, 27 | ReLU = 26, 28 | Reshape = 27, 29 | ROIPooling = 28, 30 | Scale = 29, 31 | Sigmoid = 30, 32 | Slice = 31, 33 | Softmax = 32, 34 | Split = 33, 35 | SPP = 34, 36 | TanH = 35, 37 | Threshold = 36, 38 | Tile = 37, 39 | RNN = 38, 40 | LSTM = 39, 41 | BinaryOp = 40, 42 | UnaryOp = 41, 43 | ConvolutionDepthWise = 42, 44 | Padding = 43, 45 | Squeeze = 44, 46 | ExpandDims = 45, 47 | Normalize = 46, 48 | Permute = 47, 49 | PriorBox = 48, 50 | DetectionOutput = 49, 51 | Interp = 50, 52 | DeconvolutionDepthWise = 51, 53 | ShuffleChannel = 52, 54 | -------------------------------------------------------------------------------- /ncnn_android/include/layer_type.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_TYPE_H 16 | #define NCNN_LAYER_TYPE_H 17 | 18 | namespace ncnn { 19 | 20 | namespace LayerType { 21 | enum 22 | { 23 | #include "layer_type_enum.h" 24 | CustomBit = (1<<8), 25 | }; 26 | } // namespace LayerType 27 | 28 | } // namespace ncnn 29 | 30 | #endif // NCNN_LAYER_TYPE_H 31 | -------------------------------------------------------------------------------- /ncnn_linux/include/layer_type.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_TYPE_H 16 | #define NCNN_LAYER_TYPE_H 17 | 18 | namespace ncnn { 19 | 20 | namespace LayerType { 21 | enum 22 | { 23 | #include "layer_type_enum.h" 24 | CustomBit = (1<<8), 25 | }; 26 | } // namespace LayerType 27 | 28 | } // namespace ncnn 29 | 30 | #endif // NCNN_LAYER_TYPE_H 31 | -------------------------------------------------------------------------------- /ncnn_android/include/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /ncnn_linux/include/blob.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BLOB_H 16 | #define NCNN_BLOB_H 17 | 18 | #include 19 | #include 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Blob 25 | { 26 | public: 27 | // empty 28 | Blob(); 29 | 30 | public: 31 | #if NCNN_STRING 32 | // blob name 33 | std::string name; 34 | #endif // NCNN_STRING 35 | // layer index which produce this blob as output 36 | int producer; 37 | // layer index which need this blob as input 38 | std::vector consumers; 39 | }; 40 | 41 | } // namespace ncnn 42 | 43 | #endif // NCNN_BLOB_H 44 | -------------------------------------------------------------------------------- /ncnn_linux/include/benchmark.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BENCHMARK_H 16 | #define NCNN_BENCHMARK_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_BENCHMARK 21 | 22 | #include "mat.h" 23 | #include "layer.h" 24 | 25 | namespace ncnn { 26 | 27 | struct timeval 28 | { 29 | long tv_sec; 30 | long tv_usec; 31 | }; 32 | 33 | // get now timestamp 34 | struct timeval get_current_time(); 35 | 36 | // get the time elapsed in ms 37 | double time_elapsed(struct timeval start, struct timeval end); 38 | 39 | void benchmark(const Layer* layer, struct timeval start, struct timeval end); 40 | void benchmark(const Layer* layer, const Mat& bottom_blob, Mat& top_blob, struct timeval start, struct timeval end); 41 | 42 | } // namespace ncnn 43 | 44 | #endif // NCNN_BENCHMARK 45 | 46 | #endif // NCNN_BENCHMARK_H 47 | -------------------------------------------------------------------------------- /ncnn_android/include/benchmark.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_BENCHMARK_H 16 | #define NCNN_BENCHMARK_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_BENCHMARK 21 | 22 | #include "mat.h" 23 | #include "layer.h" 24 | 25 | namespace ncnn { 26 | 27 | struct timeval 28 | { 29 | long tv_sec; 30 | long tv_usec; 31 | }; 32 | 33 | // get now timestamp 34 | struct timeval get_current_time(); 35 | 36 | // get the time elapsed in ms 37 | double time_elapsed(struct timeval start, struct timeval end); 38 | 39 | void benchmark(const Layer* layer, struct timeval start, struct timeval end); 40 | void benchmark(const Layer* layer, const Mat& bottom_blob, Mat& top_blob, struct timeval start, struct timeval end); 41 | 42 | } // namespace ncnn 43 | 44 | #endif // NCNN_BENCHMARK 45 | 46 | #endif // NCNN_BENCHMARK_H 47 | -------------------------------------------------------------------------------- /ncnn_linux/include/modelbin.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MODELBIN_H 16 | #define NCNN_MODELBIN_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Net; 25 | class ModelBin 26 | { 27 | public: 28 | // element type 29 | // 0 = auto 30 | // 1 = float32 31 | // 2 = float16 32 | // 3 = uint8 33 | // load vec 34 | Mat load(int w, int type) const; 35 | // load image 36 | Mat load(int w, int h, int type) const; 37 | // load dim 38 | Mat load(int w, int h, int c, int type) const; 39 | 40 | // construct from weight blob array 41 | ModelBin(const Mat* weights); 42 | 43 | protected: 44 | mutable const Mat* weights; 45 | 46 | friend class Net; 47 | 48 | #if NCNN_STDIO 49 | ModelBin(FILE* binfp); 50 | FILE* binfp; 51 | #endif // NCNN_STDIO 52 | 53 | ModelBin(const unsigned char*& mem); 54 | const unsigned char*& mem; 55 | }; 56 | 57 | } // namespace ncnn 58 | 59 | #endif // NCNN_MODELBIN_H 60 | -------------------------------------------------------------------------------- /ncnn_android/include/modelbin.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MODELBIN_H 16 | #define NCNN_MODELBIN_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | namespace ncnn { 23 | 24 | class Net; 25 | class ModelBin 26 | { 27 | public: 28 | // element type 29 | // 0 = auto 30 | // 1 = float32 31 | // 2 = float16 32 | // 3 = uint8 33 | // load vec 34 | Mat load(int w, int type) const; 35 | // load image 36 | Mat load(int w, int h, int type) const; 37 | // load dim 38 | Mat load(int w, int h, int c, int type) const; 39 | 40 | // construct from weight blob array 41 | ModelBin(const Mat* weights); 42 | 43 | protected: 44 | mutable const Mat* weights; 45 | 46 | friend class Net; 47 | 48 | #if NCNN_STDIO 49 | ModelBin(FILE* binfp); 50 | FILE* binfp; 51 | #endif // NCNN_STDIO 52 | 53 | ModelBin(const unsigned char*& mem); 54 | const unsigned char*& mem; 55 | }; 56 | 57 | } // namespace ncnn 58 | 59 | #endif // NCNN_MODELBIN_H 60 | -------------------------------------------------------------------------------- /ncnn_android/include/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /ncnn_linux/include/cpu.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_CPU_H 16 | #define NCNN_CPU_H 17 | 18 | namespace ncnn { 19 | 20 | // test optional cpu features 21 | // neon = armv7 neon or aarch64 asimd 22 | int cpu_support_arm_neon(); 23 | // vfpv4 = armv7 fp16 + fma 24 | int cpu_support_arm_vfpv4(); 25 | // asimdhp = aarch64 asimd half precision 26 | int cpu_support_arm_asimdhp(); 27 | 28 | // cpu info 29 | int get_cpu_count(); 30 | 31 | // bind all threads on little clusters if powersave enabled 32 | // affacts HMP arch cpu like ARM big.LITTLE 33 | // only implemented on android at the moment 34 | // switching powersave is expensive and not thread-safe 35 | // 0 = all cores enabled(default) 36 | // 1 = only little clusters enabled 37 | // 2 = only big clusters enabled 38 | // return 0 if success for setter function 39 | int get_cpu_powersave(); 40 | int set_cpu_powersave(int powersave); 41 | 42 | // misc function wrapper for openmp routines 43 | int get_omp_num_threads(); 44 | void set_omp_num_threads(int num_threads); 45 | 46 | int get_omp_dynamic(); 47 | void set_omp_dynamic(int dynamic); 48 | 49 | } // namespace ncnn 50 | 51 | #endif // NCNN_CPU_H 52 | -------------------------------------------------------------------------------- /ncnn_android/include/paramdict.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PARAMDICT_H 16 | #define NCNN_PARAMDICT_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | // at most 20 parameters 23 | #define NCNN_MAX_PARAM_COUNT 20 24 | 25 | namespace ncnn { 26 | 27 | class Net; 28 | class ParamDict 29 | { 30 | public: 31 | // empty 32 | ParamDict(); 33 | 34 | // get int 35 | int get(int id, int def) const; 36 | // get float 37 | float get(int id, float def) const; 38 | // get array 39 | Mat get(int id, const Mat& def) const; 40 | 41 | // set int 42 | void set(int id, int i); 43 | // set float 44 | void set(int id, float f); 45 | // set array 46 | void set(int id, const Mat& v); 47 | 48 | protected: 49 | friend class Net; 50 | 51 | void clear(); 52 | 53 | #if NCNN_STDIO 54 | #if NCNN_STRING 55 | int load_param(FILE* fp); 56 | #endif // NCNN_STRING 57 | int load_param_bin(FILE* fp); 58 | #endif // NCNN_STDIO 59 | int load_param(const unsigned char*& mem); 60 | 61 | protected: 62 | struct 63 | { 64 | int loaded; 65 | union { int i; float f; }; 66 | Mat v; 67 | } params[NCNN_MAX_PARAM_COUNT]; 68 | }; 69 | 70 | } // namespace ncnn 71 | 72 | #endif // NCNN_PARAMDICT_H 73 | -------------------------------------------------------------------------------- /ncnn_linux/include/paramdict.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_PARAMDICT_H 16 | #define NCNN_PARAMDICT_H 17 | 18 | #include 19 | #include "mat.h" 20 | #include "platform.h" 21 | 22 | // at most 20 parameters 23 | #define NCNN_MAX_PARAM_COUNT 20 24 | 25 | namespace ncnn { 26 | 27 | class Net; 28 | class ParamDict 29 | { 30 | public: 31 | // empty 32 | ParamDict(); 33 | 34 | // get int 35 | int get(int id, int def) const; 36 | // get float 37 | float get(int id, float def) const; 38 | // get array 39 | Mat get(int id, const Mat& def) const; 40 | 41 | // set int 42 | void set(int id, int i); 43 | // set float 44 | void set(int id, float f); 45 | // set array 46 | void set(int id, const Mat& v); 47 | 48 | protected: 49 | friend class Net; 50 | 51 | void clear(); 52 | 53 | #if NCNN_STDIO 54 | #if NCNN_STRING 55 | int load_param(FILE* fp); 56 | #endif // NCNN_STRING 57 | int load_param_bin(FILE* fp); 58 | #endif // NCNN_STDIO 59 | int load_param(const unsigned char*& mem); 60 | 61 | protected: 62 | struct 63 | { 64 | int loaded; 65 | union { int i; float f; }; 66 | Mat v; 67 | } params[NCNN_MAX_PARAM_COUNT]; 68 | }; 69 | 70 | } // namespace ncnn 71 | 72 | #endif // NCNN_PARAMDICT_H 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ncnn-benchmark 2 | The benchmark of ncnn that is a high-performance neural network inference framework optimized for the mobile platform 3 | https://github.com/Tencent/ncnn 4 | ## Hardware Platform 5 | |Device|System|CPU-Family|CPU-Num|Freq| 6 | |------|------|----------|-------|----| 7 | |RK3288|Android 5.1|Cortex-A17|4|1.8GHz| 8 | |Qualcomm820|Android 6.0|Kryo|2+2|2.15GHz/1.6GHz| 9 | |Mi5|Android 7.1.2|Kryo|2+2|1.8GHz/1.3GHz| 10 | |Hi3519|Linux 3.18.20|Cortex-A17|1|1.2GHz| 11 | ## Runtime Environment 12 | 1.Using the cpu working in performance model.   13 | ``` 14 | echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 15 | ``` 16 | 2.Loop a hundred times to take the minimum value of Inference time-consuming. 17 | ## Result 18 | |Devices|Models|Input Size|Single-Thread(ms)|Multi-Threads(ms)| 19 | |-------|------|----------|-----------------|-----------------| 20 | |RK3288|SqueezeNet v1.1|227x227x3|194|73| 21 | | |MobileNet v1.0|224x224x3|324|115| 22 | |       |ResNet18|224x224x3|759|250| 23 | |       |ResNet50|224x224x3|1855|810| 24 | |       |GoogleNet v1.0|224x224x3|701|231| 25 | |       |VGG16|224x224x3|3449|1506| 26 | | |MobileNet-SSD|300x300x3|652|245| 27 | |Qualcomm820|SqueezeNet v1.1|227x227x3|91|47| 28 | | |MobileNet v1.0|224x224x3|150|70| 29 | | |ResNet18|224x224x3|355|152| 30 | |       |ResNet50|224x224x3|735|309| 31 | | |GoogleNet v1.0|224x224x3|371|161| 32 | | |VGG16|224x224x3|1928|769| 33 | |       |MobileNet-SSD|300x300x3|330|160| 34 | |Mi5|SqueezeNet v1.1|227x227x3|98|51| 35 | | |MobileNet v1.0|224x224x3|189|79| 36 | |Hi3519|SqueezeNet v1.1|227x227x3|397|null| 37 | | |MobileNet v1.0|224x224x3|666|null| 38 | |       |ResNet18|224x224x3|1608|null| 39 | |       |GoogleNet v1.0|224x224x3|1410|null| 40 | ## User Guide 41 | ### 1. Build the benchmark demo 42 | build demo for Linux-x86 43 | ``` 44 | ./build.sh linux 45 | ``` 46 | build demo for Android 47 | ``` 48 | ./build.sh android 49 | ``` 50 | ### 2. How to run the executable files. 51 | If you build demo for linux success,and want to run the benchmark demo. 52 | ``` 53 | $ cp ./models/classification/squeezenet.param ./build-linux/install/bin/ 54 | $ cp ./models/classification/squeezenet.bin ./build-linux/install/bin/ 55 | $ cd ./build-linux/install/bin/ 56 | $ ./ncnn_classify squeezenet.param squeezenet.bin 227 227 1 1 57 | ``` 58 | Demo running params: 59 | ``` 60 | ./ncnn_classify 61 | ``` 62 | Example: 63 | ``` 64 | bug1989@ubuntu:~/ncnn-benchmark/build-linux/install/bin$ ./ncnn_classify squeezenet.param squeezenet.bin 227 227 10 2 65 | --- NCNN Classification Benchmark Demo --- 22:41:09 Dec 26 2017 66 | Loops : 10 67 | Threads : 2 68 | Time cost: Max 263.338 ms, Min 247.209 ms, Avg 252.652 ms. 69 | ``` 70 | ## The End 71 | Thanks to ncnn's author nihui and all the contributors for sharing this framework. 72 | -------------------------------------------------------------------------------- /ncnn_android/include/help.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | #ifndef _HELP_UTILS_H 5 | #define _HELP_UTILS_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "mat.h" 15 | #include "help.h" 16 | 17 | void cpuStartTimer(void); 18 | float cpuStopTimer(void); 19 | 20 | namespace ncnn { 21 | 22 | /* 23 | * Extract the layer kernel weight value 24 | */ 25 | void extract_kernel_f32(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 26 | void extract_kernel_s16(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 27 | void extract_kernel_s16(int layer_index, const char* layer_name, const short *_kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 28 | void extract_kernel_s8(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 29 | /* 30 | * Extract the layer bottom blob and top blob 2 feature maps 31 | */ 32 | void extract_feature_in_f32(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 33 | void extract_feature_in_f32_v1(int layer_index, const char* layer_name, const Mat& bottom_blob, const int count); 34 | void extract_feature_in_s16(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 35 | void extract_feature_in_s8(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 36 | 37 | void extract_feature_out_f32(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 38 | void extract_feature_out_f32_v1(int layer_index, const char* layer_name, const Mat& top_blob, const int count); 39 | /* 40 | * Create the blob's data from files 41 | */ 42 | void loaddata(ncnn::Mat& blob, const int weight, const int height, const int channels,const char *blobpath); 43 | } 44 | 45 | /* 46 | * Return the current system time ,return unit us 47 | */ 48 | long long get_current_time(void); 49 | 50 | /* 51 | * Convert string type to need type 52 | */ 53 | template 54 | Type stringToNum(const std::string& str) 55 | { 56 | std::istringstream iss(str); 57 | Type num; 58 | iss >> num; 59 | return num; 60 | } 61 | 62 | typedef struct _quantizeParams 63 | { 64 | std::string name; 65 | float dataScale; 66 | float weightScale; 67 | float biasScale; 68 | float reshapeScale; 69 | float anchorsScale; 70 | }stQuantizeParams; 71 | 72 | typedef struct _quantizeParamsBin 73 | { 74 | int index; 75 | float dataScale; 76 | float weightScale; 77 | float biasScale; 78 | float reshapeScale; 79 | float anchorsScale; 80 | }stQuantizeParamsBin; 81 | 82 | typedef enum _convModel 83 | { 84 | CONV_DIRECT = 0, 85 | CONV_WINOGRAD = 1, 86 | CONV_QUANTIZE = 2, 87 | }enConvModel; 88 | 89 | #endif //_HELP_UTILS_H 90 | 91 | -------------------------------------------------------------------------------- /ncnn_linux/include/help.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | #ifndef _HELP_UTILS_H 5 | #define _HELP_UTILS_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "mat.h" 15 | #include "help.h" 16 | 17 | void cpuStartTimer(void); 18 | float cpuStopTimer(void); 19 | 20 | namespace ncnn { 21 | 22 | /* 23 | * Extract the layer kernel weight value 24 | */ 25 | void extract_kernel_f32(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 26 | void extract_kernel_s16(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 27 | void extract_kernel_s16(int layer_index, const char* layer_name, const short *_kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 28 | void extract_kernel_s8(int layer_index, const char* layer_name, const Mat& _kernel, const Mat& _bias, int num_input, int num_output, const int _kernel_size); 29 | /* 30 | * Extract the layer bottom blob and top blob 2 feature maps 31 | */ 32 | void extract_feature_in_f32(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 33 | void extract_feature_in_f32_v1(int layer_index, const char* layer_name, const Mat& bottom_blob, const int count); 34 | void extract_feature_in_s16(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 35 | void extract_feature_in_s8(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 36 | 37 | void extract_feature_out_f32(int layer_index, const char* layer_name, const Mat& bottom_blob, const Mat& top_blob); 38 | void extract_feature_out_f32_v1(int layer_index, const char* layer_name, const Mat& top_blob, const int count); 39 | /* 40 | * Create the blob's data from files 41 | */ 42 | void loaddata(ncnn::Mat& blob, const int weight, const int height, const int channels,const char *blobpath); 43 | } 44 | 45 | /* 46 | * Return the current system time ,return unit us 47 | */ 48 | long long get_current_time(void); 49 | 50 | /* 51 | * Convert string type to need type 52 | */ 53 | template 54 | Type stringToNum(const std::string& str) 55 | { 56 | std::istringstream iss(str); 57 | Type num; 58 | iss >> num; 59 | return num; 60 | } 61 | 62 | typedef struct _quantizeParams 63 | { 64 | std::string name; 65 | float dataScale; 66 | float weightScale; 67 | float biasScale; 68 | float reshapeScale; 69 | float anchorsScale; 70 | }stQuantizeParams; 71 | 72 | typedef struct _quantizeParamsBin 73 | { 74 | int index; 75 | float dataScale; 76 | float weightScale; 77 | float biasScale; 78 | float reshapeScale; 79 | float anchorsScale; 80 | }stQuantizeParamsBin; 81 | 82 | typedef enum _convModel 83 | { 84 | CONV_DIRECT = 0, 85 | CONV_WINOGRAD = 1, 86 | CONV_QUANTIZE = 2, 87 | }enConvModel; 88 | 89 | #endif //_HELP_UTILS_H 90 | 91 | -------------------------------------------------------------------------------- /ncnn_android/include/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "mat.h" 22 | #include "modelbin.h" 23 | #include "paramdict.h" 24 | #include "platform.h" 25 | 26 | namespace ncnn { 27 | 28 | class Layer 29 | { 30 | public: 31 | // empty 32 | Layer(); 33 | // virtual destructor 34 | virtual ~Layer(); 35 | 36 | // load layer specific parameter from parsed dict 37 | // return 0 if success 38 | virtual int load_param(const ParamDict& pd); 39 | 40 | // load layer specific weight data from model binary 41 | // return 0 if success 42 | virtual int load_model(const ModelBin& mb); 43 | 44 | public: 45 | // one input and one output blob 46 | bool one_blob_only; 47 | 48 | // support inplace inference 49 | bool support_inplace; 50 | 51 | public: 52 | // implement inference 53 | // return 0 if success 54 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs) const; 55 | virtual int forward(const Mat& bottom_blob, Mat& top_blob) const; 56 | 57 | // implement inplace inference 58 | // return 0 if success 59 | virtual int forward_inplace(std::vector& bottom_top_blobs) const; 60 | virtual int forward_inplace(Mat& bottom_top_blob) const; 61 | 62 | public: 63 | #if NCNN_STRING 64 | // layer type name 65 | std::string type; 66 | // layer name 67 | std::string name; 68 | #endif // NCNN_STRING 69 | // blob index which this layer needs as input 70 | std::vector bottoms; 71 | // blob index which this layer produces as output 72 | std::vector tops; 73 | }; 74 | 75 | // layer factory function 76 | typedef Layer* (*layer_creator_func)(); 77 | 78 | struct layer_registry_entry 79 | { 80 | #if NCNN_STRING 81 | // layer type name 82 | const char* name; 83 | #endif // NCNN_STRING 84 | // layer factory entry 85 | layer_creator_func creator; 86 | }; 87 | 88 | #if NCNN_STRING 89 | // get layer type from type name 90 | int layer_to_index(const char* type); 91 | // create layer from type name 92 | Layer* create_layer(const char* type); 93 | #endif // NCNN_STRING 94 | // create layer from layer type 95 | Layer* create_layer(int index); 96 | 97 | #define DEFINE_LAYER_CREATOR(name) \ 98 | ::ncnn::Layer* name##_layer_creator() { return new name; } 99 | 100 | } // namespace ncnn 101 | 102 | #endif // NCNN_LAYER_H 103 | -------------------------------------------------------------------------------- /ncnn_linux/include/layer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_LAYER_H 16 | #define NCNN_LAYER_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "mat.h" 22 | #include "modelbin.h" 23 | #include "paramdict.h" 24 | #include "platform.h" 25 | 26 | namespace ncnn { 27 | 28 | class Layer 29 | { 30 | public: 31 | // empty 32 | Layer(); 33 | // virtual destructor 34 | virtual ~Layer(); 35 | 36 | // load layer specific parameter from parsed dict 37 | // return 0 if success 38 | virtual int load_param(const ParamDict& pd); 39 | 40 | // load layer specific weight data from model binary 41 | // return 0 if success 42 | virtual int load_model(const ModelBin& mb); 43 | 44 | public: 45 | // one input and one output blob 46 | bool one_blob_only; 47 | 48 | // support inplace inference 49 | bool support_inplace; 50 | 51 | public: 52 | // implement inference 53 | // return 0 if success 54 | virtual int forward(const std::vector& bottom_blobs, std::vector& top_blobs) const; 55 | virtual int forward(const Mat& bottom_blob, Mat& top_blob) const; 56 | 57 | // implement inplace inference 58 | // return 0 if success 59 | virtual int forward_inplace(std::vector& bottom_top_blobs) const; 60 | virtual int forward_inplace(Mat& bottom_top_blob) const; 61 | 62 | public: 63 | #if NCNN_STRING 64 | // layer type name 65 | std::string type; 66 | // layer name 67 | std::string name; 68 | #endif // NCNN_STRING 69 | // blob index which this layer needs as input 70 | std::vector bottoms; 71 | // blob index which this layer produces as output 72 | std::vector tops; 73 | }; 74 | 75 | // layer factory function 76 | typedef Layer* (*layer_creator_func)(); 77 | 78 | struct layer_registry_entry 79 | { 80 | #if NCNN_STRING 81 | // layer type name 82 | const char* name; 83 | #endif // NCNN_STRING 84 | // layer factory entry 85 | layer_creator_func creator; 86 | }; 87 | 88 | #if NCNN_STRING 89 | // get layer type from type name 90 | int layer_to_index(const char* type); 91 | // create layer from type name 92 | Layer* create_layer(const char* type); 93 | #endif // NCNN_STRING 94 | // create layer from layer type 95 | Layer* create_layer(int index); 96 | 97 | #define DEFINE_LAYER_CREATOR(name) \ 98 | ::ncnn::Layer* name##_layer_creator() { return new name; } 99 | 100 | } // namespace ncnn 101 | 102 | #endif // NCNN_LAYER_H 103 | -------------------------------------------------------------------------------- /examples/classify.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * ncnn Classification Benchmark Demo 4 | * 5 | * v1.0/BUG1989/2017.12.26 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "net.h" 16 | 17 | using namespace std; 18 | 19 | static unsigned long get_current_time(void) 20 | { 21 | struct timeval tv; 22 | 23 | gettimeofday(&tv, NULL); 24 | 25 | return (tv.tv_sec*1000000 + tv.tv_usec); 26 | } 27 | 28 | static int ncnn_classify(char *pParamPath, char *pBinPath, int width, int height, int count, int threads) 29 | { 30 | ncnn::Net classify; 31 | classify.load_param(pParamPath); 32 | classify.load_model(pBinPath); 33 | 34 | ncnn::Mat in; 35 | in.create(width, height, 3); 36 | 37 | const float mean_vals[3] = {104.f, 117.f, 123.f}; 38 | in.substract_mean_normalize(mean_vals, 0); 39 | 40 | ncnn::Mat out; 41 | 42 | double total_time = 0.; 43 | double min_time = DBL_MAX; 44 | double max_time = 0.0; 45 | double temp_time = 0.0; 46 | unsigned long time_0, time_1; 47 | 48 | for(int i =0 ;i < count; i++) 49 | { 50 | time_0 = get_current_time(); 51 | 52 | ncnn::Extractor ex = classify.create_extractor(); 53 | ex.set_light_mode(true); 54 | ex.set_num_threads(threads); 55 | ex.input("data", in); 56 | ex.extract("prob", out); 57 | 58 | time_1 = get_current_time(); 59 | temp_time = ((time_1 - time_0)/1000.0); 60 | if(temp_time < min_time) 61 | { 62 | min_time = temp_time; 63 | } 64 | if(temp_time > max_time) 65 | { 66 | max_time = temp_time; 67 | } 68 | total_time += temp_time; 69 | 70 | printf("iter %d/%d cost: %.3f ms\n", i+1, count, temp_time); 71 | } 72 | 73 | 74 | std::cout << "Time cost: Max " << max_time << \ 75 | " ms, Min " << min_time << \ 76 | " ms, Avg " << total_time/count << \ 77 | " ms." << std::endl; 78 | } 79 | 80 | void usage(void) 81 | { 82 | std::cout << "Input params illegal." << std::endl; 83 | std::cout << "./ncnn_classify " 84 | << std::endl; 85 | } 86 | 87 | /* 88 | * Param: 89 | * input: 90 | */ 91 | int main(int argc, char** argv) 92 | { 93 | char *imagePath = NULL; 94 | char *paramPath = NULL; 95 | char *binPath = NULL; 96 | char *scalePath = NULL; 97 | int loopsNum = 1; 98 | int threadsNum = 1; 99 | int width,height; 100 | 101 | if(argc != 7) 102 | { 103 | usage(); 104 | return -1; 105 | } 106 | else //user params 107 | { 108 | paramPath = argv[1]; 109 | binPath = argv[2]; 110 | width = atoi(argv[3]); 111 | height = atoi(argv[4]); 112 | loopsNum = atoi(argv[5]); 113 | threadsNum = atoi(argv[6]); 114 | } 115 | 116 | std::cout << "--- NCNN Classification Benchmark Demo --- " << __TIME__ << " " << __DATE__ << std::endl; 117 | std::cout << "Loops : " << loopsNum << std::endl; 118 | std::cout << "Threads : " << threadsNum << std::endl; 119 | 120 | ncnn_classify(paramPath, binPath, width, height, loopsNum, threadsNum); 121 | 122 | return 0; 123 | } 124 | 125 | -------------------------------------------------------------------------------- /ncnn_linux/include/net.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_NET_H 16 | #define NCNN_NET_H 17 | 18 | #include 19 | #include 20 | #include "blob.h" 21 | #include "layer.h" 22 | #include "mat.h" 23 | #include "platform.h" 24 | 25 | namespace ncnn { 26 | 27 | class Extractor; 28 | class Net 29 | { 30 | public: 31 | // empty init 32 | Net(); 33 | // clear and destroy 34 | ~Net(); 35 | 36 | #if NCNN_STRING 37 | // register custom layer by layer type name 38 | // return 0 if success 39 | int register_custom_layer(const char* type, layer_creator_func creator); 40 | #endif // NCNN_STRING 41 | // register custom layer by layer type 42 | // return 0 if success 43 | int register_custom_layer(int index, layer_creator_func creator); 44 | 45 | #if NCNN_STDIO 46 | #if NCNN_STRING 47 | // load network structure from plain param file 48 | // return 0 if success 49 | int load_param(FILE* fp); 50 | int load_param(const char* protopath); 51 | #endif // NCNN_STRING 52 | // load network structure from binary param file 53 | // return 0 if success 54 | int load_param_bin(FILE* fp); 55 | int load_param_bin(const char* protopath); 56 | 57 | // load network weight data from model file 58 | // return 0 if success 59 | int load_model(FILE* fp); 60 | int load_model(const char* modelpath); 61 | #endif // NCNN_STDIO 62 | 63 | // load network structure from external memory 64 | // memory pointer must be 32-bit aligned 65 | // return bytes consumed 66 | int load_param(const unsigned char* mem); 67 | 68 | // reference network weight data from external memory 69 | // weight data is not copied but referenced 70 | // so external memory should be retained when used 71 | // memory pointer must be 32-bit aligned 72 | // return bytes consumed 73 | int load_model(const unsigned char* mem); 74 | 75 | // unload network structure and weight data 76 | void clear(); 77 | 78 | // construct an Extractor from network 79 | Extractor create_extractor() const; 80 | 81 | protected: 82 | friend class Extractor; 83 | #if NCNN_STRING 84 | int find_blob_index_by_name(const char* name) const; 85 | int find_layer_index_by_name(const char* name) const; 86 | int custom_layer_to_index(const char* type); 87 | Layer* create_custom_layer(const char* type); 88 | #endif // NCNN_STRING 89 | Layer* create_custom_layer(int index); 90 | int forward_layer(int layer_index, std::vector& blob_mats, bool lightmode) const; 91 | 92 | protected: 93 | std::vector blobs; 94 | std::vector layers; 95 | 96 | std::vector custom_layer_registry; 97 | }; 98 | 99 | class Extractor 100 | { 101 | public: 102 | // enable light mode 103 | // intermediate blob will be recycled when enabled 104 | // enabled by default 105 | void set_light_mode(bool enable); 106 | 107 | // set thread count for this extractor 108 | // this will overwrite the global setting 109 | // default count is system depended 110 | void set_num_threads(int num_threads); 111 | 112 | #if NCNN_STRING 113 | // set input by blob name 114 | // return 0 if success 115 | int input(const char* blob_name, const Mat& in); 116 | 117 | // get result by blob name 118 | // return 0 if success 119 | int extract(const char* blob_name, Mat& feat); 120 | #endif // NCNN_STRING 121 | 122 | // set input by blob index 123 | // return 0 if success 124 | int input(int blob_index, const Mat& in); 125 | 126 | // get result by blob index 127 | // return 0 if success 128 | int extract(int blob_index, Mat& feat); 129 | 130 | protected: 131 | friend Extractor Net::create_extractor() const; 132 | Extractor(const Net* net, int blob_count); 133 | 134 | private: 135 | const Net* net; 136 | std::vector blob_mats; 137 | bool lightmode; 138 | int num_threads; 139 | }; 140 | 141 | } // namespace ncnn 142 | 143 | #endif // NCNN_NET_H 144 | -------------------------------------------------------------------------------- /ncnn_android/include/net.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_NET_H 16 | #define NCNN_NET_H 17 | 18 | #include 19 | #include 20 | #include "blob.h" 21 | #include "layer.h" 22 | #include "mat.h" 23 | #include "platform.h" 24 | 25 | namespace ncnn { 26 | 27 | class Extractor; 28 | class Net 29 | { 30 | public: 31 | // empty init 32 | Net(); 33 | // clear and destroy 34 | ~Net(); 35 | 36 | #if NCNN_STRING 37 | // register custom layer by layer type name 38 | // return 0 if success 39 | int register_custom_layer(const char* type, layer_creator_func creator); 40 | #endif // NCNN_STRING 41 | // register custom layer by layer type 42 | // return 0 if success 43 | int register_custom_layer(int index, layer_creator_func creator); 44 | 45 | #if NCNN_STDIO 46 | #if NCNN_STRING 47 | // load network structure from plain param file 48 | // return 0 if success 49 | int load_param(FILE* fp); 50 | int load_param(const char* protopath); 51 | #endif // NCNN_STRING 52 | // load network structure from binary param file 53 | // return 0 if success 54 | int load_param_bin(FILE* fp); 55 | int load_param_bin(const char* protopath); 56 | 57 | // load network weight data from model file 58 | // return 0 if success 59 | int load_model(FILE* fp); 60 | int load_model(const char* modelpath); 61 | #endif // NCNN_STDIO 62 | 63 | // load network structure from external memory 64 | // memory pointer must be 32-bit aligned 65 | // return bytes consumed 66 | int load_param(const unsigned char* mem); 67 | 68 | // reference network weight data from external memory 69 | // weight data is not copied but referenced 70 | // so external memory should be retained when used 71 | // memory pointer must be 32-bit aligned 72 | // return bytes consumed 73 | int load_model(const unsigned char* mem); 74 | 75 | // unload network structure and weight data 76 | void clear(); 77 | 78 | // construct an Extractor from network 79 | Extractor create_extractor() const; 80 | 81 | protected: 82 | friend class Extractor; 83 | #if NCNN_STRING 84 | int find_blob_index_by_name(const char* name) const; 85 | int find_layer_index_by_name(const char* name) const; 86 | int custom_layer_to_index(const char* type); 87 | Layer* create_custom_layer(const char* type); 88 | #endif // NCNN_STRING 89 | Layer* create_custom_layer(int index); 90 | int forward_layer(int layer_index, std::vector& blob_mats, bool lightmode) const; 91 | 92 | protected: 93 | std::vector blobs; 94 | std::vector layers; 95 | 96 | std::vector custom_layer_registry; 97 | }; 98 | 99 | class Extractor 100 | { 101 | public: 102 | // enable light mode 103 | // intermediate blob will be recycled when enabled 104 | // enabled by default 105 | void set_light_mode(bool enable); 106 | 107 | // set thread count for this extractor 108 | // this will overwrite the global setting 109 | // default count is system depended 110 | void set_num_threads(int num_threads); 111 | 112 | #if NCNN_STRING 113 | // set input by blob name 114 | // return 0 if success 115 | int input(const char* blob_name, const Mat& in); 116 | 117 | // get result by blob name 118 | // return 0 if success 119 | int extract(const char* blob_name, Mat& feat); 120 | #endif // NCNN_STRING 121 | 122 | // set input by blob index 123 | // return 0 if success 124 | int input(int blob_index, const Mat& in); 125 | 126 | // get result by blob index 127 | // return 0 if success 128 | int extract(int blob_index, Mat& feat); 129 | 130 | protected: 131 | friend Extractor Net::create_extractor() const; 132 | Extractor(const Net* net, int blob_count); 133 | 134 | private: 135 | const Net* net; 136 | std::vector blob_mats; 137 | bool lightmode; 138 | int num_threads; 139 | }; 140 | 141 | } // namespace ncnn 142 | 143 | #endif // NCNN_NET_H 144 | -------------------------------------------------------------------------------- /ncnn_linux/include/opencv.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_OPENCV_H 16 | #define NCNN_OPENCV_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_OPENCV 21 | 22 | #include 23 | #include 24 | #include "mat.h" 25 | 26 | // minimal opencv style data structure implementation 27 | namespace cv 28 | { 29 | 30 | struct Size 31 | { 32 | Size() : width(0), height(0) {} 33 | Size(int _w, int _h) : width(_w), height(_h) {} 34 | 35 | int width; 36 | int height; 37 | }; 38 | 39 | template 40 | struct Rect_ 41 | { 42 | Rect_() : x(0), y(0), width(0), height(0) {} 43 | Rect_(_Tp _x, _Tp _y, _Tp _w, _Tp _h) : x(_x), y(_y), width(_w), height(_h) {} 44 | 45 | _Tp x; 46 | _Tp y; 47 | _Tp width; 48 | _Tp height; 49 | 50 | // area 51 | _Tp area() const 52 | { 53 | return width * height; 54 | } 55 | }; 56 | 57 | template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 58 | { 59 | _Tp x1 = std::max(a.x, b.x), y1 = std::max(a.y, b.y); 60 | a.width = std::min(a.x + a.width, b.x + b.width) - x1; 61 | a.height = std::min(a.y + a.height, b.y + b.height) - y1; 62 | a.x = x1; a.y = y1; 63 | if( a.width <= 0 || a.height <= 0 ) 64 | a = Rect_<_Tp>(); 65 | return a; 66 | } 67 | 68 | template static inline Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 69 | { 70 | _Tp x1 = std::min(a.x, b.x), y1 = std::min(a.y, b.y); 71 | a.width = std::max(a.x + a.width, b.x + b.width) - x1; 72 | a.height = std::max(a.y + a.height, b.y + b.height) - y1; 73 | a.x = x1; a.y = y1; 74 | return a; 75 | } 76 | 77 | template static inline Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 78 | { 79 | Rect_<_Tp> c = a; 80 | return c &= b; 81 | } 82 | 83 | template static inline Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 84 | { 85 | Rect_<_Tp> c = a; 86 | return c |= b; 87 | } 88 | 89 | typedef Rect_ Rect; 90 | typedef Rect_ Rect2f; 91 | 92 | template 93 | struct Point_ 94 | { 95 | Point_() : x(0), y(0) {} 96 | Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {} 97 | 98 | _Tp x; 99 | _Tp y; 100 | }; 101 | 102 | typedef Point_ Point; 103 | typedef Point_ Point2f; 104 | 105 | #define CV_8UC1 1 106 | #define CV_8UC3 3 107 | #define CV_8UC4 4 108 | #define CV_32FC1 4 109 | 110 | struct Mat 111 | { 112 | Mat() : data(0), refcount(0), rows(0), cols(0), c(0) {} 113 | 114 | Mat(int _rows, int _cols, int flags) : data(0), refcount(0) 115 | { 116 | create(_rows, _cols, flags); 117 | } 118 | 119 | // copy 120 | Mat(const Mat& m) : data(m.data), refcount(m.refcount) 121 | { 122 | if (refcount) 123 | NCNN_XADD(refcount, 1); 124 | 125 | rows = m.rows; 126 | cols = m.cols; 127 | c = m.c; 128 | } 129 | 130 | Mat(int _rows, int _cols, int flags, void* _data) : data((unsigned char*)_data), refcount(0) 131 | { 132 | rows = _rows; 133 | cols = _cols; 134 | c = flags; 135 | } 136 | 137 | ~Mat() 138 | { 139 | release(); 140 | } 141 | 142 | // assign 143 | Mat& operator=(const Mat& m) 144 | { 145 | if (this == &m) 146 | return *this; 147 | 148 | if (m.refcount) 149 | NCNN_XADD(m.refcount, 1); 150 | 151 | release(); 152 | 153 | data = m.data; 154 | refcount = m.refcount; 155 | 156 | rows = m.rows; 157 | cols = m.cols; 158 | c = m.c; 159 | 160 | return *this; 161 | } 162 | 163 | void create(int _rows, int _cols, int flags) 164 | { 165 | release(); 166 | 167 | rows = _rows; 168 | cols = _cols; 169 | c = flags; 170 | 171 | if (total() > 0) 172 | { 173 | // refcount address must be aligned, so we expand totalsize here 174 | size_t totalsize = (total() + 3) >> 2 << 2; 175 | data = (unsigned char*)ncnn::fastMalloc(totalsize + (int)sizeof(*refcount)); 176 | refcount = (int*)(((unsigned char*)data) + totalsize); 177 | *refcount = 1; 178 | } 179 | } 180 | 181 | void release() 182 | { 183 | if (refcount && NCNN_XADD(refcount, -1) == 1) 184 | ncnn::fastFree(data); 185 | 186 | data = 0; 187 | 188 | rows = 0; 189 | cols = 0; 190 | c = 0; 191 | 192 | refcount = 0; 193 | } 194 | 195 | Mat clone() const 196 | { 197 | if (empty()) 198 | return Mat(); 199 | 200 | Mat m(rows, cols, c); 201 | 202 | if (total() > 0) 203 | { 204 | memcpy(m.data, data, total()); 205 | } 206 | 207 | return m; 208 | } 209 | 210 | bool empty() const { return data == 0 || total() == 0; } 211 | 212 | int channels() const { return c; } 213 | 214 | size_t total() const { return cols * rows * c; } 215 | 216 | const unsigned char* ptr(int y) const { return data + y * cols * c; } 217 | 218 | unsigned char* ptr(int y) { return data + y * cols * c; } 219 | 220 | // roi 221 | Mat operator()( const Rect& roi ) const 222 | { 223 | if (empty()) 224 | return Mat(); 225 | 226 | Mat m(roi.height, roi.width, c); 227 | 228 | int sy = roi.y; 229 | for (int y = 0; y < roi.height; y++) 230 | { 231 | const unsigned char* sptr = ptr(sy) + roi.x * c; 232 | unsigned char* dptr = m.ptr(y); 233 | memcpy(dptr, sptr, roi.width * c); 234 | sy++; 235 | } 236 | 237 | return m; 238 | } 239 | 240 | unsigned char* data; 241 | 242 | // pointer to the reference counter; 243 | // when points to user-allocated data, the pointer is NULL 244 | int* refcount; 245 | 246 | int rows; 247 | int cols; 248 | 249 | int c; 250 | 251 | }; 252 | 253 | #define CV_LOAD_IMAGE_GRAYSCALE 1 254 | #define CV_LOAD_IMAGE_COLOR 3 255 | Mat imread(const std::string& path, int flags); 256 | void imwrite(const std::string& path, const Mat& m); 257 | 258 | void resize(const Mat& src, Mat& dst, const Size& size, float sw = 0.f, float sh = 0.f, int flags = 0); 259 | 260 | } // namespace cv 261 | 262 | #endif // NCNN_OPENCV 263 | 264 | #endif // NCNN_OPENCV_H 265 | -------------------------------------------------------------------------------- /ncnn_android/include/opencv.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_OPENCV_H 16 | #define NCNN_OPENCV_H 17 | 18 | #include "platform.h" 19 | 20 | #if NCNN_OPENCV 21 | 22 | #include 23 | #include 24 | #include "mat.h" 25 | 26 | // minimal opencv style data structure implementation 27 | namespace cv 28 | { 29 | 30 | struct Size 31 | { 32 | Size() : width(0), height(0) {} 33 | Size(int _w, int _h) : width(_w), height(_h) {} 34 | 35 | int width; 36 | int height; 37 | }; 38 | 39 | template 40 | struct Rect_ 41 | { 42 | Rect_() : x(0), y(0), width(0), height(0) {} 43 | Rect_(_Tp _x, _Tp _y, _Tp _w, _Tp _h) : x(_x), y(_y), width(_w), height(_h) {} 44 | 45 | _Tp x; 46 | _Tp y; 47 | _Tp width; 48 | _Tp height; 49 | 50 | // area 51 | _Tp area() const 52 | { 53 | return width * height; 54 | } 55 | }; 56 | 57 | template static inline Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 58 | { 59 | _Tp x1 = std::max(a.x, b.x), y1 = std::max(a.y, b.y); 60 | a.width = std::min(a.x + a.width, b.x + b.width) - x1; 61 | a.height = std::min(a.y + a.height, b.y + b.height) - y1; 62 | a.x = x1; a.y = y1; 63 | if( a.width <= 0 || a.height <= 0 ) 64 | a = Rect_<_Tp>(); 65 | return a; 66 | } 67 | 68 | template static inline Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) 69 | { 70 | _Tp x1 = std::min(a.x, b.x), y1 = std::min(a.y, b.y); 71 | a.width = std::max(a.x + a.width, b.x + b.width) - x1; 72 | a.height = std::max(a.y + a.height, b.y + b.height) - y1; 73 | a.x = x1; a.y = y1; 74 | return a; 75 | } 76 | 77 | template static inline Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 78 | { 79 | Rect_<_Tp> c = a; 80 | return c &= b; 81 | } 82 | 83 | template static inline Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) 84 | { 85 | Rect_<_Tp> c = a; 86 | return c |= b; 87 | } 88 | 89 | typedef Rect_ Rect; 90 | typedef Rect_ Rect2f; 91 | 92 | template 93 | struct Point_ 94 | { 95 | Point_() : x(0), y(0) {} 96 | Point_(_Tp _x, _Tp _y) : x(_x), y(_y) {} 97 | 98 | _Tp x; 99 | _Tp y; 100 | }; 101 | 102 | typedef Point_ Point; 103 | typedef Point_ Point2f; 104 | 105 | #define CV_8UC1 1 106 | #define CV_8UC3 3 107 | #define CV_8UC4 4 108 | #define CV_32FC1 4 109 | 110 | struct Mat 111 | { 112 | Mat() : data(0), refcount(0), rows(0), cols(0), c(0) {} 113 | 114 | Mat(int _rows, int _cols, int flags) : data(0), refcount(0) 115 | { 116 | create(_rows, _cols, flags); 117 | } 118 | 119 | // copy 120 | Mat(const Mat& m) : data(m.data), refcount(m.refcount) 121 | { 122 | if (refcount) 123 | NCNN_XADD(refcount, 1); 124 | 125 | rows = m.rows; 126 | cols = m.cols; 127 | c = m.c; 128 | } 129 | 130 | Mat(int _rows, int _cols, int flags, void* _data) : data((unsigned char*)_data), refcount(0) 131 | { 132 | rows = _rows; 133 | cols = _cols; 134 | c = flags; 135 | } 136 | 137 | ~Mat() 138 | { 139 | release(); 140 | } 141 | 142 | // assign 143 | Mat& operator=(const Mat& m) 144 | { 145 | if (this == &m) 146 | return *this; 147 | 148 | if (m.refcount) 149 | NCNN_XADD(m.refcount, 1); 150 | 151 | release(); 152 | 153 | data = m.data; 154 | refcount = m.refcount; 155 | 156 | rows = m.rows; 157 | cols = m.cols; 158 | c = m.c; 159 | 160 | return *this; 161 | } 162 | 163 | void create(int _rows, int _cols, int flags) 164 | { 165 | release(); 166 | 167 | rows = _rows; 168 | cols = _cols; 169 | c = flags; 170 | 171 | if (total() > 0) 172 | { 173 | // refcount address must be aligned, so we expand totalsize here 174 | size_t totalsize = (total() + 3) >> 2 << 2; 175 | data = (unsigned char*)ncnn::fastMalloc(totalsize + (int)sizeof(*refcount)); 176 | refcount = (int*)(((unsigned char*)data) + totalsize); 177 | *refcount = 1; 178 | } 179 | } 180 | 181 | void release() 182 | { 183 | if (refcount && NCNN_XADD(refcount, -1) == 1) 184 | ncnn::fastFree(data); 185 | 186 | data = 0; 187 | 188 | rows = 0; 189 | cols = 0; 190 | c = 0; 191 | 192 | refcount = 0; 193 | } 194 | 195 | Mat clone() const 196 | { 197 | if (empty()) 198 | return Mat(); 199 | 200 | Mat m(rows, cols, c); 201 | 202 | if (total() > 0) 203 | { 204 | memcpy(m.data, data, total()); 205 | } 206 | 207 | return m; 208 | } 209 | 210 | bool empty() const { return data == 0 || total() == 0; } 211 | 212 | int channels() const { return c; } 213 | 214 | size_t total() const { return cols * rows * c; } 215 | 216 | const unsigned char* ptr(int y) const { return data + y * cols * c; } 217 | 218 | unsigned char* ptr(int y) { return data + y * cols * c; } 219 | 220 | // roi 221 | Mat operator()( const Rect& roi ) const 222 | { 223 | if (empty()) 224 | return Mat(); 225 | 226 | Mat m(roi.height, roi.width, c); 227 | 228 | int sy = roi.y; 229 | for (int y = 0; y < roi.height; y++) 230 | { 231 | const unsigned char* sptr = ptr(sy) + roi.x * c; 232 | unsigned char* dptr = m.ptr(y); 233 | memcpy(dptr, sptr, roi.width * c); 234 | sy++; 235 | } 236 | 237 | return m; 238 | } 239 | 240 | unsigned char* data; 241 | 242 | // pointer to the reference counter; 243 | // when points to user-allocated data, the pointer is NULL 244 | int* refcount; 245 | 246 | int rows; 247 | int cols; 248 | 249 | int c; 250 | 251 | }; 252 | 253 | #define CV_LOAD_IMAGE_GRAYSCALE 1 254 | #define CV_LOAD_IMAGE_COLOR 3 255 | Mat imread(const std::string& path, int flags); 256 | void imwrite(const std::string& path, const Mat& m); 257 | 258 | void resize(const Mat& src, Mat& dst, const Size& size, float sw = 0.f, float sh = 0.f, int flags = 0); 259 | 260 | } // namespace cv 261 | 262 | #endif // NCNN_OPENCV 263 | 264 | #endif // NCNN_OPENCV_H 265 | -------------------------------------------------------------------------------- /ncnn_android/include/mat.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MAT_H 16 | #define NCNN_MAT_H 17 | 18 | #include 19 | #include 20 | #if __ARM_NEON 21 | #include 22 | #endif 23 | 24 | namespace ncnn { 25 | 26 | // the three dimension matrix 27 | class Mat 28 | { 29 | public: 30 | // empty 31 | Mat(); 32 | // vec 33 | Mat(int w, size_t elemsize = 4); 34 | // image 35 | Mat(int w, int h, size_t elemsize = 4); 36 | // dim 37 | Mat(int w, int h, int c, size_t elemsize = 4); 38 | // copy 39 | Mat(const Mat& m); 40 | // external vec 41 | Mat(int w, void* data, size_t elemsize = 4); 42 | // external image 43 | Mat(int w, int h, void* data, size_t elemsize = 4); 44 | // external dim 45 | Mat(int w, int h, int c, void* data, size_t elemsize = 4); 46 | // release 47 | ~Mat(); 48 | // assign 49 | Mat& operator=(const Mat& m); 50 | // set all 51 | void fill(float v); 52 | template void fill(T v); 53 | // deep copy 54 | Mat clone() const; 55 | // reshape vec 56 | Mat reshape(int w) const; 57 | // reshape image 58 | Mat reshape(int w, int h) const; 59 | // reshape dim 60 | Mat reshape(int w, int h, int c) const; 61 | // allocate vec 62 | void create(int w, size_t elemsize = 4); 63 | // allocate image 64 | void create(int w, int h, size_t elemsize = 4); 65 | // allocate dim 66 | void create(int w, int h, int c, size_t elemsize = 4); 67 | // refcount++ 68 | void addref(); 69 | // refcount-- 70 | void release(); 71 | 72 | bool empty() const; 73 | size_t total() const; 74 | 75 | // data reference 76 | Mat channel(int c); 77 | const Mat channel(int c) const; 78 | float* row(int y); 79 | const float* row(int y) const; 80 | template T* row(int y); 81 | template const T* row(int y) const; 82 | 83 | // access raw data 84 | template operator T*(); 85 | template operator const T*() const; 86 | 87 | // convenient access float vec element 88 | float& operator[](int i); 89 | const float& operator[](int i) const; 90 | 91 | enum 92 | { 93 | PIXEL_CONVERT_SHIFT = 16, 94 | PIXEL_FORMAT_MASK = 0x0000ffff, 95 | PIXEL_CONVERT_MASK = 0xffff0000, 96 | 97 | PIXEL_RGB = 1, 98 | PIXEL_BGR = (1 << 1), 99 | PIXEL_GRAY = (1 << 2), 100 | PIXEL_RGBA = (1 << 3), 101 | 102 | PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 103 | PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 104 | 105 | PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 106 | PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 107 | 108 | PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 109 | PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 110 | 111 | PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 112 | PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 113 | PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 114 | }; 115 | // convenient construct from pixel data 116 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h); 117 | // convenient construct from pixel data and resize to specific size 118 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height); 119 | 120 | // convenient export to pixel data 121 | void to_pixels(unsigned char* pixels, int type); 122 | // convenient export to pixel data and resize to specific size 123 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height); 124 | 125 | // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip 126 | void substract_mean_normalize(const float* mean_vals, const float* norm_vals); 127 | 128 | // convenient construct from half precisoin floating point data 129 | static Mat from_float16(const unsigned short* data, int size); 130 | 131 | // pointer to the data 132 | void* data; 133 | 134 | // pointer to the reference counter 135 | // when points to user-allocated data, the pointer is NULL 136 | int* refcount; 137 | 138 | // element size in bytes 139 | // 4 = float32/int32 140 | // 2 = float16 141 | // 1 = int8/uint8 142 | // 0 = empty 143 | size_t elemsize; 144 | 145 | // the dimensionality 146 | int dims; 147 | 148 | int w; 149 | int h; 150 | int c; 151 | 152 | size_t cstep; 153 | }; 154 | 155 | // misc function 156 | // image pixel bilinear resize 157 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 158 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 159 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 160 | 161 | // mat process 162 | enum 163 | { 164 | BORDER_CONSTANT = 0, 165 | BORDER_REPLICATE = 1, 166 | }; 167 | void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v); 168 | void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right); 169 | void resize_bilinear(const Mat& src, Mat& dst, int w, int h); 170 | 171 | // the alignment of all the allocated buffers 172 | #define MALLOC_ALIGN 16 173 | 174 | // Aligns a pointer to the specified number of bytes 175 | // ptr Aligned pointer 176 | // n Alignment size that must be a power of two 177 | template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) 178 | { 179 | return (_Tp*)(((size_t)ptr + n-1) & -n); 180 | } 181 | 182 | // Aligns a buffer size to the specified number of bytes 183 | // The function returns the minimum number that is greater or equal to sz and is divisible by n 184 | // sz Buffer size to align 185 | // n Alignment size that must be a power of two 186 | static inline size_t alignSize(size_t sz, int n) 187 | { 188 | return (sz + n-1) & -n; 189 | } 190 | 191 | static inline void* fastMalloc(size_t size) 192 | { 193 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 194 | if (!udata) 195 | return 0; 196 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 197 | adata[-1] = udata; 198 | return adata; 199 | } 200 | 201 | static inline void fastFree(void* ptr) 202 | { 203 | if (ptr) 204 | { 205 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 206 | free(udata); 207 | } 208 | } 209 | 210 | // exchange-add operation for atomic operations on reference counters 211 | #if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) 212 | // atomic increment on the linux version of the Intel(tm) compiler 213 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) 214 | #elif defined __GNUC__ 215 | # if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) 216 | # ifdef __ATOMIC_ACQ_REL 217 | # define NCNN_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) 218 | # else 219 | # define NCNN_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) 220 | # endif 221 | # else 222 | # if defined __ATOMIC_ACQ_REL && !defined __clang__ 223 | // version for gcc >= 4.7 224 | # define NCNN_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) 225 | # else 226 | # define NCNN_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) 227 | # endif 228 | # endif 229 | #elif defined _MSC_VER && !defined RC_INVOKED 230 | # include 231 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) 232 | #else 233 | static inline void NCNN_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } 234 | #endif 235 | 236 | inline Mat::Mat() 237 | : data(0), refcount(0), elemsize(0), dims(0), w(0), h(0), c(0), cstep(0) 238 | { 239 | } 240 | 241 | inline Mat::Mat(int _w, size_t _elemsize) 242 | : data(0), refcount(0), dims(0) 243 | { 244 | create(_w, _elemsize); 245 | } 246 | 247 | inline Mat::Mat(int _w, int _h, size_t _elemsize) 248 | : data(0), refcount(0), dims(0) 249 | { 250 | create(_w, _h, _elemsize); 251 | } 252 | 253 | inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize) 254 | : data(0), refcount(0), dims(0) 255 | { 256 | create(_w, _h, _c, _elemsize); 257 | } 258 | 259 | inline Mat::Mat(const Mat& m) 260 | : data(m.data), refcount(m.refcount), elemsize(m.elemsize), dims(m.dims) 261 | { 262 | if (refcount) 263 | NCNN_XADD(refcount, 1); 264 | 265 | w = m.w; 266 | h = m.h; 267 | c = m.c; 268 | 269 | cstep = m.cstep; 270 | } 271 | 272 | inline Mat::Mat(int _w, void* _data, size_t _elemsize) 273 | : data(_data), refcount(0), elemsize(_elemsize), dims(1) 274 | { 275 | w = _w; 276 | h = 1; 277 | c = 1; 278 | 279 | cstep = w; 280 | } 281 | 282 | inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize) 283 | : data(_data), refcount(0), elemsize(_elemsize), dims(2) 284 | { 285 | w = _w; 286 | h = _h; 287 | c = 1; 288 | 289 | cstep = w * h; 290 | } 291 | 292 | inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize) 293 | : data(_data), refcount(0), elemsize(_elemsize), dims(3) 294 | { 295 | w = _w; 296 | h = _h; 297 | c = _c; 298 | 299 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 300 | } 301 | 302 | inline Mat::~Mat() 303 | { 304 | release(); 305 | } 306 | 307 | inline Mat& Mat::operator=(const Mat& m) 308 | { 309 | if (this == &m) 310 | return *this; 311 | 312 | if (m.refcount) 313 | NCNN_XADD(m.refcount, 1); 314 | 315 | release(); 316 | 317 | data = m.data; 318 | refcount = m.refcount; 319 | elemsize = m.elemsize; 320 | 321 | dims = m.dims; 322 | w = m.w; 323 | h = m.h; 324 | c = m.c; 325 | 326 | cstep = m.cstep; 327 | 328 | return *this; 329 | } 330 | 331 | inline void Mat::fill(float _v) 332 | { 333 | int size = total(); 334 | float* ptr = (float*)data; 335 | 336 | #if __ARM_NEON 337 | int nn = size >> 2; 338 | int remain = size - (nn << 2); 339 | #else 340 | int remain = size; 341 | #endif // __ARM_NEON 342 | 343 | #if __ARM_NEON 344 | float32x4_t _c = vdupq_n_f32(_v); 345 | #if __aarch64__ 346 | for (; nn>0; nn--) 347 | { 348 | vst1q_f32(ptr, _c); 349 | ptr += 4; 350 | } 351 | #else 352 | if (nn > 0) 353 | { 354 | asm volatile( 355 | "0: \n" 356 | "subs %0, #1 \n" 357 | "vst1.f32 {%e4-%f4}, [%1 :128]!\n" 358 | "bne 0b \n" 359 | : "=r"(nn), // %0 360 | "=r"(ptr) // %1 361 | : "0"(nn), 362 | "1"(ptr), 363 | "w"(_c) // %4 364 | : "cc", "memory" 365 | ); 366 | } 367 | #endif // __aarch64__ 368 | #endif // __ARM_NEON 369 | for (; remain>0; remain--) 370 | { 371 | *ptr++ = _v; 372 | } 373 | } 374 | 375 | template 376 | inline void Mat::fill(T _v) 377 | { 378 | int size = total(); 379 | T* ptr = (T*)data; 380 | for (int i=0; i 0) 400 | { 401 | memcpy(m.data, data, total() * elemsize); 402 | } 403 | 404 | return m; 405 | } 406 | 407 | inline Mat Mat::reshape(int _w) const 408 | { 409 | if (w * h * c != _w) 410 | return Mat(); 411 | 412 | if (dims == 3 && cstep != (size_t)w * h) 413 | { 414 | Mat m; 415 | m.create(_w, elemsize); 416 | 417 | // flatten 418 | for (int i=0; i 0) 529 | { 530 | size_t totalsize = total() * elemsize; 531 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 532 | refcount = (int*)(((unsigned char*)data) + totalsize); 533 | *refcount = 1; 534 | } 535 | } 536 | 537 | inline void Mat::create(int _w, int _h, size_t _elemsize) 538 | { 539 | release(); 540 | 541 | elemsize = _elemsize; 542 | 543 | dims = 2; 544 | w = _w; 545 | h = _h; 546 | c = 1; 547 | 548 | cstep = w * h; 549 | 550 | if (total() > 0) 551 | { 552 | size_t totalsize = total() * elemsize; 553 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 554 | refcount = (int*)(((unsigned char*)data) + totalsize); 555 | *refcount = 1; 556 | } 557 | } 558 | 559 | inline void Mat::create(int _w, int _h, int _c, size_t _elemsize) 560 | { 561 | release(); 562 | 563 | elemsize = _elemsize; 564 | 565 | dims = 3; 566 | w = _w; 567 | h = _h; 568 | c = _c; 569 | 570 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 571 | 572 | if (total() > 0) 573 | { 574 | size_t totalsize = total() * elemsize; 575 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 576 | refcount = (int*)(((unsigned char*)data) + totalsize); 577 | *refcount = 1; 578 | } 579 | } 580 | 581 | inline void Mat::addref() 582 | { 583 | if (refcount) 584 | NCNN_XADD(refcount, 1); 585 | } 586 | 587 | inline void Mat::release() 588 | { 589 | if (refcount && NCNN_XADD(refcount, -1) == 1) 590 | fastFree(data); 591 | 592 | data = 0; 593 | 594 | elemsize = 0; 595 | 596 | dims = 0; 597 | w = 0; 598 | h = 0; 599 | c = 0; 600 | 601 | cstep = 0; 602 | 603 | refcount = 0; 604 | } 605 | 606 | inline bool Mat::empty() const 607 | { 608 | return data == 0 || total() == 0; 609 | } 610 | 611 | inline size_t Mat::total() const 612 | { 613 | return cstep * c; 614 | } 615 | 616 | inline Mat Mat::channel(int c) 617 | { 618 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 619 | } 620 | 621 | inline const Mat Mat::channel(int c) const 622 | { 623 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 624 | } 625 | 626 | inline float* Mat::row(int y) 627 | { 628 | return (float*)data + w * y; 629 | } 630 | 631 | inline const float* Mat::row(int y) const 632 | { 633 | return (const float*)data + w * y; 634 | } 635 | 636 | template 637 | inline T* Mat::row(int y) 638 | { 639 | return (T*)data + w * y; 640 | } 641 | 642 | template 643 | inline const T* Mat::row(int y) const 644 | { 645 | return (const T*)data + w * y; 646 | } 647 | 648 | template 649 | inline Mat::operator T*() 650 | { 651 | return (T*)data; 652 | } 653 | 654 | template 655 | inline Mat::operator const T*() const 656 | { 657 | return (const T*)data; 658 | } 659 | 660 | inline float& Mat::operator[](int i) 661 | { 662 | return ((float*)data)[i]; 663 | } 664 | 665 | inline const float& Mat::operator[](int i) const 666 | { 667 | return ((const float*)data)[i]; 668 | } 669 | 670 | } // namespace ncnn 671 | 672 | #endif // NCNN_MAT_H 673 | -------------------------------------------------------------------------------- /ncnn_linux/include/mat.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making ncnn available. 2 | // 3 | // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. 4 | // 5 | // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // https://opensource.org/licenses/BSD-3-Clause 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef NCNN_MAT_H 16 | #define NCNN_MAT_H 17 | 18 | #include 19 | #include 20 | #if __ARM_NEON 21 | #include 22 | #endif 23 | 24 | namespace ncnn { 25 | 26 | // the three dimension matrix 27 | class Mat 28 | { 29 | public: 30 | // empty 31 | Mat(); 32 | // vec 33 | Mat(int w, size_t elemsize = 4); 34 | // image 35 | Mat(int w, int h, size_t elemsize = 4); 36 | // dim 37 | Mat(int w, int h, int c, size_t elemsize = 4); 38 | // copy 39 | Mat(const Mat& m); 40 | // external vec 41 | Mat(int w, void* data, size_t elemsize = 4); 42 | // external image 43 | Mat(int w, int h, void* data, size_t elemsize = 4); 44 | // external dim 45 | Mat(int w, int h, int c, void* data, size_t elemsize = 4); 46 | // release 47 | ~Mat(); 48 | // assign 49 | Mat& operator=(const Mat& m); 50 | // set all 51 | void fill(float v); 52 | template void fill(T v); 53 | // deep copy 54 | Mat clone() const; 55 | // reshape vec 56 | Mat reshape(int w) const; 57 | // reshape image 58 | Mat reshape(int w, int h) const; 59 | // reshape dim 60 | Mat reshape(int w, int h, int c) const; 61 | // allocate vec 62 | void create(int w, size_t elemsize = 4); 63 | // allocate image 64 | void create(int w, int h, size_t elemsize = 4); 65 | // allocate dim 66 | void create(int w, int h, int c, size_t elemsize = 4); 67 | // refcount++ 68 | void addref(); 69 | // refcount-- 70 | void release(); 71 | 72 | bool empty() const; 73 | size_t total() const; 74 | 75 | // data reference 76 | Mat channel(int c); 77 | const Mat channel(int c) const; 78 | float* row(int y); 79 | const float* row(int y) const; 80 | template T* row(int y); 81 | template const T* row(int y) const; 82 | 83 | // access raw data 84 | template operator T*(); 85 | template operator const T*() const; 86 | 87 | // convenient access float vec element 88 | float& operator[](int i); 89 | const float& operator[](int i) const; 90 | 91 | enum 92 | { 93 | PIXEL_CONVERT_SHIFT = 16, 94 | PIXEL_FORMAT_MASK = 0x0000ffff, 95 | PIXEL_CONVERT_MASK = 0xffff0000, 96 | 97 | PIXEL_RGB = 1, 98 | PIXEL_BGR = (1 << 1), 99 | PIXEL_GRAY = (1 << 2), 100 | PIXEL_RGBA = (1 << 3), 101 | 102 | PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 103 | PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 104 | 105 | PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 106 | PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 107 | 108 | PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 109 | PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 110 | 111 | PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT), 112 | PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT), 113 | PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT), 114 | }; 115 | // convenient construct from pixel data 116 | static Mat from_pixels(const unsigned char* pixels, int type, int w, int h); 117 | // convenient construct from pixel data and resize to specific size 118 | static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height); 119 | 120 | // convenient export to pixel data 121 | void to_pixels(unsigned char* pixels, int type); 122 | // convenient export to pixel data and resize to specific size 123 | void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height); 124 | 125 | // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip 126 | void substract_mean_normalize(const float* mean_vals, const float* norm_vals); 127 | 128 | // convenient construct from half precisoin floating point data 129 | static Mat from_float16(const unsigned short* data, int size); 130 | 131 | // pointer to the data 132 | void* data; 133 | 134 | // pointer to the reference counter 135 | // when points to user-allocated data, the pointer is NULL 136 | int* refcount; 137 | 138 | // element size in bytes 139 | // 4 = float32/int32 140 | // 2 = float16 141 | // 1 = int8/uint8 142 | // 0 = empty 143 | size_t elemsize; 144 | 145 | // the dimensionality 146 | int dims; 147 | 148 | int w; 149 | int h; 150 | int c; 151 | 152 | size_t cstep; 153 | }; 154 | 155 | // misc function 156 | // image pixel bilinear resize 157 | void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 158 | void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 159 | void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h); 160 | 161 | // mat process 162 | enum 163 | { 164 | BORDER_CONSTANT = 0, 165 | BORDER_REPLICATE = 1, 166 | }; 167 | void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v); 168 | void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right); 169 | void resize_bilinear(const Mat& src, Mat& dst, int w, int h); 170 | 171 | // the alignment of all the allocated buffers 172 | #define MALLOC_ALIGN 16 173 | 174 | // Aligns a pointer to the specified number of bytes 175 | // ptr Aligned pointer 176 | // n Alignment size that must be a power of two 177 | template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) 178 | { 179 | return (_Tp*)(((size_t)ptr + n-1) & -n); 180 | } 181 | 182 | // Aligns a buffer size to the specified number of bytes 183 | // The function returns the minimum number that is greater or equal to sz and is divisible by n 184 | // sz Buffer size to align 185 | // n Alignment size that must be a power of two 186 | static inline size_t alignSize(size_t sz, int n) 187 | { 188 | return (sz + n-1) & -n; 189 | } 190 | 191 | static inline void* fastMalloc(size_t size) 192 | { 193 | unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN); 194 | if (!udata) 195 | return 0; 196 | unsigned char** adata = alignPtr((unsigned char**)udata + 1, MALLOC_ALIGN); 197 | adata[-1] = udata; 198 | return adata; 199 | } 200 | 201 | static inline void fastFree(void* ptr) 202 | { 203 | if (ptr) 204 | { 205 | unsigned char* udata = ((unsigned char**)ptr)[-1]; 206 | free(udata); 207 | } 208 | } 209 | 210 | // exchange-add operation for atomic operations on reference counters 211 | #if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) 212 | // atomic increment on the linux version of the Intel(tm) compiler 213 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) 214 | #elif defined __GNUC__ 215 | # if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) 216 | # ifdef __ATOMIC_ACQ_REL 217 | # define NCNN_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) 218 | # else 219 | # define NCNN_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) 220 | # endif 221 | # else 222 | # if defined __ATOMIC_ACQ_REL && !defined __clang__ 223 | // version for gcc >= 4.7 224 | # define NCNN_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) 225 | # else 226 | # define NCNN_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) 227 | # endif 228 | # endif 229 | #elif defined _MSC_VER && !defined RC_INVOKED 230 | # include 231 | # define NCNN_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) 232 | #else 233 | static inline void NCNN_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } 234 | #endif 235 | 236 | inline Mat::Mat() 237 | : data(0), refcount(0), elemsize(0), dims(0), w(0), h(0), c(0), cstep(0) 238 | { 239 | } 240 | 241 | inline Mat::Mat(int _w, size_t _elemsize) 242 | : data(0), refcount(0), dims(0) 243 | { 244 | create(_w, _elemsize); 245 | } 246 | 247 | inline Mat::Mat(int _w, int _h, size_t _elemsize) 248 | : data(0), refcount(0), dims(0) 249 | { 250 | create(_w, _h, _elemsize); 251 | } 252 | 253 | inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize) 254 | : data(0), refcount(0), dims(0) 255 | { 256 | create(_w, _h, _c, _elemsize); 257 | } 258 | 259 | inline Mat::Mat(const Mat& m) 260 | : data(m.data), refcount(m.refcount), elemsize(m.elemsize), dims(m.dims) 261 | { 262 | if (refcount) 263 | NCNN_XADD(refcount, 1); 264 | 265 | w = m.w; 266 | h = m.h; 267 | c = m.c; 268 | 269 | cstep = m.cstep; 270 | } 271 | 272 | inline Mat::Mat(int _w, void* _data, size_t _elemsize) 273 | : data(_data), refcount(0), elemsize(_elemsize), dims(1) 274 | { 275 | w = _w; 276 | h = 1; 277 | c = 1; 278 | 279 | cstep = w; 280 | } 281 | 282 | inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize) 283 | : data(_data), refcount(0), elemsize(_elemsize), dims(2) 284 | { 285 | w = _w; 286 | h = _h; 287 | c = 1; 288 | 289 | cstep = w * h; 290 | } 291 | 292 | inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize) 293 | : data(_data), refcount(0), elemsize(_elemsize), dims(3) 294 | { 295 | w = _w; 296 | h = _h; 297 | c = _c; 298 | 299 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 300 | } 301 | 302 | inline Mat::~Mat() 303 | { 304 | release(); 305 | } 306 | 307 | inline Mat& Mat::operator=(const Mat& m) 308 | { 309 | if (this == &m) 310 | return *this; 311 | 312 | if (m.refcount) 313 | NCNN_XADD(m.refcount, 1); 314 | 315 | release(); 316 | 317 | data = m.data; 318 | refcount = m.refcount; 319 | elemsize = m.elemsize; 320 | 321 | dims = m.dims; 322 | w = m.w; 323 | h = m.h; 324 | c = m.c; 325 | 326 | cstep = m.cstep; 327 | 328 | return *this; 329 | } 330 | 331 | inline void Mat::fill(float _v) 332 | { 333 | int size = total(); 334 | float* ptr = (float*)data; 335 | 336 | #if __ARM_NEON 337 | int nn = size >> 2; 338 | int remain = size - (nn << 2); 339 | #else 340 | int remain = size; 341 | #endif // __ARM_NEON 342 | 343 | #if __ARM_NEON 344 | float32x4_t _c = vdupq_n_f32(_v); 345 | #if __aarch64__ 346 | for (; nn>0; nn--) 347 | { 348 | vst1q_f32(ptr, _c); 349 | ptr += 4; 350 | } 351 | #else 352 | if (nn > 0) 353 | { 354 | asm volatile( 355 | "0: \n" 356 | "subs %0, #1 \n" 357 | "vst1.f32 {%e4-%f4}, [%1 :128]!\n" 358 | "bne 0b \n" 359 | : "=r"(nn), // %0 360 | "=r"(ptr) // %1 361 | : "0"(nn), 362 | "1"(ptr), 363 | "w"(_c) // %4 364 | : "cc", "memory" 365 | ); 366 | } 367 | #endif // __aarch64__ 368 | #endif // __ARM_NEON 369 | for (; remain>0; remain--) 370 | { 371 | *ptr++ = _v; 372 | } 373 | } 374 | 375 | template 376 | inline void Mat::fill(T _v) 377 | { 378 | int size = total(); 379 | T* ptr = (T*)data; 380 | for (int i=0; i 0) 400 | { 401 | memcpy(m.data, data, total() * elemsize); 402 | } 403 | 404 | return m; 405 | } 406 | 407 | inline Mat Mat::reshape(int _w) const 408 | { 409 | if (w * h * c != _w) 410 | return Mat(); 411 | 412 | if (dims == 3 && cstep != (size_t)w * h) 413 | { 414 | Mat m; 415 | m.create(_w, elemsize); 416 | 417 | // flatten 418 | for (int i=0; i 0) 529 | { 530 | size_t totalsize = total() * elemsize; 531 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 532 | refcount = (int*)(((unsigned char*)data) + totalsize); 533 | *refcount = 1; 534 | } 535 | } 536 | 537 | inline void Mat::create(int _w, int _h, size_t _elemsize) 538 | { 539 | release(); 540 | 541 | elemsize = _elemsize; 542 | 543 | dims = 2; 544 | w = _w; 545 | h = _h; 546 | c = 1; 547 | 548 | cstep = w * h; 549 | 550 | if (total() > 0) 551 | { 552 | size_t totalsize = total() * elemsize; 553 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 554 | refcount = (int*)(((unsigned char*)data) + totalsize); 555 | *refcount = 1; 556 | } 557 | } 558 | 559 | inline void Mat::create(int _w, int _h, int _c, size_t _elemsize) 560 | { 561 | release(); 562 | 563 | elemsize = _elemsize; 564 | 565 | dims = 3; 566 | w = _w; 567 | h = _h; 568 | c = _c; 569 | 570 | cstep = alignSize(w * h * elemsize, 16) / elemsize; 571 | 572 | if (total() > 0) 573 | { 574 | size_t totalsize = total() * elemsize; 575 | data = fastMalloc(totalsize + (int)sizeof(*refcount)); 576 | refcount = (int*)(((unsigned char*)data) + totalsize); 577 | *refcount = 1; 578 | } 579 | } 580 | 581 | inline void Mat::addref() 582 | { 583 | if (refcount) 584 | NCNN_XADD(refcount, 1); 585 | } 586 | 587 | inline void Mat::release() 588 | { 589 | if (refcount && NCNN_XADD(refcount, -1) == 1) 590 | fastFree(data); 591 | 592 | data = 0; 593 | 594 | elemsize = 0; 595 | 596 | dims = 0; 597 | w = 0; 598 | h = 0; 599 | c = 0; 600 | 601 | cstep = 0; 602 | 603 | refcount = 0; 604 | } 605 | 606 | inline bool Mat::empty() const 607 | { 608 | return data == 0 || total() == 0; 609 | } 610 | 611 | inline size_t Mat::total() const 612 | { 613 | return cstep * c; 614 | } 615 | 616 | inline Mat Mat::channel(int c) 617 | { 618 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 619 | } 620 | 621 | inline const Mat Mat::channel(int c) const 622 | { 623 | return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize); 624 | } 625 | 626 | inline float* Mat::row(int y) 627 | { 628 | return (float*)data + w * y; 629 | } 630 | 631 | inline const float* Mat::row(int y) const 632 | { 633 | return (const float*)data + w * y; 634 | } 635 | 636 | template 637 | inline T* Mat::row(int y) 638 | { 639 | return (T*)data + w * y; 640 | } 641 | 642 | template 643 | inline const T* Mat::row(int y) const 644 | { 645 | return (const T*)data + w * y; 646 | } 647 | 648 | template 649 | inline Mat::operator T*() 650 | { 651 | return (T*)data; 652 | } 653 | 654 | template 655 | inline Mat::operator const T*() const 656 | { 657 | return (const T*)data; 658 | } 659 | 660 | inline float& Mat::operator[](int i) 661 | { 662 | return ((float*)data)[i]; 663 | } 664 | 665 | inline const float& Mat::operator[](int i) const 666 | { 667 | return ((const float*)data)[i]; 668 | } 669 | 670 | } // namespace ncnn 671 | 672 | #endif // NCNN_MAT_H 673 | -------------------------------------------------------------------------------- /android.toolchain.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010-2011, Ethan Rublee 2 | # Copyright (c) 2011-2014, Andrey Kamaev 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 11 | # 2. Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # 15 | # 3. Neither the name of the copyright holder nor the names of its 16 | # contributors may be used to endorse or promote products derived from this 17 | # software without specific prior written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | # POSSIBILITY OF SUCH DAMAGE. 30 | 31 | # ------------------------------------------------------------------------------ 32 | # Android CMake toolchain file, for use with the Android NDK r5-r10d 33 | # Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). 34 | # See home page: https://github.com/taka-no-me/android-cmake 35 | # 36 | # Usage Linux: 37 | # $ export ANDROID_NDK=/absolute/path/to/the/android-ndk 38 | # $ mkdir build && cd build 39 | # $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. 40 | # $ make -j8 41 | # 42 | # Usage Windows: 43 | # You need native port of make to build your project. 44 | # Android NDK r7 (and newer) already has make.exe on board. 45 | # For older NDK you have to install it separately. 46 | # For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm 47 | # 48 | # $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk 49 | # $ mkdir build && cd build 50 | # $ cmake.exe -G"MinGW Makefiles" 51 | # -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake 52 | # -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. 53 | # $ cmake.exe --build . 54 | # 55 | # 56 | # Options (can be set as cmake parameters: -D=): 57 | # ANDROID_NDK=/opt/android-ndk - path to the NDK root. 58 | # Can be set as environment variable. Can be set only at first cmake run. 59 | # 60 | # ANDROID_ABI=armeabi-v7a - specifies the target Application Binary 61 | # Interface (ABI). This option nearly matches to the APP_ABI variable 62 | # used by ndk-build tool from Android NDK. 63 | # 64 | # Possible targets are: 65 | # "armeabi" - ARMv5TE based CPU with software floating point operations 66 | # "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions 67 | # this ABI target is used by default 68 | # "armeabi-v7a-hard with NEON" - ARMv7 based devices with hardware FPU instructions and hardfp 69 | # "armeabi-v7a with NEON" - same as armeabi-v7a, but 70 | # sets NEON as floating-point unit 71 | # "armeabi-v7a with VFPV3" - same as armeabi-v7a, but 72 | # sets VFPV3 as floating-point unit (has 32 registers instead of 16) 73 | # "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP 74 | # "x86" - IA-32 instruction set 75 | # "mips" - MIPS32 instruction set 76 | # 77 | # 64-bit ABIs for NDK r10 and newer: 78 | # "arm64-v8a" - ARMv8 AArch64 instruction set 79 | # "x86_64" - Intel64 instruction set (r1) 80 | # "mips64" - MIPS64 instruction set (r6) 81 | # 82 | # ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. 83 | # Option is read-only when standalone toolchain is used. 84 | # Note: building for "android-L" requires explicit configuration. 85 | # 86 | # ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler 87 | # toolchain to be used. The list of possible values depends on the NDK 88 | # version. For NDK r10c the possible values are: 89 | # 90 | # * aarch64-linux-android-4.9 91 | # * aarch64-linux-android-clang3.4 92 | # * aarch64-linux-android-clang3.5 93 | # * arm-linux-androideabi-4.6 94 | # * arm-linux-androideabi-4.8 95 | # * arm-linux-androideabi-4.9 (default) 96 | # * arm-linux-androideabi-clang3.4 97 | # * arm-linux-androideabi-clang3.5 98 | # * mips64el-linux-android-4.9 99 | # * mips64el-linux-android-clang3.4 100 | # * mips64el-linux-android-clang3.5 101 | # * mipsel-linux-android-4.6 102 | # * mipsel-linux-android-4.8 103 | # * mipsel-linux-android-4.9 104 | # * mipsel-linux-android-clang3.4 105 | # * mipsel-linux-android-clang3.5 106 | # * x86-4.6 107 | # * x86-4.8 108 | # * x86-4.9 109 | # * x86-clang3.4 110 | # * x86-clang3.5 111 | # * x86_64-4.9 112 | # * x86_64-clang3.4 113 | # * x86_64-clang3.5 114 | # 115 | # ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions 116 | # instead of Thumb. Is not available for "armeabi-v6 with VFP" 117 | # (is forced to be ON) ABI. 118 | # 119 | # ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker 120 | # errors even if they are not used. 121 | # 122 | # ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared 123 | # libraries. Automatically turned for NDK r5x and r6x due to GLESv2 124 | # problems. 125 | # 126 | # ANDROID_STL=gnustl_static - specify the runtime to use. 127 | # 128 | # Possible values are: 129 | # none -> Do not configure the runtime. 130 | # system -> Use the default minimal system C++ runtime library. 131 | # Implies -fno-rtti -fno-exceptions. 132 | # Is not available for standalone toolchain. 133 | # system_re -> Use the default minimal system C++ runtime library. 134 | # Implies -frtti -fexceptions. 135 | # Is not available for standalone toolchain. 136 | # gabi++_static -> Use the GAbi++ runtime as a static library. 137 | # Implies -frtti -fno-exceptions. 138 | # Available for NDK r7 and newer. 139 | # Is not available for standalone toolchain. 140 | # gabi++_shared -> Use the GAbi++ runtime as a shared library. 141 | # Implies -frtti -fno-exceptions. 142 | # Available for NDK r7 and newer. 143 | # Is not available for standalone toolchain. 144 | # stlport_static -> Use the STLport runtime as a static library. 145 | # Implies -fno-rtti -fno-exceptions for NDK before r7. 146 | # Implies -frtti -fno-exceptions for NDK r7 and newer. 147 | # Is not available for standalone toolchain. 148 | # stlport_shared -> Use the STLport runtime as a shared library. 149 | # Implies -fno-rtti -fno-exceptions for NDK before r7. 150 | # Implies -frtti -fno-exceptions for NDK r7 and newer. 151 | # Is not available for standalone toolchain. 152 | # gnustl_static -> Use the GNU STL as a static library. 153 | # Implies -frtti -fexceptions. 154 | # gnustl_shared -> Use the GNU STL as a shared library. 155 | # Implies -frtti -fno-exceptions. 156 | # Available for NDK r7b and newer. 157 | # Silently degrades to gnustl_static if not available. 158 | # c++_static -> Use the LLVM libc++ runtime as a static library. 159 | # Implies -frtti -fexceptions. 160 | # c++_shared -> Use the LLVM libc++ runtime as a static library. 161 | # Implies -frtti -fno-exceptions. 162 | # 163 | # ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on 164 | # chosen runtime. If disabled, then the user is responsible for settings 165 | # these options. 166 | # 167 | # What?: 168 | # android-cmake toolchain searches for NDK/toolchain in the following order: 169 | # ANDROID_NDK - cmake parameter 170 | # ANDROID_NDK - environment variable 171 | # ANDROID_STANDALONE_TOOLCHAIN - cmake parameter 172 | # ANDROID_STANDALONE_TOOLCHAIN - environment variable 173 | # ANDROID_NDK - default locations 174 | # ANDROID_STANDALONE_TOOLCHAIN - default locations 175 | # 176 | # Make sure to do the following in your scripts: 177 | # SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) 178 | # SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) 179 | # The flags will be prepopulated with critical flags, so don't loose them. 180 | # Also be aware that toolchain also sets configuration-specific compiler 181 | # flags and linker flags. 182 | # 183 | # ANDROID and BUILD_ANDROID will be set to true, you may test any of these 184 | # variables to make necessary Android-specific configuration changes. 185 | # 186 | # Also ARMEABI or ARMEABI_V7A or ARMEABI_V7A_HARD or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 187 | # will be set true, mutually exclusive. NEON option will be set true 188 | # if VFP is set to NEON. 189 | # 190 | # ------------------------------------------------------------------------------ 191 | 192 | cmake_minimum_required( VERSION 2.6.3 ) 193 | 194 | if( DEFINED CMAKE_CROSSCOMPILING ) 195 | # subsequent toolchain loading is not really needed 196 | return() 197 | endif() 198 | 199 | if( CMAKE_TOOLCHAIN_FILE ) 200 | # touch toolchain variable to suppress "unused variable" warning 201 | endif() 202 | 203 | # inherit settings in recursive loads 204 | get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) 205 | if( _CMAKE_IN_TRY_COMPILE ) 206 | include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) 207 | endif() 208 | 209 | # this one is important 210 | if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) 211 | set( CMAKE_SYSTEM_NAME Android ) 212 | else() 213 | set( CMAKE_SYSTEM_NAME Linux ) 214 | endif() 215 | 216 | # this one not so much 217 | set( CMAKE_SYSTEM_VERSION 1 ) 218 | 219 | # rpath makes low sense for Android 220 | set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) 221 | set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) 222 | 223 | # NDK search paths 224 | set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) 225 | if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) 226 | if( CMAKE_HOST_WIN32 ) 227 | file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) 228 | set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) 229 | else() 230 | file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) 231 | set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) 232 | endif() 233 | endif() 234 | if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) 235 | set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) 236 | endif() 237 | 238 | # known ABIs 239 | set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a-hard with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) 240 | set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) 241 | set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) 242 | set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) 243 | set( ANDROID_SUPPORTED_ABIS_mips "mips" ) 244 | set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) 245 | 246 | # API level defaults 247 | set( ANDROID_DEFAULT_NDK_API_LEVEL 9 ) 248 | set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) 249 | set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) 250 | set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) 251 | set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) 252 | set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) 253 | 254 | 255 | macro( __LIST_FILTER listvar regex ) 256 | if( ${listvar} ) 257 | foreach( __val ${${listvar}} ) 258 | if( __val MATCHES "${regex}" ) 259 | list( REMOVE_ITEM ${listvar} "${__val}" ) 260 | endif() 261 | endforeach() 262 | endif() 263 | endmacro() 264 | 265 | macro( __INIT_VARIABLE var_name ) 266 | set( __test_path 0 ) 267 | foreach( __var ${ARGN} ) 268 | if( __var STREQUAL "PATH" ) 269 | set( __test_path 1 ) 270 | break() 271 | endif() 272 | endforeach() 273 | 274 | if( __test_path AND NOT EXISTS "${${var_name}}" ) 275 | unset( ${var_name} CACHE ) 276 | endif() 277 | 278 | if( " ${${var_name}}" STREQUAL " " ) 279 | set( __values 0 ) 280 | foreach( __var ${ARGN} ) 281 | if( __var STREQUAL "VALUES" ) 282 | set( __values 1 ) 283 | elseif( NOT __var STREQUAL "PATH" ) 284 | if( __var MATCHES "^ENV_.*$" ) 285 | string( REPLACE "ENV_" "" __var "${__var}" ) 286 | set( __value "$ENV{${__var}}" ) 287 | elseif( DEFINED ${__var} ) 288 | set( __value "${${__var}}" ) 289 | elseif( __values ) 290 | set( __value "${__var}" ) 291 | else() 292 | set( __value "" ) 293 | endif() 294 | 295 | if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) 296 | set( ${var_name} "${__value}" ) 297 | break() 298 | endif() 299 | endif() 300 | endforeach() 301 | unset( __value ) 302 | unset( __values ) 303 | endif() 304 | 305 | if( __test_path ) 306 | file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) 307 | endif() 308 | unset( __test_path ) 309 | endmacro() 310 | 311 | macro( __DETECT_NATIVE_API_LEVEL _var _path ) 312 | set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) 313 | file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) 314 | if( NOT __apiFileContent ) 315 | message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) 316 | endif() 317 | string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) 318 | unset( __apiFileContent ) 319 | unset( __ndkApiLevelRegex ) 320 | endmacro() 321 | 322 | macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) 323 | if( EXISTS "${_root}" ) 324 | file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) 325 | __LIST_FILTER( __gccExePath "^[.].*" ) 326 | list( LENGTH __gccExePath __gccExePathsCount ) 327 | if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) 328 | message( WARNING "Could not determine machine name for compiler from ${_root}" ) 329 | set( ${_var} "" ) 330 | else() 331 | get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) 332 | string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) 333 | endif() 334 | unset( __gccExePath ) 335 | unset( __gccExePathsCount ) 336 | unset( __gccExeName ) 337 | else() 338 | set( ${_var} "" ) 339 | endif() 340 | endmacro() 341 | 342 | 343 | # fight against cygwin 344 | set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") 345 | mark_as_advanced( ANDROID_FORBID_SYGWIN ) 346 | if( ANDROID_FORBID_SYGWIN ) 347 | if( CYGWIN ) 348 | message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) 349 | endif() 350 | 351 | if( CMAKE_HOST_WIN32 ) 352 | # remove cygwin from PATH 353 | set( __new_path "$ENV{PATH}") 354 | __LIST_FILTER( __new_path "cygwin" ) 355 | set(ENV{PATH} "${__new_path}") 356 | unset(__new_path) 357 | endif() 358 | endif() 359 | 360 | 361 | # detect current host platform 362 | if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) 363 | set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) 364 | mark_as_advanced( ANDROID_NDK_HOST_X64 ) 365 | endif() 366 | 367 | set( TOOL_OS_SUFFIX "" ) 368 | if( CMAKE_HOST_APPLE ) 369 | set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) 370 | set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) 371 | elseif( CMAKE_HOST_WIN32 ) 372 | set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) 373 | set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) 374 | set( TOOL_OS_SUFFIX ".exe" ) 375 | elseif( CMAKE_HOST_UNIX ) 376 | set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) 377 | set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) 378 | else() 379 | message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) 380 | endif() 381 | 382 | if( NOT ANDROID_NDK_HOST_X64 ) 383 | set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) 384 | endif() 385 | 386 | # see if we have path to Android NDK 387 | if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) 388 | __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) 389 | endif() 390 | if( NOT ANDROID_NDK ) 391 | # see if we have path to Android standalone toolchain 392 | __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) 393 | 394 | if( NOT ANDROID_STANDALONE_TOOLCHAIN ) 395 | #try to find Android NDK in one of the the default locations 396 | set( __ndkSearchPaths ) 397 | foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) 398 | foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) 399 | list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) 400 | endforeach() 401 | endforeach() 402 | __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) 403 | unset( __ndkSearchPaths ) 404 | 405 | if( ANDROID_NDK ) 406 | message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) 407 | message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) 408 | else() 409 | #try to find Android standalone toolchain in one of the the default locations 410 | __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) 411 | 412 | if( ANDROID_STANDALONE_TOOLCHAIN ) 413 | message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) 414 | message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) 415 | endif( ANDROID_STANDALONE_TOOLCHAIN ) 416 | endif( ANDROID_NDK ) 417 | endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) 418 | endif( NOT ANDROID_NDK ) 419 | 420 | # remember found paths 421 | if( ANDROID_NDK ) 422 | get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) 423 | set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) 424 | set( BUILD_WITH_ANDROID_NDK True ) 425 | if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) 426 | file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) 427 | string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) 428 | else() 429 | set( ANDROID_NDK_RELEASE "r1x" ) 430 | set( ANDROID_NDK_RELEASE_FULL "unreleased" ) 431 | endif() 432 | string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) 433 | string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) 434 | math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) 435 | elseif( ANDROID_STANDALONE_TOOLCHAIN ) 436 | get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) 437 | # try to detect change 438 | if( CMAKE_AR ) 439 | string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) 440 | string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) 441 | if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) 442 | message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) 443 | endif() 444 | unset( __androidStandaloneToolchainPreviousPath ) 445 | unset( __length ) 446 | endif() 447 | set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) 448 | set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) 449 | else() 450 | list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) 451 | message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. 452 | You should either set an environment variable: 453 | export ANDROID_NDK=~/my-android-ndk 454 | or 455 | export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain 456 | or put the toolchain or NDK in the default path: 457 | sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk 458 | sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) 459 | endif() 460 | 461 | # android NDK layout 462 | if( BUILD_WITH_ANDROID_NDK ) 463 | if( NOT DEFINED ANDROID_NDK_LAYOUT ) 464 | # try to automatically detect the layout 465 | if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") 466 | set( ANDROID_NDK_LAYOUT "RELEASE" ) 467 | elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) 468 | set( ANDROID_NDK_LAYOUT "LINARO" ) 469 | elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) 470 | set( ANDROID_NDK_LAYOUT "ANDROID" ) 471 | endif() 472 | endif() 473 | set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) 474 | mark_as_advanced( ANDROID_NDK_LAYOUT ) 475 | if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) 476 | set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment 477 | set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) 478 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) 479 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) 480 | elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) 481 | set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment 482 | set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) 483 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) 484 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) 485 | else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" 486 | set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) 487 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) 488 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) 489 | endif() 490 | get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) 491 | 492 | # try to detect change of NDK 493 | if( CMAKE_AR ) 494 | string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) 495 | string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) 496 | if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) 497 | message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. 498 | " ) 499 | endif() 500 | unset( __androidNdkPreviousPath ) 501 | unset( __length ) 502 | endif() 503 | endif() 504 | 505 | 506 | # get all the details about standalone toolchain 507 | if( BUILD_WITH_STANDALONE_TOOLCHAIN ) 508 | __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) 509 | set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) 510 | set( __availableToolchains "standalone" ) 511 | __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) 512 | if( NOT __availableToolchainMachines ) 513 | message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) 514 | endif() 515 | if( __availableToolchainMachines MATCHES x86_64 ) 516 | set( __availableToolchainArchs "x86_64" ) 517 | elseif( __availableToolchainMachines MATCHES i686 ) 518 | set( __availableToolchainArchs "x86" ) 519 | elseif( __availableToolchainMachines MATCHES aarch64 ) 520 | set( __availableToolchainArchs "arm64" ) 521 | elseif( __availableToolchainMachines MATCHES arm ) 522 | set( __availableToolchainArchs "arm" ) 523 | elseif( __availableToolchainMachines MATCHES mips64el ) 524 | set( __availableToolchainArchs "mips64" ) 525 | elseif( __availableToolchainMachines MATCHES mipsel ) 526 | set( __availableToolchainArchs "mips" ) 527 | endif() 528 | execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion 529 | OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) 530 | string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) 531 | if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) 532 | list( APPEND __availableToolchains "standalone-clang" ) 533 | list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) 534 | list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) 535 | list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) 536 | endif() 537 | endif() 538 | 539 | macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) 540 | foreach( __toolchain ${${__availableToolchainsLst}} ) 541 | if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) 542 | SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) 543 | FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) 544 | if( __toolchainVersionStr ) 545 | string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) 546 | string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) 547 | else() 548 | string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) 549 | endif() 550 | unset( __toolchainVersionStr ) 551 | unset( __toolchainVersionRegex ) 552 | else() 553 | set( __gcc_toolchain "${__toolchain}" ) 554 | endif() 555 | __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) 556 | if( __machine ) 557 | string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) 558 | if( __machine MATCHES x86_64 ) 559 | set( __arch "x86_64" ) 560 | elseif( __machine MATCHES i686 ) 561 | set( __arch "x86" ) 562 | elseif( __machine MATCHES aarch64 ) 563 | set( __arch "arm64" ) 564 | elseif( __machine MATCHES arm ) 565 | set( __arch "arm" ) 566 | elseif( __machine MATCHES mips64el ) 567 | set( __arch "mips64" ) 568 | elseif( __machine MATCHES mipsel ) 569 | set( __arch "mips" ) 570 | else() 571 | set( __arch "" ) 572 | endif() 573 | #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") 574 | if (__arch) 575 | list( APPEND __availableToolchainMachines "${__machine}" ) 576 | list( APPEND __availableToolchainArchs "${__arch}" ) 577 | list( APPEND __availableToolchainCompilerVersions "${__version}" ) 578 | list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) 579 | endif() 580 | endif() 581 | unset( __gcc_toolchain ) 582 | endforeach() 583 | endmacro() 584 | 585 | # get all the details about NDK 586 | if( BUILD_WITH_ANDROID_NDK ) 587 | file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) 588 | string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) 589 | set( __availableToolchains "" ) 590 | set( __availableToolchainMachines "" ) 591 | set( __availableToolchainArchs "" ) 592 | set( __availableToolchainCompilerVersions "" ) 593 | if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) 594 | # do not go through all toolchains if we know the name 595 | set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) 596 | __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) 597 | if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) 598 | __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) 599 | if( __availableToolchains ) 600 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) 601 | endif() 602 | endif() 603 | endif() 604 | if( NOT __availableToolchains ) 605 | file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) 606 | if( __availableToolchainsLst ) 607 | list(SORT __availableToolchainsLst) # we need clang to go after gcc 608 | endif() 609 | __LIST_FILTER( __availableToolchainsLst "^[.]" ) 610 | __LIST_FILTER( __availableToolchainsLst "llvm" ) 611 | __LIST_FILTER( __availableToolchainsLst "renderscript" ) 612 | __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) 613 | if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) 614 | __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) 615 | if( __availableToolchains ) 616 | set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) 617 | endif() 618 | endif() 619 | endif() 620 | if( NOT __availableToolchains ) 621 | message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) 622 | endif() 623 | endif() 624 | 625 | # build list of available ABIs 626 | set( ANDROID_SUPPORTED_ABIS "" ) 627 | set( __uniqToolchainArchNames ${__availableToolchainArchs} ) 628 | list( REMOVE_DUPLICATES __uniqToolchainArchNames ) 629 | list( SORT __uniqToolchainArchNames ) 630 | foreach( __arch ${__uniqToolchainArchNames} ) 631 | list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) 632 | endforeach() 633 | unset( __uniqToolchainArchNames ) 634 | if( NOT ANDROID_SUPPORTED_ABIS ) 635 | message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) 636 | endif() 637 | 638 | # choose target ABI 639 | __INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) 640 | # verify that target ABI is supported 641 | list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) 642 | if( __androidAbiIdx EQUAL -1 ) 643 | string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) 644 | message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. 645 | Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" 646 | " ) 647 | endif() 648 | unset( __androidAbiIdx ) 649 | 650 | # set target ABI options 651 | if( ANDROID_ABI STREQUAL "x86" ) 652 | set( X86 true ) 653 | set( ANDROID_NDK_ABI_NAME "x86" ) 654 | set( ANDROID_ARCH_NAME "x86" ) 655 | set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) 656 | set( CMAKE_SYSTEM_PROCESSOR "i686" ) 657 | elseif( ANDROID_ABI STREQUAL "x86_64" ) 658 | set( X86 true ) 659 | set( X86_64 true ) 660 | set( ANDROID_NDK_ABI_NAME "x86_64" ) 661 | set( ANDROID_ARCH_NAME "x86_64" ) 662 | set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) 663 | set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) 664 | elseif( ANDROID_ABI STREQUAL "mips64" ) 665 | set( MIPS64 true ) 666 | set( ANDROID_NDK_ABI_NAME "mips64" ) 667 | set( ANDROID_ARCH_NAME "mips64" ) 668 | set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) 669 | set( CMAKE_SYSTEM_PROCESSOR "mips64" ) 670 | elseif( ANDROID_ABI STREQUAL "mips" ) 671 | set( MIPS true ) 672 | set( ANDROID_NDK_ABI_NAME "mips" ) 673 | set( ANDROID_ARCH_NAME "mips" ) 674 | set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) 675 | set( CMAKE_SYSTEM_PROCESSOR "mips" ) 676 | elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) 677 | set( ARM64_V8A true ) 678 | set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) 679 | set( ANDROID_ARCH_NAME "arm64" ) 680 | set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) 681 | set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) 682 | set( VFPV3 true ) 683 | set( NEON true ) 684 | elseif( ANDROID_ABI STREQUAL "armeabi" ) 685 | set( ARMEABI true ) 686 | set( ANDROID_NDK_ABI_NAME "armeabi" ) 687 | set( ANDROID_ARCH_NAME "arm" ) 688 | set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) 689 | set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) 690 | elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) 691 | set( ARMEABI_V6 true ) 692 | set( ANDROID_NDK_ABI_NAME "armeabi" ) 693 | set( ANDROID_ARCH_NAME "arm" ) 694 | set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) 695 | set( CMAKE_SYSTEM_PROCESSOR "armv6" ) 696 | # need always fallback to older platform 697 | set( ARMEABI true ) 698 | elseif( ANDROID_ABI STREQUAL "armeabi-v7a") 699 | set( ARMEABI_V7A true ) 700 | set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) 701 | set( ANDROID_ARCH_NAME "arm" ) 702 | set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) 703 | set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) 704 | elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) 705 | set( ARMEABI_V7A true ) 706 | set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) 707 | set( ANDROID_ARCH_NAME "arm" ) 708 | set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) 709 | set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) 710 | set( VFPV3 true ) 711 | elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) 712 | set( ARMEABI_V7A true ) 713 | set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) 714 | set( ANDROID_ARCH_NAME "arm" ) 715 | set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) 716 | set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) 717 | set( VFPV3 true ) 718 | set( NEON true ) 719 | elseif( ANDROID_ABI STREQUAL "armeabi-v7a-hard with NEON" ) 720 | set( ARMEABI_V7A_HARD true ) 721 | set( ANDROID_NDK_ABI_NAME "armeabi-v7a-hard" ) 722 | set( ANDROID_ARCH_NAME "arm" ) 723 | set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) 724 | set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) 725 | set( VFPV3 true ) 726 | set( NEON true ) 727 | else() 728 | message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) 729 | endif() 730 | 731 | if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) 732 | # really dirty hack 733 | # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... 734 | file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) 735 | endif() 736 | 737 | if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) 738 | __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) 739 | set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) 740 | mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) 741 | else() 742 | unset( ANDROID_FORCE_ARM_BUILD CACHE ) 743 | endif() 744 | 745 | # choose toolchain 746 | if( ANDROID_TOOLCHAIN_NAME ) 747 | list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) 748 | if( __toolchainIdx EQUAL -1 ) 749 | list( SORT __availableToolchains ) 750 | string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) 751 | set( toolchains_list " * ${toolchains_list}") 752 | message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. 753 | To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) 754 | endif() 755 | list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) 756 | if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) 757 | message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) 758 | endif() 759 | else() 760 | set( __toolchainIdx -1 ) 761 | set( __applicableToolchains "" ) 762 | set( __toolchainMaxVersion "0.0.0" ) 763 | list( LENGTH __availableToolchains __availableToolchainsCount ) 764 | math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) 765 | foreach( __idx RANGE ${__availableToolchainsCount} ) 766 | list( GET __availableToolchainArchs ${__idx} __toolchainArch ) 767 | if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) 768 | list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) 769 | string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") 770 | if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) 771 | set( __toolchainMaxVersion "${__toolchainVersion}" ) 772 | set( __toolchainIdx ${__idx} ) 773 | endif() 774 | endif() 775 | endforeach() 776 | unset( __availableToolchainsCount ) 777 | unset( __toolchainMaxVersion ) 778 | unset( __toolchainVersion ) 779 | endif() 780 | unset( __toolchainArch ) 781 | if( __toolchainIdx EQUAL -1 ) 782 | message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) 783 | endif() 784 | list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) 785 | list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) 786 | list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) 787 | 788 | unset( __toolchainIdx ) 789 | unset( __availableToolchains ) 790 | unset( __availableToolchainMachines ) 791 | unset( __availableToolchainArchs ) 792 | unset( __availableToolchainCompilerVersions ) 793 | 794 | # choose native API level 795 | __INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) 796 | string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) 797 | string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) 798 | # adjust API level 799 | set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) 800 | foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) 801 | if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) 802 | set( __real_api_level ${__level} ) 803 | endif() 804 | endforeach() 805 | if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) 806 | message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") 807 | set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) 808 | endif() 809 | unset(__real_api_level) 810 | # validate 811 | list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) 812 | if( __levelIdx EQUAL -1 ) 813 | message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) 814 | else() 815 | if( BUILD_WITH_ANDROID_NDK ) 816 | __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) 817 | if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) 818 | message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) 819 | endif() 820 | unset( __realApiLevel ) 821 | endif() 822 | set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) 823 | set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) 824 | if( CMAKE_VERSION VERSION_GREATER "2.8" ) 825 | list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) 826 | set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) 827 | endif() 828 | endif() 829 | unset( __levelIdx ) 830 | 831 | 832 | # remember target ABI 833 | set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) 834 | if( CMAKE_VERSION VERSION_GREATER "2.8" ) 835 | list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) 836 | set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) 837 | endif() 838 | 839 | 840 | # runtime choice (STL, rtti, exceptions) 841 | if( NOT ANDROID_STL ) 842 | set( ANDROID_STL gnustl_static ) 843 | endif() 844 | set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) 845 | set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) 846 | mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) 847 | 848 | if( BUILD_WITH_ANDROID_NDK ) 849 | if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$") 850 | message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". 851 | The possible values are: 852 | none -> Do not configure the runtime. 853 | system -> Use the default minimal system C++ runtime library. 854 | system_re -> Same as system but with rtti and exceptions. 855 | gabi++_static -> Use the GAbi++ runtime as a static library. 856 | gabi++_shared -> Use the GAbi++ runtime as a shared library. 857 | stlport_static -> Use the STLport runtime as a static library. 858 | stlport_shared -> Use the STLport runtime as a shared library. 859 | gnustl_static -> (default) Use the GNU STL as a static library. 860 | gnustl_shared -> Use the GNU STL as a shared library. 861 | c++_shared -> Use the LLVM libc++ runtime as a shared library. 862 | c++_static -> Use the LLVM libc++ runtime as a static library. 863 | " ) 864 | endif() 865 | elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) 866 | if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$") 867 | message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". 868 | The possible values are: 869 | none -> Do not configure the runtime. 870 | gnustl_static -> (default) Use the GNU STL as a static library. 871 | gnustl_shared -> Use the GNU STL as a shared library. 872 | c++_shared -> Use the LLVM libc++ runtime as a shared library. 873 | c++_static -> Use the LLVM libc++ runtime as a static library. 874 | " ) 875 | endif() 876 | endif() 877 | 878 | unset( ANDROID_RTTI ) 879 | unset( ANDROID_EXCEPTIONS ) 880 | unset( ANDROID_STL_INCLUDE_DIRS ) 881 | unset( __libstl ) 882 | unset( __libsupcxx ) 883 | 884 | if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) 885 | message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). 886 | You are strongly recommended to switch to another NDK release. 887 | " ) 888 | endif() 889 | 890 | if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) 891 | message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: 892 | See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 893 | diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h 894 | index 5e28c64..65892a1 100644 895 | --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h 896 | +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h 897 | @@ -51,7 +51,11 @@ typedef long int ssize_t; 898 | #endif 899 | #ifndef _PTRDIFF_T 900 | #define _PTRDIFF_T 901 | -typedef long ptrdiff_t; 902 | +# ifdef __ANDROID__ 903 | + typedef int ptrdiff_t; 904 | +# else 905 | + typedef long ptrdiff_t; 906 | +# endif 907 | #endif 908 | " ) 909 | endif() 910 | 911 | 912 | # setup paths and STL for standalone toolchain 913 | if( BUILD_WITH_STANDALONE_TOOLCHAIN ) 914 | set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) 915 | set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) 916 | set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) 917 | 918 | if( NOT ANDROID_STL STREQUAL "none" ) 919 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) 920 | if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) 921 | # old location ( pre r8c ) 922 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) 923 | endif() 924 | if( (ARMEABI_V7A OR ARMEABI_V7A_HARD) AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) 925 | list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) 926 | elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) 927 | list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) 928 | else() 929 | list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) 930 | endif() 931 | # always search static GNU STL to get the location of libsupc++.a 932 | if( (ARMEABI_V7A OR ARMEABI_V7A_HARD) AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) 933 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) 934 | elseif( (ARMEABI_V7A OR ARMEABI_V7A_HARD) AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) 935 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) 936 | elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) 937 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) 938 | elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) 939 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) 940 | endif() 941 | if( __libstl ) 942 | set( __libsupcxx "${__libstl}/libsupc++.a" ) 943 | set( __libstl "${__libstl}/libstdc++.a" ) 944 | endif() 945 | if( NOT EXISTS "${__libsupcxx}" ) 946 | message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. 947 | Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. 948 | You need to either upgrade to newer NDK or manually copy 949 | $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a 950 | to 951 | ${__libsupcxx} 952 | " ) 953 | endif() 954 | if( ANDROID_STL STREQUAL "gnustl_shared" ) 955 | if( (ARMEABI_V7A OR ARMEABI_V7A_HARD) AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) 956 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) 957 | elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) 958 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) 959 | elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) 960 | set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) 961 | endif() 962 | endif() 963 | endif() 964 | endif() 965 | 966 | # clang 967 | if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) 968 | set( ANDROID_COMPILER_IS_CLANG 1 ) 969 | execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) 970 | string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") 971 | elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) 972 | string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") 973 | string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) 974 | if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) 975 | message( FATAL_ERROR "Could not find the Clang compiler driver" ) 976 | endif() 977 | set( ANDROID_COMPILER_IS_CLANG 1 ) 978 | set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) 979 | else() 980 | set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) 981 | unset( ANDROID_COMPILER_IS_CLANG CACHE ) 982 | endif() 983 | 984 | string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) 985 | if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) 986 | set( _clang_name "clang" ) 987 | endif() 988 | 989 | 990 | # setup paths and STL for NDK 991 | if( BUILD_WITH_ANDROID_NDK ) 992 | set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) 993 | set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) 994 | 995 | if( ANDROID_STL STREQUAL "none" ) 996 | # do nothing 997 | elseif( ANDROID_STL STREQUAL "system" ) 998 | set( ANDROID_RTTI OFF ) 999 | set( ANDROID_EXCEPTIONS OFF ) 1000 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) 1001 | elseif( ANDROID_STL STREQUAL "system_re" ) 1002 | set( ANDROID_RTTI ON ) 1003 | set( ANDROID_EXCEPTIONS ON ) 1004 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) 1005 | elseif( ANDROID_STL MATCHES "gabi" ) 1006 | if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 1007 | message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") 1008 | endif() 1009 | set( ANDROID_RTTI ON ) 1010 | set( ANDROID_EXCEPTIONS OFF ) 1011 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) 1012 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) 1013 | elseif( ANDROID_STL MATCHES "stlport" ) 1014 | if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d 1015 | set( ANDROID_EXCEPTIONS ON ) 1016 | else() 1017 | set( ANDROID_EXCEPTIONS OFF ) 1018 | endif() 1019 | if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 1020 | set( ANDROID_RTTI OFF ) 1021 | else() 1022 | set( ANDROID_RTTI ON ) 1023 | endif() 1024 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) 1025 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) 1026 | elseif( ANDROID_STL MATCHES "gnustl" ) 1027 | set( ANDROID_EXCEPTIONS ON ) 1028 | set( ANDROID_RTTI ON ) 1029 | if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) 1030 | if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) 1031 | # gnustl binary for 4.7 compiler is buggy :( 1032 | # TODO: look for right fix 1033 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) 1034 | else() 1035 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) 1036 | endif() 1037 | else() 1038 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) 1039 | endif() 1040 | set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) 1041 | if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) 1042 | set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) 1043 | else() 1044 | set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) 1045 | endif() 1046 | elseif( ANDROID_STL MATCHES "c\\+\\+" ) 1047 | set( ANDROID_EXCEPTIONS ON ) 1048 | set( ANDROID_RTTI ON ) 1049 | set( __libstl "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++" ) 1050 | set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libc++_static.a" ) 1051 | set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/android/support/include" "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx/include" "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++abi/libcxxabi/include" ) 1052 | else() 1053 | message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) 1054 | endif() 1055 | 1056 | # find libsupc++.a - rtti & exceptions 1057 | if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) 1058 | set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer 1059 | if( NOT EXISTS "${__libsupcxx}" ) 1060 | set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 1061 | endif() 1062 | if( NOT EXISTS "${__libsupcxx}" ) # before r7 1063 | if( ARMEABI_V7A ) 1064 | if( ANDROID_FORCE_ARM_BUILD ) 1065 | set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) 1066 | else() 1067 | set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) 1068 | endif() 1069 | elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) 1070 | set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) 1071 | else() 1072 | set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) 1073 | endif() 1074 | endif() 1075 | if( NOT EXISTS "${__libsupcxx}") 1076 | message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") 1077 | endif() 1078 | endif() 1079 | endif() 1080 | 1081 | 1082 | # case of shared STL linkage 1083 | if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) 1084 | string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) 1085 | if( NOT EXISTS "${__libstl}" ) 1086 | message( FATAL_ERROR "Unable to find shared library ${__libstl}" ) 1087 | endif() 1088 | endif() 1089 | 1090 | 1091 | # ccache support 1092 | __INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) 1093 | if( _ndk_ccache ) 1094 | if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) 1095 | unset( NDK_CCACHE CACHE ) 1096 | endif() 1097 | find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") 1098 | else() 1099 | unset( NDK_CCACHE CACHE ) 1100 | endif() 1101 | unset( _ndk_ccache ) 1102 | 1103 | 1104 | # setup the cross-compiler 1105 | if( NOT CMAKE_C_COMPILER ) 1106 | if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) 1107 | set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) 1108 | set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) 1109 | if( ANDROID_COMPILER_IS_CLANG ) 1110 | set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") 1111 | set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") 1112 | else() 1113 | set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") 1114 | set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") 1115 | endif() 1116 | else() 1117 | if( ANDROID_COMPILER_IS_CLANG ) 1118 | set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") 1119 | set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") 1120 | else() 1121 | set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) 1122 | set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) 1123 | endif() 1124 | endif() 1125 | set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) 1126 | set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) 1127 | if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" ) 1128 | # Use gcc-ar if we have it for better LTO support. 1129 | set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) 1130 | else() 1131 | set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) 1132 | endif() 1133 | set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) 1134 | set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) 1135 | set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) 1136 | set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) 1137 | set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) 1138 | endif() 1139 | 1140 | set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) 1141 | if( CMAKE_VERSION VERSION_LESS 2.8.5 ) 1142 | set( CMAKE_ASM_COMPILER_ARG1 "-c" ) 1143 | endif() 1144 | if( APPLE ) 1145 | find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) 1146 | if( NOT CMAKE_INSTALL_NAME_TOOL ) 1147 | message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) 1148 | endif() 1149 | mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) 1150 | endif() 1151 | 1152 | # Force set compilers because standard identification works badly for us 1153 | if( CMAKE_VERSION VERSION_LESS 3.5.0 ) 1154 | include( CMakeForceCompiler ) 1155 | CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) 1156 | endif() 1157 | if( ANDROID_COMPILER_IS_CLANG ) 1158 | set( CMAKE_C_COMPILER_ID Clang ) 1159 | endif() 1160 | set( CMAKE_C_PLATFORM_ID Linux ) 1161 | if( X86_64 OR MIPS64 OR ARM64_V8A ) 1162 | set( CMAKE_C_SIZEOF_DATA_PTR 8 ) 1163 | else() 1164 | set( CMAKE_C_SIZEOF_DATA_PTR 4 ) 1165 | endif() 1166 | set( CMAKE_C_HAS_ISYSROOT 1 ) 1167 | set( CMAKE_C_COMPILER_ABI ELF ) 1168 | if( CMAKE_VERSION VERSION_LESS 3.5.0 ) 1169 | CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) 1170 | endif() 1171 | if( ANDROID_COMPILER_IS_CLANG ) 1172 | set( CMAKE_CXX_COMPILER_ID Clang) 1173 | endif() 1174 | set( CMAKE_CXX_PLATFORM_ID Linux ) 1175 | set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) 1176 | set( CMAKE_CXX_HAS_ISYSROOT 1 ) 1177 | set( CMAKE_CXX_COMPILER_ABI ELF ) 1178 | set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) 1179 | # force ASM compiler (required for CMake < 2.8.5) 1180 | set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) 1181 | set( CMAKE_ASM_COMPILER_ID GNU ) 1182 | set( CMAKE_ASM_COMPILER_WORKS TRUE ) 1183 | set( CMAKE_ASM_COMPILER_FORCED TRUE ) 1184 | set( CMAKE_COMPILER_IS_GNUASM 1) 1185 | set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) 1186 | 1187 | foreach( lang C CXX ASM ) 1188 | if( ANDROID_COMPILER_IS_CLANG ) 1189 | set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) 1190 | else() 1191 | set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) 1192 | endif() 1193 | endforeach() 1194 | 1195 | # flags and definitions 1196 | remove_definitions( -DANDROID ) 1197 | add_definitions( -DANDROID ) 1198 | 1199 | if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) 1200 | if( CMAKE_HOST_WIN32 ) 1201 | # try to convert path to 8.3 form 1202 | file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) 1203 | execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" 1204 | OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE 1205 | RESULT_VARIABLE __result ERROR_QUIET ) 1206 | if( __result EQUAL 0 ) 1207 | file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) 1208 | set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) 1209 | else() 1210 | set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) 1211 | endif() 1212 | else() 1213 | set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) 1214 | endif() 1215 | if( NOT _CMAKE_IN_TRY_COMPILE ) 1216 | # quotes can break try_compile and compiler identification 1217 | message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") 1218 | endif() 1219 | else() 1220 | set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) 1221 | endif() 1222 | 1223 | # NDK flags 1224 | if (ARM64_V8A ) 1225 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) 1226 | set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) 1227 | set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) 1228 | if( NOT ANDROID_COMPILER_IS_CLANG ) 1229 | set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) 1230 | endif() 1231 | elseif( ARMEABI OR ARMEABI_V7A OR ARMEABI_V7A_HARD) 1232 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) 1233 | if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) 1234 | set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) 1235 | set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) 1236 | if( NOT ANDROID_COMPILER_IS_CLANG ) 1237 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) 1238 | endif() 1239 | else() 1240 | # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI 1241 | set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) 1242 | set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) 1243 | if( NOT ANDROID_COMPILER_IS_CLANG ) 1244 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) 1245 | endif() 1246 | endif() 1247 | elseif( X86 OR X86_64 ) 1248 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) 1249 | if( NOT ANDROID_COMPILER_IS_CLANG ) 1250 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) 1251 | endif() 1252 | set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) 1253 | set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) 1254 | elseif( MIPS OR MIPS64 ) 1255 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) 1256 | set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) 1257 | set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) 1258 | if( NOT ANDROID_COMPILER_IS_CLANG ) 1259 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) 1260 | set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) 1261 | endif() 1262 | elseif() 1263 | set( ANDROID_CXX_FLAGS_RELEASE "" ) 1264 | set( ANDROID_CXX_FLAGS_DEBUG "" ) 1265 | endif() 1266 | 1267 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries 1268 | 1269 | if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) 1270 | set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) 1271 | endif() 1272 | 1273 | if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) 1274 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ 1275 | endif() 1276 | 1277 | # ABI-specific flags 1278 | if( ARMEABI_V7A_HARD ) 1279 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=hard -mhard-float -D_NDK_MATH_NO_SOFTFP=1" ) 1280 | if( NEON ) 1281 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) 1282 | elseif( VFPV3 ) 1283 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) 1284 | else() 1285 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) 1286 | endif() 1287 | elseif( ARMEABI_V7A ) 1288 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) 1289 | if( NEON ) 1290 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) 1291 | elseif( VFPV3 ) 1292 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) 1293 | else() 1294 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) 1295 | endif() 1296 | 1297 | elseif( ARMEABI_V6 ) 1298 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 1299 | elseif( ARMEABI ) 1300 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) 1301 | endif() 1302 | 1303 | if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) 1304 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) 1305 | set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) 1306 | set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) 1307 | else() 1308 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) 1309 | set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) 1310 | set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) 1311 | endif() 1312 | 1313 | # STL 1314 | if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) 1315 | if( EXISTS "${__libstl}" ) 1316 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) 1317 | set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) 1318 | set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) 1319 | endif() 1320 | if( EXISTS "${__libsupcxx}" ) 1321 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) 1322 | set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) 1323 | set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) 1324 | # C objects: 1325 | set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) 1326 | set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) 1327 | set( CMAKE_C_LINK_EXECUTABLE " -o " ) 1328 | set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) 1329 | set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) 1330 | set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) 1331 | endif() 1332 | if( ANDROID_STL MATCHES "gnustl" ) 1333 | if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) 1334 | set( ANDROID_LIBM_PATH -lm ) 1335 | endif() 1336 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) 1337 | set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) 1338 | set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) 1339 | endif() 1340 | endif() 1341 | 1342 | # variables controlling optional build flags 1343 | if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 1344 | # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. 1345 | # So this flag option is required for all projects using OpenGL from native. 1346 | __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) 1347 | else() 1348 | __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) 1349 | endif() 1350 | __INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) 1351 | __INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) 1352 | __INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) 1353 | __INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) 1354 | __INIT_VARIABLE( ANDROID_RELRO VALUES ON ) 1355 | 1356 | set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) 1357 | set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) 1358 | set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) 1359 | set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) 1360 | set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) 1361 | set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) 1362 | mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) 1363 | 1364 | # linker flags 1365 | set( ANDROID_LINKER_FLAGS "" ) 1366 | 1367 | if( ARMEABI_V7A ) 1368 | # this is *required* to use the following linker flags that routes around 1369 | # a CPU bug in some Cortex-A8 implementations: 1370 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) 1371 | endif() 1372 | 1373 | if( ARMEABI_V7A_HARD ) 1374 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-warn-mismatch -lm_hard" ) 1375 | endif() 1376 | 1377 | if( ANDROID_NO_UNDEFINED ) 1378 | if( MIPS ) 1379 | # there is some sysroot-related problem in mips linker... 1380 | if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) 1381 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) 1382 | endif() 1383 | else() 1384 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) 1385 | endif() 1386 | endif() 1387 | 1388 | if( ANDROID_SO_UNDEFINED ) 1389 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) 1390 | endif() 1391 | 1392 | if( ANDROID_FUNCTION_LEVEL_LINKING ) 1393 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) 1394 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) 1395 | endif() 1396 | 1397 | if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) 1398 | if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR ARMEABI_V7A_HARD OR X86) ) 1399 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) 1400 | elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b 1401 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) 1402 | elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) 1403 | message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 1404 | On Linux and OS X host platform you can workaround this problem using gold linker (default). 1405 | Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. 1406 | " ) 1407 | endif() 1408 | endif() # version 4.6 1409 | 1410 | if( ANDROID_NOEXECSTACK ) 1411 | if( ANDROID_COMPILER_IS_CLANG ) 1412 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) 1413 | else() 1414 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) 1415 | endif() 1416 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) 1417 | endif() 1418 | 1419 | if( ANDROID_RELRO ) 1420 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) 1421 | endif() 1422 | 1423 | if( ANDROID_COMPILER_IS_CLANG ) 1424 | set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) 1425 | if( BUILD_WITH_ANDROID_NDK ) 1426 | set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) 1427 | endif() 1428 | endif() 1429 | 1430 | # cache flags 1431 | set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) 1432 | set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) 1433 | set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) 1434 | set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) 1435 | set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) 1436 | set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) 1437 | set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) 1438 | set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) 1439 | set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) 1440 | 1441 | # put flags to cache (for debug purpose only) 1442 | set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) 1443 | set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) 1444 | set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) 1445 | set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) 1446 | 1447 | # finish flags 1448 | set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) 1449 | set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) 1450 | set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) 1451 | set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) 1452 | set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) 1453 | set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) 1454 | set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) 1455 | set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) 1456 | set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) 1457 | 1458 | if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) 1459 | set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) 1460 | set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) 1461 | set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) 1462 | endif() 1463 | 1464 | # pie/pic 1465 | if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) 1466 | set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) 1467 | set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") 1468 | else() 1469 | set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) 1470 | set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) 1471 | set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) 1472 | endif() 1473 | 1474 | # configure rtti 1475 | if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) 1476 | if( ANDROID_RTTI ) 1477 | set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) 1478 | else() 1479 | set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) 1480 | endif() 1481 | endif() 1482 | 1483 | # configure exceptios 1484 | if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) 1485 | if( ANDROID_EXCEPTIONS ) 1486 | set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) 1487 | set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) 1488 | else() 1489 | set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) 1490 | set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) 1491 | endif() 1492 | endif() 1493 | 1494 | # global includes and link directories 1495 | include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) 1496 | get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning 1497 | link_directories( "${__android_install_path}" ) 1498 | 1499 | # detect if need link crtbegin_so.o explicitly 1500 | if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) 1501 | set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) 1502 | string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) 1503 | string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) 1504 | string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) 1505 | string( REPLACE "" "" __cmd "${__cmd}" ) 1506 | string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) 1507 | string( REPLACE "" "-shared" __cmd "${__cmd}" ) 1508 | string( REPLACE "" "" __cmd "${__cmd}" ) 1509 | string( REPLACE "" "" __cmd "${__cmd}" ) 1510 | string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) 1511 | string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) 1512 | string( REPLACE "" "" __cmd "${__cmd}" ) 1513 | separate_arguments( __cmd ) 1514 | foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) 1515 | if( ${__var} ) 1516 | set( __tmp "${${__var}}" ) 1517 | separate_arguments( __tmp ) 1518 | string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") 1519 | endif() 1520 | endforeach() 1521 | string( REPLACE "'" "" __cmd "${__cmd}" ) 1522 | string( REPLACE "\"" "" __cmd "${__cmd}" ) 1523 | execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) 1524 | if( __cmd_result EQUAL 0 ) 1525 | set( ANDROID_EXPLICIT_CRT_LINK ON ) 1526 | else() 1527 | set( ANDROID_EXPLICIT_CRT_LINK OFF ) 1528 | endif() 1529 | endif() 1530 | 1531 | if( ANDROID_EXPLICIT_CRT_LINK ) 1532 | set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) 1533 | set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) 1534 | endif() 1535 | 1536 | # setup output directories 1537 | set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) 1538 | 1539 | if( DEFINED LIBRARY_OUTPUT_PATH_ROOT 1540 | OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" 1541 | OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) 1542 | set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) 1543 | if( NOT _CMAKE_IN_TRY_COMPILE ) 1544 | if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) 1545 | set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) 1546 | else() 1547 | set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) 1548 | endif() 1549 | set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) 1550 | endif() 1551 | endif() 1552 | 1553 | # copy shaed stl library to build directory 1554 | if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) 1555 | get_filename_component( __libstlname "${__libstl}" NAME ) 1556 | execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) 1557 | if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") 1558 | message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) 1559 | endif() 1560 | unset( __fileCopyProcess ) 1561 | unset( __libstlname ) 1562 | endif() 1563 | 1564 | 1565 | # set these global flags for cmake client scripts to change behavior 1566 | set( ANDROID True ) 1567 | set( BUILD_ANDROID True ) 1568 | 1569 | # where is the target environment 1570 | set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) 1571 | 1572 | # only search for libraries and includes in the ndk toolchain 1573 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) 1574 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) 1575 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) 1576 | 1577 | 1578 | # macro to find packages on the host OS 1579 | macro( find_host_package ) 1580 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) 1581 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) 1582 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) 1583 | if( CMAKE_HOST_WIN32 ) 1584 | SET( WIN32 1 ) 1585 | SET( UNIX ) 1586 | elseif( CMAKE_HOST_APPLE ) 1587 | SET( APPLE 1 ) 1588 | SET( UNIX ) 1589 | endif() 1590 | find_package( ${ARGN} ) 1591 | SET( WIN32 ) 1592 | SET( APPLE ) 1593 | SET( UNIX 1 ) 1594 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) 1595 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) 1596 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) 1597 | endmacro() 1598 | 1599 | 1600 | # macro to find programs on the host OS 1601 | macro( find_host_program ) 1602 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) 1603 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) 1604 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) 1605 | if( CMAKE_HOST_WIN32 ) 1606 | SET( WIN32 1 ) 1607 | SET( UNIX ) 1608 | elseif( CMAKE_HOST_APPLE ) 1609 | SET( APPLE 1 ) 1610 | SET( UNIX ) 1611 | endif() 1612 | find_program( ${ARGN} ) 1613 | SET( WIN32 ) 1614 | SET( APPLE ) 1615 | SET( UNIX 1 ) 1616 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) 1617 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) 1618 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) 1619 | endmacro() 1620 | 1621 | 1622 | # export toolchain settings for the try_compile() command 1623 | if( NOT _CMAKE_IN_TRY_COMPILE ) 1624 | set( __toolchain_config "") 1625 | foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN 1626 | ANDROID_NDK_HOST_X64 1627 | ANDROID_NDK 1628 | ANDROID_NDK_LAYOUT 1629 | ANDROID_STANDALONE_TOOLCHAIN 1630 | ANDROID_TOOLCHAIN_NAME 1631 | ANDROID_ABI 1632 | ANDROID_NATIVE_API_LEVEL 1633 | ANDROID_STL 1634 | ANDROID_STL_FORCE_FEATURES 1635 | ANDROID_FORCE_ARM_BUILD 1636 | ANDROID_NO_UNDEFINED 1637 | ANDROID_SO_UNDEFINED 1638 | ANDROID_FUNCTION_LEVEL_LINKING 1639 | ANDROID_GOLD_LINKER 1640 | ANDROID_NOEXECSTACK 1641 | ANDROID_RELRO 1642 | ANDROID_LIBM_PATH 1643 | ANDROID_EXPLICIT_CRT_LINK 1644 | ANDROID_APP_PIE 1645 | ) 1646 | if( DEFINED ${__var} ) 1647 | if( ${__var} MATCHES " ") 1648 | set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) 1649 | else() 1650 | set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) 1651 | endif() 1652 | endif() 1653 | endforeach() 1654 | file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) 1655 | unset( __toolchain_config ) 1656 | endif() 1657 | 1658 | 1659 | # force cmake to produce / instead of \ in build commands for Ninja generator 1660 | if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) 1661 | # it is a bad hack after all 1662 | # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW 1663 | set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW 1664 | set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion 1665 | enable_language( C ) 1666 | enable_language( CXX ) 1667 | # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it 1668 | unset( MINGW ) 1669 | endif() 1670 | 1671 | 1672 | # Variables controlling behavior or set by cmake toolchain: 1673 | # ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a-hard with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" 1674 | # ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) 1675 | # ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none 1676 | # ANDROID_FORBID_SYGWIN : ON/OFF 1677 | # ANDROID_NO_UNDEFINED : ON/OFF 1678 | # ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) 1679 | # ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF 1680 | # ANDROID_GOLD_LINKER : ON/OFF 1681 | # ANDROID_NOEXECSTACK : ON/OFF 1682 | # ANDROID_RELRO : ON/OFF 1683 | # ANDROID_FORCE_ARM_BUILD : ON/OFF 1684 | # ANDROID_STL_FORCE_FEATURES : ON/OFF 1685 | # ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` 1686 | # Can be set only at the first run: 1687 | # ANDROID_NDK : path to your NDK install 1688 | # NDK_CCACHE : path to your ccache executable 1689 | # ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain 1690 | # ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) 1691 | # ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) 1692 | # LIBRARY_OUTPUT_PATH_ROOT : 1693 | # ANDROID_STANDALONE_TOOLCHAIN 1694 | # 1695 | # Primary read-only variables: 1696 | # ANDROID : always TRUE 1697 | # ARMEABI : TRUE for arm v6 and older devices 1698 | # ARMEABI_V6 : TRUE for arm v6 1699 | # ARMEABI_V7A : TRUE for arm v7a 1700 | # ARMEABI_V7A_HARD : TRUE for arm v7a with hardfp 1701 | # ARM64_V8A : TRUE for arm64-v8a 1702 | # NEON : TRUE if NEON unit is enabled 1703 | # VFPV3 : TRUE if VFP version 3 is enabled 1704 | # X86 : TRUE if configured for x86 1705 | # X86_64 : TRUE if configured for x86_64 1706 | # MIPS : TRUE if configured for mips 1707 | # MIPS64 : TRUE if configured for mips64 1708 | # BUILD_WITH_ANDROID_NDK : TRUE if NDK is used 1709 | # BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used 1710 | # ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform 1711 | # ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "armeabi-v7a-hard", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI 1712 | # ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK 1713 | # ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) 1714 | # ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI 1715 | # ANDROID_SYSROOT : path to the compiler sysroot 1716 | # TOOL_OS_SUFFIX : "" or ".exe" depending on host platform 1717 | # ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used 1718 | # 1719 | # Secondary (less stable) read-only variables: 1720 | # ANDROID_COMPILER_VERSION : GCC version used (not Clang version) 1721 | # ANDROID_CLANG_VERSION : version of clang compiler if clang is used 1722 | # ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform 1723 | # ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI 1724 | # ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" 1725 | # ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) 1726 | # ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools 1727 | # ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK 1728 | # ANDROID_STL_INCLUDE_DIRS : stl include paths 1729 | # ANDROID_RTTI : if rtti is enabled by the runtime 1730 | # ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime 1731 | # ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used 1732 | # 1733 | # Defaults: 1734 | # ANDROID_DEFAULT_NDK_API_LEVEL 1735 | # ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} 1736 | # ANDROID_NDK_SEARCH_PATHS 1737 | # ANDROID_SUPPORTED_ABIS_${ARCH} 1738 | # ANDROID_SUPPORTED_NDK_VERSIONS 1739 | --------------------------------------------------------------------------------