Skip to content

Commit 8365318

Browse files
committed
feat: android plugin build will use its own plugin dependencies to build
This allow a Nativescript plugin to depend on another nativescript native plugin code
1 parent d474b7c commit 8365318

File tree

7 files changed

+130
-19
lines changed

7 files changed

+130
-19
lines changed

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

Lines changed: 9 additions & 2 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,11 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService {
419421
buildGradlePath,
420422
runtimeGradleVersions.gradleAndroidPluginVersion
421423
);
424+
this.replaceFileContent(
425+
buildGradlePath,
426+
"{{pluginName}}",
427+
pluginName
428+
);
422429
}
423430

424431
private async getRuntimeGradleVersions(

lib/services/android-project-service.ts

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

51+
52+
53+
interface NativeDependency {
54+
name: string;
55+
directory: string;
56+
dependencies: string[];
57+
}
58+
function treeSort(obj: NativeDependency[], start:NativeDependency[], depth = 0):NativeDependency[] {
59+
const processed = obj.reduce((a,b,i) => {
60+
if (b.dependencies.every(Array.prototype.includes, a.map(n=>n.name))) {
61+
a.push(b);
62+
}
63+
return a;
64+
}, start);
65+
const nextNames = obj.filter(n => !processed.includes(n));
66+
const goAgain = nextNames.length && depth <= obj.length;
67+
return goAgain ? treeSort(nextNames, processed, depth + 1) : processed;
68+
}
69+
5170
export class AndroidProjectService extends projectServiceBaseLib.PlatformProjectServiceBase {
5271
private static VALUES_DIRNAME = "values";
5372
private static VALUES_VERSION_DIRNAME_PREFIX =
@@ -635,10 +654,10 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
635654
public async beforePrepareAllPlugins(
636655
projectData: IProjectData,
637656
dependencies?: IDependencyData[]
638-
): Promise<void> {
657+
): Promise<IDependencyData[]> {
639658
if (dependencies) {
640659
dependencies = this.filterUniqueDependencies(dependencies);
641-
this.provideDependenciesJson(projectData, dependencies);
660+
return this.provideDependenciesJson(projectData, dependencies);
642661
}
643662
}
644663

@@ -666,7 +685,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
666685
private provideDependenciesJson(
667686
projectData: IProjectData,
668687
dependencies: IDependencyData[]
669-
): void {
688+
): IDependencyData[] {
670689
const platformDir = path.join(
671690
projectData.platformsDir,
672691
AndroidProjectService.ANDROID_PLATFORM_NAME
@@ -675,15 +694,21 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
675694
platformDir,
676695
constants.DEPENDENCIES_JSON_NAME
677696
);
678-
const nativeDependencies = dependencies
679-
.filter(AndroidProjectService.isNativeAndroidDependency)
680-
.map(({ name, directory }) => ({
697+
let nativeDependencyDatas = dependencies
698+
.filter(AndroidProjectService.isNativeAndroidDependency);
699+
700+
let nativeDependencies = nativeDependencyDatas.map(({ name, directory, dependencies }) => ({
681701
name,
682702
directory: path.relative(platformDir, directory),
683-
}));
703+
dependencies:dependencies.filter(d=>nativeDependencyDatas.findIndex(nd=>nd.name===d) !== -1)
704+
} as NativeDependency));
705+
nativeDependencies = treeSort(nativeDependencies, []);
684706
const jsonContent = JSON.stringify(nativeDependencies, null, 4);
685707

686708
this.$fs.writeFile(dependenciesJsonPath, jsonContent);
709+
return dependencies.sort(function(a, b){
710+
return nativeDependencies.findIndex(n => n.name === a.name) - nativeDependencies.findIndex(n => n.name === b.name);
711+
});
687712
}
688713

689714
private static isNativeAndroidDependency({

lib/services/ios-project-service.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ import {
2929
IIOSNativeTargetService,
3030
IValidatePlatformOutput,
3131
} from "../definitions/project";
32+
3233
import { IBuildData } from "../definitions/build";
33-
import { IXcprojService, IXcconfigService, IOptions } from "../declarations";
34+
import { IXcprojService, IXcconfigService, IDependencyData, IOptions } from "../declarations";
3435
import { IPluginData, IPluginsService } from "../definitions/plugins";
3536
import {
3637
IFileSystem,
@@ -976,8 +977,11 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
976977
await this.addExtensions(projectData, pluginsData);
977978
}
978979

979-
public beforePrepareAllPlugins(): Promise<void> {
980-
return Promise.resolve();
980+
public beforePrepareAllPlugins(
981+
projectData: IProjectData,
982+
dependencies?: IDependencyData[]
983+
): Promise<IDependencyData[]> {
984+
return Promise.resolve(dependencies);
981985
}
982986

983987
public async checkForChanges(

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
);

test/stubs.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ import {
4949
IDeviceDebugService,
5050
IDebugResultInfo,
5151
} from "../lib/definitions/debug";
52+
import {
53+
IDependencyData,
54+
} from "../lib/declarations";
5255
import { IBuildData } from "../lib/definitions/build";
5356
import {
5457
IFileSystem,
@@ -827,8 +830,11 @@ export class PlatformProjectServiceStub
827830
return Promise.resolve();
828831
}
829832

830-
async beforePrepareAllPlugins(): Promise<void> {
831-
return Promise.resolve();
833+
async beforePrepareAllPlugins(
834+
projectData: IProjectData,
835+
dependencies?: IDependencyData[]
836+
): Promise<IDependencyData[]> {
837+
return Promise.resolve(dependencies);
832838
}
833839

834840
async cleanDeviceTempFolder(deviceIdentifier: string): Promise<void> {

vendor/gradle-plugin/build.gradle

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk
1212
def computeBuildToolsVersion = { ->
1313
project.hasProperty("buildToolsVersion") ? buildToolsVersion : "31.0.0"
1414
}
15+
1516
buildscript {
17+
def getDepPlatformDir = { dep ->
18+
file("${project.ext.USER_PROJECT_ROOT}/${project.ext.PLATFORMS_ANDROID}/${dep.directory}/$PLATFORMS_ANDROID")
19+
}
1620
def computeKotlinVersion = { -> project.hasProperty("kotlinVersion") ? kotlinVersion : "1.6.0" }
1721
def kotlinVersion = computeKotlinVersion()
1822
repositories {
@@ -28,10 +32,18 @@ buildscript {
2832
}
2933

3034
// Set up styled logger
35+
project.ext.getDepPlatformDir = getDepPlatformDir
3136
project.ext.outLogger = services.get(StyledTextOutputFactory).create("colouredOutputLogger")
3237

3338
project.ext.USER_PROJECT_ROOT = "$rootDir/../../.."
34-
39+
project.ext.PLATFORMS_ANDROID = "platforms/android"
40+
project.ext.PLUGIN_NAME = "{{pluginName}}"
41+
42+
// the build script will not work with previous versions of the CLI (3.1 or earlier)
43+
def dependenciesJson = file("${project.ext.USER_PROJECT_ROOT}/${project.ext.PLATFORMS_ANDROID}/dependencies.json")
44+
def appDependencies = new JsonSlurper().parseText(dependenciesJson.text)
45+
def pluginData = appDependencies.find { it.name == project.ext.PLUGIN_NAME }
46+
project.ext.nativescriptDependencies = appDependencies.findAll{pluginData.dependencies.contains(it.name)}
3547
project.ext.getAppPath = { ->
3648
def relativePathToApp = "app"
3749
def nsConfigFile = file("$USER_PROJECT_ROOT/nsconfig.json")
@@ -90,6 +102,15 @@ buildscript {
90102
apply from: pathToBuildScriptGradle, to: buildscript
91103
}
92104

105+
nativescriptDependencies.each { dep ->
106+
def pathToPluginBuildScriptGradle = "${getDepPlatformDir(dep)}/buildscript.gradle"
107+
def pluginBuildScriptGradle = file(pathToPluginBuildScriptGradle)
108+
if (pluginBuildScriptGradle.exists()) {
109+
outLogger.withStyle(Style.SuccessHeader).println "\t + applying user-defined buildscript from dependency ${pluginBuildScriptGradle}"
110+
apply from: pathToPluginBuildScriptGradle, to: buildscript
111+
}
112+
}
113+
93114
def pathToPluginBuildScriptGradle = "$rootDir/buildscript.gradle"
94115
def pluginBuildScriptGradle = file(pathToPluginBuildScriptGradle)
95116
if (pluginBuildScriptGradle.exists()) {
@@ -101,23 +122,48 @@ buildscript {
101122

102123
}
103124

125+
def pluginDependencies
126+
104127
allprojects {
105128
repositories {
129+
// used for local *.AAR files
130+
pluginDependencies = nativescriptDependencies.collect {
131+
getDepPlatformDir(it)
132+
}
133+
134+
// some plugins may have their android dependencies in a /libs subdirectory
135+
pluginDependencies.addAll(nativescriptDependencies.collect {
136+
"${getDepPlatformDir(it)}/libs"
137+
})
106138
mavenLocal()
107139
mavenCentral()
108140
maven {
109141
url 'https://maven.google.com/'
110142
name 'Google'
111143
}
112144
jcenter()
145+
if (pluginDependencies.size() > 0) {
146+
flatDir {
147+
dirs pluginDependencies
148+
}
149+
}
113150
}
114151
}
115152

116153
android {
154+
def applyPluginGradleConfigurations = { ->
155+
nativescriptDependencies.each { dep ->
156+
def includeGradlePath = "${getDepPlatformDir(dep)}/include.gradle"
157+
if (file(includeGradlePath).exists()) {
158+
apply from: includeGradlePath
159+
}
160+
}
161+
}
117162
kotlinOptions {
118163
jvmTarget = '1.8'
119164
}
120165
applyBeforePluginGradleConfiguration()
166+
applyPluginGradleConfigurations()
121167

122168
compileSdkVersion computeCompileSdkVersion()
123169
buildToolsVersion computeBuildToolsVersion()
@@ -164,4 +210,27 @@ tasks.whenTaskAdded({ DefaultTask currentTask ->
164210
currentTask.exclude '**/R.class', '**/R$*.class'
165211
}
166212
}
167-
})
213+
})
214+
215+
216+
217+
task addDependenciesFromNativeScriptPlugins {
218+
nativescriptDependencies.each { dep ->
219+
def aarFiles = fileTree(dir: getDepPlatformDir(dep), include: ["**/*.aar"])
220+
aarFiles.each { aarFile ->
221+
def length = aarFile.name.length() - 4
222+
def fileName = aarFile.name[0..<length]
223+
outLogger.withStyle(Style.SuccessHeader).println "\t + adding aar plugin dependency: " + aarFile.getAbsolutePath()
224+
project.dependencies.add("implementation", [name: fileName, ext: "aar"])
225+
}
226+
227+
def jarFiles = fileTree(dir: getDepPlatformDir(dep), include: ["**/*.jar"])
228+
jarFiles.each { jarFile ->
229+
def jarFileAbsolutePath = jarFile.getAbsolutePath()
230+
outLogger.withStyle(Style.SuccessHeader).println "\t + adding jar plugin dependency: $jarFileAbsolutePath"
231+
pluginsJarLibraries.add(jarFile.getAbsolutePath())
232+
}
233+
234+
project.dependencies.add("implementation", jarFiles)
235+
}
236+
}

0 commit comments

Comments
 (0)