cocoapods-binary-cache icon indicating copy to clipboard operation
cocoapods-binary-cache copied to clipboard

Integration Attempts to Use Dependent Frameworks from Wrong Path

Open VaslD opened this issue 4 years ago • 4 comments

Not entirely sure whether this is a cocoapods-binary-cache issue or CocoaPods issue. I did not see this before so I'll assume it's related to cocoapods-binary-cache.

I have some app modules packaged as Pods hosted on private Git repo, the Podfile is defined as follows:

# Enable prebuilt binary pods.
plugin "cocoapods-binary-cache"
config_cocoapods_binary_cache(
  cache_repo: {
    "default" => {
      "remote" => "[email protected]:some/repo.git",
      "local" => "~/Library/Caches/CocoaPods/Binary",
    },
  },
  prebuild_config: "Debug",
  prebuild_sandbox_path: "Pods/_Prebuild",
  device_build_enabled: true,

  # Pull source for binary pods.
  still_download_sources: false,
)

platform :ios, "11.0"
inhibit_all_warnings!
use_frameworks!

...

pod "ModuleOne", :git => "[email protected]:some/repo.git", :tag => "1.0", :binary => true

ModuleOne here is a mega Pod that depends on some other framework, say ModuleZero and so on. It has an oversimplified folder structure like this:

.
├── ModuleOne
│   └─── ModuleZero
│        ├── ModuleZero.bundle
│        └── ModuleZero.framework
├── License
├── ModuleOne.podspec
└── ReadMe.md

Running pod binary prebuild --push or bundle exec pod binary prebuild --push generated/prebuilt ModuleOne and dependencies as expected in the specified sandbox directory, but the final integration failed due to "Errno::ENOENT - No such file or directory @ realpath_rec - ...". No Pod-related workspace was generated after the command failed.

I dug around and it seemed the issue was cocoapods-binary-cache or CocoaPods looking into the wrong path when searching for dependent frameworks. When ModuleOne depended on ModuleZero, ModuleOne was prebuilt into $SANDBOX_PATH/GeneratedFrameworks/ModuleOne/ModuleOne.framework, where CocoaPods got it right; ModuleZero was left in $SANDBOX_PATH/GeneratedFrameworks/ModuleOne/ModuleOne/ModuleZero/ModuleZero.framework but somehow CocoaPods wanted to find it in $SANBOX_PATH/GeneratedFrameworks/ModuleOne/ModuleZero.framework. Even if I manually moved .framework directory, .bundle also faced the same issue.

Verbose pod binary prebuild points the stack to .gem/gems/cocoapods-1.10.0/lib/cocoapods/project.rb:326 but I've never ran into this issue on stock CocoaPods installation.

VaslD avatar Nov 09 '20 06:11 VaslD

Hi @Vasl, Thanks for the details about the issue. I would like to ask for some more information to troubleshoot it.

1/ Is ModuleZero a vendor framework of ModuleOne? In other words, in the declaration of ModuleOne, we have:

s.vendored_frameworks = ["ModuleZero/ModuleZero.framework"]

Am I right?

2/ Is the error message "Errno::ENOENT - No such file or directory @ realpath_rec" related to ModuleZero or ModuleOne? Also, it would be best if you can share what file that was (ModuleZero.bundle or `ModuleZero.framework...)

Thank you!

trinhngocthuyen avatar Nov 14 '20 23:11 trinhngocthuyen

Thank you for getting back to me. I'm on a multi-project schedule and I do not have access to that project recently. I'll take a look the next time I get the chance to work on it. Sorry if not happening soon.

I can somewhat remember that ModuleZero was a popular framework from local business/payment partner so it was included/distributed framework-only. Anyway I'll let you know when I have the source.

VaslD avatar Nov 15 '20 15:11 VaslD

So I got to look at the snapshot.

  1. ModuleZero is indeed a vendored framework of ModulesOne's default sub-spec. The Podspec has definition:

    s.subspec 'Payment' do |pay|
         pay.ios.vendored_frameworks = ['ModuleOne/ModuleZero/ModuleZero.framework']
         pay.resource = ['ModuleOne/ModuleZero/ModuleZero.bundle']
         pay.frameworks = 'CFNetwork', 'SystemConfiguration', 'Security', 'AssetsLibrary','CoreMotion', 'CoreTelephony'
         pay.ios.libraries = 'c++', 'stdc++' , 'z' , 'sqlite3'
         pay.xcconfig = { 'OTHER_LDFLAGS' => '-ObjC' }
     end
    

    And:

    s.default_subspec = ...,'Payment',...
    
  2. I cannot share files in this project as doing so violates our security policy. (Even though the framework may be from a publicly available SDK.) But I can say that .framework/ contains pretty much what you'd expect from a compiled framework: Headers/, Modules/, a binary file of the same name of the framework, and its -Info.plist. While .bundle/ contains about 10 images and some configuration files.

    The error points to .framework/ on the first/clean run. And if I manually move .framework/ to the expected path in "_Prebuild", the next run fails with .bundle/ not found.

VaslD avatar Nov 16 '20 04:11 VaslD

Hi. Sorry, I might express my point wrongly about (2). I understand it's a private repo which cannot be disclosed :D. What I wanted to check is whether the error is related to the .framework or the .bundle as we have some special logic for bundles which might went wrong.

Thank you for the details. Will check it then!

trinhngocthuyen avatar Nov 16 '20 05:11 trinhngocthuyen