peachsim 0.1.1635 → 0.1.1641

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.
Files changed (142) hide show
  1. package/README.md +10 -1
  2. package/cli/app-config.ts +14 -5
  3. package/cli/app-stubs.ts +96 -22
  4. package/cli/bridge-flow-runner.ts +2 -2
  5. package/cli/cloud-client.ts +60 -40
  6. package/cli/cloud-session.ts +16 -0
  7. package/cli/commands/assert.ts +17 -4
  8. package/cli/commands/box.ts +33 -19
  9. package/cli/commands/doctor.ts +37 -20
  10. package/cli/commands/flow.ts +1 -1
  11. package/cli/commands/inspect/actions.ts +3 -2
  12. package/cli/commands/inspect/core.ts +0 -8
  13. package/cli/commands/inspect/shared.ts +9 -4
  14. package/cli/commands/inspect.ts +65 -61
  15. package/cli/commands/platform.ts +2 -1
  16. package/cli/commands/preview.ts +1 -1
  17. package/cli/commands/record.ts +154 -68
  18. package/cli/commands/swift.ts +18 -4
  19. package/cli/commands/three-mode.ts +4 -38
  20. package/cli/commands/upload.ts +55 -49
  21. package/cli/drivers/playwright-sim-host.ts +65 -42
  22. package/cli/flow-live-status.ts +0 -2
  23. package/cli/main.ts +2 -2
  24. package/cli/outbound-endpoints.ts +7 -5
  25. package/cli/pause-aware-timeout.ts +4 -0
  26. package/cli/ws-bridge.ts +19 -16
  27. package/detox/attempt-events.cjs +99 -6
  28. package/detox/attempt-events.d.cts +7 -0
  29. package/detox/expectations.ts +7 -3
  30. package/detox/index.ts +259 -139
  31. package/detox/jest-environment.cjs +5 -1
  32. package/detox/motion-change.cjs +170 -21
  33. package/detox/motion-change.d.cts +32 -0
  34. package/detox/navigation-lifecycle.ts +35 -3
  35. package/dist-lib/agent-daemon-client.cjs +1 -1
  36. package/dist-lib/agent-events.cjs +1 -1
  37. package/dist-lib/attached-projects.cjs +1 -1
  38. package/dist-lib/auth/shared-session.cjs +1 -1
  39. package/dist-lib/backend-origin.cjs +17 -7
  40. package/dist-lib/beta.cjs +1 -1
  41. package/dist-lib/beta.mjs +1 -1
  42. package/dist-lib/bridge-constants.cjs +1 -1
  43. package/dist-lib/bridge-contract-input.cjs +1 -1
  44. package/dist-lib/bridge-contract-input.mjs +1 -1
  45. package/dist-lib/bridge-contract.cjs +1 -1
  46. package/dist-lib/bridge-contract.mjs +1 -1
  47. package/dist-lib/bundle-channel.cjs +5014 -2268
  48. package/dist-lib/capture-contract.cjs +1 -1
  49. package/dist-lib/capture-contract.mjs +1 -1
  50. package/dist-lib/cloud-contract.cjs +1 -1
  51. package/dist-lib/cloud-contract.mjs +1 -1
  52. package/dist-lib/cloud-test-args.cjs +1 -1
  53. package/dist-lib/cloud-test-args.mjs +1 -1
  54. package/dist-lib/cloud.cjs +1 -1
  55. package/dist-lib/cloud.mjs +1 -1
  56. package/dist-lib/config.cjs +1 -1
  57. package/dist-lib/config.mjs +1 -1
  58. package/dist-lib/detox/index.cjs +1036 -166
  59. package/dist-lib/detox/jest-environment.cjs +5 -1
  60. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  61. package/dist-lib/expo-swift-bundle.cjs +4613 -1963
  62. package/dist-lib/expo-swift-metadata.cjs +9 -7
  63. package/dist-lib/expo-swift-metadata.mjs +9 -7
  64. package/dist-lib/home-paths.cjs +1 -1
  65. package/dist-lib/host/bridge-host.cjs +58072 -16400
  66. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  67. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  68. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  69. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  70. package/dist-lib/host/websocket-proxy.cjs +1 -1
  71. package/dist-lib/index.cjs +2790 -143
  72. package/dist-lib/jump-to-source-babel.cjs +1 -1
  73. package/dist-lib/jump-to-source-native.cjs +1 -1
  74. package/dist-lib/kotlin-host.cjs +1 -1
  75. package/dist-lib/menu.cjs +1 -1
  76. package/dist-lib/menu.mjs +1 -1
  77. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  78. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  79. package/dist-lib/metro-production-bundle.cjs +1 -1
  80. package/dist-lib/metro-production-bundle.mjs +1 -1
  81. package/dist-lib/metro.cjs +2579 -95
  82. package/dist-lib/native-app-identity-project.cjs +243 -53
  83. package/dist-lib/native-app-identity-project.mjs +243 -53
  84. package/dist-lib/native-app-identity.cjs +29 -30
  85. package/dist-lib/native-app-identity.mjs +29 -30
  86. package/dist-lib/native-firebase-metadata.cjs +1 -1
  87. package/dist-lib/native-firebase-metadata.mjs +1 -1
  88. package/dist-lib/plist.cjs +1 -1
  89. package/dist-lib/plist.mjs +1 -1
  90. package/dist-lib/profiles.cjs +1 -1
  91. package/dist-lib/public-brand.cjs +1 -1
  92. package/dist-lib/react-native-host-modules.cjs +2 -2
  93. package/dist-lib/react-native-host-modules.mjs +2 -2
  94. package/dist-lib/scripts/dev-server-scanner.cjs +8 -6
  95. package/dist-lib/sdk.cjs +4 -3
  96. package/dist-lib/sdk.mjs +4 -3
  97. package/dist-lib/skills.cjs +66475 -23097
  98. package/dist-lib/swift-compile.cjs +452 -260
  99. package/dist-lib/swift-compile.mjs +451 -252
  100. package/dist-lib/swift-package.cjs +1 -1
  101. package/dist-lib/swift-package.mjs +1 -1
  102. package/dist-lib/swift-submit.cjs +14 -7
  103. package/dist-lib/swift-submit.mjs +14 -7
  104. package/dist-lib/swift-toolchain.cjs +316 -41
  105. package/dist-lib/swift.cjs +1 -1
  106. package/dist-lib/vite-swift.cjs +8188 -5636
  107. package/dist-lib/vite.cjs +2857 -12
  108. package/dist-lib/worklet-executable.cjs +14 -2
  109. package/dist-lib/worklet-executable.mjs +14 -2
  110. package/package.json +1 -1
  111. package/src/backend-origin.ts +21 -6
  112. package/src/expo-swift-host.ts +5 -2
  113. package/src/expoKotlinContract.ts +4 -7
  114. package/src/expoSwiftContract.ts +4 -6
  115. package/src/host/staged-host-files.ts +9 -0
  116. package/src/native-app-identity-project.ts +1 -4
  117. package/src/native-app-identity.ts +1 -4
  118. package/src/nativeAppIconContract.ts +1 -4
  119. package/src/output-lock-stdio.ts +36 -0
  120. package/src/react-native-bridge-modules.ts +106 -78
  121. package/src/react-native-host-modules.ts +4 -1
  122. package/src/settings-bundle.ts +1 -4
  123. package/src/swift-compile.ts +224 -139
  124. package/src/swift-distribution.lock.json +23 -12
  125. package/src/swift-distribution.ts +103 -4
  126. package/src/swift-host.ts +95 -30
  127. package/src/swift-icu.ts +16 -10
  128. package/src/swift-objc-compile.ts +547 -0
  129. package/src/swift-objc-metadata.ts +204 -0
  130. package/src/swift-objc-sdk.ts +883 -19
  131. package/src/swift-objc-standin.ts +126 -14
  132. package/src/swift-package-manifest.ts +42 -1
  133. package/src/swift-packages.ts +35 -21
  134. package/src/swift-root-lock.ts +153 -0
  135. package/src/swift-standin-emit.ts +40 -7
  136. package/src/swift-standins.ts +404 -138
  137. package/src/swift-submit.ts +18 -7
  138. package/src/swift-toolchain.ts +378 -46
  139. package/src/swiftContract.ts +12 -0
  140. package/src/worker-system-chunks.ts +11 -12
  141. package/src/worklet-executable.ts +19 -1
  142. package/src/xcode-project.ts +280 -33
@@ -33,7 +33,8 @@ import {
33
33
  swiftTargetModuleName,
34
34
  type SwiftPackageTarget,
35
35
  } from './swift-package'
36
- import { swiftSdkOptions, type SwiftWasmSdk } from './swift-toolchain'
36
+ import { withSwiftRootLock } from './swift-root-lock'
37
+ import { swiftEnvironment, swiftSdkOptions, type SwiftWasmSdk } from './swift-toolchain'
37
38
  import { isSwiftResourceBundles } from './swiftContract'
38
39
  import type { SwiftImageUpload } from './swift-submit'
39
40
  import type { SwiftResourceBundle } from './swiftContract'
@@ -42,17 +43,21 @@ export { swiftIcuAsset, type SwiftIcuAsset }
42
43
 
43
44
  // compiler drivers own descendants such as admission and swiftpm workers.
44
45
  // cancellation waits for their pipes to close before releasing the build root.
46
+ // `stream` echoes the output as it arrives: all of it, or only matching lines.
47
+ // a successful run then echoes the rest minus lines matching `quiet`, its
48
+ // warnings; a failed run's output goes to the caller's one diagnostic.
45
49
  async function runCompiler(
46
50
  command: string,
47
51
  args: string[],
48
52
  options: ExecFileOptions & { signal?: AbortSignal },
49
- stream = false,
53
+ stream: boolean | RegExp = false,
54
+ quiet?: RegExp,
50
55
  ): Promise<void> {
51
56
  const { signal } = options
52
57
  signal?.throwIfAborted()
53
58
  const child = spawn(command, args, {
54
59
  cwd: options.cwd,
55
- env: options.env,
60
+ env: swiftEnvironment(options.env),
56
61
  detached: true,
57
62
  stdio: ['ignore', 'pipe', 'pipe'],
58
63
  })
@@ -63,6 +68,7 @@ async function runCompiler(
63
68
  let timeout: ReturnType<typeof setTimeout> | undefined
64
69
  const chunks: Record<'stdout' | 'stderr', Buffer[]> = { stdout: [], stderr: [] }
65
70
  const sizes = { stdout: 0, stderr: 0 }
71
+ const partial = { stdout: '', stderr: '' }
66
72
  const stop = () => {
67
73
  stopping ??= terminateProcessGroup(child)
68
74
  // close and cancellation share the same awaited cleanup below.
@@ -70,7 +76,13 @@ async function runCompiler(
70
76
  }
71
77
  for (const name of ['stdout', 'stderr'] as const) {
72
78
  child[name].on('data', (bytes: Buffer) => {
73
- if (stream) process[name].write(bytes)
79
+ if (stream === true) process[name].write(bytes)
80
+ else if (stream) {
81
+ const lines = (partial[name] + bytes.toString()).split('\n')
82
+ partial[name] = lines.pop()!
83
+ for (const line of lines)
84
+ if (stream.test(line)) process[name].write(`${line}\n`)
85
+ }
74
86
  sizes[name] += bytes.length
75
87
  if (sizes[name] <= (options.maxBuffer ?? 1024 * 1024)) chunks[name].push(bytes)
76
88
  else {
@@ -102,7 +114,13 @@ async function runCompiler(
102
114
  },
103
115
  ),
104
116
  )
105
- else resolve()
117
+ else {
118
+ if (quiet)
119
+ for (const name of ['stdout', 'stderr'] as const)
120
+ for (const line of Buffer.concat(chunks[name]).toString().split('\n'))
121
+ if (line && !quiet.test(line)) process[name].write(`${line}\n`)
122
+ resolve()
123
+ }
106
124
  })
107
125
  if (options.timeout)
108
126
  timeout = setTimeout(() => {
@@ -118,6 +136,14 @@ async function runCompiler(
118
136
 
119
137
  const WASM_TRIPLE = 'wasm32-unknown-wasip1'
120
138
 
139
+ // swiftpm's step counter, echoed while a build runs; its diagnostics print
140
+ // once, with the failure.
141
+ const SWIFTPM_PROGRESS = /^\[\d+\/\d+\] /
142
+ // lines that are not diagnostics: progress, already echoed, and the notice
143
+ // that the native build system peach selects is deprecated.
144
+ const SWIFTPM_NOISE =
145
+ /^(?:\[\d+\/\d+\] |Building for production\.\.\.$|warning: '--build-system native' has been deprecated)/
146
+
121
147
  // compiler jobs match the fixture builder's cap to fit a 16GiB Linux slot.
122
148
  const BUILD_JOBS = String(
123
149
  Math.min(4, Math.max(1, Math.floor(os.availableParallelism() / 2))),
@@ -153,6 +179,8 @@ export interface SwiftCompileOptions {
153
179
  toolchainBin: string
154
180
  timeoutMs?: number
155
181
  signal?: AbortSignal
182
+ /** called as the compile reaches each stage, in addition to the stderr line. */
183
+ onStage?: (stage: string) => void
156
184
  }
157
185
 
158
186
  export interface SwiftCompileArtifact {
@@ -212,6 +240,10 @@ export function swiftModuleInputFiles(root: string): string[] {
212
240
  'scripts/contrast-app-Package.swift',
213
241
  'scripts/build-distribution.ts',
214
242
  'scripts/distribution-clang.ts',
243
+ 'scripts/distribution-libxml2.ts',
244
+ 'scripts/distribution-libxml2.json',
245
+ 'Sources/libxml2/include/module.modulemap',
246
+ 'Sources/libxml2/COPYING',
215
247
  'scripts/build-distribution-plugins.sh',
216
248
  'scripts/build-distribution-plugins-docker.sh',
217
249
  'scripts/build-preview-plugin.sh',
@@ -234,12 +266,8 @@ export function swiftModuleInputFiles(root: string): string[] {
234
266
  return files.sort()
235
267
  }
236
268
 
237
- // the host halves of the module's macros: the rnx plugin (#Preview, @Entry,
238
- // @Model) and #Predicate's FoundationMacros stand-in, which one script builds
239
- // side by side. manifest swiftSettings cannot load a plugin library (RAN: the
240
- // flag reaches the driver but the plugin never loads), so every build loads
241
- // both with -Xswiftc, as scripts/build.sh does for the fixtures. their
242
- // sources are under Sources/, which the artifact hash already covers.
269
+ // the host macro plugins build side by side and load explicitly for every
270
+ // app compile. their source inputs also participate in artifact identity.
243
271
  /** the host macro plugin libraries a module root compiles with, and whether a
244
272
  * checkout's must be rebuilt (scripts/build-preview-plugin.sh) first. */
245
273
  export function swiftMacroPlugins(moduleRoot: string): {
@@ -262,11 +290,21 @@ export function swiftMacroPlugins(moduleRoot: string): {
262
290
  const plugins = [
263
291
  {
264
292
  library: path.join(dir, `libRnxPreviewMacros.${ext}`),
265
- source: path.join(moduleRoot, 'Sources/RnxPreviewMacros/PreviewMacro.swift'),
293
+ sources: [path.join(moduleRoot, 'Sources/RnxPreviewMacros/PreviewMacro.swift')],
266
294
  },
267
295
  {
268
296
  library: path.join(dir, `libFoundationMacros.${ext}`),
269
- source: path.join(moduleRoot, 'Sources/FoundationMacros/PredicateMacro.swift'),
297
+ sources: [
298
+ path.join(moduleRoot, 'Sources/FoundationMacros/PredicateMacro.swift'),
299
+ path.join(moduleRoot, 'Sources/SwiftMacroSupport/PredicateExpression.swift'),
300
+ ],
301
+ },
302
+ {
303
+ library: path.join(dir, `libTipKitMacros.${ext}`),
304
+ sources: [
305
+ path.join(moduleRoot, 'Sources/TipKitMacros/TipKitMacros.swift'),
306
+ path.join(moduleRoot, 'Sources/SwiftMacroSupport/PredicateExpression.swift'),
307
+ ],
270
308
  },
271
309
  ]
272
310
  return {
@@ -275,8 +313,9 @@ export function swiftMacroPlugins(moduleRoot: string): {
275
313
  !existsSync(compilerStamp) ||
276
314
  readFileSync(compilerStamp, 'utf8').trim() !== release ||
277
315
  plugins.some(
278
- ({ library, source }) =>
279
- !existsSync(library) || statSync(source).mtimeMs > statSync(library).mtimeMs,
316
+ ({ library, sources }) =>
317
+ !existsSync(library) ||
318
+ sources.some((source) => statSync(source).mtimeMs > statSync(library).mtimeMs),
280
319
  ),
281
320
  }
282
321
  }
@@ -342,6 +381,16 @@ export function swiftModuleDigest(root: string): Buffer {
342
381
  return digest
343
382
  }
344
383
 
384
+ // optimized consumers can reference private symbols from an imported framework.
385
+ // source revisions need separate object trees, while app edits keep one warm tree.
386
+ export function swiftProjectBuildKey(moduleRoot: string, release: string): string {
387
+ return createHash('sha256')
388
+ .update(`${release}\0${swiftModuleSdk(moduleRoot).wasmSdkId}`)
389
+ .update(swiftModuleDigest(moduleRoot))
390
+ .digest('hex')
391
+ .slice(0, 32)
392
+ }
393
+
345
394
  export function compileTargets(input: SwiftCompileInput): SwiftPackageTarget[] {
346
395
  const manifest = input.files['Package.swift']
347
396
  return manifest === undefined
@@ -384,11 +433,13 @@ const OPTIONAL_FRAMEWORK_DEPENDENCIES: Record<string, string[]> = {
384
433
  Accelerate: [],
385
434
  CryptoKit: [],
386
435
  CommonCrypto: [],
436
+ ImagePlayground: [],
437
+ QuickLookThumbnailing: [],
438
+ libxml2: [],
387
439
  CoreText: [],
388
440
  Compression: ['PeachCodec'],
389
441
  zlib: ['PeachCodec'],
390
442
  PeachCodec: [],
391
- Security: ['CryptoKit'],
392
443
  TikTokBusinessSDK: [],
393
444
  nSure: [],
394
445
  Statsig: [],
@@ -569,7 +620,7 @@ export function swiftSdkPaths(
569
620
  sdk,
570
621
  'wasm32-unknown-wasip1',
571
622
  ],
572
- { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] },
623
+ { encoding: 'utf8', env: swiftEnvironment(), stdio: ['ignore', 'pipe', 'pipe'] },
573
624
  )
574
625
  const field = (name: string) => {
575
626
  const value = new RegExp(`^${name}:\\s*(.+)$`, 'm').exec(configuration)?.[1]?.trim()
@@ -900,9 +951,10 @@ export function emitSwiftPackageManifest(args: {
900
951
  // compiled: whole, and ahead of the sdk libraries, so PeachICU's
901
952
  // reservation keeps icu's data member out. merged into one relocatable
902
953
  // object (wasm-ld -r) or linked from an archive, a protocol conformance
903
- // goes unfound at runtime or icu links twice (RAN, the Expo fixture). the
904
- // libraries the objects autolink follow, since the driver reads autolink
905
- // entries only from objects it compiled.
954
+ // goes unfound at runtime or icu links twice (RAN, the Expo fixture).
955
+ // clang loads configuration inputs before command-line libraries. forward
956
+ // the file opaquely so swift neither expands it nor scans every framework
957
+ // object for autolinks; distribution.link supplies those libraries.
906
958
  const imports = distribution
907
959
  ? `, "-I", ${JSON.stringify(path.join(moduleRoot, 'modules'))}`
908
960
  : ''
@@ -946,7 +998,7 @@ export function emitSwiftPackageManifest(args: {
946
998
  ].join(', ')
947
999
  const library =
948
1000
  distribution && distributionLink
949
- ? ['-Xlinker', `@${distributionLink.path}`, ...distribution.link]
1001
+ ? ['-Xclang-linker', `--config=${distributionLink.path}`, ...distribution.link]
950
1002
  .map((flag) => `, ${JSON.stringify(flag)}`)
951
1003
  .join('')
952
1004
  : ''
@@ -1636,25 +1688,32 @@ function objcRootedClasses(sources: string[]): Set<string> {
1636
1688
  // the header swift emits on iOS keeps an Objective-C class out of its C++
1637
1689
  // section. here its root is a swift class from a module with no C++ header,
1638
1690
  // so C++ that includes the header fails on the undeclared base. a top-level
1639
- // class in `rooted` gains @_expose(!Cxx) in front of its declaration,
1640
- // shifting that one line's columns. swift rejects the attribute in a local
1691
+ // class in `rooted` gains @_expose(!Cxx), keeping @main first so SwiftPM
1692
+ // recognizes the entry without changing source lines. swift rejects it in a local
1641
1693
  // scope, so a nested class keeps its exposure.
1642
1694
  function hideObjCClassesFromCxx(source: string, rooted: Set<string>): string {
1643
1695
  if (rooted.size === 0) return source
1644
1696
  const code = swiftCodeMask(source)
1645
- const starts: number[] = []
1697
+ const insertions: { at: number; text: string }[] = []
1646
1698
  let depth = 0
1647
1699
  for (const match of code.matchAll(
1648
1700
  /[{}]|\bclass\s+(?!(?:func|var|let|subscript)\b)([A-Za-z_]\w*)/g,
1649
1701
  )) {
1650
1702
  if (match[0] === '{') depth++
1651
1703
  else if (match[0] === '}') depth--
1652
- else if (depth === 0 && rooted.has(match[1]!))
1653
- starts.push(declarationStart(code, match.index, 0))
1704
+ else if (depth === 0 && rooted.has(match[1]!)) {
1705
+ const start = declarationStart(code, match.index, 0)
1706
+ const main = /@main\b/.exec(code.slice(start, match.index))
1707
+ insertions.push(
1708
+ main
1709
+ ? { at: start + main.index + main[0].length, text: ' @_expose(!Cxx)' }
1710
+ : { at: start, text: '@_expose(!Cxx) ' },
1711
+ )
1712
+ }
1654
1713
  }
1655
1714
  let out = source
1656
- for (const at of starts.reverse())
1657
- out = `${out.slice(0, at)}@_expose(!Cxx) ${out.slice(at)}`
1715
+ for (const { at, text } of insertions.reverse())
1716
+ out = `${out.slice(0, at)}${text}${out.slice(at)}`
1658
1717
  return out
1659
1718
  }
1660
1719
 
@@ -5952,6 +6011,7 @@ function projectDiagnostic(
5952
6011
  const prefix = `${base}${path.sep}`
5953
6012
  return designTimeDiagnostic(output, files)
5954
6013
  .split('\n')
6014
+ .filter((line) => !SWIFTPM_NOISE.test(line))
5955
6015
  .map((line) => (line.startsWith(prefix) ? line.slice(prefix.length) : line))
5956
6016
  .join('\n')
5957
6017
  .trim()
@@ -6093,8 +6153,10 @@ export function compileSwiftProjectUnit(
6093
6153
  }
6094
6154
  const hash = swiftArtifactHash(input, options.release, moduleRoot)
6095
6155
  const sharedRoot = path.join(rnxHomeDir(), 'cache', 'swift-projects', hash)
6096
- const report = (message: string) =>
6156
+ const report = (message: string) => {
6097
6157
  console.error(`[swift-project ${hash.slice(0, 16)}] ${message}`)
6158
+ options.onStage?.(message)
6159
+ }
6098
6160
  report('checking verified artifacts')
6099
6161
  return serialize(
6100
6162
  root,
@@ -6133,13 +6195,9 @@ export function compileSwiftProjectUnit(
6133
6195
  hash,
6134
6196
  release: options.release,
6135
6197
  timeoutMs: options.timeoutMs,
6136
- // the builder's swiftpm tree holds the sootsim-swift objects, which
6137
- // depend on the toolchain and sdk and not on the caller's checkout
6138
- // path, so every caller shares one warm tree per toolchain.
6139
- buildKey: createHash('sha256')
6140
- .update(`${options.release}\0${swiftModuleSdk(moduleRoot).wasmSdkId}`)
6141
- .digest('hex')
6142
- .slice(0, 32),
6198
+ // framework sources and compiler inputs own the shared object tree;
6199
+ // unrelated app edits reuse it without retaining stale private ABI.
6200
+ buildKey: swiftProjectBuildKey(moduleRoot, options.release),
6143
6201
  }),
6144
6202
  )
6145
6203
  try {
@@ -6180,113 +6238,140 @@ export function compileSwiftProjectUnit(
6180
6238
  rmSync(requestRoot, { recursive: true, force: true })
6181
6239
  }
6182
6240
  }
6183
- writeSwiftProject(layout, input, moduleRoot)
6184
- const swift = path.join(options.toolchainBin, 'swift')
6185
- if (!existsSync(swift)) {
6186
- throw new Error(
6187
- `swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`,
6188
- )
6189
- }
6190
- report('preparing compiler plugins')
6191
- const macroPlugins = await ensureMacroPlugins(
6192
- moduleRoot,
6193
- options.toolchainBin,
6194
- options.release,
6195
- options.signal,
6196
- )
6197
- // memoized per toolchain, so only a process's first build waits on it,
6198
- // and that one reads and gzips it while swift builds
6199
- const sdk = swiftModuleSdk(moduleRoot).wasmSdkId
6200
- const icu = swiftIcuAsset(options.toolchainBin, sdk)
6201
- const buildArgs = [
6202
- 'build',
6203
- ...swiftPackageCacheOptions(),
6204
- '--build-system',
6205
- 'native',
6206
- '-j',
6207
- BUILD_JOBS,
6208
- '--package-path',
6241
+ // the root's sources, manifest and executable are shared by every process
6242
+ // using it, so one process writes, builds and reads them at a time.
6243
+ return withSwiftRootLock(
6209
6244
  root,
6210
- ...swiftSdkOptions(),
6211
- '--swift-sdk',
6212
- sdk,
6213
- '-c',
6214
- 'release',
6215
- '-Xswiftc',
6216
- '-Osize',
6217
- '-Xswiftc',
6218
- '-num-threads',
6219
- '-Xswiftc',
6220
- BUILD_JOBS,
6221
- ...macroPlugins.flatMap((plugin) => [
6222
- '-Xswiftc',
6223
- '-load-plugin-library',
6224
- '-Xswiftc',
6225
- plugin,
6226
- ]),
6227
- ]
6228
- const buildOptions = {
6229
- env: {
6230
- ...process.env,
6231
- // shipped host plugins resolve against the selected compiler's runtime.
6232
- ...(process.platform === 'linux'
6233
- ? {
6234
- LD_LIBRARY_PATH: [
6235
- path.resolve(options.toolchainBin, '../lib/swift/linux'),
6236
- path.resolve(options.toolchainBin, '../lib/swift/host'),
6237
- process.env.LD_LIBRARY_PATH,
6238
- ]
6239
- .filter(Boolean)
6240
- .join(':'),
6241
- }
6242
- : {}),
6243
- },
6244
- maxBuffer: 64 * 1024 * 1024,
6245
- timeout: options.timeoutMs,
6246
- signal: options.signal,
6247
- }
6248
- report('compiling and linking Swift modules')
6249
- try {
6250
- await runCompiler(swift, buildArgs, buildOptions, true)
6251
- } catch (error) {
6252
- const output = outputOf(error)
6253
- const moduleCache = path.join(
6254
- root,
6255
- '.build',
6256
- WASM_TRIPLE,
6257
- 'release',
6258
- 'ModuleCache',
6259
- )
6260
- if (
6261
- output.includes('was compiled with module cache path') &&
6262
- existsSync(moduleCache)
6263
- ) {
6264
- rmSync(moduleCache, { recursive: true, force: true })
6265
- try {
6266
- await runCompiler(swift, buildArgs, buildOptions, true)
6267
- } catch (retryError) {
6245
+ async () => {
6246
+ // a process that held the root while this one waited may have built
6247
+ // this exact address.
6248
+ const built = readCompiledArtifact(path.join(sharedRoot, 'artifact'), hash)
6249
+ if (built) {
6250
+ report('reusing verified disk artifact')
6251
+ return retain(root, built)
6252
+ }
6253
+ writeSwiftProject(layout, input, moduleRoot)
6254
+ const swift = path.join(options.toolchainBin, 'swift')
6255
+ if (!existsSync(swift)) {
6268
6256
  throw new Error(
6269
- projectDiagnostic(outputOf(retryError), layout, input.files),
6270
- {
6271
- cause: retryError,
6272
- },
6257
+ `swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`,
6273
6258
  )
6274
6259
  }
6275
- } else {
6276
- throw new Error(projectDiagnostic(output, layout, input.files), {
6277
- cause: error,
6278
- })
6279
- }
6280
- }
6281
- const artifact = {
6282
- hash,
6283
- bytes: readFileSync(builtArtifact(layout)),
6284
- icu: await icu,
6285
- }
6286
- saveCompiledArtifact(root, artifact)
6287
- saveCompiledArtifact(sharedRoot, artifact)
6288
- report('compiled artifact verified')
6289
- return retain(root, artifact)
6260
+ report('preparing compiler plugins')
6261
+ const macroPlugins = await ensureMacroPlugins(
6262
+ moduleRoot,
6263
+ options.toolchainBin,
6264
+ options.release,
6265
+ options.signal,
6266
+ )
6267
+ // memoized per toolchain, so only a process's first build waits on it,
6268
+ // and that one reads and gzips it while swift builds
6269
+ const sdk = swiftModuleSdk(moduleRoot).wasmSdkId
6270
+ const icu = swiftIcuAsset(options.toolchainBin, sdk)
6271
+ const buildArgs = [
6272
+ 'build',
6273
+ ...swiftPackageCacheOptions(),
6274
+ '--build-system',
6275
+ 'native',
6276
+ '-j',
6277
+ BUILD_JOBS,
6278
+ '--package-path',
6279
+ root,
6280
+ ...swiftSdkOptions(),
6281
+ '--swift-sdk',
6282
+ sdk,
6283
+ '-c',
6284
+ 'release',
6285
+ '-Xswiftc',
6286
+ '-Osize',
6287
+ '-Xswiftc',
6288
+ '-num-threads',
6289
+ '-Xswiftc',
6290
+ BUILD_JOBS,
6291
+ ...macroPlugins.flatMap((plugin) => [
6292
+ '-Xswiftc',
6293
+ '-load-plugin-library',
6294
+ '-Xswiftc',
6295
+ plugin,
6296
+ ]),
6297
+ ]
6298
+ const buildOptions = {
6299
+ env: {
6300
+ ...process.env,
6301
+ // shipped host plugins resolve against the selected compiler's runtime.
6302
+ ...(process.platform === 'linux'
6303
+ ? {
6304
+ LD_LIBRARY_PATH: [
6305
+ path.resolve(options.toolchainBin, '../lib/swift/linux'),
6306
+ path.resolve(options.toolchainBin, '../lib/swift/host'),
6307
+ process.env.LD_LIBRARY_PATH,
6308
+ ]
6309
+ .filter(Boolean)
6310
+ .join(':'),
6311
+ }
6312
+ : {}),
6313
+ },
6314
+ maxBuffer: 64 * 1024 * 1024,
6315
+ timeout: options.timeoutMs,
6316
+ signal: options.signal,
6317
+ }
6318
+ report('compiling and linking Swift modules')
6319
+ try {
6320
+ await runCompiler(
6321
+ swift,
6322
+ buildArgs,
6323
+ buildOptions,
6324
+ SWIFTPM_PROGRESS,
6325
+ SWIFTPM_NOISE,
6326
+ )
6327
+ } catch (error) {
6328
+ const output = outputOf(error)
6329
+ const moduleCache = path.join(
6330
+ root,
6331
+ '.build',
6332
+ WASM_TRIPLE,
6333
+ 'release',
6334
+ 'ModuleCache',
6335
+ )
6336
+ if (
6337
+ output.includes('was compiled with module cache path') &&
6338
+ existsSync(moduleCache)
6339
+ ) {
6340
+ rmSync(moduleCache, { recursive: true, force: true })
6341
+ try {
6342
+ await runCompiler(
6343
+ swift,
6344
+ buildArgs,
6345
+ buildOptions,
6346
+ SWIFTPM_PROGRESS,
6347
+ SWIFTPM_NOISE,
6348
+ )
6349
+ } catch (retryError) {
6350
+ throw new Error(
6351
+ projectDiagnostic(outputOf(retryError), layout, input.files),
6352
+ {
6353
+ cause: retryError,
6354
+ },
6355
+ )
6356
+ }
6357
+ } else {
6358
+ throw new Error(projectDiagnostic(output, layout, input.files), {
6359
+ cause: error,
6360
+ })
6361
+ }
6362
+ }
6363
+ const artifact = {
6364
+ hash,
6365
+ bytes: readFileSync(builtArtifact(layout)),
6366
+ icu: await icu,
6367
+ }
6368
+ saveCompiledArtifact(root, artifact)
6369
+ saveCompiledArtifact(sharedRoot, artifact)
6370
+ report('compiled artifact verified')
6371
+ return retain(root, artifact)
6372
+ },
6373
+ options.signal,
6374
+ )
6290
6375
  },
6291
6376
  options.signal,
6292
6377
  )
@@ -1,11 +1,15 @@
1
1
  {
2
- "id": "4fdcd218fa180b52",
3
- "release": "swift-6.4.0-RELEASE-custom-91504a66b3f012ac",
4
- "wasmSdkId": "swift-6.4.0-RELEASE_wasm-peach-7fd9a101",
5
- "wasmSdkUrl": "https://r2.sootsim.com/swift-wasm-sdk/swift-6.4.0-RELEASE_wasm-peach-7fd9a101.artifactbundle.tar.gz",
6
- "wasmSdkChecksum": "72f7fec1d090d142d26148d6cc0cd5b1ce78da70bb97bd577dc1482eaf0299b2",
7
- "source": "80c26dea3c4bbf0e29458c33a3a0e856b0942564",
2
+ "id": "e8dd3a9ff9c4dc74",
3
+ "release": "swift-6.4.0-RELEASE-custom-0d775d32d7c74eae",
4
+ "wasmSdkId": "swift-6.4.0-RELEASE_wasm-peach-21f60db0",
5
+ "wasmSdkUrl": "https://r2.sootsim.com/swift-wasm-sdk/swift-6.4.0-RELEASE_wasm-peach-21f60db0.artifactbundle.tar.gz",
6
+ "wasmSdkChecksum": "7b7573fd23120549fc928581a42968676f5f00f9ef63e5618032a6928a724e16",
7
+ "source": "693296741f3865605388c21ee7e220cb0b6ccaa3",
8
8
  "targets": [
9
+ "ImagePlayground",
10
+ "QuickLookThumbnailing",
11
+ "libxml2",
12
+ "CarPlay",
9
13
  "System",
10
14
  "_LocationEssentials",
11
15
  "GeoToolbox",
@@ -42,6 +46,7 @@
42
46
  "Darwin",
43
47
  "MachO",
44
48
  "ObjectiveC",
49
+ "PeachObjCRuntime",
45
50
  "PeachObjC",
46
51
  "UIUtilities",
47
52
  "UIKitCore",
@@ -56,6 +61,7 @@
56
61
  "DeviceCheck",
57
62
  "PassKit",
58
63
  "Translation",
64
+ "TipKit",
59
65
  "CoreSpotlight",
60
66
  "CoreVideo",
61
67
  "CoreMedia",
@@ -139,7 +145,12 @@
139
145
  "FoundationModels",
140
146
  "CoreTransferable",
141
147
  "AudioToolbox",
148
+ "CoreAudioTypes",
149
+ "AudioUnit",
142
150
  "Intents",
151
+ "IntentsUI",
152
+ "WatchConnectivity",
153
+ "CoreServices",
143
154
  "MobileCoreServices",
144
155
  "ImageIO",
145
156
  "CoreLocationEnums",
@@ -181,16 +192,16 @@
181
192
  },
182
193
  "hosts": {
183
194
  "darwin-arm64": {
184
- "sha256": "2b6768539f39bbdc2d77447fc91b00e9a7ee2d9ed732ea10e67a7b05c1c854ea",
185
- "size": 69899802
195
+ "sha256": "0e06928cd63077f30226a27b2a3e92e89bdcaaf2fcd57fcac6a38a8465ee6865",
196
+ "size": 71438614
186
197
  },
187
198
  "linux-x64": {
188
- "sha256": "2d357dc6c24559b1e4f792c4142de2608e2dd91a2b322c74013af31a9346ad6e",
189
- "size": 69902826
199
+ "sha256": "baae9a89308dfde3cc47366ab4163369ac8537274361d10381004f006a965afa",
200
+ "size": 71444190
190
201
  },
191
202
  "linux-arm64": {
192
- "sha256": "fdbdc2b25d102db38da6c00e74c6d198b87537aefe74365ef65793ec6feb3faa",
193
- "size": 69900830
203
+ "sha256": "422e2fbd6f65a8aebe0456e9becc2a6a28505825457c9758e8275f35e2fe63f1",
204
+ "size": 71442522
194
205
  }
195
206
  }
196
207
  }