Skip to content

Commit 283b31c

Browse files
authored
Merge pull request #3398 from NativeScript/plamen5kov/rebuild-aar
Plamen5kov/rebuild aar
2 parents 069e69f + 1cda138 commit 283b31c

32 files changed

+2207
-87
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ env:
55
- NATIVESCRIPT_SKIP_POSTINSTALL_TASKS=1
66
language: node_js
77
node_js:
8-
- '6'
8+
- '8'
99
git:
1010
submodules: true
1111
install:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<% if (isJekyll) { %>---
2+
title: tns plugin build
3+
position: 8
4+
---<% } %>
5+
# tns plugin build
6+
==========
7+
8+
Usage | Synopsis
9+
------|-------
10+
General | `$ tns plugin build`
11+
12+
<% if(isConsole) { %>Attempts to build the plugin's Android-specific project files located in `platforms/android`. Strips and removes `include.gradle` flavor declarations, if any are present. <% } %>
13+
<% if(isHtml) { %>Attempts to build the plugin's Android-specific project files located in `platforms/android`. The resulting Android Library (aar), and the generated Android Gradle project used to build the library can be found at `platforms/android`. Also strips and removes `include.gradle` flavor declarations, if any are present. For more information about working with plugins, see [NativeScript Plugins](https://github.com/NativeScript/nativescript-cli/blob/master/PLUGINS.md).<% } %>
14+
15+
16+
<% if(isHtml) { %>
17+
### Prerequisites
18+
19+
* Verify that the command is being executed in the source directory of a plugin - e.g. `nativescript-barcodescanner/src`
20+
21+
### Related Commands
22+
23+
Command | Description
24+
----------|----------
25+
[plugin](plugin.html) | Lets you manage the plugins for your project.
26+
[plugin install](plugin-install.html) | Installs the specified plugin and its dependencies.
27+
[plugin remove](plugin-remove.html) | Uninstalls the specified plugin and its dependencies.
28+
<% } %>

docs/man_pages/lib-management/plugin.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Lets you manage the plugins for your project.
1919
* `update` - Uninstalls and installs the specified plugin(s) and its dependencies.
2020
* `find` - Finds NativeScript plugins in npm.
2121
* `search` - Finds NativeScript plugins in npm.
22+
* `build` - Builds the Android parts of a NativeScript plugin.
2223

2324
<% if(isHtml) { %>
2425
### Related Commands
@@ -28,4 +29,5 @@ Command | Description
2829
[plugin add](plugin-add.html) | Installs the specified plugin and its dependencies.
2930
[plugin remove](plugin-remove.html) | Uninstalls the specified plugin and its dependencies.
3031
[plugin update](plugin-update.html) | Updates the specified plugin(s) and its dependencies.
32+
[plugin build](plugin-build.html) | Builds the Android project of a NativeScript plugin, and updates the `include.gradle`.
3133
<% } %>

lib/bootstrap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ $injector.require("projectData", "./project-data");
99
$injector.requirePublic("projectDataService", "./services/project-data-service");
1010
$injector.requirePublic("projectService", "./services/project-service");
1111
$injector.require("androidProjectService", "./services/android-project-service");
12+
$injector.require("androidPluginBuildService", "./services/android-plugin-build-service");
1213
$injector.require("iOSEntitlementsService", "./services/ios-entitlements-service");
1314
$injector.require("iOSProjectService", "./services/ios-project-service");
1415
$injector.require("iOSProvisionService", "./services/ios-provision-service");
@@ -90,6 +91,7 @@ $injector.requireCommand("plugin|add", "./commands/plugin/add-plugin");
9091
$injector.requireCommand("plugin|install", "./commands/plugin/add-plugin");
9192
$injector.requireCommand("plugin|remove", "./commands/plugin/remove-plugin");
9293
$injector.requireCommand("plugin|update", "./commands/plugin/update-plugin");
94+
$injector.requireCommand("plugin|build", "./commands/plugin/build-plugin");
9395

9496
$injector.require("doctorService", "./services/doctor-service");
9597
$injector.require("xcprojService", "./services/xcproj-service");

lib/commands/plugin/build-plugin.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { EOL } from "os";
2+
import * as path from "path";
3+
import * as constants from "../../constants";
4+
export class BuildPluginCommand implements ICommand {
5+
public allowedParameters: ICommandParameter[] = [];
6+
public pluginProjectPath: string;
7+
8+
constructor(private $androidPluginBuildService: IAndroidPluginBuildService,
9+
private $errors: IErrors,
10+
private $logger: ILogger,
11+
private $fs: IFileSystem,
12+
private $options: IOptions) {
13+
14+
this.pluginProjectPath = path.resolve(this.$options.path || ".");
15+
}
16+
17+
public async execute(args: string[]): Promise<void> {
18+
const platformsAndroidPath = path.join(this.pluginProjectPath, constants.PLATFORMS_DIR_NAME, "android");
19+
let pluginName = "";
20+
21+
const pluginPackageJsonPath = path.join(this.pluginProjectPath, constants.PACKAGE_JSON_FILE_NAME);
22+
23+
if (this.$fs.exists(pluginPackageJsonPath)) {
24+
const packageJsonContents = this.$fs.readJson(pluginPackageJsonPath);
25+
26+
if (packageJsonContents && packageJsonContents["name"]) {
27+
pluginName = packageJsonContents["name"];
28+
}
29+
}
30+
31+
const tempAndroidProject = path.join(platformsAndroidPath, "android-project");
32+
33+
const options: IBuildOptions = {
34+
aarOutputDir: platformsAndroidPath,
35+
platformsAndroidDirPath: platformsAndroidPath,
36+
pluginName: pluginName,
37+
tempPluginDirPath: tempAndroidProject
38+
};
39+
40+
const androidPluginBuildResult = await this.$androidPluginBuildService.buildAar(options);
41+
42+
if (androidPluginBuildResult) {
43+
this.$logger.info(`${pluginName} successfully built aar at ${platformsAndroidPath}.${EOL}Temporary Android project can be found at ${tempAndroidProject}.`);
44+
}
45+
46+
const migratedIncludeGradle = this.$androidPluginBuildService.migrateIncludeGradle(options);
47+
48+
if (migratedIncludeGradle) {
49+
this.$logger.info(`${pluginName} include gradle updated.`);
50+
}
51+
}
52+
53+
public async canExecute(args: string[]): Promise<boolean> {
54+
if (!this.$fs.exists(path.join(this.pluginProjectPath, constants.PLATFORMS_DIR_NAME, "android"))) {
55+
this.$errors.failWithoutHelp("No plugin found at the current directory, or the plugin does not need to have its platforms/android components built into an `.aar`.");
56+
}
57+
58+
return true;
59+
}
60+
}
61+
62+
$injector.registerCommand("plugin|build", BuildPluginCommand);

lib/common

Submodule common updated 1 file

lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ export const SRC_DIR = "src";
2424
export const MAIN_DIR = "main";
2525
export const ASSETS_DIR = "assets";
2626
export const MANIFEST_FILE_NAME = "AndroidManifest.xml";
27+
export const INCLUDE_GRADLE_NAME = "include.gradle";
2728
export const BUILD_DIR = "build";
2829
export const OUTPUTS_DIR = "outputs";
2930
export const APK_DIR = "apk";
3031
export const RESOURCES_DIR = "res";
3132
export const CONFIG_NS_FILE_NAME = "nsconfig.json";
3233
export const CONFIG_NS_APP_RESOURCES_ENTRY = "appResourcesPath";
3334
export const CONFIG_NS_APP_ENTRY = "appPath";
35+
export const DEPENDENCIES_JSON_NAME = "dependencies.json";
3436

3537
export class PackageVersion {
3638
static NEXT = "next";
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
interface IBuildOptions extends IAndroidBuildOptions{
3+
}
4+
5+
interface IAndroidBuildOptions {
6+
platformsAndroidDirPath: string,
7+
pluginName: string,
8+
aarOutputDir: string,
9+
tempPluginDirPath: string
10+
}
11+
12+
interface IAndroidPluginBuildService {
13+
buildAar(options: IBuildOptions): Promise<boolean>;
14+
migrateIncludeGradle(options: IBuildOptions): boolean;
15+
}

lib/definitions/project.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,26 @@ interface IPlatformProjectService extends NodeJS.EventEmitter {
297297
* If there are parts in the project that are inconsistent with the desired options, marks them in the changeset flags.
298298
*/
299299
checkForChanges(changeset: IProjectChangesInfo, options: IProjectChangesOptions, projectData: IProjectData): Promise<void>;
300+
301+
/**
302+
* Build native part of a nativescript plugins if necessary
303+
*/
304+
prebuildNativePlugin(buildOptions: IBuildOptions): Promise<void>;
305+
306+
/**
307+
* Traverse through the production dependencies and find plugins that need build/rebuild
308+
*/
309+
checkIfPluginsNeedBuild(projectData: IProjectData): Promise<Array<any>>;
310+
311+
/**
312+
* Get gradle options the CLI generates when building project
313+
*/
314+
getBuildOptions(configurationFilePath?: string): Array<string>;
315+
316+
/**
317+
* Get gradle options the CLI generates when building project
318+
*/
319+
executeCommand(projectRoot: string, args: any, childProcessOpts?: any, spawnFromEventOptions?: ISpawnFromEventOptions): Promise<ISpawnResult>;
300320
}
301321

302322
interface IAndroidProjectPropertiesManager {

lib/project-data.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ export class ProjectData implements IProjectData {
152152
}
153153

154154
private getNsConfigContent(projectDir: string): string {
155+
if (!projectDir) {
156+
return null;
157+
}
158+
155159
const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME);
156160

157161
if (!this.$fs.exists(configNSFilePath)) {

0 commit comments

Comments
 (0)