Skip to content

Commit 9dee3af

Browse files
Fix Android builds when gradle args and project dir have spaces
In case you try building application, it will fail in case the following conditions are applied: * build on Windows * build for Android * build in release * path to project dir has spaces * path to certificate (keystore) has spaces OR the certificate(keystore) name itself has spaces OR the password has spaces The problem is in Node.js's `child_process` when `spawn` is used - on Windows it has issues when both the command (in our case this is the FULL PATH to gradlew.bat executable in platforms dir of the project) and ANY of the arguments passed to `child_process's spawn` have spaces. As we are also setting the current working directory of the spawned process to be the path to `<project dir>/platforms/android`, change the `command` passed to `spawn` to be just `gradlew`. This way we'll never have spaces in the command and we'll not hit this issue.
1 parent ddd8328 commit 9dee3af

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

lib/services/android-project-service.ts

+21-20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as projectServiceBaseLib from "./platform-project-service-base";
66
import { DeviceAndroidDebugBridge } from "../common/mobile/android/device-android-debug-bridge";
77
import { EOL } from "os";
88
import { Configurations } from "../common/constants";
9+
import { SpawnOptions } from "child_process";
910

1011
export class AndroidProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService {
1112
private static VALUES_DIRNAME = "values";
@@ -253,18 +254,15 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
253254
buildOptions.unshift("--stacktrace");
254255
buildOptions.unshift("--debug");
255256
}
257+
256258
buildOptions.unshift("buildapk");
257-
let gradleBin = path.join(projectRoot, "gradlew");
258-
if (this.$hostInfo.isWindows) {
259-
gradleBin += ".bat"; // cmd command line parsing rules are weird. Avoid issues with quotes. See https://github.com/apache/cordova-android/blob/master/bin/templates/cordova/lib/builders/GradleBuilder.js for another approach
260-
}
261259

262260
this.$childProcess.on(constants.BUILD_OUTPUT_EVENT_NAME, (data: any) => {
263261
this.emit(constants.BUILD_OUTPUT_EVENT_NAME, data);
264262
});
265-
await this.spawn(gradleBin,
266-
buildOptions,
267-
{ stdio: buildConfig.buildOutputStdio || "inherit", cwd: this.getPlatformData(projectData).projectRoot },
263+
264+
await this.executeGradleCommand(this.getPlatformData(projectData).projectRoot, buildOptions,
265+
{ stdio: buildConfig.buildOutputStdio || "inherit" },
268266
{ emitOptions: { eventName: constants.BUILD_OUTPUT_EVENT_NAME }, throwError: true });
269267
} else {
270268
this.$errors.failWithoutHelp("Cannot complete build because this project is ANT-based." + EOL +
@@ -417,24 +415,14 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
417415
}
418416

419417
public stopServices(projectRoot: string): Promise<ISpawnResult> {
420-
let gradleBin = path.join(projectRoot, "gradlew");
421-
if (this.$hostInfo.isWindows) {
422-
gradleBin += ".bat";
423-
}
424-
425-
return this.$childProcess.spawnFromEvent(gradleBin, ["--stop", "--quiet"], "close", { stdio: "inherit", cwd: projectRoot });
418+
// TODO: Check if we have to pass compileSdk and other options here
419+
return this.executeGradleCommand(projectRoot, ["--stop", "--quiet"]);
426420
}
427421

428422
public async cleanProject(projectRoot: string, projectData: IProjectData): Promise<void> {
429423
const buildOptions = this.getBuildOptions({ release: false }, projectData);
430424
buildOptions.unshift("clean");
431-
432-
let gradleBin = path.join(projectRoot, "gradlew");
433-
if (this.$hostInfo.isWindows) {
434-
gradleBin += ".bat";
435-
}
436-
437-
await this.spawn(gradleBin, buildOptions, { stdio: "inherit", cwd: this.getPlatformData(projectData).projectRoot });
425+
await this.executeGradleCommand(projectRoot, buildOptions);
438426
}
439427

440428
public async cleanDeviceTempFolder(deviceIdentifier: string, projectData: IProjectData): Promise<void> {
@@ -504,6 +492,19 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
504492

505493
return versionInManifest;
506494
}
495+
496+
private async executeGradleCommand(projectRoot: string, gradleArgs: string[], childProcessOpts?: SpawnOptions, spawnFromEventOptions?: ISpawnFromEventOptions): Promise<ISpawnResult> {
497+
const gradleBin = this.$hostInfo.isWindows ? "gradlew.bat" : "./gradlew";
498+
499+
childProcessOpts = childProcessOpts || {};
500+
childProcessOpts.cwd = childProcessOpts.cwd || projectRoot;
501+
childProcessOpts.stdio = childProcessOpts.stdio || "inherit";
502+
503+
return await this.spawn(gradleBin,
504+
gradleArgs,
505+
childProcessOpts,
506+
spawnFromEventOptions);
507+
}
507508
}
508509

509510
$injector.register("androidProjectService", AndroidProjectService);

0 commit comments

Comments
 (0)