diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 000000000..3186f3f07 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/packages/cli-config-apple/src/tools/installPods.ts b/packages/cli-config-apple/src/tools/installPods.ts index c9d4d1fa4..cbcbb0bdf 100644 --- a/packages/cli-config-apple/src/tools/installPods.ts +++ b/packages/cli-config-apple/src/tools/installPods.ts @@ -12,14 +12,16 @@ import { import runBundleInstall from './runBundleInstall'; interface PodInstallOptions { - skipBundleInstall?: boolean; newArchEnabled?: boolean; iosFolderPath?: string; + useBundler?: boolean; + root?: string; } interface RunPodInstallOptions { shouldHandleRepoUpdate?: boolean; newArchEnabled?: boolean; + useBundler?: boolean; } async function runPodInstall(loader: Ora, options: RunPodInstallOptions) { @@ -30,8 +32,10 @@ async function runPodInstall(loader: Ora, options: RunPodInstallOptions) { options?.newArchEnabled ? 'with New Architecture' : '', )} ${chalk.dim('(this may take a few minutes)')}`, ); + const command = options.useBundler ? 'bundle' : 'pod'; + const args = options.useBundler ? ['exec', 'pod', 'install'] : ['install']; - await execa('bundle', ['exec', 'pod', 'install'], { + await execa(command, args, { env: { RCT_NEW_ARCH_ENABLED: options?.newArchEnabled ? '1' : '0', RCT_IGNORE_PODS_DEPRECATION: '1', // From React Native 0.79 onwards, users shouldn't install CocoaPods manually. @@ -139,12 +143,8 @@ async function installPods(loader?: Ora, options?: PodInstallOptions) { return; } - if (fs.existsSync('../Gemfile') && !options?.skipBundleInstall) { + if (options?.useBundler) { await runBundleInstall(loader); - } else if (!fs.existsSync('../Gemfile')) { - throw new CLIError( - 'Could not find the Gemfile. Currently the CLI requires to have this file in the root directory of the project to install CocoaPods. If your configuration is different, please install the CocoaPods manually.', - ); } try { @@ -157,10 +157,11 @@ async function installPods(loader?: Ora, options?: PodInstallOptions) { await installCocoaPods(loader); } await runPodInstall(loader, { + useBundler: options?.useBundler, newArchEnabled: options?.newArchEnabled, }); } finally { - process.chdir('..'); + process.chdir(options?.root ?? '..'); } } diff --git a/packages/cli-config-apple/src/tools/pods.ts b/packages/cli-config-apple/src/tools/pods.ts index 1ca5693af..3cfb407ab 100644 --- a/packages/cli-config-apple/src/tools/pods.ts +++ b/packages/cli-config-apple/src/tools/pods.ts @@ -6,6 +6,7 @@ import { CLIError, cacheManager, getLoader, + logger, } from '@react-native-community/cli-tools'; import installPods from './installPods'; import { @@ -24,6 +25,18 @@ interface NativeDependencies { [key: string]: DependencyConfig; } +function checkGemfileForCocoaPods(gemfilePath: string): boolean { + try { + const gemfileContent = fs.readFileSync(gemfilePath, 'utf-8'); + // Check for common CocoaPods gem declarations, because some projects might have Gemfile but for other purposes + return /^\s*gem\s+['"]cocoapods['"]/.test(gemfileContent); + } catch (error) { + logger.debug(`Failed to read Gemfile at: ${gemfilePath}`); + logger.debug(String(error)); + return false; + } +} + function getPackageJson(root: string) { try { return require(path.join(root, 'package.json')); @@ -87,7 +100,6 @@ async function getChecksum( async function install( packageJson: Record, - cachedDependenciesHash: string | undefined, currentDependenciesHash: string, iosFolderPath: string, platform: string, @@ -101,9 +113,24 @@ async function install( platform, reactNativePath, }); + const gemfilePath = path.join(root, 'Gemfile'); + let useBundler = checkGemfileForCocoaPods(gemfilePath); + + if (!useBundler) { + logger.debug( + `Could not find the Gemfile at: ${chalk.cyan(gemfilePath)} + The default React Native Template uses Gemfile to leverage Ruby Bundler and we advice the same. + If you use Gemfile, make sure it's ${chalk.bold( + 'in the project root directory', + )}. + Falling back to installing CocoaPods using globally installed "pod".`, + ); + } + await installPods(loader, { - skipBundleInstall: !!cachedDependenciesHash, + useBundler, iosFolderPath, + root, }); cacheManager.set(packageJson.name, 'dependencies', currentDependenciesHash); loader.succeed(); @@ -161,7 +188,6 @@ export default async function resolvePods( if (options?.forceInstall) { await install( packageJson, - cachedDependenciesHash, currentDependenciesHash, platformFolderPath, platformName, @@ -182,17 +208,14 @@ export default async function resolvePods( currentPodfileLockChecksum ?? '', ); } else { - const loader = getLoader('Installing CocoaPods...'); try { - await installPods(loader, { - skipBundleInstall: !!cachedDependenciesHash, - newArchEnabled: options?.newArchEnabled, - iosFolderPath: platformFolderPath, - }); - cacheManager.set( - packageJson.name, - 'dependencies', + await install( + packageJson, currentDependenciesHash, + platformFolderPath, + platformName, + root, + reactNativePath, ); cacheManager.set(packageJson.name, 'podfile', currentPodfileHash); // We need to read again the checksum because value changed after running `pod install` @@ -202,9 +225,7 @@ export default async function resolvePods( 'podfileLock', currentPodfileLockChecksum ?? '', ); - loader.succeed(); } catch (error) { - loader.fail(); throw new CLIError( `Something when wrong while installing CocoaPods. Please run ${chalk.bold( 'pod install', diff --git a/packages/cli-config/src/schema.ts b/packages/cli-config/src/schema.ts index 0eb8e5013..cb229bd83 100644 --- a/packages/cli-config/src/schema.ts +++ b/packages/cli-config/src/schema.ts @@ -158,7 +158,9 @@ export const projectConfig = t automaticPodsInstallation: t.bool().default(true), assets: t.array().items(t.string()).default([]), }) - .default({}), + .default({ + automaticPodsInstallation: true, + }), android: t // AndroidProjectParams .object({ diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index 87c49f890..2441238b3 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -293,7 +293,9 @@ async function createFromTemplate({ platform: 'ios', reactNativePath, }); - await installPods(loader, {}); + await installPods(loader, { + useBundler: true, + }); loader.succeed(); setEmptyHashForCachedDependencies(projectName); } else if (installPodsValue === 'undefined') { @@ -312,7 +314,9 @@ async function createFromTemplate({ platform: 'ios', reactNativePath, }); - await installPods(loader, {}); + await installPods(loader, { + useBundler: true, + }); loader.succeed(); setEmptyHashForCachedDependencies(projectName); }