mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
198 lines
8.4 KiB
JavaScript
198 lines
8.4 KiB
JavaScript
const { isAbsolute, join, resolve, sep } = require("path");
|
|
const { readFileSync, writeFileSync } = require("fs");
|
|
|
|
const shelljs = require("shelljs");
|
|
const semver = require("semver");
|
|
|
|
const SnapshotGenerator = require("./snapshot-generator");
|
|
const {
|
|
CONSTANTS
|
|
} = require("./utils");
|
|
const {
|
|
ANDROID_PROJECT_DIR,
|
|
ANDROID_APP_PATH,
|
|
ANDROID_CONFIGURATIONS_PATH,
|
|
getAndroidRuntimeVersion,
|
|
getAndroidV8Version,
|
|
getRuntimeNdkRevision,
|
|
getMksnapshotParams
|
|
} = require("../../helpers/androidProjectHelpers");
|
|
|
|
// min version with settings.json file specifying the V8 version
|
|
const MIN_ANDROID_RUNTIME_VERSION = "5.2.1";
|
|
const VALID_ANDROID_RUNTIME_TAGS = Object.freeze(["next", "rc"]);
|
|
|
|
const resolveRelativePath = (path) => {
|
|
if (path)
|
|
return isAbsolute(path) ? path : resolve(process.cwd(), path);
|
|
return null;
|
|
};
|
|
|
|
function ProjectSnapshotGenerator(options) {
|
|
this.options = options = options || {};
|
|
options.projectRoot = resolveRelativePath(options.projectRoot) || process.cwd();
|
|
|
|
console.log("Project root: " + options.projectRoot);
|
|
console.log("Snapshots build directory: " + this.getBuildPath());
|
|
|
|
this.validateAndroidRuntimeVersion();
|
|
}
|
|
module.exports = ProjectSnapshotGenerator;
|
|
|
|
ProjectSnapshotGenerator.calculateBuildPath = function (projectRoot) {
|
|
return join(
|
|
ProjectSnapshotGenerator.calculateProjectPath(projectRoot),
|
|
"snapshot-build",
|
|
"build"
|
|
);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.prototype.getBuildPath = function () {
|
|
return ProjectSnapshotGenerator.calculateBuildPath(this.options.projectRoot);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.calculateProjectPath = function (projectRoot) {
|
|
return join(projectRoot, ANDROID_PROJECT_DIR);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.calculateConfigurationsPath = function (projectRoot) {
|
|
return join(projectRoot, ANDROID_CONFIGURATIONS_PATH);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.calculateAppPath = function (projectRoot) {
|
|
return join(projectRoot, ANDROID_APP_PATH);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.prototype.getProjectPath = function () {
|
|
return ProjectSnapshotGenerator.calculateProjectPath(this.options.projectRoot);
|
|
}
|
|
|
|
ProjectSnapshotGenerator.cleanSnapshotArtefacts = function (projectRoot) {
|
|
const platformPath = ProjectSnapshotGenerator.calculateProjectPath(projectRoot);
|
|
|
|
// Remove blob files from prepared folder
|
|
shelljs.rm("-rf", join(platformPath, "src/main/assets/snapshots"));
|
|
|
|
// Remove prepared include.gradle configurations
|
|
const configurationsPath = ProjectSnapshotGenerator.calculateConfigurationsPath(projectRoot);
|
|
shelljs.rm("-rf", join(configurationsPath, SnapshotGenerator.SNAPSHOT_PACKAGE_NANE));
|
|
}
|
|
|
|
ProjectSnapshotGenerator.installSnapshotArtefacts = function (projectRoot) {
|
|
const buildPath = ProjectSnapshotGenerator.calculateBuildPath(projectRoot);
|
|
const platformPath = ProjectSnapshotGenerator.calculateProjectPath(projectRoot);
|
|
|
|
const appPath = ProjectSnapshotGenerator.calculateAppPath(projectRoot);
|
|
const configurationsPath = ProjectSnapshotGenerator.calculateConfigurationsPath(projectRoot);
|
|
const configDestinationPath = join(configurationsPath, SnapshotGenerator.SNAPSHOT_PACKAGE_NANE);
|
|
|
|
// Remove build folder to make sure that the apk will be fully rebuild
|
|
shelljs.rm("-rf", join(platformPath, "build"));
|
|
|
|
// Copy include.gradle to the specified destination in the platforms folder
|
|
shelljs.mkdir("-p", configDestinationPath);
|
|
shelljs.cp(join(buildPath, "include.gradle"), join(configDestinationPath, "include.gradle"));
|
|
|
|
if (shelljs.test("-e", join(buildPath, "ndk-build/libs"))) {
|
|
// useLibs = true
|
|
const libsDestinationPath = join(platformPath, "src", SnapshotGenerator.SNAPSHOT_PACKAGE_NANE, "jniLibs");
|
|
|
|
// Copy the libs to the specified destination in the platforms folder
|
|
shelljs.mkdir("-p", libsDestinationPath);
|
|
shelljs.cp("-R", join(buildPath, "ndk-build/libs") + sep, libsDestinationPath);
|
|
} else {
|
|
// useLibs = false
|
|
const blobsSrcPath = join(buildPath, "snapshots/blobs");
|
|
const blobsDestinationPath = resolve(appPath, "../snapshots");
|
|
const appPackageJsonPath = join(appPath, "package.json");
|
|
|
|
// Copy the blobs in the prepared app folder
|
|
shelljs.cp("-R", blobsSrcPath + sep, resolve(appPath, "../snapshots"));
|
|
|
|
// Update the package.json file
|
|
const appPackageJson = shelljs.test("-e", appPackageJsonPath) ? JSON.parse(readFileSync(appPackageJsonPath, 'utf8')) : {};
|
|
appPackageJson["android"] = appPackageJson["android"] || {};
|
|
appPackageJson["android"]["heapSnapshotBlob"] = "../snapshots";
|
|
writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2));
|
|
}
|
|
}
|
|
|
|
ProjectSnapshotGenerator.prototype.validateAndroidRuntimeVersion = function () {
|
|
const currentRuntimeVersion = getAndroidRuntimeVersion(this.options.projectRoot);
|
|
|
|
if (!currentRuntimeVersion || !this.getProjectPath()) {
|
|
throw new Error("In order to generate a V8 snapshot you must have the \"android\" platform installed - to do so please run \"tns platform add android\".");
|
|
}
|
|
|
|
if (!VALID_ANDROID_RUNTIME_TAGS.includes(currentRuntimeVersion) &&
|
|
!semver.gte(currentRuntimeVersion, MIN_ANDROID_RUNTIME_VERSION)) {
|
|
|
|
throw new Error("In order to support heap snapshots, you must have at least tns-android@" + MIN_ANDROID_RUNTIME_VERSION +
|
|
" installed. Current Android Runtime version is: " + currentRuntimeVersion + ".");
|
|
}
|
|
}
|
|
|
|
ProjectSnapshotGenerator.prototype.generate = function (generationOptions) {
|
|
if (generationOptions.skipSnapshotTools) {
|
|
console.log("Skipping snapshot tools.");
|
|
return Promise.resolve();
|
|
}
|
|
|
|
generationOptions = generationOptions || {};
|
|
|
|
console.log("Running snapshot generation with the following arguments: ");
|
|
console.log(JSON.stringify(generationOptions, null, '\t'));
|
|
|
|
// Clean build folder
|
|
shelljs.rm("-rf", this.getBuildPath());
|
|
shelljs.mkdir("-p", this.getBuildPath());
|
|
|
|
const snapshotToolsPath = resolveRelativePath(generationOptions.snapshotToolsPath) || CONSTANTS.SNAPSHOT_TMP_DIR;
|
|
console.log("Snapshot tools path: " + snapshotToolsPath);
|
|
|
|
// Generate snapshots
|
|
const generator = new SnapshotGenerator({ buildPath: this.getBuildPath() });
|
|
const noV8VersionFoundMessage = `Cannot find suitable v8 version!`;
|
|
const mksnapshotParams = getMksnapshotParams(this.options.projectRoot);
|
|
const recommendedAndroidNdkRevision = getRuntimeNdkRevision(this.options.projectRoot);
|
|
const v8Version = generationOptions.v8Version || getAndroidV8Version(this.options.projectRoot);
|
|
if (!v8Version) {
|
|
throw new Error(noV8VersionFoundMessage);
|
|
}
|
|
|
|
// NOTE: Order is important! Add new archs at the end of the array
|
|
const defaultTargetArchs = ["arm", "arm64", "ia32", "ia64"];
|
|
const runtimeVersion = getAndroidRuntimeVersion(this.options.projectRoot);
|
|
if (runtimeVersion && semver.lt(semver.coerce(runtimeVersion), "6.0.2")) {
|
|
const indexOfIa64 = defaultTargetArchs.indexOf("ia64");
|
|
// Before 6.0.2 version of Android runtime we supported only arm, arm64 and ia32.
|
|
defaultTargetArchs.splice(indexOfIa64, defaultTargetArchs.length - indexOfIa64);
|
|
}
|
|
|
|
const options = {
|
|
snapshotToolsPath,
|
|
targetArchs: generationOptions.targetArchs || defaultTargetArchs,
|
|
v8Version: generationOptions.v8Version || v8Version,
|
|
preprocessedInputFile: generationOptions.preprocessedInputFile,
|
|
useLibs: generationOptions.useLibs || false,
|
|
inputFiles: generationOptions.inputFiles || [join(this.options.projectRoot, "__snapshot.js")],
|
|
androidNdkPath: generationOptions.androidNdkPath,
|
|
mksnapshotParams: mksnapshotParams,
|
|
snapshotInDocker: generationOptions.snapshotInDocker,
|
|
recommendedAndroidNdkRevision,
|
|
runtimeVersion
|
|
};
|
|
|
|
return generator.generate(options).then(() => {
|
|
console.log("Snapshots build finished succesfully!");
|
|
|
|
if (generationOptions.install) {
|
|
ProjectSnapshotGenerator.cleanSnapshotArtefacts(this.options.projectRoot);
|
|
ProjectSnapshotGenerator.installSnapshotArtefacts(this.options.projectRoot);
|
|
console.log(generationOptions.useLibs ?
|
|
"Snapshot is included in the app as dynamically linked library (.so file)." :
|
|
"Snapshot is included in the app as binary .blob file. The more space-efficient option is to embed it in a dynamically linked library (.so file).");
|
|
}
|
|
});;
|
|
}
|