peachsim 0.1.1635 → 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/README.md +5 -1
- package/cli/app-config.ts +14 -5
- package/cli/app-stubs.ts +62 -13
- package/cli/bridge-flow-runner.ts +2 -2
- package/cli/cloud-client.ts +60 -40
- package/cli/commands/doctor.ts +13 -5
- package/cli/commands/flow.ts +1 -1
- package/cli/commands/inspect/shared.ts +9 -4
- package/cli/commands/inspect.ts +65 -47
- package/cli/commands/preview.ts +1 -1
- package/cli/commands/record.ts +97 -47
- package/cli/commands/swift.ts +9 -3
- package/cli/commands/upload.ts +48 -42
- package/cli/drivers/playwright-sim-host.ts +65 -42
- package/cli/main.ts +1 -1
- package/cli/outbound-endpoints.ts +7 -5
- package/cli/pause-aware-timeout.ts +4 -0
- package/cli/ws-bridge.ts +19 -10
- package/detox/attempt-events.cjs +62 -5
- package/detox/attempt-events.d.cts +7 -0
- package/detox/expectations.ts +7 -3
- package/detox/index.ts +121 -47
- package/detox/motion-change.cjs +170 -21
- package/detox/motion-change.d.cts +32 -0
- 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 +1 -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 +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +4038 -1983
- 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 +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +509 -86
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +3551 -1574
- package/dist-lib/expo-swift-metadata.cjs +9 -7
- package/dist-lib/expo-swift-metadata.mjs +9 -7
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +43633 -2635
- 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 +2748 -128
- 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 +2547 -83
- package/dist-lib/native-app-identity-project.cjs +237 -50
- package/dist-lib/native-app-identity-project.mjs +237 -50
- package/dist-lib/native-app-identity.cjs +29 -30
- package/dist-lib/native-app-identity.mjs +29 -30
- 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 +2 -2
- package/dist-lib/react-native-host-modules.mjs +2 -2
- package/dist-lib/scripts/dev-server-scanner.cjs +8 -6
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +65403 -22739
- package/dist-lib/swift-compile.cjs +93 -32
- package/dist-lib/swift-compile.mjs +93 -32
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +7 -5
- package/dist-lib/swift-submit.mjs +7 -5
- package/dist-lib/swift-toolchain.cjs +316 -41
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +7335 -5432
- package/dist-lib/vite.cjs +2857 -12
- package/dist-lib/worklet-executable.cjs +14 -2
- package/dist-lib/worklet-executable.mjs +14 -2
- package/package.json +1 -1
- package/src/backend-origin.ts +13 -6
- package/src/expo-swift-host.ts +5 -2
- package/src/expoKotlinContract.ts +4 -7
- package/src/expoSwiftContract.ts +4 -6
- package/src/host/staged-host-files.ts +9 -0
- package/src/native-app-identity-project.ts +1 -4
- package/src/native-app-identity.ts +1 -4
- package/src/nativeAppIconContract.ts +1 -4
- package/src/output-lock-stdio.ts +36 -0
- package/src/react-native-bridge-modules.ts +21 -6
- package/src/react-native-host-modules.ts +4 -1
- package/src/settings-bundle.ts +1 -4
- package/src/swift-compile.ts +91 -33
- package/src/swift-distribution.lock.json +22 -12
- package/src/swift-distribution.ts +103 -4
- package/src/swift-host.ts +89 -26
- package/src/swift-icu.ts +16 -10
- package/src/swift-objc-compile.ts +355 -0
- package/src/swift-objc-sdk.ts +689 -18
- package/src/swift-objc-standin.ts +126 -14
- package/src/swift-package-manifest.ts +39 -1
- package/src/swift-packages.ts +35 -21
- package/src/swift-standin-emit.ts +40 -7
- package/src/swift-standins.ts +404 -138
- package/src/swift-submit.ts +3 -5
- package/src/swift-toolchain.ts +378 -46
- package/src/worker-system-chunks.ts +11 -12
- package/src/worklet-executable.ts +19 -1
- package/src/xcode-project.ts +270 -30
package/src/xcode-project.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// reads an xcode project's application target the way xcode builds it: the
|
|
2
2
|
// swift sources and resources that are members of the target, the local
|
|
3
3
|
// swift packages its products come from, the remote package products it links,
|
|
4
|
-
// and the build settings that change how its swift compiles.
|
|
5
|
-
//
|
|
4
|
+
// and the build settings that change how its swift compiles. project opening
|
|
5
|
+
// prepares declared generated swift sources without running xcode. the project
|
|
6
|
+
// file is data: project.pbxproj, or
|
|
6
7
|
// xcode 27.2's json project.xcproj, which xcode-json-project.ts reads into
|
|
7
8
|
// the same object table.
|
|
8
9
|
|
|
10
|
+
import { execFileSync } from 'node:child_process'
|
|
11
|
+
import { createHash } from 'node:crypto'
|
|
9
12
|
import fs from 'node:fs'
|
|
10
13
|
import path from 'node:path'
|
|
11
14
|
import plist from 'plist'
|
|
@@ -45,6 +48,19 @@ export interface XcodeModuleTarget {
|
|
|
45
48
|
mainActorIsolation: boolean
|
|
46
49
|
/** the compilation conditions the build configuration defines, as `-D` passes them. */
|
|
47
50
|
defines: string[]
|
|
51
|
+
/** the resolved source iOS minimum, including for native package dependencies. */
|
|
52
|
+
iosDeploymentTarget: string | null
|
|
53
|
+
/** original implementation inputs and clang settings, before any declaration import. */
|
|
54
|
+
objc?: {
|
|
55
|
+
headers: string[]
|
|
56
|
+
prefixHeader: string | null
|
|
57
|
+
bridgingHeader: string | null
|
|
58
|
+
headerSearchPaths: string[]
|
|
59
|
+
frameworkSearchPaths: string[]
|
|
60
|
+
flags: string[]
|
|
61
|
+
cxxFlags: string[]
|
|
62
|
+
fileFlags: Record<string, string[]>
|
|
63
|
+
}
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
/** an application target, resolved to files on disk with everything it builds. */
|
|
@@ -72,8 +88,8 @@ export interface XcodeAppTarget extends XcodeModuleTarget {
|
|
|
72
88
|
localPackageDirs: string[]
|
|
73
89
|
/** prebuilt frameworks and xcframeworks the projects vendor and link, at their path when it resolves. */
|
|
74
90
|
binaryFrameworks: { name: string; path: string | null }[]
|
|
75
|
-
/**
|
|
76
|
-
packageResolved: string
|
|
91
|
+
/** workspace pins, or local package locks when the workspace has no lock. */
|
|
92
|
+
packageResolved: string[]
|
|
77
93
|
/** every application target in the workspace, for a chooser. */
|
|
78
94
|
appTargets: string[]
|
|
79
95
|
/** the build configuration every target's settings are read in. */
|
|
@@ -498,14 +514,17 @@ function expand(value: string, lookup: (name: string) => string): string {
|
|
|
498
514
|
)
|
|
499
515
|
}
|
|
500
516
|
|
|
517
|
+
const preparedSourcePhases = new Map<string, string>()
|
|
518
|
+
|
|
501
519
|
// the swift sources and resources that are members of a target.
|
|
502
|
-
//
|
|
503
|
-
//
|
|
504
|
-
// the script instead of silently dropping the file.
|
|
520
|
+
// metadata-only reads never execute scripts. opening a project prepares the
|
|
521
|
+
// declared swift outputs with the project's own shell and build settings.
|
|
505
522
|
function targetMembers(
|
|
506
523
|
ref: TargetRef,
|
|
507
524
|
settings: (key: string) => string,
|
|
508
|
-
options: { requireSources?: boolean
|
|
525
|
+
options: { requireSources?: boolean; prepareGeneratedSources?: boolean },
|
|
526
|
+
settingKeys: Set<string>,
|
|
527
|
+
projectInputs: Set<string>,
|
|
509
528
|
): {
|
|
510
529
|
sources: string[]
|
|
511
530
|
resources: string[]
|
|
@@ -517,30 +536,137 @@ function targetMembers(
|
|
|
517
536
|
const allSources = new Set<string>()
|
|
518
537
|
const resources = new Set<string>()
|
|
519
538
|
const scriptForOutput = new Map<string, string>()
|
|
520
|
-
const noteScriptOutput = (raw: string, script: string) => {
|
|
521
|
-
const expanded = expand(raw, settings)
|
|
522
|
-
if (!expanded.endsWith('.swift')) return
|
|
523
|
-
const absolute = path.isAbsolute(expanded)
|
|
524
|
-
? path.normalize(expanded)
|
|
525
|
-
: path.resolve(project.projectDir, expanded)
|
|
526
|
-
if (!scriptForOutput.has(absolute)) scriptForOutput.set(absolute, script)
|
|
527
|
-
}
|
|
528
539
|
for (const phaseId of list(target.buildPhases)) {
|
|
529
540
|
const phase = project.object(phaseId)
|
|
530
541
|
if (phase?.isa !== 'PBXShellScriptBuildPhase') continue
|
|
531
542
|
const script = str(phase.name) ?? phaseId
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
+
const absolute = (raw: string) =>
|
|
544
|
+
path.resolve(project.projectDir, expand(raw, settings))
|
|
545
|
+
const inputs = list(phase.inputPaths).map(absolute)
|
|
546
|
+
const outputs = list(phase.outputPaths).map(absolute)
|
|
547
|
+
const fileLists = new Map<string, { file: string; entries: string[] }[]>()
|
|
548
|
+
for (const kind of ['INPUT', 'OUTPUT']) {
|
|
549
|
+
const lists = list(
|
|
550
|
+
kind === 'INPUT' ? phase.inputFileListPaths : phase.outputFileListPaths,
|
|
551
|
+
).map((raw) => {
|
|
552
|
+
const file = absolute(raw)
|
|
553
|
+
if (!fs.existsSync(file)) {
|
|
554
|
+
return { file, entries: [] }
|
|
555
|
+
}
|
|
556
|
+
const entries = fs
|
|
557
|
+
.readFileSync(file, 'utf8')
|
|
558
|
+
.split(/\r?\n/)
|
|
559
|
+
.map((line) => line.trim())
|
|
560
|
+
.filter((line) => line !== '' && !line.startsWith('#'))
|
|
561
|
+
.map(absolute)
|
|
562
|
+
return { file, entries }
|
|
563
|
+
})
|
|
564
|
+
fileLists.set(kind, lists)
|
|
565
|
+
}
|
|
566
|
+
const allOutputs = [
|
|
567
|
+
...outputs,
|
|
568
|
+
...fileLists.get('OUTPUT')!.flatMap((item) => item.entries),
|
|
569
|
+
]
|
|
570
|
+
for (const output of allOutputs)
|
|
571
|
+
if (output.endsWith('.swift') && !scriptForOutput.has(output))
|
|
572
|
+
scriptForOutput.set(output, script)
|
|
573
|
+
const inputFiles = [
|
|
574
|
+
...inputs,
|
|
575
|
+
...fileLists.get('INPUT')!.flatMap((item) => [item.file, ...item.entries]),
|
|
576
|
+
...fileLists.get('OUTPUT')!.map((item) => item.file),
|
|
577
|
+
]
|
|
578
|
+
if (allOutputs.some((file) => file.endsWith('.swift')))
|
|
579
|
+
for (const file of inputFiles) if (fs.existsSync(file)) projectInputs.add(file)
|
|
580
|
+
if (
|
|
581
|
+
options.prepareGeneratedSources &&
|
|
582
|
+
options.requireSources !== false &&
|
|
583
|
+
allOutputs.some((file) => file.endsWith('.swift'))
|
|
584
|
+
) {
|
|
585
|
+
const phaseDir = path.join(settings('TARGET_TEMP_DIR'), `Script-${phaseId}`)
|
|
586
|
+
for (const lists of fileLists.values())
|
|
587
|
+
for (const { file } of lists)
|
|
588
|
+
if (!fs.existsSync(file))
|
|
589
|
+
throw new Error(
|
|
590
|
+
`${targetName}: Run Script "${script}" missing file list ${file}`,
|
|
591
|
+
)
|
|
592
|
+
const env = {
|
|
593
|
+
...process.env,
|
|
594
|
+
...Object.fromEntries(
|
|
595
|
+
[...settingKeys]
|
|
596
|
+
.filter((key) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
597
|
+
.map((key) => [key, settings(key)]),
|
|
598
|
+
),
|
|
599
|
+
}
|
|
600
|
+
const declared = { INPUT: inputs, OUTPUT: outputs }
|
|
601
|
+
for (const kind of ['INPUT', 'OUTPUT'] satisfies (keyof typeof declared)[]) {
|
|
602
|
+
env[`SCRIPT_${kind}_FILE_COUNT`] = String(declared[kind].length)
|
|
603
|
+
declared[kind].forEach((file, index) => {
|
|
604
|
+
env[`SCRIPT_${kind}_FILE_${index}`] = file
|
|
605
|
+
})
|
|
606
|
+
const lists = fileLists.get(kind)!
|
|
607
|
+
env[`SCRIPT_${kind}_FILE_LIST_COUNT`] = String(lists.length)
|
|
608
|
+
lists.forEach((_item, index) => {
|
|
609
|
+
env[`SCRIPT_${kind}_FILE_LIST_${index}`] = path.join(
|
|
610
|
+
phaseDir,
|
|
611
|
+
`${kind}-${index}.xcfilelist`,
|
|
612
|
+
)
|
|
613
|
+
})
|
|
614
|
+
}
|
|
615
|
+
const signature = createHash('sha256').update(
|
|
616
|
+
JSON.stringify([phase, [...settingKeys].map((key) => [key, settings(key)])]),
|
|
617
|
+
)
|
|
618
|
+
for (const file of inputFiles) {
|
|
619
|
+
signature.update(file)
|
|
620
|
+
if (fs.existsSync(file)) {
|
|
621
|
+
const stat = fs.statSync(file)
|
|
622
|
+
signature.update(`${stat.mtimeMs}:${stat.ctimeMs}:${stat.size}`)
|
|
623
|
+
} else signature.update('missing')
|
|
624
|
+
}
|
|
625
|
+
const stamp = signature.digest('hex')
|
|
626
|
+
const key = `${project.projectFile}:${targetId}:${phaseId}:${settings('CONFIGURATION')}`
|
|
627
|
+
if (
|
|
628
|
+
preparedSourcePhases.get(key) === stamp &&
|
|
629
|
+
allOutputs.every((file) => fs.existsSync(file))
|
|
630
|
+
)
|
|
631
|
+
continue
|
|
632
|
+
fs.mkdirSync(phaseDir, { recursive: true })
|
|
633
|
+
fs.mkdirSync(settings('BUILT_PRODUCTS_DIR'), { recursive: true })
|
|
634
|
+
fs.mkdirSync(settings('DERIVED_FILE_DIR'), { recursive: true })
|
|
635
|
+
for (const [kind, lists] of fileLists)
|
|
636
|
+
lists.forEach((item, index) => {
|
|
637
|
+
fs.writeFileSync(
|
|
638
|
+
env[`SCRIPT_${kind}_FILE_LIST_${index}`]!,
|
|
639
|
+
`${item.entries.join('\n')}\n`,
|
|
640
|
+
)
|
|
641
|
+
})
|
|
642
|
+
try {
|
|
643
|
+
execFileSync(
|
|
644
|
+
str(phase.shellPath) ?? '/bin/sh',
|
|
645
|
+
['-c', str(phase.shellScript) ?? ''],
|
|
646
|
+
{
|
|
647
|
+
cwd: project.projectDir,
|
|
648
|
+
env,
|
|
649
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
650
|
+
timeout: 120_000,
|
|
651
|
+
},
|
|
652
|
+
)
|
|
653
|
+
} catch (error) {
|
|
654
|
+
const output =
|
|
655
|
+
error instanceof Error
|
|
656
|
+
? `${error.message}\n${'stdout' in error ? String(error.stdout) : ''}${'stderr' in error ? String(error.stderr) : ''}`
|
|
657
|
+
: String(error)
|
|
658
|
+
throw new Error(
|
|
659
|
+
`${targetName}: Run Script "${script}" failed preparing generated Swift sources:\n${output}`,
|
|
660
|
+
)
|
|
543
661
|
}
|
|
662
|
+
const missing = allOutputs.filter(
|
|
663
|
+
(file) => file.endsWith('.swift') && !fs.existsSync(file),
|
|
664
|
+
)
|
|
665
|
+
if (missing.length > 0)
|
|
666
|
+
throw new Error(
|
|
667
|
+
`${targetName}: Run Script "${script}" did not produce ${missing.join(', ')}`,
|
|
668
|
+
)
|
|
669
|
+
preparedSourcePhases.set(key, stamp)
|
|
544
670
|
}
|
|
545
671
|
}
|
|
546
672
|
visitXcodeTargetMembers(
|
|
@@ -769,7 +895,7 @@ export function readXcodeAppTarget(
|
|
|
769
895
|
input: string,
|
|
770
896
|
targetName?: string,
|
|
771
897
|
configurationName?: string,
|
|
772
|
-
options: { requireSources?: boolean } = {},
|
|
898
|
+
options: { requireSources?: boolean; prepareGeneratedSources?: boolean } = {},
|
|
773
899
|
): XcodeAppTarget {
|
|
774
900
|
// canonical, so every path returned agrees with the host's realpath checks
|
|
775
901
|
const xcodeprojOrWorkspace = fs.realpathSync(input)
|
|
@@ -881,22 +1007,112 @@ export function readXcodeAppTarget(
|
|
|
881
1007
|
SRCROOT: ref.project.projectDir,
|
|
882
1008
|
SOURCE_ROOT: ref.project.projectDir,
|
|
883
1009
|
PROJECT_DIR: ref.project.projectDir,
|
|
1010
|
+
SYMROOT: path.join(ref.project.projectDir, '.build/peach-xcode/Build/Products'),
|
|
1011
|
+
BUILD_DIR: '$(SYMROOT)',
|
|
1012
|
+
OBJROOT: path.join(
|
|
1013
|
+
ref.project.projectDir,
|
|
1014
|
+
'.build/peach-xcode/Build/Intermediates.noindex',
|
|
1015
|
+
),
|
|
1016
|
+
CONFIGURATION_BUILD_DIR:
|
|
1017
|
+
'$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)',
|
|
1018
|
+
BUILT_PRODUCTS_DIR: '$(CONFIGURATION_BUILD_DIR)',
|
|
1019
|
+
TARGET_BUILD_DIR: '$(CONFIGURATION_BUILD_DIR)',
|
|
1020
|
+
PROJECT_TEMP_DIR: '$(OBJROOT)/$(PROJECT_NAME).build',
|
|
1021
|
+
CONFIGURATION_TEMP_DIR:
|
|
1022
|
+
'$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)',
|
|
1023
|
+
TARGET_TEMP_DIR: '$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME).build',
|
|
1024
|
+
DERIVED_FILE_DIR: '$(TARGET_TEMP_DIR)/DerivedSources',
|
|
1025
|
+
DERIVED_FILES_DIR: '$(DERIVED_FILE_DIR)',
|
|
1026
|
+
PLATFORM_NAME: 'iphonesimulator',
|
|
1027
|
+
EFFECTIVE_PLATFORM_NAME: '-iphonesimulator',
|
|
1028
|
+
CURRENT_ARCH: 'arm64',
|
|
1029
|
+
ARCHS: 'arm64',
|
|
1030
|
+
ACTION: 'build',
|
|
884
1031
|
DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? 'en',
|
|
885
1032
|
},
|
|
886
1033
|
options,
|
|
887
1034
|
)
|
|
888
1035
|
for (const file of read) xcconfigs.add(file)
|
|
889
1036
|
const swiftVersion = Number.parseFloat(settings('SWIFT_VERSION') || '5')
|
|
1037
|
+
const members = targetMembers(ref, settings, options, keys, xcconfigs)
|
|
1038
|
+
const implementations = members.allSources.filter((file) =>
|
|
1039
|
+
/\.(c|cc|cpp|cxx|m|mm)$/.test(file),
|
|
1040
|
+
)
|
|
1041
|
+
const absolute = (file: string) => path.resolve(ref.project.projectDir, file)
|
|
1042
|
+
const fileFlags: Record<string, string[]> = {}
|
|
1043
|
+
for (const phaseId of list(ref.target.buildPhases)) {
|
|
1044
|
+
const phase = ref.project.object(phaseId)
|
|
1045
|
+
if (phase?.isa !== 'PBXSourcesBuildPhase') continue
|
|
1046
|
+
for (const id of list(phase.files)) {
|
|
1047
|
+
const file = ref.project.object(id)
|
|
1048
|
+
const resolved = ref.project.resolvePath(str(file?.fileRef) ?? '')
|
|
1049
|
+
if (resolved && implementations.includes(resolved))
|
|
1050
|
+
fileFlags[resolved] = settingList(
|
|
1051
|
+
expand(
|
|
1052
|
+
str(isDict(file?.settings) ? file.settings.COMPILER_FLAGS : undefined) ??
|
|
1053
|
+
'',
|
|
1054
|
+
settings,
|
|
1055
|
+
),
|
|
1056
|
+
)
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
890
1059
|
return {
|
|
891
1060
|
settings,
|
|
892
1061
|
keys,
|
|
893
1062
|
module: {
|
|
894
1063
|
name,
|
|
895
1064
|
moduleName: applyOperator(settings('PRODUCT_MODULE_NAME'), 'c99extidentifier'),
|
|
896
|
-
...
|
|
1065
|
+
...members,
|
|
897
1066
|
languageMode: swiftVersion >= 6 ? 6 : 5,
|
|
898
1067
|
mainActorIsolation: settings('SWIFT_DEFAULT_ACTOR_ISOLATION') === 'MainActor',
|
|
899
1068
|
defines: compilationConditions(settings),
|
|
1069
|
+
iosDeploymentTarget: settings('IPHONEOS_DEPLOYMENT_TARGET') || null,
|
|
1070
|
+
...(implementations.some((file) => /\.mm?$/.test(file))
|
|
1071
|
+
? {
|
|
1072
|
+
objc: {
|
|
1073
|
+
headers: Object.keys(ref.project.objects).flatMap((id) => {
|
|
1074
|
+
const file = ref.project.resolvePath(id)
|
|
1075
|
+
return file && /\.(h|hh|hpp|hxx|pch)$/.test(file) && fs.existsSync(file)
|
|
1076
|
+
? [file]
|
|
1077
|
+
: []
|
|
1078
|
+
}),
|
|
1079
|
+
prefixHeader: settings('GCC_PREFIX_HEADER')
|
|
1080
|
+
? absolute(settings('GCC_PREFIX_HEADER'))
|
|
1081
|
+
: null,
|
|
1082
|
+
bridgingHeader: settings('SWIFT_OBJC_BRIDGING_HEADER')
|
|
1083
|
+
? absolute(settings('SWIFT_OBJC_BRIDGING_HEADER'))
|
|
1084
|
+
: null,
|
|
1085
|
+
headerSearchPaths: [
|
|
1086
|
+
...settingList(settings('HEADER_SEARCH_PATHS')),
|
|
1087
|
+
...settingList(settings('USER_HEADER_SEARCH_PATHS')),
|
|
1088
|
+
].map(absolute),
|
|
1089
|
+
frameworkSearchPaths: settingList(settings('FRAMEWORK_SEARCH_PATHS')).map(
|
|
1090
|
+
absolute,
|
|
1091
|
+
),
|
|
1092
|
+
flags: [
|
|
1093
|
+
...(settings('CLANG_ENABLE_OBJC_ARC') === 'YES' ? ['-fobjc-arc'] : []),
|
|
1094
|
+
...(settings('CLANG_ENABLE_OBJC_WEAK') === 'YES'
|
|
1095
|
+
? ['-fobjc-weak']
|
|
1096
|
+
: []),
|
|
1097
|
+
...(settings('CLANG_ENABLE_MODULES') === 'YES' ? ['-fmodules'] : []),
|
|
1098
|
+
...(settings('GCC_C_LANGUAGE_STANDARD')
|
|
1099
|
+
? [`-std=${settings('GCC_C_LANGUAGE_STANDARD')}`]
|
|
1100
|
+
: []),
|
|
1101
|
+
...settingList(settings('GCC_PREPROCESSOR_DEFINITIONS')).map(
|
|
1102
|
+
(value) => `-D${value}`,
|
|
1103
|
+
),
|
|
1104
|
+
...settingList(settings('OTHER_CFLAGS')),
|
|
1105
|
+
],
|
|
1106
|
+
cxxFlags: [
|
|
1107
|
+
...(settings('CLANG_CXX_LANGUAGE_STANDARD')
|
|
1108
|
+
? [`-std=${settings('CLANG_CXX_LANGUAGE_STANDARD')}`]
|
|
1109
|
+
: []),
|
|
1110
|
+
...settingList(settings('OTHER_CPLUSPLUSFLAGS')),
|
|
1111
|
+
],
|
|
1112
|
+
fileFlags,
|
|
1113
|
+
},
|
|
1114
|
+
}
|
|
1115
|
+
: {}),
|
|
900
1116
|
} satisfies XcodeModuleTarget,
|
|
901
1117
|
}
|
|
902
1118
|
}
|
|
@@ -967,6 +1183,23 @@ export function readXcodeAppTarget(
|
|
|
967
1183
|
...projects.flatMap((project) =>
|
|
968
1184
|
Object.entries(project.objects).flatMap(([id, entry]) => {
|
|
969
1185
|
if (!isDict(entry)) return []
|
|
1186
|
+
if (entry.isa === 'PBXFileSystemSynchronizedRootGroup') {
|
|
1187
|
+
const folder = project.resolvePath(id)
|
|
1188
|
+
const pending = folder ? [folder] : []
|
|
1189
|
+
const packages: string[] = []
|
|
1190
|
+
while (pending.length > 0) {
|
|
1191
|
+
const dir = pending.pop()!
|
|
1192
|
+
if (fs.existsSync(path.join(dir, 'Package.swift'))) {
|
|
1193
|
+
packages.push(dir)
|
|
1194
|
+
continue
|
|
1195
|
+
}
|
|
1196
|
+
if (!isDirectory(dir)) continue
|
|
1197
|
+
for (const child of fs.readdirSync(dir, { withFileTypes: true }))
|
|
1198
|
+
if (child.isDirectory() && !child.name.startsWith('.'))
|
|
1199
|
+
pending.push(path.join(dir, child.name))
|
|
1200
|
+
}
|
|
1201
|
+
return packages
|
|
1202
|
+
}
|
|
970
1203
|
const candidate =
|
|
971
1204
|
entry.isa === 'XCLocalSwiftPackageReference'
|
|
972
1205
|
? path.resolve(project.projectDir, str(entry.relativePath) ?? '')
|
|
@@ -1046,6 +1279,13 @@ export function readXcodeAppTarget(
|
|
|
1046
1279
|
'Package.resolved',
|
|
1047
1280
|
)
|
|
1048
1281
|
|
|
1282
|
+
const packageResolved = fs.existsSync(resolvedFile)
|
|
1283
|
+
? [fs.realpathSync(resolvedFile)]
|
|
1284
|
+
: [...new Set(localPackageDirs.map((dir) => path.join(dir, 'Package.resolved')))]
|
|
1285
|
+
.filter((file) => fs.existsSync(file))
|
|
1286
|
+
.map((file) => fs.realpathSync(file))
|
|
1287
|
+
.sort()
|
|
1288
|
+
|
|
1049
1289
|
// the app is last in its own dependency order
|
|
1050
1290
|
const used = order.map((ref) => ref.project)
|
|
1051
1291
|
return {
|
|
@@ -1074,7 +1314,7 @@ export function readXcodeAppTarget(
|
|
|
1074
1314
|
binaryFrameworks: [...binaryFrameworks]
|
|
1075
1315
|
.map(([name, file]) => ({ name, path: file }))
|
|
1076
1316
|
.sort((left, right) => left.name.localeCompare(right.name)),
|
|
1077
|
-
packageResolved
|
|
1317
|
+
packageResolved,
|
|
1078
1318
|
appTargets: appTargetNames,
|
|
1079
1319
|
configuration,
|
|
1080
1320
|
settings,
|