Android NDK linking V8 static library: cannot find

2020-02-07 05:23发布

I've been pulling my hair out over this one. I am developing on Ubuntu 12.04 64-bit. I created a native Android app with V8 embedded in it, but after rebooting my computer, it doesn't link with V8 anymore! I've tried reinstalling ndk and recompiling V8, but to no avail. It appears the linker does include the static libraries, but doesn't find the symbols in them. I checked with nm, and the symbols appear to be there.

When I run ndk_build, I get the following output:

$ ndk-build V=1
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
[armeabi] Compile++ thumb: native-activity <= main.cpp
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi/objs/native-activity/main.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Ijni/include -I/home/schooten/bin/packages/android-ndk-r9d/sources/android/native_app_glue -I/home/schooten/bin/packages/android-ndk-r9d/sources/cxx-stl/system/include -Ijni -DANDROID  -Wa,--noexecstack -Wformat -Werror=format-security      -I/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm/usr/include -c  jni/main.cpp -o ./obj/local/armeabi/objs/native-activity/main.o 
[armeabi] Compile thumb  : android_native_app_glue <= android_native_app_glue.c
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -MMD -MP -MF ./obj/local/armeabi/objs/android_native_app_glue/android_native_app_glue.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/home/schooten/bin/packages/android-ndk-r9d/sources/android/native_app_glue -DANDROID  -Wa,--noexecstack -Wformat -Werror=format-security    -I/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm/usr/include -c  /home/schooten/bin/packages/android-ndk-r9d/sources/android/native_app_glue/android_native_app_glue.c -o ./obj/local/armeabi/objs/android_native_app_glue/android_native_app_glue.o 
[armeabi] StaticLibrary  : libandroid_native_app_glue.a
rm -f obj/local/armeabi/libandroid_native_app_glue.a
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar crsD ./obj/local/armeabi/libandroid_native_app_glue.a ./obj/local/armeabi/objs/android_native_app_glue/android_native_app_glue.o
[armeabi] StaticLibrary  : libstdc++.a
rm -f obj/local/armeabi/libstdc++.a
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar crsD ./obj/local/armeabi/libstdc++.a 
[armeabi] SharedLibrary  : libnative-activity.so
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -Wl,-soname,libnative-activity.so -shared --sysroot=/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm ./obj/local/armeabi/objs/native-activity/main.o ./obj/local/armeabi/libandroid_native_app_glue.a jni/lib/libv8_libbase.arm.a jni/lib/libv8_nosnapshot.a jni/lib/libv8_base.a jni/lib/libstlport_static.a ./obj/local/armeabi/libstdc++.a -lgcc -no-canonical-prefixes  -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -L/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm/usr/lib -llog -landroid -lEGL -lGLESv1_CM -llog -lstdc++ -lc -lm -o ./obj/local/armeabi/libnative-activity.so
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function __clearColor(v8::FunctionCallbackInfo<v8::Value> const&):jni/main.cpp:88: error: undefined reference to 'v8::Value::Int32Value() const'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function __clearColor(v8::FunctionCallbackInfo<v8::Value> const&):jni/main.cpp:89: error: undefined reference to 'v8::Value::Int32Value() const'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function __clearColor(v8::FunctionCallbackInfo<v8::Value> const&):jni/main.cpp:90: error: undefined reference to 'v8::Value::Int32Value() const'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function __clearColor(v8::FunctionCallbackInfo<v8::Value> const&):jni/main.cpp:91: error: undefined reference to 'v8::Value::Int32Value() const'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/main.cpp:101: error: undefined reference to 'v8::Isolate::New()'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/include/v8.h:4045: error: undefined reference to 'v8::Isolate::Enter()'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/main.cpp:104: error: undefined reference to 'v8::HandleScope::HandleScope(v8::Isolate*)'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/main.cpp:108: error: undefined reference to 'v8::ObjectTemplate::New(v8::Isolate*)'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/main.cpp:110: error: undefined reference to 'v8::ObjectTemplate::New(v8::Isolate*)'
/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/native-activity/main.o: in function run_javascript(char*):jni/main.cpp:112: error: undefined reference to 'v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::String::NewStringType, int)'
... etc ...

In particular, this line tells me that the *.a files are included:

/home/schooten/bin/packages/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -Wl,-soname,libnative-activity.so -shared --sysroot=/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm ./obj/local/armeabi/objs/native-activity/main.o ./obj/local/armeabi/libandroid_native_app_glue.a jni/lib/libv8_libbase.arm.a jni/lib/libv8_nosnapshot.a jni/lib/libv8_base.a jni/lib/libstlport_static.a ./obj/local/armeabi/libstdc++.a -lgcc -no-canonical-prefixes  -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -L/home/schooten/bin/packages/android-ndk-r9d/platforms/android-9/arch-arm/usr/lib -llog -landroid -lEGL -lGLESv1_CM -llog -lstdc++ -lc -lm -o ./obj/local/armeabi/libnative-activity.so

My Android.mk looks like this:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE          := stlport
LOCAL_MODULE_FILENAME := stlport_static
LOCAL_SRC_FILES := lib/libstlport_static.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE          := v8_base
LOCAL_MODULE_FILENAME := v8_base_static
LOCAL_SRC_FILES := lib/libv8_base.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE          := v8_nosnapshot
LOCAL_MODULE_FILENAME := v8_nosnapshot_static
LOCAL_SRC_FILES := lib/libv8_nosnapshot.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE          := v8_libbase
LOCAL_MODULE_FILENAME := v8_libbase_static
LOCAL_SRC_FILES := lib/libv8_libbase.arm.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue v8_libbase v8_nosnapshot v8_base stlport
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)

The LOCAL_STATIC_LIBRARIES order was determined empirically. I fiddled with it some more, but to no avail. I even tried LOCAL_WHOLE_STATIC_LIBRARIES. I checked the existence of symbols with nm:

arm-linux-gnueabi-nm jni/lib/libv8_base.a | grep Int32Value
         U _ZNK2v85Value10Int32ValueEv
00000000 T _ZNK2v85Value10Int32ValueEv
         U _ZNK2v85Value10Int32ValueEv

arm-linux-gnueabi-nm jni/lib/libv8_base.a | grep Utf8Value
00000000 T _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
00000000 T _ZN2v86String9Utf8ValueC2ENS_6HandleINS_5ValueEEE
00000000 T _ZN2v86String9Utf8ValueD1Ev
00000000 T _ZN2v86String9Utf8ValueD2Ev
         U _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
         U _ZN2v86String9Utf8ValueD1Ev
         U _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
         U _ZN2v86String9Utf8ValueD1Ev
         U _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
         U _ZN2v86String9Utf8ValueD1Ev
         U _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
         U _ZN2v86String9Utf8ValueD1Ev
         U _ZN2v86String9Utf8ValueC1ENS_6HandleINS_5ValueEEE
         U _ZN2v86String9Utf8ValueD1Ev

I am no expert at name munging, but it appears they are there. The values are all zeroes, but I believe this is normal.

So I figured, maybe the linker doesn't understand the static library, and it fails silently.
But how do I check why the linker is failing to pick up the symbols?

1条回答
SAY GOODBYE
2楼-- · 2020-02-07 06:14

I finally fixed it, with help of a friend. First I tried a workaround where I tried to link V8 as a shared library, which didn't turn out well because the NDK native activity interface I'm using turned out to be incompatible with loading additional shared objects.

There were two different issues going on with my static libraries. The first and most important one is that the static libraries built by V8 are not suitable for linking. You can check this by using:

ar x [static_library.a]

which will normally extract the *.o objects from the library. In this case, it reported:

`x' cannot be used on thin archives

A thin archive is just a set of references to the absolute paths of the *.o files, and no actual content. That explains why my build stopped working at one point where I moved or deleted the original *.o files from the V8 build tree. Strangely, the linker kept silent about that.

Creating static libraries is not currently a build option in V8. Thankfully, this guy has a patch for creating proper static libraries in V8.

The app still didn't link after I did that, because I copied the wrong files the first time round. As it turned out, the static libraries are also built for the host architecture (don't ask me why), and I accidentally copied those. I learned that you can use:

file objectfile.o

to see what architecture it is. Hence I found my static libraries were i386 and not arm. So, the linker was skipping these files, because the architecture didn't match (you can mix architectures in a static library).

Here is the V8 patch that I made to V8 3.27.28 based on the patch by Curu Wong. I will try to get this patch committed. Patch 1:

~/Work/javascript/Engines/v8-trunk/tools/gyp$ diff -u v8.gyp.orig  v8.gyp
--- v8.gyp.orig 2014-06-18 21:09:59.368336736 +0200
+++ v8.gyp  2014-06-18 21:12:20.264331660 +0200
@@ -108,6 +108,7 @@
     {
       'target_name': 'v8_snapshot',
       'type': 'static_library',
+      'standalone_static_library': 1,
       'conditions': [
         ['want_separate_host_toolset==1', {
           'toolsets': ['host', 'target'],
@@ -180,6 +181,7 @@
     {
       'target_name': 'v8_nosnapshot',
       'type': 'static_library',
+      'standalone_static_library': 1,
       'dependencies': [
         'v8_base',
       ],
@@ -237,6 +239,7 @@
     {
       'target_name': 'v8_base',
       'type': 'static_library',
+      'standalone_static_library': 1,
       'dependencies': [
         'v8_libbase.<(v8_target_arch)',
       ],

Patch 2:

~/Work/javascript/Engines/v8-trunk/third_party/icu$ diff -u icu.gyp.orig icu.gyp
--- icu.gyp.orig    2014-06-18 21:10:22.060335920 +0200
+++ icu.gyp 2014-06-18 21:15:06.468325674 +0200
@@ -56,6 +56,7 @@
         {
           'target_name': 'icudata',
           'type': 'static_library',
+          'standalone_static_library': 1,
           'defines': [
             'U_HIDE_DATA_SYMBOL',
           ],
@@ -141,6 +142,11 @@
         {
           'target_name': 'icui18n',
           'type': '<(component)',
+          'conditions': [
+            [ 'component!="shared_library"', {
+                'standalone_static_library': 1,
+            }],
+          ],
           'sources': [
             '<@(icui18n_sources)',
           ],
@@ -241,6 +247,11 @@
         {
           'target_name': 'icuuc',
           'type': '<(component)',
+          'conditions': [
+            [ 'component!="shared_library"', {
+                'standalone_static_library': 1,
+            }],
+          ],
           'sources': [
             '<@(icuuc_sources)',
           ],
查看更多
登录 后发表回答