trinhngocthuyen / cocoapods-spm

A CocoaPods plugin to add SPM dependencies to CocoaPods-based projects
MIT License
35 stars 7 forks source link

[Bug] Update to 0.1.2 fails upon pod install – 'force_encoding': can't modify frozen String: "stack level too deep" #64

Closed kalub92 closed 2 months ago

kalub92 commented 2 months ago

What happened?

I am attempting to install an SPM package as a spm_dependency in a .podspec and have defined the related spm_pkg in my Podfile.

On 0.1.1, I could successfully complete pod install and attempt to compile in Xcode. But after updating to 0.1.2 this morning, I'm getting stuck during pod install.

I added the CocoaPods env data, but had to redact quite a bit, but left what matters.

This is the error I see when it gets to the Resolving SPM packages... step:

/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.15.0/lib/cocoapods/user_interface/error_report.rb:34:in `force_encoding': can't modify frozen String: "stack level too deep" (FrozenError)
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.15.0/lib/cocoapods/user_interface/error_report.rb:34:in `report'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.15.0/lib/cocoapods/command.rb:66:in `report_error'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/claide-1.0.3/lib/claide/command.rb:396:in `handle_exception'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/claide-1.0.3/lib/claide/command.rb:337:in `rescue in run'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/claide-1.0.3/lib/claide/command.rb:324:in `run'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.15.0/lib/cocoapods/command.rb:52:in `run'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.15.0/bin/pod:55:in `<top (required)>'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `load'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `<main>'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `eval'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `<main>'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:96:in `each': stack level too deep (SystemStackError)
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:96:in `find'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:96:in `block in direct_products_of'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:93:in `each'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:93:in `flat_map'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:93:in `direct_products_of'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `recursive_products_of'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:80:in `block in recursive_products_of'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `each'
         ... 8445 levels...
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `load'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `<main>'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `eval'
        from /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `<main>'

CocoaPods environment

Stack

   CocoaPods : 1.12.1
        Ruby : ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]
    RubyGems : 3.3.3
        Host : macOS 14.3.1 (23D60)
       Xcode : 15.0 (15A240d)
         Git : git version 2.39.3 (Apple Git-145)
Ruby lib dir : /Users/cstultz/.rvm/rubies/ruby-3.1.0/lib
Repositories : trunk - CDN - https://cdn.cocoapods.org/

Installation Source

Executable Path: /Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod

Plugins

cocoapods-deintegrate : 1.0.5
cocoapods-plugins     : 1.0.0
cocoapods-pod-linkage : 0.0.1
cocoapods-search      : 1.0.1
cocoapods-spm         : 0.1.2
cocoapods-trunk       : 1.6.0
cocoapods-try         : 1.2.0
slather               : 2.7.2

Podfile

require '../tools/cocoapods-utilities/Utilities.rb'
plugin 'cocoapods-pod-linkage'
plugin 'cocoapods-spm'

# Check for bundler
verify_bundler_was_used()

workspace 'FooWorkspace'
use_frameworks! :linkage => :dynamic
inhibit_all_warnings!
platform :ios, '16.0'
source 'https://cdn.cocoapods.org/'

install! 'cocoapods', :disable_input_output_paths => true

def test_pods
  pod_module 'TestKit'
end

def spm_pods
  spm_pkg "SPMPackageA",
          :git => "https://github.com/foobardev/spm-package-a.git",
          :tag => "2.1.3"

  spm_pkg "SPMPackageB",
          :git => "https://github.com/foobardev/spm-package-b.git",
          :tag => "1.4.0"
end

# You should NOT add or remove pods directly to the targets below! Use the methods above.
abstract_target 'Foo' do

  target 'Bar' do
    project 'FooWorkspace', 'DebugTeam' => :debug, 'UnitTests' => :debug
  end

  target 'Bar Tests' do
    project 'FooWorkspace, 'DebugTeam' => :debug, 'UnitTests' => :debug
    test_pods
    pod 'Nimble', '~> 11.2.0'
    pod 'Quick', '~> 6.1.0'
    pod 'DGCharts', '5.0'
  end

end

Anything else?

Here is my .podspec definition (again, fairly redacted):


Pod::Spec.new do |s|
  s.name = 'TestKit'
  s.version = '0.1.1'
  s.summary = 'This pod contains mocks and infrastructure needed to run all types of unit and integration tests.'

  s.source_files = 'lib/sources/**/*.swift'
  s.resources = 'lib/resources/**/*'

  s.ios.frameworks = 'UIKit', 'Foundation'

  s.spm_dependency 'SPMPackageA/SPMPackageA'
  s.spm_dependency 'SPMPackageB/SPMPackageB'

end
kalub92 commented 2 months ago

Some more context is that SPMPackageA has a fairly complicated structure of products, targets, and dependencies that are related to some local .binaryTarget XCFrameworks, which I was wondering if that could be part of this issue?

trinhngocthuyen commented 2 months ago

@kalub92 Thanks for reaching out! For reproducing the issue, is it okay for you to share what packages were being used, if you don't mind?

kalub92 commented 2 months ago

@trinhngocthuyen I wish I could, but they are internal frameworks I use at work so I can try to reproduce the situation using a similar structure and share it here but otherwise I can't really share the internals of the packages.

trinhngocthuyen commented 2 months ago

A package with a similar structure should be sufficient to debug the issue. For the record, in the "Resolving SPM packages" step, the plugin ended up with a loop when resolving products' dependencies recursively. So, yes, there might be a corner case the plugin hasn't handled yet.

kalub92 commented 2 months ago

@trinhngocthuyen, I was able to reproduce a similar recursion-related (I think) issue by re-creating the structure of the SPM packages in the Xcode project here: SampleSPMPackageIssue

Here are the sample package refs:

Output of pod install:

[!] Metadata of `` does not exist

/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/result.rb:30:in `metadata_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:87:in `direct_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:80:in `block in recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `flat_map'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:80:in `block in recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `flat_map'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:80:in `block in recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `flat_map'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:79:in `recursive_products_of'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:68:in `block in resolve_product_deps'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:65:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:65:in `resolve_product_deps'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver/product_dep_resolver.rb:18:in `resolve'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver.rb:22:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/resolver.rb:22:in `resolve'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/patch/installer.rb:60:in `block in resolve_spm_dependencies'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/user_interface.rb:64:in `section'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/patch/installer.rb:58:in `resolve_spm_dependencies'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-spm-0.1.2/lib/cocoapods-spm/patch/installer.rb:12:in `resolve_dependencies'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/installer.rb:162:in `install!'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/command/install.rb:52:in `run'
/Users/cstultz/.rvm/rubies/ruby-3.1.0/lib/ruby/gems/3.1.0/gems/claide-1.1.0/lib/claide/command.rb:334:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/command.rb:52:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/bin/pod:55:in `<top (required)>'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `load'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `<main>'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `eval'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `<main>'
trinhngocthuyen commented 2 months ago

@kalub92 Thank you for your input. I really appreciate the effort πŸ‘. I've just made some patches in #65, #66, #67 that target the demo project. Would you mind trying again with the latest on main? Thanks!

On a side note, the demo project crashed because OneSignalOutcomes.framework was missing (it was neither found in SamplePackageA, SamplePackageAInterface), and SamplePackageB)

trinhngocthuyen commented 2 months ago

Although the "metadata not exist" issue (in this comment) has been fixed, I think the "stack level too deep" issue persists.

Can reproduce the issue with the GoogleMaps package https://github.com/googlemaps/ios-maps-sdk/blob/main/Package.swift. Let me investigate this case.

kalub92 commented 2 months ago

You're welcome! Awesome… Thanks so much.

In the sample project, your three recent PRs fixed the Metadata of `` does not exist issue on pod install. I also updated SamplePackageB to include the missing OneSignalOutcomes.xcframework.

I just ran pod install after updating cocoapods-spm from main in my work project repo, but am still getting the same stack level too deep error.

However, I removed my internal dependencies and attempted the same thing with only the GoogleMaps package and found that I get the exact same error output. So I'm hopeful that whatever is causing it is the same between both!

kalub92 commented 2 months ago

@trinhngocthuyen any update on this? 😁

trinhngocthuyen commented 2 months ago

@kalub92 I figured out the root cause but haven't fixed it thoroughly.

Following is the explanation of the issue for GoogleMaps:

trinhngocthuyen commented 2 months ago

Well, the current linking strategy (based on xcconfig settings) seems a bit buggy.

As this's a blocker, I think we might gonna need an option to fall back to the normal linking, meaning:

This way, we buy some buffer time to fix the issue with the current linking strategy.

trinhngocthuyen commented 2 months ago

@kalub92 The PR https://github.com/trinhngocthuyen/cocoapods-spm/pull/69 introduces the option to switch to the default Xcode linking. For the workaround, could you please help try this option?

Example: Podfile#L42-L50

kalub92 commented 2 months ago

@trinhngocthuyen I see – that makes sense in terms of the binary target and product/library names being the same!

Thanks for making the workaround. It resolved the stack level too deep issue and allowed the Resolving SPM Packages step during pod install to complete.

I tried this on my work project, but now I am seeing the following error during one of the post-install hooks (e.g. 5.update_settings.rb):

NoMethodError - undefined method `flat_map' for nil:NilClass

          spm_dependencies_for(target).flat_map { |d| @spm_products[d.product].to_a }.uniq(&:name)
                                      ^^^^^^^^^
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/resolver/result.rb:38:in `spm_products_for'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/post_integrate/5.update_settings.rb:90:in `modulemap_args_for_target'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/post_integrate/5.update_settings.rb:49:in `block in update_modulemap_flags'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:66:in `block in perform_settings_update'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:76:in `block (2 levels) in perform_settings_update'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:75:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:75:in `block in perform_settings_update'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:74:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:74:in `perform_settings_update'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/post_integrate/5.update_settings.rb:46:in `update_modulemap_flags'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/post_integrate/5.update_settings.rb:10:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:53:in `block (2 levels) in run_hooks'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/user_interface.rb:149:in `message'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:52:in `block in run_hooks'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:48:in `each'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/hooks/base.rb:48:in `run_hooks'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/patch/installer.rb:54:in `run_spm_post_integrate_hooks'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bundler/gems/cocoapods-spm-faf3f2ad2c7d/lib/cocoapods-spm/patch/installer.rb:35:in `integrate'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/installer.rb:170:in `install!'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/command/install.rb:52:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/claide-1.0.3/lib/claide/command.rb:334:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/lib/cocoapods/command.rb:52:in `run'
/Users/cstultz/.rvm/gems/ruby-3.1.0/gems/cocoapods-1.12.1/bin/pod:55:in `<top (required)>'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `load'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/pod:25:in `<main>'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `eval'
/Users/cstultz/.rvm/gems/ruby-3.1.0/bin/ruby_executable_hooks:22:in `<main>'
trinhngocthuyen commented 2 months ago

@kalub92 could you help try again? tentatively fixed by https://github.com/trinhngocthuyen/cocoapods-spm/pull/70

kalub92 commented 2 months ago

@trinhngocthuyen that fixed it! You're my hero! πŸŽ‰πŸŽ‰πŸŽ‰

Do you have a donate button or anything somewhere?

I'm super grateful for your help with this and would love to repay you in some way!

trinhngocthuyen commented 2 months ago

@kalub92 I'm glad it helps. Thanks for the kind gesture btw! Using this plugin and providing feedback is already a treat for me πŸ‘.

trinhngocthuyen commented 2 months ago

This should be fixed for both linking strategies in 0.1.4. Closing this issue for now. Feel free to reopen if this issue persists.