编译ReactNative-0.57.8的64位so
背景
支持64位so的要求:
- Google Play要求在2019-8月之后的所有更新包都必须支持64位
- 方舟编译器也需要支持64位
ReactNative从0.58.0版本开始,支持64位,但更新ReactNative的版本的成本非常之高,升级频率一般在1年左右
ReactNative已经开源,理论上只要利用其源码编译出64位的so就可以
ReactNative的源码编译
参考文章:Building from source
步骤:
- 下载0.57.8的源码:v0.57.8源码 或 从github下载对应的Tag也可以
- 创建一个ReactNative项目:
- 参考文档:Getting Started
- npm install -g react-native-cli
- react-native init AwesomeProject –version 0.57.8
- 修改项目的编译参数:
- 打开文件:AwesomeProject/android/build.gradle
- 修改如下参数及对应值:—- 因为reactnative-0.57.8的依赖
- minSdkVersion = 16
- compileSdkVersion = 27
- targetSdkVersion = 26
- buildToolsVersion = “27.0.3”
- 下载Android-NDK:android-ndk-r17c
- 修改环境变量
- vim ~/.bash_profile
- 添加如下配置:
- export ANDROID_SDK=android-sdk路径
- export ANDROID_NDK=android-ndk-r17c路径
- 添加local.properties文件:
- 位置:AwesomeProject/android/
- 内容:
- sdk.dir=android-sdk路径
- ndk.dir=android-ndk-r17c路径
- 替换AwesomeProject/node_modules目录下的react-native:
- 删除AwesomeProject/node_modules/react-native文件夹
- 复react-native-0.57.8的源码到目录AwesomeProject/node_modules下,并修改目录名为react-native
- 在AwesomeProject/node_modules/react-native目录下,执行npm install脚本
- 修改AwesomeProject/android/build.gradle文件:
1
2
3
4
5
6
7
8
9...
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'de.undercouch:gradle-download-task:3.4.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
... - 修改AwesomeProject/android/settings.gradle文件:
1
2
3
4
5
6...
include ':ReactAndroid'
project(':ReactAndroid').projectDir = new File(
rootProject.projectDir, '../node_modules/react-native/ReactAndroid')
... - 修改AwesomeProject/android/app/build.gradle文件:
1
2
3
4
5
6
7
8
9
10...
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}'
implementation project(':ReactAndroid')
...
}
... - Android Studio打开项目: Import project,选择 AwesomeProject/android 文件夹
- 编译:app [assembleDebug]
编译64位so
修改配置,编译64位so:
- ReactAndroid/src/main/jni/Application.mk:添加arm64-v8a, x86_64
1
2
3...
APP_ABI := armeabi-v7a x86 arm64-v8a x86_64
... - android/app/build.gradle:添加arm64-v8a, x86_64
1
2
3
4
5...
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
... - Clean工程:注意保留ReactAndroid/build/downloads目录,每次下载时间很长
- 编译:app [assembleDebug]
- 结果:编译出错,无法找到jsc的64位so
问题原因分析:ReactNative的jni代码依赖了第三方库的C代码,如下所示:
- boost:源码依赖,先下载源码,再编译
- double-conversion:源码依赖,先下载源码,再编译
- folly:源码依赖,先下载源码,再编译
- glibc:c的运行库
- glog:源码依赖,先下载源码,再编译
- jsc:依赖aar(org.webkit:android-jsc:r174650),但此aar里,只有armeabi armeabi-v7a x86,没有64位的so,分析过程如下:
- 查找jsc的task:
1
2:ReactAndroid:downloadJSCHeaders
:ReactAndroid:prepareJSC - prepareJSC:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// Create Android.mk library module based on so files from mvn + include headers fetched from webkit.org
task prepareJSC(dependsOn: dependenciesPath ? [] : [downloadJSCHeaders]) << {
copy {
from zipTree(configurations.compile.fileCollection { dep -> dep.name == 'android-jsc' }.singleFile)
from dependenciesPath ? "$dependenciesPath/jsc-headers" : {downloadJSCHeaders.dest}
from 'src/main/jni/third-party/jsc/Android.mk'
include 'jni/**/*.so', '*.h', 'Android.mk'
filesMatching('*.h', { fname -> fname.path = "JavaScriptCore/${fname.path}"})
into "$thirdPartyNdkDir/jsc";
}
}
// 对应的依赖
dependencies {
...
compile 'org.webkit:android-jsc:r174650'
} - 从prepareJSC的逻辑:当下载了org.webkit:android-jsc:r174650文件后,读取其中so文件
- 下载org.webkit:android-jsc:r174650文件,修改后缀为.zip,解压,发现没有64位so:
- 查找jsc的task:
分析0.58.0的解决方案:(注意:react-native-0.58.0版本已经支持了64位so)
- 下载0.58.0的源码:0.58.0
- 其依赖jsc的方式没有变:依赖aar,版本号也没有变,还是r174650
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16task prepareJSC(dependsOn: dependenciesPath ? [] : [downloadJSCHeaders]) << {
copy {
from zipTree(configurations.compile.fileCollection { dep -> dep.name == 'android-jsc' }.singleFile)
from dependenciesPath ? "$dependenciesPath/jsc-headers" : {downloadJSCHeaders.dest}
from 'src/main/jni/third-party/jsc'
include 'jni/**/*.so', '*.h', 'Android.mk'
filesMatching('*.h', { fname -> fname.path = "JavaScriptCore/${fname.path}"})
into "$thirdPartyNdkDir/jsc";
}
}
dependencies {
...
compile 'org.webkit:android-jsc:r174650'
...
} - 但ReactAndroid/src/main/third-party/jsc目录有变化,内置了arm64-v8a和x86_64的so进来:
解决方案: 由于android-jsc的版本号一样,那0.58.0内置的jsc的64位so,在0.57.8版本里也可以使用
- 完整复制0.58.0下的jsc64位so到0.57.8的对应目录下
- 修改ReactAndroid/build.gradle脚本:使用文件对比工具FileMerge,查看0.58.0与jsc有关的改动点:
- prepareJSC里,copy命令修改:from ‘src/main/jni/third-party/jsc/Android.mk’ 改为 from ‘src/main/jni/third-party/jsc’
- jniLibs.srcDirs的目录修改:jniLibs.srcDir “$buildDir/react-ndk/exported” 改为 jniLibs.srcDirs = [“$buildDir/react-ndk/exported”, ‘src/main/jni/third-party/jsc/jni’]
- prepareJSC里,copy命令修改:from ‘src/main/jni/third-party/jsc/Android.mk’ 改为 from ‘src/main/jni/third-party/jsc’
- 编译:app [assembleDebug]
- 编译后的so:链接:https://pan.baidu.com/s/1f-O6mcmrUxVu6g4DOXXqkA 密码:qk83