Skip to content

Commit 1435eef

Browse files
feat: build transient native dependencies (#5643)
Co-authored-by: Igor Randjelovic <rigor789@gmail.com>
1 parent 356630a commit 1435eef

12 files changed

+325
-133
lines changed

lib/definitions/android-plugin-migrator.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ interface IBuildAndroidPluginData extends Partial<IProjectDir> {
4444
* Optional custom Gradle path.
4545
*/
4646
gradlePath?: string;
47-
48-
/**
47+
48+
/**
4949
* Optional custom Gradle arguments.
5050
*/
51-
gradleArgs?: string,
51+
gradleArgs?: string;
5252
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
258258
await this.setupGradle(
259259
pluginTempDir,
260260
options.platformsAndroidDirPath,
261-
options.projectDir
261+
options.projectDir,
262+
options.pluginName
262263
);
263264
await this.buildPlugin({
264265
gradlePath: options.gradlePath,
@@ -398,7 +399,8 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
398399
private async setupGradle(
399400
pluginTempDir: string,
400401
platformsAndroidDirPath: string,
401-
projectDir: string
402+
projectDir: string,
403+
pluginName: string
402404
): Promise<void> {
403405
const gradleTemplatePath = path.resolve(
404406
path.join(__dirname, "../../vendor/gradle-plugin")
@@ -419,6 +421,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
419421
buildGradlePath,
420422
runtimeGradleVersions.gradleAndroidPluginVersion
421423
);
424+
this.replaceFileContent(buildGradlePath, "{{pluginName}}", pluginName);
422425
}
423426

424427
private async getRuntimeGradleVersions(
@@ -729,7 +732,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
729732
`-PcompileSdk=android-${pluginBuildSettings.androidToolsInfo.compileSdkVersion}`,
730733
`-PbuildToolsVersion=${pluginBuildSettings.androidToolsInfo.buildToolsVersion}`,
731734
`-PappPath=${this.$projectData.getAppDirectoryPath()}`,
732-
`-PappResourcesPath=${this.$projectData.getAppResourcesDirectoryPath()}`
735+
`-PappResourcesPath=${this.$projectData.getAppResourcesDirectoryPath()}`,
733736
];
734737
if (pluginBuildSettings.gradleArgs) {
735738
localArgs.push(pluginBuildSettings.gradleArgs);

lib/services/android-project-service.ts

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,71 @@ import { IInjector } from "../common/definitions/yok";
4848
import { injector } from "../common/yok";
4949
import { INotConfiguredEnvOptions } from "../common/definitions/commands";
5050

51+
interface NativeDependency {
52+
name: string;
53+
directory: string;
54+
dependencies: string[];
55+
}
56+
57+
//
58+
// we sort the native dependencies topologically to make sure they are processed in the right order
59+
// native dependenciess need to be sorted so the deepst dependencies are built before it's parents
60+
//
61+
// for example, given this dep structure (assuming these are all native dependencies that need to be built)
62+
// |- dep1
63+
// |- dep2
64+
// |- dep3
65+
// |- dep4
66+
// |-dep5
67+
// |- dep6
68+
//
69+
// It is sorted:
70+
// |- dep1 - doesn't depend on anything, so the order stays the same as in the input list
71+
// |- dep3 - doesn't depend on anything, so the order stays the same as in the input list
72+
// |- dep5 - doesn't depend on anything, so the order stays the same as in the input list
73+
// |- dep6 - doesn't depend on anything, so the order stays the same as in the input list
74+
// |- dep4 - depends on dep6, so dep6 must be built first, ie above ^
75+
// |- dep2 - depends on dep3, dep4, dep5 and dep6, so all of them must be built first
76+
//
77+
// for more details see: https://wikiless.org/wiki/Topological_sorting?lang=en
78+
//
79+
function topologicalSortNativeDependencies(
80+
nativeDeps: NativeDependency[],
81+
start: NativeDependency[] = [],
82+
depth = 0
83+
): NativeDependency[] {
84+
const processedDeps = nativeDeps.reduce(
85+
(accumulator, nativeDep: NativeDependency) => {
86+
if (
87+
nativeDep.dependencies.every(
88+
Array.prototype.includes,
89+
accumulator.map((n) => n.name)
90+
)
91+
) {
92+
accumulator.push(nativeDep);
93+
}
94+
return accumulator;
95+
},
96+
start
97+
);
98+
99+
const remainingDeps = nativeDeps.filter(
100+
(nativeDep) => !processedDeps.includes(nativeDep)
101+
);
102+
103+
// recurse if we still have unprocessed deps
104+
// the second condition here prevents infinite recursion
105+
if (remainingDeps.length && depth <= nativeDeps.length) {
106+
return topologicalSortNativeDependencies(
107+
remainingDeps,
108+
processedDeps,
109+
depth + 1
110+
);
111+
}
112+
113+
return processedDeps;
114+
}
115+
51116
export class AndroidProjectService extends projectServiceBaseLib.PlatformProjectServiceBase {
52117
private static VALUES_DIRNAME = "values";
53118
private static VALUES_VERSION_DIRNAME_PREFIX =
@@ -635,10 +700,10 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
635700
public async beforePrepareAllPlugins(
636701
projectData: IProjectData,
637702
dependencies?: IDependencyData[]
638-
): Promise<void> {
703+
): Promise<IDependencyData[]> {
639704
if (dependencies) {
640705
dependencies = this.filterUniqueDependencies(dependencies);
641-
this.provideDependenciesJson(projectData, dependencies);
706+
return this.provideDependenciesJson(projectData, dependencies);
642707
}
643708
}
644709

@@ -666,7 +731,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
666731
private provideDependenciesJson(
667732
projectData: IProjectData,
668733
dependencies: IDependencyData[]
669-
): void {
734+
): IDependencyData[] {
670735
const platformDir = path.join(
671736
projectData.platformsDir,
672737
AndroidProjectService.ANDROID_PLATFORM_NAME
@@ -675,15 +740,37 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
675740
platformDir,
676741
constants.DEPENDENCIES_JSON_NAME
677742
);
678-
const nativeDependencies = dependencies
679-
.filter(AndroidProjectService.isNativeAndroidDependency)
680-
.map(({ name, directory }) => ({
681-
name,
682-
directory: path.relative(platformDir, directory),
683-
}));
684-
const jsonContent = JSON.stringify(nativeDependencies, null, 4);
743+
let nativeDependencyData = dependencies.filter(
744+
AndroidProjectService.isNativeAndroidDependency
745+
);
685746

747+
let nativeDependencies = nativeDependencyData.map(
748+
({ name, directory, dependencies }) => {
749+
return {
750+
name,
751+
directory: path.relative(platformDir, directory),
752+
dependencies: dependencies.filter((dep) => {
753+
// filter out transient dependencies that don't have native dependencies
754+
return (
755+
nativeDependencyData.findIndex(
756+
(nativeDep) => nativeDep.name === dep
757+
) !== -1
758+
);
759+
}),
760+
} as NativeDependency;
761+
}
762+
);
763+
nativeDependencies = topologicalSortNativeDependencies(nativeDependencies);
764+
const jsonContent = JSON.stringify(nativeDependencies, null, 4);
686765
this.$fs.writeFile(dependenciesJsonPath, jsonContent);
766+
767+
// we sort all the dependencies to respect the topological sorting of the native dependencies
768+
return dependencies.sort(function (a, b) {
769+
return (
770+
nativeDependencies.findIndex((n) => n.name === a.name) -
771+
nativeDependencies.findIndex((n) => n.name === b.name)
772+
);
773+
});
687774
}
688775

689776
private static isNativeAndroidDependency({

lib/services/ios-project-service.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { IOSProvisionService } from "./ios-provision-service";
1313
import { IOSEntitlementsService } from "./ios-entitlements-service";
1414
import { IOSBuildData } from "../data/build-data";
1515
import { IOSPrepareData } from "../data/prepare-data";
16-
import { BUILD_XCCONFIG_FILE_NAME, CONFIG_FILE_NAME_DISPLAY, IosProjectConstants } from "../constants";
16+
import {
17+
BUILD_XCCONFIG_FILE_NAME,
18+
CONFIG_FILE_NAME_DISPLAY,
19+
IosProjectConstants,
20+
} from "../constants";
1721
import { hook } from "../common/helpers";
1822
import {
1923
IPlatformData,
@@ -29,8 +33,14 @@ import {
2933
IIOSNativeTargetService,
3034
IValidatePlatformOutput,
3135
} from "../definitions/project";
36+
3237
import { IBuildData } from "../definitions/build";
33-
import { IXcprojService, IXcconfigService, IOptions } from "../declarations";
38+
import {
39+
IXcprojService,
40+
IXcconfigService,
41+
IDependencyData,
42+
IOptions,
43+
} from "../declarations";
3444
import { IPluginData, IPluginsService } from "../definitions/plugins";
3545
import {
3646
IFileSystem,
@@ -976,8 +986,11 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
976986
await this.addExtensions(projectData, pluginsData);
977987
}
978988

979-
public beforePrepareAllPlugins(): Promise<void> {
980-
return Promise.resolve();
989+
public beforePrepareAllPlugins(
990+
projectData: IProjectData,
991+
dependencies?: IDependencyData[]
992+
): Promise<IDependencyData[]> {
993+
return Promise.resolve(dependencies);
981994
}
982995

983996
public async checkForChanges(

lib/services/platform-environment-requirements.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ export class PlatformEnvironmentRequirements
2424
// private $staticConfig: IStaticConfig,
2525
private $analyticsService: IAnalyticsService,
2626
// @ts-ignore - required by the hook helper!
27-
private $injector: IInjector
28-
) // private $previewQrCodeService: IPreviewQrCodeService
29-
{}
27+
private $injector: IInjector // private $previewQrCodeService: IPreviewQrCodeService
28+
) {}
3029

3130
// public get $previewAppController(): IPreviewAppController {
3231
// return this.$injector.resolve("previewAppController");

lib/services/project-changes-service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ export class ProjectChangesService implements IProjectChangesService {
9393
);
9494

9595
this.$nodeModulesDependenciesBuilder
96-
.getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies)
96+
.getProductionDependencies(
97+
projectData.projectDir,
98+
projectData.ignoredDependencies
99+
)
97100
.filter(
98101
(dep) =>
99102
dep.nativescript &&

lib/services/webpack/webpack.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ declare global {
163163
beforePrepareAllPlugins(
164164
projectData: IProjectData,
165165
dependencies?: IDependencyData[]
166-
): Promise<void>;
166+
): Promise<IDependencyData[]>;
167167

168168
handleNativeDependenciesChange(
169169
projectData: IProjectData,

lib/tools/node-modules/node-modules-builder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ export class NodeModulesBuilder implements INodeModulesBuilder {
1818
platformData,
1919
projectData,
2020
}: IPrepareNodeModulesData): Promise<void> {
21-
const dependencies = this.$nodeModulesDependenciesBuilder.getProductionDependencies(
21+
let dependencies = this.$nodeModulesDependenciesBuilder.getProductionDependencies(
2222
projectData.projectDir, projectData.ignoredDependencies
2323
);
24-
await platformData.platformProjectService.beforePrepareAllPlugins(
24+
dependencies = await platformData.platformProjectService.beforePrepareAllPlugins(
2525
projectData,
2626
dependencies
2727
);

lib/tools/node-modules/node-modules-dependencies-builder.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { IDependencyData } from "../../declarations";
55
import { IFileSystem } from "../../common/declarations";
66
import * as _ from "lodash";
77
import { injector } from "../../common/yok";
8+
import { resolvePackagePath } from "@rigor789/resolve-package-path";
89

910
interface IDependencyDescription {
1011
parent: IDependencyDescription;
@@ -43,7 +44,8 @@ export class NodeModulesDependenciesBuilder
4344
const currentModule = queue.shift();
4445
const resolvedDependency = this.findModule(
4546
currentModule,
46-
resolvedDependencies
47+
resolvedDependencies,
48+
projectPath
4749
);
4850

4951
if (
@@ -86,16 +88,29 @@ export class NodeModulesDependenciesBuilder
8688

8789
private findModule(
8890
depDescription: IDependencyDescription,
89-
resolvedDependencies: IDependencyData[]
91+
resolvedDependencies: IDependencyData[],
92+
rootPath: string
9093
): IDependencyData {
9194
try {
9295
const parentModulesPath =
9396
depDescription?.parentDir ?? depDescription?.parent?.parentDir;
94-
const modulePath = require
95-
.resolve(`${depDescription.name}/package.json`, {
96-
paths: [parentModulesPath],
97-
})
98-
.replace(/[\\/]+package\.json$/, "");
97+
98+
let modulePath: string = resolvePackagePath(depDescription.name, {
99+
paths: [parentModulesPath],
100+
});
101+
102+
// perhaps traverse up the tree here?
103+
if (!modulePath) {
104+
// fallback to searching in the root path
105+
modulePath = resolvePackagePath(depDescription.name, {
106+
paths: [rootPath],
107+
});
108+
}
109+
110+
// if we failed to find the module...
111+
if (!modulePath) {
112+
return null;
113+
}
99114

100115
// if we already resolved this dependency, we return null to avoid a duplicate resolution
101116
if (

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy