OS: Ubuntu 20.04
MlPack(branch): master
I am trying to build a program which is dependent on mlpack
for android. For that I am using ndk-build. To make the library compatible for arm64 architecture, I have used buildroot environment 2020.08.1 to create the sysroot and aarch64-linux-gnu-gcc and aarch64-linux-gnu-g++. I have followed this link and set the following menuconfig to do that:
Target options → TargetArchitecture = AArch64 (Little Endian)
Toolchain → Toolchain type = External
Toolchain → Toolchain = Linaro AArch64
Filesystem images → enable "tar the root file system"
Then, in mlpack/build folder I have run the following command:
cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_MARKDOWN_BINDINGS=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF -DCMAKE_TOOLCHAIN_FILE=../board/crosscompile-toolchain.cmake -DBOARD_NAME="RPI4" -DDISABLE_DOWNLOADS=OFF -DTOOLCHAIN_PREFIX=//home/niaz/buildroot-2020.08.1/output/host/bin/aarch64-linux-gnu- -DCMAKE_SYSROOT=/home/niaz/buildroot-2020.08.1/output/host/arm64-buildroot-linux-gnu/sysroot ../
I followed this command here for that.
But after I try to compile the following code to ndk-build
, I get the error:
hello.hpp
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
class hello{
public:
string getJniString(string save_model_path);
};
hello.cpp
#include "hello.hpp"
#include "mlpack/core.hpp"
#include "mlpack/methods/random_forest/random_forest.hpp"
#include "mlpack/methods/decision_tree/random_dimension_select.hpp"
#include "mlpack/core/cv/k_fold_cv.hpp"
#include "mlpack/core/cv/metrics/accuracy.hpp"
#include "mlpack/core/cv/metrics/precision.hpp"
#include "mlpack/core/cv/metrics/recall.hpp"
using namespace arma;
using namespace mlpack;
using namespace mlpack::tree;
using namespace mlpack::cv;
using namespace std;
string hello::getJniString(string save_model_path){
string val = "";
mat dataset;
bool loaded = mlpack::data::Load("encoded_food.txt",dataset);
if (!loaded){
val = "failed to load";
return val;
}
Row<size_t> labels;
labels = conv_to<Row<size_t>>::from(dataset.row(dataset.n_rows - 1));
dataset.shed_row(dataset.n_rows - 1);
const size_t numClasses = 4;
const size_t minimumLeafSize = 5;
const size_t numTrees = 10;
RandomForest<GiniGain, RandomDimensionSelect> rf;
rf = RandomForest<GiniGain, RandomDimensionSelect>(dataset, labels,
numClasses, numTrees, minimumLeafSize);
Row<size_t> predictions;
rf.Classify(dataset, predictions);
const size_t correct = arma::accu(predictions == labels);
val = "Training Accuracy: " + to_string(double(correct) / double(labels.n_elem));
mlpack::data::Save(save_model_path, "model", rf, false);
return val;
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -I$(LOCAL_PATH)/boost
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/ -lboost_serialization-clang-mt-a64-1_74 -lboost_program_options-clang-mt-a64-1_74 -lmlpack
LOCAL_LDFLAGS += -Wl
LOCAL_CPPFLAGS += -frtti
LOCAL_CPPFLAGS += -fexceptions
LOCAL_CPPFLAGS += -fopenmp
LOCAL_CPPFLAGS += -fPIC
LOCAL_CFLAGS += -B/usr/lib/x86_64-linux-gnu
LOCAL_CPP_FEATURES += exceptions
LOCAL_MODULE = hello-jni-prebuilt
CODE_PATH := .
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libs/build/include $(LOCAL_PATH)
LOCAL_SRC_FILES = hello.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_PLATFORM := android-21
APP_CFLAGS += -Wno-error=format-security
APP_ABI := all
NDK_TOOLCHAIN_VERSION := clang++
APP_STL:= c++_static
APP_ALLOW_MISSING_DEPS=true
Error
ld: error: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol std::runtime_error::~runtime_error(); recompile with -fPIC
>>> defined in /home/niaz/NDK/android-ndk-r23b-linux/android-ndk-r23b/sources/cxx-stl/llvm-libc++abi/../llvm-libc++/libs/arm64-v8a/libc++abi.a(stdlib_stdexcept.o)
>>> referenced by prefixedoutstream.cpp
>>> prefixedoutstream.cpp.o:(_ZN6mlpack4util17PrefixedOutStream9BaseLogicIbEENSt9enable_ifIXntsrN4arma12is_arma_typeIT_EE5valueEvE4typeERKS6_) in archive /home/niaz/u/new/android-deliverables-24.2/jni/lib/libmlpack.a
I have found in some similar questions that adding -fPIC -WL -z
as flags should solve this issue. But I do not understand how to add them in Android.mk or Application.mk
Even if I add -fPIC to CFlags the error still occurs. I solve same issue by send
-Bsymbolic
to ld, see more at https://github.com/google/ExoPlayer/issues/9933#issuecomment-1029775358