Android Ndk: Link Using a Pre-Compiled Static Library

Android NDK: Link using a pre-compiled static library

You have to build pcap as static module. Something like this

include $(CLEAR_VARS)
LOCAL_MODULE := pcap
LOCAL_CFLAGS := declare_flags
LOCAL_C_INCLUDES := declare_include
LOCAL_SRC_FILES := src_files
include $(BUILD_STATIC_LIBRARY)

This build pcap as local module which you could link with LOCAL_STATIC_LIBRARIES

just add

LOCAL_STATIC_LIBRARIES := pcap

before calling

include $(BUILD_SHARED_LIBRARY)

Unable to link prebuilt static library with shared library in Android NDK

Your problem is probably because of you mix different STL's (versions)

Most of your "undefined reference" is related to:

std::__1
std::__ndk1

Like:

out/target/product/generic_arm64/obj/STATIC_LIBRARIES/libsecuretest_intermediates/libsecuretest.a(MyUtils.cpp.o):function MyUtils::Int32toHexString(int, int): error: undefined reference to 'std::__ndk1::locale::locale()'

Please try to compile also the "libsecuretest" with the AOSP build (maybe the libc++ versions is different).

NOTE:

I tried to check my AOSP libc++ symbols (PLATFORM_VERSION=6.0.1) and get:

$ nm -DC libc++.so | grep 'locale::locale()'
000682ad T std::__1::locale::locale()
000682ad T std::__1::locale::locale()

Also I get same symbols with libc++ from the phones Pixel2(Android9) S8(Andorid 8.0.0)

adb pull /system/lib/libc++.so

[And check it with the same "nm" command...]

But the symbols of the ndk18 is:

$nm -DC libc++_shared.so | grep 'locale::locale()'
00000000000865b0 T std::__ndk1::locale::locale()
00000000000865b0 T std::__ndk1::locale::locale()

Android NDK: building static library with other static libraries

NDK has the command you need, it's called LOCAL_EXPORT_STATIC_LIBRARIES.

include $(CLEAR_VARS)
LOCAL_EXPORT_STATIC_LIBRARIES := a-ssl a-crypto
LOCAL_C_INCLUDES += $(PATH_TO_PROJECT)/vendor/android-openssl/openssl/include
LOCAL_MODULE := project-alib
LOCAL_SRC_FILES := ../../source.c
include $(BUILD_STATIC_LIBRARY)

You could also inherit the openssl includes path from a-ssl. FInally, to clean this up a bit more, consider changing the order of modules in your Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_EXPORT_STATIC_LIBRARIES := a-ssl a-crypto
LOCAL_MODULE := project-alib
LOCAL_SRC_FILES := ../../source.c
include $(BUILD_STATIC_LIBRARY)

LOCAL_PATH := $(PATH_TO_PROJECT)/vendor/android-openssl

include $(CLEAR_VARS)
LOCAL_MODULE := a-ssl
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/include
LOCAL_SRC_FILES := $(LOCAL_PATH)/prebuilt/$(TARGET_ARCH_ABI)/libcrypto.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := a-crypto
LOCAL_SRC_FILES := $(LOCAL_PATH)/prebuilt/$(TARGET_ARCH_ABI)/libssl.a
include $(PREBUILT_STATIC_LIBRARY)

Android: Linking to prebuilt static libraries

Your libraries are interdependent:

Lapack requires Blas
Mumps requires Blas and Metis
Ipopt requires Mumps, Metis, and Lapack

This means that the order for linking them should be reverse:

ipopt
mumps
metis
lapack
blas

If you don't want to waste your time on figuring out the best order, but rather let the linker to find out (this may slow your builds significantly), you can use

target_link_libraries(native-lib -Wl,--start-group
blas
lapack
metis
mumps
ipopt
-Wl,--end-group).

You can also teach CMake about the dependencies between imported static libs, via IMPORTED_LINK_INTERFACE_LIBRARIES, e.g.

set_target_properties(lapack 
PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES
blas)

and so on.

This will translate

target_link_libraries( native-lib
blas
lapack
)

To

clang++ -o libnative-lib.so … libblas.a libnlapack.a libblas.a

How to compile a static library using the Android NDK?

As I understand it, the correct method is to use ndk-build and not invoking the compiler directly.

In Android.mk you need to specify a module for each static library you want to compile, and then specify that your shared library should use it.

Example of a modified Android.mk file of the hello-jni sample project:

LOCAL_PATH := $(call my-dir)

# Define vars for library that will be build statically.
include $(CLEAR_VARS)
LOCAL_MODULE := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := <list_of_src_files>

# Optional compiler flags.
LOCAL_LDLIBS = -lz -lm
LOCAL_CFLAGS = -Wall -pedantic -std=c99 -g

include $(BUILD_STATIC_LIBRARY)

# First lib, which will be built statically.
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_STATIC_LIBRARIES := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

If you want control over which modules to compile when you run ndk-build you can create create a Application.mk file (in the same directory as Android.mk) and list all the modules as in the following example:

APP_MODULES := <module_name_1> <module_name_2> ... <module_name_n>

Linking prebuilt static libraries ndk vs. Android source

Why is this?

ndk-build and the AOSP build system are two entirely different build systems that unfortunately look very similar.

Ultimately, what is the correct way to link a static lib in the src tree?

In the AOSP tree? Prebuilt modules are defined differently. Here are a couple examples:

https://android.googlesource.com/platform/prebuilts/sdk/+/9c011b3a7784803b96dc0f0a840aa9033a0cd62a/tools/Android.mk#291

include $(CLEAR_VARS)
LOCAL_MODULE := libbcc
LOCAL_SRC_FILES := $(HOST_OS)/lib64/$(LOCAL_MODULE)$(HOST_SHLIB_SUFFIX)
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(HOST_SHLIB_SUFFIX)
LOCAL_IS_HOST_MODULE := true
LOCAL_MULTILIB := 64
include $(BUILD_PREBUILT)

https://android.googlesource.com/platform/development/+/518e6c3a28cc63fd094c8b255e268650b03fdab5/host/windows/prebuilt/usb/Android.mk

include $(CLEAR_VARS)
LOCAL_IS_HOST_MODULE := true
LOCAL_MODULE := AdbWinApi
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_SRC_FILES_x86 := AdbWinApi.a
LOCAL_MODULE_SUFFIX := .a
LOCAL_MULTILIB := 32
LOCAL_MODULE_HOST_OS := windows
include $(BUILD_PREBUILT)

You then use them the same way you would any other library: LOCAL_STATIC_LIBRARIES := libmyprebuilt. Both of the above examples are for host modules. For a target module simply remove that line.

Note that AOSP's new (still in progress) build system, Soong, does not yet have support for prebuilt modules. These can only be defined in Android.mk files right now.

Android NDK - Including prebuilt static libraries gives undefined reference errors

Maybe it's just part of the problem, but at least this reference is wrong:

LOCAL_SRC_FILES := libkes.a

You're building for all the ndk compatible architectures, but always referencing the same static prebuilt for each of them, which cannot work.

You should have a different .a for each architecture you're targeting, ie ./armeabi/libkes.a, ./x86/libkes.a, ./armeabi-v7a/libkes.a, etc. In that case you'll be able to reference your .a using TARGET_ARCH_ABI variable, like so:

LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libkes.a


Related Topics



Leave a reply



Submit