Skip to content

Commit 8e0647c

Browse files
Fix Android builds when gradle args and project dir have spaces (#2648)
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 1edddff commit 8e0647c

File tree

1 file changed

+20
-20
lines changed

1 file changed

+20
-20
lines changed

lib/services/android-project-service.ts

+20-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,13 @@ 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+
return this.executeGradleCommand(projectRoot, ["--stop", "--quiet"]);
426419
}
427420

428421
public async cleanProject(projectRoot: string, projectData: IProjectData): Promise<void> {
429422
const buildOptions = this.getBuildOptions({ release: false }, projectData);
430423
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 });
424+
await this.executeGradleCommand(projectRoot, buildOptions);
438425
}
439426

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

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

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

0 commit comments

Comments
 (0)