peachsim 0.1.1625 → 0.1.1640
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 +15 -2
- package/cli/app-config.ts +18 -6
- package/cli/app-fonts.ts +37 -17
- package/cli/app-stubs.ts +284 -20
- package/cli/bridge-flow-runner.ts +66 -45
- package/cli/cloud-client.ts +60 -40
- package/cli/command-registry.ts +1 -0
- package/cli/commands/control.ts +283 -49
- package/cli/commands/doctor.ts +30 -189
- package/cli/commands/flow.ts +79 -11
- package/cli/commands/inspect/core.ts +10 -5
- package/cli/commands/inspect/settling.ts +14 -2
- package/cli/commands/inspect/shared.ts +9 -4
- package/cli/commands/inspect/wait-ready.ts +12 -0
- package/cli/commands/inspect.ts +91 -50
- package/cli/commands/install-desktop.ts +1 -0
- package/cli/commands/maestro-compare.ts +97 -38
- package/cli/commands/maestro.ts +9 -1
- package/cli/commands/preview.ts +1 -1
- package/cli/commands/record.ts +118 -48
- 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 +14 -3
- package/cli/commands/upload.ts +93 -48
- package/cli/desktop-companion.ts +102 -17
- package/cli/drivers/desktop.ts +14 -1
- package/cli/drivers/playwright-sim-host.ts +103 -45
- package/cli/drivers/playwright.ts +9 -8
- package/cli/drivers/types.ts +5 -0
- package/cli/maestro-accessibility.ts +1 -1
- package/cli/maestro-compare.ts +84 -12
- package/cli/main.ts +3 -2
- package/cli/outbound-endpoints.ts +20 -6
- package/cli/pause-aware-timeout.ts +106 -0
- package/cli/scene-video.ts +89 -0
- package/cli/ws-bridge.ts +37 -19
- package/detox/attempt-events.cjs +66 -5
- package/detox/attempt-events.d.cts +7 -0
- package/detox/expectations.ts +7 -3
- package/detox/index.ts +269 -170
- package/detox/motion-change.cjs +206 -21
- package/detox/motion-change.d.cts +39 -2
- package/detox/navigation-lifecycle.ts +35 -3
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +8 -7
- 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 +11887 -7900
- 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 +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +6 -3
- package/dist-lib/config.mjs +6 -3
- package/dist-lib/detox/index.cjs +1379 -725
- package/dist-lib/dev-bundle-resolution.cjs +14 -2
- package/dist-lib/expo-swift-bundle.cjs +9341 -5462
- package/dist-lib/expo-swift-metadata.cjs +11 -7
- package/dist-lib/expo-swift-metadata.mjs +11 -7
- package/dist-lib/home-paths.cjs +32 -3
- package/dist-lib/host/bridge-host.cjs +50204 -7258
- 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 +3541 -448
- 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 +1 -1
- package/dist-lib/menu.mjs +1 -1
- 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 +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +2931 -104
- package/dist-lib/native-app-identity-project.cjs +289 -49
- package/dist-lib/native-app-identity-project.mjs +289 -49
- package/dist-lib/native-app-identity.cjs +77 -26
- package/dist-lib/native-app-identity.mjs +76 -26
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- 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 +1 -1
- package/dist-lib/react-native-host-modules.cjs +6 -2
- package/dist-lib/react-native-host-modules.mjs +6 -2
- package/dist-lib/scripts/dev-server-scanner.cjs +22 -8
- package/dist-lib/sdk.cjs +27 -11
- package/dist-lib/sdk.mjs +27 -10
- package/dist-lib/skills.cjs +72201 -26208
- package/dist-lib/swift-compile.cjs +1007 -140
- package/dist-lib/swift-compile.mjs +1049 -174
- package/dist-lib/swift-package.cjs +12 -3
- package/dist-lib/swift-package.mjs +12 -3
- package/dist-lib/swift-submit.cjs +13 -5
- package/dist-lib/swift-submit.mjs +11 -5
- package/dist-lib/swift-toolchain.cjs +423 -33
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +8628 -5268
- package/dist-lib/vite.cjs +2859 -12
- package/dist-lib/worklet-executable.cjs +14 -2
- package/dist-lib/worklet-executable.mjs +14 -2
- package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
- package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
- package/package.json +1 -1
- package/scripts/dev-server-scanner.ts +2 -1
- package/skills/peach-perf/SKILL.md +11 -5
- package/skills/peach-setup/SKILL.md +16 -19
- package/src/backend-origin.ts +13 -6
- package/src/bridge-constants.ts +11 -0
- package/src/bridge-contract.ts +22 -34
- package/src/config.ts +15 -0
- package/src/desktop-host-delivery.ts +5 -1
- package/src/dev-bundle-resolution.ts +2 -1
- package/src/expo-manifest-body.ts +13 -0
- package/src/expo-swift-host.ts +196 -49
- package/src/expo-swift-ready.ts +78 -0
- package/src/expoKotlinContract.ts +4 -7
- package/src/expoSwiftContract.ts +17 -6
- package/src/home-paths.ts +48 -2
- package/src/host/bridge-host.ts +5 -2
- package/src/host/staged-host-files.ts +9 -0
- package/src/native-app-identity-project.ts +27 -6
- package/src/native-app-identity.ts +91 -4
- package/src/native-firebase-config.ts +209 -13
- package/src/nativeAppIconContract.ts +1 -4
- package/src/output-lock-stdio.ts +36 -0
- package/src/process-group.ts +25 -2
- package/src/react-native-bridge-modules.ts +431 -0
- package/src/react-native-host-modules.ts +8 -1
- package/src/settings-bundle.ts +1 -4
- package/src/swift-binary-modules.ts +2 -2
- package/src/swift-compile.ts +918 -109
- package/src/swift-compiler-digest.ts +14 -0
- package/src/swift-distribution.lock.json +24 -12
- package/src/swift-distribution.ts +103 -4
- package/src/swift-host.ts +180 -55
- package/src/swift-icu.ts +27 -13
- package/src/swift-objc-compile.ts +355 -0
- package/src/swift-objc-sdk.ts +821 -27
- package/src/swift-objc-standin.ts +148 -14
- package/src/swift-package-manifest.ts +60 -7
- package/src/swift-package.ts +15 -1
- package/src/swift-packages.ts +154 -81
- package/src/swift-standin-emit.ts +96 -15
- package/src/swift-standins.ts +530 -116
- package/src/swift-submit.ts +13 -5
- package/src/swift-toolchain.ts +500 -42
- package/src/vite-plugin.ts +12 -1
- package/src/worker-system-chunks.ts +11 -12
- package/src/worklet-executable.ts +19 -1
- package/src/xcode-project.ts +270 -30
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
// headers import; the stand-in's own typecheck then leaves out whatever peach
|
|
14
14
|
// cannot spell.
|
|
15
15
|
|
|
16
|
-
import { spawnSync } from 'node:child_process'
|
|
16
|
+
import { execFileSync, spawnSync } from 'node:child_process'
|
|
17
17
|
import { createHash } from 'node:crypto'
|
|
18
18
|
import fs from 'node:fs'
|
|
19
19
|
import path from 'node:path'
|
|
20
20
|
import { IOS_SDK_HEADERS, IOS_SDK_OVERLAYS, IOS_SDK_TARGET } from './swift-objc-sdk'
|
|
21
|
+
import { swiftEnvironment } from './swift-toolchain'
|
|
21
22
|
import type { SymbolGraph } from './swift-standin-emit'
|
|
22
23
|
|
|
23
24
|
/** a module map and the headers it reaches: a framework's, or a library
|
|
@@ -26,6 +27,7 @@ export interface ObjcSurface {
|
|
|
26
27
|
module: string
|
|
27
28
|
modulemap: string
|
|
28
29
|
headers: string
|
|
30
|
+
dependencies?: { module: string; headers: string }[]
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export interface ObjcView {
|
|
@@ -36,6 +38,100 @@ export interface ObjcView {
|
|
|
36
38
|
imports: string[]
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
/** bump when importer behavior changes the Swift view independently of SDK headers. */
|
|
42
|
+
export const OBJC_IMPORT_VERSION = '3'
|
|
43
|
+
|
|
44
|
+
export const NATIVE_GRAPH_SDK_VERSION = '27.1'
|
|
45
|
+
|
|
46
|
+
const NATIVE_GRAPH_INPUTS = {
|
|
47
|
+
sdk: NATIVE_GRAPH_SDK_VERSION,
|
|
48
|
+
settings: 'e68503e5e534e9194af5efe8c636ca8b824e2d8237c5f38ec84aa4d155bc8418',
|
|
49
|
+
build: 'ff785237ba22f1d8f347a5c4f4c68400a387c6d935ef3a443545a72faef57e70',
|
|
50
|
+
compiler: 'Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)',
|
|
51
|
+
target: IOS_SDK_TARGET,
|
|
52
|
+
}
|
|
53
|
+
export const NATIVE_GRAPH_ID = createHash('sha256')
|
|
54
|
+
.update(JSON.stringify(NATIVE_GRAPH_INPUTS))
|
|
55
|
+
.digest('hex')
|
|
56
|
+
|
|
57
|
+
/** a mixed framework's swift overlay and underlying clang module load together. */
|
|
58
|
+
export function nativeInterfaceView(
|
|
59
|
+
surface: ObjcSurface,
|
|
60
|
+
frameworks: readonly string[],
|
|
61
|
+
work: string,
|
|
62
|
+
): ObjcView {
|
|
63
|
+
if (process.platform !== 'darwin')
|
|
64
|
+
throw new Error('mixed framework declarations require the pinned native iOS SDK')
|
|
65
|
+
const xcrun = (args: string[]) =>
|
|
66
|
+
execFileSync('xcrun', args, {
|
|
67
|
+
encoding: 'utf8',
|
|
68
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
69
|
+
}).trim()
|
|
70
|
+
const sdk = xcrun(['--sdk', 'iphonesimulator', '--show-sdk-path'])
|
|
71
|
+
const compiler = xcrun(['--find', 'swiftc'])
|
|
72
|
+
const version = execFileSync(compiler, ['--version'], { encoding: 'utf8' })
|
|
73
|
+
.trim()
|
|
74
|
+
.split('\n')[0]
|
|
75
|
+
const digest = (file: string) =>
|
|
76
|
+
createHash('sha256')
|
|
77
|
+
.update(fs.readFileSync(path.join(sdk, file)))
|
|
78
|
+
.digest('hex')
|
|
79
|
+
const actual = {
|
|
80
|
+
sdk: xcrun(['--sdk', 'iphonesimulator', '--show-sdk-version']),
|
|
81
|
+
compiler: version,
|
|
82
|
+
settings: digest('SDKSettings.json'),
|
|
83
|
+
build: digest('System/Library/CoreServices/SystemVersion.plist'),
|
|
84
|
+
}
|
|
85
|
+
const mismatches = Object.entries(actual)
|
|
86
|
+
.filter(([key, value]) => Reflect.get(NATIVE_GRAPH_INPUTS, key) !== value)
|
|
87
|
+
.map(
|
|
88
|
+
([key, value]) =>
|
|
89
|
+
`${key}: expected ${Reflect.get(NATIVE_GRAPH_INPUTS, key)}, got ${value}`,
|
|
90
|
+
)
|
|
91
|
+
if (mismatches.length)
|
|
92
|
+
throw new Error(
|
|
93
|
+
`native declaration SDK or compiler differs from ${NATIVE_GRAPH_ID}: ${mismatches.join('; ')}`,
|
|
94
|
+
)
|
|
95
|
+
const toolchainBin = path.dirname(compiler)
|
|
96
|
+
const search = ['-sdk', sdk, ...frameworks.flatMap((dir) => ['-F', dir])]
|
|
97
|
+
const out = path.join(work, 'native-graphs')
|
|
98
|
+
fs.mkdirSync(out, { recursive: true })
|
|
99
|
+
const run = spawnSync(
|
|
100
|
+
path.join(toolchainBin, 'swift-symbolgraph-extract'),
|
|
101
|
+
[
|
|
102
|
+
'-module-name',
|
|
103
|
+
surface.module,
|
|
104
|
+
'-target',
|
|
105
|
+
IOS_SDK_TARGET,
|
|
106
|
+
...search,
|
|
107
|
+
'-minimum-access-level',
|
|
108
|
+
'public',
|
|
109
|
+
'-skip-synthesized-members',
|
|
110
|
+
'-omit-extension-block-symbols',
|
|
111
|
+
'-output-dir',
|
|
112
|
+
out,
|
|
113
|
+
],
|
|
114
|
+
{ encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 },
|
|
115
|
+
)
|
|
116
|
+
if (run.error) throw run.error
|
|
117
|
+
if (run.status !== 0)
|
|
118
|
+
throw new Error(
|
|
119
|
+
`native interface extraction ${run.signal ?? `exit ${run.status}`}: ${run.stderr.trim().slice(-4000)}`,
|
|
120
|
+
)
|
|
121
|
+
const graphs = fs
|
|
122
|
+
.readdirSync(out)
|
|
123
|
+
.filter((file) => file.endsWith('.symbols.json'))
|
|
124
|
+
.sort()
|
|
125
|
+
.map((file): SymbolGraph => JSON.parse(fs.readFileSync(path.join(out, file), 'utf8')))
|
|
126
|
+
if (graphs.length === 0)
|
|
127
|
+
throw new Error('native interface extraction returned no graphs')
|
|
128
|
+
return {
|
|
129
|
+
graphs,
|
|
130
|
+
values: enumValues(graphs, surface, true, toolchainBin, search, work),
|
|
131
|
+
imports: [],
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
39
135
|
// the opaque declarations a failed import asks for, by name.
|
|
40
136
|
type Missing = Map<string, 'class' | 'protocol' | 'struct' | 'macro'>
|
|
41
137
|
|
|
@@ -62,7 +158,7 @@ export const IOS_SDK_ID = createHash('sha256')
|
|
|
62
158
|
|
|
63
159
|
// the sdk, written once per content under the cache directory so the module
|
|
64
160
|
// cache keyed by its paths stays warm across stand-ins.
|
|
65
|
-
function
|
|
161
|
+
export function materializeObjcSdk(cacheDir: string): string {
|
|
66
162
|
const sdk = path.join(cacheDir, 'ios-sdk', IOS_SDK_ID)
|
|
67
163
|
if (fs.existsSync(sdk)) return sdk
|
|
68
164
|
fs.mkdirSync(path.dirname(sdk), { recursive: true })
|
|
@@ -115,7 +211,7 @@ export function objcView(
|
|
|
115
211
|
throw new Error(
|
|
116
212
|
`this peach's Swift has no iOS simulator standard library at ${stdlib}`,
|
|
117
213
|
)
|
|
118
|
-
const sdk =
|
|
214
|
+
const sdk = materializeObjcSdk(cacheDir)
|
|
119
215
|
// a framework's module map sits in Modules/ beside Headers/; a library
|
|
120
216
|
// slice keeps it among its headers.
|
|
121
217
|
const framework = path.basename(path.dirname(surface.modulemap)) === 'Modules'
|
|
@@ -123,16 +219,16 @@ export function objcView(
|
|
|
123
219
|
const include = path.join(work, 'include')
|
|
124
220
|
const headersDir = framework
|
|
125
221
|
? path.join(frameworks, `${surface.module}.framework`, 'Headers')
|
|
126
|
-
: include
|
|
222
|
+
: path.join(include, surface.module)
|
|
127
223
|
const originals = new Map(
|
|
128
224
|
headerFiles(surface.headers).map((file) => [
|
|
129
|
-
file,
|
|
225
|
+
path.join(headersDir, file),
|
|
130
226
|
fs.readFileSync(path.join(surface.headers, file), 'utf8'),
|
|
131
227
|
]),
|
|
132
228
|
)
|
|
133
229
|
for (const [file, text] of originals) {
|
|
134
|
-
fs.mkdirSync(path.dirname(
|
|
135
|
-
fs.writeFileSync(
|
|
230
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
231
|
+
fs.writeFileSync(file, text)
|
|
136
232
|
}
|
|
137
233
|
if (framework) {
|
|
138
234
|
fs.mkdirSync(path.join(frameworks, `${surface.module}.framework`, 'Modules'), {
|
|
@@ -143,7 +239,28 @@ export function objcView(
|
|
|
143
239
|
path.join(frameworks, `${surface.module}.framework`, 'Modules', 'module.modulemap'),
|
|
144
240
|
)
|
|
145
241
|
} else {
|
|
146
|
-
fs.copyFileSync(surface.modulemap, path.join(
|
|
242
|
+
fs.copyFileSync(surface.modulemap, path.join(headersDir, 'module.modulemap'))
|
|
243
|
+
}
|
|
244
|
+
// dependency headers take the same learned declarations but never become
|
|
245
|
+
// the surface's own imports.
|
|
246
|
+
const dependencyOriginals = new Map<string, string>()
|
|
247
|
+
for (const dependency of surface.dependencies ?? []) {
|
|
248
|
+
const dir = path.join(include, dependency.module)
|
|
249
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
250
|
+
for (const file of headerFiles(dependency.headers)) {
|
|
251
|
+
const destination = path.join(dir, file)
|
|
252
|
+
const text = fs.readFileSync(path.join(dependency.headers, file), 'utf8')
|
|
253
|
+
dependencyOriginals.set(destination, text)
|
|
254
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true })
|
|
255
|
+
fs.writeFileSync(destination, text)
|
|
256
|
+
}
|
|
257
|
+
const supplied = path.join(dependency.headers, 'module.modulemap')
|
|
258
|
+
fs.writeFileSync(
|
|
259
|
+
path.join(dir, 'module.modulemap'),
|
|
260
|
+
fs.existsSync(supplied)
|
|
261
|
+
? fs.readFileSync(supplied, 'utf8')
|
|
262
|
+
: `module ${dependency.module} { umbrella "." export * }\n`,
|
|
263
|
+
)
|
|
147
264
|
}
|
|
148
265
|
const stubs = path.join(work, 'stubs')
|
|
149
266
|
const stubIncludes = path.join(work, 'stub-include')
|
|
@@ -152,12 +269,25 @@ export function objcView(
|
|
|
152
269
|
const search = [
|
|
153
270
|
'-sdk',
|
|
154
271
|
sdk,
|
|
272
|
+
// keep compiler support headers without importing host platform modules.
|
|
273
|
+
'-resource-dir',
|
|
274
|
+
path.join(sdk, 'usr/lib/swift'),
|
|
275
|
+
'-I',
|
|
276
|
+
path.resolve(toolchainBin, '../lib/swift/clang/include'),
|
|
277
|
+
'-I',
|
|
278
|
+
path.resolve(toolchainBin, '../lib/swift/shims'),
|
|
155
279
|
'-I',
|
|
156
280
|
stdlib,
|
|
157
281
|
'-F',
|
|
158
282
|
frameworks,
|
|
159
283
|
'-I',
|
|
160
284
|
include,
|
|
285
|
+
'-I',
|
|
286
|
+
headersDir,
|
|
287
|
+
...(surface.dependencies ?? []).flatMap((dependency) => [
|
|
288
|
+
'-I',
|
|
289
|
+
path.join(include, dependency.module),
|
|
290
|
+
]),
|
|
161
291
|
'-F',
|
|
162
292
|
stubs,
|
|
163
293
|
'-I',
|
|
@@ -215,8 +345,8 @@ export function objcView(
|
|
|
215
345
|
path.join(root, 'Modules', 'module.modulemap'),
|
|
216
346
|
'framework module PeachMissing {\n umbrella header "PeachMissing.h"\n export *\n}\n',
|
|
217
347
|
)
|
|
218
|
-
for (const [file, text] of originals)
|
|
219
|
-
fs.writeFileSync(
|
|
348
|
+
for (const [file, text] of [...originals, ...dependencyOriginals])
|
|
349
|
+
fs.writeFileSync(file, `${MISSING_IMPORT}${text}`)
|
|
220
350
|
}
|
|
221
351
|
// the identifier a diagnostic points at, read from the header as compiled.
|
|
222
352
|
const tokenAt = (file: string, line: number, column: number) => {
|
|
@@ -254,11 +384,11 @@ export function objcView(
|
|
|
254
384
|
'-output-dir',
|
|
255
385
|
out,
|
|
256
386
|
],
|
|
257
|
-
{ encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 },
|
|
387
|
+
{ encoding: 'utf8', env: swiftEnvironment(), maxBuffer: 256 * 1024 * 1024 },
|
|
258
388
|
)
|
|
259
389
|
if (run.error) throw run.error
|
|
260
390
|
const errors = [
|
|
261
|
-
...run.stderr.matchAll(/^(?:(
|
|
391
|
+
...run.stderr.matchAll(/^(?:(.+?):(\d+):(\d+): )?(?:fatal )?error: (.*)$/gm),
|
|
262
392
|
]
|
|
263
393
|
if (errors.length === 0 && run.status === 0) break
|
|
264
394
|
let progress = false
|
|
@@ -300,7 +430,11 @@ export function objcView(
|
|
|
300
430
|
}
|
|
301
431
|
if (!progress || round === ROUNDS)
|
|
302
432
|
throw new Error(
|
|
303
|
-
`its headers do not import as Swift: ${
|
|
433
|
+
`its headers do not import as Swift: ${
|
|
434
|
+
errors.length > 0
|
|
435
|
+
? [...new Set(errors.map((match) => match[4]!))].slice(0, 10).join('; ')
|
|
436
|
+
: `swift-symbolgraph-extract ${run.signal ?? `exit ${run.status}`}: ${(run.stderr.trim() || run.stdout.trim() || 'no diagnostic').slice(0, 4000)}`
|
|
437
|
+
}`,
|
|
304
438
|
)
|
|
305
439
|
if (missing.size > 0) declareMissing()
|
|
306
440
|
}
|
|
@@ -383,7 +517,7 @@ function enumValues(
|
|
|
383
517
|
'-ast-dump=json',
|
|
384
518
|
probe,
|
|
385
519
|
],
|
|
386
|
-
{ encoding: 'utf8', maxBuffer: 1024 * 1024 * 1024 },
|
|
520
|
+
{ encoding: 'utf8', env: swiftEnvironment(), maxBuffer: 1024 * 1024 * 1024 },
|
|
387
521
|
)
|
|
388
522
|
if (run.status !== 0)
|
|
389
523
|
throw new Error(
|
|
@@ -8,10 +8,10 @@
|
|
|
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
|
-
import { swiftToolchainBin } from './swift-toolchain'
|
|
14
|
+
import { swiftEnvironment, swiftToolchainBin } from './swift-toolchain'
|
|
15
15
|
import type { SwiftTargetDependency } from './swift-package'
|
|
16
16
|
|
|
17
17
|
const TARGET_TYPES = [
|
|
@@ -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
|
|
30
|
+
/** a named target setting active on ios, and the swiftpm build
|
|
31
31
|
* configuration it needs (null applies in both). */
|
|
32
|
-
export interface
|
|
32
|
+
export interface SwiftManifestSetting {
|
|
33
33
|
name: string
|
|
34
34
|
configuration: 'debug' | 'release' | null
|
|
35
35
|
}
|
|
@@ -47,9 +47,17 @@ export interface SwiftManifestTarget {
|
|
|
47
47
|
dependencies: SwiftTargetDependency[]
|
|
48
48
|
languageMode: number
|
|
49
49
|
mainActorIsolation: boolean
|
|
50
|
-
defines:
|
|
50
|
+
defines: SwiftManifestSetting[]
|
|
51
|
+
libraries: SwiftManifestSetting[]
|
|
52
|
+
nativeSettings: {
|
|
53
|
+
tool: 'c' | 'cxx'
|
|
54
|
+
flags: string[]
|
|
55
|
+
configuration: 'debug' | 'release' | null
|
|
56
|
+
}[]
|
|
51
57
|
/** true when the target declares `resources:`. */
|
|
52
58
|
declaresResources: boolean
|
|
59
|
+
/** public header directory relative to the target, as SwiftPM declares it. */
|
|
60
|
+
publicHeadersPath: string
|
|
53
61
|
/** a binary target's archive url; a local one's artifact is `dir`. */
|
|
54
62
|
url: string | null
|
|
55
63
|
/** the declared SHA-256 for a remote binary archive. */
|
|
@@ -80,7 +88,7 @@ function swiftCommand(): { file: string; args: string[] } {
|
|
|
80
88
|
: { file: path.join(swiftToolchainBin(lock.release), 'swift'), args: [] }
|
|
81
89
|
}
|
|
82
90
|
|
|
83
|
-
const cacheDir = path.join(
|
|
91
|
+
const cacheDir = path.join(peachCacheDir(), 'swift-manifests')
|
|
84
92
|
const evaluated = new Map<string, SwiftPackageManifest>()
|
|
85
93
|
|
|
86
94
|
function dump(dir: string): { key: string; raw: Record<string, Json> } {
|
|
@@ -108,6 +116,7 @@ function dump(dir: string): { key: string; raw: Record<string, Json> } {
|
|
|
108
116
|
[
|
|
109
117
|
...command.args,
|
|
110
118
|
'package',
|
|
119
|
+
...swiftPackageCacheOptions(),
|
|
111
120
|
'--package-path',
|
|
112
121
|
dir,
|
|
113
122
|
// swiftpm's scratch files never land in the app's own package
|
|
@@ -117,6 +126,7 @@ function dump(dir: string): { key: string; raw: Record<string, Json> } {
|
|
|
117
126
|
],
|
|
118
127
|
{
|
|
119
128
|
encoding: 'utf8',
|
|
129
|
+
env: swiftEnvironment(),
|
|
120
130
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
121
131
|
maxBuffer: 64 * 1024 * 1024,
|
|
122
132
|
},
|
|
@@ -249,10 +259,42 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
249
259
|
}
|
|
250
260
|
let languageMode = packageMode
|
|
251
261
|
let mainActorIsolation = false
|
|
252
|
-
const defines:
|
|
262
|
+
const defines: SwiftManifestSetting[] = []
|
|
263
|
+
const libraries: SwiftManifestSetting[] = []
|
|
264
|
+
const nativeSettings: SwiftManifestTarget['nativeSettings'] = []
|
|
265
|
+
for (const [tool, standard] of [
|
|
266
|
+
['c', string(raw.cLanguageStandard)],
|
|
267
|
+
['cxx', string(raw.cxxLanguageStandard)],
|
|
268
|
+
] satisfies ['c' | 'cxx', string | undefined][]) {
|
|
269
|
+
if (standard)
|
|
270
|
+
nativeSettings.push({ tool, flags: [`-std=${standard}`], configuration: null })
|
|
271
|
+
}
|
|
253
272
|
for (const setting of array(target.settings)) {
|
|
254
273
|
const { kind: rawKind, tool, condition } = record(setting)
|
|
255
274
|
const settingKind = record(rawKind)
|
|
275
|
+
if ((tool === 'c' || tool === 'cxx') && linksOnIOS(condition, traits)) {
|
|
276
|
+
const config = string(record(condition).config)
|
|
277
|
+
const header = string(record(settingKind.headerSearchPath)._0)
|
|
278
|
+
const definition = string(record(settingKind.define)._0)
|
|
279
|
+
const value = string(record(settingKind.define)._1)
|
|
280
|
+
const unsafe = record(settingKind.unsafeFlags)._0
|
|
281
|
+
const flags = header
|
|
282
|
+
? ['-I', path.resolve(targetDir, header)]
|
|
283
|
+
: definition
|
|
284
|
+
? [`-D${definition}${value === undefined ? '' : `=${value}`}`]
|
|
285
|
+
: Array.isArray(unsafe)
|
|
286
|
+
? unsafe.flatMap((flag) => string(flag) ?? [])
|
|
287
|
+
: null
|
|
288
|
+
if (!flags)
|
|
289
|
+
throw new Error(
|
|
290
|
+
`${name}: unsupported ${tool} compiler setting ${JSON.stringify(rawKind)}`,
|
|
291
|
+
)
|
|
292
|
+
nativeSettings.push({
|
|
293
|
+
tool,
|
|
294
|
+
flags,
|
|
295
|
+
configuration: config === 'debug' || config === 'release' ? config : null,
|
|
296
|
+
})
|
|
297
|
+
}
|
|
256
298
|
const mode = string(record(settingKind.swiftLanguageMode)._0)
|
|
257
299
|
if (mode)
|
|
258
300
|
languageMode = Math.max(5, Number(/^(\d+)/.exec(mode)?.[1] ?? languageMode))
|
|
@@ -271,6 +313,14 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
271
313
|
configuration: config === 'debug' || config === 'release' ? config : null,
|
|
272
314
|
})
|
|
273
315
|
}
|
|
316
|
+
const library = string(record(settingKind.linkedLibrary)._0)
|
|
317
|
+
if (library && string(tool) === 'linker' && linksOnIOS(condition, traits)) {
|
|
318
|
+
const config = string(record(condition).config)
|
|
319
|
+
libraries.push({
|
|
320
|
+
name: library,
|
|
321
|
+
configuration: config === 'debug' || config === 'release' ? config : null,
|
|
322
|
+
})
|
|
323
|
+
}
|
|
274
324
|
}
|
|
275
325
|
targets.set(name, {
|
|
276
326
|
name,
|
|
@@ -285,7 +335,10 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
285
335
|
languageMode,
|
|
286
336
|
mainActorIsolation,
|
|
287
337
|
defines,
|
|
338
|
+
libraries,
|
|
339
|
+
nativeSettings,
|
|
288
340
|
declaresResources: array(target.resources).length > 0,
|
|
341
|
+
publicHeadersPath: string(target.publicHeadersPath) ?? 'include',
|
|
289
342
|
url: string(target.url) ?? null,
|
|
290
343
|
checksum: string(target.checksum) ?? null,
|
|
291
344
|
})
|
package/src/swift-package.ts
CHANGED
|
@@ -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, [
|
|
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
|
? []
|