The Android NDK docs are mostly focused on building C/C++ JNI code. What I want to do is build an external dynamic library written in Go that does not use CMake and has no JNI wrapper.
For the question, it is not important that the library is written in Go, just that it is not written in C. cgo is used to generate C bindings for the dynamic (.so) library, and I have to pass CC=<path/to/android/ndk/clang>
to it so that it can use the NDK compiler internally.
I do not use JNI. Rather, I use JNA to access the C-exported methods in libstuff.so
.
Currently, I do the following:
- Manually build the shared library with cgo, passing the correct Android compiler path to it
- Copy the library to
myapp/src/main/jniLibs/<arch>/libstuff.so
- Build the project
(I also have to pass CGO_LDFLAGS="-Wl,-soname,libstuff.so"
in step 1, otherwise JNA cannot find it...)
Goal
What I want to do is build the shared library automatically when I build the Android Gradle project, passing on the right compiler binary and architecture to the Go compiler and having libstuff.so
for the relevant architectures be included in the APK, or actually the AAR as I am building an Android library.
What I've tried
I've tried with the following CMake script:
cmake_minimum_required(VERSION 3.18.1)
project(stuff_project)
include(ExternalProject)
# Test
message("================")
message(ANDROID_ARCH_NAME=${ANDROID_ARCH_NAME})
message("================")
ExternalProject_Add(external_proj
PREFIX "path/to/go/library"
SOURCE_DIR "path/to/go/library"
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND "<command to build go library>"
INSTALL_COMMAND ""
)
The command in BUILD_COMMAND
builds the library for ${ANDROID_ARCH_NAME}
/ ${ANDROID_LLVM_TRIPLE}
using ${ANDROID_C_COMPILER}
with extra flags ${CMAKE_C_FLAGS}
and ${CMAKE_SHARED_LINKER_FLAGS}
and copies it to ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
.
This is inspired by A/B/WireGuard and it works when running cmake
and cmake --build
from the command line (where I did not use the Android compiler or anything), but when running Gradle with android { ... externalNativeBuild { cmake { version "3.18.1"; path 'CMakeLists.txt' } } }
it only prints the test messages above when configuring and never actually builds the project. (Maybe I have to make external_proj
a dependent of something? But of what?)
How do I fix this?
Related
The WireGuard Android app also uses a Go library and uses CMake's add_custom_target
with a COMMAND
to build the library. However, this library has a JNI wrapper and does not use JNA. I also tried the add_custom_target
method, but the command is never executed.