-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathfindOutputFile.ts
More file actions
112 lines (100 loc) · 3.7 KB
/
findOutputFile.ts
File metadata and controls
112 lines (100 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { existsSync } from 'node:fs';
import { logger, spawn } from '@rock-js/tools';
import { getAdbPath } from './adb.js';
import type { AndroidProject } from './runAndroid.js';
/**
* Gradle produces following output binaries:
* - build/outputs/apk/debug/app-debug.apk - for buildTypes.debug in install* and assemble* tasks
* - build/outputs/bundle/release/app-release.aab - for buildTypes.release in bundle* tasks
* - build/outputs/bundle/production/debug/app-production-debug.aab - for buildTypes.debug and flavors.production in bundle* tasks
* - build/outputs/apk/customBuildType/app-customBuildType.apk - for buildTypes.customBuildType in install* and assemble* tasks
*/
export async function findOutputFile(
androidProject: AndroidProject,
tasks: string[],
device?: string,
) {
const { appName, sourceDir } = androidProject;
const selectedTask = tasks.find(
(t) =>
t.startsWith('install') ||
t.startsWith('assemble') ||
t.startsWith('bundle'),
);
if (!selectedTask) {
return false;
}
// handle if selected task includes build flavour as well, eg. installProductionDebug should create ['production','debug'] array
const variantFromBuildTypeAndFlavor = selectedTask
?.replace('install', '')
?.replace('assemble', '')
?.replace('bundle', '')
.split(/(?=[A-Z])/);
const apkOrBundle = selectedTask?.includes('bundle') ? 'bundle' : 'apk';
// create path to output file, eg. `production/debug`
const variantPath = variantFromBuildTypeAndFlavor?.join('/')?.toLowerCase();
// create output file name, eg. `production-debug`
let variant = variantFromBuildTypeAndFlavor?.join('-')?.toLowerCase();
let buildDirectory = `${sourceDir}/${appName}/build/outputs/${apkOrBundle}/${variantPath}`;
if (!existsSync(buildDirectory)) {
// default "debug" nor "release" build type or flavor is not found. fallback to searching for buildTypes that might be named with pascalCase
const buildTypeVariant = variantFromBuildTypeAndFlavor;
buildTypeVariant[0] = buildTypeVariant[0]?.toLowerCase();
const variantPath = buildTypeVariant?.join('');
variant = buildTypeVariant?.join('');
buildDirectory = `${sourceDir}/${appName}/build/outputs/${apkOrBundle}/${variantPath}`;
}
const outputFile = await getInstallOutputFileName(
appName,
variant,
buildDirectory,
apkOrBundle === 'apk' ? 'apk' : 'aab',
device,
);
return outputFile ? `${buildDirectory}/${outputFile}` : undefined;
}
async function getInstallOutputFileName(
appName: string,
variant: string,
buildDirectory: string,
apkOrAab: 'apk' | 'aab',
device: string | undefined,
) {
const availableCPUs = await getAvailableCPUs(device);
// check if there is an apk file like app-armeabi-v7a-debug.apk
for (const availableCPU of availableCPUs.concat('universal')) {
const outputFile = `${appName}-${availableCPU}-${variant}.${apkOrAab}`;
if (existsSync(`${buildDirectory}/${outputFile}`)) {
return outputFile;
}
}
// check if there is a default file like app-debug.apk
const outputFile = `${appName}-${variant}.${apkOrAab}`;
if (existsSync(`${buildDirectory}/${outputFile}`)) {
return outputFile;
}
logger.debug('Could not find the output file:', {
buildDirectory,
outputFile,
appName,
variant,
apkOrAab,
});
return undefined;
}
/**
* Gets available CPUs of devices from ADB
*/
async function getAvailableCPUs(device?: string) {
const adbPath = getAdbPath();
try {
const adbArgs = ['shell', 'getprop', 'ro.product.cpu.abilist'];
if (device) {
adbArgs.unshift('-s', device);
}
const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
return output.trim().split(',');
} catch {
return [];
}
}