Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable New Architecture with react-native.config.js #2091

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/cli-config/src/schema.ts
Expand Up @@ -156,6 +156,7 @@ export const projectConfig = t
.array()
.items(t.string())
.default([]),
newArchEnabled: t.bool().default(false),
})
.default({}),
android: t
Expand Down
17 changes: 8 additions & 9 deletions packages/cli-doctor/src/commands/info.ts
Expand Up @@ -6,7 +6,11 @@
*/

import getEnvironmentInfo from '../tools/envinfo';
import {logger, version} from '@react-native-community/cli-tools';
import {
getArchitectureForIos,
logger,
version,
} from '@react-native-community/cli-tools';
import {Config} from '@react-native-community/cli-types';
import {readFile} from 'fs-extra';
import path from 'path';
Expand Down Expand Up @@ -52,16 +56,11 @@ const info = async function getInfo(_argv: Array<string>, ctx: Config) {
}

try {
const project = await readFile(
path.join(
ctx.project.ios.sourceDir,
'/Pods/Pods.xcodeproj/project.pbxproj',
),
const isNewArchitecture = await getArchitectureForIos(
ctx.project.ios.sourceDir,
);

platforms.iOS.newArchEnabled = project.includes(
'-DRCT_NEW_ARCH_ENABLED=1',
);
platforms.iOS.newArchEnabled = isNewArchitecture;
} catch {
platforms.iOS.newArchEnabled = notFound;
}
Expand Down
14 changes: 13 additions & 1 deletion packages/cli-platform-ios/src/commands/buildIOS/index.ts
Expand Up @@ -12,12 +12,24 @@ import {BuildFlags, buildOptions} from './buildOptions';
import {getConfiguration} from './getConfiguration';
import {getXcodeProjectAndDir} from './getXcodeProjectAndDir';
import resolvePods from '../../tools/pods';
import {getArchitectureForIos} from '@react-native-community/cli-tools';

async function buildIOS(_: Array<string>, ctx: Config, args: BuildFlags) {
const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios);

const isAppRunningNewArchitecture = ctx.project.ios?.sourceDir
? await getArchitectureForIos(ctx.project.ios?.sourceDir)
: undefined;

// check if pods need to be installed
await resolvePods(ctx.root, ctx.dependencies, {forceInstall: args.forcePods});
await resolvePods(ctx.root, ctx.dependencies, {
forceInstall: args.forcePods,
enableNewArchitecture:
ctx.project.ios?.newArchEnabled !== undefined
? ctx.project.ios?.newArchEnabled
: isAppRunningNewArchitecture,
isRunningNewArchitecture: isAppRunningNewArchitecture,
});

process.chdir(sourceDir);

Expand Down
15 changes: 13 additions & 2 deletions packages/cli-platform-ios/src/commands/runIOS/index.ts
Expand Up @@ -21,6 +21,7 @@ import {
isPackagerRunning,
logAlreadyRunningBundler,
handlePortUnavailable,
getArchitectureForIos,
} from '@react-native-community/cli-tools';
import {buildProject} from '../buildIOS/buildProject';
import {BuildFlags, buildOptions} from '../buildIOS/buildOptions';
Expand All @@ -45,11 +46,21 @@ export interface FlagsT extends BuildFlags {

async function runIOS(_: Array<string>, ctx: Config, args: FlagsT) {
link.setPlatform('ios');

let {packager, port} = args;

const isAppRunningNewArchitecture = ctx.project.ios?.sourceDir
? await getArchitectureForIos(ctx.project.ios?.sourceDir)
: undefined;

// check if pods need to be installed
await resolvePods(ctx.root, ctx.dependencies, {forceInstall: args.forcePods});
await resolvePods(ctx.root, ctx.dependencies, {
forceInstall: args.forcePods,
enableNewArchitecture:
ctx.project.ios?.newArchEnabled !== undefined
? ctx.project.ios?.newArchEnabled
: isAppRunningNewArchitecture,
isRunningNewArchitecture: isAppRunningNewArchitecture,
});

const packagerStatus = await isPackagerRunning(port);

Expand Down
Expand Up @@ -25,6 +25,7 @@ describe('ios::getProjectConfig', () => {
});
expect(projectConfig('/', {})).toMatchInlineSnapshot(`
Object {
"newArchEnabled": undefined,
"sourceDir": "/ios",
"watchModeCommandParams": undefined,
"xcodeProject": null,
Expand All @@ -45,6 +46,7 @@ describe('ios::getProjectConfig', () => {
});
expect(projectConfig('/', {})).toMatchInlineSnapshot(`
Object {
"newArchEnabled": undefined,
"sourceDir": "/ios",
"watchModeCommandParams": undefined,
"xcodeProject": null,
Expand Down
1 change: 1 addition & 0 deletions packages/cli-platform-ios/src/config/index.ts
Expand Up @@ -51,6 +51,7 @@ export function projectConfig(
sourceDir,
watchModeCommandParams: userConfig.watchModeCommandParams,
xcodeProject,
newArchEnabled: userConfig.newArchEnabled,
};
}

Expand Down
25 changes: 18 additions & 7 deletions packages/cli-platform-ios/src/tools/installPods.ts
Expand Up @@ -13,20 +13,28 @@ import runBundleInstall from './runBundleInstall';

interface PodInstallOptions {
skipBundleInstall?: boolean;
newArchEnabled?: boolean;
}

async function runPodInstall(
loader: Ora,
shouldHandleRepoUpdate: boolean = true,
) {
interface RunPodInstallOptions {
shouldHandleRepoUpdate?: boolean;
newArchEnabled?: boolean;
}

async function runPodInstall(loader: Ora, options?: RunPodInstallOptions) {
const shouldHandleRepoUpdate = options?.shouldHandleRepoUpdate || true;
try {
loader.start(
`Installing CocoaPods dependencies ${chalk.dim(
'(this may take a few minutes)',
)}`,
);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡We can add here a log that New Architecture is enabled.

await execa('bundle', ['exec', 'pod', 'install']);
await execa('bundle', ['exec', 'pod', 'install'], {
env: {
RCT_NEW_ARCH_ENABLED: options?.newArchEnabled ? '1' : '0',
},
});
} catch (error) {
// "pod" command outputs errors to stdout (at least some of them)
const stderr = (error as any).stderr || (error as any).stdout;
Expand All @@ -40,7 +48,10 @@ async function runPodInstall(
*/
if (stderr.includes('pod repo update') && shouldHandleRepoUpdate) {
await runPodUpdate(loader);
await runPodInstall(loader, false);
await runPodInstall(loader, {
shouldHandleRepoUpdate: false,
newArchEnabled: options?.newArchEnabled,
});
} else {
loader.fail();
logger.error(stderr);
Expand Down Expand Up @@ -139,7 +150,7 @@ async function installPods(loader?: Ora, options?: PodInstallOptions) {
await installCocoaPods(loader);
}

await runPodInstall(loader);
await runPodInstall(loader, {newArchEnabled: options?.newArchEnabled});
} finally {
process.chdir('..');
}
Expand Down
16 changes: 14 additions & 2 deletions packages/cli-platform-ios/src/tools/pods.ts
Expand Up @@ -16,6 +16,8 @@ import {

interface ResolvePodsOptions {
forceInstall?: boolean;
enableNewArchitecture?: boolean;
isRunningNewArchitecture: boolean | undefined;
}

interface NativeDependencies {
Expand Down Expand Up @@ -77,20 +79,30 @@ export default async function resolvePods(
'dependencies',
);

const isRunningDifferentArchitecture =
options?.enableNewArchitecture !== undefined &&
options.isRunningNewArchitecture !== options?.enableNewArchitecture;

if (
!cachedDependenciesHash ||
!compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) ||
!arePodsInstalled ||
options?.forceInstall
options?.forceInstall ||
isRunningDifferentArchitecture
) {
const loader = getLoader('Installing CocoaPods...');
try {
await installPods(loader, {skipBundleInstall: !!cachedDependenciesHash});
await installPods(loader, {
skipBundleInstall: !!cachedDependenciesHash,
newArchEnabled:
options?.enableNewArchitecture && isRunningDifferentArchitecture,
});
cacheManager.set(
packageJson.name,
'dependencies',
currentDependenciesHash,
);

loader.succeed();
} catch {
loader.fail();
Expand Down
7 changes: 6 additions & 1 deletion packages/cli-tools/src/cacheManager.ts
Expand Up @@ -4,7 +4,12 @@ import os from 'os';
import appDirs from 'appdirsjs';
import logger from './logger';

type CacheKey = 'eTag' | 'lastChecked' | 'latestVersion' | 'dependencies';
type CacheKey =
| 'eTag'
| 'lastChecked'
| 'latestVersion'
| 'dependencies'
| 'newArchEnabled';
type Cache = {[key in CacheKey]?: string};

function loadCache(name: string): Cache | undefined {
Expand Down
14 changes: 14 additions & 0 deletions packages/cli-tools/src/getArchitectureForIos.ts
@@ -0,0 +1,14 @@
import {readFile} from 'fs-extra';
import path from 'path';

export default async function getArchitectureForIos(iosSourceDir: string) {
try {
const project = await readFile(
path.join(iosSourceDir, '/Pods/Pods.xcodeproj/project.pbxproj'),
);

return project.includes('-DRCT_NEW_ARCH_ENABLED=1');
} catch {
return false;
}
}
1 change: 1 addition & 0 deletions packages/cli-tools/src/index.ts
Expand Up @@ -17,5 +17,6 @@ export {default as handlePortUnavailable} from './handlePortUnavailable';
export * from './port';
export {default as cacheManager} from './cacheManager';
export {default as runSudo} from './runSudo';
export {default as getArchitectureForIos} from './getArchitectureForIos';

export * from './errors';
2 changes: 2 additions & 0 deletions packages/cli-types/src/ios.ts
Expand Up @@ -6,6 +6,7 @@
export interface IOSProjectParams {
sourceDir?: string;
watchModeCommandParams?: string[];
newArchEnabled?: boolean;
}

export type IOSProjectInfo = {
Expand All @@ -17,6 +18,7 @@ export interface IOSProjectConfig {
sourceDir: string;
xcodeProject: IOSProjectInfo | null;
watchModeCommandParams?: string[];
newArchEnabled?: boolean;
}

export interface IOSDependencyConfig {
Expand Down