2013-08-13 08:07:23 +08:00
#!/usr/bin/env node
/ *
Licensed to the Apache Software Foundation ( ASF ) under one
or more contributor license agreements . See the NOTICE file
distributed with this work for additional information
regarding copyright ownership . The ASF licenses this file
to you under the Apache License , Version 2.0 ( the
"License" ) ; you may not use this file except in compliance
with the License . You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing ,
software distributed under the License is distributed on an
"AS IS" BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND , either express or implied . See the License for the
specific language governing permissions and limitations
under the License .
* /
2014-08-16 01:42:43 +08:00
var shelljs = require ( 'shelljs' ) ,
2013-09-27 23:48:55 +08:00
child _process = require ( 'child_process' ) ,
Q = require ( 'q' ) ,
2013-08-13 08:07:23 +08:00
path = require ( 'path' ) ,
fs = require ( 'fs' ) ,
2014-06-20 04:12:40 +08:00
which = require ( 'which' ) ,
2013-08-13 08:07:23 +08:00
ROOT = path . join ( _ _dirname , '..' , '..' ) ;
2014-08-16 01:42:43 +08:00
var isWindows = process . platform == 'win32' ;
2014-08-19 02:45:23 +08:00
function forgivingWhichSync ( cmd ) {
try {
2014-08-19 03:26:05 +08:00
return which . sync ( cmd ) ;
2014-08-19 02:45:23 +08:00
} catch ( e ) {
return '' ;
}
}
2014-08-16 01:42:43 +08:00
function tryCommand ( cmd , errMsg ) {
var d = Q . defer ( ) ;
child _process . exec ( cmd , function ( err , stdout , stderr ) {
if ( err ) d . reject ( new Error ( errMsg ) ) ;
else d . resolve ( stdout ) ;
} ) ;
return d . promise ;
}
2013-08-13 08:07:23 +08:00
// Get valid target from framework/project.properties
module . exports . get _target = function ( ) {
if ( fs . existsSync ( path . join ( ROOT , 'framework' , 'project.properties' ) ) ) {
2014-08-16 01:42:43 +08:00
var target = shelljs . grep ( /target=android-[\d+]/ , path . join ( ROOT , 'framework' , 'project.properties' ) ) ;
2013-08-13 08:07:23 +08:00
return target . split ( '=' ) [ 1 ] . replace ( '\n' , '' ) . replace ( '\r' , '' ) . replace ( ' ' , '' ) ;
} else if ( fs . existsSync ( path . join ( ROOT , 'project.properties' ) ) ) {
// if no target found, we're probably in a project and project.properties is in ROOT.
2013-11-21 01:35:23 +08:00
// this is called on the project itself, and can support Google APIs AND Vanilla Android
2014-08-16 01:42:43 +08:00
var target = shelljs . grep ( /target=android-[\d+]/ , path . join ( ROOT , 'project.properties' ) ) ||
shelljs . grep ( /target=Google Inc.:Google APIs:[\d+]/ , path . join ( ROOT , 'project.properties' ) ) ;
2014-05-09 03:37:09 +08:00
if ( target == "" || ! target ) {
// Try Google Glass APIs
2014-08-16 01:42:43 +08:00
target = shelljs . grep ( /target=Google Inc.:Glass Development Kit Preview:[\d+]/ , path . join ( ROOT , 'project.properties' ) ) ;
2014-05-09 03:37:09 +08:00
}
2013-11-21 01:35:23 +08:00
return target . split ( '=' ) [ 1 ] . replace ( '\n' , '' ) . replace ( '\r' , '' ) ;
2013-08-13 08:07:23 +08:00
}
}
2014-08-16 01:58:53 +08:00
// Returns a promise. Called only by build and clean commands.
2013-08-13 08:07:23 +08:00
module . exports . check _ant = function ( ) {
2014-08-16 01:42:43 +08:00
return tryCommand ( 'ant -version' , 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.' ) ;
2013-08-13 08:07:23 +08:00
}
2013-09-27 23:48:55 +08:00
// Returns a promise.
2013-08-13 08:07:23 +08:00
module . exports . check _java = function ( ) {
2014-08-19 02:45:23 +08:00
var javacPath = forgivingWhichSync ( 'javac' ) ;
var hasJavaHome = ! ! process . env [ 'JAVA_HOME' ] ;
return Q ( ) . then ( function ( ) {
if ( hasJavaHome ) {
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
if ( ! javacPath ) {
process . env [ 'PATH' ] += path . delimiter + path . join ( process . env [ 'JAVA_HOME' ] , 'bin' ) ;
}
} else {
if ( javacPath ) {
// OS X has a command for finding JAVA_HOME.
if ( fs . existsSync ( '/usr/libexec/java_home' ) ) {
return tryCommand ( '/usr/libexec/java_home' , 'Failed to run: /usr/libexec/java_home' )
. then ( function ( stdout ) {
process . env [ 'JAVA_HOME' ] = stdout . trim ( ) ;
} ) ;
} else {
// See if we can derive it from javac's location.
var maybeJavaHome = path . dirname ( path . dirname ( javacPath ) ) ;
if ( fs . existsSync ( path . join ( maybeJavaHome , 'lib' , 'tools.jar' ) ) ) {
process . env [ 'JAVA_HOME' ] = maybeJavaHome ;
} else {
throw new Error ( 'Could not find JAVA_HOME. Try setting the environment variable manually' ) ;
}
}
} else if ( isWindows ) {
// Try to auto-detect java in the default install paths.
var firstJdkDir =
shelljs . ls ( process . env [ 'ProgramFiles' ] + '\\java\\jdk*' ) [ 0 ] ||
shelljs . ls ( 'C:\\Program Files\\java\\jdk*' ) [ 0 ] ||
shelljs . ls ( 'C:\\Program Files (x86)\\java\\jdk*' ) [ 0 ] ;
if ( firstJdkDir ) {
// shelljs always uses / in paths.
firstJdkDir = firstJdkDir . replace ( /\//g , path . sep ) ;
if ( ! javacPath ) {
process . env [ 'PATH' ] += path . delimiter + path . join ( firstJdkDir , 'bin' ) ;
}
process . env [ 'JAVA_HOME' ] = firstJdkDir ;
}
2014-08-16 01:42:43 +08:00
}
2013-11-28 05:59:20 +08:00
}
2014-08-19 02:45:23 +08:00
} ) . then ( function ( ) {
var msg =
'Failed to run "java -version", make sure your java environment is set up\n' +
'including JDK and JRE.\n' +
'Your JAVA_HOME variable is: ' + process . env [ 'JAVA_HOME' ] ;
return tryCommand ( 'java -version' , msg )
} ) . then ( function ( ) {
2014-08-16 01:42:43 +08:00
msg = 'Failed to run "javac -version", make sure you have a Java JDK (not just a JRE) installed.' ;
return tryCommand ( 'javac -version' , msg )
2013-11-28 05:59:20 +08:00
} ) ;
2013-08-13 08:07:23 +08:00
}
2013-09-27 23:48:55 +08:00
// Returns a promise.
2013-08-13 08:07:23 +08:00
module . exports . check _android = function ( ) {
2014-08-19 02:45:23 +08:00
var androidCmdPath = forgivingWhichSync ( 'android' ) ;
var adbInPath = ! ! forgivingWhichSync ( 'adb' ) ;
var hasAndroidHome = ! ! process . env [ 'ANDROID_HOME' ] && fs . existsSync ( process . env [ 'ANDROID_HOME' ] ) ;
2014-08-16 01:42:43 +08:00
if ( hasAndroidHome && ! androidCmdPath ) {
2014-08-19 02:45:23 +08:00
process . env [ 'PATH' ] += path . delimiter + path . join ( process . env [ 'ANDROID_HOME' ] , 'tools' ) ;
2014-08-16 01:42:43 +08:00
}
if ( androidCmdPath && ! hasAndroidHome ) {
2014-08-19 02:45:23 +08:00
var parentDir = path . dirname ( androidCmdPath ) ;
if ( path . basename ( parentDir ) == 'tools' ) {
process . env [ 'ANDROID_HOME' ] = path . dirname ( parentDir ) ;
hasAndroidHome = true ;
}
2014-08-16 01:42:43 +08:00
}
if ( hasAndroidHome && ! adbInPath ) {
2014-08-19 02:45:23 +08:00
process . env [ 'PATH' ] += path . delimiter + path . join ( process . env [ 'ANDROID_HOME' ] , 'platform-tools' ) ;
2014-08-16 01:42:43 +08:00
}
2013-08-13 08:07:23 +08:00
2014-08-16 01:42:43 +08:00
var valid _target = this . get _target ( ) ;
var msg = 'Failed to run "android". Make sure you have the latest Android SDK installed, and that the "android" command (inside the tools/ folder) is added to your PATH.' ;
return tryCommand ( 'android list targets' , msg )
. then ( function ( output ) {
2013-09-27 23:48:55 +08:00
if ( ! output . match ( valid _target ) ) {
2014-08-16 01:42:43 +08:00
return Q . reject ( new Error ( 'Please install Android target ' + valid _target . split ( '-' ) [ 1 ] +
' (the Android newest SDK). Make sure you have the latest Android tools installed as well.' +
' Run "android" from your command-line to install/update any missing SDKs or tools.' ) ) ;
2013-09-27 23:48:55 +08:00
}
2014-08-19 02:45:23 +08:00
} ) . then ( function ( ) {
if ( ! process . env [ 'ANDROID_HOME' ] ) {
throw new Error ( 'ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.' ) ;
}
if ( ! fs . existsSync ( process . env [ 'ANDROID_HOME' ] ) ) {
throw new Error ( 'ANDROID_HOME is set to a non-existant path: ' + process . env [ 'ANDROID_HOME' ] ) ;
}
2013-09-27 23:48:55 +08:00
} ) ;
2013-08-13 08:07:23 +08:00
}
2013-09-27 23:48:55 +08:00
// Returns a promise.
2013-08-13 08:07:23 +08:00
module . exports . run = function ( ) {
2014-08-16 01:58:53 +08:00
return Q . all ( [ this . check _java ( ) , this . check _android ( ) ] ) ;
2013-09-14 09:38:46 +08:00
}
2013-10-18 21:59:42 +08:00