shoutem / platform

Shoutem platform
Other
42 stars 17 forks source link

Use of iOS dynamic frameworks in a custom extension (use_frameworks! or use_modular_headers!) #73

Open Souro7 opened 4 years ago

Souro7 commented 4 years ago

What we are trying to do

We are trying to use a dynamic framework (native iOS swift) for our extension. Specifically, use_frameworks! is being used.

What we have tried so far

For this, we have created a react-native bridge, which uses the same Framework. This works perfectly in our react-native app when we add the following to our Podfile:

use_frameworks!
  pre_install do |installer|
     installer.pod_targets.each do |pod|
       if pod.name.eql?('RNPermissions') || pod.name.start_with?('Permission-')
         def pod.build_type;
           Pod::BuildType.static_library # I assume you use CocoaPods >= 1.9
         end
       end
     end
   end

We have published a version of our extension using the same, however the shoutem clone command fails at pod install with the following error when we clone this app from shoutem:

Screenshot 2020-10-08 at 6 19 54 PM

Again to fix this, we made the following changes to the Podfile:

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

This resolves the pod install issue. However, this leads to Build fail with the following errors:

Screenshot 2020-10-08 at 6 34 01 PM

Another approach we have tried is use_modular_headers! instead of use_frameworks!. This eliminates the previous errors, however, the Build still fails with the following error:

Screenshot 2020-10-08 at 6 39 38 PM

Our entire Podfile is attached below:

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

platform :ios, '11.0'

install! 'cocoapods', :deterministic_uuids => false

target 'NewTest' do
  config = use_native_modules!

  use_react_native!

  pod 'Shopify', :path => '../node_modules/shoutem.shopify/Shopify.podspec'

  # React Native FBSDK dependencies
  pod 'FBSDKCoreKit'
  pod 'FBSDKLoginKit'

  use_modular_headers!
  $static_framework = ['CocoaLibEvent', 'openssl-ios-bitcode', 'OpenSSL-Universal']

  pre_install do |installer|
    Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
    installer.pod_targets.each do |pod|
      if pod.name.eql?('RNPermissions') || pod.name.start_with?('Permission-')
                              def pod.build_type;
                                Pod::BuildType.static_library
                              end
                            end
        if $static_framework.include?(pod.name)
          def pod.build_type;
            Pod::BuildType.static_library
          end
        end
      end
  end
             pod 'RNNearBee', :path => '../node_modules/react-native-nearbee'
             pod 'ReactNativePermissions', :path => '../node_modules/react-native-permissions-ble-fix'
             pod 'Permission-BluetoothPeripheral', :path => "../node_modules/react-native-permissions/ios/BluetoothPeripheral.podspec"
             pod 'Permission-LocationAlways', :path => "../node_modules/react-native-permissions/ios/LocationAlways.podspec"
             pod 'Permission-LocationWhenInUse', :path => "../node_modules/react-native-permissions/ios/LocationWhenInUse.podspec"
             pod 'Permission-Notifications', :path => "../node_modules/react-native-permissions/ios/Notifications.podspec"

end

## <Additional target>

use_flipper!
post_install do |installer|
  flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
    end

    ## <Extension postinstall targets>

                if target.name == 'Starscream'
                    target.build_configurations.each do |config|
                        config.build_settings['SWIFT_VERSION'] = '4.2'
                    end
                end

  end
end

Question

We can see that it is mentioned in your documentation that we are supposed to

Uncomment this line if you're using Swift or would like to use dynamic frameworks: https://shoutem.github.io/docs/extensions/tutorials/using-native-api#referencing-a-3rd-party-sdk

Is there a way to use iOS dynamic frameworks in our extension?

Definitely-Not-Vlad commented 4 years ago

Hey @Souro7.

Looking into the issue, I tried to clone the app you had mentioned in an email thread, but it apparently no longer exists. If you could provide me with a new app ID to clone and reproduce this behavior, I'd be happy to have a crack at resolving this.

Looking into the last error you mention: 'glog.glog.log_severity' appears within namespace 'google', I found this github issue comment which states that you can utilize the following in the Podfile (in our case the Podfile.template) resolve this issue:

pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec', :modular_headers => false
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec', :modular_headers => false

As I'm unable to verify this without an test / example app ID, I can't check it out, but if you give me an app ID I'd be happy to try it myself.

This may fail as the path for the podspec may be different now compared to when this was written, so if it fails, double check that the path is correct.

Souro7 commented 4 years ago

Hi @Definitely-Not-Vlad, I have created a new app again with the changes as suggested by you: Framework (167903)

I was able to resolve the errors by adding the flags you suggested. But it looks like we should build only the required framework using modular headers

using :modular_headers => true

Is there a better way to do this in Shoutem? Since it looks like the dependency of that framework is not getting linked when this is done.

Runtime error:

Screenshot 2020-11-02 at 7 26 48 PM

Updated Podfile:

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

platform :ios, '11.0'

install! 'cocoapods', :deterministic_uuids => false

target 'Framework' do
  config = use_native_modules!

  use_react_native!

  pod 'Shopify', :path => '../node_modules/shoutem.shopify/Shopify.podspec'
  pod 'Permission-Notifications', :path => '../node_modules/react-native-permissions/ios/Notifications.podspec'

  # React Native FBSDK dependencies
  pod 'FBSDKCoreKit'
  pod 'FBSDKLoginKit'

  $static_framework = ['CocoaLibEvent', 'openssl-ios-bitcode', 'OpenSSL-Universal']
      pre_install do |installer|
    Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
    installer.pod_targets.each do |pod|
      if pod.name.eql?('RNPermissions') || pod.name.start_with?('Permission-')
                              def pod.build_type;
                                Pod::BuildType.static_library
                              end
                            end
        if $static_framework.include?(pod.name)
          def pod.build_type;
            Pod::BuildType.static_library
          end
        end
      end
  end
      pod 'EddystoneScanner', :modular_headers => true
      pod 'NearBee', '3.2.7-beta1', :modular_headers => true
      pod 'RNNearBee', :path => '../node_modules/react-native-nearbee', :modular_headers => true

             pod 'ReactNativePermissions', :path => '../node_modules/react-native-permissions-ble-fix'
             pod 'Permission-BluetoothPeripheral', :path => "../node_modules/react-native-permissions/ios/BluetoothPeripheral.podspec"
             pod 'Permission-LocationAlways', :path => "../node_modules/react-native-permissions/ios/LocationAlways.podspec"
             pod 'Permission-LocationWhenInUse', :path => "../node_modules/react-native-permissions/ios/LocationWhenInUse.podspec"
             pod 'Permission-Notifications', :path => "../node_modules/react-native-permissions/ios/Notifications.podspec"

end

## <Additional target>

use_flipper!
post_install do |installer|
  flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
    end

    ## <Extension postinstall targets>

                if target.name == 'Starscream'
                    target.build_configurations.each do |config|
                        config.build_settings['SWIFT_VERSION'] = '4.2'
                    end
                end

  end
end
Definitely-Not-Vlad commented 3 years ago

I was going to try to apply what you did with the :modular_headers => false, but it looks like we'd end up in the same spot.

Is there a better way to do this in Shoutem? Since it looks like the dependency of that framework is not getting linked when this is done.

Unfortunately I can't think of a way to resolve this. Sorry for not being of much help with this. I'm not familiar enough with using (or not using) modular headers as this isn't a use case we've run into so far.