├── lib ├── cocoapods-fix-react-native.rb ├── cocoapods-fix-react-native │ ├── versions │ │ ├── 0_58_0-post.rb │ │ ├── 0_58_1-post.rb │ │ ├── 0_58_1-pre.rb │ │ ├── 0_58_2-post.rb │ │ ├── 0_58_2-pre.rb │ │ ├── 0_58_3-post.rb │ │ ├── 0_58_3-pre.rb │ │ ├── 0_58_4-post.rb │ │ ├── 0_58_4-pre.rb │ │ ├── 0_58_5-post.rb │ │ ├── 0_58_5-pre.rb │ │ ├── 0_58_6-post.rb │ │ ├── 0_59_0-post.rb │ │ ├── 0_59_0-pre.rb │ │ ├── 0_59_1-post.rb │ │ ├── 0_59_1-pre.rb │ │ ├── 0_59_10-post.rb │ │ ├── 0_59_10-pre.rb │ │ ├── 0_59_2-post.rb │ │ ├── 0_59_2-pre.rb │ │ ├── 0_59_3-post.rb │ │ ├── 0_59_3-pre.rb │ │ ├── 0_59_4-post.rb │ │ ├── 0_59_4-pre.rb │ │ ├── 0_59_5-post.rb │ │ ├── 0_59_5-pre.rb │ │ ├── 0_59_6-post.rb │ │ ├── 0_59_6-pre.rb │ │ ├── 0_59_7-post.rb │ │ ├── 0_59_7-pre.rb │ │ ├── 0_59_8-post.rb │ │ ├── 0_59_8-pre.rb │ │ ├── 0_59_9-post.rb │ │ ├── 0_59_9-pre.rb │ │ ├── 0_57_1-post.rb │ │ ├── 0_57_2-post.rb │ │ ├── 0_57_3-post.rb │ │ ├── 0_57_4-post.rb │ │ ├── 0_57_5-post.rb │ │ ├── 0_57_7-post.rb │ │ ├── 0_57_8-post.rb │ │ ├── 0_58_6-pre.rb │ │ ├── 0_57_0-post.rb │ │ ├── 0_58_0-pre.rb │ │ ├── 0_53_3-post.rb │ │ ├── 0_56_0-post.rb │ │ ├── 0_56_1-post.rb │ │ ├── 0_54_2-post.rb │ │ ├── 0_55_4-post.rb │ │ ├── 0_54_4-post.rb │ │ └── 0_55_3-post.rb │ ├── issues │ │ └── react_dependency_version.rb │ ├── helpers │ │ └── root_helper.rb │ └── fix_with_context.rb └── cocoapods_plugin.rb ├── .gitignore ├── Rakefile ├── Gemfile ├── spec ├── command │ └── native_spec.rb └── spec_helper.rb ├── .travis.yml ├── cocoapods-fix-react-native.gemspec ├── LICENSE.txt └── README.md /lib/cocoapods-fix-react-native.rb: -------------------------------------------------------------------------------- 1 | # NOOP 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | pkg 3 | .idea/ 4 | Gemfile.lock 5 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_0-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_8-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_1-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_0-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_1-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_0-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_2-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_1-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_2-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_1-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_3-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_2-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_3-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_2-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_4-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_3-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_4-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_3-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_5-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_4-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_5-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_4-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_6-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_5-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_0-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_6-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_0-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_6-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_1-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_0-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_1-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_0-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_10-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_9-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_10-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_9-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_2-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_1-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_2-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_1-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_3-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_2-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_3-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_2-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_4-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_3-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_4-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_3-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_5-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_4-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_5-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_4-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_6-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_5-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_6-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_5-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_7-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_6-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_7-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_6-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_8-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_7-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_8-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_7-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_9-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_8-post' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_59_9-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_59_8-pre' 2 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_1-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_0-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_2-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_1-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_3-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_2-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_4-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_3-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_5-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_4-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_7-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_5-post' 2 | 3 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_8-post.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_57_7-post' 2 | 3 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | 3 | def specs(dir) 4 | FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ') 5 | end 6 | 7 | desc 'Runs all the specs' 8 | task :specs do 9 | sh "bundle exec bacon #{specs('**')}" 10 | end 11 | 12 | task :default => :specs 13 | 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in cocoapods-fix-react-native.gemspec 4 | gemspec 5 | 6 | group :development do 7 | gem 'cocoapods' 8 | 9 | gem 'mocha' 10 | gem 'bacon' 11 | gem 'mocha-on-bacon' 12 | gem 'prettybacon' 13 | gem 'pry' 14 | end 15 | -------------------------------------------------------------------------------- /spec/command/native_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../../spec_helper', __FILE__) 2 | 3 | # This project has about 8 LOC of Ruby, I'm 4 | # not particularly bothered with testing it. 5 | # 6 | # It'd need integration really. 7 | # 8 | describe 'Empty test' do 9 | it 'is a pretty chill spec' do 10 | 23.should.equal 23 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/issues/react_dependency_version.rb: -------------------------------------------------------------------------------- 1 | class ReactDependencyVersion 2 | def fix_with_context(context) 3 | all_pods_targets = context.pods_project.targets 4 | all_pods_targets.each do |t| 5 | deployment_target = t.build_configurations.first.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] 6 | has_react_dep = t.dependencies.find { |dep| dep.name == 'React' } 7 | 8 | if has_react_dep && deployment_target == '4.3' 9 | raise 'You have a Pod which has a deployment target of 4.3, and a dependency on React.' \ 10 | "\nIn order for React Native to compile you need to give the Podspec for #{t.name} a version like `s.platform = :ios, '9.0'`.\n" 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | deploy: 2 | provider: rubygems 3 | gem: cocoapods-fix-react-native 4 | api_key: 5 | secure: TT/isZpKJdjiBEFUXwmDCVViGQCujZCNYSROG89YyePH9ukMq87EObuXSpciyV46YURkpOMAbcLdBoHhrv/zCtk5J/PhRoKvKk2QnUUeSpf6JxgcpN6HKLKBiId4sXOHMh4M12g7+4an+LharXOk2RS/zEICgUs0QZgmRKSPKoxofjI/oh8Zr1Fx+hriTOX0Lj0oXT0FCA2+gQiQRpahciC1q5UenxRMmn8nv8cHgDxKF3Vfkdk7PVVMR3Mm7zVwZh4ly4AUFHTOq7hWQAP1AuoYZa+nShu4MRANLedSICQjoyoBrt66KJ8fEHDdUBudvRsEIhq3wYir+ioT8YUT3FZwv0pc6dkB4ZfuVllyhzPo/Pr9zZtr47S1JHg0nyGRap7hHKefU5mIlp2MACtelzSToy2Lum9qiru3iIWmPlJLsMEOlnMmkKvQtsT6LLs9+VOk92RT+71bK73IhUkvHsTzjcxEl0c8Rc9VC/X69Ta4Uj53pG/fo5ShpLQVJBx0E1+fpF+kSIgz71Ekw+Ym3BqYeeLk7kWlB2dYm0d+NeR0ycJXsM6ezoJBk2n6AJ2FDXNpxeX6H0D/S1RN9dmEXm/LeSZ7h3ujTMYbAFK4fsmwtL1MF4mnCnQ3uqp9fFRZqyVko26mjD74gV4JoiPuHR+Zk/f7ha+k7drdjUzAcBI= 6 | -------------------------------------------------------------------------------- /lib/cocoapods_plugin.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-fix-react-native/fix_with_context' 2 | require 'cocoapods-fix-react-native/issues/react_dependency_version' 3 | 4 | Pod::HooksManager.register('cocoapods-fix-react-native', :pre_install) do |context| 5 | # The pre-fix resolver, usually for modifying Podspecs 6 | fixer = CocoaPodsFixReactNative.new 7 | fixer.pre_fix_with_context(context) 8 | end 9 | 10 | 11 | Pod::HooksManager.register('cocoapods-fix-react-native', :post_install) do |context| 12 | # Check that the min version of iOS has been set right for CocoaPods 13 | # This happens when a pod has a lower than iOS 6 deployment target. 14 | dep_version = ReactDependencyVersion.new 15 | dep_version.fix_with_context(context) 16 | 17 | # The post-fix resolver, for editing the RN source code after it's been installed 18 | fixer = CocoaPodsFixReactNative.new 19 | fixer.post_fix_with_context(context) 20 | end 21 | -------------------------------------------------------------------------------- /cocoapods-fix-react-native.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | 4 | Gem::Specification.new do |spec| 5 | spec.name = 'cocoapods-fix-react-native' 6 | spec.version = Time.now.strftime("%Y.%m.%d.%H") 7 | spec.authors = ['Orta Therox'] 8 | spec.email = ['orta.therox@gmail.com'] 9 | spec.description = "CocoaPods plugin which automates hot-patching React Native" 10 | spec.summary = "CocoaPods plugin which automates hot-patching React Native" 11 | spec.homepage = 'https://github.com/orta/cocoapods-fix-react-native' 12 | spec.license = 'MIT' 13 | 14 | spec.files = `git ls-files`.split($/) 15 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 16 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 17 | spec.require_paths = ['lib'] 18 | 19 | spec.add_development_dependency 'bundler', '> 1.3' 20 | spec.add_development_dependency 'rake' 21 | end 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Orta Therox 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/helpers/root_helper.rb: -------------------------------------------------------------------------------- 1 | # Notes: 2 | # 3 | # - All file paths should be relative to the React repo, rather than the Pods dir, or node_modules 4 | # - An enviroment variable of `COCOAPODS_FIX_REACT_NATIVE_DEV_ROOT` will override the defaults for dev. 5 | # 6 | # - Returns the root directory to use for React Native 7 | 8 | def get_root 9 | # Are you using :path based Pods? 10 | dev_pods_react = !File.directory?('Pods/React/React') 11 | 12 | # Check for whether we're in a project that uses relative paths 13 | same_repo_node_modules = File.directory?('node_modules/react-native') 14 | previous_repo_node_modules = File.directory?('../node_modules/react-native') 15 | 16 | # Find out where the files could be rooted 17 | $root = 'Pods/React' 18 | 19 | if dev_pods_react 20 | # Use this as an override, if present and non empty string 21 | $env_root = ENV["COCOAPODS_FIX_REACT_NATIVE_DEV_ROOT"] 22 | 23 | if defined?($env_root) && ($env_root != nil) && ($env_root != '') 24 | $root = $env_root 25 | else 26 | $root = 'node_modules/react-native' if same_repo_node_modules 27 | $root = '../node_modules/react-native' if previous_repo_node_modules 28 | end 29 | end 30 | 31 | return $root 32 | end -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | ROOT = Pathname.new(File.expand_path('../../', __FILE__)) 3 | $:.unshift((ROOT + 'lib').to_s) 4 | $:.unshift((ROOT + 'spec').to_s) 5 | 6 | require 'bundler/setup' 7 | require 'bacon' 8 | require 'mocha-on-bacon' 9 | require 'pretty_bacon' 10 | require 'pathname' 11 | require 'cocoapods' 12 | 13 | Mocha::Configuration.prevent(:stubbing_non_existent_method) 14 | 15 | require 'cocoapods_plugin' 16 | 17 | #-----------------------------------------------------------------------------# 18 | 19 | module Pod 20 | 21 | # Disable the wrapping so the output is deterministic in the tests. 22 | # 23 | UI.disable_wrap = true 24 | 25 | # Redirects the messages to an internal store. 26 | # 27 | module UI 28 | @output = '' 29 | @warnings = '' 30 | 31 | class << self 32 | attr_accessor :output 33 | attr_accessor :warnings 34 | 35 | def puts(message = '') 36 | @output << "#{message}\n" 37 | end 38 | 39 | def warn(message = '', actions = []) 40 | @warnings << "#{message}\n" 41 | end 42 | 43 | def print(message) 44 | @output << message 45 | end 46 | end 47 | end 48 | end 49 | 50 | #-----------------------------------------------------------------------------# 51 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_6-pre.rb: -------------------------------------------------------------------------------- 1 | require_relative './0_58_5-pre' 2 | 3 | # https://github.com/facebook/react-native/issues/23390 4 | react_podspec_file = 'React.podspec' 5 | react_podspec_old_code = ' 6 | s.subspec "cxxreact" do |ss| 7 | ss.dependency "React/jsinspector" 8 | ss.dependency "boost-for-react-native", "1.63.0" 9 | ss.dependency "Folly", folly_version 10 | ss.compiler_flags = folly_compiler_flags 11 | ss.source_files = "ReactCommon/cxxreact/*.{cpp,h}" 12 | ss.exclude_files = "ReactCommon/cxxreact/SampleCxxModule.*" 13 | ss.private_header_files = "ReactCommon/cxxreact/*.h" 14 | ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Folly\"" } 15 | end 16 | ' 17 | react_podspec_new_code = ' 18 | s.subspec "cxxreact" do |ss| 19 | ss.dependency "React/jsinspector" 20 | ss.dependency "boost-for-react-native", "1.63.0" 21 | ss.dependency "Folly", folly_version 22 | ss.dependency "DoubleConversion", "1.1.6" 23 | ss.dependency "glog", "0.3.5" 24 | ss.compiler_flags = folly_compiler_flags 25 | ss.source_files = "ReactCommon/cxxreact/*.{cpp,h}" 26 | ss.exclude_files = "ReactCommon/cxxreact/SampleCxxModule.*" 27 | ss.private_header_files = "ReactCommon/cxxreact/*.h" 28 | ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Folly\"" } 29 | end 30 | ' 31 | patch_pod_file react_podspec_file, react_podspec_old_code, react_podspec_new_code 32 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_57_0-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 11 | def has_pods_project_source_file(source_filename) 12 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 13 | File.open(pods_project).grep(/#{source_filename}/).any? 14 | end 15 | 16 | # Detect dependent source file required for building when the given source file is present 17 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 18 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 19 | end 20 | 21 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 22 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 23 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 24 | end 25 | end 26 | 27 | def detect_missing_subspecs 28 | return unless $has_frameworks 29 | 30 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 31 | # When the React pod is generated it must include all the required source, and see umbrella deps. 32 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 33 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 34 | 35 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 36 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 37 | end 38 | 39 | detect_missing_subspecs 40 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_58_0-pre.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # TODO: move to be both file in pods and file in node_mods? 8 | def patch_pod_file(path, old_code, new_code) 9 | file = File.join($root, path) 10 | unless File.exist?(file) 11 | Pod::UI.warn "#{file} does not exist so was not patched.." 12 | return 13 | end 14 | code = File.read(file) 15 | if code.include?(old_code) 16 | Pod::UI.message "Patching #{file}", '- ' 17 | FileUtils.chmod('+w', file) 18 | File.write(file, code.sub(old_code, new_code)) 19 | end 20 | end 21 | 22 | # https://github.com/facebook/react-native/pull/23274 23 | react_podspec_file = 'React.podspec' 24 | react_podspec_old_code = ' 25 | s.subspec "jsiexecutor" do |ss| 26 | ss.dependency "React/cxxreact" 27 | ss.dependency "React/jsi" 28 | ss.dependency "Folly", folly_version 29 | ss.compiler_flags = folly_compiler_flags 30 | ss.source_files = "ReactCommon/jsiexecutor/jsireact/*.{cpp,h}" 31 | ss.private_header_files = "ReactCommon/jsiexecutor/jsireact/*.h" 32 | ss.header_dir = "jsireact" 33 | ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"" } 34 | end 35 | ' 36 | react_podspec_new_code = ' 37 | s.subspec "jsiexecutor" do |ss| 38 | ss.dependency "React/cxxreact" 39 | ss.dependency "React/jsi" 40 | ss.dependency "Folly", folly_version 41 | ss.compiler_flags = folly_compiler_flags 42 | ss.source_files = "ReactCommon/jsiexecutor/jsireact/*.{cpp,h}" 43 | ss.private_header_files = "ReactCommon/jsiexecutor/jsireact/*.h" 44 | ss.header_dir = "jsireact" 45 | ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\", \"$(PODS_TARGET_SRCROOT)/ReactCommon/jsiexecutor\"" } 46 | end 47 | ' 48 | patch_pod_file react_podspec_file, react_podspec_old_code, react_podspec_new_code 49 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_53_3-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | def fix_unused_yoga_headers 26 | filepath = 'Pods/Target Support Files/yoga/yoga-umbrella.h' 27 | # This only exists when using CocoaPods + Frameworks 28 | return unless File.exist?(filepath) 29 | 30 | contents = [] 31 | file = File.open(filepath, 'r') 32 | file.each_line do |line| 33 | contents << line 34 | end 35 | file.close 36 | 37 | if contents[14].include? 'YGNode.h' 38 | Pod::UI.message "Patching #{filepath}", '- ' 39 | contents.delete_at(14) # #import "YGNode.h" 40 | contents.delete_at(14) # #import "YGNodePrint.h" 41 | contents.delete_at(14) # #import "Yoga-internal.h" 42 | 43 | file = File.open(filepath, 'w') do |f| 44 | f.puts(contents) 45 | end 46 | end 47 | end 48 | 49 | fix_unused_yoga_headers 50 | 51 | # https://github.com/facebook/react-native/pull/14664 52 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 53 | animation_view_old_code = 'import ' 54 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 55 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 56 | 57 | # https://github.com/facebook/react-native/issues/13198 58 | # Only needed when you have the DevSupport subspec 59 | has_dev_support = File.exist?(File.join($root, 'Libraries/WebSocket/RCTReconnectingWebSocket.m')) 60 | 61 | # Move Fishhook to be based on RN's imports 62 | websocket = 'Libraries/WebSocket/RCTReconnectingWebSocket.m' 63 | websocket_old_code = 'import ' 64 | websocket_new_code = 'import ' 65 | patch_pod_file websocket, websocket_old_code, websocket_new_code 66 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_56_0-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 26 | def has_pods_project_source_file(source_filename) 27 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 28 | File.open(pods_project).grep(/#{source_filename}/).any? 29 | end 30 | 31 | # Detect dependent source file required for building when the given source file is present 32 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 33 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 34 | end 35 | 36 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 37 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 38 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 39 | end 40 | end 41 | 42 | def detect_missing_subspecs 43 | return unless $has_frameworks 44 | 45 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 46 | # When the React pod is generated it must include all the required source, and see umbrella deps. 47 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 48 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 49 | 50 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 51 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 52 | end 53 | 54 | detect_missing_subspecs 55 | 56 | # # https://github.com/facebook/react-native/pull/14664 57 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 58 | animation_view_old_code = 'import ' 59 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 60 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 61 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_56_1-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 26 | def has_pods_project_source_file(source_filename) 27 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 28 | File.open(pods_project).grep(/#{source_filename}/).any? 29 | end 30 | 31 | # Detect dependent source file required for building when the given source file is present 32 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 33 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 34 | end 35 | 36 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 37 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 38 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 39 | end 40 | end 41 | 42 | def detect_missing_subspecs 43 | return unless $has_frameworks 44 | 45 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 46 | # When the React pod is generated it must include all the required source, and see umbrella deps. 47 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 48 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 49 | 50 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 51 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 52 | end 53 | 54 | detect_missing_subspecs 55 | 56 | # # https://github.com/facebook/react-native/pull/14664 57 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 58 | animation_view_old_code = 'import ' 59 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 60 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 61 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/fix_with_context.rb: -------------------------------------------------------------------------------- 1 | require 'molinillo/dependency_graph' 2 | 3 | class CocoaPodsFixReactNative 4 | def post_fix_with_context(context) 5 | # Get the current version of React Native in your app 6 | react_spec = nil 7 | context.umbrella_targets.each do |target| 8 | react = target.specs.find { |s| s.name == 'React' || s.name.start_with?('React/') } 9 | next if react.nil? 10 | react_spec = react 11 | end 12 | 13 | if react_spec.nil? 14 | Pod::UI.warn "No React dependency found" 15 | return 16 | end 17 | 18 | version = react_spec.version.to_s 19 | 20 | unless patch_exist?(version) 21 | Pod::UI.warn "CP-Fix-React-Native does not support #{version} yet, please send " + 22 | 'PRs to https://github.com/orta/cocoapods-fix-react-native' 23 | return 24 | end 25 | 26 | path_to_fix = version_file(version) 27 | 28 | if File.exist? path_to_fix 29 | Pod::UI.section "Patching React Native #{version}" do 30 | require(path_to_fix) 31 | end 32 | end 33 | end 34 | 35 | def pre_fix_with_context(context) 36 | # Get the current version of React Native in your app 37 | locked_dependencies = Molinillo::DependencyGraph.new 38 | if context.lockfile 39 | context.lockfile.dependencies.each do |dependency| 40 | locked_dependencies.add_vertex(dependency.name, dependency, true) 41 | end 42 | else 43 | Pod::UI.warn 'No Podfile.lock present. Continuing without locked dependencies.' 44 | end 45 | 46 | sources = context.podfile.sources.map do |source| 47 | Pod::Config.instance.sources_manager.source_with_name_or_url(source) 48 | end 49 | 50 | react_spec = nil 51 | 52 | begin 53 | resolver = Pod::Resolver.new(context.sandbox, context.podfile, locked_dependencies, sources, true) 54 | target_definitions = resolver.resolve 55 | 56 | target_definitions.each do |(definition, dependencies)| 57 | next if definition.name == 'Pods' 58 | 59 | react = dependencies.find { |d| d.spec.name == 'React' || d.spec.name.start_with?('React/') } 60 | next if react.nil? 61 | react_spec = react.spec 62 | end 63 | rescue StandardError => e 64 | Pod::UI.warn 'Failed to resolve dependencies, so pre-patch was not applied, ' + 65 | 'please try running `pod install` again to apply the patch.' 66 | end 67 | 68 | return if react_spec.nil? 69 | 70 | version = react_spec.version.to_s 71 | 72 | # There will probably always be a neeed for the post, but a pre can be ignored 73 | return unless patch_exist?(version) 74 | 75 | path_to_fix = version_file(version, 'pre') 76 | 77 | if File.exist? path_to_fix 78 | Pod::UI.section "Patching React Native #{version}" do 79 | require(path_to_fix) 80 | end 81 | end 82 | end 83 | 84 | private 85 | 86 | def patch_exist?(version) 87 | version_file_name = version.tr('.', '_') 88 | patches = Dir.glob(File.join(versions_path, "#{version_file_name}-*")) 89 | patches.present? 90 | end 91 | 92 | def version_file(version, suffix = 'post') 93 | file_to_parse = version.tr('.', '_') + "-#{suffix}.rb" 94 | File.join(versions_path, file_to_parse) 95 | end 96 | 97 | def versions_path 98 | File.expand_path('../versions', __FILE__) 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_54_2-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods-fix-react-native/helpers/root_helper' 2 | 3 | # Obtain the React Native root directory 4 | $root = get_root 5 | 6 | # TODO: move to be both file in pods and file in node_mods? 7 | def edit_pod_file(path, old_code, new_code) 8 | file = File.join($root, path) 9 | code = File.read(file) 10 | if code.include?(old_code) 11 | puts "[CPFRN] Editing #{file}" if Pod::Config.instance.verbose 12 | FileUtils.chmod('+w', file) 13 | File.write(file, code.sub(old_code, new_code)) 14 | end 15 | end 16 | 17 | def fix_cplusplus_header_compiler_error 18 | filepath = File.join($root, 'React/Base/Surface/SurfaceHostingView/RCTSurfaceSizeMeasureMode.h') 19 | FileUtils.chmod('+w', filepath) 20 | 21 | contents = [] 22 | 23 | file = File.open(filepath, 'r') 24 | file.each_line do |line| 25 | contents << line 26 | end 27 | file.close 28 | 29 | if contents[32].include? '&' 30 | contents.insert(26, '#ifdef __cplusplus') 31 | contents[36] = '#endif' 32 | 33 | file = File.open(filepath, 'w') do |f| 34 | f.puts(contents) 35 | end 36 | end 37 | end 38 | 39 | def fix_unused_yoga_headers 40 | filepath = 'Pods/Target Support Files/yoga/yoga-umbrella.h' 41 | # This only exists when using CocoaPods + Frameworks 42 | return unless File.exists?(filepath) 43 | 44 | contents = [] 45 | file = File.open(filepath, 'r') 46 | file.each_line do |line| 47 | contents << line 48 | end 49 | file.close 50 | 51 | if contents[12].include? 'Utils.h' 52 | contents.delete_at(15) # #import "YGNode.h" 53 | contents.delete_at(15) # #import "YGNodePrint.h" 54 | contents.delete_at(15) # #import "Yoga-internal.h" 55 | contents.delete_at(12) # #import "Utils.h" 56 | 57 | file = File.open(filepath, 'w') do |f| 58 | f.puts(contents) 59 | end 60 | end 61 | end 62 | 63 | fix_unused_yoga_headers 64 | fix_cplusplus_header_compiler_error 65 | 66 | # https://github.com/facebook/react-native/pull/14664 67 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 68 | animation_view_old_code = 'import ' 69 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 70 | edit_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 71 | 72 | # https://github.com/facebook/react-native/issues/13198 73 | # Only needed when you have the DevSupport subspec 74 | has_dev_support = File.exist?(File.join($root, 'Libraries/WebSocket/RCTReconnectingWebSocket.m')) 75 | 76 | if has_dev_support 77 | # Move Fishhook to be based on RN's imports 78 | websocket = 'Libraries/WebSocket/RCTReconnectingWebSocket.m' 79 | websocket_old_code = 'import ' 80 | websocket_new_code = 'import ' 81 | edit_pod_file websocket, websocket_old_code, websocket_new_code 82 | end 83 | 84 | # There's a link in the DevSettings to dev-only import 85 | filepath = "#{$root}/React/Modules/RCTDevSettings.mm" 86 | contents = [] 87 | file = File.open(filepath, 'r') 88 | found = false 89 | file.each_line do |line| 90 | contents << line 91 | end 92 | file.close 93 | 94 | comment_start = '#if ENABLE_PACKAGER_CONNECTION' 95 | comment_end = '#endif' 96 | 97 | if contents[22].rstrip != comment_start 98 | contents.insert(22, comment_start) 99 | contents.insert(24, comment_end) 100 | 101 | contents.insert(207, comment_start) 102 | contents.insert(231, comment_end) 103 | 104 | file = File.open(filepath, 'w') do |f| 105 | f.puts(contents) 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_55_4-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | def fix_unused_yoga_headers 26 | filepath = 'Pods/Target Support Files/yoga/yoga-umbrella.h' 27 | # This only exists when using CocoaPods + Frameworks 28 | return unless File.exists?(filepath) 29 | 30 | contents = [] 31 | file = File.open(filepath, 'r') 32 | file.each_line do |line| 33 | contents << line 34 | end 35 | file.close 36 | 37 | if contents[12].include? 'Utils.h' 38 | Pod::UI.message "Patching #{filepath}", '- ' 39 | contents.delete_at(14) # #import "YGLayout.h" 40 | contents.delete_at(15) # #import "YGNode.h" 41 | contents.delete_at(15) # #import "YGNodePrint.h" 42 | contents.delete_at(15) # #import "YGStyle.h" 43 | contents.delete_at(15) # #import "Yoga-internal.h" 44 | contents.delete_at(12) # #import "Utils.h" 45 | 46 | file = File.open(filepath, 'w') do |f| 47 | f.puts(contents) 48 | end 49 | end 50 | end 51 | 52 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 53 | def has_pods_project_source_file(source_filename) 54 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 55 | File.open(pods_project).grep(/#{source_filename}/).any? 56 | end 57 | 58 | # Detect dependent source file required for building when the given source file is present 59 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 60 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 61 | end 62 | 63 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 64 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 65 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 66 | end 67 | end 68 | 69 | def detect_missing_subspecs 70 | return unless $has_frameworks 71 | 72 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 73 | # When the React pod is generated it must include all the required source, and see umbrella deps. 74 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 75 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 76 | 77 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 78 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 79 | end 80 | 81 | fix_unused_yoga_headers 82 | detect_missing_subspecs 83 | 84 | # # https://github.com/facebook/react-native/pull/14664 85 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 86 | animation_view_old_code = 'import ' 87 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 88 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 89 | 90 | # https://github.com/facebook/react-native/issues/13198 91 | # Only needed when you have the DevSupport subspec 92 | has_dev_support = File.exist?(File.join($root, 'Libraries/WebSocket/RCTReconnectingWebSocket.m')) 93 | 94 | if has_dev_support 95 | # Move Fishhook to be based on RN's imports 96 | websocket = 'Libraries/WebSocket/RCTReconnectingWebSocket.m' 97 | websocket_old_code = 'import ' 98 | websocket_new_code = 'import ' 99 | patch_pod_file websocket, websocket_old_code, websocket_new_code 100 | end 101 | 102 | # There's a link in the DevSettings to dev-only import 103 | filepath = "#{$root}/React/Modules/RCTDevSettings.mm" 104 | contents = [] 105 | file = File.open(filepath, 'r') 106 | found = false 107 | file.each_line do |line| 108 | contents << line 109 | end 110 | file.close 111 | 112 | comment_start = '#if ENABLE_PACKAGER_CONNECTION' 113 | comment_end = '#endif' 114 | 115 | if contents[20].include? 'RCTPackagerClient.h' 116 | Pod::UI.message "Patching #{filepath}", '- ' 117 | contents.insert(20, comment_start) 118 | contents.insert(22, comment_end) 119 | 120 | contents.insert(205, comment_start) 121 | contents.insert(229, comment_end) 122 | 123 | file = File.open(filepath, 'w') do |f| 124 | f.puts(contents) 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hi there! This a CocoaPods plugin that **we, the community**, can use to plug 2 | the holes in React Native's CocoaPods support. 3 | 4 | CocoaPods allows you to add code to run before and at the end of the Podfile via 5 | installation hooks. You probably already have some custom code in there. This 6 | plugin allows all that code to be centralized and reasoned about in a single 7 | place per React Native version. 8 | 9 | ## Why Does This Need To Exist? 10 | 11 | React Native is a pragmatic project, it's great Facebook open sources it, but if 12 | you want to work with a flow they don't use - the onus is on you to make sure it 13 | continues to work. Facebook have a big mono-repo, and so they don't need to use 14 | CocoaPods, and they also use static compilation because they don't use Swift. 15 | Meaning if you want to use CocoaPods and Swift, you're pretty far from their 16 | workflow. 17 | 18 | In order to get it working for just your app you scour, like, a million issues 19 | on React Native (or go look at [artsy/eigen][eigen]) to get it compiling on your 20 | setup. Again, not optimal. 21 | 22 | This plugin _tries_ to fix this by centralizing the code needed to modify React 23 | Native. This means makes it easy to update your versions of React Native, 24 | because you can update the gem at the same time. 25 | 26 | ## Installation 27 | 28 | Lazy way (bad, but ok if 1 engineer): 29 | 30 | $ gem install cocoapods-fix-react-native 31 | 32 | Correct way, edit 33 | [`your Gemfile`](http://www.mokacoding.com/blog/ruby-for-ios-developers-bundler/) 34 | to be: 35 | 36 | gem "cocoapods" 37 | gem "cocoapods-fix-react-native" 38 | 39 | Then remove any React Native related `pre_install` and `post_install` code, and 40 | add this to the top level of your `Podfile`: 41 | 42 | plugin 'cocoapods-fix-react-native' 43 | 44 | For the first time you do this, I'd recommend running `rm -rf Pods; bundle exec 45 | pod install`. After that you can `bundle exec pod install` like normal. 46 | 47 | ## How do I Update This? 48 | 49 | bundle update cocoapods-fix-react-native 50 | 51 | This project is auto-deployed after every merged PR, so it's should always be 52 | up-to-date. 53 | 54 | ## How Does This Work? 55 | 56 | A CocoaPods plugin can register hooks before and after installation, just like 57 | you can in your `Podfile`. This hook will first look at what version of React 58 | Native is installed, and will then run a corresponding scripts to make changes 59 | to the environment. 60 | 61 | ## Custom React Native Root Directory 62 | 63 | To set a custom React Native root directory for dev an environment variable `COCOAPODS_FIX_REACT_NATIVE_DEV_ROOT` may be set. Example: 64 | 65 | # Some shell script that sets up environment variables 66 | export COCOAPODS_FIX_REACT_NATIVE_DEV_ROOT="../my_react_project_directory/node_modules/react-native" 67 | 68 | ## Contributing Back 69 | 70 | You'll note that this repo has issues disabled, I'm not going to make the time 71 | to support questions and requests for fixes to this. I have a lot of projects, 72 | and only so much time. However, I'm happy to handle the mainainance and upkeep 73 | from code people submit. If you want a change, you'll need to do so yourself, so 74 | let's cover how you do that: 75 | 76 | This project is very specific about what versions of React Native it supports, 77 | you can see them in the folder 78 | [`lib/cocoapods-fix-react-native/versions/`][versions]: 79 | 80 | ``` 81 | ~/dev/projects/react-native/cocoapods-fix-react-native master* 82 | ❯ tree lib/cocoapods-fix-react-native/versions/ 83 | lib/cocoapods-fix-react-native/versions/ 84 | └── 0_54_4-post.rb 85 | ``` 86 | 87 | There's likely more than just one by the time you read this, but if you want to 88 | use a version that isn't supported yet, then you're going to want to copy the 89 | most recent into a new file. The files are named by converting dots to 90 | underscores. E.g. `0.54.4` -> `0_54_4-pre.rb`/`0_54_4-post.rb`. 91 | 92 | The scripts itself should be entirely self contained, so that it's easy to 93 | understand without learning the project. 94 | 95 | The biggest change you'd need to make from the sort of code you can find inside 96 | the issues is that it needs to support many different potential roots. So 97 | instead of just `Pods/React/*` - this plugin will also handle 98 | `node_modules/react-native/*` and `../node_modules/react-native/*`. Basically, 99 | your dev repo, and your prod app. 100 | 101 | This can be done by removing `'Pods/React'` from the path and wrapping it with a 102 | `File.join($root, 'Path/InReactLib.js')`. You'll see this in the current 103 | scripts. 104 | 105 | ### Getting Setup To Improve 106 | 107 | Clone this repo: 108 | 109 | ``` 110 | git clone https://github.com/orta/cocoapods-fix-react-native 111 | cd cocoapods-fix-react-native 112 | bundle install 113 | ``` 114 | 115 | You want to use a `:path` based gem in your project's Gemfile to point to the 116 | cloned repo. Make you to your App's `Gemfile` something like this: 117 | 118 | ```ruby 119 | gem 'cocoapods', '~> 1.4.0' 120 | gem 'cocoapods-fix-react-native', path: "../../../../react-native/cocoapods-fix-react-native" 121 | ``` 122 | 123 | Then when you run `bundle exec pod install` in that project, it will use the the 124 | code from your cloned copy. 125 | 126 | As `use_frameworks!` is more strict than static libraries, I'd recommend working 127 | on this project using a repo that has frameworks. 128 | 129 | [eigen]: https://github.com/artsy/eigen/ 130 | [versions]: https://github.com/orta/cocoapods-fix-react-native/tree/master/lib/cocoapods-fix-react-native/versions 131 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_54_4-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | def fix_cplusplus_header_compiler_error 26 | filepath = File.join($root, 'React/Base/Surface/SurfaceHostingView/RCTSurfaceSizeMeasureMode.h') 27 | FileUtils.chmod('+w', filepath) 28 | 29 | contents = [] 30 | 31 | file = File.open(filepath, 'r') 32 | file.each_line do |line| 33 | contents << line 34 | end 35 | file.close 36 | 37 | if contents[32].include? '&' 38 | Pod::UI.message "Patching #{filepath}", '- ' 39 | contents.insert(26, '#ifdef __cplusplus') 40 | contents[36] = '#endif' 41 | 42 | file = File.open(filepath, 'w') do |f| 43 | f.puts(contents) 44 | end 45 | end 46 | end 47 | 48 | def fix_unused_yoga_headers 49 | filepath = 'Pods/Target Support Files/yoga/yoga-umbrella.h' 50 | # This only exists when using CocoaPods + Frameworks 51 | return unless File.exists?(filepath) 52 | 53 | contents = [] 54 | file = File.open(filepath, 'r') 55 | file.each_line do |line| 56 | contents << line 57 | end 58 | file.close 59 | 60 | if contents[12].include? 'Utils.h' 61 | Pod::UI.message "Patching #{filepath}", '- ' 62 | contents.delete_at(15) # #import "YGNode.h" 63 | contents.delete_at(15) # #import "YGNodePrint.h" 64 | contents.delete_at(15) # #import "Yoga-internal.h" 65 | contents.delete_at(12) # #import "Utils.h" 66 | 67 | file = File.open(filepath, 'w') do |f| 68 | f.puts(contents) 69 | end 70 | end 71 | end 72 | 73 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 74 | def has_pods_project_source_file(source_filename) 75 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 76 | File.open(pods_project).grep(/#{source_filename}/).any? 77 | end 78 | 79 | # Detect dependent source file required for building when the given source file is present 80 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 81 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 82 | end 83 | 84 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 85 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 86 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 87 | end 88 | end 89 | 90 | def detect_missing_subspecs 91 | return unless $has_frameworks 92 | 93 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 94 | # When the React pod is generated it must include all the required source, and see umbrella deps. 95 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 96 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 97 | 98 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 99 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 100 | end 101 | 102 | fix_unused_yoga_headers 103 | fix_cplusplus_header_compiler_error 104 | detect_missing_subspecs 105 | 106 | # https://github.com/facebook/react-native/pull/14664 107 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 108 | animation_view_old_code = 'import ' 109 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 110 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 111 | 112 | # https://github.com/facebook/react-native/issues/13198 113 | # Only needed when you have the DevSupport subspec 114 | has_dev_support = File.exist?(File.join($root, 'Libraries/WebSocket/RCTReconnectingWebSocket.m')) 115 | 116 | if has_dev_support 117 | # Move Fishhook to be based on RN's imports 118 | websocket = 'Libraries/WebSocket/RCTReconnectingWebSocket.m' 119 | websocket_old_code = 'import ' 120 | websocket_new_code = 'import ' 121 | patch_pod_file websocket, websocket_old_code, websocket_new_code 122 | end 123 | 124 | # There's a link in the DevSettings to dev-only import 125 | filepath = "#{$root}/React/Modules/RCTDevSettings.mm" 126 | contents = [] 127 | file = File.open(filepath, 'r') 128 | found = false 129 | file.each_line do |line| 130 | contents << line 131 | end 132 | file.close 133 | 134 | comment_start = '#if ENABLE_PACKAGER_CONNECTION' 135 | comment_end = '#endif' 136 | 137 | if contents[22].rstrip != comment_start 138 | Pod::UI.message "Patching #{filepath}", '- ' 139 | 140 | contents.insert(22, comment_start) 141 | contents.insert(24, comment_end) 142 | 143 | contents.insert(207, comment_start) 144 | contents.insert(231, comment_end) 145 | 146 | file = File.open(filepath, 'w') do |f| 147 | f.puts(contents) 148 | end 149 | end 150 | -------------------------------------------------------------------------------- /lib/cocoapods-fix-react-native/versions/0_55_3-post.rb: -------------------------------------------------------------------------------- 1 | require 'cocoapods' 2 | require 'cocoapods-fix-react-native/helpers/root_helper' 3 | 4 | # Obtain the React Native root directory 5 | $root = get_root 6 | 7 | # Detect CocoaPods + Frameworks 8 | $has_frameworks = File.exists?'Pods/Target Support Files/React/React-umbrella.h' 9 | 10 | # TODO: move to be both file in pods and file in node_mods? 11 | def patch_pod_file(path, old_code, new_code) 12 | file = File.join($root, path) 13 | unless File.exist?(file) 14 | Pod::UI.warn "#{file} does not exist so was not patched.." 15 | return 16 | end 17 | code = File.read(file) 18 | if code.include?(old_code) 19 | Pod::UI.message "Patching #{file}", '- ' 20 | FileUtils.chmod('+w', file) 21 | File.write(file, code.sub(old_code, new_code)) 22 | end 23 | end 24 | 25 | def fix_cplusplus_header_compiler_error 26 | filepath = File.join($root, 'React/Base/Surface/SurfaceHostingView/RCTSurfaceSizeMeasureMode.h') 27 | FileUtils.chmod('+w', filepath) 28 | 29 | contents = [] 30 | 31 | file = File.open(filepath, 'r') 32 | file.each_line do |line| 33 | contents << line 34 | end 35 | file.close 36 | 37 | if contents[30].include? '&' 38 | Pod::UI.message "Patching #{filepath}", '- ' 39 | contents.insert(27, '#ifdef __cplusplus') 40 | contents[34] = '#endif' 41 | 42 | file = File.open(filepath, 'w') do |f| 43 | f.puts(contents) 44 | end 45 | end 46 | end 47 | 48 | def fix_unused_yoga_headers 49 | filepath = 'Pods/Target Support Files/yoga/yoga-umbrella.h' 50 | # This only exists when using CocoaPods + Frameworks 51 | return unless File.exists?(filepath) 52 | 53 | contents = [] 54 | file = File.open(filepath, 'r') 55 | file.each_line do |line| 56 | contents << line 57 | end 58 | file.close 59 | 60 | if contents[12].include? 'Utils.h' 61 | Pod::UI.message "Patching #{filepath}", '- ' 62 | contents.delete_at(14) # #import "YGLayout.h" 63 | contents.delete_at(15) # #import "YGNode.h" 64 | contents.delete_at(15) # #import "YGNodePrint.h" 65 | contents.delete_at(15) # #import "YGStyle.h" 66 | contents.delete_at(15) # #import "Yoga-internal.h" 67 | contents.delete_at(12) # #import "Utils.h" 68 | 69 | file = File.open(filepath, 'w') do |f| 70 | f.puts(contents) 71 | end 72 | end 73 | end 74 | 75 | # Detect source file dependency in the generated Pods.xcodeproj workspace sub-project 76 | def has_pods_project_source_file(source_filename) 77 | pods_project = 'Pods/Pods.xcodeproj/project.pbxproj' 78 | File.open(pods_project).grep(/#{source_filename}/).any? 79 | end 80 | 81 | # Detect dependent source file required for building when the given source file is present 82 | def meets_pods_project_source_dependency(source_filename, dependent_source_filename) 83 | has_pods_project_source_file(source_filename) ? has_pods_project_source_file(dependent_source_filename) : true 84 | end 85 | 86 | def detect_missing_subspec_dependency(subspec_name, source_filename, dependent_source_filename) 87 | unless meets_pods_project_source_dependency(source_filename, dependent_source_filename) 88 | Pod::UI.warn "#{subspec_name} subspec may be required given your current dependencies" 89 | end 90 | end 91 | 92 | def detect_missing_subspecs 93 | return unless $has_frameworks 94 | 95 | # For CocoaPods + Frameworks, RCTNetwork and CxxBridge subspecs are necessary for DevSupport. 96 | # When the React pod is generated it must include all the required source, and see umbrella deps. 97 | detect_missing_subspec_dependency('RCTNetwork', 'RCTBlobManager.mm', 'RCTNetworking.mm') 98 | detect_missing_subspec_dependency('CxxBridge', 'RCTJavaScriptLoader.mm', 'RCTCxxBridge.mm') 99 | 100 | # RCTText itself shouldn't require DevSupport, but it depends on Core -> RCTDevSettings -> RCTPackagerClient 101 | detect_missing_subspec_dependency('DevSupport', 'RCTDevSettings.mm', 'RCTPackagerClient.m') 102 | end 103 | 104 | fix_unused_yoga_headers 105 | fix_cplusplus_header_compiler_error 106 | detect_missing_subspecs 107 | 108 | # # https://github.com/facebook/react-native/pull/14664 109 | animation_view_file = 'Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.h' 110 | animation_view_old_code = 'import ' 111 | animation_view_new_code = 'import "RCTValueAnimatedNode.h"' 112 | patch_pod_file animation_view_file, animation_view_old_code, animation_view_new_code 113 | 114 | # https://github.com/facebook/react-native/issues/13198 115 | # Only needed when you have the DevSupport subspec 116 | has_dev_support = File.exist?(File.join($root, 'Libraries/WebSocket/RCTReconnectingWebSocket.m')) 117 | 118 | if has_dev_support 119 | # Move Fishhook to be based on RN's imports 120 | websocket = 'Libraries/WebSocket/RCTReconnectingWebSocket.m' 121 | websocket_old_code = 'import ' 122 | websocket_new_code = 'import ' 123 | patch_pod_file websocket, websocket_old_code, websocket_new_code 124 | end 125 | 126 | # There's a link in the DevSettings to dev-only import 127 | filepath = "#{$root}/React/Modules/RCTDevSettings.mm" 128 | contents = [] 129 | file = File.open(filepath, 'r') 130 | found = false 131 | file.each_line do |line| 132 | contents << line 133 | end 134 | file.close 135 | 136 | comment_start = '#if ENABLE_PACKAGER_CONNECTION' 137 | comment_end = '#endif' 138 | 139 | if contents[20].include? 'RCTPackagerClient.h' 140 | Pod::UI.message "Patching #{filepath}", '- ' 141 | contents.insert(20, comment_start) 142 | contents.insert(22, comment_end) 143 | 144 | contents.insert(205, comment_start) 145 | contents.insert(229, comment_end) 146 | 147 | file = File.open(filepath, 'w') do |f| 148 | f.puts(contents) 149 | end 150 | end 151 | --------------------------------------------------------------------------------