Android APP embed v8的错误汇总

Android APP embed v8的过程(请参见编译和嵌入v8至Android APP),非常艰难,会出现各种各样的错误,此文对此进行总结,便于问题的记录和后续查询和分析。遇到的问题大致分为2类:

  1. 在Ubuntu 16.04系统下,编译v8的时候,环境的配置、各种参数的设置问题,这最终会影响到生成的库(分static library和shared library两种情形)是否正确。这里定义叫编译v8库的问题。
  2. 利用Android studio将生成的v8的静态库或者分享库通过NDK嵌入到Android APP时候的各种编译错误或者参数配置问题。此类问题定义为embed v8 in Android APP问题。

解决问题的思路:

  1. 得到问题的信息,然后在网上搜索,查询是否已有他人的经验可用,比如Stack Overflow和其他网站;
  2. 在v8的官方wiki页面,找到问题反馈途径(其中,mailing list较常用):
  3. 结合已有的知识储备,通过实际分析v8构建和相关工具链的机制来修改参数,不断尝试。

编译v8库的问题

  1. How to build v8 use gnu-libstdc++ instead of llvm-libc++?
    tools/dev/v8gen.py android.arm.release -- use_sysroot=false use_glib=false use_custom_libcxx=false
    

embed v8 in Android APP问题

Note:目前已实现嵌入v8到Android APP并进一步实现基于v8和OpenGL的javascript游戏引擎。请参见我的Github 示例V8AndroidSunGameEngine

  1. 利用v8的最新分支编译成静态库,然后在AS里面gradle打包,CMake构建时出现下面错误:

    Build command failed.
    Error while executing process /usr/local/v8/v8/third_party/android_tools/sdk/cmake/3.6.4111459/bin/cmake with arguments {--build /mnt/share/V8Wrapper/app/.externalNativeBuild/cmake/debug/armeabi-v7a --target native-lib}
    [1/1] Linking CXX shared library ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so
    FAILED: : && /usr/local/v8/v8/third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++  --target=armv7-none-linux-androideabi --gcc-toolchain=/usr/local/v8/v8/third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 --sysroot=/usr/local/v8/v8/third_party/android_ndk/sysroot -fPIC -isystem /usr/local/v8/v8/third_party/android_ndk/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=16 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot /usr/local/v8/v8/third_party/android_ndk/platforms/android-16/arch-arm -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--fix-cortex-a8 -Wl,--exclude-libs,libunwind.a -L/usr/local/v8/v8/third_party/android_ndk/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o  /usr/local/v8/v8/third_party/android_ndk/platforms/android-16/arch-arm/usr/lib/liblog.so ../../../../src/main/cpp/libs/libv8_base.a ../../../../src/main/cpp/libs/libv8_libplatform.a ../../../../src/main/cpp/libs/libv8_libbase.a ../../../../src/main/cpp/libs/libv8_nosnapshot.a ../../../../src/main/cpp/libs/libv8_libsampler.a -latomic -lm "/usr/local/v8/v8/third_party/android_ndk/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++.a" && :
    ../../src/isolate.cc:0: error: undefined reference to 'vtable for v8::internal::SetupIsolateDelegate'
    /usr/local/v8/v8/third_party/android_ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: the vtable symbol may be undefined because the class is missing its key function
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.
    

    原因:链接时使用的是libv8_nosnapshot.a库,该库并没有包含v8::internal::SetupIsolateDelegate的相关定义。该问题的讨论可以参考v8 mail list的帖子:https://groups.google.com/forum/#!starred/v8-users/hjNr1F6lLgg

    解决办法:目前有两种办法:

    1. (该办法已验证OK)采用libv8_snapshot.a库替代libv8_nosnapshot.a库。同时在C++源代码的前面加上部分内部空间声明(否则构建apk的时候CMake会报错,找不到这几个函数定义):

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      /**
      * Must stub in case external snapshot files are used.
      */

      namespace v8::internal {
      void ReadNatives() {}

      void DisposeNatives() {}

      void SetNativesFromFile(v8::StartupData *s) {}

      void SetSnapshotFromFile(v8::StartupData *s) {}
      }
    2. (该办法目前未亲自验证)成功编译v8之后,生成的include目录下并未包含setup-isolate.h头文件,而v8::internal::SetupIsolateDelegate的相关定义在该头文件中。从v8源码的src子目录中找到setup-isolate.h头文件,并将其添加到Android studio工程的CMakeLists.txt文件对应的cpp源码段落中。可参考https://groups.google.com/forum/#!starred/v8-users/hjNr1F6lLgg

附录和链接