mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: When copying bundle files from the platform folders in the .build output, the script had a bug where all bundles were copied - meaning that only the last one would be in the resulting xcframework output. This caused an issue when we tried to publish an app built with precompiled binaries to AppStore where the field `CFBundleSupportedPlatforms` was wrong and caused the submission to be rejected. This was caused by the script copying the wrong bundle file into the final xcframework outputs. This issue is described here: https://github.com/react-native-community/discussions-and-proposals/discussions/923#discussioncomment-14089245 This commit fixes the above error by using the iOS 15 `vtool` to show the actual platform for a given framework and then making sure we don't copy bundles in the wrong way. Testing this on my local machine for iOS/iOS-simulator/MacOS/catalyst yields the following results (before/after this fix): **Before:** ```bash Copying bundles to the framework... ../.build/Build/Products/Debug/ReactNativeDependencies_glog.bundle → ios-arm64 ../.build/Build/Products/Debug/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug/ReactNativeDependencies_glog.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug/ReactNativeDependencies_boost.bundle → ios-arm64 ../.build/Build/Products/Debug/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug/ReactNativeDependencies_boost.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug/ReactNativeDependencies_folly.bundle → ios-arm64 ../.build/Build/Products/Debug/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug/ReactNativeDependencies_folly.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_glog.bundle → ios-arm64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_glog.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_boost.bundle → ios-arm64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_boost.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_folly.bundle → ios-arm64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_folly.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_glog.bundle → ios-arm64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_glog.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_boost.bundle → ios-arm64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_boost.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_folly.bundle → ios-arm64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_folly.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_glog.bundle → ios-arm64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_glog.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_boost.bundle → ios-arm64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_boost.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_folly.bundle → ios-arm64 ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_folly.bundle → macos-arm64_x86_64 ``` **After:** ```bash Copying bundles to the framework... ../.build/Build/Products/Debug/ReactNativeDependencies_glog.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug/ReactNativeDependencies_boost.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug/ReactNativeDependencies_folly.bundle → macos-arm64_x86_64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_glog.bundle → ios-arm64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_boost.bundle → ios-arm64 ../.build/Build/Products/Debug-iphoneos/ReactNativeDependencies_folly.bundle → ios-arm64 ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-iphonesimulator/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-simulator ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_glog.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_boost.bundle → ios-arm64_x86_64-maccatalyst ../.build/Build/Products/Debug-maccatalyst/ReactNativeDependencies_folly.bundle → ios-arm64_x86_64-maccatalyst ``` ## Changelog: [IOS] [FIXED] - Fixed copying bundles correctly to xcframeworks when precompiling ReactNativeDependencies.xcframework Pull Request resolved: https://github.com/facebook/react-native/pull/53325 Test Plan: Ensure that the info.plist files in the nightlies for the ReactNativeDepdendencies.xcframework has the correct bundles for its targets. Reviewed By: andrewdacenko Differential Revision: D80457335 Pulled By: cipolleschi fbshipit-source-id: aeb4166f66218f72bdd29b6fc579fcc7b6d12844
194 lines
6.2 KiB
JavaScript
194 lines
6.2 KiB
JavaScript
/**
|
|
* 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
|
|
* @format
|
|
*/
|
|
|
|
const {HEADERS_FOLDER, TARGET_FOLDER} = require('./constants');
|
|
const {execSync} = require('child_process');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
/*::
|
|
import type { Dependency, Platform } from './types';
|
|
*/
|
|
|
|
/**
|
|
* Composes the final XCFramework from the artifacts in the build folder
|
|
*/
|
|
async function createFramework(
|
|
scheme /*: string */,
|
|
configuration /*: string */,
|
|
dependencies /*: $ReadOnlyArray<Dependency> */,
|
|
rootFolder /*: string */,
|
|
buildFolder /*: string */,
|
|
identity /*: ?string */,
|
|
) {
|
|
console.log('✅ Composing iOS XCFramework...');
|
|
|
|
// Get the build destination path from the prebuild step
|
|
const frameworksOutputFolder = path.join(buildFolder, 'Build', 'Products');
|
|
const frameworks = fs.readdirSync(frameworksOutputFolder);
|
|
console.log('Frameworks found:', frameworks.join(', '));
|
|
|
|
const frameworkPaths = frameworks.map(framework =>
|
|
path.join(frameworksOutputFolder, framework),
|
|
);
|
|
|
|
const output = path.join(rootFolder, `${scheme}.xcframework`);
|
|
|
|
// Check if output already exists and delete it
|
|
fs.rmSync(output, {recursive: true, force: true});
|
|
|
|
console.log('Output path:', output);
|
|
|
|
const frameworksArgs = frameworkPaths
|
|
.map(
|
|
framework =>
|
|
`-framework ${path.join(
|
|
framework,
|
|
'PackageFrameworks',
|
|
`${scheme}.framework`,
|
|
)}`,
|
|
)
|
|
.join(' ');
|
|
|
|
const command = `xcodebuild -create-xcframework ${frameworksArgs} -output ${output} `;
|
|
execSync(command, {stdio: 'inherit'});
|
|
|
|
// Copy bundles into the framework
|
|
copyBundles(scheme, dependencies, output, frameworkPaths);
|
|
|
|
// Copy headers to the framework - start by building the Header folder
|
|
await copyHeaders(scheme, dependencies, rootFolder);
|
|
|
|
// Copy Symbols to symbols folder
|
|
const symbolPaths = frameworkPaths.map(framework =>
|
|
path.join(framework, `${scheme}.framework.dSYM`),
|
|
);
|
|
console.log('Copying symbols to symbols folder...');
|
|
const symbolOutput = path.join(rootFolder, 'Symbols');
|
|
fs.mkdirSync(symbolOutput, {recursive: true});
|
|
symbolPaths.forEach(symbol => execSync(`cp -r ${symbol} ${symbolOutput}`));
|
|
|
|
if (identity) {
|
|
signXCFramework(identity, output);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copies headers needed from the package to a Header folder that we'll pass to
|
|
* each framework arch type
|
|
*/
|
|
async function copyHeaders(
|
|
scheme /*: string */,
|
|
dependencies /*: $ReadOnlyArray<Dependency> */,
|
|
rootFolder /*: string */,
|
|
) {
|
|
console.log('Copying header files for dependencies...');
|
|
|
|
// Create and clean the header folder
|
|
const headeDestinationFolder = path.join(
|
|
rootFolder,
|
|
`${scheme}.xcframework`,
|
|
'Headers',
|
|
);
|
|
fs.rmSync(headeDestinationFolder, {force: true, recursive: true});
|
|
fs.mkdirSync(headeDestinationFolder, {recursive: true});
|
|
|
|
// Now we can go through all dependencies and copy header files for each depencendy
|
|
dependencies.forEach(dep => {
|
|
const depHeaders = path.join(
|
|
rootFolder,
|
|
dep.name,
|
|
TARGET_FOLDER,
|
|
HEADERS_FOLDER,
|
|
);
|
|
|
|
// Copy all header files from the dependency to headerTempFolder
|
|
execSync(`cp -r ${depHeaders}/* ${headeDestinationFolder}/`);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Copies the bundles in the source frameworks to the target xcframework inside the xcframework's Resources folder
|
|
*/
|
|
function copyBundles(
|
|
scheme /*: string */,
|
|
dependencies /*: $ReadOnlyArray<Dependency> */,
|
|
outputFolder /*:string*/,
|
|
frameworkPaths /*:Array<string>*/,
|
|
) {
|
|
console.log('Copying bundles to the framework...');
|
|
// Let's precalculate the target folder. It is the xcframework's output folder with
|
|
// all its targets.
|
|
const targetArchFolders = fs
|
|
.readdirSync(outputFolder)
|
|
.map(p => path.join(outputFolder, p))
|
|
.filter(p => fs.statSync(p).isDirectory());
|
|
// For each framework (in frameworkPaths), copy the bundles from the source folder.
|
|
// A bundle is the name of the framework + _ + target name + .bundle. We can
|
|
// check if the target has a bundle by checking if it defines one or more resources.
|
|
frameworkPaths.forEach(frameworkPath => {
|
|
const frameworkPlatforms = execSync(
|
|
`vtool -show-build ${path.join(frameworkPath, 'PackageFrameworks', scheme + '.framework', scheme)}|grep platform`,
|
|
).toString();
|
|
dependencies.forEach(dep => {
|
|
const resources = dep.files.resources;
|
|
if (!resources || resources.length === 0) {
|
|
return;
|
|
}
|
|
// Get bundle source folder
|
|
const bundleName = `${scheme}_${dep.name}.bundle`;
|
|
const sourceBundlePath = path.join(frameworkPath, bundleName);
|
|
if (fs.existsSync(sourceBundlePath)) {
|
|
// Target folder - needs to be copied to the resulting framework
|
|
let targetArchFolderFound = false;
|
|
targetArchFolders.forEach(targetArchFolder => {
|
|
const targetPlatforms = execSync(
|
|
`vtool -show-build ${path.join(targetArchFolder, scheme + '.framework', scheme)}|grep platform`,
|
|
).toString();
|
|
|
|
if (targetPlatforms === frameworkPlatforms) {
|
|
console.log(
|
|
` ${path.relative(outputFolder, sourceBundlePath)} → ${path.basename(targetArchFolder)}`,
|
|
);
|
|
const targetBundlePath = path.join(
|
|
targetArchFolder,
|
|
`${scheme}.framework`,
|
|
bundleName,
|
|
);
|
|
|
|
// A bundle is a directory, so we need to copy the whole directory
|
|
execSync(`cp -r "${sourceBundlePath}/" "${targetBundlePath}"`);
|
|
targetArchFolderFound = true;
|
|
}
|
|
});
|
|
|
|
if (!targetArchFolderFound) {
|
|
throw Error(
|
|
`Could not find target architecture for folder ${path.relative(outputFolder, frameworkPath)}. Expected to find ${frameworkPlatforms}`,
|
|
);
|
|
}
|
|
} else {
|
|
console.warn(`Bundle ${sourceBundlePath} not found`);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function signXCFramework(
|
|
identity /*: string */,
|
|
xcframeworkPath /*: string */,
|
|
) {
|
|
console.log('Signing XCFramework...');
|
|
const command = `codesign --timestamp --sign "${identity}" ${xcframeworkPath}`;
|
|
execSync(command, {stdio: 'inherit'});
|
|
}
|
|
|
|
module.exports = {createFramework};
|