I'm writing a simple proof of concept app that integrates OpenSSL using NDK. Unfortunately, it gives me undefined reference errors during build.
What I did:
Cross-compiled OpenSSL for Android (x86_64 is shown, and similarly for other ABIs):
openssl-1.1.1q $ ./Configure android-x86_64 openssl-1.1.1q $ make openssl-1.1.1q $ cp libssl.a <path_to_project_cpp_dir>/libs/x86_64/ openssl-1.1.1q $ cp -r ./include/openssl <path_to_project_cpp_dir>/libs/include/ Added the following CMakeLists.txt into project's cpp dir:
cmake_minimum_required(VERSION 3.18.1) project("ndk-poc") add_library( # Sets the name of the library. ndk-poc # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ndk-poc.cpp) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that you want CMake to locate. log) add_library(libssl STATIC IMPORTED) set_target_properties( # Specifies the target library. libssl # Specifies the parameter you want to define. PROPERTIES IMPORTED_LOCATION # Provides the path to the library you want to import. ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libssl.a ) include_directories(${CMAKE_SOURCE_DIR}/libs/include/) target_link_libraries( # Specifies the target library. ndk-poc # Links the target library to the log library # included in the NDK. libssl ${log-lib}) And this is my test ndk-poc.cpp:
#include <jni.h> #include <string> #include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/sha.h> extern "C" JNIEXPORT jstring JNICALL Java_com_techyourchance_android_screens_home_HomeFragment_stringFromJNI( JNIEnv* env, jobject /* this */) { /* Testing OPENSSL prime generation and BigNum. */ BIGNUM *prime1 = NULL; int bits = 16; /* Number of bits for the generated prime. */ int safe = 0; prime1 = BN_new(); if (prime1 == NULL) { printf("Out of memory.\n"); } else if (BN_generate_prime_ex(prime1, bits, safe, NULL, NULL, NULL)) { printf("Success!\n"); int len; len = BN_num_bytes(prime1); unsigned char* buffer; buffer = static_cast<unsigned char*>(malloc(len)); if (!buffer) { printf("Out of memory allocating buffer.\n"); } else { int wlen; wlen = BN_bn2bin(prime1, buffer); printf("Wrote %d bytes.\n", wlen); int i; for(i=0;i<wlen;++i) { printf("Byte %d of buffer = %d.\n", i, buffer[i]); } free(buffer); char* st; st = BN_bn2dec(prime1); printf("Prime = %s.\n", st); OPENSSL_free(st); } } else { printf("Error generating prime.\n"); } std::string result = "Test completed!"; return env->NewStringUTF(result.c_str()); } Results:
I don't see any errors inside Android Studio, but when I try building the project, all usages of OpenSSL's APIs in my test code result in unresolved reference errors:
... C:/Users/Vasiliy/projects/ndk-poc/app/src/main/cpp/ndk-poc.cpp:38: error: undefined reference to 'BN_bn2dec' C:/Users/Vasiliy/projects/ndk-poc/app/src/main/cpp/ndk-poc.cpp:40: error: undefined reference to 'CRYPTO_free' clang++: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. What did I miss?
include_directoriesbeforeadd_library.include_directoriesright afterproject, I still get the same errors.libcrypto? Or are you actually using anything fromlibsslspecifically?libcryptoinstead oflibsslresolved the issue. Funny thing is that I tried to link against both of them while debugging this issue, but probably made some other mistake because it also works. What a facepalm. Could you please post this as an answer so I could accept it?