11const fs = require ( "fs" ) ;
22const { dirname, relative, join, EOL } = require ( "path" ) ;
33const child_process = require ( "child_process" ) ;
4- const { convertToUnixPath } = require ( "../../lib/utils" ) ;
5-
4+ const { convertToUnixPath, warn } = require ( "../../lib/utils" ) ;
5+ const PropertiesReader = require ( 'properties-reader' ) ;
66const shelljs = require ( "shelljs" ) ;
77
88const { createDirectory, downloadFile, getHostOS, getHostOSArch, CONSTANTS , has32BitArch, isMacOSCatalinaOrHigher, isSubPath } = require ( "./utils" ) ;
@@ -192,8 +192,9 @@ SnapshotGenerator.prototype.setupDocker = function () {
192192 child_process . execSync ( `docker pull ${ SNAPSHOTS_DOCKER_IMAGE } ` ) ;
193193}
194194
195- SnapshotGenerator . prototype . buildSnapshotLibs = function ( androidNdkBuildPath , targetArchs ) {
195+ SnapshotGenerator . prototype . buildSnapshotLibs = function ( androidNdkPath , recommendedAndroidNdkRevision , targetArchs ) {
196196 // Compile *.c files to produce *.so libraries with ndk-build tool
197+ const androidNdkBuildPath = this . getAndroidNdkBuildPath ( androidNdkPath , recommendedAndroidNdkRevision ) ;
197198 const ndkBuildPath = join ( this . buildPath , "ndk-build" ) ;
198199 const androidArchs = targetArchs . map ( arch => this . convertToAndroidArchName ( arch ) ) ;
199200 console . log ( "Building native libraries for " + androidArchs . join ( ) ) ;
@@ -207,6 +208,54 @@ SnapshotGenerator.prototype.buildSnapshotLibs = function (androidNdkBuildPath, t
207208 return join ( ndkBuildPath , "libs" ) ;
208209}
209210
211+ SnapshotGenerator . prototype . getAndroidNdkBuildPath = function ( androidNdkPath , recommendedAndroidNdkRevision ) {
212+ const ndkBuildExecutableName = "ndk-build" ;
213+ // fallback for Android Runtime < 6.2.0 with the 6.1.0 value
214+ recommendedAndroidNdkRevision = recommendedAndroidNdkRevision || "20.0.5594570" ;
215+ let androidNdkBuildPath = "" ;
216+ if ( androidNdkPath ) {
217+ // specified by the user
218+ const localNdkRevision = this . getAndroidNdkRevision ( androidNdkPath ) ;
219+ androidNdkBuildPath = join ( androidNdkPath , ndkBuildExecutableName ) ;
220+ if ( ! fs . existsSync ( androidNdkBuildPath ) ) {
221+ throw new Error ( `The provided Android NDK path does not contain ${ ndkBuildExecutableName } executable.` ) ;
222+ } else if ( localNdkRevision !== recommendedAndroidNdkRevision ) {
223+ warn ( `The provided Android NDK is v${ localNdkRevision } while the recommended one is v${ recommendedAndroidNdkRevision } ` ) ;
224+ }
225+ } else {
226+ // available globally
227+ let hasAndroidNdkInPath = true ;
228+ androidNdkBuildPath = ndkBuildExecutableName ;
229+ try {
230+ child_process . execSync ( `${ androidNdkBuildPath } --version` ) ;
231+ console . log ( `Cannot determine the version of the global Android NDK. The recommended versions is v${ recommendedAndroidNdkRevision } ` ) ;
232+ } catch ( _ ) {
233+ hasAndroidNdkInPath = false ;
234+ }
235+
236+ if ( ! hasAndroidNdkInPath ) {
237+ // installed in ANDROID_HOME
238+ const androidHome = process . env . ANDROID_HOME ;
239+ androidNdkBuildPath = join ( androidHome , "ndk" , recommendedAndroidNdkRevision , ndkBuildExecutableName ) ;
240+ if ( ! fs . existsSync ( androidNdkBuildPath ) ) {
241+ throw new Error ( `Android NDK v${ recommendedAndroidNdkRevision } is not installed. You can find installation instructions in this article: https://developer.android.com/studio/projects/install-ndk#specific-version` ) ;
242+ }
243+ }
244+ }
245+
246+ return androidNdkBuildPath ;
247+ }
248+
249+ SnapshotGenerator . prototype . getAndroidNdkRevision = function ( androidNdkPath ) {
250+ const ndkPropertiesFile = join ( androidNdkPath , "source.properties" ) ;
251+ if ( fs . existsSync ( ndkPropertiesFile ) ) {
252+ const properties = PropertiesReader ( ndkPropertiesFile ) ;
253+ return properties . get ( "Pkg.Revision" ) ;
254+ } else {
255+ return null ;
256+ }
257+ }
258+
210259SnapshotGenerator . prototype . buildIncludeGradle = function ( ) {
211260 shelljs . cp ( INCLUDE_GRADLE_PATH , join ( this . buildPath , "include.gradle" ) ) ;
212261}
@@ -236,8 +285,7 @@ SnapshotGenerator.prototype.generate = function (options) {
236285 ) . then ( ( ) => {
237286 this . buildIncludeGradle ( ) ;
238287 if ( options . useLibs ) {
239- const androidNdkBuildPath = options . androidNdkPath ? join ( options . androidNdkPath , "ndk-build" ) : "ndk-build" ;
240- this . buildSnapshotLibs ( androidNdkBuildPath , options . targetArchs ) ;
288+ this . buildSnapshotLibs ( options . androidNdkPath , options . recommendedAndroidNdkRevision , options . targetArchs ) ;
241289 }
242290 return this . buildPath ;
243291 } ) ;
0 commit comments