peachsim 0.1.1620 → 0.1.1635
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/LICENSE +1 -1
- package/README.md +45 -6
- package/cli/app-config.ts +4 -1
- package/cli/app-fonts.ts +39 -18
- package/cli/app-stubs.ts +224 -9
- package/cli/bridge-flow-runner.ts +248 -156
- package/cli/cloud-client.ts +68 -57
- package/cli/command-registry.ts +1 -0
- package/cli/commands/box/search-command.ts +3 -2
- package/cli/commands/box.ts +10 -29
- package/cli/commands/control.ts +391 -92
- package/cli/commands/doctor.ts +17 -184
- package/cli/commands/flow.ts +79 -11
- package/cli/commands/inspect/core.ts +10 -5
- package/cli/commands/inspect/settling.ts +71 -22
- package/cli/commands/inspect/wait-ready.ts +12 -0
- package/cli/commands/inspect.ts +26 -3
- package/cli/commands/install-desktop.ts +1 -0
- package/cli/commands/maestro-compare.ts +105 -67
- package/cli/commands/maestro.ts +9 -1
- package/cli/commands/platform.ts +71 -36
- package/cli/commands/record.ts +21 -1
- package/cli/commands/screenshot.ts +23 -1
- package/cli/commands/serve.ts +7 -2
- package/cli/commands/setup.ts +19 -42
- package/cli/commands/swift.ts +5 -0
- package/cli/commands/upload.ts +51 -8
- package/cli/desktop-companion.ts +102 -17
- package/cli/dev-build-freshness.ts +37 -2
- package/cli/drivers/desktop.ts +14 -1
- package/cli/drivers/playwright-sim-host.ts +44 -8
- package/cli/drivers/playwright.ts +9 -8
- package/cli/drivers/types.ts +5 -0
- package/cli/maestro-accessibility.ts +53 -0
- package/cli/maestro-compare.ts +108 -12
- package/cli/main.ts +2 -1
- package/cli/outbound-endpoints.ts +35 -6
- package/cli/parent-pid.ts +0 -9
- package/cli/pause-aware-timeout.ts +102 -0
- package/cli/remote-simulators.ts +112 -0
- package/cli/remoteSimulatorContract.ts +21 -0
- package/cli/scene-video.ts +89 -0
- package/cli/ws-bridge.ts +23 -14
- package/detox/attempt-events.cjs +4 -0
- package/detox/expectations.ts +5 -1
- package/detox/index.ts +241 -181
- package/detox/motion-change.cjs +73 -0
- package/detox/motion-change.d.cts +21 -0
- package/detox/navigation-lifecycle.ts +22 -4
- package/dist-lib/agent-daemon-client.cjs +3 -2
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +3 -2
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +13 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +14 -8
- package/dist-lib/bridge-contract.mjs +13 -7
- package/dist-lib/bundle-channel.cjs +10480 -7962
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -2
- package/dist-lib/cloud.mjs +3 -2
- package/dist-lib/config.cjs +10 -6
- package/dist-lib/config.mjs +10 -6
- package/dist-lib/detox/index.cjs +1854 -966
- package/dist-lib/dev-bundle-resolution.cjs +64 -24
- package/dist-lib/expo-swift-bundle.cjs +8715 -6271
- package/dist-lib/expo-swift-metadata.cjs +7 -4
- package/dist-lib/expo-swift-metadata.mjs +7 -4
- package/dist-lib/home-paths.cjs +32 -3
- package/dist-lib/host/bridge-host.cjs +10135 -7060
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1843 -408
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +1 -1
- package/dist-lib/menu.cjs +3 -2
- package/dist-lib/menu.mjs +3 -2
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +5 -4
- package/dist-lib/metro-production-bundle.mjs +5 -4
- package/dist-lib/metro.cjs +1182 -418
- package/dist-lib/native-app-identity-project.cjs +782 -23
- package/dist-lib/native-app-identity-project.mjs +781 -23
- package/dist-lib/native-app-identity.cjs +276 -9
- package/dist-lib/native-app-identity.mjs +273 -8
- package/dist-lib/native-firebase-metadata.cjs +5 -4
- package/dist-lib/native-firebase-metadata.mjs +5 -4
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +3 -2
- package/dist-lib/react-native-host-modules.cjs +8 -1
- package/dist-lib/react-native-host-modules.mjs +8 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +106 -28
- package/dist-lib/sdk.cjs +115 -34
- package/dist-lib/sdk.mjs +115 -33
- package/dist-lib/skills.cjs +15274 -9904
- package/dist-lib/swift-compile.cjs +1165 -173
- package/dist-lib/swift-compile.mjs +1212 -203
- package/dist-lib/swift-package.cjs +12 -3
- package/dist-lib/swift-package.mjs +12 -3
- package/dist-lib/swift-submit.cjs +7 -1
- package/dist-lib/swift-submit.mjs +5 -1
- package/dist-lib/swift-toolchain.cjs +133 -18
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +2648 -862
- package/dist-lib/vite.cjs +70 -14
- package/dist-lib/worklet-executable.cjs +25 -2
- package/dist-lib/worklet-executable.mjs +25 -2
- package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
- package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
- package/package.json +2 -2
- package/scripts/dev-server-scanner.ts +35 -14
- package/skills/peach-perf/SKILL.md +11 -5
- package/skills/peach-setup/SKILL.md +16 -19
- package/src/admitted-mac-build.ts +34 -8
- package/src/android-app-identity.ts +146 -0
- package/src/android-autolinking.ts +75 -0
- package/src/android-string-value.ts +36 -0
- package/src/android-strings.ts +5 -36
- package/src/androidAutolinkingContract.ts +40 -0
- package/src/bridge-constants.ts +11 -0
- package/src/bridge-contract.ts +22 -34
- package/src/bundleGlobalFooter.ts +26 -7
- package/src/codex-client.ts +3 -2
- package/src/config.ts +15 -0
- package/src/desktop-host-delivery.ts +5 -1
- package/src/dev-bundle-resolution.ts +60 -26
- package/src/expo-kotlin-host.ts +6 -36
- package/src/expo-manifest-body.ts +13 -0
- package/src/expo-swift-bundle.ts +17 -12
- package/src/expo-swift-host.ts +640 -192
- package/src/expo-swift-ready.ts +78 -0
- package/src/expoSwiftContract.ts +19 -0
- package/src/home-paths.ts +48 -2
- package/src/host/bridge-host.ts +12 -57
- package/src/host/staged-host-files.ts +29 -2
- package/src/installed-package-versions.ts +54 -14
- package/src/launchMetadataContract.ts +24 -0
- package/src/metro-plugin.ts +37 -42
- package/src/native-app-identity-project.ts +142 -5
- package/src/native-app-identity.ts +176 -11
- package/src/native-firebase-config.ts +209 -13
- package/src/nitro-compile.ts +2 -5
- package/src/nitro-source.ts +147 -63
- package/src/process-group.ts +114 -61
- package/src/process-output.ts +0 -9
- package/src/public-brand.ts +1 -0
- package/src/react-native-bridge-modules.ts +416 -0
- package/src/react-native-host-modules.ts +7 -0
- package/src/sim-client.ts +6 -4
- package/src/swift-binary-modules.ts +2 -2
- package/src/swift-compile.ts +1007 -108
- package/src/swift-compiler-digest.ts +14 -0
- package/src/swift-distribution.lock.json +40 -12
- package/src/swift-distribution.ts +61 -9
- package/src/swift-host.ts +149 -56
- package/src/swift-icu.ts +14 -6
- package/src/swift-objc-sdk.ts +133 -10
- package/src/swift-objc-standin.ts +38 -3
- package/src/swift-package-manifest.ts +21 -6
- package/src/swift-package.ts +15 -1
- package/src/swift-packages.ts +119 -60
- package/src/swift-standin-emit.ts +57 -9
- package/src/swift-standins.ts +185 -25
- package/src/swift-submit.ts +10 -0
- package/src/swift-toolchain.ts +149 -23
- package/src/vite-plugin.ts +20 -20
- package/src/worklet-executable.ts +30 -3
- package/src/worklets-babel.ts +35 -14
- package/src/xcode-project.ts +10 -0
package/src/swift-standins.ts
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
import { execFileSync, spawnSync } from 'node:child_process'
|
|
13
13
|
import { createHash } from 'node:crypto'
|
|
14
14
|
import fs from 'node:fs'
|
|
15
|
-
import os from 'node:os'
|
|
16
15
|
import path from 'node:path'
|
|
17
16
|
import { getCliVersion } from './cli-version'
|
|
17
|
+
import { cacheDir as peachCacheDir, swiftPackageCacheOptions } from './home-paths'
|
|
18
18
|
import { parsePlistSource } from './plist'
|
|
19
19
|
import {
|
|
20
20
|
swiftDistributionAt,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
swiftPeachModules,
|
|
25
25
|
swiftSdkPaths,
|
|
26
26
|
} from './swift-compile'
|
|
27
|
-
import { IOS_SDK_ID, objcView } from './swift-objc-standin'
|
|
27
|
+
import { IOS_SDK_ID, objcView, type ObjcSurface } from './swift-objc-standin'
|
|
28
28
|
import {
|
|
29
29
|
STANDIN_EMIT_VERSION,
|
|
30
30
|
STANDIN_IMPORTS,
|
|
@@ -33,11 +33,14 @@ import {
|
|
|
33
33
|
type SwiftStandinBehaviors,
|
|
34
34
|
type StandinBehavior,
|
|
35
35
|
} from './swift-standin-emit'
|
|
36
|
+
import { swiftSdkOptions } from './swift-toolchain'
|
|
36
37
|
import type { SwiftPackageBinary } from './swift-packages'
|
|
37
38
|
|
|
38
39
|
const TRIPLE = 'wasm32-unknown-wasip1'
|
|
39
|
-
//
|
|
40
|
-
const cacheDir = path.join(
|
|
40
|
+
// every stand-in artifact and temporary workspace belongs to peach.
|
|
41
|
+
const cacheDir = path.join(peachCacheDir(), 'swift-standins')
|
|
42
|
+
// each binary stand-in is a target under its module's directory here.
|
|
43
|
+
export const SWIFT_STANDINS_DIR = '__standins__'
|
|
41
44
|
|
|
42
45
|
export interface SwiftStandin {
|
|
43
46
|
/** the module it stands in for, which names its compile target. */
|
|
@@ -46,6 +49,8 @@ export interface SwiftStandin {
|
|
|
46
49
|
target: string
|
|
47
50
|
/** the target's files, relative to its directory. */
|
|
48
51
|
files: Record<string, string>
|
|
52
|
+
/** other generated modules named by this target's public headers. */
|
|
53
|
+
dependencies?: string[]
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
export interface SwiftStandins {
|
|
@@ -59,6 +64,8 @@ interface Toolchain {
|
|
|
59
64
|
toolchainBin: string
|
|
60
65
|
/** the toolchain release, read once where the toolchain is resolved. */
|
|
61
66
|
release: string
|
|
67
|
+
/** modules generated earlier in this dependency closure. */
|
|
68
|
+
standinModules?: string
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
function exec(file: string, args: string[], cwd?: string): string {
|
|
@@ -216,7 +223,7 @@ const files = (dir: string, test: (name: string) => boolean): string[] =>
|
|
|
216
223
|
type Surface =
|
|
217
224
|
| { kind: 'swift'; module: string; interface: string }
|
|
218
225
|
| { kind: 'c'; module: string; modulemap: string; headers: string }
|
|
219
|
-
| { kind: 'objc'
|
|
226
|
+
| (ObjcSurface & { kind: 'objc' })
|
|
220
227
|
|
|
221
228
|
const OBJC = /^\s*(?:@interface|@protocol|@class|@import|#import)\b/m
|
|
222
229
|
|
|
@@ -303,10 +310,12 @@ function peachModuleDirs(toolchain: Toolchain, imports: string[]): string[] {
|
|
|
303
310
|
path.join(toolchainBin, 'swift'),
|
|
304
311
|
[
|
|
305
312
|
'build',
|
|
313
|
+
...swiftPackageCacheOptions(),
|
|
306
314
|
'--build-system',
|
|
307
315
|
'native',
|
|
308
316
|
'-j',
|
|
309
317
|
'4',
|
|
318
|
+
...swiftSdkOptions(),
|
|
310
319
|
'--swift-sdk',
|
|
311
320
|
swiftModuleSdk(moduleRoot).wasmSdkId,
|
|
312
321
|
'-c',
|
|
@@ -432,7 +441,13 @@ function wasmFlags(toolchain: Toolchain, imports: string[]): string[] {
|
|
|
432
441
|
sysroot,
|
|
433
442
|
'-resource-dir',
|
|
434
443
|
resources,
|
|
444
|
+
// the sdk toolset's emulation defines, which raw swiftc does not read
|
|
445
|
+
'-Xcc',
|
|
446
|
+
'-D_WASI_EMULATED_SIGNAL',
|
|
447
|
+
'-Xcc',
|
|
448
|
+
'-D_WASI_EMULATED_MMAN',
|
|
435
449
|
...peachModuleDirs(toolchain, imports).flatMap((dir) => ['-I', dir]),
|
|
450
|
+
...(toolchain.standinModules ? ['-I', toolchain.standinModules] : []),
|
|
436
451
|
]
|
|
437
452
|
}
|
|
438
453
|
|
|
@@ -460,6 +475,7 @@ function objcStandin(
|
|
|
460
475
|
toolchain,
|
|
461
476
|
work,
|
|
462
477
|
behavior,
|
|
478
|
+
binary.headerDependencies?.map((dependency) => dependency.module),
|
|
463
479
|
)
|
|
464
480
|
}
|
|
465
481
|
|
|
@@ -475,6 +491,7 @@ function graphStandin(
|
|
|
475
491
|
toolchain: Toolchain,
|
|
476
492
|
work: string,
|
|
477
493
|
behavior: ReadonlyMap<string, StandinBehavior>,
|
|
494
|
+
imports: string[] = [],
|
|
478
495
|
): SwiftStandin {
|
|
479
496
|
const paths = new Set(
|
|
480
497
|
graphs.flatMap((graph) =>
|
|
@@ -498,6 +515,9 @@ function graphStandin(
|
|
|
498
515
|
behavior,
|
|
499
516
|
omit,
|
|
500
517
|
plain,
|
|
518
|
+
inert: binary.publicHeaders !== undefined,
|
|
519
|
+
imports,
|
|
520
|
+
family: imports,
|
|
501
521
|
})
|
|
502
522
|
for (const entry of skipped) {
|
|
503
523
|
if (behavior.has(entry.path))
|
|
@@ -525,6 +545,7 @@ function graphStandin(
|
|
|
525
545
|
module,
|
|
526
546
|
target: binary.target,
|
|
527
547
|
files: { [`${module}.swift`]: source },
|
|
548
|
+
...(imports.length ? { dependencies: imports } : {}),
|
|
528
549
|
}
|
|
529
550
|
const before = omit.size + plain.size
|
|
530
551
|
const elsewhere: string[] = []
|
|
@@ -899,6 +920,7 @@ export function standinLibrary(
|
|
|
899
920
|
binary: SwiftPackageBinary,
|
|
900
921
|
searchRoot: string,
|
|
901
922
|
): string | null {
|
|
923
|
+
if (binary.publicHeaders !== undefined) return null
|
|
902
924
|
const dir = xcframework(binary).dir
|
|
903
925
|
const library = simulatorLibraryName(dir)
|
|
904
926
|
const supplied = path.join(dir, RUST_TARGET)
|
|
@@ -920,14 +942,18 @@ export function standinLibrary(
|
|
|
920
942
|
[
|
|
921
943
|
'build',
|
|
922
944
|
'--release',
|
|
945
|
+
'--locked',
|
|
923
946
|
'--target',
|
|
924
947
|
RUST_TARGET,
|
|
925
948
|
'--message-format=json-render-diagnostics',
|
|
926
949
|
'--manifest-path',
|
|
927
950
|
manifest,
|
|
951
|
+
'--target-dir',
|
|
952
|
+
path.join(cacheDir, 'cargo', key(manifest)),
|
|
928
953
|
],
|
|
929
954
|
{
|
|
930
955
|
encoding: 'utf8',
|
|
956
|
+
env: { ...process.env, CARGO_HOME: path.join(cacheDir, 'cargo-home') },
|
|
931
957
|
maxBuffer: 256 * 1024 * 1024,
|
|
932
958
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
933
959
|
},
|
|
@@ -976,10 +1002,31 @@ function sourceBinaryStandins(
|
|
|
976
1002
|
behavior: SwiftStandinBehaviors,
|
|
977
1003
|
): SwiftStandin[] | string {
|
|
978
1004
|
const repo = path.resolve(toolchain.moduleRoot, '../..')
|
|
979
|
-
|
|
1005
|
+
fs.mkdirSync(cacheDir, { recursive: true })
|
|
1006
|
+
const work = fs.mkdtempSync(path.join(cacheDir, 'request-'))
|
|
980
1007
|
try {
|
|
981
|
-
const artifact =
|
|
1008
|
+
const artifact =
|
|
1009
|
+
binary.publicHeaders !== undefined
|
|
1010
|
+
? { dir: path.join(work, 'headers') }
|
|
1011
|
+
: xcframework(binary)
|
|
982
1012
|
const local = { ...binary, dir: artifact.dir, url: null, checksum: null }
|
|
1013
|
+
if (binary.publicHeaders !== undefined) {
|
|
1014
|
+
const dependencies = binary.headerDependencies ?? []
|
|
1015
|
+
for (const header of [
|
|
1016
|
+
{ module: binary.target, path: binary.publicHeaders },
|
|
1017
|
+
...dependencies,
|
|
1018
|
+
])
|
|
1019
|
+
fs.cpSync(
|
|
1020
|
+
path.join(binary.dir, header.path),
|
|
1021
|
+
path.join(artifact.dir, header.module),
|
|
1022
|
+
{ recursive: true },
|
|
1023
|
+
)
|
|
1024
|
+
local.publicHeaders = binary.target
|
|
1025
|
+
local.headerDependencies = dependencies.map(({ module }) => ({
|
|
1026
|
+
module,
|
|
1027
|
+
path: module,
|
|
1028
|
+
}))
|
|
1029
|
+
}
|
|
983
1030
|
const generation = standinGenerationInputs([local], toolchain, behavior)
|
|
984
1031
|
const request = path.join(work, 'request.json')
|
|
985
1032
|
const delivery = path.join(work, 'delivery')
|
|
@@ -993,7 +1040,7 @@ function sourceBinaryStandins(
|
|
|
993
1040
|
release: toolchain.release,
|
|
994
1041
|
}),
|
|
995
1042
|
)
|
|
996
|
-
|
|
1043
|
+
const build = spawnSync(
|
|
997
1044
|
'bun',
|
|
998
1045
|
[
|
|
999
1046
|
path.join(repo, 'scripts/build/swift-standins-submit.ts'),
|
|
@@ -1004,11 +1051,20 @@ function sourceBinaryStandins(
|
|
|
1004
1051
|
'--delivery-dir',
|
|
1005
1052
|
delivery,
|
|
1006
1053
|
],
|
|
1007
|
-
{ cwd: repo,
|
|
1008
|
-
)
|
|
1009
|
-
const receipt: unknown = JSON.parse(
|
|
1010
|
-
fs.readFileSync(path.join(delivery, 'standins.json'), 'utf8'),
|
|
1054
|
+
{ cwd: repo, encoding: 'utf8', maxBuffer: 8 * 1024 * 1024 },
|
|
1011
1055
|
)
|
|
1056
|
+
if (build.stdout) process.stdout.write(build.stdout)
|
|
1057
|
+
if (build.stderr) process.stderr.write(build.stderr)
|
|
1058
|
+
if (build.error || build.status !== 0)
|
|
1059
|
+
throw new Error(
|
|
1060
|
+
`source stand-in build for ${binary.target} failed (${build.error?.message ?? build.signal ?? `exit ${build.status}`}): ${build.stderr?.trim().slice(-4000) || build.stdout?.trim().slice(-4000) || 'builder returned no diagnostic'}`,
|
|
1061
|
+
)
|
|
1062
|
+
const output = path.join(delivery, 'standins.json')
|
|
1063
|
+
if (!fs.existsSync(output))
|
|
1064
|
+
throw new Error(
|
|
1065
|
+
`source stand-in builder returned no standins.json for ${binary.target}`,
|
|
1066
|
+
)
|
|
1067
|
+
const receipt: unknown = JSON.parse(fs.readFileSync(output, 'utf8'))
|
|
1012
1068
|
if (
|
|
1013
1069
|
!receipt ||
|
|
1014
1070
|
typeof receipt !== 'object' ||
|
|
@@ -1055,7 +1111,7 @@ export function standinGenerationInputs(
|
|
|
1055
1111
|
const { moduleRoot, release } = toolchain
|
|
1056
1112
|
const sdk = swiftModuleSdk(moduleRoot)
|
|
1057
1113
|
const parts = [
|
|
1058
|
-
'standin/
|
|
1114
|
+
'standin/v6',
|
|
1059
1115
|
release,
|
|
1060
1116
|
sdk.wasmSdkId,
|
|
1061
1117
|
sdk.wasmSdkChecksum,
|
|
@@ -1068,7 +1124,9 @@ export function standinGenerationInputs(
|
|
|
1068
1124
|
const modules = new Set(
|
|
1069
1125
|
binaries.flatMap((binary) => {
|
|
1070
1126
|
try {
|
|
1071
|
-
return
|
|
1127
|
+
return binary.publicHeaders !== undefined
|
|
1128
|
+
? [binary.target]
|
|
1129
|
+
: surfaces(xcframework(binary).dir).map((surface) => surface.module)
|
|
1072
1130
|
} catch {
|
|
1073
1131
|
return []
|
|
1074
1132
|
}
|
|
@@ -1095,7 +1153,15 @@ export function standinGenerationInputs(
|
|
|
1095
1153
|
binary.source,
|
|
1096
1154
|
binary.url ?? '',
|
|
1097
1155
|
binary.checksum ?? '',
|
|
1098
|
-
|
|
1156
|
+
binary.publicHeaders !== undefined
|
|
1157
|
+
? [
|
|
1158
|
+
treeDigest(path.join(binary.dir, binary.publicHeaders)),
|
|
1159
|
+
...(binary.headerDependencies ?? []).map(
|
|
1160
|
+
(dependency) =>
|
|
1161
|
+
`${dependency.module}\0${treeDigest(path.join(binary.dir, dependency.path))}`,
|
|
1162
|
+
),
|
|
1163
|
+
].join('\0')
|
|
1164
|
+
: xcframework(binary).digest,
|
|
1099
1165
|
)
|
|
1100
1166
|
} catch {
|
|
1101
1167
|
// unreadable here fails again below, where it becomes a gap
|
|
@@ -1128,17 +1194,55 @@ function binaryStandins(
|
|
|
1128
1194
|
// calls, so peach names the path and asks for the artifact
|
|
1129
1195
|
if (!binary.url && !fs.existsSync(binary.dir))
|
|
1130
1196
|
return `${path.relative(process.cwd(), binary.dir) || binary.dir} is not on disk, and Xcode fails without it too; run the script that downloads or builds it, then run again`
|
|
1197
|
+
fs.mkdirSync(cacheDir, { recursive: true })
|
|
1198
|
+
const work = fs.mkdtempSync(path.join(cacheDir, 'work-'))
|
|
1131
1199
|
let all: Surface[]
|
|
1132
1200
|
let digest: string
|
|
1133
1201
|
try {
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1202
|
+
if (binary.publicHeaders !== undefined) {
|
|
1203
|
+
const headers = path.join(binary.dir, binary.publicHeaders)
|
|
1204
|
+
const modulemap = path.join(work, 'module.modulemap')
|
|
1205
|
+
const supplied = path.join(headers, 'module.modulemap')
|
|
1206
|
+
const roots = files(headers, (name) => name.endsWith('.h'))
|
|
1207
|
+
if (roots.length === 0)
|
|
1208
|
+
throw new Error('its public header directory has no headers')
|
|
1209
|
+
fs.writeFileSync(
|
|
1210
|
+
modulemap,
|
|
1211
|
+
fs.existsSync(supplied)
|
|
1212
|
+
? fs.readFileSync(supplied, 'utf8')
|
|
1213
|
+
: `module ${binary.target} {\n${roots.map((file) => ` header "${file}"`).join('\n')}\n export *\n}\n`,
|
|
1214
|
+
)
|
|
1215
|
+
all = [
|
|
1216
|
+
{
|
|
1217
|
+
kind: 'objc',
|
|
1218
|
+
module: binary.target,
|
|
1219
|
+
modulemap,
|
|
1220
|
+
headers,
|
|
1221
|
+
dependencies: binary.headerDependencies?.map((dependency) => ({
|
|
1222
|
+
module: dependency.module,
|
|
1223
|
+
headers: path.join(binary.dir, dependency.path),
|
|
1224
|
+
})),
|
|
1225
|
+
},
|
|
1226
|
+
]
|
|
1227
|
+
digest = [
|
|
1228
|
+
treeDigest(headers),
|
|
1229
|
+
...(binary.headerDependencies ?? []).map(
|
|
1230
|
+
(dependency) =>
|
|
1231
|
+
`${dependency.module}\0${treeDigest(path.join(binary.dir, dependency.path))}`,
|
|
1232
|
+
),
|
|
1233
|
+
].join('\0')
|
|
1234
|
+
} else {
|
|
1235
|
+
const artifact = xcframework(binary)
|
|
1236
|
+
all = surfaces(artifact.dir)
|
|
1237
|
+
digest = artifact.digest
|
|
1238
|
+
}
|
|
1137
1239
|
} catch (error) {
|
|
1240
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
1138
1241
|
return error instanceof Error ? error.message : String(error)
|
|
1139
1242
|
}
|
|
1140
1243
|
const found = all.filter((surface) => !provided.has(surface.module))
|
|
1141
1244
|
if (found.length === 0) {
|
|
1245
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
1142
1246
|
if (all.length > 0) return []
|
|
1143
1247
|
return 'its iOS simulator slice has no Swift interface or C modulemap'
|
|
1144
1248
|
}
|
|
@@ -1162,18 +1266,22 @@ function binaryStandins(
|
|
|
1162
1266
|
}
|
|
1163
1267
|
const id = hash.digest('hex').slice(0, 32)
|
|
1164
1268
|
const memo = built.get(id)
|
|
1165
|
-
if (memo)
|
|
1269
|
+
if (memo) {
|
|
1270
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
1271
|
+
return memo
|
|
1272
|
+
}
|
|
1166
1273
|
const cached = path.join(cacheDir, 'standins', `${id}.json`)
|
|
1167
1274
|
if (fs.existsSync(cached)) {
|
|
1168
1275
|
const value: SwiftStandin[] = JSON.parse(fs.readFileSync(cached, 'utf8'))
|
|
1169
1276
|
built.set(id, value)
|
|
1277
|
+
fs.rmSync(work, { recursive: true, force: true })
|
|
1170
1278
|
return value
|
|
1171
1279
|
}
|
|
1172
|
-
const work = fs.mkdtempSync(path.join(os.tmpdir(), 'peach-standin-'))
|
|
1173
1280
|
let result: SwiftStandin[] | string
|
|
1174
1281
|
try {
|
|
1175
1282
|
result =
|
|
1176
1283
|
process.platform === 'darwin' &&
|
|
1284
|
+
process.env.TM_EXEC_BUILD_PLATFORM !== 'mac' &&
|
|
1177
1285
|
process.env.TM_SESSION &&
|
|
1178
1286
|
process.env.CI !== 'true' &&
|
|
1179
1287
|
toolchain.moduleRoot === path.resolve(import.meta.dirname, '../../sootsim-swift') &&
|
|
@@ -1246,10 +1354,62 @@ export function swiftStandins(
|
|
|
1246
1354
|
): SwiftStandins {
|
|
1247
1355
|
const standins: SwiftStandin[] = []
|
|
1248
1356
|
const gaps = new Map<string, string>()
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1357
|
+
fs.mkdirSync(cacheDir, { recursive: true })
|
|
1358
|
+
const modules = fs.mkdtempSync(path.join(cacheDir, 'modules-'))
|
|
1359
|
+
const generatedToolchain = { ...toolchain, standinModules: modules }
|
|
1360
|
+
const byTarget = new Map(binaries.map((binary) => [binary.target, binary]))
|
|
1361
|
+
const prerequisites = new Set(
|
|
1362
|
+
binaries.flatMap((binary) =>
|
|
1363
|
+
(binary.headerDependencies ?? []).map((dependency) => dependency.module),
|
|
1364
|
+
),
|
|
1365
|
+
)
|
|
1366
|
+
const visited = new Set<string>()
|
|
1367
|
+
const visit = (binary: SwiftPackageBinary) => {
|
|
1368
|
+
if (visited.has(binary.target)) return
|
|
1369
|
+
visited.add(binary.target)
|
|
1370
|
+
for (const dependency of binary.headerDependencies ?? []) {
|
|
1371
|
+
const target = byTarget.get(dependency.module)
|
|
1372
|
+
if (target) visit(target)
|
|
1373
|
+
}
|
|
1374
|
+
const result = binaryStandins(binary, generatedToolchain, provided, behavior)
|
|
1375
|
+
if (typeof result === 'string') {
|
|
1376
|
+
gaps.set(binary.target, result)
|
|
1377
|
+
return
|
|
1378
|
+
}
|
|
1379
|
+
for (const standin of result) {
|
|
1380
|
+
// source objc dependents typecheck against the same generated declarations
|
|
1381
|
+
// that the app links, including on cache hits.
|
|
1382
|
+
if (prerequisites.has(standin.module)) {
|
|
1383
|
+
const source = standin.files[`${standin.module}.swift`]
|
|
1384
|
+
if (source !== undefined) {
|
|
1385
|
+
const file = path.join(modules, `${standin.module}.swift`)
|
|
1386
|
+
fs.writeFileSync(file, source)
|
|
1387
|
+
try {
|
|
1388
|
+
exec(path.join(toolchain.toolchainBin, 'swiftc'), [
|
|
1389
|
+
'-emit-module',
|
|
1390
|
+
'-parse-as-library',
|
|
1391
|
+
'-swift-version',
|
|
1392
|
+
'5',
|
|
1393
|
+
'-module-name',
|
|
1394
|
+
standin.module,
|
|
1395
|
+
...wasmFlags(generatedToolchain, standin.dependencies ?? []),
|
|
1396
|
+
'-emit-module-path',
|
|
1397
|
+
path.join(modules, `${standin.module}.swiftmodule`),
|
|
1398
|
+
file,
|
|
1399
|
+
])
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
gaps.set(binary.target, failure(error))
|
|
1402
|
+
return
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
standins.push(standin)
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
try {
|
|
1410
|
+
for (const binary of binaries) visit(binary)
|
|
1411
|
+
return { standins, gaps }
|
|
1412
|
+
} finally {
|
|
1413
|
+
fs.rmSync(modules, { recursive: true, force: true })
|
|
1253
1414
|
}
|
|
1254
|
-
return { standins, gaps }
|
|
1255
1415
|
}
|
package/src/swift-submit.ts
CHANGED
|
@@ -32,6 +32,10 @@ export const SWIFT_HMR_PATH = '/__peach/swift-hmr'
|
|
|
32
32
|
|
|
33
33
|
// shared with the compile service; collection enforces these before reading.
|
|
34
34
|
export const MAX_SWIFT_COMPILE_FILES = 256
|
|
35
|
+
/** how long one swift build may run when the caller asks for no budget. */
|
|
36
|
+
export const DEFAULT_SWIFT_COMPILE_BUILD_MS = 10 * 60_000
|
|
37
|
+
/** the longest build budget a caller may request. */
|
|
38
|
+
export const MAX_SWIFT_COMPILE_BUILD_MS = 60 * 60_000
|
|
35
39
|
export const MAX_SWIFT_COMPILE_SOURCE_BYTES = 2 * 1024 * 1024
|
|
36
40
|
export const MAX_SWIFT_COMPILE_RESOURCES = 128
|
|
37
41
|
export const MAX_SWIFT_COMPILE_RESOURCE_BYTES = 2 * 1024 * 1024
|
|
@@ -237,6 +241,11 @@ export type SwiftCompileSubmit = (work: {
|
|
|
237
241
|
entry: string
|
|
238
242
|
/** the directory-derived id of the One package. */
|
|
239
243
|
packageId: string
|
|
244
|
+
/**
|
|
245
|
+
* how long the build may run, up to `MAX_SWIFT_COMPILE_BUILD_MS`; absent means
|
|
246
|
+
* the default. hosted requests above the default require an internal compile key.
|
|
247
|
+
*/
|
|
248
|
+
buildBudgetMs?: number
|
|
240
249
|
}) => Promise<SwiftCompileOutcome>
|
|
241
250
|
|
|
242
251
|
/** the HTTP submitter, shared by the browser worker and the node build. */
|
|
@@ -394,6 +403,7 @@ export async function compileSwiftProject(
|
|
|
394
403
|
images?: Record<string, SwiftImageUpload>
|
|
395
404
|
entry: string
|
|
396
405
|
packageId: string
|
|
406
|
+
buildBudgetMs?: number
|
|
397
407
|
},
|
|
398
408
|
origin: string,
|
|
399
409
|
signal?: AbortSignal,
|
package/src/swift-toolchain.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// the one place that
|
|
1
|
+
// the one place that selects and verifies the toolchain app Swift compiles with.
|
|
2
2
|
// a binary .swiftmodule loads only in the compiler release that wrote it, so
|
|
3
3
|
// every caller names the release from packages/sootsim-swift/toolchain.json
|
|
4
4
|
// or the Swift distribution's lock (docs/swift-distribution.md).
|
|
@@ -6,13 +6,61 @@
|
|
|
6
6
|
// node builtins only: packages/sootsim-swift/scripts/build.sh imports this
|
|
7
7
|
// file straight from a checkout, with no install.
|
|
8
8
|
import { execFileSync } from 'node:child_process'
|
|
9
|
+
import { createHash } from 'node:crypto'
|
|
9
10
|
import fs from 'node:fs'
|
|
10
11
|
import os from 'node:os'
|
|
11
12
|
import path from 'node:path'
|
|
12
13
|
|
|
14
|
+
/** swiftpm's SDK directory option, shared by discovery and compilation. */
|
|
15
|
+
export function swiftSdkOptions(): string[] {
|
|
16
|
+
const directory = process.env.PEACH_SWIFT_SDKS_PATH
|
|
17
|
+
return directory ? ['--swift-sdks-path', path.resolve(directory)] : []
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// host archives include the official driver/runtime and the qualified patched frontend.
|
|
21
|
+
export const SWIFT_HOST_COMPILER_RELEASE = 'swift-6.4.0-RELEASE-custom-91504a66b3f012ac'
|
|
22
|
+
export const SWIFT_HOST_COMPILER_ID = '91504a66b3f012ac'
|
|
23
|
+
const compilerArchives: Record<string, { checksum: string; manifest: string }> = {
|
|
24
|
+
'darwin-arm64': {
|
|
25
|
+
checksum: '5d0ecbafd88c896beac74fd74c9d5fb20f973e0f58abbc1d2f27d5af0cbc4e59',
|
|
26
|
+
manifest: '827130a60b782ed413c9df41410afe7baf32dcb132b945a70ac0ff4c0594c690',
|
|
27
|
+
},
|
|
28
|
+
'linux-x64': {
|
|
29
|
+
checksum: '9d8491107efa347ccadf5f6974e80b2cff2b33cd8c34317dab777c5542512b3e',
|
|
30
|
+
manifest: '6221c024fa86b2201dcada23d9e13f6a11d7450cf22164a9708703f992de129f',
|
|
31
|
+
},
|
|
32
|
+
'linux-arm64': {
|
|
33
|
+
checksum: '14f5c7b39b1e36a1d9ce426a875676182fdb5247763a7e99cb72f74957bc0d9a',
|
|
34
|
+
manifest: '57ff31b79f9b3d9a6c0fd51c73271cdd88088522c0fc6d7a28ade03d68008b68',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function swiftHostCompilerArchive(
|
|
39
|
+
release: string,
|
|
40
|
+
host = `${process.platform}-${process.arch}`,
|
|
41
|
+
) {
|
|
42
|
+
if (release !== SWIFT_HOST_COMPILER_RELEASE)
|
|
43
|
+
throw new Error(`unqualified host compiler ${release}`)
|
|
44
|
+
const archive = compilerArchives[host]
|
|
45
|
+
if (!archive) throw new Error(`unsupported Swift compiler host ${host}`)
|
|
46
|
+
return {
|
|
47
|
+
...archive,
|
|
48
|
+
identity: SWIFT_HOST_COMPILER_ID,
|
|
49
|
+
url: `https://r2.sootsim.com/swift-host-compiler/${SWIFT_HOST_COMPILER_ID}/${release}-${host}.tar.gz`,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// source archives and bootstrap images retain the official release name.
|
|
54
|
+
export function swiftUpstreamRelease(release: string): string {
|
|
55
|
+
return release.replace(/-custom-[a-f0-9]{16}$/, '')
|
|
56
|
+
}
|
|
57
|
+
|
|
13
58
|
// swift.org's x.y.0 archives report the compiler identity as x.y.
|
|
14
59
|
export function swiftCompilerRelease(release: string): string {
|
|
15
|
-
return release.replace(
|
|
60
|
+
return swiftUpstreamRelease(release).replace(
|
|
61
|
+
/^swift-(\d+\.\d+)\.0-RELEASE$/,
|
|
62
|
+
'swift-$1-RELEASE',
|
|
63
|
+
)
|
|
16
64
|
}
|
|
17
65
|
|
|
18
66
|
/**
|
|
@@ -33,7 +81,8 @@ export function swiftToolchainBin(release: string): string {
|
|
|
33
81
|
return path.join(process.env.CONTRAST_SWIFT_TOOLCHAINS, release, 'usr/bin')
|
|
34
82
|
}
|
|
35
83
|
const image = path.join('/opt/swift', release, 'usr/bin')
|
|
36
|
-
if (fs.existsSync(path.join(image, 'swift')))
|
|
84
|
+
if (release.includes('-custom-') || fs.existsSync(path.join(image, 'swift')))
|
|
85
|
+
return image
|
|
37
86
|
return (
|
|
38
87
|
(process.env.PATH ?? '')
|
|
39
88
|
.split(path.delimiter)
|
|
@@ -57,27 +106,20 @@ const verified = new Map<string, string>()
|
|
|
57
106
|
* release and the commands that install it.
|
|
58
107
|
*/
|
|
59
108
|
export function swiftToolchain(release: string, sdk: SwiftWasmSdk): string {
|
|
60
|
-
const
|
|
109
|
+
const key = JSON.stringify([release, sdk.wasmSdkId, swiftSdkOptions()])
|
|
110
|
+
const cached = verified.get(key)
|
|
61
111
|
if (cached) return cached
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
68
|
-
})
|
|
69
|
-
: ''
|
|
70
|
-
if (!version.includes(`(${swiftCompilerRelease(release)})`)) {
|
|
71
|
-
const found = version
|
|
72
|
-
? `found ${version.split('\n')[0]?.trim()} at ${swift}`
|
|
73
|
-
: process.platform === 'darwin'
|
|
74
|
-
? `found no ${release}.xctoolchain in ~/Library/Developer/Toolchains or /Library/Developer/Toolchains`
|
|
75
|
-
: 'found no swift on PATH'
|
|
112
|
+
let bin: string
|
|
113
|
+
try {
|
|
114
|
+
bin = swiftCompiler(release)
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
76
117
|
throw new Error(
|
|
77
|
-
`
|
|
118
|
+
`Swift compiler ${release} is unavailable or differs from its pin: ${reason}\n${swiftInstallSteps(release, sdk)}`,
|
|
78
119
|
)
|
|
79
120
|
}
|
|
80
|
-
const
|
|
121
|
+
const swift = path.join(bin, 'swift')
|
|
122
|
+
const sdks = execFileSync(swift, ['sdk', 'list', ...swiftSdkOptions()], {
|
|
81
123
|
encoding: 'utf8',
|
|
82
124
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
83
125
|
})
|
|
@@ -86,15 +128,99 @@ export function swiftToolchain(release: string, sdk: SwiftWasmSdk): string {
|
|
|
86
128
|
`peach compiles Swift with the ${sdk.wasmSdkId} SDK, which ${swift} does not have.\n${swiftInstallSteps(release, sdk)}`,
|
|
87
129
|
)
|
|
88
130
|
}
|
|
89
|
-
verified.set(
|
|
131
|
+
verified.set(key, bin)
|
|
90
132
|
return bin
|
|
91
133
|
}
|
|
92
134
|
|
|
93
|
-
|
|
135
|
+
// stream large compiler binaries without retaining a second copy in memory.
|
|
136
|
+
export function swiftFileChecksum(file: string): string {
|
|
137
|
+
const hash = createHash('sha256')
|
|
138
|
+
const fd = fs.openSync(file, 'r')
|
|
139
|
+
const buffer = Buffer.allocUnsafe(1024 * 1024)
|
|
140
|
+
try {
|
|
141
|
+
let size = fs.readSync(fd, buffer, 0, buffer.length, null)
|
|
142
|
+
while (size > 0) {
|
|
143
|
+
hash.update(buffer.subarray(0, size))
|
|
144
|
+
size = fs.readSync(fd, buffer, 0, buffer.length, null)
|
|
145
|
+
}
|
|
146
|
+
} finally {
|
|
147
|
+
fs.closeSync(fd)
|
|
148
|
+
}
|
|
149
|
+
return hash.digest('hex')
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** validate the pinned manifest and every replaced binary, independently of --version. */
|
|
153
|
+
export function verifySwiftHostCompiler(release: string, root: string): void {
|
|
154
|
+
const pin = swiftHostCompilerArchive(release)
|
|
155
|
+
const file = path.join(root, 'compiler.json')
|
|
156
|
+
if (swiftFileChecksum(file) !== pin.manifest)
|
|
157
|
+
throw new Error(`Swift compiler manifest mismatch at ${root}`)
|
|
158
|
+
const manifest: unknown = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
159
|
+
if (
|
|
160
|
+
!manifest ||
|
|
161
|
+
typeof manifest !== 'object' ||
|
|
162
|
+
!('identity' in manifest) ||
|
|
163
|
+
manifest.identity !== pin.identity ||
|
|
164
|
+
!('host' in manifest) ||
|
|
165
|
+
manifest.host !== `${process.platform}-${process.arch}` ||
|
|
166
|
+
!('files' in manifest) ||
|
|
167
|
+
!manifest.files ||
|
|
168
|
+
typeof manifest.files !== 'object'
|
|
169
|
+
) {
|
|
170
|
+
throw new Error(`Swift compiler identity mismatch at ${root}`)
|
|
171
|
+
}
|
|
172
|
+
const files = Object.entries(manifest.files)
|
|
173
|
+
if (files.length !== 15) throw new Error('incomplete Swift compiler manifest')
|
|
174
|
+
for (const [relative, checksum] of files) {
|
|
175
|
+
if (
|
|
176
|
+
relative.startsWith('/') ||
|
|
177
|
+
relative.split('/').includes('..') ||
|
|
178
|
+
typeof checksum !== 'string' ||
|
|
179
|
+
swiftFileChecksum(path.join(root, relative)) !== checksum
|
|
180
|
+
) {
|
|
181
|
+
throw new Error(`Swift compiler binary mismatch: ${relative}`)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const verifiedCompilers = new Map<string, string>()
|
|
187
|
+
/** select the actual compiler, including its patched identity, before consulting SDKs. */
|
|
188
|
+
export function swiftCompiler(release: string): string {
|
|
189
|
+
const cached = verifiedCompilers.get(release)
|
|
190
|
+
if (cached) return cached
|
|
191
|
+
const bin = swiftToolchainBin(release)
|
|
192
|
+
if (release.includes('-custom-'))
|
|
193
|
+
verifySwiftHostCompiler(release, path.resolve(bin, '../..'))
|
|
194
|
+
const version = execFileSync(path.join(bin, 'swift'), ['--version'], {
|
|
195
|
+
encoding: 'utf8',
|
|
196
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
197
|
+
})
|
|
198
|
+
if (!version.includes(`(${swiftCompilerRelease(release)})`))
|
|
199
|
+
throw new Error(`compiler release mismatch at ${bin}`)
|
|
200
|
+
verifiedCompilers.set(release, bin)
|
|
201
|
+
return bin
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** the commands that install the pinned compiler and SDK on this host. */
|
|
94
205
|
export function swiftInstallSteps(release: string, wasmSdk: SwiftWasmSdk): string {
|
|
206
|
+
const sdkOptions = swiftSdkOptions()
|
|
207
|
+
.map((arg) => ` '${arg.replaceAll("'", "'\\''")}'`)
|
|
208
|
+
.join('')
|
|
209
|
+
if (release.includes('-custom-')) {
|
|
210
|
+
const archive = swiftHostCompilerArchive(release)
|
|
211
|
+
const directory = path.resolve(swiftToolchainBin(release), '../..')
|
|
212
|
+
return [
|
|
213
|
+
'install the pinned compiler and SDK:',
|
|
214
|
+
` curl -fsSL ${archive.url} -o compiler.tar.gz`,
|
|
215
|
+
` echo '${archive.checksum} compiler.tar.gz' | shasum -a 256 -c -`,
|
|
216
|
+
` mkdir -p '${directory}'`,
|
|
217
|
+
` tar -xzf compiler.tar.gz --strip-components=1 -C '${directory}'`,
|
|
218
|
+
` '${directory}/usr/bin/swift' sdk install ${wasmSdk.wasmSdkUrl} --checksum ${wasmSdk.wasmSdkChecksum}${sdkOptions}`,
|
|
219
|
+
].join('\n')
|
|
220
|
+
}
|
|
95
221
|
const version = release.replace(/^swift-/, '').toLowerCase()
|
|
96
222
|
const downloads = `https://download.swift.org/swift-${version}`
|
|
97
|
-
const sdk = `swift sdk install ${wasmSdk.wasmSdkUrl} --checksum ${wasmSdk.wasmSdkChecksum}`
|
|
223
|
+
const sdk = `swift sdk install ${wasmSdk.wasmSdkUrl} --checksum ${wasmSdk.wasmSdkChecksum}${sdkOptions}`
|
|
98
224
|
if (process.platform === 'darwin') {
|
|
99
225
|
const swift = `~/Library/Developer/Toolchains/${release}.xctoolchain/usr/bin/swift`
|
|
100
226
|
return [
|