简体   繁体   中英

ndk-build: Header file of static prebuilt static library not found even on LOAD_STATIC_LIBRARY

I know this question has been asked many times before and I have gone through previous answers but it still hasn't helped me. So I am going to ask this question as explicitly as I can.

I have built a static library libdivecomputer.a using make-standalone-toolchain.sh of android_ndk for x86 arch. I have put this .a file under project-root/jni/include. Running ar on this archive gives me this output.

$ ar t libdivecomputer.a 
version.o
descriptor.o
iterator.o
context.o
device.o
parser.o
datetime.o
suunto_common.o
suunto_common2.o
suunto_solution.o
suunto_solution_parser.o
suunto_eon.o
suunto_eon_parser.o
suunto_vyper.o
suunto_vyper_parser.o
suunto_vyper2.o
suunto_d9.o
suunto_d9_parser.o
reefnet_sensus.o
reefnet_sensus_parser.o
reefnet_sensuspro.o
reefnet_sensuspro_parser.o
reefnet_sensusultra.o
reefnet_sensusultra_parser.o
uwatec_aladin.o
uwatec_memomouse.o
uwatec_memomouse_parser.o
uwatec_smart.o
uwatec_smart_parser.o
uwatec_meridian.o
oceanic_common.o
oceanic_atom2.o
oceanic_atom2_parser.o
oceanic_veo250.o
oceanic_veo250_parser.o
oceanic_vtpro.o
oceanic_vtpro_parser.o
mares_common.o
mares_nemo.o
mares_nemo_parser.o
mares_puck.o
mares_darwin.o
mares_darwin_parser.o
mares_iconhd.o
mares_iconhd_parser.o
ihex.o
hw_ostc.o
hw_ostc_parser.o
hw_frog.o
hw_ostc3.o
cressi_edy.o
cressi_edy_parser.o
cressi_leonardo.o
cressi_leonardo_parser.o
zeagle_n2ition3.o
atomics_cobalt.o
atomics_cobalt_parser.o
shearwater_common.o
shearwater_predator.o
shearwater_predator_parser.o
shearwater_petrel.o
diverite_nitekq.o
diverite_nitekq_parser.o
ringbuffer.o
checksum.o
array.o
buffer.o
serial_posix.o
irda_dummy.o

As can be seen it contains an entry device.o. I intend to use it. Now, I have generated a native header for the application using javah. And made a corresponding C file which contains a single function. I have also included device.h in this file because I intend to use it later.

com_venky_Home.c

#include "com_venky_Home.h"
#include <android/log.h>
#include <device.h>

#define  LOG_TAG    "Native com_venky_Home"

#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define  LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define  LOGW(...)  __android_log_print(ANDROID_LOG_WARNING, LOG_TAG, __VA_ARGS__)

JNIEXPORT void Java_com_venky_Home_doImport (JNIEnv* pEnv, jobject pThis, jint fd) {
    LOGD ("Native code doImport was called with fd : %d\n", fd);   
}

Now, for compiling this script, I am using ndk-build. Hence, I have made Android.mk and Application.mk files for including the static library.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := dc
LOCAL_SRC_FILES := include/libdivecomputer.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := com_venky_Home.c
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := dc
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_PLATFORM := android-19
APP_ABI := x86

Now, as soon as I compile it using ndk-build, I get this error

$ ndk-build
Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 12 in ./AndroidManifest.xml
[x86] Compile        : mylib <= com_venky_Home.c
jni/com_venky_Home.c:4:20: fatal error: device.h: No such file or directory
compilation terminated.
make: *** [obj/local/x86/objs/mylib/com_venky_Home.o] Error 1

On running ndk-build V=1 , I get the following message.

$ ndk-build V=1
Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 12 in ./AndroidManifest.xml    
rm -f ./libs/armeabi/lib*.so ./libs/armeabi-v7a/lib*.so ./libs/armeabi-v7a-hard/lib*.so ./libs/mips/lib*.so ./libs/x86/lib*.so
rm -f ./libs/armeabi/gdbserver ./libs/armeabi-v7a/gdbserver ./libs/armeabi-v7a-hard/gdbserver ./libs/mips/gdbserver ./libs/x86/gdbserver
rm -f ./libs/armeabi/gdb.setup ./libs/armeabi-v7a/gdb.setup ./libs/armeabi-v7a-hard/gdb.setup ./libs/mips/gdb.setup ./libs/x86/gdb.setup
[x86] Compile        : mylib <= com_venky_Home.c
/android_ndk/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/i686-linux-android-gcc -MMD -MP -MF ./obj/local/x86/objs/mylib/com_venky_Home.o.d -ffunction-sections -funwind-tables -no-canonical-prefixes -fstack-protector -O2 -g -DNDEBUG -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 -Ijni/include -Ijni -DANDROID  -Wa,--noexecstack -Wformat -Werror=format-security    -I/android_ndk/platforms/android-19/arch-x86/usr/include -c  jni/com_venky_Home.c -o ./obj/local/x86/objs/mylib/com_venky_Home.o 
jni/com_venky_Home.c:4:20: fatal error: device.h: No such file or directory
compilation terminated.
make: *** [obj/local/x86/objs/mylib/com_venky_Home.o] Error 1

As can be seen, jni/include is indeed been included for searching header files from -Ijni/include option. Hence, device.h should be easily found by the linker. But it is not. Why? How can I resolve this error?

Your device.h isn't a system header. Thus, include it accordingly:

#include "device.h"

I will answer my own question. As @alexcohn has rightly said, I had to make sure that the headers (*.h) were actually present there. Therein lied my folly. There are two things necessary here.

1. You have to have a library present. In case of ndk standalone build, it should be present at ndk-arm/sysroot/usr/lib directory. Your -l option specifies this library. Remember the name should be undecorated.
For ex. libvenkatesh.so would have -lvenkatesh as the library option.
But this is true for well formed libraries only. In case you have another C file that have the implementation of required functions, you might directly add them to your gcc command.
For ex. gcc file1.c file2.c
Also, this can be done for library files as well. If -l option is too cryptic for you, add the libraries directly.
For ex. gcc file.c libvenky.a libmy.so
But for big projects, it easily gets out of hand. And hence -l option is useful.
Then there is -L option. This option specifies where the compiler should search for library files in addition to standard places. After adding -L option, you can link the libraries directly without path.
For ex. Suppose I have multiple libraries in lib folder of my project.

lib
 |--- liba.so  libb.so  libc.a

Using -L option $gcc file.c -Llib -la -lb -lc would be right.

2.You must have header files to those libraries. And this you must include in your code. (#include statements).

#include <a.h>
#include <b.h>
#include <sample/c.h>

But these .h files might be present in a non standard location. To specify its location, use the -I option. Suppose I have an include folder where I keep all my headers.

include
   |--- a.h  b.h  sample
                     |--- c.h

Then complete compilation command would be.
$gcc file.c -o bin/file.o -Llib -Iinclude -la -lb -lc

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM