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

Make react-native link play nicely with CocoaPods-based iOS projects. #15460

Closed
wants to merge 19 commits into from

Conversation

mironiasty
Copy link
Contributor

The core React Native codebase already has full support for CocoaPods. However, react-native link doesn’t play nicely with CocoaPods, so installing third-party libs from the RN ecosystem is really hard.

This change will allow to link projects that contains its own .podspec file to CocoaPods-based projects. In case link detect Podfile in iOS directory, it will look for related .podspec file in linked project directory, and add it to Podfile. If Podfile and .podspec files are not present, it will fall back to previous implementation.

Test Plan

  1. Build a React Native project where the iOS part uses CocoaPods to manage its dependencies. The most common scenario here is to have React Native be a Pod dependency, among others.
  2. Install a RN-related library, that contains .podspec file, with react-native link (as an example it could be: react-native-maps
  3. Building the resulting iOS workspace should succeed (and there should be new entry in Podfile)

@facebook-github-bot facebook-github-bot added GH Review: review-needed CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. labels Aug 11, 2017
@pull-bot
Copy link

pull-bot commented Aug 11, 2017

Messages
📖

📄 Docs - Thanks for your contribution to the docs!

@facebook-github-bot label Documentation

Attention: @hramos, @grabbou, @Kureev

Generated by 🚫 dangerJS

Copy link
Contributor

@Kureev Kureev left a comment

Choose a reason for hiding this comment

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

Code looks good to me! I'd even say very good. Documentation, test coverage - everything is there. I only need some time in order to test it before I give my approval.

@Kureev
Copy link
Contributor

Kureev commented Aug 11, 2017

@mironiasty once again, great job 🙌 Really enjoy reviewing high-quality PRs

@mironiasty
Copy link
Contributor Author

@Kureev Thanks :)

Also another way to test it, is to create Expo project, and then use exp detach on it. This should create iOS project with Podfile. And such project could be updated with modified implementation of react-native link.

@grabbou
Copy link
Contributor

grabbou commented Aug 22, 2017

This looks really solid. Let me get back to you on that tomorrow latest. Pretty sure will be flawless :)

Copy link
Contributor

@Kureev Kureev left a comment

Choose a reason for hiding this comment

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

First of all, sorry for taking that much time for review.
I've made a quick test an it works flawless.

After @grabbou double-check this, we're confident to merge it in

@grabbou grabbou requested a review from hramos as a code owner August 31, 2017 10:42
* Unregister native module IOS with CocoaPods
*/
module.exports = function unregisterNativeModule(dependencyConfig, iOSProject) {

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe empty line here and on line 14 is not intended? (nitpick)

module.exports = function unregisterNativeModule(dependencyConfig, iOSProject) {

const podContent = fs.readFileSync(iOSProject.podfile, 'utf8');
const removed = removePodEntry(podContent, dependencyConfig.podspec);
Copy link
Contributor

Choose a reason for hiding this comment

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

After removing, shall we also call pod install to sync the project? What happens right now after you unlink?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't call pod install anywhere. It is up to user to call it later on (it could be also run automatically in build process/Xcode). Right now link/unlink processes only modify configuration files (and with this change only modify Podfile file).

const nextTarget = /target (\'|\")\w+(\'|\") do/g;
// match line that has only 'end' (if we don't catch new target or function, this would mean this is end of current target)
const endOfCurrentTarget = /^\s*end\s*$/g;
// match function defeinition, like: post_install do |installer| (some Podfiles have function defined inside main target
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo in definition


module.exports = function findLineToAddPod(podLines, firstTargetLine){

// match line with new targe: target 'project_name' do (most likely target inside podfile main target)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo in target

'use strict';

module.exports = function findLineToAddPod(podLines, firstTargetLine){

Copy link
Contributor

Choose a reason for hiding this comment

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

Same here: no need to include an empty line :)

const newEntry = `pod '${podName}', :path => '../node_modules/${nodePath}'\n`;

if (!linesToAddEntry) {
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

This file has wrong indentation. Try running prettier for all the files in your PR (not sure if you have it integrated already)

Copy link
Contributor

@grabbou grabbou left a comment

Choose a reason for hiding this comment

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

Okay, I think this is a good start - in the future ,we might want to handle multiple targets in CocoaPods as well.

Last thing to improve here is to run prettier on all files. Some of the files use tabs for indentation.

Check if your editor has well configured prettier and editor-config.

@mironiasty
Copy link
Contributor Author

Sorry for these tabs, I hope it is fixed now. (I've been working on other project with tabs, and priettier used that config on react-native files)

@grabbou
Copy link
Contributor

grabbou commented Oct 17, 2017

@facebook-github-bot shipit

@facebook-github-bot facebook-github-bot added the Import Started This pull request has been imported. This does not imply the PR has been approved. label Oct 17, 2017
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

@hramos is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

grabbou pushed a commit that referenced this pull request Oct 18, 2017
Summary:
The core React Native codebase already has full support for CocoaPods. However, `react-native link` doesn’t play nicely with CocoaPods, so installing third-party libs from the RN ecosystem is really hard.

This change will allow to link projects that contains its own `.podspec` file to CocoaPods-based projects. In case `link` detect `Podfile` in `iOS` directory, it will look for related `.podspec` file in linked project directory, and add it to `Podfile`. If `Podfile` and `.podspec` files are not present, it will fall back to previous implementation.

**Test Plan**
1. Build a React Native project where the iOS part uses CocoaPods to manage its dependencies. The most common scenario here is to have React Native be a Pod dependency, among others.
2. Install a RN-related library, that contains `.podspec` file, with `react-native link` (as an example it could be: [react-native-maps](https://github.com/airbnb/react-native-maps)
3. Building the resulting iOS workspace should succeed (and there should be new entry in `Podfile`)
Closes #15460

Differential Revision: D6078649

Pulled By: hramos

fbshipit-source-id: 9651085875892fd66299563ca0e42fb2bcc00825
ide pushed a commit that referenced this pull request Oct 19, 2017
Summary:
The core React Native codebase already has full support for CocoaPods. However, `react-native link` doesn’t play nicely with CocoaPods, so installing third-party libs from the RN ecosystem is really hard.

This change will allow to link projects that contains its own `.podspec` file to CocoaPods-based projects. In case `link` detect `Podfile` in `iOS` directory, it will look for related `.podspec` file in linked project directory, and add it to `Podfile`. If `Podfile` and `.podspec` files are not present, it will fall back to previous implementation.

**Test Plan**
1. Build a React Native project where the iOS part uses CocoaPods to manage its dependencies. The most common scenario here is to have React Native be a Pod dependency, among others.
2. Install a RN-related library, that contains `.podspec` file, with `react-native link` (as an example it could be: [react-native-maps](https://github.com/airbnb/react-native-maps)
3. Building the resulting iOS workspace should succeed (and there should be new entry in `Podfile`)
Closes #15460

Differential Revision: D6078649

Pulled By: hramos

fbshipit-source-id: 9651085875892fd66299563ca0e42fb2bcc00825
@chrisbianca
Copy link

One of the core maintainers of https://github.com/invertase/react-native-firebase here.

We've spent the last year battling with RN's lack of integration with Cocoapods and the pain this causes our users. Having given up on the Cocoapods approach and switching to usage of react-native link as it used to be, we are in the position where we have a .podspec for legacy support, but do not wish this to be used for new projects due to the complications this brings with needing to also add the appropriate React pod and subspecs.

Since this change, our .podspec is picked up automatically, but it seems this PR provides no way for us to opt out of that decision and override the presence of the podspec.

return {
    sourceDir: path.dirname(projectPath),
    folder: folder,
    pbxprojPath: path.join(projectPath, 'project.pbxproj'),
    podfile: findPodfilePath(projectPath),
    podspec: findPodspecName(folder),
    projectPath: projectPath,
    projectName: path.basename(projectPath),
    libraryFolder: userConfig.libraryFolder || 'Libraries',
    sharedLibraries: mapSharedLibaries(userConfig.sharedLibraries || []),
    plist: userConfig.plist || [],
  };

As such, this has fundamentally broken our on-boarding flow for new users and leaves us with only two options:

  1. To remove the .podspec completely which removes backwards compatibility for those devs who have been using the .podspec previously
  2. To switch back to the .podspec approach and introduce the added step of having the users need to set up React and subspecs as pod - something which we know causes issues based on our past experiences

Neither of these are particularly viable alternatives and both involve compromises.

As somebody that has tried to submit PRs to improve the build process customisability in the past (on the Android side), only for the PR to be completely ignored, it's incredibly frustrating to now be affected by a change that hasn't taken into consideration what this might mean for some libraries.

@mironiasty
Copy link
Contributor Author

One thing that might be worth to mention here: this change would only work for users that have Pods configured for their iOS project (so users without Podfile should not be affected). But from react-native-firebase installation documentation, I see that configuring pods is recommended step for users.

I don't know what is exact problem with linking your project using CocoaPods. If problem is related to missing react entries in Podfile, maybe you can recommend creating project with create-react-native-app and detaching project from Expo (this way, user should have fully working Podfile).

As for adding option to opt-out from linking podspecs: I can think of two ways of doing it:

  • Adding new parameter to link (react-native link react-native-firebase --ignore-pods)
  • Checking for predefined comment in project .podspec file (like #REACT_NATIVE_IGNORE_FOR_LINKING)

I'm not sure which one would be better. Also adding any of them, would again increase complexity of linking process.

@chrisbianca
Copy link

@mironiasty thanks for your response.

Our users need to configure pods in order to use the Firebase dependencies, as this is the approach that Google recommend and we don't want to deviate from it.

We also categorically don't want to recommend people creating projects using Expo as a way of getting started. This has also caused us numerous problems down the line and is not a viable alternative given the large dependency that react-native-firebase has on native code.

Regarding your options above:

  1. This would only work when linking just this library, anybody running react-native link without the library would encounter problems
  2. This would work, though feels somewhat hacky

A much better option (and one that keeps in sync with the rest of the rnpm settings) would be to allow this to be overridden as part of the package.json. For example, setting an ignorePodSpec as so:

"rnpm": {
    "ios" {
      "ignorePodSpec": true,
    }
  },

grabbou pushed a commit to react-native-community/cli that referenced this pull request Sep 26, 2018
Summary:
The core React Native codebase already has full support for CocoaPods. However, `react-native link` doesn’t play nicely with CocoaPods, so installing third-party libs from the RN ecosystem is really hard.

This change will allow to link projects that contains its own `.podspec` file to CocoaPods-based projects. In case `link` detect `Podfile` in `iOS` directory, it will look for related `.podspec` file in linked project directory, and add it to `Podfile`. If `Podfile` and `.podspec` files are not present, it will fall back to previous implementation.

**Test Plan**
1. Build a React Native project where the iOS part uses CocoaPods to manage its dependencies. The most common scenario here is to have React Native be a Pod dependency, among others.
2. Install a RN-related library, that contains `.podspec` file, with `react-native link` (as an example it could be: [react-native-maps](https://github.com/airbnb/react-native-maps)
3. Building the resulting iOS workspace should succeed (and there should be new entry in `Podfile`)
Closes facebook/react-native#15460

Differential Revision: D6078649

Pulled By: hramos

fbshipit-source-id: 9651085875892fd66299563ca0e42fb2bcc00825
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Import Started This pull request has been imported. This does not imply the PR has been approved.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants