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.
Files changed (185) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +45 -6
  3. package/cli/app-config.ts +4 -1
  4. package/cli/app-fonts.ts +39 -18
  5. package/cli/app-stubs.ts +224 -9
  6. package/cli/bridge-flow-runner.ts +248 -156
  7. package/cli/cloud-client.ts +68 -57
  8. package/cli/command-registry.ts +1 -0
  9. package/cli/commands/box/search-command.ts +3 -2
  10. package/cli/commands/box.ts +10 -29
  11. package/cli/commands/control.ts +391 -92
  12. package/cli/commands/doctor.ts +17 -184
  13. package/cli/commands/flow.ts +79 -11
  14. package/cli/commands/inspect/core.ts +10 -5
  15. package/cli/commands/inspect/settling.ts +71 -22
  16. package/cli/commands/inspect/wait-ready.ts +12 -0
  17. package/cli/commands/inspect.ts +26 -3
  18. package/cli/commands/install-desktop.ts +1 -0
  19. package/cli/commands/maestro-compare.ts +105 -67
  20. package/cli/commands/maestro.ts +9 -1
  21. package/cli/commands/platform.ts +71 -36
  22. package/cli/commands/record.ts +21 -1
  23. package/cli/commands/screenshot.ts +23 -1
  24. package/cli/commands/serve.ts +7 -2
  25. package/cli/commands/setup.ts +19 -42
  26. package/cli/commands/swift.ts +5 -0
  27. package/cli/commands/upload.ts +51 -8
  28. package/cli/desktop-companion.ts +102 -17
  29. package/cli/dev-build-freshness.ts +37 -2
  30. package/cli/drivers/desktop.ts +14 -1
  31. package/cli/drivers/playwright-sim-host.ts +44 -8
  32. package/cli/drivers/playwright.ts +9 -8
  33. package/cli/drivers/types.ts +5 -0
  34. package/cli/maestro-accessibility.ts +53 -0
  35. package/cli/maestro-compare.ts +108 -12
  36. package/cli/main.ts +2 -1
  37. package/cli/outbound-endpoints.ts +35 -6
  38. package/cli/parent-pid.ts +0 -9
  39. package/cli/pause-aware-timeout.ts +102 -0
  40. package/cli/remote-simulators.ts +112 -0
  41. package/cli/remoteSimulatorContract.ts +21 -0
  42. package/cli/scene-video.ts +89 -0
  43. package/cli/ws-bridge.ts +23 -14
  44. package/detox/attempt-events.cjs +4 -0
  45. package/detox/expectations.ts +5 -1
  46. package/detox/index.ts +241 -181
  47. package/detox/motion-change.cjs +73 -0
  48. package/detox/motion-change.d.cts +21 -0
  49. package/detox/navigation-lifecycle.ts +22 -4
  50. package/dist-lib/agent-daemon-client.cjs +3 -2
  51. package/dist-lib/agent-events.cjs +1 -1
  52. package/dist-lib/attached-projects.cjs +1 -1
  53. package/dist-lib/auth/shared-session.cjs +3 -2
  54. package/dist-lib/backend-origin.cjs +1 -1
  55. package/dist-lib/beta.cjs +1 -1
  56. package/dist-lib/beta.mjs +1 -1
  57. package/dist-lib/bridge-constants.cjs +13 -1
  58. package/dist-lib/bridge-contract-input.cjs +1 -1
  59. package/dist-lib/bridge-contract-input.mjs +1 -1
  60. package/dist-lib/bridge-contract.cjs +14 -8
  61. package/dist-lib/bridge-contract.mjs +13 -7
  62. package/dist-lib/bundle-channel.cjs +10480 -7962
  63. package/dist-lib/capture-contract.cjs +1 -1
  64. package/dist-lib/capture-contract.mjs +1 -1
  65. package/dist-lib/cloud-contract.cjs +1 -1
  66. package/dist-lib/cloud-contract.mjs +1 -1
  67. package/dist-lib/cloud-test-args.cjs +1 -1
  68. package/dist-lib/cloud-test-args.mjs +1 -1
  69. package/dist-lib/cloud.cjs +3 -2
  70. package/dist-lib/cloud.mjs +3 -2
  71. package/dist-lib/config.cjs +10 -6
  72. package/dist-lib/config.mjs +10 -6
  73. package/dist-lib/detox/index.cjs +1854 -966
  74. package/dist-lib/dev-bundle-resolution.cjs +64 -24
  75. package/dist-lib/expo-swift-bundle.cjs +8715 -6271
  76. package/dist-lib/expo-swift-metadata.cjs +7 -4
  77. package/dist-lib/expo-swift-metadata.mjs +7 -4
  78. package/dist-lib/home-paths.cjs +32 -3
  79. package/dist-lib/host/bridge-host.cjs +10135 -7060
  80. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  81. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  82. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  83. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  84. package/dist-lib/host/websocket-proxy.cjs +1 -1
  85. package/dist-lib/index.cjs +1843 -408
  86. package/dist-lib/jump-to-source-babel.cjs +1 -1
  87. package/dist-lib/jump-to-source-native.cjs +1 -1
  88. package/dist-lib/kotlin-host.cjs +1 -1
  89. package/dist-lib/menu.cjs +3 -2
  90. package/dist-lib/menu.mjs +3 -2
  91. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  92. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  93. package/dist-lib/metro-production-bundle.cjs +5 -4
  94. package/dist-lib/metro-production-bundle.mjs +5 -4
  95. package/dist-lib/metro.cjs +1182 -418
  96. package/dist-lib/native-app-identity-project.cjs +782 -23
  97. package/dist-lib/native-app-identity-project.mjs +781 -23
  98. package/dist-lib/native-app-identity.cjs +276 -9
  99. package/dist-lib/native-app-identity.mjs +273 -8
  100. package/dist-lib/native-firebase-metadata.cjs +5 -4
  101. package/dist-lib/native-firebase-metadata.mjs +5 -4
  102. package/dist-lib/plist.cjs +1 -1
  103. package/dist-lib/plist.mjs +1 -1
  104. package/dist-lib/profiles.cjs +1 -1
  105. package/dist-lib/public-brand.cjs +3 -2
  106. package/dist-lib/react-native-host-modules.cjs +8 -1
  107. package/dist-lib/react-native-host-modules.mjs +8 -1
  108. package/dist-lib/scripts/dev-server-scanner.cjs +106 -28
  109. package/dist-lib/sdk.cjs +115 -34
  110. package/dist-lib/sdk.mjs +115 -33
  111. package/dist-lib/skills.cjs +15274 -9904
  112. package/dist-lib/swift-compile.cjs +1165 -173
  113. package/dist-lib/swift-compile.mjs +1212 -203
  114. package/dist-lib/swift-package.cjs +12 -3
  115. package/dist-lib/swift-package.mjs +12 -3
  116. package/dist-lib/swift-submit.cjs +7 -1
  117. package/dist-lib/swift-submit.mjs +5 -1
  118. package/dist-lib/swift-toolchain.cjs +133 -18
  119. package/dist-lib/swift.cjs +1 -1
  120. package/dist-lib/vite-swift.cjs +2648 -862
  121. package/dist-lib/vite.cjs +70 -14
  122. package/dist-lib/worklet-executable.cjs +25 -2
  123. package/dist-lib/worklet-executable.mjs +25 -2
  124. package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
  125. package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
  126. package/package.json +2 -2
  127. package/scripts/dev-server-scanner.ts +35 -14
  128. package/skills/peach-perf/SKILL.md +11 -5
  129. package/skills/peach-setup/SKILL.md +16 -19
  130. package/src/admitted-mac-build.ts +34 -8
  131. package/src/android-app-identity.ts +146 -0
  132. package/src/android-autolinking.ts +75 -0
  133. package/src/android-string-value.ts +36 -0
  134. package/src/android-strings.ts +5 -36
  135. package/src/androidAutolinkingContract.ts +40 -0
  136. package/src/bridge-constants.ts +11 -0
  137. package/src/bridge-contract.ts +22 -34
  138. package/src/bundleGlobalFooter.ts +26 -7
  139. package/src/codex-client.ts +3 -2
  140. package/src/config.ts +15 -0
  141. package/src/desktop-host-delivery.ts +5 -1
  142. package/src/dev-bundle-resolution.ts +60 -26
  143. package/src/expo-kotlin-host.ts +6 -36
  144. package/src/expo-manifest-body.ts +13 -0
  145. package/src/expo-swift-bundle.ts +17 -12
  146. package/src/expo-swift-host.ts +640 -192
  147. package/src/expo-swift-ready.ts +78 -0
  148. package/src/expoSwiftContract.ts +19 -0
  149. package/src/home-paths.ts +48 -2
  150. package/src/host/bridge-host.ts +12 -57
  151. package/src/host/staged-host-files.ts +29 -2
  152. package/src/installed-package-versions.ts +54 -14
  153. package/src/launchMetadataContract.ts +24 -0
  154. package/src/metro-plugin.ts +37 -42
  155. package/src/native-app-identity-project.ts +142 -5
  156. package/src/native-app-identity.ts +176 -11
  157. package/src/native-firebase-config.ts +209 -13
  158. package/src/nitro-compile.ts +2 -5
  159. package/src/nitro-source.ts +147 -63
  160. package/src/process-group.ts +114 -61
  161. package/src/process-output.ts +0 -9
  162. package/src/public-brand.ts +1 -0
  163. package/src/react-native-bridge-modules.ts +416 -0
  164. package/src/react-native-host-modules.ts +7 -0
  165. package/src/sim-client.ts +6 -4
  166. package/src/swift-binary-modules.ts +2 -2
  167. package/src/swift-compile.ts +1007 -108
  168. package/src/swift-compiler-digest.ts +14 -0
  169. package/src/swift-distribution.lock.json +40 -12
  170. package/src/swift-distribution.ts +61 -9
  171. package/src/swift-host.ts +149 -56
  172. package/src/swift-icu.ts +14 -6
  173. package/src/swift-objc-sdk.ts +133 -10
  174. package/src/swift-objc-standin.ts +38 -3
  175. package/src/swift-package-manifest.ts +21 -6
  176. package/src/swift-package.ts +15 -1
  177. package/src/swift-packages.ts +119 -60
  178. package/src/swift-standin-emit.ts +57 -9
  179. package/src/swift-standins.ts +185 -25
  180. package/src/swift-submit.ts +10 -0
  181. package/src/swift-toolchain.ts +149 -23
  182. package/src/vite-plugin.ts +20 -20
  183. package/src/worklet-executable.ts +30 -3
  184. package/src/worklets-babel.ts +35 -14
  185. package/src/xcode-project.ts +10 -0
package/src/swift-icu.ts CHANGED
@@ -4,6 +4,7 @@ import { existsSync, readFileSync } from 'node:fs'
4
4
  import path from 'node:path'
5
5
  import { promisify } from 'node:util'
6
6
  import { gzip } from 'node:zlib'
7
+ import { swiftSdkOptions } from './swift-toolchain.ts'
7
8
 
8
9
  /**
9
10
  * the icu common data a swift artifact reserves and its host fills
@@ -49,15 +50,21 @@ function memo<T>(
49
50
 
50
51
  /** the raw blob, for a harness that fills an artifact in node. */
51
52
  export function swiftIcuData(toolchainBin: string, sdk: string): Promise<Buffer> {
52
- return memo(raw, `${toolchainBin}\0${sdk}`, () => load(toolchainBin, sdk))
53
+ return memo(raw, JSON.stringify([toolchainBin, sdk, swiftSdkOptions()]), () =>
54
+ load(toolchainBin, sdk),
55
+ )
53
56
  }
54
57
 
55
58
  /** the served form: gzipped and content-addressed. */
56
59
  export function swiftIcuAsset(toolchainBin: string, sdk: string): Promise<SwiftIcuAsset> {
57
- return memo(assets, `${toolchainBin}\0${sdk}`, async () => {
58
- const zipped = await deflate(await swiftIcuData(toolchainBin, sdk))
59
- return { sha256: createHash('sha256').update(zipped).digest('hex'), gzip: zipped }
60
- })
60
+ return memo(
61
+ assets,
62
+ JSON.stringify([toolchainBin, sdk, swiftSdkOptions()]),
63
+ async () => {
64
+ const zipped = await deflate(await swiftIcuData(toolchainBin, sdk))
65
+ return { sha256: createHash('sha256').update(zipped).digest('hex'), gzip: zipped }
66
+ },
67
+ )
61
68
  }
62
69
 
63
70
  async function load(toolchainBin: string, sdk: string): Promise<Buffer> {
@@ -66,12 +73,13 @@ async function load(toolchainBin: string, sdk: string): Promise<Buffer> {
66
73
  // missing piece instead of shelling out to sdk configure.
67
74
  if (!existsSync(swift))
68
75
  throw new Error(`swift-icu: no swift at ${swift} for the ${sdk} SDK's icu data`)
69
- const { stdout: listed } = await run(swift, ['sdk', 'list'])
76
+ const { stdout: listed } = await run(swift, ['sdk', 'list', ...swiftSdkOptions()])
70
77
  if (!listed.split('\n').some((line) => line.trim() === sdk))
71
78
  throw new Error(`swift-icu: ${sdk} is not installed for ${swift}`)
72
79
  const { stdout } = await run(swift, [
73
80
  'sdk',
74
81
  'configure',
82
+ ...swiftSdkOptions(),
75
83
  '--show-configuration',
76
84
  sdk,
77
85
  'wasm32-unknown-wasip1',
@@ -11,6 +11,129 @@ export const IOS_SDK_TARGET = 'arm64-apple-ios16.0-simulator'
11
11
 
12
12
  /** the clang headers and module maps, by path under the sdk root. */
13
13
  export const IOS_SDK_HEADERS: Record<string, string> = {
14
+ // darwin pointer and mach port identities used in public native headers.
15
+ 'usr/include/pthread.h': `#pragma once
16
+ struct _opaque_pthread_t;
17
+ typedef struct _opaque_pthread_t *pthread_t;
18
+ `,
19
+ 'usr/include/mach/mach_types.h': `#pragma once
20
+ #include <stdint.h>
21
+ typedef unsigned int natural_t;
22
+ typedef int integer_t;
23
+ typedef int vm_prot_t;
24
+ typedef integer_t cpu_type_t;
25
+ typedef integer_t cpu_subtype_t;
26
+ typedef natural_t *thread_state_t;
27
+ typedef int thread_state_flavor_t;
28
+ typedef natural_t mach_port_t;
29
+ typedef mach_port_t thread_t;
30
+ typedef thread_t thread_act_t;
31
+ typedef thread_act_t *thread_act_array_t;
32
+ typedef natural_t mach_msg_type_number_t;
33
+ `,
34
+ 'usr/include/mach/mach.h': `#pragma once
35
+ #include <mach/mach_types.h>
36
+ `,
37
+ 'usr/include/TargetConditionals.h': `#pragma once
38
+ #define TARGET_OS_IPHONE 1
39
+ #define TARGET_OS_IOS 1
40
+ #define TARGET_OS_SIMULATOR 1
41
+ #define TARGET_OS_OSX 0
42
+ #define TARGET_OS_MAC 1
43
+ #define TARGET_OS_TV 0
44
+ #define TARGET_OS_WATCH 0
45
+ #define TARGET_OS_VISION 0
46
+ #define TARGET_OS_MACCATALYST 0
47
+ #define TARGET_IPHONE_SIMULATOR 1
48
+ #define TARGET_CPU_ARM64 1
49
+ #define TARGET_CPU_X86_64 0
50
+ #define TARGET_RT_64_BIT 1
51
+ `,
52
+ 'usr/include/stdlib.h': `#pragma once
53
+ #include <stddef.h>
54
+ void exit(int) __attribute__((noreturn));
55
+ void abort(void) __attribute__((noreturn));
56
+ void *malloc(size_t);
57
+ void free(void *);
58
+ `,
59
+ 'usr/include/unistd.h': `#pragma once
60
+ #include <stdlib.h>
61
+ void _exit(int) __attribute__((noreturn));
62
+ `,
63
+ 'usr/include/string.h': `#pragma once
64
+ #include <stddef.h>
65
+ size_t strlen(const char *);
66
+ char *strdup(const char *);
67
+ void *memcpy(void *, const void *, size_t);
68
+ void *memset(void *, int, size_t);
69
+ int strcmp(const char *, const char *);
70
+ `,
71
+ 'usr/include/sys/types.h': `#pragma once
72
+ #include <time.h>
73
+ #include <stddef.h>
74
+ typedef long ssize_t;
75
+ `,
76
+ 'usr/include/time.h': `#pragma once
77
+ typedef long time_t;
78
+ `,
79
+ 'usr/include/dlfcn.h': `#pragma once
80
+ typedef struct dl_info {
81
+ const char *dli_fname;
82
+ void *dli_fbase;
83
+ const char *dli_sname;
84
+ void *dli_saddr;
85
+ } Dl_info;
86
+ `,
87
+ 'usr/include/sys/ucontext.h': `#pragma once
88
+ #include <stdint.h>
89
+ #define _STRUCT_ARM_EXCEPTION_STATE64 struct __darwin_arm_exception_state64
90
+ _STRUCT_ARM_EXCEPTION_STATE64 { uint64_t __far; uint32_t __esr, __exception; };
91
+ #define _STRUCT_ARM_THREAD_STATE64 struct __darwin_arm_thread_state64
92
+ _STRUCT_ARM_THREAD_STATE64 {
93
+ uint64_t __x[29];
94
+ uint64_t __fp, __lr, __sp, __pc;
95
+ uint32_t __cpsr, __pad;
96
+ };
97
+ #define _STRUCT_ARM_NEON_STATE64 struct __darwin_arm_neon_state64
98
+ _STRUCT_ARM_NEON_STATE64 { unsigned __int128 __v[32]; uint32_t __fpsr, __fpcr; };
99
+ #define _STRUCT_MCONTEXT64 struct __darwin_mcontext64
100
+ _STRUCT_MCONTEXT64 {
101
+ _STRUCT_ARM_EXCEPTION_STATE64 __es;
102
+ _STRUCT_ARM_THREAD_STATE64 __ss;
103
+ _STRUCT_ARM_NEON_STATE64 __ns;
104
+ };
105
+ `,
106
+ 'usr/include/mach-o/loader.h': `#pragma once
107
+ #include <stdint.h>
108
+ #include <mach/mach_types.h>
109
+ #define LC_SEGMENT_64 0x19
110
+ struct mach_header_64 {
111
+ uint32_t magic;
112
+ int32_t cputype, cpusubtype;
113
+ uint32_t filetype, ncmds, sizeofcmds, flags, reserved;
114
+ };
115
+ struct segment_command_64 {
116
+ uint32_t cmd, cmdsize;
117
+ char segname[16];
118
+ uint64_t vmaddr, vmsize, fileoff, filesize;
119
+ int32_t maxprot, initprot;
120
+ uint32_t nsects, flags;
121
+ };
122
+ struct section_64 {
123
+ char sectname[16], segname[16];
124
+ uint64_t addr, size;
125
+ uint32_t offset, align, reloff, nreloc, flags, reserved1, reserved2, reserved3;
126
+ };
127
+ `,
128
+ 'usr/include/mach-o/nlist.h': `#pragma once
129
+ #include <stdint.h>
130
+ struct nlist_64 {
131
+ union { uint32_t n_strx; } n_un;
132
+ uint8_t n_type, n_sect;
133
+ uint16_t n_desc;
134
+ uint64_t n_value;
135
+ };
136
+ `,
14
137
  'usr/include/module.modulemap': `module ObjectiveC [system] {
15
138
  header "objc/NSObject.h"
16
139
  export *
@@ -67,6 +190,10 @@ __attribute__((objc_root_class))
67
190
  @end
68
191
  @interface Protocol : NSObject
69
192
  @end
193
+ `,
194
+ 'System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h': `#pragma once
195
+ #import <Foundation/Foundation.h>
196
+ typedef const struct __attribute__((objc_bridge(NSString))) __CFString *CFStringRef;
70
197
  `,
71
198
  'System/Library/Frameworks/CoreGraphics.framework/Headers/CoreGraphics.h': `#pragma once
72
199
  #include <stdint.h>
@@ -99,9 +226,15 @@ typedef struct __attribute__((objc_bridge(id))) CGColorSpace *CGColorSpaceRef;
99
226
  #include <stddef.h>
100
227
  #include <stdbool.h>
101
228
  #include <stdarg.h>
229
+ #include <stdlib.h>
230
+ #include <string.h>
231
+ #include <time.h>
232
+ #include <TargetConditionals.h>
102
233
  #import <objc/NSObject.h>
103
234
  #import <CoreGraphics/CoreGraphics.h>
104
235
 
236
+ @class NSException;
237
+ typedef void NSUncaughtExceptionHandler(NSException *exception);
105
238
  #define FOUNDATION_EXPORT extern
106
239
  #define FOUNDATION_EXTERN extern
107
240
  #define FOUNDATION_STATIC_INLINE static inline
@@ -237,16 +370,6 @@ typedef struct __attribute__((objc_bridge(id))) CGColorSpace *CGColorSpaceRef;
237
370
  #define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end")
238
371
  #define NS_NONATOMIC_IOSONLY nonatomic
239
372
  #define NS_UNAVAILABLE_INIT
240
- #define TARGET_OS_IPHONE 1
241
- #define TARGET_OS_IOS 1
242
- #define TARGET_OS_SIMULATOR 1
243
- #define TARGET_OS_OSX 0
244
- #define TARGET_OS_MAC 1
245
- #define TARGET_OS_TV 0
246
- #define TARGET_OS_WATCH 0
247
- #define TARGET_OS_VISION 0
248
- #define TARGET_OS_MACCATALYST 0
249
- #define TARGET_IPHONE_SIMULATOR 1
250
373
  #define NSIntegerMax LONG_MAX
251
374
  #define NSIntegerMin LONG_MIN
252
375
  #define NSUIntegerMax ULONG_MAX
@@ -26,6 +26,7 @@ export interface ObjcSurface {
26
26
  module: string
27
27
  modulemap: string
28
28
  headers: string
29
+ dependencies?: { module: string; headers: string }[]
29
30
  }
30
31
 
31
32
  export interface ObjcView {
@@ -123,7 +124,7 @@ export function objcView(
123
124
  const include = path.join(work, 'include')
124
125
  const headersDir = framework
125
126
  ? path.join(frameworks, `${surface.module}.framework`, 'Headers')
126
- : include
127
+ : path.join(include, surface.module)
127
128
  const originals = new Map(
128
129
  headerFiles(surface.headers).map((file) => [
129
130
  file,
@@ -143,7 +144,22 @@ export function objcView(
143
144
  path.join(frameworks, `${surface.module}.framework`, 'Modules', 'module.modulemap'),
144
145
  )
145
146
  } else {
146
- fs.copyFileSync(surface.modulemap, path.join(include, 'module.modulemap'))
147
+ fs.copyFileSync(surface.modulemap, path.join(headersDir, 'module.modulemap'))
148
+ }
149
+ for (const dependency of surface.dependencies ?? []) {
150
+ const dir = path.join(include, dependency.module)
151
+ fs.mkdirSync(dir, { recursive: true })
152
+ for (const file of headerFiles(dependency.headers)) {
153
+ fs.mkdirSync(path.dirname(path.join(dir, file)), { recursive: true })
154
+ fs.copyFileSync(path.join(dependency.headers, file), path.join(dir, file))
155
+ }
156
+ const supplied = path.join(dependency.headers, 'module.modulemap')
157
+ fs.writeFileSync(
158
+ path.join(dir, 'module.modulemap'),
159
+ fs.existsSync(supplied)
160
+ ? fs.readFileSync(supplied, 'utf8')
161
+ : `module ${dependency.module} { umbrella "." export * }\n`,
162
+ )
147
163
  }
148
164
  const stubs = path.join(work, 'stubs')
149
165
  const stubIncludes = path.join(work, 'stub-include')
@@ -158,6 +174,12 @@ export function objcView(
158
174
  frameworks,
159
175
  '-I',
160
176
  include,
177
+ '-I',
178
+ headersDir,
179
+ ...(surface.dependencies ?? []).flatMap((dependency) => [
180
+ '-I',
181
+ path.join(include, dependency.module),
182
+ ]),
161
183
  '-F',
162
184
  stubs,
163
185
  '-I',
@@ -174,6 +196,19 @@ export function objcView(
174
196
  const slash = include.indexOf('/')
175
197
  if (slash > 0 && /^[A-Z]/.test(include)) {
176
198
  const name = include.slice(0, slash)
199
+ const umbrella = `${name}/${name}.h`
200
+ if (
201
+ Object.hasOwn(
202
+ IOS_SDK_HEADERS,
203
+ `System/Library/Frameworks/${name}.framework/Headers/${name}.h`,
204
+ )
205
+ ) {
206
+ // retain the sdk module's owner when a vendor imports a leaf header.
207
+ const header = path.join(stubIncludes, include)
208
+ fs.mkdirSync(path.dirname(header), { recursive: true })
209
+ fs.writeFileSync(header, `#import <${umbrella}>\n`)
210
+ return true
211
+ }
177
212
  const root = path.join(stubs, `${name}.framework`)
178
213
  const header = path.join(root, 'Headers', include.slice(slash + 1))
179
214
  fs.mkdirSync(path.dirname(header), { recursive: true })
@@ -287,7 +322,7 @@ export function objcView(
287
322
  }
288
323
  if (!progress || round === ROUNDS)
289
324
  throw new Error(
290
- `its headers do not import as Swift: ${[...new Set(errors.map((match) => match[4]!))].slice(0, 3).join('; ')}`,
325
+ `its headers do not import as Swift: ${[...new Set(errors.map((match) => match[4]!))].slice(0, 10).join('; ')}`,
291
326
  )
292
327
  if (missing.size > 0) declareMissing()
293
328
  }
@@ -8,8 +8,8 @@
8
8
  import { execFileSync } from 'node:child_process'
9
9
  import { createHash } from 'node:crypto'
10
10
  import fs from 'node:fs'
11
- import os from 'node:os'
12
11
  import path from 'node:path'
12
+ import { cacheDir as peachCacheDir, swiftPackageCacheOptions } from './home-paths'
13
13
  import lock from './swift-distribution.lock.json' with { type: 'json' }
14
14
  import { swiftToolchainBin } from './swift-toolchain'
15
15
  import type { SwiftTargetDependency } from './swift-package'
@@ -27,9 +27,9 @@ export type SwiftManifestTargetType = (typeof TARGET_TYPES)[number]
27
27
  const isTargetType = (value: string | undefined): value is SwiftManifestTargetType =>
28
28
  TARGET_TYPES.some((type) => type === value)
29
29
 
30
- /** a swift condition a target defines on ios, and the swiftpm build
30
+ /** a named target setting active on ios, and the swiftpm build
31
31
  * configuration it needs (null applies in both). */
32
- export interface SwiftManifestDefine {
32
+ export interface SwiftManifestSetting {
33
33
  name: string
34
34
  configuration: 'debug' | 'release' | null
35
35
  }
@@ -47,9 +47,12 @@ export interface SwiftManifestTarget {
47
47
  dependencies: SwiftTargetDependency[]
48
48
  languageMode: number
49
49
  mainActorIsolation: boolean
50
- defines: SwiftManifestDefine[]
50
+ defines: SwiftManifestSetting[]
51
+ libraries: SwiftManifestSetting[]
51
52
  /** true when the target declares `resources:`. */
52
53
  declaresResources: boolean
54
+ /** public header directory relative to the target, as SwiftPM declares it. */
55
+ publicHeadersPath: string
53
56
  /** a binary target's archive url; a local one's artifact is `dir`. */
54
57
  url: string | null
55
58
  /** the declared SHA-256 for a remote binary archive. */
@@ -80,7 +83,7 @@ function swiftCommand(): { file: string; args: string[] } {
80
83
  : { file: path.join(swiftToolchainBin(lock.release), 'swift'), args: [] }
81
84
  }
82
85
 
83
- const cacheDir = path.join(os.tmpdir(), 'peach-swift-manifests')
86
+ const cacheDir = path.join(peachCacheDir(), 'swift-manifests')
84
87
  const evaluated = new Map<string, SwiftPackageManifest>()
85
88
 
86
89
  function dump(dir: string): { key: string; raw: Record<string, Json> } {
@@ -108,6 +111,7 @@ function dump(dir: string): { key: string; raw: Record<string, Json> } {
108
111
  [
109
112
  ...command.args,
110
113
  'package',
114
+ ...swiftPackageCacheOptions(),
111
115
  '--package-path',
112
116
  dir,
113
117
  // swiftpm's scratch files never land in the app's own package
@@ -249,7 +253,8 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
249
253
  }
250
254
  let languageMode = packageMode
251
255
  let mainActorIsolation = false
252
- const defines: SwiftManifestDefine[] = []
256
+ const defines: SwiftManifestSetting[] = []
257
+ const libraries: SwiftManifestSetting[] = []
253
258
  for (const setting of array(target.settings)) {
254
259
  const { kind: rawKind, tool, condition } = record(setting)
255
260
  const settingKind = record(rawKind)
@@ -271,6 +276,14 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
271
276
  configuration: config === 'debug' || config === 'release' ? config : null,
272
277
  })
273
278
  }
279
+ const library = string(record(settingKind.linkedLibrary)._0)
280
+ if (library && string(tool) === 'linker' && linksOnIOS(condition, traits)) {
281
+ const config = string(record(condition).config)
282
+ libraries.push({
283
+ name: library,
284
+ configuration: config === 'debug' || config === 'release' ? config : null,
285
+ })
286
+ }
274
287
  }
275
288
  targets.set(name, {
276
289
  name,
@@ -285,7 +298,9 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
285
298
  languageMode,
286
299
  mainActorIsolation,
287
300
  defines,
301
+ libraries,
288
302
  declaresResources: array(target.resources).length > 0,
303
+ publicHeadersPath: string(target.publicHeadersPath) ?? 'include',
289
304
  url: string(target.url) ?? null,
290
305
  checksum: string(target.checksum) ?? null,
291
306
  })
@@ -8,6 +8,8 @@ export interface SwiftPackageTarget {
8
8
  path: string
9
9
  /** true for `.executableTarget`: the one that links the wasm artifact. */
10
10
  executable: boolean
11
+ /** true for a header-only `.systemLibrary` supplied by the target SDK. */
12
+ systemLibrary?: boolean
11
13
  /** the target's declared `.swiftLanguageMode(.vN)`; 5 when it declares none. */
12
14
  languageMode: number
13
15
  /** true when the target declares `.defaultIsolation(MainActor.self)`. */
@@ -16,6 +18,8 @@ export interface SwiftPackageTarget {
16
18
  cxxInterop?: boolean
17
19
  /** compilation conditions the target declares unconditionally with `.define`. */
18
20
  defines?: string[]
21
+ /** libraries the target declares unconditionally with `.linkedLibrary`. */
22
+ linkedLibraries?: string[]
19
23
  /** true when declared or implicit resources give the target `Bundle.module`. */
20
24
  resources: boolean
21
25
  /** declared dependencies on other targets in the same package. */
@@ -202,7 +206,11 @@ export function swiftManifestTargets(
202
206
  ): SwiftPackageTarget[] {
203
207
  const implicitResources = swiftImplicitResourcePaths(resourcePaths)
204
208
  const targets: SwiftPackageTarget[] = []
205
- const declarations = manifestCalls(manifest, ['executableTarget', 'target'])
209
+ const declarations = manifestCalls(manifest, [
210
+ 'executableTarget',
211
+ 'target',
212
+ 'systemLibrary',
213
+ ])
206
214
  const targetNames = new Set(
207
215
  declarations.flatMap(({ flat }) => {
208
216
  const name = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1]
@@ -230,6 +238,9 @@ export function swiftManifestTargets(
230
238
  const defines = [
231
239
  ...call.matchAll(/\.define\(\s*"([A-Za-z_][A-Za-z0-9_]*)"\s*\)/g),
232
240
  ].map((match) => match[1]!)
241
+ const linkedLibraries = [...call.matchAll(/\.linkedLibrary\(\s*"([^"]+)"\s*\)/g)].map(
242
+ (match) => match[1]!,
243
+ )
233
244
  const excluded = [
234
245
  ...(/\bexclude\s*:\s*\[([^\]]*)\]/.exec(flat)?.[1] ?? '').matchAll(/"([^"]+)"/g),
235
246
  ].map((match) => match[1].replace(/^\.\//, '').replace(/\/+$/, ''))
@@ -270,10 +281,12 @@ export function swiftManifestTargets(
270
281
  name,
271
282
  path: targetPath,
272
283
  executable,
284
+ ...(kind === 'systemLibrary' ? { systemLibrary: true } : {}),
273
285
  languageMode,
274
286
  mainActorIsolation,
275
287
  ...(cxxInterop ? { cxxInterop: true } : {}),
276
288
  ...(defines.length === 0 ? {} : { defines }),
289
+ ...(linkedLibraries.length === 0 ? {} : { linkedLibraries }),
277
290
  resources,
278
291
  ...(dependencies.length === 0 ? {} : { dependencies }),
279
292
  ...(excluded.length === 0 ? {} : { exclude: excluded }),
@@ -380,6 +393,7 @@ export function swiftPackagePartition(
380
393
  targets[0].languageMode === 5 &&
381
394
  !targets[0].mainActorIsolation &&
382
395
  !targets[0].defines?.length &&
396
+ !targets[0].linkedLibraries?.length &&
383
397
  !targets[0].cxxInterop &&
384
398
  !swiftManifestCxxLanguageStandard(manifest)
385
399
  ? []