Skip to content

Commit

Permalink
feat: add warnings for run-ios and run-android when manually… (re…
Browse files Browse the repository at this point in the history
…act-native-community#447)

* wip

* add warnings for run-ios and run-android

* memoize in place

* cleanup
  • Loading branch information
thymikee authored Jun 30, 2019
1 parent 023360b commit f6b546e
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 11 deletions.
3 changes: 3 additions & 0 deletions packages/platform-android/src/commands/runAndroid/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
getDefaultUserTerminal,
CLIError,
} from '@react-native-community/cli-tools';
import warnAboutManuallyLinkedLibs from '../../link/warnAboutManuallyLinkedLibs';

// Verifies this is an Android project
function checkAndroid(root) {
Expand Down Expand Up @@ -55,6 +56,8 @@ function runAndroid(argv: Array<string>, config: ConfigT, args: FlagsT) {
return;
}

warnAboutManuallyLinkedLibs(config);

if (!args.packager) {
return buildAndRun(args);
}
Expand Down
51 changes: 51 additions & 0 deletions packages/platform-android/src/link/warnAboutManuallyLinkedLibs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// @flow

import chalk from 'chalk';
import {logger} from '@react-native-community/cli-tools';
import type {ConfigT} from 'types';
import getLinkConfig from './index';

// TODO: move to cli-tools once platform-ios and platform-android are migrated
// to TS and unify with iOS implementation
export default function warnAboutManuallyLinkedLibs(
config: ConfigT,
platform: string = 'android',
linkConfig: $Call<typeof getLinkConfig> = getLinkConfig(),
) {
let deps = [];

for (let key in config.dependencies) {
const dependency = config.dependencies[key];
try {
const projectConfig = config.project[platform];
const dependencyConfig = dependency.platforms[platform];
if (projectConfig && dependencyConfig) {
const x = linkConfig.isInstalled(
projectConfig,
dependency.name,
dependencyConfig,
);
deps = deps.concat(x ? dependency.name : []);
}
} catch (error) {
logger.debug('Checking manually linked modules failed.', error);
}
}

const installedModules = [...new Set(deps)];

if (installedModules.length) {
logger.error(
`React Native CLI uses autolinking for native dependencies, but following modules are linked manually: \n${installedModules
.map(
x =>
` - ${chalk.bold(x)} ${chalk.dim(
`(to unlink run: "react-native unlink ${x}")`,
)}`,
)
.join(
'\n',
)}\nThis is likely to happen when upgrading React Native from version lower than 0.60 to 0.60 or later. Please unlink them as they are likely to cause build failures. You can do so with "react-native unlink" command as shown above. If a library is not compatible with autolinking yet, please ignore this warning and notify the library maintainers.`,
);
}
}
4 changes: 3 additions & 1 deletion packages/platform-ios/src/commands/runIOS/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/

import child_process from 'child_process';
Expand All @@ -16,6 +15,7 @@ import type {ConfigT} from 'types';
import findXcodeProject from './findXcodeProject';
import parseIOSDevicesList from './parseIOSDevicesList';
import findMatchingSimulator from './findMatchingSimulator';
import warnAboutManuallyLinkedLibs from '../../link/warnAboutManuallyLinkedLibs';
import {
logger,
CLIError,
Expand All @@ -42,6 +42,8 @@ function runIOS(_: Array<string>, ctx: ConfigT, args: FlagsT) {
);
}

warnAboutManuallyLinkedLibs(ctx);

process.chdir(args.projectPath);

const xcodeProject = findXcodeProject(fs.readdirSync('.'));
Expand Down
5 changes: 4 additions & 1 deletion packages/platform-ios/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
*/

import path from 'path';
import {memoize} from 'lodash';
import findProject from './findProject';
import findPodfilePath from './findPodfilePath';
import findPodspec from './findPodspec';
import type {UserConfigT} from 'types';

const memoizedFindProject = memoize(findProject);

/**
* For libraries specified without an extension, add '.tbd' for those that
* start with 'lib' and '.framework' to the rest.
Expand All @@ -37,7 +40,7 @@ export function projectConfig(
if (!userConfig) {
return;
}
const project = userConfig.project || findProject(folder);
const project = userConfig.project || memoizedFindProject(folder);

/**
* No iOS config found here
Expand Down
10 changes: 7 additions & 3 deletions packages/platform-ios/src/link-pods/isInstalled.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/

import readPodfile from './readPodfile';
import getPodspecName from '../config/getPodspecName';
import type {ProjectConfigIOST, DependencyConfigIOST} from 'types';

export default function isInstalled(iOSProject, dependencyConfig) {
if (!iOSProject.podfile) {
export default function isInstalled(
iOSProject: ProjectConfigIOST,
dependencyConfig: DependencyConfigIOST,
) {
if (!iOSProject.podfile || !dependencyConfig.podspecPath) {
return false;
}
// match line with pod declaration: pod 'dependencyPodName' (other possible parameters of pod are ignored)
Expand Down
9 changes: 7 additions & 2 deletions packages/platform-ios/src/link/common/isInstalled.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/

import isInstalledIOS from '../isInstalled';
import isInstalledPods from '../../link-pods/isInstalled';
import type {ProjectConfigIOST, DependencyConfigIOST} from 'types';

export default function isInstalled(projectConfig, name, dependencyConfig) {
export default function isInstalled(
projectConfig: ProjectConfigIOST,
name?: string,
dependencyConfig: DependencyConfigIOST,
) {
return (
isInstalledIOS(projectConfig, dependencyConfig) ||
isInstalledPods(projectConfig, dependencyConfig)
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-ios/src/link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/

import isInstalled from './common/isInstalled';
Expand Down
20 changes: 17 additions & 3 deletions packages/platform-ios/src/link/isInstalled.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,33 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/

import xcode from 'xcode';
import getGroup from './getGroup';
import hasLibraryImported from './hasLibraryImported';
import type {ProjectConfigIOST, DependencyConfigIOST} from 'types';

const memo = new Map();

/**
* Returns true if `xcodeproj` specified by dependencyConfig is present
* in a top level `libraryFolder`
*/
export default function isInstalled(projectConfig, dependencyConfig) {
const project = xcode.project(projectConfig.pbxprojPath).parseSync();
export default function isInstalled(
projectConfig: ProjectConfigIOST,
dependencyConfig: DependencyConfigIOST,
) {
let project;

if (memo.has(projectConfig.pbxprojPath)) {
project = memo.get(projectConfig.pbxprojPath);
} else {
project = xcode.project(projectConfig.pbxprojPath).parseSync();
memo.set(projectConfig.pbxprojPath, project);
}

const libraries = getGroup(project, projectConfig.libraryFolder);

if (!libraries) {
Expand Down
51 changes: 51 additions & 0 deletions packages/platform-ios/src/link/warnAboutManuallyLinkedLibs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// @flow

import chalk from 'chalk';
import {logger} from '@react-native-community/cli-tools';
import type {ConfigT} from 'types';
import getLinkConfig from './index';

// TODO: move to cli-tools once platform-ios and platform-android are migrated
// to TS and unify with Android implementation
export default function warnAboutManuallyLinkedLibs(
config: ConfigT,
platform?: string = 'ios',
linkConfig: $Call<typeof getLinkConfig> = getLinkConfig(),
) {
let deps = [];

for (let key in config.dependencies) {
const dependency = config.dependencies[key];
try {
const projectConfig = config.project[platform];
const dependencyConfig = dependency.platforms[platform];
if (projectConfig && dependencyConfig) {
const x = linkConfig.isInstalled(
projectConfig,
dependency.name,
dependencyConfig,
);
deps = deps.concat(x ? dependency.name : []);
}
} catch (error) {
logger.debug('Checking manually linked modules failed.', error);
}
}

const installedModules = [...new Set(deps)];

if (installedModules.length) {
logger.error(
`React Native CLI uses autolinking for native dependencies, but following modules are linked manually: \n${installedModules
.map(
x =>
` - ${chalk.bold(x)} ${chalk.dim(
`(to unlink run: "react-native unlink ${x}")`,
)}`,
)
.join(
'\n',
)}\nThis is likely to happen when upgrading React Native from version lower than 0.60 to 0.60 or later. Please unlink them as they are likely to cause build failures. You can do so with "react-native unlink" command as shown above. If a library is not compatible with autolinking yet, please ignore this warning and notify the library maintainers.`,
);
}
}

0 comments on commit f6b546e

Please sign in to comment.