Open fluidsonic opened 9 years ago
One comment: as @mrackwitz has pointed out repeatedly, the Embed Frameworks Script
is necessarily to allow scoping dependencies per build configuration.
CocoaPods is also not really optimized to be used to build _other_frameworks that are used in your app -- those frameworks ideally would be Pods themselves.
Thanks for your detailed issue - could you add your Podfile to it to make it more clear?
Does the "Copy Resources" script actually handle resources from Pods which are build as frameworks for you? Using the current swift branch, resources should be part of the frameworks.
@segiddins Working with Development Pods isn't fun and Xcode is more than capable of building modular apps consisting of many frameworks. Why should I make that more complicated with CocoaPods?
@neonichu Using my example above, for some reason the Api
app target compiles the asset catalog of the Mixpanel
pod. Both are framework targets.
The Mixpanel
pods target has all images inside the asset catalog in the Copy Bundle Resources
phase instead of the asset catalog itself. This seems to be the problem.
@neonichu Why DO app targets still have a Copy Pods Resources
phase when I use use_frameworks!
? Just as you said - the resources should be in the frameworks anyway.
@fluidsonic there are Pods which do not include any source_files
- for them no framework target will be created and any possible resources will be copied into the app bundle by the script. Also the script phase will always be present at the moment in case one switches back to not using frameworks. If it is possible to integrate the resources into a suitable framework target, they will be omitted from the script.
The Mixpanel situation sounds like a bug, though.
@neonichu Are there really pods having neither source files, nor public header files nor vendored frameworks? How would you even use them?
It's also funny that for LayerKit no pod target is created but for CrashlyticsFramework one is created.
The difference is that LayerKit declares its public headers using public_header_files
while CrashlyticsFrameworks declares its public headers using source_files
. Both have no real source files (i.e. .c
, .m
, .swift
, etc.).
So why can't LayerKit
be a pod target too? Why not all? I find the current behavior inconsistent and confusing. Both pods mentioned above have a vendored_framework
and no real source files yet only one of them becomes a pod target.
@fluidsonic a Pod could contain just vendored_libraries
and accompanying resources - or even just package resources, without any code.
Currently, only the presence of any content in the source_files
attribute is used to decide the behaviour - that should indeed be changed to omit headers. Then LayerKit and CrashlyticsFramework would behave the same.
I can't really reproduce the Mixpanel situation you are describing, the Pod doesn't even include any asset catalogues, just plain PNGs. Those simply end up in the framework bundle. Could you share your Podfile to understand the situation better?
Oh, there are two different issues here.
Mixpanel has their PNG files in an asset catalog but in the podspec's resources
they include the PNGs directly. No big issue if the file names are correct.
Yet CocoaPods tries to compile the asset catalog.
PhaseScriptExecution Copy\ Pods\ Resources /Users/marc/Library/Developer/Xcode/DerivedData/MixpanelTest-dxfigjxrwhagxhgzhgxpaxavltjj/Build/Intermediates/MixpanelTest.build/Debug-iphonesimulator/Framework.build/Script-7B9072465AC6FF5A09E4148E.sh
cd /Users/marc/Documents/MixpanelTest
/bin/sh -c /Users/marc/Library/Developer/Xcode/DerivedData/MixpanelTest-dxfigjxrwhagxhgzhgxpaxavltjj/Build/Intermediates/MixpanelTest.build/Debug-iphonesimulator/Framework.build/Script-7B9072465AC6FF5A09E4148E.sh
building file list ... done
sent 29 bytes received 20 bytes 98.00 bytes/sec
total size is 0 speedup is 0.00
2014-12-17 12:01:12.505 IBCocoaTouchImageCatalogTool[1010:11885] CoreUI(DEBUG): CSIGenerator using LZVN Compression coreui version (298.200000)
/* com.apple.actool.document.warnings */
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPArrowLeft.imageset/[][][][][][][MPArrowLeft.png]: warning: The image set "MPArrowLeft" has 2 unassigned images.
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPCheckmark.imageset/[][][][][][][MPCheckmark.png]: warning: The image set "MPCheckmark" has 2 unassigned images.
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPDismissKeyboard.imageset/[][][][][][][MPDismissKeyboard.png]: warning: The image set "MPDismissKeyboard" has 2 unassigned images.
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPLogo.imageset/[][][][][][][MPLogo.png]: warning: The image set "MPLogo" has 2 unassigned images.
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPArrowRight.imageset/[][][][][][][MPArrowRight.png]: warning: The image set "MPArrowRight" has 2 unassigned images.
/Users/marc/Documents/MixpanelTest/Pods/Mixpanel/Mixpanel/Media.xcassets:./MPCloseBtn.imageset/[][][][][][][MPCloseBtn.png]: warning: The image set "MPCloseBtn" has 2 unassigned images.
/* com.apple.actool.compilation-results */
/Users/marc/Library/Developer/Xcode/DerivedData/MixpanelTest-dxfigjxrwhagxhgzhgxpaxavltjj/Build/Products/Debug-iphonesimulator/Framework.framework/Assets.car
Framework
target which compiled Mixpanel's asset catalog, although it's not one of its dependencies. I only added it as a dependency of the App
target.Here is the test project.
Thanks, we definitely need to change the "Copy Resources" script, it compiles and copies asset catalogs unconditionally. //cc @mrackwitz
@neonichu @mrackwiz As of 0.36.rc1 the Copy Resource script still "compiles and copies asset catalogs unconditionally".
Are there any work arounds for this, my app bundle is now twice the size it should be.
This issue's purpose is to share our experience with CocoaPods+Frameworks and to discuss possible improvements. Our app project has 4 app targets (for staging), 3 framework targets (used by the app targets), 1 subproject (another Swift framework), 12 Pod dependencies and 4 transitive Pod dependencies.
Build times are horrible at the moment and even indexing takes 5-10 minutes. Debugging Swift code in the console is completely broken. Swift build & indexing times weren't great before telling CocoaPods to use frameworks, but after the switch they became worse, esp. indexing times. CocoaPods seems to be doing (and allow through
Podfile
) unnecessary complex configurations which make things worse. I don't know though whether the debugger would work correctly when not using CocoaPods. It's known for problems with Swift code.One thing I don't understand is why a custom script is necessary to achieve the copying & signing of frameworks. Xcode by itself is capable of resolving dependencies and copying frameworks as long as you configure it that way.
Another thing which is weird is that frameworks targets also have an
Embed Pods Frameworks
phase which just copies frameworks into other frameworks and pollutes the app bundle with these ghost frameworks that never get loaded anyway. Pod dependencies of framework targets are supposed to be transient dependencies, aren't they?It's also annoying that when two targets (one app target, one framework target - where the app target depends on the framework target) have the same dependency as per
Podfile
BUT the dependency is compiled twice by CocoaPods (since they become two distinct Pods targets) - wasting a lot of time.An Experiment
I was able to manually remove the
Embed Pods Frameworks
phases and replace them with aCopy Files
phase withDestination
set toFrameworks
. After adding all Pod frameworks to theCopy Files
phase the app still builds & runs fine.I'll try to explain our workspace's structure, how it's configured and what the pros/cons of these changes are.
Workspace Structure
(I simplified the structure a bit since we also have one app target per staging level.)
Projects & Targets
App
ProjectApp
(the actual app)Api
(Swift framework)Database
(Swift framework)Model
(Swift framework)Pods
ProjectPods-AFNetworking
Pods-Mixpanel
Target Dependencies Phase (Explicit Target Dependencies)
Empty for all targets.
Link With Libraries Phase (Implicit Target Dependencies)
App
: none!Api
:Model
(fromApp
project)AFNetworking
(fromPods
project)Database
:Model
(fromApp
project)Model
: none!Copy Files Phase (Implicit Target Dependencies)
App
:Api
(fromApp
project)Database
(fromApp
project)Model
(fromApp
project)AFNetworking
(fromPods
project)Mixpanel
(fromPods
project)Pods
project)Api
,Database
andModel
: none!Results
Works as expected! Everything is built in the correct order and copied into the app bundle. It runs fine on the device. It's a simple configuration but CocoaPods seems to make this unnecessary complex.
It also works after deleting the app or wiping
DerivedData
so there's nothing in the cache which affects this.Cons
AFNetworking
Pods targets (e.g.Pods-App1-AFNetworking
andPods-App2-AFNetworking
) and both useAFNetworking.framework
as output name then Xcode gets confused (at least after restarting it).Pros
Pods-App
andPods-Api
) anymore.The two app targets
App
andApi
depend on the same Pods targetAFNetworking
so the Pod is only built once. Build time is reduced!In my case the targets
App
andApi
both haveAFNetworking
as a dependency which is fine. But CocoaPods unnecessarily created two distinct Pods targets for them:Pods-App-AFNetworking
andPods-Api-AFNetworking
. This is also unnecessary sinceApp
depends onApi
and alsoApi
is a framework so dependencies should be only transitive.Embed Pods Frameworks
scripts runs on every build. So build time is reduced even further.-framework
and-iquote
flags in thexcconfig
files. Let Xcode do that.Summary
CocoaPods is doing stuff on its own which could also be done by Xcode itself. Xcode can handle things like copying frameworks more effectively which reduces build times. CocoaPods' custom script phases are totally annoying as they run on every build.
I think with frameworks enabled the compilation of storyboards, asset catalogs and the copying of resources could also be done by Xcode without having a custom script. Again this script is executed for every build which takes time and for some reason every target also compiles asset catalogs of non-dependencies.
Simplifying & cleaning up the overall structure could also save build time, improve indexing time & quality and speed up Xcode in general. But I expect that such improvements require overall architectural changes which is a lot of work.