mirror of
https://github.com/apache/cordova-android.git
synced 2026-05-30 00:00:04 +08:00
refactor: java checks (#1130)
Co-authored-by: エリス <erisu@users.noreply.github.com> Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update spec/unit/java.spec.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update spec/unit/java.spec.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update bin/templates/cordova/lib/utils.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update bin/templates/cordova/lib/check_reqs.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update spec/unit/check_reqs.spec.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Update spec/unit/check_reqs.spec.js Co-authored-by: Raphael von der Grün <raphinesse@gmail.com> Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>
This commit is contained in:
+18
-89
@@ -20,30 +20,20 @@
|
||||
const execa = require('execa');
|
||||
var path = require('path');
|
||||
var fs = require('fs-extra');
|
||||
var os = require('os');
|
||||
var which = require('which');
|
||||
const glob = require('fast-glob');
|
||||
const { forgivingWhichSync, isWindows, isDarwin } = require('./utils');
|
||||
const java = require('./env/java');
|
||||
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
|
||||
var PROJECT_ROOT = path.join(__dirname, '..', '..');
|
||||
const { CordovaError, ConfigParser, events } = require('cordova-common');
|
||||
var android_sdk = require('./android_sdk');
|
||||
const { createEditor } = require('properties-parser');
|
||||
const semver = require('semver');
|
||||
|
||||
function forgivingWhichSync (cmd) {
|
||||
const whichResult = which.sync(cmd, { nothrow: true });
|
||||
const EXPECTED_JAVA_VERSION = '1.8.x';
|
||||
|
||||
// On null, returns empty string to maintain backwards compatibility
|
||||
// realpathSync follows symlinks
|
||||
return whichResult === null ? '' : fs.realpathSync(whichResult);
|
||||
}
|
||||
|
||||
module.exports.isWindows = function () {
|
||||
return (os.platform() === 'win32');
|
||||
};
|
||||
|
||||
module.exports.isDarwin = function () {
|
||||
return (os.platform() === 'darwin');
|
||||
};
|
||||
// Re-exporting these for backwards compatibility and for unit testing.
|
||||
// TODO: Remove uses and use the ./utils module directly.
|
||||
Object.assign(module.exports, { isWindows, isDarwin });
|
||||
|
||||
/**
|
||||
* @description Get valid target from framework/project.properties if run from this repo
|
||||
@@ -143,72 +133,18 @@ module.exports.check_gradle = function () {
|
||||
'in your path, or install Android Studio'));
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_java = function () {
|
||||
var javacPath = forgivingWhichSync('javac');
|
||||
var hasJavaHome = !!process.env.JAVA_HOME;
|
||||
return Promise.resolve().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.
|
||||
var find_java = '/usr/libexec/java_home';
|
||||
var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
|
||||
if (fs.existsSync(find_java)) {
|
||||
return execa(find_java).then(({ stdout }) => {
|
||||
process.env.JAVA_HOME = stdout;
|
||||
}).catch(function (err) {
|
||||
if (err) {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}
|
||||
});
|
||||
} 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 CordovaError(default_java_error_msg);
|
||||
}
|
||||
}
|
||||
} else if (module.exports.isWindows()) {
|
||||
const { env } = process;
|
||||
const baseDirs = [env.ProgramFiles, env['ProgramFiles(x86)']];
|
||||
const globOpts = { absolute: true, onlyDirectories: true };
|
||||
const flatMap = (arr, f) => [].concat(...arr.map(f));
|
||||
/**
|
||||
* Checks for the java installation and correct version
|
||||
*/
|
||||
module.exports.check_java = async function () {
|
||||
const javaVersion = await java.getVersion();
|
||||
|
||||
const jdkDir = flatMap(baseDirs, cwd =>
|
||||
glob.sync('java/jdk*', { cwd, ...globOpts })
|
||||
)[0];
|
||||
|
||||
if (jdkDir) {
|
||||
env.PATH += path.delimiter + path.join(jdkDir, 'bin');
|
||||
env.JAVA_HOME = path.normalize(jdkDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(function () {
|
||||
return execa('javac', ['-version'], { all: true })
|
||||
.then(({ all: output }) => {
|
||||
// Java <= 8 writes version info to stderr, Java >= 9 to stdout
|
||||
const match = /javac\s+([\d.]+)/i.exec(output);
|
||||
return match && match[1];
|
||||
}, () => {
|
||||
var msg =
|
||||
'Failed to run "javac -version", make sure that you have a JDK version 8 installed.\n' +
|
||||
'You can get it from the following location:\n' +
|
||||
'https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html';
|
||||
if (process.env.JAVA_HOME) {
|
||||
msg += '\n\n';
|
||||
msg += 'Your JAVA_HOME is invalid: ' + process.env.JAVA_HOME;
|
||||
}
|
||||
throw new CordovaError(msg);
|
||||
});
|
||||
});
|
||||
if (!semver.satisfies(javaVersion.version, EXPECTED_JAVA_VERSION)) {
|
||||
throw new CordovaError(
|
||||
`Requirements check failed for JDK ${EXPECTED_JAVA_VERSION}! Detected version: ${javaVersion.version}\n` +
|
||||
'Check your ANDROID_SDK_ROOT / JAVA_HOME / PATH environment variables.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
@@ -384,13 +320,6 @@ module.exports.run = function () {
|
||||
return Promise.all([this.check_java(), this.check_android()]).then(function (values) {
|
||||
console.log('Using Android SDK: ' + process.env.ANDROID_SDK_ROOT);
|
||||
|
||||
if (!String(values[0]).startsWith('1.8.')) {
|
||||
throw new CordovaError(
|
||||
'Requirements check failed for JDK 8 (\'1.8.*\')! Detected version: ' + values[0] + '\n' +
|
||||
'Check your ANDROID_SDK_ROOT / JAVA_HOME / PATH environment variables.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!values[1]) {
|
||||
throw new CordovaError('Requirements check failed for Android SDK! Android SDK was not detected.');
|
||||
}
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
const execa = require('execa');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const glob = require('fast-glob');
|
||||
const { CordovaError, events } = require('cordova-common');
|
||||
const utils = require('../utils');
|
||||
const semver = require('semver');
|
||||
|
||||
/**
|
||||
* Will be set to true on successful ensureness.
|
||||
* If true, skips the expensive java checks.
|
||||
*/
|
||||
let javaIsEnsured = false;
|
||||
|
||||
const java = {
|
||||
/**
|
||||
* Gets the version from the javac executable.
|
||||
*
|
||||
* @returns {semver.SemVer}
|
||||
*/
|
||||
getVersion: async () => {
|
||||
await java._ensure(process.env);
|
||||
|
||||
// Java <= 8 writes version info to stderr, Java >= 9 to stdout
|
||||
let version = null;
|
||||
try {
|
||||
version = (await execa('javac', ['-version'], { all: true })).all;
|
||||
} catch (ex) {
|
||||
events.emit('verbose', ex.shortMessage);
|
||||
|
||||
let msg =
|
||||
'Failed to run "javac -version", make sure that you have a JDK version 8 installed.\n' +
|
||||
'You can get it from the following location:\n' +
|
||||
'https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html';
|
||||
if (process.env.JAVA_HOME) {
|
||||
msg += '\n\n';
|
||||
msg += 'Your JAVA_HOME is invalid: ' + process.env.JAVA_HOME;
|
||||
}
|
||||
throw new CordovaError(msg);
|
||||
}
|
||||
|
||||
return semver.coerce(version);
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensures that Java is installed. Will throw exception if not.
|
||||
* Will set JAVA_HOME and PATH environment variables.
|
||||
*
|
||||
* This function becomes a no-op if already ran previously.
|
||||
*/
|
||||
_ensure: async (environment) => {
|
||||
if (javaIsEnsured) {
|
||||
return;
|
||||
}
|
||||
|
||||
const javacPath = utils.forgivingWhichSync('javac');
|
||||
const hasJavaHome = !!environment.JAVA_HOME;
|
||||
if (hasJavaHome) {
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (!javacPath) {
|
||||
environment.PATH += path.delimiter + path.join(environment.JAVA_HOME, 'bin');
|
||||
}
|
||||
} else {
|
||||
if (javacPath) {
|
||||
// OS X has a command for finding JAVA_HOME.
|
||||
const find_java = '/usr/libexec/java_home';
|
||||
const default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
|
||||
if (fs.existsSync(find_java)) {
|
||||
try {
|
||||
environment.JAVA_HOME = (await execa(find_java)).stdout;
|
||||
} catch (ex) {
|
||||
events.emit('verbose', ex.shortMessage);
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}
|
||||
} 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'))) {
|
||||
environment.JAVA_HOME = maybeJavaHome;
|
||||
} else {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}
|
||||
}
|
||||
} else if (utils.isWindows()) {
|
||||
const baseDirs = [environment.ProgramFiles, environment['ProgramFiles(x86)']];
|
||||
const globOpts = { absolute: true, onlyDirectories: true };
|
||||
const flatMap = (arr, f) => [].concat(...arr.map(f));
|
||||
const jdkDir = flatMap(baseDirs, cwd => {
|
||||
return glob.sync('java/jdk*', { cwd, ...globOpts });
|
||||
}
|
||||
)[0];
|
||||
|
||||
if (jdkDir) {
|
||||
environment.PATH += path.delimiter + path.join(jdkDir, 'bin');
|
||||
environment.JAVA_HOME = path.normalize(jdkDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
javaIsEnsured = true;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = java;
|
||||
Vendored
+13
@@ -24,6 +24,8 @@
|
||||
// TODO: Perhaps this should live in cordova-common?
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const which = require('which');
|
||||
const os = require('os');
|
||||
|
||||
/**
|
||||
* Reads, searches, and replaces the found occurences with replacementString and then writes the file back out.
|
||||
@@ -53,3 +55,14 @@ exports.compareByAll = fns => {
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
exports.forgivingWhichSync = (cmd) => {
|
||||
const whichResult = which.sync(cmd, { nothrow: true });
|
||||
|
||||
// On null, returns empty string to maintain backwards compatibility
|
||||
// realpathSync follows symlinks
|
||||
return whichResult === null ? '' : fs.realpathSync(whichResult);
|
||||
};
|
||||
|
||||
exports.isWindows = () => os.platform() === 'win32';
|
||||
exports.isDarwin = () => os.platform() === 'darwin';
|
||||
|
||||
Reference in New Issue
Block a user