前言

随着javascript语言的快速发展,以及跨平台应用的场景越来越广,当前已经出现采用JS engine嵌入移动APP,实现JS编写跨移动平台的应用。比如FaceBook的ReactNative,而Cocos2D引擎也实现了JS的版本Cocos2d-JS。当前主流的JS engine很多,包括v8、spidermonkey、JavascriptCore、Rhino和Nashorn等。

关于JS引擎介绍,可以参见维基百科JavaScript_engine介绍

关于各引擎的对比,可以参见JS engine对比文章1JS engine简单对比文章2。文章1有人翻译成了中文,请参见https://blog.csdn.net/Kaitiren/article/details/23255195。

关于如何选择一个JS engine,这里提几点:

  1. 引擎的性能,当然是越快越好;
  2. 嵌入之后,对APP的包体大小的影响;
  3. 该引擎的官方文档是否齐全,API是否清晰好用,是否处于活跃开发阶段,开发社区的支持是否足够
  4. 多平台的支持性,比如v8只支持JIT编译,而IOS是限制第三方JS engine使用JIT的。

关于v8引擎的构建,请参考构建v8 engine指南

ubuntu 16.04 LTS系统下构建Firefox for Android

前提条件:
Hardware requirements
2G RAM with lots of available swap space. Additional RAM will significantly decrease build time.
For debug builds: at least 8 GB free disk space
For optimized builds: at least 1 GB free disk space (6 GB recommended)

注意:实际上,构建很消耗资源,所以建议RAM 8G以上,磁盘空间剩余30G以上。另外网络带宽要比较高,国内的话,最好使用VPN

Mozilla官方也有构建指南,不过其中有些不是很清楚,官方文档请参见https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build

具体构建步骤:

  1. 安装支持32位的相关库(If you’re using a 64-bit Linux, you’ll need to install 32 bit libs to allow the toolchain binaries to run)

    sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 lib32z1 libbz2-1.0:i386

  2. 获取启动配置的py文件,打开终端,执行如下命令:

    wget -O bootstrap.py https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py

  3. 确保系统的默认的python版本为2.7(Ubuntu 16.04LTS版本默认安装的python就是2.7,所以这里只需确认下即可),在终端里执行步骤2中下载的bootstrap.py:

    python #先确认python版本是2.7
    python bootstrap.py

    其中,python bootstrap.py会去安装python和autoconf2.13等工具(在执行的终端窗口可以看到sudo apt-get install autoconf2.13 build-essential nodejs python-dev python-pip python-setuptools unzip uuid zip命令被自动执行),此外还会下载构建所依赖的Android SDK、NDK等,下载过程比较耗时,需要耐心等候。同时,执行途中会弹出如图1提示(请选择3,这里Artifact mode构建更快,3和4的具体区别,请参见Artifact_builds):

    其他选项,默认选择Y(是)或者按照终端的提示建议操作,然后继续让命令过程继续执行即可。下面摘录自官方文档的说明:

    The bootstrapping script will install system packages, the Android SDK (and NDK, if required), and the currently required versions of the Android platform plus extras. If you want to know more about what Bootstrap.py is doing you can look at our detailed setup instructions. Please follow the steps in the terminal to complete the configuration. If you want to use git, when you are aksed to run the Mercurial configuration wizard, you can select option 2. No.
    
    The bootstrap script will print out configuration options for you when it finishes (more on this below).  For now, copy this configuration text to a safe place and continue on.  You can re-run the bootstrap script to print this information again later.
    
    Once you have all the dependencies installed, you need to clone the Firefox repository.
    
  4. 拉取源码,这里建议采用hg而非Git。

    hg clone https://hg.mozilla.org/mozilla-central

  5. 下载完成之后,在源码目录,本文以/usr/local/spidermonkey/mozilla-central为例。在终端下,进入该目录(留意该目录下的mach文件),然后再次执行启动配置命令:

    cd /usr/local/spidermonkey/mozilla-central
    ./mach bootstrap

    这一步会弹出步骤3中示意图1的选项,仍然选择3即可。

  6. /usr/local/spidermonkey/mozilla-central目录下,新建一个名为mozconfig的文件,打开该文件,在里面添加入下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # Build Firefox for Android:
    ac_add_options --enable-application=mobile/android
    ac_add_options --target=arm-linux-androideabi

    # With the following Android SDK:
    ac_add_options --with-android-sdk="/absolute/path/to/.mozbuild/android-sdk"

    # Enable artifact building:
    ac_add_options --enable-artifact-builds

    # Write build artifacts to:
    mk_add_options MOZ_OBJDIR=./objdir-frontend

    注意:上面的Android SDK的路径/absolute/path/to/.mozbuild/android-sdk,需要根据你当前的实际路径做修改。一般而言,步骤3完成之后,会将Android SDK默认安装在你的用户目录即$Home/.mozbuild/下,比如我的就是/home/coulsonchen/.mozbuild/android-sdk-linux。可去该目录下实际确认下。另外,MOZ_OBJDIR=./objdir-frontend,这里是指定构建的目标目录,位于/usr/local/spidermonkey/mozilla-central/objdir-frontend下,objdir-frontend可以修改成你设定的其他名称。

  7. 可以修改源码目录下的源码或者配置,修改完成之后,执行构建:

    ./mach build

    构建完成之后,这个时候其实是可以用Android Studio打开Firefox的整个工程的(build过程已经生成了gradle相关文件)。注意:需要在./mach build后执行./mach gradle clean app:assembleLocalWithGeckoBinariesMinApi21PhotonDebug命令,然后通过Android Studio open项目的时候,选择项目的路径为Firefox的源码下载目录,即/usr/local/spidermonkey/mozilla-central。接着就可以通过Android studio开发和构建Firefox了,并且可Debug和Run。具体请参见官方说明构建Firefox For Android的“Developing Firefox for Android in Android Studio”章节部分。

  8. 打包成Android的APK文件:

    ./mach package

    生成的APK文件在构建的目标目录下的/dist子目录下,即/usr/local/spidermonkey/mozilla-central/objdir-frontend/dist下,名称类似fennec-61.0a1.en-US.android-arm.apk

  9. 安装到Android手机(支持Android Ice Cream Sandwich (API 15)及以后版本的手机)

    ./mach install

    可在终端的输出中查看到相关信息,比如:

    也可以直接copy步骤8中生成的apk文件,通过adb install安装即可,安装后在手机桌面会生成Firefox的快捷图标。

  10. 运行Firefox,在手机上查看效果

    ./mach run

    类似效果如下:

    也可以直接在手机桌面,点击Firefox的快捷图标,启动浏览器,即可体验试用。

ubuntu 16.04 LTS系统下构建spidermonkey的shared library

前置条件:
1.spidermonkey的源码和Firefox的源码位于是同一个仓库(事实上,Firefox就是内嵌spidermonkey作为JS的执行engine),因此这里按照“ubuntu 16.04 LTS系统下构建Firefox for Android”的步骤1-4以完成spidermonkey的源码下载。然后接着按照下面步骤执行:

实施步骤:

  1. 进入源码的js/src子目录(本文示例源码下载存放路径为/usr/local/spidermonkey/mozilla-central),即/usr/local/spidermonkey/mozilla-central/js/src。依序执行下列命令:

    cd /usr/local/spidermonkey/mozilla-central
    cd js/src
    autoconf2.13

    spidermonkey当前强制要求使用autoconf2.13,在python bootstrap.py的过程中会自动安装,如果没有成功安装,请单独选择一个目录,然后按照下面方式手工安装(安装成功之后再从终端回到/usr/local/spidermonkey/mozilla-central/js/src目录):

    wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.13.tar.gz
    tar -xvzf autoconf-2.13.tar.gz
    cd autoconf-2.13/
    ./configure –program-suffix=2.13
    make
    sudo make install
    cd /usr/local/spidermonkey/mozilla-central/js/src
    autoconf2.13

    # This name should end with "_OPT.OBJ" to make the version control system ignore it.如果之前已有上一次构建遗留的build_OPT.OBJ目录,可以先`rm -R build_OPT.OBJ`删除之后再新建,避免多次构建直接缓存干扰
    

    rm -R build_OPT.OBJ
    mkdir build_OPT.OBJ
    cd build_OPT.OBJ

  2. 先测试构建环境的配置是否OK。通过构建Linux 64位下的库(target system type:x86_64-pc-linux-gnu)来检验:

  • 2.1、检查配置

    coulsonchen@coulsonchen:/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ$ ../configure

    执行该命令后,可能遇到下面错误(Only GCC 6.1 or newer is supported (found version 5.4.0)):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    Creating Python environment
    New python executable in /usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ/_virtualenv/bin/python2.7
    Also creating executable in /usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ/_virtualenv/bin/python
    Installing setuptools, pip, wheel...done.
    running build_ext
    copying build/lib.linux-x86_64-2.7/psutil/_psutil_linux.so -> psutil
    copying build/lib.linux-x86_64-2.7/psutil/_psutil_posix.so -> psutil

    Error processing command. Ignoring because optional. (optional:packages.txt:comm/build/virtualenv_packages.txt)
    Reexecuting in the virtualenv
    checking for vcs source checkout... hg
    checking for a shell... /bin/sh
    checking for host system type... x86_64-pc-linux-gnu
    checking for target system type... x86_64-pc-linux-gnu
    checking for a shell... /bin/sh
    checking for host system type... x86_64-pc-linux-gnu
    checking for target system type... x86_64-pc-linux-gnu
    checking for android platform directory... no
    checking for android sysroot directory... no
    checking for android system directory... no
    checking for the Android toolchain directory... not found
    checking for android platform directory... no
    checking for android system directory... no
    checking for android sysroot directory... no
    checking for the Android toolchain directory... not found
    checking for vcs source checkout... hg
    checking whether cross compiling... no
    checking for the target C compiler... /usr/bin/gcc
    checking whether the target C compiler can be used... no
    DEBUG: <truncated - see config.log for full output>
    DEBUG: | %KERNEL "Linux"
    DEBUG: | #elif _WIN32 || __CYGWIN__
    DEBUG: | %KERNEL "WINNT"
    DEBUG: | #elif __NetBSD__
    DEBUG: | %KERNEL "NetBSD"
    DEBUG: | #elif __APPLE__
    DEBUG: | %KERNEL "Darwin"
    DEBUG: | #endif
    DEBUG: | #if _MSC_VER || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    DEBUG: | %ENDIANNESS "little"
    DEBUG: | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    DEBUG: | %ENDIANNESS "big"
    DEBUG: | #endif
    DEBUG: Executing: `/usr/bin/gcc -std=gnu99 -E /tmp/conftest._Zswij.c`
    DEBUG: COMPILER = gcc
    DEBUG: VERSION = 5.4.0
    DEBUG: STDC_VERSION = 199901L
    DEBUG: CPU = x86_64
    DEBUG: KERNEL = Linux
    DEBUG: ENDIANNESS = little
    ERROR: Only GCC 6.1 or newer is supported (found version 5.4.0).

这里有两种解决办法:
- 用clang替代gcc(添加环境变量指定编译使用的编译器为clang,CC=clang CXX=clang++  ../configure,即在./configure前面加上`CC=clang CXX=clang++`),如下所示:
    > coulsonchen@coulsonchen:/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ$ CC=clang CXX=clang++  ../configure

        Reexecuting in the virtualenv
        checking for vcs source checkout... hg
        checking for a shell... /bin/sh
        checking for host system type... x86_64-pc-linux-gnu
        checking for target system type... x86_64-pc-linux-gnu
        checking for a shell... /bin/sh
        checking for host system type... x86_64-pc-linux-gnu
        checking for target system type... x86_64-pc-linux-gnu
        checking for android platform directory... no
        checking for android sysroot directory... no
        checking for android system directory... no
        checking for the Android toolchain directory... not found
        checking for android platform directory... no
        checking for android system directory... no
        checking for android sysroot directory... no
        checking for the Android toolchain directory... not found
        checking for vcs source checkout... hg
        checking whether cross compiling... no
        checking for the target C compiler... not found
        DEBUG: _cc: Trying clang
        ERROR: Cannot find the target C compiler
    这里提示找不到clang编译器,那么就通过命令安装即可(`sudo apt-get install clang`)。当然也可以使用Android ndk目录下自带的clang。
- 更新gcc至6.1之后的版本,请参见[https://blog.csdn.net/gatieme/article/details/52871438](https://blog.csdn.net/gatieme/article/details/52871438)
  • 2.2、构建(make),检查是否构建成功并测试构建出来的可执行程序是否可用。注:依然在目录/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ下执行终端命令:

    make

    构建的时间比较长,需要耐心等待。待完成之后,在/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ的子目录/dist/bin下可看到生成了名为js的可执行程序(javascript的交互命令行),另外也生成了spidermonkey的分享库(shared library)libmozjs-xxx.so(在/dist/bin子目录下,其中xx表示当前源码的版本,如采用Mozilla源码45,那么就是libmozjs-45.so,嵌入其他C++程序使用的时候可以将其改名为libmozjs.so)执行如下命令:

    ./dist/bin/js ../Y.js

    可看到输出信息“5! is 120”。执行执行./dist/bin/js就进入了javascript的交互命令行,在交互命令行里面可以执行javascript的语句,定义函数等等。和python的交互命令行类似。

3.先清除之前的配置缓存
如果是重新下载的源码,第一次执行的时候可以不用担心。但多次构建时该步骤一定要引起重视。所以为了保险起见,在构建目录/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ的终端下执行:

rm ./config.cache

4. 修改构建Android库的配置参数
因为这里涉及到交叉编译,即在Linux Host主机上构建target为Android arm(或arm64,或x86)平台的库。这里首先需要弄清楚,配置脚本有哪些参数是可以配置,哪些参数又是针对构建Android平台库时必须设置的呢?

我们可以通过运行如下命令来检查所有的参数:

../configure –help
../configure –help |grep reStr

其中reStr是需要过滤的字符串,比如要查看Android相关的参数

../configure –help |grep android

最终配置交叉编译Android arm平台库的参数命令如下(反复尝试,查阅多个文章才得出,这个过程很艰难,稍微多了或者少了某个参数,或者参数错误,都可能导致配置失败,进而也无法进行make构建):

../configure –with-android-sdk=”/home/coulsonchen/.mozbuild/android-sdk-linux” –with-android-ndk=”/home/coulsonchen/.mozbuild/android-ndk-r15c” –with-android-version=23 –with-android-toolchain=/home/coulsonchen/.mozbuild/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 –target=arm-linux-androideabi

如果是编译Android arm64平台库,则应该修改为:

../configure –with-android-sdk=”/home/coulsonchen/.mozbuild/android-sdk-linux” –with-android-ndk=”/home/coulsonchen/.mozbuild/android-ndk-r15c” –with-android-version=23 –with-android-toolchain=/home/coulsonchen/.mozbuild/android-ndk-r15c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 –target=aarch64-linux-android

即目标平台target和with-android-toolchain参数需要根据目标平台变化而相应修改。Android ndk r15c(目前spidermonkey构建采用的ndk版本)支持的目标平台可去其路径下(/home/coulsonchen/.mozbuild/android-ndk-r15c/toolchains)查看:

注意:x86 for Android的名称应该为i386-linux-android

5. 完成最终构建(make)

make

注:在默认情况下,这一步构建会出现异常,且该问题很难找到原因,目前官方也没有给出解答,在网上也几乎找不到类似问题。这里有几个回避的方案:

  • 异常现象:
    执行make之后,构建一段时间,可以在终端看到,因为异常退出了,并没有真正成功构建。异常信息截取如下(其中第一行是整个链接命令):
    /home/coulsonchen/.mozbuild/android-ndk-r15c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -std=gnu++14 --target=arm-linux-androideabi -Qunused-arguments -isystem /home/coulsonchen/.mozbuild/android-ndk-r15c/platforms/android-23/arch-arm/usr/include -isystem /home/coulsonchen/.mozbuild/android-ndk-r15c/platforms/android-23/arch-arm/usr/include -gcc-toolchain /usr/local/my-android-toolchain -D__ANDROID_API__=23 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -Qunused-arguments -Wall -Wempty-body -Wignored-qualifiers -Woverloaded-virtual -Wpointer-arith -Wsign-compare -Wtype-limits -Wunreachable-code -Wunreachable-code-return -Wwrite-strings -Wno-invalid-offsetof -Wclass-varargs -Wloop-analysis -Wc++1z-compat -Wcomma -Wimplicit-fallthrough -Wstring-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wformat -Wformat-security -Wno-gnu-zero-variadic-macro-arguments -Wno-unknown-warning-option -Wno-return-type-c-linkage -fno-sized-deallocation -fno-short-enums -fno-exceptions -I/home/coulsonchen/.mozbuild/android-ndk-r15c/sources/cxx-stl/llvm-libc++/include -I/home/coulsonchen/.mozbuild/android-ndk-r15c/sources/android/support/include -I/home/coulsonchen/.mozbuild/android-ndk-r15c/sources/cxx-stl/llvm-libc++abi/include -march=armv7-a -mthumb -mfpu=vfpv3-d16 -mfloat-abi=softfp -mno-unaligned-access -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-rtti -fno-exceptions -fno-math-errno -pipe -g -O3 -funwind-tables  -fPIC -shared -Wl,-z,defs -Wl,-h,libmozjs-61a1.so -o libmozjs-61a1.so /usr/local/gecko-dev/js/src/obj/js/src/build/libmozjs-61a1_so.list  -L/home/coulsonchen/.mozbuild/android-ndk-r15c/platforms/android-23/arch-arm/usr/lib -Wl,-rpath-link=/home/coulsonchen/.mozbuild/android-ndk-r15c/platforms/android-23/arch-arm/usr/lib --sysroot=/home/coulsonchen/.mozbuild/android-ndk-r15c/platforms/android-23/arch-arm -Wl,--allow-shlib-undefined -gcc-toolchain /usr/local/my-android-toolchain -mthumb -Wl,-z,noexecstack -Wl,-z,text -Wl,-z,relro -Wl,--build-id -B /usr/local/gecko-dev/js/src/obj/build/unix/gold -Wl,-rpath-link,/usr/local/gecko-dev/js/src/obj/dist/bin -Wl,-rpath-link,/usr/local/lib     ../../../mozglue/build/libmozglue.so   -lm  -lz -llog -lm -ldl -L/home/coulsonchen/.mozbuild/android-ndk-r15c/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -lc++_static -lc++abi -lunwind -landroid_support
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    ../../../build/unix/gold/ld: error: hidden symbol '__android_log_print' is not defined locally
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    /usr/local/spidermonkey/mozilla-central/config/rules.mk:699: recipe for target 'libmozjs-60a1.so' failed
    make[3]: *** [libmozjs-60a1.so] Error 1
    make[3]: Leaving directory '/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ/js/src/build'
    /usr/local/spidermonkey/mozilla-central/config/recurse.mk:73: recipe for target 'js/src/build/target' failed
    make[2]: *** [js/src/build/target] Error 2
    make[2]: Leaving directory '/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ'
    /usr/local/spidermonkey/mozilla-central/config/recurse.mk:32: recipe for target 'compile' failed
    make[1]: *** [compile] Error 2
    make[1]: Leaving directory '/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ'
    /usr/local/spidermonkey/mozilla-central/config/rules.mk:434: recipe for target 'default' failed
    make: *** [default] Error 2
    
  • 问题分析:
    根据报错信息,可以看出是在链接生成libmozjs-60a1.so(60a1是源码的版本号,版本是xx,那么应该对应libmozjs-xx.so)的时候出错,且都是error: hidden symbol '__android_log_print' is not defined locally错误,我们知道__android_log_print是Android的log库里面提供的日志打印方法。但查询ndk的目录,log库和工具类设置都是正常的,也能找到相关的头文件。且这个错误的信息对于不熟悉C++的人来说,简直一头雾水,在网上查询也几乎找不到像样的解释(Stack Overflow上有一篇帖子对hidden symbol的问题做了较好的解释,比较有启发性,这里不做具体阐述)。
  • 解决(回避)的方案:

    1. 既然,是引用Android log库的__android_log_print方法,那我们直接注释掉相关引用,绕过去,不就可以解决该问题吗。初步想来,该方法是可行的,因为日志打印只是辅助调试,对功能使用不影响。那么首先需要找出spidermonkey源码里面引用到__android_log_print的地方。这里可以直接利用工具在源码目录下面搜索,也可以通过在终端copy上面提到的链接命令,将其中的-llog去掉(也就是不再链接Android的log库),然后执行该链接命令(注意:直接copy链接命令,命令里面的某些路径是用的相对路径,copy到终端里面直接执行的话,可能会提示找不到某个文件或者目录的错误,这里一定要将找不到的这些文件或者目录替换成绝对路径,这样就可以找到了。这是因为该链接命令执行前,构建过程可能切换了工作路径,所以直接copy链接命令执行,相对路径就发生了变化,从而无法直接copy后执行),可以看到有类似下图的报错(注意,图中源码存放路径和本文的源码存放路径不同):

      这说明,去掉链接log库之后,由于__android_log_print未定义,所以肯定报错undefined reference to __android_log_print,但是这给我们提供了信息,即spidermonkey的哪些源码文件引用了__android_log_print,直接找到这些地方,将其注释掉(目前发现在两个文件中存在引用__android_log_print,一是/usr/local/spidermonkey/mozilla-central/js/src/vm/JSContext.cpp,二是构建目录下头文件/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ/dist/include/mozilla/Assertions.h,其实是链接到/usr/local/spidermonkey/mozilla-central/mfbt/Assertions.h)。注释掉这些地方之后,再次执行make,应该就可以成功了(最终会生成交互命令行的可执行程序jslibmozjs-xx.so分享库)。
    2. 上面提到Stack Overflow上这篇帖子解释了hidden symbol的问题,主要是与分享库有关,那么我们是不是可以生成static library来绕过这个问题呢,生成静态库只需要在配置命令加一个参数即可,请参见下面章节的描述。不过这种方法,暂无验证是否有效。
    3. 直接从make构建的异常信息入手,找到相关的Makefile文件及其引用的.mk文件,找到链接生成libmozjs-xx.so的命令所在处(mk文件内的具体行),弄清楚其中的逻辑,然后修改Makefile文件,再次执行make构建即可。不过这个方法非常费事,对C++和make构建不熟悉的话难度非常大,不建议采用。

构建完成之后,在构建目录(/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ)下(或在其子目录dist/binjs/src/build下,dist/bin下其实是一个链接文件,最终链接到js/src/build下的libmozjs-xxx.so),可以找到生成的libmozjs-xxx.so共享库,此时在Android studio中新建支持cpp的工程,把libmozjs-xxx.so和spidermonkey的相关头文件(位于/usr/local/spidermonkey/mozilla-central/js/src/build_OPT.OBJ/dist/include,其实最终链接到源码目录即/usr/local/spidermonkey/mozilla-central/js/src下的头文件,这些头文件不一定全部复制,可根据实际需要选取要引用到的) copy进去,通过NDK连接,然后就可以实现嵌入spidermonkey engine到Android APP,在APP里面执行javascript的代码了。简单的demo请参见https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/How_to_embed_the_JavaScript_engine

如果要生成static库(.a格式)而不是shared库,那么在步骤4中,还应该添加一个参数(–disable-shared-js),示例:

../configure –with-android-sdk=”/home/coulsonchen/.mozbuild/android-sdk-linux” –with-android-ndk=”/home/coulsonchen/.mozbuild/android-ndk-r15c” –with-android-version=23 –with-android-toolchain=/home/coulsonchen/.mozbuild/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 –target=arm-linux-androideabi –disable-shared-js

附录

  1. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Build_Documentation
  2. https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build
  3. http://mozilla.6506.n7.nabble.com/How-to-build-SpiderMonkey-for-Android-arm64-td333026.html
  4. https://developer.android.com/ndk/downloads/older_releases.html#ndk-15c-downloads