|
23 | 23 |
|
24 | 24 | const { |
25 | 25 | BUILTIN_FRAMEWORKS, |
| 26 | + FLAVORED_FRAMEWORKS_MANIFEST, |
26 | 27 | readFlavoredFrameworksManifest, |
27 | 28 | readPluginFrameworks, |
28 | 29 | } = require('./flavored-frameworks'); |
@@ -2285,10 +2286,20 @@ function pbxListValues(list /*: string */) /*: Array<string> */ { |
2285 | 2286 | * machine with the plugin frameworks the injected project links. Only `spm |
2286 | 2287 | * add` / `spm update` change what the project links, so the build-time sync |
2287 | 2288 | * reports a mismatch instead of fixing it: one `error:` line per framework, |
2288 | | - * then PluginFrameworkMismatchError. Never writes the project. |
| 2289 | + * then PluginFrameworkMismatchError. Never writes the project. Checks the |
| 2290 | + * project Xcode is building (`PROJECT_FILE_PATH`) when it is injected. |
2289 | 2291 | */ |
2290 | | -function assertPluginFrameworksLinked(appRoot /*: string */) /*: void */ { |
2291 | | - const xcodeprojPath = findInjectedXcodeproj(appRoot); |
| 2292 | +function assertPluginFrameworksLinked( |
| 2293 | + appRoot /*: string */, |
| 2294 | + env /*: {+[string]: ?string} */ = process.env, |
| 2295 | +) /*: void */ { |
| 2296 | + const builtProjectPath = env.PROJECT_FILE_PATH; |
| 2297 | + const xcodeprojPath = |
| 2298 | + builtProjectPath != null && |
| 2299 | + builtProjectPath.endsWith('.xcodeproj') && |
| 2300 | + fs.existsSync(path.join(builtProjectPath, SPM_INJECTED_MARKER)) |
| 2301 | + ? builtProjectPath |
| 2302 | + : findInjectedXcodeproj(appRoot); |
2292 | 2303 | const rootUuid = |
2293 | 2304 | xcodeprojPath != null ? readMarker(xcodeprojPath)?.rootUuid : null; |
2294 | 2305 | if (xcodeprojPath == null || rootUuid == null) { |
@@ -2316,36 +2327,47 @@ function assertPluginFrameworksLinked(appRoot /*: string */) /*: void */ { |
2316 | 2327 | const outputs = pbxListValues( |
2317 | 2328 | findField(text, embedPhase, 'outputPaths')?.value ?? '', |
2318 | 2329 | ); |
2319 | | - const builtinPrefixes = new Set( |
2320 | | - BUILTIN_FRAMEWORKS.map(framework => frameworkSettingPrefix(framework.id)), |
| 2330 | + const linkedPrefixes = new Set( |
| 2331 | + inputs.map(input => /^\$\((RN_SPM_\w+)_FRAMEWORK\)$/.exec(input)?.[1]), |
2321 | 2332 | ); |
2322 | | - const linkedPluginNames /*: Map<string, string> */ = new Map(); |
2323 | | - inputs |
2324 | | - .map(input => /^\$\((RN_SPM_\w+)_FRAMEWORK\)$/.exec(input)?.[1]) |
2325 | | - .filter(Boolean) |
2326 | | - .forEach((prefix, index) => { |
2327 | | - if (!builtinPrefixes.has(prefix)) { |
2328 | | - linkedPluginNames.set( |
2329 | | - prefix, |
2330 | | - path.basename(outputs[index] ?? prefix, '.framework'), |
2331 | | - ); |
2332 | | - } |
2333 | | - }); |
| 2333 | + // Built-in framework names come from the staged manifest. Without it, only |
| 2334 | + // setting prefixes are compared: a missing manifest is not a plugin mismatch. |
| 2335 | + let linkedPluginNames /*: ?Set<string> */ = null; |
| 2336 | + if ( |
| 2337 | + fs.existsSync( |
| 2338 | + path.join(appRoot, 'build', 'xcframeworks', FLAVORED_FRAMEWORKS_MANIFEST), |
| 2339 | + ) |
| 2340 | + ) { |
| 2341 | + const builtinIds = new Set(BUILTIN_FRAMEWORKS.map(({id}) => id)); |
| 2342 | + const builtinNames = new Set( |
| 2343 | + readFlavoredFrameworksManifest(appRoot) |
| 2344 | + .frameworks.filter(framework => builtinIds.has(framework.id)) |
| 2345 | + .map(framework => framework.frameworkName), |
| 2346 | + ); |
| 2347 | + linkedPluginNames = new Set( |
| 2348 | + outputs |
| 2349 | + .map(output => path.basename(output, '.framework')) |
| 2350 | + .filter(name => !builtinNames.has(name)), |
| 2351 | + ); |
| 2352 | + } |
2334 | 2353 |
|
2335 | 2354 | const pluginFrameworks = readPluginFrameworks(appRoot); |
2336 | | - const pairedPrefixes = new Set( |
2337 | | - pluginFrameworks.map(framework => frameworkSettingPrefix(framework.id)), |
| 2355 | + const pairedNames = new Set( |
| 2356 | + pluginFrameworks.map(framework => framework.frameworkName), |
2338 | 2357 | ); |
2339 | 2358 | const problems /*: Array<string> */ = []; |
2340 | 2359 | for (const {id, frameworkName} of pluginFrameworks) { |
2341 | | - if (!linkedPluginNames.has(frameworkSettingPrefix(id))) { |
| 2360 | + if ( |
| 2361 | + !linkedPrefixes.has(frameworkSettingPrefix(id)) || |
| 2362 | + linkedPluginNames?.has(frameworkName) === false |
| 2363 | + ) { |
2342 | 2364 | problems.push( |
2343 | 2365 | `error: ${frameworkName} (${id}) is a precompiled framework from an autolinking plugin, but the Xcode project does not link it. Run \`npx react-native spm\` to update the project.`, |
2344 | 2366 | ); |
2345 | 2367 | } |
2346 | 2368 | } |
2347 | | - for (const [prefix, frameworkName] of linkedPluginNames) { |
2348 | | - if (!pairedPrefixes.has(prefix)) { |
| 2369 | + for (const frameworkName of linkedPluginNames ?? []) { |
| 2370 | + if (!pairedNames.has(frameworkName)) { |
2349 | 2371 | problems.push( |
2350 | 2372 | `error: The Xcode project links ${frameworkName}.framework, but no autolinking plugin provides it on this machine. Precompile ${frameworkName}, or run \`npx react-native spm\` to update the project.`, |
2351 | 2373 | ); |
|
0 commit comments