react-native-maps iOS build issues when using use_frameworks! :linkage => :static

Viewed 3487

Main errors: GMUHeatmapTileLayer.h not found and GMUKMLParser.h not found.

This is how my Podfile looks like:

source 'https://github.com/CocoaPods/Specs.git'
    
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
    
install! 'cocoapods', :deterministic_uuids => false
    
platform :ios, '10.0'
    
 
target 'myProject' do
  rn_maps_path = '../node_modules/react-native-maps';
  pod 'react-native-google-maps', path: rn_maps_path
  pod 'GoogleMaps'
  pod 'GooglePlaces'
  pod 'Google-Maps-iOS-Utils',


  config = use_native_modules!
  use_react_native!(
  :path => config[:reactNativePath],
  # to enable hermes on iOS, change `false` to `true` and then install pods
  :hermes_enabled => false
  )

  pod 'react-native-document-picker', :path => '../node_modules/react-native-document-picker'

  pod 'Google-Mobile-Ads-SDK',  '~> 7.69.0'

  pod 'GoogleSignIn', '~> 5.0.0'

  pod 'RNPhotoEditor', :path => '../node_modules/react-native-photo-editor/ios'

  use_frameworks! :linkage => :static

  pod 'iOSPhotoEditor', :git => 'https://github.com/prscX/photo-editor', :branch => 'master'


  post_install do |installer|
     installer.pods_project.targets.each do |target|
      if target.name.include?('iOSPhotoEditor')
        target.build_configurations.each do |config|
          config.build_settings['SWIFT_VERSION'] = '5'
        end
      end
      target.build_configurations.each do |config|
        config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
      end

      if target.name == 'react-native-google-maps'
        target.build_configurations.each do |config|
          config.build_settings['CLANG_ENABLE_MODULES'] = 'No'
        end
      end

      if (target.name&.eql?('FBReactNativeSpec'))
        target.build_phases.each do |build_phase|
          if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs'))
            target.build_phases.move(build_phase, 0)
          end
        end
      end
    end
  end

  # Follow [Flipper iOS Setup Guidelines][https://fbflipper.com/docs/getting-started/ios-native/]
  # This is required because iOSPhotoEditor is implementated using Swift
  $static_framework = ['FlipperKit', 'Flipper', 'Flipper-Folly',
    'CocoaAsyncSocket', 'ComponentKit', 'Flipper-DoubleConversion',
    'Flipper-Glog', 'Flipper-PeerTalk', 'Flipper-RSocket', 'Yoga', 'YogaKit',
    'CocoaLibEvent', 'OpenSSL-Universal', 'boost-for-react-native']

  pre_install do |installer|
    Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
    installer.pod_targets.each do |pod|
        if $static_framework.include?(pod.name)
          def pod.build_type;
            Pod::BuildType.static_library
          end
        end
      end
  end
end

After adding the code for react-native-photo-editor that requires use_frameworks! :linkage => :static

react-native-maps cannot find the google-maps-ios-utils files.

GMUHeatmapTileLayer.h file not found

I've tried manually adding google-maps-ios-utils as described here:

https://github.com/googlemaps/google-maps-ios-utils/blob/b721e95a500d0c9a4fd93738e83fc86c2a57ac89/Swift.md

but still no way for those files to be accessed by AirGoogleMaps files:

enter image description here

Deps:

RN: 0.64.0
react-native-maps: 0.28
Google-Maps-iOS-Utils: 2.1.0
GoogleMaps: 3.5.0

Has anyone succeeded using the react-native-maps with google maps and use_frameworks!?

Is there something wrong with my pod file?

How can I make this Google-Maps-iOS-Utils: 2.1.0 work?

Has anyone some steps to add this library manually and make it build with a bridging header in RN 0.64 with the use_frameworks as above?

I also tried all the steps from this answer but same error as in print screen image shows up.

https://github.com/react-native-maps/react-native-maps/issues/3536#issuecomment-683563649

More info about node_modules deps:

"dependencies": {
"@react-native-async-storage/async-storage": "1.14.1",
"@react-native-community/geolocation": "2.0.2",
"@react-native-community/google-signin": "5.0.0",
"@react-native-community/hooks": "2.6.0",
"@react-native-community/image-editor": "2.3.0",
"@react-native-community/netinfo": "6.0.0",
"@sentry/browser": "6.2.3",
"@sentry/react-native": "2.4.0",
"@svgr/webpack": "4.2.0",
"@xobotyi/scrollbar-width": "1.9.5",
"abortcontroller-polyfill": "1.7.1",
"bfj": "6.1.1",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"color": "3.1.3",
"cross-fetch": "3.1.2",
"css-loader": "1.0.1",
"dotenv": "6.2.0",
"dotenv-expand": "4.2.0",
"file-loader": "2.0.0",
"html-webpack-plugin": "4.0.0-beta.4",
"leaflet": "1.7.1",
"lokijs": "1.5.11",
"mini-css-extract-plugin": "0.4.4",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.2.1",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.5.0",
"postcss-safe-parser": "4.0.1",
"query-string": "6.6.0",
"react": "17.0.1",
"react-dev-utils": "10.2.1",
"react-dom": "17.0.1",
"react-leaflet": "3.1.0",
"react-native": "0.64.0",
"react-native-admob": "2.0.0-beta.6",
"react-native-device-info": "8.0.7",
"react-native-document-picker": "5.0.2",
"react-native-fs": "2.16.6",
"react-native-google-places-autocomplete": "2.2.0",
"react-native-image-crop-picker": "0.36.0",
"react-native-image-size": "1.1.3",
"react-native-local-mongodb": "2.2.9",
"react-native-maps": "0.28.0",
"react-native-photo-editor": "^1.0.10",
"react-native-safe-area-context": "3.2.0",
"react-native-sensitive-info": "5.5.8",
"react-native-splash-screen": "3.2.0",
"react-native-svg": "12.1.0",
"react-native-vector-icons": "8.1.0",
"react-native-web": "0.15.0",
"react-router": "5.1.2",
"react-router-dom": "5.1.2",
"resolve": "1.10.0",
"rn-fetch-blob": "0.12.0",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.2.3",
"ts-events": "3.4.0",
"typescript": "4.0.5",
"url-loader": "1.1.2",
"uuid": "3.4.0",
"webpack": "4.41.6",
"webpack-dev-server": "3.10.3",
"webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "3.6.3"
},
"resolutions": {
  "typescript": "4.0.5"
},
"devDependencies": {
"@babel/core": "7.12.9",
"@babel/plugin-proposal-class-properties": "7.12.13",
"@babel/plugin-proposal-decorators": "7.12.13",
"@babel/plugin-transform-flow-strip-types": "7.12.13",
"@babel/plugin-transform-runtime": "7.12.15",
"@babel/polyfill": "7.12.1",
"@babel/runtime": "7.12.5",
"@carimus/metro-symlinked-deps": "1.1.0",
"@react-native-community/eslint-config": "2.0.0",
"@typescript-eslint/eslint-plugin": "4.19.0",
"@typescript-eslint/parser": "4.19.0",
"babel-jest": "26.6.3",
"babel-loader": "8.2.2",
"babel-plugin-module-resolver": "4.0.0",
"babel-plugin-named-asset-import": "0.2.3",
"babel-plugin-react-native-web": "0.15.0",
"babel-plugin-transform-remove-console": "6.9.4",
"babel-preset-react-app": "7.0.2",
"eslint": "7.19.0",
"jest": "26.6.3",
"jetifier": "^1.6.6",
"metro-react-native-babel-preset": "0.64.0",
"mockdate": "2.0.5",
"moment-timezone": "0.5.33",
"path-exists": "4.0.0",
"react-error-overlay": "6.0.6",
"react-test-renderer": "17.0.1",
"sftp-sync-deploy": "0.7.1",
"yarn-run-all": "3.1.1"
},

Additional notes:

The build process got broken (triggering a new crash relates to rn-maps) when I added https://github.com/prscX/react-native-photo-editor (which requires use_frameworks). If I remove this module and the extra settings associated with it from Podfile everything is ok.

2 Answers

To be able to build the project with react-native-maps and use_frameworks as described in the question I had to fork the react-native-maps library and replace

Google-Maps-iOS-Utils with Google_Maps_iOS_Utils in header imports in

lib/ios/AirGoogleMaps/AIRGoogleMap.m:

#import <Google_Maps_iOS_Utils/GMUKMLParser.h>
#import <Google_Maps_iOS_Utils/GMUPlacemark.h>
#import <Google_Maps_iOS_Utils/GMUPoint.h>
#import <Google_Maps_iOS_Utils/GMUGeometryRenderer.h>

and in lib/ios/AirGoogleMaps/AIRGoogleMapHeatmap.h:

#import <Google_Maps_iOS_Utils/GMUHeatmapTileLayer.h>

If anybody knows a better solution than this, I will be happy to accept it and if the answer is added in next few days I will grant it the bounty attached to the question.

I will probably keep the fork until react-native-maps is updated to have a newer version of google-maps-ios-utils(in v3 i think the issue is fixed).

"react-native-maps": "https://github.com/fdobre/react-native-maps#hot-fix-use-frameworks-ios",

TL;DR: Here is working project build with basic requirment (react-native-maps with user frameworks and react-native-photo-editor).

Add AirMaps and AirGoogleMaps.

source

  1. Right click on your project and click Add files to <projecjName> right click on project and click "Add Files to "projectName"
  2. goto -> node_modules/react-native-maps/lib/ios/
  3. Select both AirMaps and AirGoogleMaps
  4. Make sure the option create groups and your target is selected.

Add AirMaps and AirGoogleMaps

Add Airmaps folder to Library Search Path:

  1. Goto target->build settings-> search for library search path and add the following line (with quotation) for both debug and release, "$(PODS_ROOT)/../../node_modules/react-native-maps/lib/ios/AirMaps"

add AirMaps folder to library search path for Debug

add AirMaps folder to library search path for Release

Add google-maps-ios-utils:

According to these official instruction

  1. git clone https://github.com/googlemaps/google-maps-ios-utils on ios folder with a different name. We need only the content of src folder.

  2. On XCODE, Right click on a project and create a group named Google-Maps-iOS-Utils.creating a new group Google-Maps-iOS-Utils

  3. Right click on that folder and click Add files to ...

  4. Select all the folders of src directory of previously cloned directory of step(i).

  5. Make sure the the options is selected "create groups" and target is selected as your app target. add all the folder in src folder to google-maps-ios-utils group

  6. Delete the Google-Maps-iOS-Utils/Heatmap/HeatMapInterpolationPoint.swift file as mentioned here. Select remove reference when deleting.

  7. Goto project -> build settings -> search for preprocessor macros and add the following for both Debug and Release.

    HAVE_GOOGLE_MAPS=1

    HAVE_GOOGLE_MAPS_UTILS=1

Adding HAVE_GOOGLE_MAPS=1 and HAVE_GOOGLE_MAPS_UTILS=1 to preprocessor macros in build settings

Duplicate Symbol Error

As we have manually added AirGoogleMaps, AirMaps, Google-Maps-iOS-Utils we may get error:

Error: ld: 658 duplicate symbols for architecture x86_64

solution:

  1. Delete Google-Maps-iOS-Utils from Pods/Pods pods section (select the option "Remove References"). Because we have manually added Google-Maps-iOS-Utils Manually. Delete Google-Maps-iOS-Utils

if we compile we'll get ld: 470 duplicate symbols for architecture x86_64.

  1. Delete react-native-maps and react-native-google-maps from Pods/Development Pods Delete react-native-maps and react-native-google-maps

(This is the repetitive task) All 3 folders that are removed here, will regenerate everything pod install execute.

Update 1:

Here is what my Pod file looks like:

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '10.0'

target 'myAwesomeProject' do
  rn_maps_path = '../node_modules/react-native-maps'
  pod 'react-native-google-maps', :path => rn_maps_path
  config = use_native_modules!

  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => false
  )

  target 'myAwesomeProjectTests' do
    inherit! :complete
    # Pods for testing
  end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable the next line.
  use_flipper!()
  pod 'RNPhotoEditor', :path => '../node_modules/react-native-photo-editor/ios'
use_frameworks! :linkage => :static
pod 'iOSPhotoEditor', :git => 'https://github.com/prscX/photo-editor', :branch => 'master'

post_install do |installer|
installer.pods_project.targets.each do |target|
  flipper_post_install(installer) # as stated here https://fbflipper.com/docs/getting-started/react-native-ios/#react-native-063
  if target.name.include?('iOSPhotoEditor')
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '5'
    end
  end
  if target.name == 'react-native-google-maps'
    target.build_configurations.each do |config|
      config.build_settings['CLANG_ENABLE_MODULES'] = 'No' # as mentioned here https://github.com/react-native-maps/react-native-maps/issues/3597#issuecomment-745026120
    end
  end
  if (target.name&.eql?('FBReactNativeSpec')) #as mentioned here https://github.com/software-mansion/react-native-screens/issues/842#issuecomment-812543933
    target.build_phases.each do |build_phase|
      if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs'))
        target.build_phases.move(build_phase, 0)
      end
    end
  end
end
end 

$static_framework = ['FlipperKit', 'Flipper', 'Flipper-Folly',
'CocoaAsyncSocket', 'ComponentKit', 'Flipper-DoubleConversion',
'Flipper-Glog', 'Flipper-PeerTalk', 'Flipper-RSocket', 'Yoga', 'YogaKit',
'CocoaLibEvent', 'OpenSSL-Universal', 'boost-for-react-native']


pre_install do |installer|
Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
installer.pod_targets.each do |pod|
    if $static_framework.include?(pod.name)
      def pod.build_type;
        Pod::BuildType.static_library
      end
    end
  end
end



  # post_install do |installer|
  #   react_native_post_install(installer)
  # end
end

Update 2:

If your problem is not solved by the above answer. Please follow the instructions on my GitHub repo step by step.

Update 3:

Error: 'Google-Maps-iOs-Utils/GMUKMLParser.h' file not found

problem with import statement

Solution:

react-native-maps official guide says to follow this instructions on google-maps-ios-utils/Swift.md. However these instructions are vague. Here is a more clear instructions set:

  1. We already have cloned and added google-maps-ios-utils above .If you haven't, please follow these instructions avobe.

  2. Create Swift Bridging Header

    1. File > New > File > Header File
    2. Usually the name would be [Project Name]-Bridging-Header.h but you name it whatever you want. I am naming it just Header.h in this project as it is really a simple project.new fileselect file typeselect location for header filefinal header file location
    3. Goto target->Build Settings->search for Swift Compiler - General
      1. In Objective-C Bridging Header put Header.h.linking the bridging header
  3. Put these following line on the header file:

    #import "GMUMarkerClustering.h"
    #import "GMUGeoJSONParser.h"
    #import "GMUKMLParser.h"
    #import "GMUGeometryRenderer.h"
    
  4. Put these following line in Google-Maps-iOS-Utils/Clustering/GMUMarkerClustering.h

    #import "GMUCluster.h"
    #import "GMUClusterItem.h"
    #import "GMUClusterManager.h"
    #import "GMUDefaultClusterIconGenerator.h"
    #import "GMUDefaultClusterRenderer.h"
    #import "GMUGridBasedClusterAlgorithm.h"
    #import "GMUNonHierarchicalDistanceBasedAlgorithm.h"
    #import "GMUStaticCluster.h"
    
    #import "GQTPointQuadTree.h"
    
  5. (This is a repetitive task. you need to do this step every time "yarn install" executes)Change to import statement to #import "GMUHeatmapTileLayer.h" in AirGoogleMaps/AIRGoogleMapHeatmap.h file. changing the import statement in AIRGoogleMapHeatman.h

  6. (This is a repetitive task. you need to do this step every time "yarn install" executes) Put these following line in AirGoogleMaps/AIRGoogleMap.m

    #import "GMUKMLParser.h"
    #import "GMUPlacemark.h"
    #import "GMUPoint.h"
    #import "GMUGeometryRenderer.h"
    

changing the import statement in AirGoogleMap.m

Update 4:

In comment, @Florin mentioned of an error

Build input files cannot be found: '/ios/master/src/GeometryUtils/Internal/CatesianPoint.swift'...'

which caused because I didn't know how to use submodules in git. So, when cloned google-maps-ios-utils, that repo doesn't get pushed to my GitHub repo(mentioned in the first line of this answer). That problem is fixed. I have just added the ```src`` folder content without cloning the whole repo in my repo and pushed the changes.

Related