stim 1.17.2 → 1.19.0
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 +50 -1
- package/dist/{activity-IRvJY_ru.mjs → activity-BSw0x84R.mjs} +4 -4
- package/dist/{agent-device-usage-output-BK41vnzN.mjs → agent-device-usage-output-Bjxu_VmX.mjs} +8 -8
- package/dist/{android-B9yaNKwa.mjs → android-BXc6BmEi.mjs} +658 -404
- package/dist/{android-B_YNZy61.mjs → android-BdQC6zs1.mjs} +9 -9
- package/dist/android-BvV1gGdN.mjs +4 -0
- package/dist/{android-DE4v59Mb.mjs → android-DE5g_5gv.mjs} +2 -2
- package/dist/{android-cas-ZFpjJBL_.mjs → android-cas-C87geAg-.mjs} +5 -5
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/api-DIf_s86s.mjs +150 -0
- package/dist/api-run.d.mts +1 -0
- package/dist/api-run.mjs +145 -0
- package/dist/api.d.mts +218 -0
- package/dist/api.mjs +2 -0
- package/dist/{app-install-VPkI5WEg.mjs → app-install-CFI4ptUL.mjs} +33 -13
- package/dist/{attempt-Bk2ouQVL.mjs → attempt-DW-mQqM7.mjs} +14 -4
- package/dist/{web-Dl0KSRHf.mjs → browser-web-CDhqQxhv.mjs} +138 -176
- package/dist/{budget-DfcgFdQB.mjs → budget-Dz-kyXLv.mjs} +1391 -58
- package/dist/build-facts-B87vo-Im.d.mts +142 -0
- package/dist/{cache-manifest-DnUHBJaU.mjs → cache-manifest-DiwKSyv9.mjs} +3 -3
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{chrome-BrcVWQyD.mjs → chrome-BTUOo8p2.mjs} +1 -1
- package/dist/cli-C9Zvgbdc.mjs +68 -0
- package/dist/cli.mjs +1 -1
- package/dist/{client-SvBdgObD.mjs → client-CuUo8Nvg.mjs} +381 -49
- package/dist/collector-run.d.mts +6 -0
- package/dist/collector-run.mjs +9 -9
- package/dist/{command-output-CDAIFD-8.mjs → command-output-Bt8ygHE7.mjs} +2 -2
- package/dist/{config-D0DbpZtM.mjs → config-DC5jEtd1.mjs} +9 -5
- package/dist/{created-devices-CpvzBL25.mjs → created-devices-D0s26Hx5.mjs} +2 -2
- package/dist/{dependency-state-CLcBHH2M.mjs → dependency-state-DKaS1OM9.mjs} +2 -2
- package/dist/{detached-entry-CiTEgMR1.mjs → detached-entry-pB_IPfV4.mjs} +1 -1
- package/dist/{dev-client-B-XC4uRH.mjs → dev-client-CDY_zAmD.mjs} +2 -2
- package/dist/{device-C8IOoJPv.mjs → device-BHw0WlHl.mjs} +8 -8
- package/dist/{device-capacity-ZC4XSZ4R.mjs → device-capacity-BoN1jQkO.mjs} +25 -14
- package/dist/device-host-worker.mjs +19 -19
- package/dist/{gradle-dJpre3Yn.mjs → device-ios-B2ruohE-.mjs} +661 -107
- package/dist/{device-lease-DpoS36_u.mjs → device-lease-Cu7PtQpZ.mjs} +9 -9
- package/dist/{device-lease-run-B8YltIH_.mjs → device-lease-run-D38SnZtt.mjs} +4 -4
- package/dist/{device-pool-3o7s5lo4.mjs → device-pool-CP4rAsHx.mjs} +3 -3
- package/dist/{device-remote-hFSkpfQu.mjs → device-remote-B5GiUifk.mjs} +15 -16
- package/dist/{doctor-CFv1fCrF.mjs → doctor-PRJH94v6.mjs} +61 -34
- package/dist/doctor-watchman-wZhyTdp4.mjs +259 -0
- package/dist/{error-diagnostics-C-NMnhrk.mjs → error-diagnostics--v5HGOU0.mjs} +11 -11
- package/dist/{exec-CaErVv7t.mjs → exec-i8GDPwq9.mjs} +93 -6
- package/dist/{gc-DEmkg3Xh.mjs → gc-CyHMcKcn.mjs} +25 -471
- package/dist/{guide-CSmhMTf8.mjs → guide-dRaQJJk9.mjs} +681 -507
- package/dist/{hosted-android-E1Heoqnv.mjs → hosted-android-Bs7fytj7.mjs} +3 -3
- package/dist/{hosted-client-Bp4knSwu.mjs → hosted-client-C5G4h_OJ.mjs} +2 -2
- package/dist/{hosted-ios-BnbeYOUD.mjs → hosted-ios-Bik035eL.mjs} +1 -1
- package/dist/{hosted-logs-OcgIBvCT.mjs → hosted-logs-CI9Az9a4.mjs} +9 -9
- package/dist/{hosted-macos-DcxKjtfH.mjs → hosted-macos-DABm3ScO.mjs} +5 -5
- package/dist/{hosted-native-1Ebbig4w.mjs → hosted-native-DbV2aUVw.mjs} +13 -9
- package/dist/{idle-shutdown-IGyNV8Cr.mjs → idle-shutdown-DYiMBn34.mjs} +7 -8
- package/dist/{ios-DSfnPfse.mjs → ios-BWbHFZVz.mjs} +19 -7
- package/dist/{ios-Cr1h5gnO.mjs → ios-DCrkgXEM.mjs} +1 -1
- package/dist/ios-DYUr9LGc.mjs +8 -0
- package/dist/ios-ITYno9rO.mjs +2241 -0
- package/dist/{ios-device-pAN4t54-.mjs → ios-device-CJ_ZOGky.mjs} +3 -3
- package/dist/{ios-device-Ee7sDXfp.mjs → ios-device-CrW8aMb5.mjs} +1 -1
- package/dist/{ios-state-8L3lgum6.mjs → ios-state-By0XuLTQ.mjs} +1 -1
- package/dist/{launch-verify-lTnWZikR.mjs → launch-verify-DCveSE6d.mjs} +5 -5
- package/dist/{logs-BAaS7gS2.mjs → logs-Bao1HOMy.mjs} +13 -13
- package/dist/{macos-BIRQS90f.mjs → macos-ciyBdTY5.mjs} +194 -132
- package/dist/macos-nIOATJmR.mjs +2 -0
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +349 -47
- package/dist/manifest-CX0d1IkZ.mjs +148 -0
- package/dist/{metro-g8NqiJp-.mjs → metro-DI2AjPF_.mjs} +196 -43
- package/dist/{metro-gateway-C-ijGI2F.mjs → metro-gateway-BxpJLIwh.mjs} +4 -4
- package/dist/{metro-store-CDDZHtPl.mjs → metro-store-BAHFcJm6.mjs} +16 -2
- package/dist/{build-plan-BDsSi09V.mjs → miss-reason-CjQCOKqq.mjs} +207 -249
- package/dist/{named-ports-C8m8EQs2.mjs → named-ports-B4iWH4E-.mjs} +70 -8
- package/dist/{native-runtime-BEK171xQ.mjs → native-runtime-BGxsbfny.mjs} +6 -6
- package/dist/{ndjson-PclOIwVY.mjs → ndjson-LGZAMsqa.mjs} +8 -4
- package/dist/offload-worker.d.mts +3 -45
- package/dist/offload-worker.mjs +11 -11
- package/dist/{ownership-DyRQru0q.mjs → ownership-EB0ySdGK.mjs} +3 -3
- package/dist/{page-QF_Ke10s.mjs → page-Bv9s2KwY.mjs} +1 -1
- package/dist/placement-log-Dxe34rJm.mjs +88 -0
- package/dist/plan-placement-BVY59qa8.mjs +290 -0
- package/dist/{ports-4nYqxPWC.mjs → ports-ByPc0_97.mjs} +3 -3
- package/dist/{prebuild-D7RUMkwN.mjs → prebuild-BKJ3wJI1.mjs} +5 -5
- package/dist/preview-BbSottmO.mjs +986 -0
- package/dist/{rolldown-runtime-BsOwBuO_.mjs → process-identity-Biv3arCO.mjs} +11 -1
- package/dist/project-B5eQ1USs.mjs +612 -0
- package/dist/{pull-request-pxnDCQzn.mjs → pull-request-IHNdMnG8.mjs} +1 -1
- package/dist/pull-requests.mjs +1 -1
- package/dist/react-native-ios-BMh2i25I.mjs +2 -0
- package/dist/react-native-ios-CSpIxexZ.mjs +2083 -0
- package/dist/{recordings-BNgsD1Tr.mjs → recordings-Bv8McZN4.mjs} +1 -1
- package/dist/{reload-DcRxj3qG.mjs → reload-rAPdqeRR.mjs} +14 -15
- package/dist/{remote-cache-Ci4DQYYj.mjs → remote-cache-N3hAEaAL.mjs} +5 -5
- package/dist/{run-CkE9y0nc.mjs → run-lAkle1-c.mjs} +5 -5
- package/dist/{server-bare-BkrSxSsZ.mjs → server-bare-CkIjnegq.mjs} +5 -6
- package/dist/server-expo-DGsdUGX2.mjs +2 -0
- package/dist/{server-expo-CHTyXD0G.mjs → server-expo-n3tUi3Em.mjs} +5 -6
- package/dist/{settings-SR9OmW9h.mjs → settings-2am7TSxp.mjs} +5 -5
- package/dist/{settings-Cfd-0r2d.mjs → settings-CxgngUZk.mjs} +116 -103
- package/dist/{settings-BBpMcDbD.mjs → settings-Djl-mpjX.mjs} +1 -1
- package/dist/settings.schema.json +198 -9
- package/dist/{simslim-BWNrc3M3.mjs → simslim-D9LkJxIO.mjs} +7 -7
- package/dist/{slot-launch-DmjBmpQV.mjs → slot-launch-HV_KtPIw.mjs} +6 -6
- package/dist/{spawn-claims-D0XfSe8u.mjs → spawn-claims-Kqiifsk2.mjs} +1 -1
- package/dist/{spawn-entry-jw19m8Nl.mjs → spawn-entry-Dcb7sDUz.mjs} +1 -0
- package/dist/{stage-CzaiwFsI.mjs → stage-BgaZJVZY.mjs} +14 -3
- package/dist/{start-AlfCPRVU.mjs → start-D8NbxNBb.mjs} +1 -1
- package/dist/{start-DUz3mYdb.mjs → start-DtxthMfI.mjs} +34 -27
- package/dist/{state-PeQiJuIu.mjs → state-D2KtnALG.mjs} +4 -4
- package/dist/{state-DyaNTgfR.mjs → state-Tp4uImDS.mjs} +5 -3
- package/dist/{state-B4PQFXMW.d.mts → state-lKh8shBp.d.mts} +2 -3
- package/dist/{stats-Bq4fJOdB.mjs → stats-8EJ5ivFT.mjs} +6 -6
- package/dist/{status-DlKvVJBE.mjs → status-BEeL6IKz.mjs} +6 -4
- package/dist/{status-BA2pehwf.mjs → status-BOyp0CUl.mjs} +31 -34
- package/dist/{stim-desktop-Cnz8CPnl.mjs → stim-desktop-C65jk_q2.mjs} +1 -1
- package/dist/{stim-installations-QMEI32v1.mjs → stim-installations-DbmUjsLv.mjs} +1 -1
- package/dist/stop-D0UIpZuh.mjs +72 -0
- package/dist/{stop-zF1y04f2.mjs → stop-DRipAg-e.mjs} +2 -2
- package/dist/{stop-DQIasgKp.mjs → stop-zDlknFoz.mjs} +79 -33
- package/dist/supervisor-run.d.mts +24 -22
- package/dist/supervisor-run.mjs +21 -22
- package/dist/{support-CsJNVfOc.mjs → support-CNqYkV0y.mjs} +7 -7
- package/dist/{support-WvD__tSV.mjs → support-DsNaFg6D.mjs} +5 -5
- package/dist/swiftpm-macos-aJzPAj1t.mjs +119 -0
- package/dist/{toolchain-DNyR3NPq.mjs → toolchain-C3xSoyUl.mjs} +475 -269
- package/dist/{trigger-Bemu8ytw.mjs → trigger-CAhmG-4s.mjs} +6 -6
- package/dist/trigger-CoalsMTV.mjs +2 -0
- package/dist/{warm-progress-DF4JRvYI.mjs → warm-progress-pFLB2e6P.mjs} +135 -38
- package/dist/{status-CzS4bPO9.mjs → watchman-BL1IdOtq.mjs} +75 -7
- package/dist/web-DFpFeZu5.mjs +2 -0
- package/dist/web-DbbrPUn0.mjs +127 -0
- package/dist/web-run.mjs +10 -10
- package/dist/{workspace-state-DqcCbpE7.mjs → workspace-state-CR9X86xJ.mjs} +3 -3
- package/dist/{ownership-BMLqyBgJ.mjs → workspaces-Djb2gfi9.mjs} +661 -23
- package/dist/{worktree-Be_7NLKy.mjs → worktree-BL4M1rhB.mjs} +252 -50
- package/dist/{worktree-j3IcFAI5.mjs → worktree-DV-A0LNL.mjs} +1 -1
- package/package.json +10 -5
- package/shim/bundle-response.cjs +2 -1
- package/shim/bundle-response.d.cts +1 -1
- package/shim/expo-metro-config.cjs +1 -1
- package/dist/build-progress-D0WkjCPd.mjs +0 -1036
- package/dist/build-slots-41v_d2x9.mjs +0 -142
- package/dist/cli-CYXb29oE.mjs +0 -51
- package/dist/deps-iKw0eD4P.mjs +0 -438
- package/dist/device-ios-C2Um-XUR.mjs +0 -412
- package/dist/errors-B6W7FkxQ.mjs +0 -15
- package/dist/guide-status-Du-ZQ3FD.mjs +0 -125
- package/dist/idle-BXG__1BA.mjs +0 -176
- package/dist/in-use-CvGOUn-x.mjs +0 -130
- package/dist/ios-BJ4XUSe1.mjs +0 -3867
- package/dist/native-run-D1Q56rAD.mjs +0 -158
- package/dist/preview-B-g9d7kV.mjs +0 -318
- package/dist/process-identity-BmRm1qV0.mjs +0 -12
- package/dist/project-D47Rh0ly.mjs +0 -276
- package/dist/server-expo-CeakhI8P.mjs +0 -2
- package/dist/state-BKa8wNN5.mjs +0 -148
- package/dist/stop-BIiM49EY.mjs +0 -48
- package/dist/stop-cause-rhmGfwvt.mjs +0 -97
- package/dist/trigger-CXts6qt1.mjs +0 -2
- package/dist/watchman-APYjXSQa.mjs +0 -48
- package/dist/workspace-process-lock-2mNzOlaB.mjs +0 -58
- package/dist/workspaces-Bcib97-6.mjs +0 -306
|
@@ -1,145 +1,18 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { r as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { o as androidHome } from "./android-B_YNZy61.mjs";
|
|
10
|
-
import { t as cleanLine } from "./server-expo-CHTyXD0G.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-i8GDPwq9.mjs";
|
|
2
|
+
import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
3
|
+
import { a as formatElapsed, l as phaseLine } from "./command-output-Bt8ygHE7.mjs";
|
|
4
|
+
import { _ as workspaceDerivedData } from "./workspace-state-CR9X86xJ.mjs";
|
|
5
|
+
import { Ot as resolveOptimizations } from "./settings-CxgngUZk.mjs";
|
|
6
|
+
import { a as spawnDeclared } from "./spawn-claims-Kqiifsk2.mjs";
|
|
7
|
+
import { o as androidHome } from "./android-BdQC6zs1.mjs";
|
|
8
|
+
import { t as cleanLine } from "./server-expo-n3tUi3Em.mjs";
|
|
11
9
|
import { createRequire } from "node:module";
|
|
12
|
-
import { createHash } from "node:crypto";
|
|
13
10
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
14
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
11
|
+
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
15
12
|
import { stimBuildDigest } from "@stim-cli/core/state";
|
|
16
13
|
import { fileURLToPath } from "node:url";
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
const STATS_LOG_FILE = "ccache-stats.log";
|
|
20
|
-
const CCACHE_UNAVAILABLE = {
|
|
21
|
-
status: "unavailable",
|
|
22
|
-
hits: null,
|
|
23
|
-
misses: null,
|
|
24
|
-
hitRatePercent: null
|
|
25
|
-
};
|
|
26
|
-
const CCACHE_NOT_RUN = {
|
|
27
|
-
status: "not-run",
|
|
28
|
-
hits: null,
|
|
29
|
-
misses: null,
|
|
30
|
-
hitRatePercent: null
|
|
31
|
-
};
|
|
32
|
-
function ccacheStatsLog(root) {
|
|
33
|
-
return join(workspaceLogsDir$1(root), STATS_LOG_FILE);
|
|
34
|
-
}
|
|
35
|
-
function ccacheEnvironment({ binary, dir, workspaceRoot, statsLog }) {
|
|
36
|
-
return {
|
|
37
|
-
CMAKE_C_COMPILER_LAUNCHER: binary,
|
|
38
|
-
CMAKE_CXX_COMPILER_LAUNCHER: binary,
|
|
39
|
-
CCACHE_DIR: dir,
|
|
40
|
-
CCACHE_BASEDIR: workspaceRoot,
|
|
41
|
-
CCACHE_NOHASHDIR: "true",
|
|
42
|
-
CCACHE_SLOPPINESS,
|
|
43
|
-
CCACHE_MAXSIZE: "5G",
|
|
44
|
-
CCACHE_STATSLOG: statsLog
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function parseCcacheBinary(output) {
|
|
48
|
-
const first = String(output ?? "").split("\n")[0]?.trim();
|
|
49
|
-
if (!first || !isAbsolute(first)) return null;
|
|
50
|
-
return first;
|
|
51
|
-
}
|
|
52
|
-
const CMAKE_LAUNCHER = /CMAKE_(C|CXX)_COMPILER_LAUNCHER\b/;
|
|
53
|
-
function projectCmakeLauncher(source) {
|
|
54
|
-
if (typeof source !== "string") return null;
|
|
55
|
-
const match = CMAKE_LAUNCHER.exec(source);
|
|
56
|
-
return match ? `CMAKE_${match[1]}_COMPILER_LAUNCHER` : null;
|
|
57
|
-
}
|
|
58
|
-
const HIT_COUNTERS = /* @__PURE__ */ new Set(["direct_cache_hit", "preprocessed_cache_hit"]);
|
|
59
|
-
function parseCcacheStatsLog(text) {
|
|
60
|
-
if (typeof text !== "string") return null;
|
|
61
|
-
let hits = 0;
|
|
62
|
-
let misses = 0;
|
|
63
|
-
for (const raw of text.split("\n")) {
|
|
64
|
-
const line = raw.trim();
|
|
65
|
-
if (HIT_COUNTERS.has(line)) hits += 1;
|
|
66
|
-
else if (line === "cache_miss") misses += 1;
|
|
67
|
-
}
|
|
68
|
-
const total = hits + misses;
|
|
69
|
-
if (total === 0) return null;
|
|
70
|
-
return {
|
|
71
|
-
status: "reported",
|
|
72
|
-
hits,
|
|
73
|
-
misses,
|
|
74
|
-
hitRatePercent: Math.round(hits / total * 1e3) / 10
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
function readCcacheActivity(statsLog) {
|
|
78
|
-
let text;
|
|
79
|
-
try {
|
|
80
|
-
text = readFileSync(statsLog, "utf-8");
|
|
81
|
-
} catch {
|
|
82
|
-
return CCACHE_UNAVAILABLE;
|
|
83
|
-
}
|
|
84
|
-
return parseCcacheStatsLog(text) ?? CCACHE_UNAVAILABLE;
|
|
85
|
-
}
|
|
86
|
-
function ccacheActivityLine(activity) {
|
|
87
|
-
if (activity.status === "reported") return `${activity.hits} hits / ${activity.misses} misses (${activity.hitRatePercent}%)`;
|
|
88
|
-
if (activity.status === "not-run") return "not run; artifact cache supplied the app";
|
|
89
|
-
return "unavailable; no C++ compile went through ccache";
|
|
90
|
-
}
|
|
91
|
-
function lookupCcache() {
|
|
92
|
-
try {
|
|
93
|
-
return parseCcacheBinary(getExecutor().findExecutable("ccache"));
|
|
94
|
-
} catch {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function readOrNull(file) {
|
|
99
|
-
try {
|
|
100
|
-
return readFileSync(file, "utf-8");
|
|
101
|
-
} catch {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
function canonical(root) {
|
|
106
|
-
try {
|
|
107
|
-
return realpathSync(root);
|
|
108
|
-
} catch {
|
|
109
|
-
return root;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function resolveCcache({ root, dir = sharedCcache$1(), lookup = lookupCcache, onNote = (line) => console.error(line) }) {
|
|
113
|
-
const binary = lookup();
|
|
114
|
-
if (!binary) {
|
|
115
|
-
onNote(chalk.dim(phaseLine("cache", "ccache off (not installed; brew install ccache)")));
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
const declared = projectCmakeLauncher(readOrNull(join(root, "android", "app", "build.gradle")));
|
|
119
|
-
if (declared) {
|
|
120
|
-
onNote(chalk.dim(phaseLine("cache", `ccache off (android/app/build.gradle sets ${declared} itself)`)));
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
const statsLog = ccacheStatsLog(root);
|
|
124
|
-
register({
|
|
125
|
-
dir,
|
|
126
|
-
name: "ccache",
|
|
127
|
-
prune: "atomic",
|
|
128
|
-
note: "ccache keeps itself under CCACHE_MAXSIZE, so it is emptied whole or not at all"
|
|
129
|
-
});
|
|
130
|
-
onNote(chalk.dim(phaseLine("cache", `ccache on (${dir})`)));
|
|
131
|
-
return {
|
|
132
|
-
dir,
|
|
133
|
-
statsLog,
|
|
134
|
-
env: ccacheEnvironment({
|
|
135
|
-
binary,
|
|
136
|
-
dir,
|
|
137
|
-
workspaceRoot: canonical(root),
|
|
138
|
-
statsLog
|
|
139
|
-
})
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
//#endregion
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
143
16
|
//#region src/engine/bundler.ts
|
|
144
17
|
const COCOAPODS_SPEC = /^ {4}cocoapods \(/m;
|
|
145
18
|
function bundlerPin(root) {
|
|
@@ -300,15 +173,6 @@ function describeDiagnostic(diagnostic) {
|
|
|
300
173
|
}
|
|
301
174
|
//#endregion
|
|
302
175
|
//#region src/engine/xcode.ts
|
|
303
|
-
const IOS_DIR = "ios";
|
|
304
|
-
const PREBUILD_REMEDY = "Generate it with `npx expo prebuild -p ios` (stim ios does this automatically for an Expo project with no ios/ directory), or commit the native project.";
|
|
305
|
-
function buildFailure(message, remedy) {
|
|
306
|
-
return { error: {
|
|
307
|
-
code: "STIM_BUILD_FAILED",
|
|
308
|
-
message,
|
|
309
|
-
remedy
|
|
310
|
-
} };
|
|
311
|
-
}
|
|
312
176
|
function pickXcodeProject(entries) {
|
|
313
177
|
const names = (Array.isArray(entries) ? entries : []).filter((e) => typeof e === "string");
|
|
314
178
|
const workspaces = names.filter((e) => e.endsWith(".xcworkspace")).toSorted();
|
|
@@ -336,22 +200,6 @@ function pickXcodeProject(entries) {
|
|
|
336
200
|
}
|
|
337
201
|
return null;
|
|
338
202
|
}
|
|
339
|
-
function discoverXcodeProject(root) {
|
|
340
|
-
const dir = join(root, IOS_DIR);
|
|
341
|
-
let entries;
|
|
342
|
-
try {
|
|
343
|
-
entries = readdirSync(dir);
|
|
344
|
-
} catch {
|
|
345
|
-
return buildFailure(`No ${IOS_DIR}/ directory in ${root}.`, PREBUILD_REMEDY);
|
|
346
|
-
}
|
|
347
|
-
const picked = pickXcodeProject(entries);
|
|
348
|
-
if (!picked) return buildFailure(`${dir} contains no .xcworkspace and no .xcodeproj.`, PREBUILD_REMEDY);
|
|
349
|
-
return {
|
|
350
|
-
...picked,
|
|
351
|
-
dir,
|
|
352
|
-
path: join(dir, picked.file)
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
203
|
function parseSchemeList(text) {
|
|
356
204
|
const empty = {
|
|
357
205
|
name: null,
|
|
@@ -454,18 +302,6 @@ function compilationPrefixMappings(workspaceRoot, derivedDataPath) {
|
|
|
454
302
|
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) mappings.push(`${derived}=/^derived-data`);
|
|
455
303
|
return mappings.map((mapping) => /[\s"\\]/.test(mapping) ? `"${mapping.replace(/["\\]/g, "\\$&")}"` : mapping).join(" ");
|
|
456
304
|
}
|
|
457
|
-
function ccacheEnabled(podfileProperties) {
|
|
458
|
-
if (!podfileProperties || typeof podfileProperties !== "object") return false;
|
|
459
|
-
return podfileProperties["apple.ccacheEnabled"] === "true";
|
|
460
|
-
}
|
|
461
|
-
function readPodfileProperties(root) {
|
|
462
|
-
try {
|
|
463
|
-
const parsed = JSON.parse(readFileSync(join(root, IOS_DIR, "Podfile.properties.json"), "utf-8"));
|
|
464
|
-
return parsed && typeof parsed === "object" ? parsed : null;
|
|
465
|
-
} catch {
|
|
466
|
-
return null;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
305
|
const SWIFT_PREFIX_MAPPING_MIN_SWIFT = {
|
|
470
306
|
major: 6,
|
|
471
307
|
minor: 4
|
|
@@ -475,40 +311,12 @@ function swiftPrefixMappingSupported(version) {
|
|
|
475
311
|
const min = SWIFT_PREFIX_MAPPING_MIN_SWIFT;
|
|
476
312
|
return version.major > min.major || version.major === min.major && version.minor >= min.minor;
|
|
477
313
|
}
|
|
478
|
-
|
|
479
|
-
major: 0,
|
|
480
|
-
minor: 87
|
|
481
|
-
};
|
|
482
|
-
function reactNativeSupportsSwiftCache(version) {
|
|
483
|
-
if (!version) return false;
|
|
484
|
-
const min = SWIFT_CACHE_MIN_REACT_NATIVE;
|
|
485
|
-
return version.major > min.major || version.major === min.major && version.minor >= min.minor;
|
|
486
|
-
}
|
|
487
|
-
function parseReactNativeVersion(packageJson) {
|
|
488
|
-
if (!packageJson || typeof packageJson !== "object") return null;
|
|
489
|
-
const raw = packageJson.version;
|
|
490
|
-
const m = typeof raw === "string" ? /^(\d+)\.(\d+)\./.exec(raw) : null;
|
|
491
|
-
if (!m || m[1] === void 0 || m[2] === void 0) return null;
|
|
492
|
-
return {
|
|
493
|
-
major: parseInt(m[1], 10),
|
|
494
|
-
minor: parseInt(m[2], 10)
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
function detectReactNativeVersion(root) {
|
|
498
|
-
const file = resolvePackageJson(root, "react-native");
|
|
499
|
-
if (!file) return null;
|
|
500
|
-
try {
|
|
501
|
-
return parseReactNativeVersion(JSON.parse(readFileSync(file, "utf-8")));
|
|
502
|
-
} catch {
|
|
503
|
-
return null;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
function compilationCacheSettings({ workspaceRoot, derivedDataPath, casPath, xcodeMajor, swiftVersion = null, reactNativeVersion = null, ccache = false, optimizations = resolveOptimizations({}, {}).ios }) {
|
|
314
|
+
function compilationCacheSettings({ workspaceRoot, derivedDataPath, casPath, xcodeMajor, swiftVersion = null, swiftCacheCompatible = false, ccache = false, optimizations = resolveOptimizations({}, {}).ios }) {
|
|
507
315
|
if (xcodeMajor === null || xcodeMajor === void 0) return [];
|
|
508
316
|
if (xcodeMajor < 26) return [];
|
|
509
317
|
if (ccache) return [];
|
|
510
318
|
const swiftMappable = swiftPrefixMappingSupported(swiftVersion);
|
|
511
|
-
const auto = swiftMappable &&
|
|
319
|
+
const auto = swiftMappable && swiftCacheCompatible;
|
|
512
320
|
const swift = optimizations.compilationCache && (optimizations.swiftCompilationCache ?? auto);
|
|
513
321
|
const mappings = optimizations.prefixMapping ? compilationPrefixMappings(workspaceRoot, derivedDataPath) : "";
|
|
514
322
|
return [
|
|
@@ -544,34 +352,6 @@ function parseXcodeMajor(output) {
|
|
|
544
352
|
function detectXcodeMajor(exec = null) {
|
|
545
353
|
return parseXcodeMajor((exec || getExecutor()).runQuiet("xcodebuild -version", { timeoutMs: 1e4 }));
|
|
546
354
|
}
|
|
547
|
-
function resolveCompilationCacheSettings({ root, derivedDataPath, exec = null, casPath = sharedCompilationCache$1(), optimizations = resolveOptimizations({}, {}).ios, onNote = (line) => console.error(line) }) {
|
|
548
|
-
const xcodeMajor = detectXcodeMajor(exec);
|
|
549
|
-
const ccache = ccacheEnabled(readPodfileProperties(root));
|
|
550
|
-
const probe = xcodeMajor !== null && xcodeMajor >= 26 && !ccache && optimizations.compilationCache && optimizations.swiftCompilationCache !== false;
|
|
551
|
-
const swiftVersion = probe ? detectSwiftVersion(exec) : null;
|
|
552
|
-
const reactNativeVersion = probe ? detectReactNativeVersion(root) : null;
|
|
553
|
-
const settings = compilationCacheSettings({
|
|
554
|
-
workspaceRoot: root,
|
|
555
|
-
derivedDataPath,
|
|
556
|
-
casPath,
|
|
557
|
-
xcodeMajor,
|
|
558
|
-
swiftVersion,
|
|
559
|
-
reactNativeVersion,
|
|
560
|
-
ccache,
|
|
561
|
-
optimizations
|
|
562
|
-
});
|
|
563
|
-
if (settings.length > 0 && optimizations.compilationCache) {
|
|
564
|
-
register({
|
|
565
|
-
dir: casPath,
|
|
566
|
-
name: "Xcode compilation cache",
|
|
567
|
-
prune: "atomic",
|
|
568
|
-
note: "shared Xcode compilation cache"
|
|
569
|
-
});
|
|
570
|
-
const swift = settings.includes("SWIFT_ENABLE_COMPILE_CACHE=YES") ? settings.includes("SWIFT_ENABLE_PREFIX_MAPPING=YES") ? "Swift on" : "Swift on, unmapped" : swiftVersion && !swiftPrefixMappingSupported(swiftVersion) ? `Swift off, ${swiftVersion.major}.${swiftVersion.minor} < ${SWIFT_PREFIX_MAPPING_MIN_SWIFT.major}.${SWIFT_PREFIX_MAPPING_MIN_SWIFT.minor}` : swiftVersion && reactNativeVersion && !reactNativeSupportsSwiftCache(reactNativeVersion) ? `Swift off, react-native ${reactNativeVersion.major}.${reactNativeVersion.minor} < ${SWIFT_CACHE_MIN_REACT_NATIVE.major}.${SWIFT_CACHE_MIN_REACT_NATIVE.minor}` : "Swift off";
|
|
571
|
-
onNote(chalk.dim(phaseLine("cache", `compilation cache on (CAS at ${casPath}, ${swift})`)));
|
|
572
|
-
}
|
|
573
|
-
return settings;
|
|
574
|
-
}
|
|
575
355
|
function xcodebuildArgs({ project, scheme, udid = null, destination = null, configuration = "Debug", sdk = "iphonesimulator", derivedDataPath, extraArgs = [], buildSettings = [] }) {
|
|
576
356
|
return [
|
|
577
357
|
project.flag,
|
|
@@ -774,13 +554,13 @@ function compilationCacheActivityLine(activity) {
|
|
|
774
554
|
if (activity.status === "not-run") return "not run; artifact cache supplied the app";
|
|
775
555
|
return "unavailable; Xcode did not report reliable statistics";
|
|
776
556
|
}
|
|
777
|
-
async function
|
|
778
|
-
if (!root || typeof root !== "string") throw new TypeError("
|
|
779
|
-
if (!logWriter || typeof logWriter.write !== "function") throw new TypeError("
|
|
780
|
-
if (!udid && !destination) throw new TypeError("
|
|
557
|
+
async function buildXcode({ root, udid = null, logWriter, project, scheme = null, configuration = "Debug", sdk = "iphonesimulator", destination = null, arch = null, derivedDataPath = null, extraArgs = [], compilationCache, startedAt: clockStart, now = () => Date.now(), exec = null, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line) }) {
|
|
558
|
+
if (!root || typeof root !== "string") throw new TypeError("buildXcode requires {root}");
|
|
559
|
+
if (!logWriter || typeof logWriter.write !== "function") throw new TypeError("buildXcode requires {logWriter} with a write() method");
|
|
560
|
+
if (!udid && !destination) throw new TypeError("buildXcode requires {udid} (or an explicit {destination})");
|
|
781
561
|
const executor = exec || getExecutor();
|
|
782
562
|
const dd = derivedDataPath || (scheme ? join(workspaceDerivedData(root), `scheme-${createHash("sha256").update(scheme).digest("hex")}`) : workspaceDerivedData(root));
|
|
783
|
-
const startedAt = now();
|
|
563
|
+
const startedAt = clockStart ?? now();
|
|
784
564
|
const elapsed = () => now() - startedAt;
|
|
785
565
|
const reportError = (message, remedy) => {
|
|
786
566
|
logWriter.write({
|
|
@@ -791,23 +571,18 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
|
|
|
791
571
|
...remedy ? { remedy } : {}
|
|
792
572
|
});
|
|
793
573
|
};
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
}],
|
|
805
|
-
durationMs: elapsed()
|
|
806
|
-
});
|
|
807
|
-
}
|
|
808
|
-
target = discovered;
|
|
574
|
+
if (project.error) {
|
|
575
|
+
reportError(project.error.message, project.error.remedy);
|
|
576
|
+
return failedResult({
|
|
577
|
+
code: project.error.code,
|
|
578
|
+
diagnostics: [{
|
|
579
|
+
message: project.error.message,
|
|
580
|
+
remedy: project.error.remedy ?? void 0
|
|
581
|
+
}],
|
|
582
|
+
durationMs: elapsed()
|
|
583
|
+
});
|
|
809
584
|
}
|
|
810
|
-
const resolvedTarget =
|
|
585
|
+
const resolvedTarget = project;
|
|
811
586
|
const selected = resolveScheme(resolvedTarget, {
|
|
812
587
|
exec: executor,
|
|
813
588
|
scheme
|
|
@@ -824,12 +599,9 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
|
|
|
824
599
|
});
|
|
825
600
|
}
|
|
826
601
|
const buildScheme = selected.scheme;
|
|
827
|
-
const cacheSettings = compilationCache ===
|
|
828
|
-
root,
|
|
602
|
+
const cacheSettings = typeof compilationCache === "function" ? compilationCache({
|
|
829
603
|
derivedDataPath: dd,
|
|
830
|
-
exec: executor
|
|
831
|
-
onNote,
|
|
832
|
-
optimizations
|
|
604
|
+
exec: executor
|
|
833
605
|
}) : compilationCache || [];
|
|
834
606
|
const buildSettings = arch ? [
|
|
835
607
|
...cacheSettings,
|
|
@@ -1075,11 +847,436 @@ async function buildIos({ root, udid = null, logWriter, project = null, scheme =
|
|
|
1075
847
|
};
|
|
1076
848
|
}
|
|
1077
849
|
//#endregion
|
|
1078
|
-
//#region src/
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
850
|
+
//#region src/engine/deps.ts
|
|
851
|
+
const DEPS_ERROR = "STIM_DEPS_FAILED";
|
|
852
|
+
const TRANSCRIPT_LINES = 2e3;
|
|
853
|
+
const MAX_POD_DIAGNOSTIC_LINES = 15;
|
|
854
|
+
const POD_MARKER = /^\[!\]/;
|
|
855
|
+
const POD_CONTINUATION = /^\s+\S/;
|
|
856
|
+
const RUBY_HEAD = /^\S.*\.rb:\d+:in\s+(?:`[^']*'|'[^']*'):\s*\S/;
|
|
857
|
+
const RUBY_FRAME = /^\s*from\s+\S/;
|
|
858
|
+
const RUBY_CONTEXT_BEFORE = 4;
|
|
859
|
+
const BUNDLER_FROZEN = /frozen mode|lockfile can't be updated|in deployment mode after changing/i;
|
|
860
|
+
const BUNDLER_NO_COCOAPODS = /cocoapods is not currently included in the bundle|command not found: pod\b/i;
|
|
861
|
+
function extractPodDiagnostics(transcript) {
|
|
862
|
+
if (typeof transcript !== "string" || transcript === "") return null;
|
|
863
|
+
const lines = transcript.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
864
|
+
return extractPodBangBlocks(lines) || extractRubyHead(lines);
|
|
865
|
+
}
|
|
866
|
+
function extractPodBangBlocks(lines) {
|
|
867
|
+
const blocks = [];
|
|
868
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
869
|
+
const line = lines[i];
|
|
870
|
+
if (line === void 0 || !POD_MARKER.test(line)) continue;
|
|
871
|
+
const block = [line];
|
|
872
|
+
let j = i + 1;
|
|
873
|
+
for (; j < lines.length; j += 1) {
|
|
874
|
+
const next = lines[j];
|
|
875
|
+
if (next === void 0 || !POD_CONTINUATION.test(next)) break;
|
|
876
|
+
block.push(next);
|
|
877
|
+
}
|
|
878
|
+
blocks.push(block);
|
|
879
|
+
i = j - 1;
|
|
880
|
+
}
|
|
881
|
+
if (blocks.length === 0) return null;
|
|
882
|
+
const out = [];
|
|
883
|
+
let dropped = 0;
|
|
884
|
+
for (const block of blocks) {
|
|
885
|
+
const room = MAX_POD_DIAGNOSTIC_LINES - out.length;
|
|
886
|
+
if (room <= 0) {
|
|
887
|
+
dropped += block.length;
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
out.push(...block.slice(0, room));
|
|
891
|
+
dropped += Math.max(0, block.length - room);
|
|
892
|
+
}
|
|
893
|
+
if (dropped > 0) out.push(`(+${dropped} more [!] lines in the build log)`);
|
|
894
|
+
return {
|
|
895
|
+
source: "cocoapods",
|
|
896
|
+
lines: out
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function extractRubyHead(lines) {
|
|
900
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
901
|
+
const line = lines[i];
|
|
902
|
+
if (line === void 0 || !RUBY_HEAD.test(line) || RUBY_FRAME.test(line)) continue;
|
|
903
|
+
let start = i;
|
|
904
|
+
while (start > 0 && i - start < RUBY_CONTEXT_BEFORE) {
|
|
905
|
+
const prev = lines[start - 1];
|
|
906
|
+
if (prev === void 0 || prev.trim() === "" || RUBY_FRAME.test(prev) || POD_MARKER.test(prev)) break;
|
|
907
|
+
start -= 1;
|
|
908
|
+
}
|
|
909
|
+
let end = i + 1;
|
|
910
|
+
while (end < lines.length) {
|
|
911
|
+
const next = lines[end];
|
|
912
|
+
if (next === void 0 || next.trim() === "" || RUBY_FRAME.test(next)) break;
|
|
913
|
+
end += 1;
|
|
914
|
+
}
|
|
915
|
+
return {
|
|
916
|
+
source: "ruby",
|
|
917
|
+
lines: lines.slice(start, end).filter((entry) => entry.trim() !== "").slice(0, MAX_POD_DIAGNOSTIC_LINES)
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
function podsAreStale(lockText, manifestText) {
|
|
923
|
+
const lock = normalize(lockText);
|
|
924
|
+
const manifest = normalize(manifestText);
|
|
925
|
+
if (lock === null && manifest === null) return {
|
|
926
|
+
noPods: true,
|
|
927
|
+
stale: false
|
|
928
|
+
};
|
|
929
|
+
if (lock === null) return {
|
|
930
|
+
stale: true,
|
|
931
|
+
reason: "ios/Podfile.lock is missing but ios/Pods exists"
|
|
932
|
+
};
|
|
933
|
+
if (manifest === null) return {
|
|
934
|
+
stale: true,
|
|
935
|
+
reason: "ios/Pods/Manifest.lock is missing (pods have never been installed here)"
|
|
936
|
+
};
|
|
937
|
+
if (lock !== manifest) return {
|
|
938
|
+
stale: true,
|
|
939
|
+
reason: "ios/Podfile.lock and ios/Pods/Manifest.lock differ"
|
|
940
|
+
};
|
|
941
|
+
return { stale: false };
|
|
942
|
+
}
|
|
943
|
+
function normalize(text) {
|
|
944
|
+
if (typeof text !== "string") return null;
|
|
945
|
+
return text.replace(/\r\n/g, "\n").trimEnd();
|
|
946
|
+
}
|
|
947
|
+
function podfilePath(root) {
|
|
948
|
+
return join(root, "ios", "Podfile");
|
|
949
|
+
}
|
|
950
|
+
function readPodState(root) {
|
|
951
|
+
return {
|
|
952
|
+
hasPodfile: existsSync(podfilePath(root)),
|
|
953
|
+
lockText: readOrNull(join(root, "ios", "Podfile.lock")),
|
|
954
|
+
manifestText: readOrNull(join(root, "ios", "Pods", "Manifest.lock"))
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
function readOrNull(file) {
|
|
958
|
+
try {
|
|
959
|
+
return readFileSync(file, "utf-8");
|
|
960
|
+
} catch {
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
function podEnv(root, options = {}) {
|
|
965
|
+
return podEnvForRuby(readRubyVersion(root), options);
|
|
966
|
+
}
|
|
967
|
+
function podEnvForRuby(version, { env = process.env, home = homedir(), exists = existsSync } = {}) {
|
|
968
|
+
const out = {
|
|
969
|
+
...env,
|
|
970
|
+
FORCE_COLOR: "0",
|
|
971
|
+
CLICOLOR: "0",
|
|
972
|
+
LANG: env.LANG ?? "en_US.UTF-8",
|
|
973
|
+
LC_ALL: env.LC_ALL ?? env.LANG ?? "en_US.UTF-8"
|
|
974
|
+
};
|
|
975
|
+
if (!version) return out;
|
|
976
|
+
const candidates = [
|
|
977
|
+
{ bin: join(home, ".rbenv", "versions", version, "bin") },
|
|
978
|
+
{
|
|
979
|
+
bin: join(home, ".rvm", "rubies", `ruby-${version}`, "bin"),
|
|
980
|
+
gems: join(home, ".rvm", "gems", `ruby-${version}`)
|
|
981
|
+
},
|
|
982
|
+
{ bin: join(home, ".asdf", "installs", "ruby", version, "bin") },
|
|
983
|
+
{ bin: join(home, ".local", "share", "mise", "installs", "ruby", version, "bin") }
|
|
984
|
+
];
|
|
985
|
+
for (const c of candidates) {
|
|
986
|
+
if (!exists(c.bin)) continue;
|
|
987
|
+
out.PATH = `${c.bin}${delimiter}${out.PATH ?? ""}`;
|
|
988
|
+
if (c.gems && exists(c.gems)) {
|
|
989
|
+
out.GEM_HOME = c.gems;
|
|
990
|
+
out.GEM_PATH = c.gems;
|
|
991
|
+
}
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
return out;
|
|
995
|
+
}
|
|
996
|
+
function readRubyVersion(root, { read = readFileSync } = {}) {
|
|
997
|
+
try {
|
|
998
|
+
const first = String(read(join(root, ".ruby-version"), "utf-8")).split("\n").map((l) => l.trim()).find((l) => l && !l.startsWith("#"));
|
|
999
|
+
if (!first) return null;
|
|
1000
|
+
return first.replace(/^ruby-/, "");
|
|
1001
|
+
} catch {
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
function bundlerEnv(root, gemfile) {
|
|
1006
|
+
return {
|
|
1007
|
+
...podEnv(root),
|
|
1008
|
+
BUNDLE_GEMFILE: gemfile,
|
|
1009
|
+
BUNDLE_FROZEN: "true"
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
1012
|
+
const BUNDLE_PATH_SETTING = /^BUNDLE_PATH:[ \t]*["']?([^"'\r\n]+?)["']?[ \t]*$/m;
|
|
1013
|
+
function bundlePathInsideProject(root, env) {
|
|
1014
|
+
const fromEnv = env.BUNDLE_PATH;
|
|
1015
|
+
const configured = fromEnv || BUNDLE_PATH_SETTING.exec(readOrNull(join(root, ".bundle", "config")) ?? "")?.[1];
|
|
1016
|
+
if (!configured || configured.startsWith("~")) return null;
|
|
1017
|
+
const resolved = resolve(root, configured);
|
|
1018
|
+
if (resolved !== root && !resolved.startsWith(root + sep)) return null;
|
|
1019
|
+
return {
|
|
1020
|
+
path: relative(root, resolved) || ".",
|
|
1021
|
+
where: fromEnv ? "where the BUNDLE_PATH environment variable points" : "where its own .bundle/config points BUNDLE_PATH"
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
async function runCaptured(ctx) {
|
|
1025
|
+
const startedAt = ctx.now();
|
|
1026
|
+
const transcript = [];
|
|
1027
|
+
const push = (line) => {
|
|
1028
|
+
const msg = stripAnsi(String(line)).trimEnd();
|
|
1029
|
+
if (!msg.trim()) return;
|
|
1030
|
+
transcript.push(msg);
|
|
1031
|
+
if (transcript.length > TRANSCRIPT_LINES) transcript.splice(TRANSCRIPT_LINES / 2, 1);
|
|
1032
|
+
ctx.logWriter?.write?.({
|
|
1033
|
+
src: "build",
|
|
1034
|
+
level: "debug",
|
|
1035
|
+
msg,
|
|
1036
|
+
raw: true,
|
|
1037
|
+
event: ctx.event
|
|
1038
|
+
});
|
|
1039
|
+
};
|
|
1040
|
+
let child;
|
|
1041
|
+
try {
|
|
1042
|
+
child = spawnDeclared(() => ctx.spawn(ctx.cmd, ctx.args, {
|
|
1043
|
+
cwd: ctx.cwd,
|
|
1044
|
+
stdio: [
|
|
1045
|
+
"ignore",
|
|
1046
|
+
"pipe",
|
|
1047
|
+
"pipe"
|
|
1048
|
+
],
|
|
1049
|
+
env: ctx.env
|
|
1050
|
+
}));
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
return {
|
|
1053
|
+
transcript,
|
|
1054
|
+
code: null,
|
|
1055
|
+
signal: null,
|
|
1056
|
+
error,
|
|
1057
|
+
durationMs: ctx.now() - startedAt
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
const reader = {
|
|
1061
|
+
out: createLineReader(push),
|
|
1062
|
+
err: createLineReader(push)
|
|
1063
|
+
};
|
|
1064
|
+
child.stdout?.setEncoding?.("utf-8");
|
|
1065
|
+
child.stderr?.setEncoding?.("utf-8");
|
|
1066
|
+
child.stdout?.on("data", (chunk) => reader.out.push(chunk));
|
|
1067
|
+
child.stderr?.on("data", (chunk) => reader.err.push(chunk));
|
|
1068
|
+
const stopHeartbeat = ctx.label ? startBuildHeartbeat({
|
|
1069
|
+
intervalMs: ctx.heartbeatMs,
|
|
1070
|
+
elapsed: () => ctx.now() - startedAt,
|
|
1071
|
+
emit: ctx.onHeartbeat,
|
|
1072
|
+
label: ctx.label,
|
|
1073
|
+
estimateMs: ctx.estimateMs ?? null
|
|
1074
|
+
}) : () => {};
|
|
1075
|
+
let result;
|
|
1076
|
+
try {
|
|
1077
|
+
result = await waitForChild(child);
|
|
1078
|
+
} finally {
|
|
1079
|
+
stopHeartbeat();
|
|
1080
|
+
}
|
|
1081
|
+
reader.out.flush();
|
|
1082
|
+
reader.err.flush();
|
|
1083
|
+
return {
|
|
1084
|
+
transcript,
|
|
1085
|
+
code: result.code ?? null,
|
|
1086
|
+
signal: result.signal ?? null,
|
|
1087
|
+
error: result.error ?? null,
|
|
1088
|
+
durationMs: ctx.now() - startedAt
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
async function ensureBundledGems(root, pin, ctx) {
|
|
1092
|
+
const env = bundlerEnv(root, pin.gemfile);
|
|
1093
|
+
const cwd = dirname(pin.gemfile);
|
|
1094
|
+
const check = await runCaptured({
|
|
1095
|
+
...ctx,
|
|
1096
|
+
cmd: "bundle",
|
|
1097
|
+
args: ["check", "--dry-run"],
|
|
1098
|
+
cwd,
|
|
1099
|
+
env,
|
|
1100
|
+
event: "bundle_check",
|
|
1101
|
+
label: "gems"
|
|
1102
|
+
});
|
|
1103
|
+
if (check.error) return bundlerSpawnFailure("bundle check", check, pin);
|
|
1104
|
+
if (check.code === 0) return { bundler: true };
|
|
1105
|
+
const install = await runCaptured({
|
|
1106
|
+
...ctx,
|
|
1107
|
+
cmd: "bundle",
|
|
1108
|
+
args: ["install"],
|
|
1109
|
+
cwd,
|
|
1110
|
+
env,
|
|
1111
|
+
event: "bundle_install",
|
|
1112
|
+
label: "gems"
|
|
1113
|
+
});
|
|
1114
|
+
if (install.error) return bundlerSpawnFailure("bundle install", install, pin);
|
|
1115
|
+
const inProject = bundlePathInsideProject(cwd, env);
|
|
1116
|
+
const note = inProject ? `\`bundle install\` put this project's gems in ${inProject.path}${sep}, ${inProject.where}; Gemfile.lock itself is never written.` : void 0;
|
|
1117
|
+
if (install.code === 0) return {
|
|
1118
|
+
bundler: true,
|
|
1119
|
+
note
|
|
1120
|
+
};
|
|
1121
|
+
const how = install.signal ? `signal ${install.signal}` : `exit code ${install.code}`;
|
|
1122
|
+
const transcript = install.transcript.join("\n");
|
|
1123
|
+
const extracted = extractPodDiagnostics(transcript);
|
|
1124
|
+
return {
|
|
1125
|
+
bundler: false,
|
|
1126
|
+
failure: {
|
|
1127
|
+
failed: true,
|
|
1128
|
+
code: DEPS_ERROR,
|
|
1129
|
+
reason: `\`bundle install\` failed (${how}).`,
|
|
1130
|
+
remedy: frozenRemedy(root, pin, transcript) || gemInstallRemedy(root, pin),
|
|
1131
|
+
diagnosticSource: extracted ? extracted.source : "tail",
|
|
1132
|
+
diagnosticLines: extracted ? extracted.lines : [],
|
|
1133
|
+
lastLines: install.transcript.slice(-20),
|
|
1134
|
+
durationMs: install.durationMs
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
function bundlerSpawnFailure(command, run, pin) {
|
|
1139
|
+
if (isMissingBinary(run.error)) return {
|
|
1140
|
+
bundler: false,
|
|
1141
|
+
note: missingBundlerNote(pin)
|
|
1142
|
+
};
|
|
1143
|
+
return {
|
|
1144
|
+
bundler: false,
|
|
1145
|
+
failure: {
|
|
1146
|
+
failed: true,
|
|
1147
|
+
code: DEPS_ERROR,
|
|
1148
|
+
reason: `Could not run \`${command}\`: ${run.error?.message || run.error}`,
|
|
1149
|
+
remedy: `Bundler is how this project pins its CocoaPods (${pin.lockfile}). Check that \`bundle\` runs in ${dirname(pin.gemfile)}, then run again.`,
|
|
1150
|
+
lastLines: run.transcript.slice(-20),
|
|
1151
|
+
durationMs: run.durationMs
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
function missingBundlerNote(pin) {
|
|
1156
|
+
return `${pin.lockfile} pins this project's CocoaPods, but \`bundle\` is not on PATH, so pods run as plain \`pod install\` with whatever CocoaPods PATH resolves to (\`gem install bundler\` to use the pin).`;
|
|
1157
|
+
}
|
|
1158
|
+
function frozenRemedy(root, pin, transcript) {
|
|
1159
|
+
if (!BUNDLER_FROZEN.test(transcript)) return void 0;
|
|
1160
|
+
return `Stim runs bundler with BUNDLE_FROZEN so it can never write into your checkout, and ${pin.gemfile} no longer matches ${pin.lockfile}. Run \`cd ${root} && bundle install\` yourself, keep the updated Gemfile.lock, then run again.`;
|
|
1161
|
+
}
|
|
1162
|
+
function gemInstallRemedy(root, pin) {
|
|
1163
|
+
const version = readRubyVersion(root);
|
|
1164
|
+
return `${version ? `This repo pins ruby ${version} (.ruby-version), so put that ruby on PATH (rbenv/rvm/asdf/mise) first. ` : ""}Bundler could not install the gems ${pin.lockfile} pins, so \`bundle exec pod install\` cannot run. Run \`cd ${root} && bundle install\` and fix what it reports, then run again.`;
|
|
1165
|
+
}
|
|
1166
|
+
async function runPodInstall(root, logWriter, { spawnFn = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line) } = {}) {
|
|
1167
|
+
const iosDir = join(root, "ios");
|
|
1168
|
+
if (!existsSync(iosDir)) return {
|
|
1169
|
+
failed: true,
|
|
1170
|
+
code: DEPS_ERROR,
|
|
1171
|
+
reason: `No ios/ directory in ${root}, so there is nothing to pod install.`,
|
|
1172
|
+
remedy: "Run `stim ios` on a project with native iOS sources, or let prebuild generate them.",
|
|
1173
|
+
lastLines: []
|
|
1174
|
+
};
|
|
1175
|
+
const ctx = {
|
|
1176
|
+
logWriter,
|
|
1177
|
+
spawn: spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts)),
|
|
1178
|
+
now,
|
|
1179
|
+
heartbeatMs,
|
|
1180
|
+
onHeartbeat
|
|
1181
|
+
};
|
|
1182
|
+
const notes = [];
|
|
1183
|
+
const pin = bundlerPin(root);
|
|
1184
|
+
let bundler = false;
|
|
1185
|
+
if (pin) {
|
|
1186
|
+
const gems = await ensureBundledGems(root, pin, ctx);
|
|
1187
|
+
if (gems.failure) return {
|
|
1188
|
+
...gems.failure,
|
|
1189
|
+
notes
|
|
1190
|
+
};
|
|
1191
|
+
if (gems.note) notes.push(gems.note);
|
|
1192
|
+
bundler = gems.bundler;
|
|
1193
|
+
}
|
|
1194
|
+
const args = bundler ? [
|
|
1195
|
+
"bundle",
|
|
1196
|
+
"exec",
|
|
1197
|
+
"pod",
|
|
1198
|
+
"install"
|
|
1199
|
+
] : ["pod", "install"];
|
|
1200
|
+
const command = args.join(" ");
|
|
1201
|
+
const run = await runCaptured({
|
|
1202
|
+
...ctx,
|
|
1203
|
+
cmd: args[0],
|
|
1204
|
+
args: args.slice(1),
|
|
1205
|
+
cwd: iosDir,
|
|
1206
|
+
env: bundler && pin ? bundlerEnv(root, pin.gemfile) : podEnv(root),
|
|
1207
|
+
event: "pod_install",
|
|
1208
|
+
label: "pods",
|
|
1209
|
+
estimateMs
|
|
1210
|
+
});
|
|
1211
|
+
if (run.error) return {
|
|
1212
|
+
...(bundler ? missingBundle(run.error, pin) : missingPod(run.error)) || {
|
|
1213
|
+
failed: true,
|
|
1214
|
+
code: "STIM_DEPS_FAILED",
|
|
1215
|
+
reason: `Could not run \`${command}\`: ${run.error?.message || run.error}`,
|
|
1216
|
+
lastLines: run.transcript.slice(-20),
|
|
1217
|
+
durationMs: run.durationMs
|
|
1218
|
+
},
|
|
1219
|
+
command,
|
|
1220
|
+
notes
|
|
1221
|
+
};
|
|
1222
|
+
if (run.code !== 0) {
|
|
1223
|
+
const how = run.signal ? `signal ${run.signal}` : `exit code ${run.code}`;
|
|
1224
|
+
const transcript = run.transcript.join("\n");
|
|
1225
|
+
const extracted = extractPodDiagnostics(transcript);
|
|
1226
|
+
return {
|
|
1227
|
+
failed: true,
|
|
1228
|
+
code: DEPS_ERROR,
|
|
1229
|
+
reason: `\`${command}\` failed (${how}).`,
|
|
1230
|
+
remedy: podFailureRemedy(root, pin, transcript),
|
|
1231
|
+
command,
|
|
1232
|
+
notes,
|
|
1233
|
+
diagnosticSource: extracted ? extracted.source : "tail",
|
|
1234
|
+
diagnosticLines: extracted ? extracted.lines : [],
|
|
1235
|
+
lastLines: run.transcript.slice(-20),
|
|
1236
|
+
durationMs: run.durationMs
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
return {
|
|
1240
|
+
ok: true,
|
|
1241
|
+
command,
|
|
1242
|
+
notes,
|
|
1243
|
+
durationMs: run.durationMs
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
function podFailureRemedy(root, pin, transcript) {
|
|
1247
|
+
if (pin) {
|
|
1248
|
+
const frozen = frozenRemedy(root, pin, transcript);
|
|
1249
|
+
if (frozen) return frozen;
|
|
1250
|
+
if (BUNDLER_NO_COCOAPODS.test(transcript)) return `${pin.lockfile} resolves cocoapods, but bundler found no \`pod\` executable in the bundle it loaded: the installed gems belong to a different Gemfile than ${pin.gemfile}, or that Gemfile's bundle was never installed. Run \`cd ${root} && bundle install && bundle exec pod --version\` and make that work, then run again.`;
|
|
1251
|
+
}
|
|
1252
|
+
const pinned = /Could not find proper version of cocoapods/.test(transcript) ? readRubyVersion(root) : null;
|
|
1253
|
+
if (!pinned) return void 0;
|
|
1254
|
+
return `This repo pins ruby ${pinned} (.ruby-version) and its Gemfile's cocoapods was installed under it; the shell's ruby is likely a different version, so bundler looks in the wrong gem home. Put ruby ${pinned} on PATH (rbenv/rvm/asdf/mise) -- \`bundle install\` will NOT fix this.`;
|
|
1255
|
+
}
|
|
1256
|
+
function isMissingBinary(err) {
|
|
1257
|
+
const nodeErr = err;
|
|
1258
|
+
const message = String(nodeErr?.message || err || "");
|
|
1259
|
+
return nodeErr?.code === "ENOENT" || /ENOENT|not found/i.test(message);
|
|
1260
|
+
}
|
|
1261
|
+
function missingBundle(err, pin) {
|
|
1262
|
+
if (!isMissingBinary(err)) return null;
|
|
1263
|
+
return {
|
|
1264
|
+
failed: true,
|
|
1265
|
+
code: DEPS_ERROR,
|
|
1266
|
+
reason: "Bundler is not installed: no `bundle` executable on PATH.",
|
|
1267
|
+
remedy: `${pin?.lockfile ?? "Gemfile.lock"} pins this project's CocoaPods, so pods run through bundler. Install bundler (\`gem install bundler\`) and run again.`,
|
|
1268
|
+
lastLines: []
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
function missingPod(err) {
|
|
1272
|
+
if (!isMissingBinary(err)) return null;
|
|
1273
|
+
return {
|
|
1274
|
+
failed: true,
|
|
1275
|
+
code: DEPS_ERROR,
|
|
1276
|
+
reason: "CocoaPods is not installed: no `pod` executable on PATH.",
|
|
1277
|
+
remedy: "Install CocoaPods (`brew install cocoapods`, or `gem install cocoapods`) and run again.",
|
|
1278
|
+
lastLines: []
|
|
1279
|
+
};
|
|
1083
1280
|
}
|
|
1084
1281
|
//#endregion
|
|
1085
1282
|
//#region src/offload/toolchain.ts
|
|
@@ -1087,7 +1284,10 @@ const distDir = dirname(fileURLToPath(import.meta.url));
|
|
|
1087
1284
|
function quiet(file, args) {
|
|
1088
1285
|
return getExecutor().runFileQuiet(file, args, { timeoutMs: 2e4 });
|
|
1089
1286
|
}
|
|
1090
|
-
function iosToolchain() {
|
|
1287
|
+
function iosToolchain(root) {
|
|
1288
|
+
return iosToolchainForRuby(readRubyVersion(root));
|
|
1289
|
+
}
|
|
1290
|
+
function iosToolchainForRuby(rubyVersion) {
|
|
1091
1291
|
const xcode = quiet("xcodebuild", ["-version"]);
|
|
1092
1292
|
return {
|
|
1093
1293
|
stimBuild: stimBuildDigest(distDir),
|
|
@@ -1098,9 +1298,15 @@ function iosToolchain() {
|
|
|
1098
1298
|
"iphonesimulator",
|
|
1099
1299
|
"--show-sdk-version"
|
|
1100
1300
|
])?.trim() ?? null,
|
|
1101
|
-
cocoapods:
|
|
1301
|
+
cocoapods: cocoapodsVersion(rubyVersion)
|
|
1102
1302
|
};
|
|
1103
1303
|
}
|
|
1304
|
+
function cocoapodsVersion(rubyVersion) {
|
|
1305
|
+
return getExecutor().runFileQuiet("pod", ["--version"], {
|
|
1306
|
+
timeoutMs: 2e4,
|
|
1307
|
+
env: Object.fromEntries(Object.entries(podEnvForRuby(rubyVersion)).filter((entry) => entry[1] !== void 0))
|
|
1308
|
+
})?.trim().split("\n").pop()?.trim() ?? null;
|
|
1309
|
+
}
|
|
1104
1310
|
function macosToolchain() {
|
|
1105
1311
|
const xcode = quiet("xcodebuild", ["-version"]);
|
|
1106
1312
|
return {
|
|
@@ -1190,7 +1396,7 @@ function sdkPackages() {
|
|
|
1190
1396
|
platforms
|
|
1191
1397
|
};
|
|
1192
1398
|
}
|
|
1193
|
-
function workerToolchain() {
|
|
1399
|
+
function workerToolchain(rubyVersion = null) {
|
|
1194
1400
|
let listed = null;
|
|
1195
1401
|
try {
|
|
1196
1402
|
listed = JSON.parse(quiet("xcrun", [
|
|
@@ -1202,7 +1408,7 @@ function workerToolchain() {
|
|
|
1202
1408
|
]) ?? "null");
|
|
1203
1409
|
} catch {}
|
|
1204
1410
|
return {
|
|
1205
|
-
...
|
|
1411
|
+
...iosToolchainForRuby(rubyVersion),
|
|
1206
1412
|
macosSdk: quiet("xcrun", [
|
|
1207
1413
|
"--sdk",
|
|
1208
1414
|
"macosx",
|
|
@@ -1295,4 +1501,4 @@ function toolchainMismatches(target, worker) {
|
|
|
1295
1501
|
return out;
|
|
1296
1502
|
}
|
|
1297
1503
|
//#endregion
|
|
1298
|
-
export {
|
|
1504
|
+
export { bundlerPin as A, readBundleExecutable as C, swiftPrefixMappingSupported as D, startBuildHeartbeat as E, tailLines as O, pickXcodeProject as S, resolveScheme as T, buildXcode as _, toolchainMismatches as a, detectSwiftVersion as b, podsAreStale as c, runCaptured as d, runPodInstall as f, SWIFT_PREFIX_MAPPING_MIN_SWIFT as g, HEARTBEAT_INTERVAL_MS as h, macosToolchain as i, podInstallCommand as j, describeDiagnostic as k, readPodState as l, COMPILATION_CACHE_UNAVAILABLE as m, androidToolchain as n, workerToolchain as o, COMPILATION_CACHE_NOT_RUN as p, iosToolchain as r, DEPS_ERROR as s, androidRequirements as t, readRubyVersion as u, compilationCacheActivityLine as v, readBundleId as w, detectXcodeMajor as x, compilationCacheSettings as y };
|