/
githubmr
/
facebook-react-native
Обзор
Документация
Войти
/
githubmr
/
facebook-react-native
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
packages/react-native/scripts/swiftpm/headers-utils.js
282 строки
9 KB
Riccardo Cipolleschi
add function hard links for headers from ReactCodegen (#53640)
22 сен 2025, 20:14
22 сен 2025, 20:14
c6395ec
Код
Авторство
О чём код?
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow strict-local * @format */ const {reactCommonMappings} = require('./headers-mappings'); const {listHeadersInFolder, setupSymlink} = require('./utils'); const fs = require('fs'); const path = require('path'); /** * Helper function to create symlinks from a source path * @param {string} sourcePath - Source directory to search for headers * @param {string} outputPath - Default output directory for symlinks * @param {boolean} preserveStructure - Whether to preserve directory structure * @param {Array<string>} excludeFolders - Folder names to exclude * @returns {number} Number of symlinks created */ function symlinkHeadersFromPath( sourcePath /*: string */, outputPath /*: string */, preserveStructure /*: boolean */, excludeFolders /*: Array<string> */, ) /*: number */ { let linkedCount = 0; try { // Build find command with exclusions using -prune const headerFiles = listHeadersInFolder(sourcePath, excludeFolders); headerFiles.forEach(sourceHeaderPath => { if (fs.existsSync(sourceHeaderPath)) { const relativePath = path.relative(sourcePath, sourceHeaderPath); let destPath = ''; let mappedOutputPath = outputPath; if (preserveStructure) { // Preserve directory structure destPath = path.join(mappedOutputPath, relativePath); } else { // Flatten structure - just use the header filename const headerName = path.basename(sourceHeaderPath); destPath = path.join(mappedOutputPath, headerName); } // Create destination directory if it doesn't exist setupSymlink(sourceHeaderPath, destPath); linkedCount++; } }); } catch (error) { console.warn( `Failed to process headers from ${sourcePath}:`, error.message, ); } return linkedCount; } /** * Create symlinks for ReactApple headers with special path logic. * ReactApple has a custom structure, which is: * * ReactApple * ├── Libraries * │ └── RCTFoundation * │ ├── RCTDeprecation * │ │ ├── BUCK * │ │ ├── Exported * │ │ │ └── RCTDeprecation.h * │ │ ├── RCTDeprecation.m * │ │ ├── RCTDeprecation.podspec * │ │ └── README.md * │ └── README.md * └── README.md * * We need to create symlinks for the headers in the "Exported" folder to * the headersOutput/<parent-of-Exported> folder. * @param {string} reactApplePath - Path to ReactApple directory * @param {string} headersOutput - Base headers output directory * @returns {number} Number of symlinks created */ function symlinkReactAppleHeaders( reactApplePath /*: string */, headersOutput /*: string */, ) /*: number */ { let linkedCount = 0; const mappings /*: {[string]: string } */ = {}; mappings[ `${reactApplePath}/Libraries/RCTFoundation/RCTDeprecation/Exported` ] = `${headersOutput}/RCTDeprecation`; // Iterate over the key-value pairs of the mappings object for (const [sourceDir, destDir] of Object.entries(mappings)) { const headerFiles = listHeadersInFolder(sourceDir, ['tests']); headerFiles.forEach(sourceHeaderPath => { const destFilePath = path.join(destDir, path.basename(sourceHeaderPath)); setupSymlink(sourceHeaderPath, destFilePath); linkedCount++; }); } return linkedCount; } /** * Create symlinks for ReactCommon headers with conditional path logic * The proper way to map ReactCommon headers is a bit complicated, because we it collects * packages that needs linking in various ways: * - Headers in the react/renderer subpath needs to be mapped to React folder * - Platform specific code in * react/renderer/components/<component>/platform/ios/react/renderer/components/<component>/<headers> * needs to be flattened to react/renderer/components/<component>/<headers>. * - Some headers related to TurboModules needs to be mapped to ReactCommon * - Some modules in specific folders, such as oscompat, needs to be mapped to their parent folder. * - Yoga structure which is ReactCommon/yoga/yoga/<public-headers> need to be flattened to just yoga/<public-headers>. * * This function implement the basic logic of scanning the ReactCommon folder and proceed with the mapping * by following the rules above. It can also be customized by passing an array of path that needs to be flattened * and a map of special mapping objects. * @param {string} reactCommonPath - Path to ReactCommon directory * @param {string} headersOutput - Base headers output directory * @returns {number} Number of symlinks created */ function symlinkReactCommonHeaders( reactCommonPath /*: string */, headersOutput /*: string */, ) /*: number */ { let linkedCount = 0; const mappings = reactCommonMappings(reactCommonPath, headersOutput); // Iterate over the key-value pairs of the mappings object for (const [sourceDir, options] of Object.entries(mappings)) { const headerFiles = listHeadersInFolder(sourceDir, options.excludeFolders); headerFiles.forEach(sourceHeaderPath => { const relativePath = path.relative(sourceDir, sourceHeaderPath); let destPath = ''; let mappedOutputPath = options.destination; if (options.preserveStructure) { // Preserve directory structure destPath = path.join(mappedOutputPath, relativePath); } else { // Flatten structure - just use the header filename const headerName = path.basename(sourceHeaderPath); destPath = path.join(mappedOutputPath, headerName); } setupSymlink(sourceHeaderPath, destPath); linkedCount++; }); } return linkedCount; } /** * Create symlinks for third-party dependencies headers in the output folder * @param {string} reactNativePath - Path to the React Native directory * @param {string} outputFolder - Path to the output folder * @param {string} folderName - Name of the folder where headers will be created (default: 'headers') * @returns {number} Number of symlinks created */ function symlinkThirdPartyDependenciesHeaders( reactNativePath /*: string */, outputFolder /*: string */, folderName /*: string */ = 'headers', ) /*: number */ { console.log('Creating symlinks for Third-Party Dependencies headers...'); // Look for ReactNativeDependencies.xcframework/Headers folder specifically const thirdPartyHeadersPath = path.join( reactNativePath, 'third-party', 'ReactNativeDependencies.xcframework', 'Headers', ); if (!fs.existsSync(thirdPartyHeadersPath)) { console.warn( `Third-party dependencies headers path does not exist: ${thirdPartyHeadersPath}`, ); return 0; } const headersOutput = path.join(outputFolder, folderName); let linkedCount = 0; // No custom mappings needed for third-party dependencies const headerFiles = listHeadersInFolder(thirdPartyHeadersPath, ['tests']); headerFiles.forEach(sourceHeaderPath => { if (fs.existsSync(sourceHeaderPath)) { // Calculate relative path from Headers base to preserve structure const relativePath = path.relative( thirdPartyHeadersPath, sourceHeaderPath, ); const destPath = path.join(headersOutput, relativePath); setupSymlink(sourceHeaderPath, destPath); linkedCount++; } }); console.log( `Created symlinks for ${linkedCount} Third-Party Dependencies headers with preserved directory structure`, ); return linkedCount; } /** * Create symlinks for Codegen headers in the output folder */ function symlinkCodegenHeaders( reactNativePath /*: string */, iosAppPath /*: string */, outputFolder /*: string */, ) /*: number */ { console.log('Creating symlinks for Codegen headers...'); // Look for ReactCodegen folder specifically const reactCodegenPath = path.join( iosAppPath, 'build', 'generated', 'ios', 'ReactCodegen', ); if (!fs.existsSync(reactCodegenPath)) { console.warn(`ReactCodegen path does not exist: ${reactCodegenPath}`); return 0; } const headersOutput = path.join(outputFolder, 'headers'); const reactCodegenHeadersOutput = path.join(headersOutput, 'ReactCodegen'); let linkedCount = 0; // No custom mappings needed for codegen headers const headerFiles = listHeadersInFolder(reactCodegenPath, [ 'headers', 'tests', ]); headerFiles.forEach(sourcePath => { if (fs.existsSync(sourcePath)) { // Calculate relative path from ReactCodegen base const relativePath = path.relative(reactCodegenPath, sourcePath); let destPath /*: string */ = ''; // If relative path contains no subpath (just a filename), put it in ReactCodegen folder if (path.dirname(relativePath) === '.') { destPath = path.join(reactCodegenHeadersOutput, relativePath); } else { // Otherwise, preserve the structure under headers/ destPath = path.join(headersOutput, relativePath); } setupSymlink(sourcePath, destPath); linkedCount++; } }); console.log( `Created symlinks for ${linkedCount} Codegen headers with conditional directory structure`, ); return linkedCount; } module.exports = { symlinkHeadersFromPath, symlinkReactAppleHeaders, symlinkReactCommonHeaders, symlinkThirdPartyDependenciesHeaders, symlinkCodegenHeaders, };