Linking an Android shared native library to another

2 weeks ago 9
ARTICLE AD BOX

I'm trying to create an Android build for a native (C) library (https://github.com/MayaPosch/nymphrpc). This library has itself a dependency on another C library, Poco (https://github.com/pocoproject/poco).

I have a build.gradle.kts for Poco:

plugins { id("com.android.library") } android { namespace = "org.pocoproject.poco" compileSdk = 36 ndkVersion = "26.1.10909125" defaultConfig { minSdk = 21 targetSdk = 21 externalNativeBuild { cmake { arguments += "-DANDROID_STL=c++_shared" } } } externalNativeBuild { cmake { path = file("../../../poco/CMakeLists.txt") } } buildFeatures { prefab = true prefabPublishing = true } prefab { create("Data") { headers = "../../../poco/Data/include" } create("Foundation") { headers = "../../../poco/Foundation/include" } create("JSON") { headers = "../../../poco/JSON/include" } create("Net") { headers = "../../../poco/Net/include" } create("Util") { headers = "../../../poco/Util/include" } } }

Because the library I'm trying to build (nymphrpc) doesn't use a build system that seems to be compatible with Gradle, I've written a simple CMakeLists.txt for it:

cmake_minimum_required(VERSION 3.10) project( nymphrpc VERSION 0.1 LANGUAGES CXX ) find_package(Poco COMPONENTS Foundation Net JSON REQUIRED CONFIG) set(SRC ... ) set(HEADERS ... ) add_library( nymphrpc SHARED ${SRC} ) target_link_libraries( nymphrpc PRIVATE Poco::Foundation Poco::JSON Poco::Net ) target_include_directories( nymphrpc PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<INSTALL_INTERFACE:include/libnymphrpc> ) set_target_properties( nymphrpc PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION} ) install( TARGETS nymphrpc LIBRARY LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nymph ) install( FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nymph )

This works to build the library on my Linux desktop. To build it on Android I've written the following Gradle file:

plugins { id("com.android.library") } android { namespace = "ws.nyanko.nymphrpc" compileSdk = 36 ndkVersion = "26.1.10909125" defaultConfig { minSdk = 21 targetSdk = 21 externalNativeBuild { cmake { arguments += "-DANDROID_STL=c++_shared" } } } externalNativeBuild { cmake { path = file("../../../nymphrpc/CMakeLists.txt") } } buildFeatures { prefab = true prefabPublishing = true } prefab { create("nymphrpc") { headers = "../../../nymphrpc/src" } } } dependencies { implementation(project(":Poco")) }

While building this all Poco is built fine (an AAR file is created with libraries (.so files), a CMake config and header files) and although nymphrpc seems to compile correctly (thus it finds Poco's headers and CMake files), it fails to link.

[15/15] Linking CXX shared library /path/to/repo/build/nymphrpc/intermediates/cxx/Debug/2k5x57b1/obj/arm64-v8a/libnymphrpc.so FAILED: /path/to/repo/build/nymphrpc/intermediates/cxx/Debug/2k5x57b1/obj/arm64-v8a/libnymphrpc.so : && /var/lib/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --sysroot=/var/lib/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fvisibility=default -fno-limit-debug-info -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl, --no-undefined -shared -Wl,-soname,libnymphrpc.so -o /path/to/repo/build/nymphrpc/intermediates/cxx/Debug/2k5x57b1/obj/arm64-v8a/libnymphrpc.so src/CMakeFiles/nymphrpc.dir/callback_request.cpp.o src/CMakeFiles/nymphrpc.dir/dispatcher.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_listener.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_logger.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_message.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_method.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_server.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_session.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_socket_listener.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_types.cpp.o src/CMakeFiles/nymphrpc.dir/nymph_utilities.cpp.o src/CMakeFiles/nymphrpc.dir/remote_client.cpp.o src/CMakeFiles/nymphrpc.dir/remote_server.cpp.o src/CMakeFiles/nymphrpc.dir/worker.cpp.o -latomic -lm && : ld.lld: error: undefined symbol: Poco::Mutex::Mutex() >>> referenced by nymph_listener.cpp:41 (/path/to/repo/nymphrpc/src/nymph_listener.cpp:41) >>> src/CMakeFiles/nymphrpc.dir/nymph_listener.cpp.o:(__cxx_global_var_init.1) >>> referenced by nymph_listener.cpp:54 (/path/to/repo/nymphrpc/src/nymph_listener.cpp:54) >>> src/CMakeFiles/nymphrpc.dir/nymph_listener.cpp.o:(NymphListener::callbacksMutex()) >>> referenced by nymph_socket_listener.cpp:34 (/path/to/repo/nymphrpc/src/nymph_socket_listener.cpp:34) >>> src/CMakeFiles/nymphrpc.dir/nymph_socket_listener.cpp.o:(NymphSocketListener::NymphSocketListener(NymphSocket, Poco::Condition*, Poco::Mutex*)) >>> referenced 9 more times

As far as I can see it doesn't actually link to Poco for some reason, it mentions -latomic -lm but not -lPocoFoundation as I would expect it to, but I'm unable to deduce why that is the case. Especially because this CMake setup works just fine to build a regular Linux library.

Read Entire Article