import { ExpoConfig } from '@expo/config-types'; import { XcodeProject } from 'xcode'; import { isNotComment } from './utils/Xcodeproj'; import { ConfigPlugin } from '../Plugin.types'; import { withXcodeProject } from '../plugins/ios-plugins'; import { addWarningIOS } from '../utils/warnings'; type Bitcode = NonNullable['bitcode']; /** * Plugin to set a bitcode preference for the Xcode project * based on the project's Expo config `ios.bitcode` value. */ export const withBitcode: ConfigPlugin = (config) => { return withXcodeProject(config, async (config) => { config.modResults = await setBitcodeWithConfig(config, { project: config.modResults, }); return config; }); }; /** * Plugin to set a custom bitcode preference for the Xcode project. * Does not read from the Expo config `ios.bitcode`. * * @param bitcode custom bitcode setting. */ export const withCustomBitcode: ConfigPlugin = (config, bitcode) => { return withXcodeProject(config, async (config) => { config.modResults = await setBitcode(bitcode, { project: config.modResults, }); return config; }); }; /** * Get the bitcode preference from the Expo config. */ export function getBitcode(config: Pick): Bitcode { return config.ios?.bitcode; } /** * Enable or disable the `ENABLE_BITCODE` property of the project configurations. */ export function setBitcodeWithConfig( config: Pick, { project }: { project: XcodeProject } ): XcodeProject { const bitcode = getBitcode(config); return setBitcode(bitcode, { project }); } /** * Enable or disable the `ENABLE_BITCODE` property. */ export function setBitcode(bitcode: Bitcode, { project }: { project: XcodeProject }): XcodeProject { const isDefaultBehavior = bitcode == null; // If the value is undefined, then do nothing. if (isDefaultBehavior) { return project; } const targetName = typeof bitcode === 'string' ? bitcode : undefined; const isBitcodeEnabled = !!bitcode; if (targetName) { // Assert if missing const configs = Object.entries(project.pbxXCBuildConfigurationSection()).filter(isNotComment); const hasConfiguration = configs.find(([, configuration]) => configuration.name === targetName); if (hasConfiguration) { // If targetName is defined then disable bitcode everywhere. project.addBuildProperty('ENABLE_BITCODE', 'NO'); } else { const names = [ // Remove duplicates, wrap in double quotes, and sort alphabetically. ...new Set(configs.map(([, configuration]) => `"${configuration.name}"`)), ].sort(); addWarningIOS( 'ios.bitcode', `No configuration named "${targetName}". Expected one of: ${names.join(', ')}.` ); } } project.addBuildProperty('ENABLE_BITCODE', isBitcodeEnabled ? 'YES' : 'NO', targetName); return project; }