Skip to content

Commit 5e5f18a

Browse files
Merge pull request #3750 from NativeScript/vladimirov/rebuild-plugin-when-required-only
feat: Improve rebuild of native plugins and node_modules checks
2 parents 0f403d2 + 1a2388e commit 5e5f18a

15 files changed

+172
-34
lines changed

lib/commands/appstore-upload.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ export class PublishIOS implements ICommand {
6060
const platformInfo: IPreparePlatformInfo = {
6161
platform,
6262
appFilesUpdaterOptions,
63-
skipModulesNativeCheck: !this.$options.syncAllFiles,
6463
platformTemplate: this.$options.platformTemplate,
6564
projectData: this.$projectData,
6665
config: this.$options,

lib/commands/build.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export class BuildCommandBase {
1717
const platformInfo: IPreparePlatformInfo = {
1818
platform,
1919
appFilesUpdaterOptions,
20-
skipModulesNativeCheck: !this.$options.syncAllFiles,
2120
platformTemplate: this.$options.platformTemplate,
2221
projectData: this.$projectData,
2322
config: this.$options,

lib/commands/prepare.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export class PrepareCommand implements ICommand {
1414
const platformInfo: IPreparePlatformInfo = {
1515
platform: args[0],
1616
appFilesUpdaterOptions,
17-
skipModulesNativeCheck: !this.$options.syncAllFiles,
1817
platformTemplate: this.$options.platformTemplate,
1918
projectData: this.$projectData,
2019
config: this.$options,

lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,5 @@ export const PACKAGE_PLACEHOLDER_NAME = "__PACKAGE__";
217217
export class AddPlaformErrors {
218218
public static InvalidFrameworkPathStringFormat = "Invalid frameworkPath: %s. Please ensure the specified frameworkPath exists.";
219219
}
220+
221+
export const PLUGIN_BUILD_DATA_FILENAME = "plugin-data.json";
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
interface IFilesHashService {
22
generateHashes(files: string[]): Promise<IStringDictionary>;
33
getChanges(files: string[], oldHashes: IStringDictionary): Promise<IStringDictionary>;
4-
}
4+
hasChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean;
5+
}

lib/definitions/project-changes.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ interface IProjectChangesOptions extends IAppFilesUpdaterOptions, IProvision, IT
4141
nativePlatformStatus?: "1" | "2" | "3";
4242
}
4343

44+
interface ICheckForChangesOptions extends IPlatform, IProjectDataComposition {
45+
projectChangesOptions: IProjectChangesOptions;
46+
}
47+
4448
interface IProjectChangesService {
45-
checkForChanges(platform: string, projectData: IProjectData, buildOptions: IProjectChangesOptions): Promise<IProjectChangesInfo>;
49+
checkForChanges(checkForChangesOpts: ICheckForChangesOptions): Promise<IProjectChangesInfo>;
4650
getPrepareInfo(platform: string, projectData: IProjectData): IPrepareInfo;
4751
savePrepareInfo(platform: string, projectData: IProjectData): void;
4852
getPrepareInfoFilePath(platform: string, projectData: IProjectData): string;

lib/services/android-plugin-build-service.ts

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from "path";
2-
import { MANIFEST_FILE_NAME, INCLUDE_GRADLE_NAME, ASSETS_DIR, RESOURCES_DIR, TNS_ANDROID_RUNTIME_NAME, AndroidBuildDefaults } from "../constants";
2+
import { MANIFEST_FILE_NAME, INCLUDE_GRADLE_NAME, ASSETS_DIR, RESOURCES_DIR, TNS_ANDROID_RUNTIME_NAME, AndroidBuildDefaults, PLUGIN_BUILD_DATA_FILENAME } from "../constants";
33
import { getShortPluginName, hook } from "../common/helpers";
44
import { Builder, parseString } from "xml2js";
55
import { ILogger } from "log4js";
@@ -25,7 +25,8 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
2525
private $npm: INodePackageManager,
2626
private $projectDataService: IProjectDataService,
2727
private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
28-
private $errors: IErrors) { }
28+
private $errors: IErrors,
29+
private $filesHashService: IFilesHashService) { }
2930

3031
private static MANIFEST_ROOT = {
3132
$: {
@@ -172,23 +173,80 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
172173
this.validateOptions(options);
173174
const manifestFilePath = this.getManifest(options.platformsAndroidDirPath);
174175
const androidSourceDirectories = this.getAndroidSourceDirectories(options.platformsAndroidDirPath);
175-
const shouldBuildAar = !!manifestFilePath || androidSourceDirectories.length > 0;
176+
const shortPluginName = getShortPluginName(options.pluginName);
177+
const pluginTempDir = path.join(options.tempPluginDirPath, shortPluginName);
178+
const pluginSourceFileHashesInfo = await this.getSourceFilesHashes(options.platformsAndroidDirPath, shortPluginName);
179+
180+
const shouldBuildAar = await this.shouldBuildAar({
181+
manifestFilePath,
182+
androidSourceDirectories,
183+
pluginTempDir,
184+
pluginSourceDir: options.platformsAndroidDirPath,
185+
shortPluginName,
186+
fileHashesInfo: pluginSourceFileHashesInfo
187+
});
176188

177189
if (shouldBuildAar) {
178-
const shortPluginName = getShortPluginName(options.pluginName);
179-
const pluginTempDir = path.join(options.tempPluginDirPath, shortPluginName);
180-
const pluginTempMainSrcDir = path.join(pluginTempDir, "src", "main");
190+
this.cleanPluginDir(pluginTempDir);
181191

192+
const pluginTempMainSrcDir = path.join(pluginTempDir, "src", "main");
182193
await this.updateManifest(manifestFilePath, pluginTempMainSrcDir, shortPluginName);
183194
this.copySourceSetDirectories(androidSourceDirectories, pluginTempMainSrcDir);
184195
await this.setupGradle(pluginTempDir, options.platformsAndroidDirPath, options.projectDir);
185196
await this.buildPlugin({ pluginDir: pluginTempDir, pluginName: options.pluginName });
186197
this.copyAar(shortPluginName, pluginTempDir, options.aarOutputDir);
198+
this.writePluginHashInfo(pluginSourceFileHashesInfo, pluginTempDir);
187199
}
188200

189201
return shouldBuildAar;
190202
}
191203

204+
private cleanPluginDir(pluginTempDir: string): void {
205+
// In case plugin was already built in the current process, we need to clean the old sources as they may break the new build.
206+
this.$fs.deleteDirectory(pluginTempDir);
207+
this.$fs.ensureDirectoryExists(pluginTempDir);
208+
}
209+
210+
private getSourceFilesHashes(pluginTempPlatformsAndroidDir: string, shortPluginName: string): Promise<IStringDictionary> {
211+
const pathToAar = path.join(pluginTempPlatformsAndroidDir, `${shortPluginName}.aar`);
212+
const pluginNativeDataFiles = this.$fs.enumerateFilesInDirectorySync(pluginTempPlatformsAndroidDir, (file: string, stat: IFsStats) => file !== pathToAar);
213+
return this.$filesHashService.generateHashes(pluginNativeDataFiles);
214+
}
215+
216+
private writePluginHashInfo(fileHashesInfo: IStringDictionary, pluginTempDir: string): void {
217+
const buildDataFile = this.getPathToPluginBuildDataFile(pluginTempDir);
218+
this.$fs.writeJson(buildDataFile, fileHashesInfo);
219+
}
220+
221+
private async shouldBuildAar(opts: {
222+
manifestFilePath: string,
223+
androidSourceDirectories: string[],
224+
pluginTempDir: string,
225+
pluginSourceDir: string,
226+
shortPluginName: string,
227+
fileHashesInfo: IStringDictionary
228+
}): Promise<boolean> {
229+
230+
let shouldBuildAar = !!opts.manifestFilePath || !!opts.androidSourceDirectories.length;
231+
232+
if (shouldBuildAar &&
233+
this.$fs.exists(opts.pluginTempDir) &&
234+
this.$fs.exists(path.join(opts.pluginSourceDir, `${opts.shortPluginName}.aar`))) {
235+
236+
const buildDataFile = this.getPathToPluginBuildDataFile(opts.pluginTempDir);
237+
if (this.$fs.exists(buildDataFile)) {
238+
const oldHashes = this.$fs.readJson(buildDataFile);
239+
shouldBuildAar = this.$filesHashService.hasChangesInShasums(oldHashes, opts.fileHashesInfo);
240+
}
241+
}
242+
243+
return shouldBuildAar;
244+
}
245+
246+
private getPathToPluginBuildDataFile(pluginDir: string): string {
247+
return path.join(pluginDir, PLUGIN_BUILD_DATA_FILENAME);
248+
}
249+
192250
private async updateManifest(manifestFilePath: string, pluginTempMainSrcDir: string, shortPluginName: string): Promise<void> {
193251
let updatedManifestContent;
194252
this.$fs.ensureDirectoryExists(pluginTempMainSrcDir);
@@ -256,7 +314,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
256314
return runtimeGradleVersions || {};
257315
}
258316

259-
private getGradleVersions(packageData: { gradle: { version: string, android: string }}): IRuntimeGradleVersions {
317+
private getGradleVersions(packageData: { gradle: { version: string, android: string } }): IRuntimeGradleVersions {
260318
const packageJsonGradle = packageData && packageData.gradle;
261319
let runtimeVersions: IRuntimeGradleVersions = null;
262320
if (packageJsonGradle && (packageJsonGradle.version || packageJsonGradle.android)) {

lib/services/files-hash-service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ export class FilesHashService implements IFilesHashService {
2626

2727
public async getChanges(files: string[], oldHashes: IStringDictionary): Promise<IStringDictionary> {
2828
const newHashes = await this.generateHashes(files);
29+
return this.getChangesInShasums(oldHashes, newHashes);
30+
}
31+
32+
public hasChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean {
33+
return !!_.keys(this.getChangesInShasums(oldHashes, newHashes)).length;
34+
}
35+
36+
private getChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): IStringDictionary {
2937
return _.omitBy(newHashes, (hash: string, pathToFile: string) => !!_.find(oldHashes, (oldHash: string, oldPath: string) => pathToFile === oldPath && hash === oldHash));
3038
}
3139
}

lib/services/livesync/livesync-service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,6 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
469469
deviceBuildInfoDescriptor,
470470
liveSyncData,
471471
settings,
472-
skipModulesNativeCheck: !liveSyncData.watchAllFiles,
473472
bundle: liveSyncData.bundle,
474473
release: liveSyncData.release,
475474
env: liveSyncData.env

lib/services/platform-service.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,17 @@ export class PlatformService extends EventEmitter implements IPlatformService {
269269

270270
const bundle = appFilesUpdaterOptions.bundle;
271271
const nativePlatformStatus = (nativePrepare && nativePrepare.skipNativePrepare) ? constants.NativePlatformStatus.requiresPlatformAdd : constants.NativePlatformStatus.requiresPrepare;
272-
const changesInfo = await this.$projectChangesService.checkForChanges(platform, projectData, {
273-
bundle,
274-
release: appFilesUpdaterOptions.release,
275-
provision: config.provision,
276-
teamId: config.teamId,
277-
nativePlatformStatus,
278-
skipModulesNativeCheck: skipNativeCheckOptions.skipModulesNativeCheck
272+
const changesInfo = await this.$projectChangesService.checkForChanges({
273+
platform,
274+
projectData,
275+
projectChangesOptions: {
276+
bundle,
277+
release: appFilesUpdaterOptions.release,
278+
provision: config.provision,
279+
teamId: config.teamId,
280+
nativePlatformStatus,
281+
skipModulesNativeCheck: skipNativeCheckOptions.skipModulesNativeCheck
282+
}
279283
});
280284

281285
this.$logger.trace("Changes info in prepare platform:", changesInfo);

0 commit comments

Comments
 (0)