@expo-harmony/cli 55.0.26-harmony.7 → 55.0.26-harmony.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -46
- package/build/bin/expo-harmony.js +1 -1
- package/build/buildHap/build.d.ts +3 -10
- package/build/buildHap/build.js +11 -69
- package/build/buildHap/index.d.ts +2 -0
- package/build/buildHap/index.js +19 -0
- package/build/cli.d.ts +3 -3
- package/build/cli.js +21 -187
- package/build/command.d.ts +9 -0
- package/build/command.js +20 -0
- package/build/doctor/doctor.d.ts +1 -1
- package/build/doctor/doctor.js +64 -56
- package/build/doctor/index.d.ts +2 -0
- package/build/doctor/index.js +16 -0
- package/build/exportEmbed/export.d.ts +2 -2
- package/build/exportEmbed/export.js +53 -49
- package/build/exportEmbed/index.d.ts +2 -0
- package/build/exportEmbed/index.js +19 -0
- package/build/file.d.ts +2 -1
- package/build/file.js +18 -8
- package/build/help.d.ts +1 -0
- package/build/help.js +36 -0
- package/build/index.d.ts +5 -3
- package/build/index.js +6 -5
- package/build/internal/prebuild.d.ts +3 -0
- package/build/internal/prebuild.js +9 -0
- package/build/log.d.ts +4 -0
- package/build/log.js +6 -0
- package/build/modules/index.d.ts +2 -0
- package/build/modules/index.js +16 -0
- package/build/native/bare.d.ts +4 -0
- package/build/native/bare.js +130 -0
- package/build/native/build.d.ts +15 -0
- package/build/native/build.js +67 -0
- package/build/{run → native}/cache.d.ts +2 -2
- package/build/{run → native}/cache.js +8 -8
- package/build/native/hvigor.d.ts +2 -0
- package/build/native/hvigor.js +77 -0
- package/build/native/install.d.ts +5 -0
- package/build/native/install.js +13 -0
- package/build/native/prepareProject.d.ts +11 -0
- package/build/native/prepareProject.js +68 -0
- package/build/native/project.d.ts +8 -0
- package/build/native/project.js +58 -0
- package/build/native/toolchain.d.ts +16 -0
- package/build/{tools.js → native/toolchain.js} +1 -57
- package/build/native/types.d.ts +47 -0
- package/build/native/types.js +2 -0
- package/build/prebuild/check.d.ts +7 -3
- package/build/prebuild/check.js +26 -20
- package/build/prebuild/clean.js +5 -5
- package/build/prebuild/index.d.ts +2 -0
- package/build/prebuild/index.js +51 -0
- package/build/prebuild/prebuild.js +11 -3
- package/build/prebuild/template.js +2 -2
- package/build/process.d.ts +11 -1
- package/build/process.js +16 -0
- package/build/profile.d.ts +1 -0
- package/build/profile.js +12 -0
- package/build/projectLock.js +7 -2
- package/build/run/devices.d.ts +1 -1
- package/build/run/devices.js +15 -10
- package/build/run/emulators.d.ts +1 -1
- package/build/run/emulators.js +2 -5
- package/build/run/index.d.ts +2 -0
- package/build/run/index.js +25 -0
- package/build/run/metro.js +1 -1
- package/build/run/run.d.ts +4 -10
- package/build/run/run.js +45 -90
- package/build/start/index.d.ts +2 -0
- package/build/start/index.js +33 -0
- package/package.json +14 -4
- package/src/bin/expo-harmony.ts +2 -2
- package/src/buildHap/build.ts +13 -105
- package/src/buildHap/index.ts +19 -0
- package/src/cli.ts +24 -227
- package/src/command.ts +24 -0
- package/src/doctor/doctor.ts +63 -61
- package/src/doctor/index.ts +16 -0
- package/src/exportEmbed/export.ts +64 -55
- package/src/exportEmbed/index.ts +17 -0
- package/src/file.ts +20 -11
- package/src/help.ts +33 -0
- package/src/index.ts +5 -3
- package/src/internal/prebuild.ts +3 -0
- package/src/log.ts +5 -0
- package/src/modules/index.ts +16 -0
- package/src/native/bare.ts +145 -0
- package/src/native/build.ts +81 -0
- package/src/{run → native}/cache.ts +10 -9
- package/src/native/hvigor.ts +81 -0
- package/src/native/install.ts +17 -0
- package/src/native/prepareProject.ts +99 -0
- package/src/native/project.ts +88 -0
- package/src/{tools.ts → native/toolchain.ts} +11 -118
- package/src/native/types.ts +44 -0
- package/src/prebuild/check.ts +30 -19
- package/src/prebuild/clean.ts +3 -3
- package/src/prebuild/index.ts +56 -0
- package/src/prebuild/prebuild.ts +11 -1
- package/src/prebuild/template.ts +2 -2
- package/src/process.ts +38 -1
- package/src/profile.ts +13 -0
- package/src/projectLock.ts +9 -1
- package/src/run/devices.ts +16 -11
- package/src/run/emulators.ts +4 -6
- package/src/run/index.ts +25 -0
- package/src/run/metro.ts +1 -1
- package/src/run/run.ts +56 -129
- package/src/start/index.ts +31 -0
- package/build/buildHap/common.d.ts +0 -24
- package/build/buildHap/common.js +0 -92
- package/build/run/install.d.ts +0 -7
- package/build/run/install.js +0 -26
- package/build/tools.d.ts +0 -39
- package/src/buildHap/common.ts +0 -145
- package/src/run/install.ts +0 -41
package/build/run/run.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type MetroSession } from './metro';
|
|
2
|
+
import { type NativeBuildResult } from '../native/build';
|
|
2
3
|
export interface HarmonyRunOptions {
|
|
3
4
|
appId?: string;
|
|
4
5
|
device?: string;
|
|
@@ -10,18 +11,12 @@ export interface HarmonyRunOptions {
|
|
|
10
11
|
sync?: boolean;
|
|
11
12
|
variant?: 'debug' | 'release';
|
|
12
13
|
}
|
|
13
|
-
export interface HarmonyRunResult {
|
|
14
|
+
export interface HarmonyRunResult extends NativeBuildResult {
|
|
14
15
|
bundleName: string;
|
|
15
16
|
device: {
|
|
16
17
|
id: string;
|
|
17
18
|
transport: string;
|
|
18
19
|
};
|
|
19
|
-
export: null | {
|
|
20
|
-
assetCount: number;
|
|
21
|
-
bundleSha256: string;
|
|
22
|
-
sourceMapSha256: string;
|
|
23
|
-
};
|
|
24
|
-
hapPath: string;
|
|
25
20
|
installed: boolean;
|
|
26
21
|
launched: true;
|
|
27
22
|
metro: {
|
|
@@ -34,7 +29,6 @@ export interface HarmonyRunResult {
|
|
|
34
29
|
variant: 'debug' | 'release';
|
|
35
30
|
}
|
|
36
31
|
interface HarmonyRunSessionOptions extends HarmonyRunOptions {
|
|
37
|
-
/** Give a CLI-started Metro process ownership of the current terminal. */
|
|
38
32
|
interactiveBundler?: boolean;
|
|
39
33
|
}
|
|
40
34
|
interface HarmonyRunSession {
|
|
@@ -46,6 +40,6 @@ interface HarmonyRunSession {
|
|
|
46
40
|
};
|
|
47
41
|
result: HarmonyRunResult;
|
|
48
42
|
}
|
|
49
|
-
declare function runHarmonySessionAsync(
|
|
50
|
-
declare function runHarmonyAsync(
|
|
43
|
+
declare function runHarmonySessionAsync(root: string, options?: HarmonyRunSessionOptions): Promise<HarmonyRunSession>;
|
|
44
|
+
declare function runHarmonyAsync(root: string, options?: HarmonyRunOptions): Promise<HarmonyRunResult>;
|
|
51
45
|
export { runHarmonyAsync, runHarmonySessionAsync };
|
package/build/run/run.js
CHANGED
|
@@ -8,14 +8,13 @@ exports.runHarmonySessionAsync = runHarmonySessionAsync;
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const devices_1 = require("./devices");
|
|
10
10
|
const errors_1 = require("../errors");
|
|
11
|
-
const
|
|
12
|
-
const tools_1 = require("../tools");
|
|
13
|
-
const install_1 = require("./install");
|
|
11
|
+
const toolchain_1 = require("../native/toolchain");
|
|
14
12
|
const metro_1 = require("./metro");
|
|
15
|
-
const cache_1 = require("./cache");
|
|
16
|
-
const path_1 = require("../path");
|
|
17
13
|
const projectLock_1 = require("../projectLock");
|
|
18
|
-
const
|
|
14
|
+
const build_1 = require("../native/build");
|
|
15
|
+
const prepareProject_1 = require("../native/prepareProject");
|
|
16
|
+
const log_1 = require("../log");
|
|
17
|
+
const profile_1 = require("../profile");
|
|
19
18
|
const BundleName = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*){2,}$/u;
|
|
20
19
|
function resolveRunIdentity(plan, options) {
|
|
21
20
|
if (options.appId && !BundleName.test(options.appId)) {
|
|
@@ -29,8 +28,8 @@ function resolveRunIdentity(plan, options) {
|
|
|
29
28
|
bundleName: options.appId || plan.bundleName,
|
|
30
29
|
};
|
|
31
30
|
}
|
|
32
|
-
async function runHarmonyUnlockedAsync(
|
|
33
|
-
const
|
|
31
|
+
async function runHarmonyUnlockedAsync(root, options = {}) {
|
|
32
|
+
const settings = {
|
|
34
33
|
appId: options.appId,
|
|
35
34
|
device: options.device,
|
|
36
35
|
interactiveBundler: Boolean(options.interactiveBundler),
|
|
@@ -43,109 +42,61 @@ async function runHarmonyUnlockedAsync(projectRoot, options = {}) {
|
|
|
43
42
|
variant: options.variant || 'debug',
|
|
44
43
|
};
|
|
45
44
|
const steps = {};
|
|
46
|
-
await (0,
|
|
47
|
-
...
|
|
48
|
-
|
|
45
|
+
const plan = await (0, prepareProject_1.prepareNativeProjectAsync)(root, {
|
|
46
|
+
...settings,
|
|
47
|
+
check: false,
|
|
49
48
|
}, steps);
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
(0,
|
|
54
|
-
const device = await (0, common_1.timed)(steps, 'device', () => (0, devices_1.selectDeviceAsync)(toolchain.hdc, normalizedOptions.device, {
|
|
49
|
+
const identity = resolveRunIdentity(plan, settings);
|
|
50
|
+
const tools = (0, toolchain_1.resolveHarmonyToolchain)();
|
|
51
|
+
(0, log_1.progress)(settings, 'Selecting a Harmony device or emulator');
|
|
52
|
+
const device = await (0, profile_1.timedAsync)(steps, 'device', () => (0, devices_1.selectDeviceAsync)(tools.hdc, settings.device, {
|
|
55
53
|
cwd: plan.harmonyRoot,
|
|
56
|
-
emulator: (0,
|
|
57
|
-
emulatorLogFile: node_path_1.default.join(
|
|
58
|
-
onProgress: message => (0,
|
|
54
|
+
emulator: (0, toolchain_1.resolveHarmonyEmulator)(tools),
|
|
55
|
+
emulatorLogFile: node_path_1.default.join(root, '.expo', 'harmony', 'emulator.log'),
|
|
56
|
+
onProgress: message => (0, log_1.progress)(settings, message),
|
|
59
57
|
}));
|
|
60
|
-
|
|
61
|
-
if (normalizedOptions.variant === 'release') {
|
|
62
|
-
(0, common_1.progress)(normalizedOptions, 'Exporting the release Hermes bundle');
|
|
63
|
-
exportManifest = await (0, common_1.timed)(steps, 'export', () => (0, export_1.exportEmbedAsync)(projectRoot, { resetCache: normalizedOptions.resetCache, skipDoctor: true }));
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
steps.export = 0;
|
|
67
|
-
}
|
|
68
|
-
(0, common_1.progress)(normalizedOptions, 'Installing Harmony project dependencies');
|
|
69
|
-
await (0, common_1.timed)(steps, 'ohpm', () => (0, install_1.installHarmonyDependenciesAsync)(plan, toolchain));
|
|
58
|
+
const built = await (0, build_1.buildNativeAsync)(root, plan, tools, settings, steps);
|
|
70
59
|
let metro = {
|
|
71
60
|
owner: 'disabled',
|
|
72
|
-
port:
|
|
61
|
+
port: settings.port,
|
|
73
62
|
stop: async () => { },
|
|
74
63
|
waitAsync: async () => { },
|
|
75
64
|
};
|
|
76
65
|
try {
|
|
77
|
-
(
|
|
78
|
-
|
|
79
|
-
if (nativeBuildCache.changed) {
|
|
80
|
-
(0, common_1.progress)(normalizedOptions, 'Invalidated stale Harmony native build objects');
|
|
81
|
-
}
|
|
82
|
-
(0, common_1.progress)(normalizedOptions, `Building the ${normalizedOptions.variant} HAP`);
|
|
83
|
-
const buildEnv = {
|
|
84
|
-
...process.env,
|
|
85
|
-
EXPO_HARMONY_NODE: process.env.EXPO_HARMONY_NODE || process.execPath,
|
|
86
|
-
EXPO_METRO_TARGET: 'harmony',
|
|
87
|
-
HERMES_V1_ENABLED: 'true',
|
|
88
|
-
...(normalizedOptions.variant === 'release' ? { EXPO_HARMONY_BUNDLE_PREBUILT: '1' } : {}),
|
|
89
|
-
...(toolchain.sdkHome && !process.env.DEVECO_SDK_HOME
|
|
90
|
-
? { DEVECO_SDK_HOME: toolchain.sdkHome }
|
|
91
|
-
: {}),
|
|
92
|
-
};
|
|
93
|
-
await (0, common_1.timed)(steps, 'build', () => (0, common_1.runCheckedAsync)(toolchain.hvigor.command, [
|
|
94
|
-
...toolchain.hvigor.args,
|
|
95
|
-
...plan.hvigorArgs,
|
|
96
|
-
], {
|
|
97
|
-
code: 'ERR_HARMONY_BUILD_FAILED',
|
|
98
|
-
cwd: plan.harmonyRoot,
|
|
99
|
-
env: buildEnv,
|
|
100
|
-
message: 'Hvigor build',
|
|
101
|
-
operation: 'hvigor-build',
|
|
102
|
-
timeoutMs: 15 * 60_000,
|
|
103
|
-
}));
|
|
104
|
-
if (!(0, common_1.isNonEmptyRegularFile)(plan.expectedHap)) {
|
|
105
|
-
throw new errors_1.HarmonyCliError('ERR_HARMONY_HAP_MISSING', 'Hvigor completed without producing the expected non-empty regular HAP.', { operation: 'verify-hap' });
|
|
106
|
-
}
|
|
107
|
-
await (0, common_1.timed)(steps, 'nativeCacheCommit', () => (0, cache_1.commitHarmonyNativeBuildCacheAsync)(nativeBuildCache));
|
|
108
|
-
if (normalizedOptions.variant === 'debug') {
|
|
109
|
-
(0, common_1.progress)(normalizedOptions, normalizedOptions.noBundler
|
|
66
|
+
if (settings.variant === 'debug') {
|
|
67
|
+
(0, log_1.progress)(settings, settings.noBundler
|
|
110
68
|
? 'Connecting to the existing Expo Metro server'
|
|
111
69
|
: 'Starting Expo Metro');
|
|
112
|
-
metro = await (0,
|
|
113
|
-
? (0, metro_1.requireExistingMetroAsync)(
|
|
114
|
-
: (0, metro_1.startExpoMetroAsync)(
|
|
115
|
-
interactive:
|
|
116
|
-
port:
|
|
117
|
-
resetCache:
|
|
70
|
+
metro = await (0, profile_1.timedAsync)(steps, 'metro', () => settings.noBundler
|
|
71
|
+
? (0, metro_1.requireExistingMetroAsync)(settings.port)
|
|
72
|
+
: (0, metro_1.startExpoMetroAsync)(root, {
|
|
73
|
+
interactive: settings.interactiveBundler,
|
|
74
|
+
port: settings.port,
|
|
75
|
+
resetCache: settings.resetCache,
|
|
118
76
|
}));
|
|
119
|
-
await (0,
|
|
77
|
+
await (0, profile_1.timedAsync)(steps, 'metroPort', () => (0, devices_1.configureMetroPortAsync)(tools.hdc, device, settings.port, { cwd: plan.harmonyRoot }));
|
|
120
78
|
}
|
|
121
79
|
else {
|
|
122
80
|
steps.metro = 0;
|
|
123
81
|
steps.metroPort = 0;
|
|
124
82
|
}
|
|
125
|
-
if (
|
|
83
|
+
if (settings.noInstall) {
|
|
126
84
|
steps.install = 0;
|
|
127
85
|
}
|
|
128
86
|
else {
|
|
129
|
-
(0,
|
|
130
|
-
await (0,
|
|
87
|
+
(0, log_1.progress)(settings, `Installing the HAP on ${device.id}`);
|
|
88
|
+
await (0, profile_1.timedAsync)(steps, 'install', () => (0, devices_1.installHapAsync)(tools.hdc, device, plan.expectedHap, { cwd: plan.harmonyRoot }));
|
|
131
89
|
}
|
|
132
|
-
(0,
|
|
133
|
-
await (0,
|
|
90
|
+
(0, log_1.progress)(settings, `Launching ${identity.bundleName}`);
|
|
91
|
+
await (0, profile_1.timedAsync)(steps, 'launch', () => (0, devices_1.launchAppAsync)(tools.hdc, device, identity.bundleName, identity.abilityName, { cwd: plan.harmonyRoot }));
|
|
134
92
|
const result = {
|
|
135
93
|
bundleName: identity.bundleName,
|
|
136
94
|
device: {
|
|
137
95
|
id: device.id,
|
|
138
96
|
transport: device.transport,
|
|
139
97
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
assetCount: exportManifest.assets.length,
|
|
143
|
-
bundleSha256: exportManifest.bundle.sha256,
|
|
144
|
-
sourceMapSha256: exportManifest.sourceMap.sha256,
|
|
145
|
-
}
|
|
146
|
-
: null,
|
|
147
|
-
hapPath: (0, path_1.toPosixPath)(node_path_1.default.relative(projectRoot, plan.expectedHap)),
|
|
148
|
-
installed: !normalizedOptions.noInstall,
|
|
98
|
+
...built,
|
|
99
|
+
installed: !settings.noInstall,
|
|
149
100
|
launched: true,
|
|
150
101
|
metro: {
|
|
151
102
|
owner: metro.owner,
|
|
@@ -154,20 +105,24 @@ async function runHarmonyUnlockedAsync(projectRoot, options = {}) {
|
|
|
154
105
|
ok: true,
|
|
155
106
|
schemaVersion: 1,
|
|
156
107
|
steps,
|
|
157
|
-
variant:
|
|
108
|
+
variant: settings.variant,
|
|
158
109
|
};
|
|
159
110
|
return { metro, result };
|
|
160
111
|
}
|
|
161
112
|
catch (error) {
|
|
162
113
|
await metro.stop();
|
|
163
|
-
throw error
|
|
114
|
+
throw new errors_1.HarmonyCliError(error?.code || 'ERR_HARMONY_UNKNOWN', error?.message || 'Harmony run failed.', {
|
|
115
|
+
cause: error,
|
|
116
|
+
exitCode: error?.exitCode,
|
|
117
|
+
operation: error?.operation,
|
|
118
|
+
});
|
|
164
119
|
}
|
|
165
120
|
}
|
|
166
|
-
async function runHarmonySessionAsync(
|
|
167
|
-
return (0, projectLock_1.withHarmonyProjectLockAsync)(
|
|
121
|
+
async function runHarmonySessionAsync(root, options = {}) {
|
|
122
|
+
return (0, projectLock_1.withHarmonyProjectLockAsync)(root, 'run', () => runHarmonyUnlockedAsync(root, options));
|
|
168
123
|
}
|
|
169
|
-
async function runHarmonyAsync(
|
|
170
|
-
const session = await runHarmonySessionAsync(
|
|
124
|
+
async function runHarmonyAsync(root, options = {}) {
|
|
125
|
+
const session = await runHarmonySessionAsync(root, options);
|
|
171
126
|
try {
|
|
172
127
|
return session.result;
|
|
173
128
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const options_1 = require("./options");
|
|
6
|
+
const command = async (argv, io) => {
|
|
7
|
+
const args = (0, command_1.parseCommandArgs)(options_1.parseStartArgs, argv, io);
|
|
8
|
+
if (!args)
|
|
9
|
+
return 0;
|
|
10
|
+
const { projectRoot: root, options } = args;
|
|
11
|
+
const { startExpoMetroAsync } = await import('../run/metro.js');
|
|
12
|
+
const metro = await startExpoMetroAsync(root, {
|
|
13
|
+
...options,
|
|
14
|
+
interactive: true,
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
if (metro.owner === 'existing') {
|
|
18
|
+
io.log(`Expo Metro is already running on port ${metro.port}.`);
|
|
19
|
+
if (options.resetCache) {
|
|
20
|
+
io.warn('Stop the existing Metro server and run this command again to reset its cache.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
io.log('\n› Logs for your project will appear below. Press Ctrl+C to exit.');
|
|
25
|
+
await metro.waitAsync();
|
|
26
|
+
}
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await metro.stop();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.command = command;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo-harmony/cli",
|
|
3
|
-
"version": "55.0.26-harmony.
|
|
3
|
+
"version": "55.0.26-harmony.9",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"react-native",
|
|
6
6
|
"expo",
|
|
@@ -30,15 +30,25 @@
|
|
|
30
30
|
"require": "./build/index.js",
|
|
31
31
|
"default": "./build/index.js"
|
|
32
32
|
},
|
|
33
|
-
"./bin/expo-harmony": "./build/bin/expo-harmony.js"
|
|
33
|
+
"./bin/expo-harmony": "./build/bin/expo-harmony.js",
|
|
34
|
+
"./native-build": {
|
|
35
|
+
"types": "./build/native/hvigor.d.ts",
|
|
36
|
+
"require": "./build/native/hvigor.js",
|
|
37
|
+
"default": "./build/native/hvigor.js"
|
|
38
|
+
},
|
|
39
|
+
"./internal/prebuild": {
|
|
40
|
+
"types": "./build/internal/prebuild.d.ts",
|
|
41
|
+
"require": "./build/internal/prebuild.js",
|
|
42
|
+
"default": "./build/internal/prebuild.js"
|
|
43
|
+
}
|
|
34
44
|
},
|
|
35
45
|
"bin": {
|
|
36
46
|
"expo-harmony": "build/bin/expo-harmony.js"
|
|
37
47
|
},
|
|
38
48
|
"dependencies": {
|
|
39
|
-
"@expo-harmony/config-plugins": "55.0.10-harmony.
|
|
49
|
+
"@expo-harmony/config-plugins": "55.0.10-harmony.3",
|
|
40
50
|
"@expo-harmony/expo-modules-autolinking": "55.0.25-harmony.3",
|
|
41
|
-
"@expo-harmony/prebuild-config": "55.0.0-harmony.
|
|
51
|
+
"@expo-harmony/prebuild-config": "55.0.0-harmony.7",
|
|
42
52
|
"@expo/config": "55.0.17",
|
|
43
53
|
"cross-spawn": "^7.0.6",
|
|
44
54
|
"json5": "2.2.3"
|
package/src/bin/expo-harmony.ts
CHANGED
package/src/buildHap/build.ts
CHANGED
|
@@ -1,39 +1,16 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
|
|
3
|
-
import { HarmonyCliError } from '../errors';
|
|
4
|
-
import { exportEmbedAsync } from '../exportEmbed/export';
|
|
5
|
-
import type { HarmonyExportManifest } from '../exportEmbed/manifest';
|
|
6
|
-
import { toPosixPath } from '../path';
|
|
7
1
|
import { withHarmonyProjectLockAsync } from '../projectLock';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from '../run/cache';
|
|
12
|
-
import { installHarmonyDependenciesAsync } from '../run/install';
|
|
13
|
-
import {
|
|
14
|
-
resolveHarmonyBuildPlanAsync,
|
|
15
|
-
resolveHarmonyToolchain,
|
|
16
|
-
} from '../tools';
|
|
17
|
-
import {
|
|
18
|
-
ensureGeneratedProjectAsync,
|
|
19
|
-
isNonEmptyRegularFile,
|
|
20
|
-
progress,
|
|
21
|
-
runCheckedAsync,
|
|
22
|
-
timed,
|
|
23
|
-
} from './common';
|
|
2
|
+
import { buildNativeAsync, type NativeBuildResult } from '../native/build';
|
|
3
|
+
import { prepareNativeProjectAsync } from '../native/prepareProject';
|
|
4
|
+
import { resolveHarmonyToolchain } from '../native/toolchain';
|
|
24
5
|
|
|
25
6
|
export interface HarmonyBuildOptions {
|
|
26
7
|
io?: Pick<Console, 'error' | 'log' | 'warn'>;
|
|
27
|
-
/** @internal For release verification after a successful isolated prebuild check. */
|
|
28
|
-
skipGeneratedProjectCheck?: boolean;
|
|
29
8
|
sync?: boolean;
|
|
30
9
|
variant?: 'debug' | 'release';
|
|
31
10
|
}
|
|
32
11
|
|
|
33
|
-
export interface HarmonyBuildResult {
|
|
12
|
+
export interface HarmonyBuildResult extends NativeBuildResult {
|
|
34
13
|
bundleName: string;
|
|
35
|
-
export: null | { assetCount: number; bundleSha256: string; sourceMapSha256: string };
|
|
36
|
-
hapPath: string;
|
|
37
14
|
headless: true;
|
|
38
15
|
installed: false;
|
|
39
16
|
launched: false;
|
|
@@ -48,13 +25,12 @@ type NormalizedBuildOptions = Required<HarmonyBuildOptions> & {
|
|
|
48
25
|
};
|
|
49
26
|
|
|
50
27
|
async function buildHarmonyUnlockedAsync(
|
|
51
|
-
|
|
28
|
+
root: string,
|
|
52
29
|
options: HarmonyBuildOptions = {}
|
|
53
30
|
): Promise<HarmonyBuildResult> {
|
|
54
|
-
const
|
|
31
|
+
const settings: NormalizedBuildOptions = {
|
|
55
32
|
io: options.io || console,
|
|
56
33
|
requireDeviceTools: false,
|
|
57
|
-
skipGeneratedProjectCheck: Boolean(options.skipGeneratedProjectCheck),
|
|
58
34
|
sync: Boolean(options.sync),
|
|
59
35
|
variant: options.variant || 'debug',
|
|
60
36
|
};
|
|
@@ -66,98 +42,30 @@ async function buildHarmonyUnlockedAsync(
|
|
|
66
42
|
metroPort: 0,
|
|
67
43
|
};
|
|
68
44
|
|
|
69
|
-
await
|
|
70
|
-
|
|
71
|
-
const plan = await timed(steps, 'buildPlan', () => resolveHarmonyBuildPlanAsync(
|
|
72
|
-
projectRoot,
|
|
73
|
-
{ buildMode: normalizedOptions.variant }
|
|
74
|
-
));
|
|
75
|
-
const toolchain = resolveHarmonyToolchain();
|
|
76
|
-
|
|
77
|
-
let exportManifest: HarmonyExportManifest | null = null;
|
|
78
|
-
if (normalizedOptions.variant === 'release') {
|
|
79
|
-
progress(normalizedOptions, 'Exporting the release Hermes bundle');
|
|
80
|
-
exportManifest = await timed(steps, 'export', () => exportEmbedAsync(
|
|
81
|
-
projectRoot,
|
|
82
|
-
{ skipDoctor: true }
|
|
83
|
-
));
|
|
84
|
-
} else {
|
|
85
|
-
steps.export = 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
progress(normalizedOptions, 'Installing Harmony project dependencies');
|
|
89
|
-
await timed(steps, 'ohpm', () => installHarmonyDependenciesAsync(plan, toolchain));
|
|
90
|
-
|
|
91
|
-
progress(normalizedOptions, 'Checking Harmony native dependency cache');
|
|
92
|
-
const nativeBuildCache = await timed(steps, 'nativeCache', () => (
|
|
93
|
-
prepareHarmonyNativeBuildCacheAsync(projectRoot, plan)
|
|
94
|
-
));
|
|
95
|
-
|
|
96
|
-
if (nativeBuildCache.changed) {
|
|
97
|
-
progress(normalizedOptions, 'Invalidated stale Harmony native build objects');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
progress(normalizedOptions, `Building the ${normalizedOptions.variant} HAP without a device`);
|
|
101
|
-
const buildEnv = {
|
|
102
|
-
...process.env,
|
|
103
|
-
EXPO_HARMONY_NODE: process.env.EXPO_HARMONY_NODE || process.execPath,
|
|
104
|
-
EXPO_METRO_TARGET: 'harmony',
|
|
105
|
-
HERMES_V1_ENABLED: 'true',
|
|
106
|
-
...(normalizedOptions.variant === 'release' ? { EXPO_HARMONY_BUNDLE_PREBUILT: '1' } : {}),
|
|
107
|
-
...(toolchain.sdkHome && !process.env.DEVECO_SDK_HOME
|
|
108
|
-
? { DEVECO_SDK_HOME: toolchain.sdkHome }
|
|
109
|
-
: {}),
|
|
110
|
-
};
|
|
111
|
-
await timed(steps, 'build', () => runCheckedAsync(toolchain.hvigor.command, [
|
|
112
|
-
...toolchain.hvigor.args,
|
|
113
|
-
...plan.hvigorArgs,
|
|
114
|
-
], {
|
|
115
|
-
code: 'ERR_HARMONY_BUILD_FAILED',
|
|
116
|
-
cwd: plan.harmonyRoot,
|
|
117
|
-
env: buildEnv,
|
|
118
|
-
message: 'Hvigor build',
|
|
119
|
-
operation: 'hvigor-build',
|
|
120
|
-
timeoutMs: 15 * 60_000,
|
|
121
|
-
}));
|
|
122
|
-
|
|
123
|
-
if (!isNonEmptyRegularFile(plan.expectedHap)) {
|
|
124
|
-
throw new HarmonyCliError(
|
|
125
|
-
'ERR_HARMONY_HAP_MISSING',
|
|
126
|
-
'Hvigor completed without producing the expected non-empty regular HAP.',
|
|
127
|
-
{ operation: 'verify-hap' }
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
await timed(steps, 'nativeCacheCommit', () => commitHarmonyNativeBuildCacheAsync(nativeBuildCache));
|
|
45
|
+
const plan = await prepareNativeProjectAsync(root, settings, steps);
|
|
46
|
+
const built = await buildNativeAsync(root, plan, resolveHarmonyToolchain(), settings, steps);
|
|
132
47
|
|
|
133
48
|
return {
|
|
134
49
|
bundleName: plan.bundleName,
|
|
135
|
-
|
|
136
|
-
? {
|
|
137
|
-
assetCount: exportManifest.assets.length,
|
|
138
|
-
bundleSha256: exportManifest.bundle.sha256,
|
|
139
|
-
sourceMapSha256: exportManifest.sourceMap.sha256,
|
|
140
|
-
}
|
|
141
|
-
: null,
|
|
142
|
-
hapPath: toPosixPath(path.relative(projectRoot, plan.expectedHap)),
|
|
50
|
+
...built,
|
|
143
51
|
headless: true,
|
|
144
52
|
installed: false,
|
|
145
53
|
launched: false,
|
|
146
54
|
ok: true,
|
|
147
55
|
schemaVersion: 1,
|
|
148
56
|
steps,
|
|
149
|
-
variant:
|
|
57
|
+
variant: settings.variant,
|
|
150
58
|
};
|
|
151
59
|
}
|
|
152
60
|
|
|
153
61
|
async function buildHarmonyAsync(
|
|
154
|
-
|
|
62
|
+
root: string,
|
|
155
63
|
options: HarmonyBuildOptions = {}
|
|
156
64
|
): Promise<HarmonyBuildResult> {
|
|
157
65
|
return withHarmonyProjectLockAsync(
|
|
158
|
-
|
|
66
|
+
root,
|
|
159
67
|
'build',
|
|
160
|
-
() => buildHarmonyUnlockedAsync(
|
|
68
|
+
() => buildHarmonyUnlockedAsync(root, options)
|
|
161
69
|
);
|
|
162
70
|
}
|
|
163
71
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { parseCommandArgs, type Command } from '../command';
|
|
2
|
+
import { parseBuildArgs } from './options';
|
|
3
|
+
|
|
4
|
+
export const command: Command = async (argv, io) => {
|
|
5
|
+
const args = parseCommandArgs(parseBuildArgs, argv, io);
|
|
6
|
+
if (!args) return 0;
|
|
7
|
+
|
|
8
|
+
const { projectRoot: root, options } = args;
|
|
9
|
+
const { buildHarmonyAsync } = await import('./build.js');
|
|
10
|
+
|
|
11
|
+
const result = await buildHarmonyAsync(root, {
|
|
12
|
+
...options,
|
|
13
|
+
io,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
io.log(`Built ${result.variant} HAP at ${result.hapPath}; no device actions were performed.`);
|
|
17
|
+
|
|
18
|
+
return 0;
|
|
19
|
+
};
|