Cocoapods: Xcode 10 new build system makes asset catalog invalid specified by podspec's`resource(s)`

Created on 22 Sep 2018  ·  82Comments  ·  Source: CocoaPods/CocoaPods

Report

What did you do?

ℹ Please replace these two lines with what you did.
Xcode 10 new build system, CocoaPods 1.5.3.
Private pod (named Pod1), podspec: s.resources = ['Pod1/Assets/*'], this folder includes a asset catalog(images.xcassets).
Pod install and compile

What did you expect to happen?

image in Pod1's images.xcassets do not show in UI by using -[UIImage imageNamed:] with new build system

What happened instead?

  • images not show.
  • images in pod's images.assets not in Asset.car in .app
  • build log:
Showing All Messages
:-1: ignoring duplicated output file: '/Users/ooops/Library/Developer/Xcode/DerivedData/Example-aavrswxzmgwwppbxcwetebxamdir/Build/Products/Debug-iphonesimulator/Example.app/Assets.car' (in target 'Example')

CocoaPods Environment

Stack

   CocoaPods : 1.5.3
        Ruby : ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-darwin17]
    RubyGems : 2.6.14
        Host : Mac OS X 10.14 (18A384a)
       Xcode : 10.0 (10A255)
         Git : git version 2.19.0
Ruby lib dir : /Users/ooops/.rvm/rubies/ruby-2.2.7/lib
Repositories : master - https://github.com/CocoaPods/Specs.git @ 29c32347b0e16c19f1f2b438980959b5240bcc48
               sankuai-binaryspecs - ssh://[email protected]/ios/binaryspecs.git @ 5c5f950f2d3697f524280a4d7bcb3dee485ba9ca
               sankuai-bizapp-specs - ssh://[email protected]/sjst/bizapp-specs.git @ f4413e94a43dc0539f11d4d453bdd09a5710d370
               sankuai-specs - ssh://[email protected]/ios/specs.git @ 33e04c7093977188ea0944da9f9a5f6582957c8e
               sankuai-specs-1 - ssh://[email protected]/wm/specs.git @ dbee903fe0a3627de127fda74117f76338db224f

Installation Source

Executable Path: /Users/ooops/.rvm/gems/ruby-2.2.7/bin/pod

Plugins

cocoapods-deintegrate : 1.0.2
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.3.0
cocoapods-try         : 1.1.0

Podfile

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'Example' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for Example
  pod 'Pod1', :path => '../Pod1'
  pod 'Pod2', :path => '../Pod2'

end

Project that demonstrates the issue

cocoapods-resources.zip
I didn't show image in demo app, just open the build artifact and show package content of .app to see if Asset.car contains the image in Pod1/Assets/images.xcassets

Investigation

I have read the Build System Release Notes for Xcode 10, it said

Targets which have multiple asset catalogs that aren't in the same build phase may produce an error regarding a "duplicate output file". (39810274)

Workaround: Ensure that all asset catalogs are processed by the same build phase in the target.

The problem is I don't know how to ensure all asset catalogs are processed in same build phase for the target.
Any advice or guidance would be greatly appreciated.

new build system workaround available

Most helpful comment

*.xcassets of Copy Bundle Resources --> Assets.car
*.xcassets of [CP] Copy Pods Resource --> other Assets.car
The first one covers second in the New Build System,That's the reason.

All 82 comments

I am having similar issue too. clean and rebuild will include all assets. but when I re-run the project, Assets.car will be empty, recompiled without assets from pods. It seems the "re-run" doesn't copy the assets from pods.

I had to switch back to legacy build system on Xcode 10. Please fix this.

I havent verified but this might be the same issue as this https://github.com/CocoaPods/CocoaPods/issues/8073

Worth trying master to see if it fixes it and use:

install! 'cocoapods', :disable_input_output_paths => true

Other than that I need to find time to investigate this so I am uncertain yet if its a CocoaPods issue or an Xcode 10 new build system issue.

Meanwhile investigation you can you can use a work arounds : using the Xcode Legacy Build System and not the Xcode 10 new build system.

Xcode / File / Workspace Settings / Build system / select "Legacy Build System"

capture d ecran 2018-09-25 a 11 04 14

@samirGuerdah Thanks for your workaround. I have already known this way can make it work. But I also hope this issue can be solved when using new build system.

Uncertain yet if its a CocoaPods bug itself or new build system bug. It appears that switching to legacy makes it work for folks. I haven't had the time to investigate it though.

@dnkoutso Remind

@ooopscc there is no specific time an issue will be dealt with. This is mostly handled by free time of a few folks. If you need this faster I highly recommend to investigate the sources, otherwise I cannot provide a time frame sorry.

It is ok to leave it alone for now, because I can use legacy build system. I post this issue not asking for workaround, I already know it. I think it’s not compatible with new build system, just solve it whenever it’s convenient for you. Thanks.

Trying to investigate this issue. Found that warning is fixed by removing input/output paths (or using related install option). But assets are still not present on incremental builds just like @ansonbtl described.

*.xcassets of Copy Bundle Resources --> Assets.car
*.xcassets of [CP] Copy Pods Resource --> other Assets.car
The first one covers second in the New Build System,That's the reason.

Great guess! Anyone have ideas how to guarantee [CP] Copy Pods Resource execution after Copy Bundle Resources?

It seems I found the solution.

Placing Assets.car in input files of the [CP] Copy Pods Resource script tells the build system to wait for it to be created before running the script. See Xcode 10 Build System Release notes:

In the new build system, shell scripts can't rely on the state of build artifacts not listed in other build phases (for example, the Info.plist file or .dSYM files.) Add files the script build phase depends on as explicit input dependencies to the shell script build phase. (40852184)

As for the warning about duplicated output, if we remove _Assets.car_ from output files of the script, it is not executed at all. Seems that build system do not see that script processes it + there are no changes in input files. Thus it is skipped. The warning itself does not cause any change in the build process as I can see. I guess we can ignore this warning since it is a known issue with provided workaround . Thus I hope it will be fixed by Apple at some point.

I also inspected build system CompileAssetsCatalog phase and found more arguments to actool that it uses. For example resource thinning in debug configuration and enabling on demand resources. These parameters are passed via env variables to resources script so they can be added to actool call in it.

@dnkoutso I want to create PR that will incorporate the fix and changes above. I found that I can modify the script in _copy_resources_script.rb_, but I do not see where I can alter script`s input and output files. Maybe you can help me?

Meanwhile the workaround for new build system will be to copy ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to the input files of [CP] Copy Pods Resourceafter pod install or pod update.

@dnkoutso I try to put the action that @OneSman7 describes in post_install hook, but fails.
Would you please help me figure out why this modification will be reverted.

post_install do |installer|
    app_project = installer.aggregate_targets.first.user_project
    main_target = app_project.targets.first
    build_phases = main_target.build_phases.grep(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
    phase = build_phases[1]  # This is [CP] Copy Pod Resources phase, just for testing.
    phase.input_paths.clear
    phase.shell_script = ""
    app_project.save
end

@ooopscc as I see your script removes any code from Copy Pod Resources and input paths.
This just breaks the phase.
The cause of the "assets bug" is the parallelization of the new build system. It tries to run as much tasks as possible at once on multiple cores. Thus in incremental builds Copy Pod Resources phase is executed a bit earlier that regular Compile assets phase. So Xcode just overwrites Assets.car.
We need to make sure Copy Pod Resources phase is executed later. As stated in new docs, if script phases depend on certain file it should be stated in input paths. So I proposed to make Copy Pod Resources phase dependant on Assets.car existing in build folder -> add it to input path of this phase.
No other change is needed. To remove the warning we can remove Assets.car from output path, but it hides form the build system that Assets.car is processed by this script, so it decides not to execute it (all other input files do not change from build to build). This warning is a known issue, so I hope that Apple will fix it in the future.

@OneSman7 Thanks for the details. The hook I wrote is just a test to see if the modification will work. The full script should add the Assets.car to the input paths.
Use the above script, I can get the correct input paths (same as the final one), and the clear and save seems work, but after a while, it is modified and my changes is reverted.

I see. I do not know what is reverting your changes, but I think that modifying anything except for Pods project in post install hook can have unexpected consequences since it was not intended.
I suggest adding input path manually after each pod install or update. It is not happening so often and the change is not reverted :)

It seems I overestimated my Ruby skills, my current workload and the complexity of CocoaPods project.
I cannot tell if will be able to create PR any time soon, so I will write about my findings here. Maybe someone else can use them to fix the issue.

The origin of the issue is described in full detail above. To reenable pods assets in incremental builds we need to add ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car path to the input paths of the Copy Pod Resource script build phase (maybe just copy from output paths). We can ignore the warning of duplicated output since it is a known issue by Apple and do not affect anything.

In CocoaPods/lib/cocoapods/installer/user_project_integrator/target_integrator.rb in resource_output_paths method there is a line basename = extname == '.xcassets' ? 'Assets' : File.basename(resource_input_path). Here we are able to determine that we will output Assets.car. I was thinking about 2 possible additions:

  1. Making 'Assets' a constant. Search for it in output paths in add_copy_resources_script_phase method. If a path with this constant is found, add it to the input path also.
  2. Avoid searching, make resource_output_paths method return Assets.car path if it was added. If it was returned add it to the input paths.

I also studied CompileAssetCatalog command in Xcode 10:

/Applications/Xcode.app/Contents/Developer/usr/bin/actool --output-format human-readable-text --notices --warnings --export-dependency-info .../assetcatalog_dependencies --output-partial-info-plist .../assetcatalog_generated_info.plist --app-icon AppIcon --compress-pngs --enable-on-demand-resources YES --filter-for-device-model iPhone10,6 --filter-for-device-os-version 11.4 --target-device iphone --minimum-deployment-target 9.3 --platform iphonesimulator --product-type com.apple.product-type.application --compile .../Assets.xcassets

I was thinking about adding additional options to actool call in CocoaPods/lib/cocoapods/generator/copy_resources_script.rb:

  1. --enable-on-demand-resources YES. The value can be obtained from ENABLE_ON_DEMAND_RESOURCES=YES env var.
  2. --filter-for-device-model iPhone10,6 --filter-for-device-os-version 11.4. If these options should be added can be obtained from BUILD_ACTIVE_RESOURCES_ONLY=YES env var. The values for options themselves are in TARGET_DEVICE_MODEL=iPhone10,6 and TARGET_DEVICE_OS_VERSION=11.4 env vars.
  3. --product-type com.apple.product-type.application. The value can be obtained from PRODUCT_TYPE=com.apple.product-type.application env var.
  4. The value of COMPRESS_PNG_FILES=YES env var can be used to determine whether to add --compress-pngs option.

These additions can bring support for on demand resources and improve debugging (they enable app resources thinning in debug builds, which decreases resources compile time and helps testing app thinning).

Thank you @OneSman7 for the very thorough investigation and explanation!

For others trying to find a workaround, one option is to add the following to your project's Podfile:

# Work around for issue described here: https://github.com/CocoaPods/CocoaPods/issues/8122#issuecomment-427680543
post_install do |installer|
  project_path = '<Your_Project_File_Here>.xcodeproj'
  project = Xcodeproj::Project.open(project_path)
  project.targets.each do |target|
    build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

    if build_phase.present?
      build_phase.input_paths.push('${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car')
    end
  end

  project.save(project_path)
end

This would make sure that every time pod install or pod update is run, the copy pod resources phase is updated with the workaround suggested by others in this issue.

Unfortunately, @matt-loflin's script didn't quite work for me, though I appreciate seeing that script spelled out. Using the script produced the following compiler error on my project:

invalid task ('PhaseScriptExecution [CP]\ Copy\ Pods\ Resources ... with mutable output but no other virtual output node (in target 'Secret')

I'm surprised more people aren't hitting this issue. For me, that warning about duplicated output file on Assets.car isn't benign. My assets (colors in xcassets) don't actually load at runtime.

I was able to reproduce this issue with the finished tutorial project on raywenderlich.com (https://www.raywenderlich.com/5823-how-to-create-a-cocoapod-in-swift). With that project, you see the same warning. And at runtime, you see Could not load the "background" image referenced from a nib in the bundle with identifier.

Seems like using xcassets as resources in a CocoaPod framework is broken under Xcode 10.1 when using the new build system.

I've also been having trouble with @matt-loflin's script.
When I run pod install the script works fine; the input path is added to the "[CP] Copy Pods Resources" build phase and all the images work as expected.

However, when I run pod install again, the input path is removed from the build phase. This is obviously a problem and it's an even bigger one when it occurs in a CI workflow.

According to this StackOverflow answer, the script would have to be run after the "Integrating client project" step, but there are no installer hooks that run after the project integrator:
https://stackoverflow.com/questions/33846361/hook-in-podfile-to-edit-my-project-file/38208513#38208513

*.xcassets of Copy Bundle Resources --> Assets.car
*.xcassets of [CP] Copy Pods Resource --> other Assets.car
The first one covers second in the New Build System,That's the reason.

@shixiaoda

I don't think so,If this is true,Why first time run it was work?

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

Use legacy is not work on xcode10.2. Have some idea?

+1. Still broken for the new build system in Xcode 10.2.
Also for both cocoapods version 1.5.3 and 1.7.0.beta.3.
Waiting for solutions.

+1. Still broken for the new build system in Xcode 10.2.

+1 still seeing this in 10.2

+1 Still same issue

+1 still seeing this in 10.2

I move [CP] Copy Pods Resources after Copy Bundle Resources

and Use:

install! 'cocoapods', :disable_input_output_paths => true

in podfile.

It seem works in new build system

+1

Adding ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to my [CP] Copy Pods Resources phase's "input list" seems to solve the issue (I can compile now) though I have no idea if this is safe. It also obviously gets blown away on ever pod install.

In Xcode 11 beta this warning is now error. Adding ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to input files still works. But I wish there were more clean solution.

I have an Assets.car issue but I don't know if it's the same as this issue or separate?

1) Xcode target builds fine
2) Xcode unit tests run fine.
3) lib lint is giving a warnings about duplicate output file around Assets.car:
Target Framework has an .xcassets file
Unit Tests target has a TestAssets.xcassets file

warning: ignoring duplicated output file: '/Users/david.ferrero/Library/Developer/Xcode/DerivedData/.../MyLibUI-Unit-Tests.xctest/Assets.car' in shell script build phase '[CP] Copy Pods Resources'. This warning represents an extremely serious project misconfiguration and will likely cause some shell scripts in your project to be skipped entirely, leading to other build failures or missing files in the build directory. This will be a hard error in the future. (in target 'MyLibUI-Unit-Tests')

For those who google Xcode 11 beta error message, here it is.

Warning first:

warning: duplicate output file '/Users/valentine/Library/Developer/Xcode/DerivedData/MyProj-aqxzijyfpejuxqbbjaivvdfgeawg/Build/Products/Development-Debug-iphonesimulator/MyProj.app/Assets.car' on task: PhaseScriptExecution [CP] Copy Pods Resources /Users/valentine/Library/Developer/Xcode/DerivedData/MyProj-aqxzijyfpejuxqbbjaivvdfgeawg/Build/Intermediates.noindex/MyProj.build/Development-Debug-iphonesimulator/MyProj.build/Script-1EF392577225761A8D70A2CD.sh (in target 'MyProj')

Followed by error:

error: Multiple commands produce '/Users/valentine/Library/Developer/Xcode/DerivedData/MyProj-aqxzijyfpejuxqbbjaivvdfgeawg/Build/Products/Development-Debug-iphonesimulator/MyProj.app/Assets.car':
1) Target 'MyProj' (project 'MyProj') has compile command with input '/Users/valentine/Projects/MyProj/Resources/panel-ipad.xcassets'
2) That command depends on command in Target 'MyProj' (project 'MyProj'): script phase “[CP] Copy Pods Resources”

If you are using Xcode 11 and distributing assets through pods using e.g.:
s.resources = ["your resource.xcassets"] (in podspec)
then as a workaround you can set:
install! 'cocoapods', :disable_input_output_paths => true (in Podfile)
as was already mentioned above.

This will download your resources from pods, but will not copy those assets to apps bundle during build.
To get resources to the app bundle as a workaround you will need to manually reference them in your project structure from Pods folder.

Any solution for this issue? It is breaking most of the projects out there.

I have modified @matt-loflin 's script in order to always include ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car as input file (even after the first pod install run).

    project_path = '[YOUR_PROJ_NAME].xcodeproj'
    project = Xcodeproj::Project.open(project_path)
    project.targets.each do |target|
      build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

      assets_path = '${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car'
      if build_phase.present? && build_phase.input_paths.include?(assets_path) == false
        build_phase.input_paths.push(assets_path)
      end
    end

The problem with the previous version of the script was the fact that we were always appending the Assets.car file to the input files list and a later phase of pod install cleans these duplicated entries (no explanation for it however).

I have modified @matt-loflin 's script in order to always include ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car as input file (even after the first pod install run).

    project_path = '[YOUR_PROJ_NAME].xcodeproj'
    project = Xcodeproj::Project.open(project_path)
    project.targets.each do |target|
      build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

      assets_path = '${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car'
      if build_phase.present? && build_phase.input_paths.include?(assets_path) == false
        build_phase.input_paths.push(assets_path)
      end
    end

The problem with the previous version of the script was the fact that we were always appending the Assets.car file to the input files list and a later phase of pod install cleans these duplicated entries (no explanation for it however).

I will try this workaround and let you know!

I have modified @matt-loflin 's script in order to always include ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car as input file (even after the first pod install run).

    project_path = '[YOUR_PROJ_NAME].xcodeproj'
    project = Xcodeproj::Project.open(project_path)
    project.targets.each do |target|
      build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

      assets_path = '${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car'
      if build_phase.present? && build_phase.input_paths.include?(assets_path) == false
        build_phase.input_paths.push(assets_path)
      end
    end

The problem with the previous version of the script was the fact that we were always appending the Assets.car file to the input files list and a later phase of pod install cleans these duplicated entries (no explanation for it however).

It doesn't work either.

Same issue. And I can provide a demo to 100% trigger this build failure. Only New Build System has this issue. Legacy does not.

pod version: 1.7.4
Xcode version: Xcode 11 Beta3
macOS version: macOS 10.14.4

Demo: https://github.com/dreampiggy/CocoaPodsXCAssetsIssue

experiencing the same issue. does anyone know of any workarounds for configuring the static framework / podspec so devs don't see this?

Its almost one year still this issue not get fixed. Sad.

Upvote. Since this is an error now it is critical.
@dnkoutso are there any plans to work on resolving this?

With this now coming up on Xcode 11 whenever you use a pod that has assets, it's become a significant issue. This is effectively a blocker for anyone using one of those pods.

The manual fix above has been confirmed to work, with the automated fixes being less successful. Getting that built into cocoapods would likely work correctly for everyone.

How can we make that happen?

This looks like a blocking issue with new build system on Xcode 11 since it's already beta 5. Do we have any plan to fix it?

I have modified @matt-loflin 's script in order to always include ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car as input file (even after the first pod install run).

    project_path = '[YOUR_PROJ_NAME].xcodeproj'
    project = Xcodeproj::Project.open(project_path)
    project.targets.each do |target|
      build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

      assets_path = '${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car'
      if build_phase.present? && build_phase.input_paths.include?(assets_path) == false
        build_phase.input_paths.push(assets_path)
      end
    end

The problem with the previous version of the script was the fact that we were always appending the Assets.car file to the input files list and a later phase of pod install cleans these duplicated entries (no explanation for it however).

I will try this workaround and let you know!

Note. This only works on Xcode New Build System
One Legacy Build System This will cause build error for Xcode :)

Using post-installer does not solve the problem. Because CocoaPods's logic, it's to call your post-installer first, then override all the input files. So your changes will be reverted.

I write a CocoaPods plugin to solve this problem. But need a official workaround.

Good Apple.

Hi. Xcode 11 issue is critical for our project too.
@dalemyers, could you please help with manual fix that works for Xcode 11? If I add Assets.car to '[CP] Copy Pods Resources' it just doesn't compile. How can I fix it manually to compile project and have assets?

I have no idea what issue you are seeing unfortunately. Sorry I can't be of more help.

I have no idea what issue you are seeing unfortunately. Sorry I can't be of more help.

Run this demo using Xcode 11 and New Build System (Legacy have no issue) : https://github.com/dreampiggy/CocoaPodsXCAssetsIssue

This issue only appear, when you have at least one Pod, using the spec.resource = 'ABC.xcassets' syntax, not the resource bundles.

@dalemyers I mean issue with pods that have assets. We have to use XCode 11 and new build system, because XCode 11 fixes another critical issue from XCode 10. And this fix works only with new build system (https://forums.swift.org/t/swift-compilation-reaching-arg-max-limit-causing-xcode-build-failure/6494)

Any news at this one? Same issue at my end.

as with Xcode 11 (starting already with its first Beta) the warning with duplicate output files is now error. Therefore for Workaround I've ended up using this post_install script:

# Work around for issue described here: https://github.com/CocoaPods/CocoaPods/issues/8122#issuecomment-427680543
# need to reference resources manually from Pods folder (one time task - will not breal with "pods update" command)
post_install do |installer|
  project_path = '[YOUR_PROJ_NAME].xcodeproj'
  project = Xcodeproj::Project.open(project_path)
  project.targets.each do |target|
    build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }

    if build_phase.present?
      target.build_phases.delete(build_phase)
    end
  end

  project.save(project_path)
end

the difference between this and previous workarounds is that now I'm removing whole [CP] Copy Pods Resources phase instead of trying to fix it (as previous workarounds are not working any more in Xcode 11).
Only thing you need to do next to this script is adding your resources references to the project manually, which is single time task and will not brake with "pods update" command.
This workaround has no side-effect on frameworks, so only resources needs to be manually referenced till proper solution is done in CocoaPods.

Xcode 11 has now gone GM and this continues to be an issue. Considering the number of people seeing this on a beta, the numbers when it is launched are going to skyrocket. This has the potential to be a significant issue for cocoapods. We need to figure out a solution to it.

From what I've gathered from above, the only real fix we've identified is to patch CocoaPods itself to add the assets file to the phase.

Are there any other alternatives that we've found?

@dalemyers I currently use a hard-code written CocoaPods plugin to solve this problem. If this can help, you can have a try:

I don't know the official way to solve this problem, the plugin logic is just the simple temporary workaround from this issue comments. When using Xcode 11 GM New Build System, since CocoaPods touch the Assets.car, it SHOULD be here in the Input File List.

However, the Legacy Build System does not have this limit and I have to check the build system in this patch. Why ? Maybe Apple knows.

Adding ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to my [CP] Copy Pods Resources phase's _"Input Files"_ list mo more working with Cocoapods 1.8.0, still working with 1.7.5.

Meanwhile investigation you can you can use a work arounds : using the Xcode Legacy Build System and not the Xcode 10 new build system.

Xcode / File / Workspace Settings / Build system / select "Legacy Build System"

capture d ecran 2018-09-25 a 11 04 14

This fixed my issue

I solved this by creating a subspec for the entire project with resource bundles in it, like:

s.subspec 'Sources' do |source|
    source.source_files = 'MyProject/**/*.{pch,h,m,swift}'
    source.resources = 'MyProject/**/*.{png,json,plist,xib,otf,ttf,strings,html,der,storyboard}'
    source.resource_bundles = { 'Resources' => ['MyProject/**/*.xcassets']}
    source.exclude_files = 'MyProject/Info.plist' # this is because Info.plist is going to overwrite the main one
end

it is probably going to work also with:

Pod::Spec.new do |source|
...
  source.resources = 'MyProject/**/*.{png,json,plist,xib,otf,ttf,strings,html,der,storyboard}'
  source.resource_bundles = { 'Resources' => ['MyProject/**/*.xcassets']}
...
end

(not tested)

Tried it all on Xcode 11, but the very first workaround helped:

install! 'cocoapods', :disable_input_output_paths => true

After this the script is always executed (no possible skip optimisation), but it is only 10 additional sec in our case. And back is compiling as usual and running CI.

Thanks @dnkoutso! It is really better to try proposed fix and not inventing the wheel.

P.S.: I checked generated Assets.car on a clean build - all resources from pods were there. If your build are clean and generated by CI - you win)

Our build times are already 12 minutes for initial build and 90 seconds on subsequent builds... using this work around gives us build times close to 2x longer. I really think there should be a fix for this from the cocoa pods team? Our only option is to look at Carthage or SPM for everything.

@dreampiggy mentioned a plugin, we'll give that a try for now.

Still no solution for this problem?

Just adding my experience here:
If we build our project with zero changes, the install! 'cocoapods', :disable_input_output_paths => true workaround results in our project rebuilding the asset catalog (24secs)+ running the Copy Pod Resources script (27secs) every time.
incremental-build
We're using (with great success) the patch to cocoapods from @dreampiggy here: https://github.com/dreampiggy/cocoapods-xcode-patch which selectively inserts ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to the input file list files.

@dreampiggy have you attempted to make a PR to include this fix?

https://github.com/dreampiggy/cocoapods-xcode-patch

That plugin is a patch, in logic. It's OK someone can port this to the official implementation.
But the logic there check Whether current workspace using Legacy Build System or New Build System, which is a little ugly. I don't know any better solution now.

Can anyone who really familiar with CocoaPods or Ruby, help to port that and create a MR ?

If you are using Xcode 11 and distributing assets through pods using e.g.:
s.resources = ["your resource.xcassets"] (in podspec)
then as a workaround you can set:
install! 'cocoapods', :disable_input_output_paths => true (in Podfile)
as was already mentioned above.

This will download your resources from pods, but will not copy those assets to apps bundle during build.
To get resources to the app bundle as a workaround you will need to manually reference them in your project structure from Pods folder.

@BalkiX This answer works for me, but is there a downside of putting this in my Podfile?

If you are using Xcode 11 and distributing assets through pods using e.g.:
s.resources = ["your resource.xcassets"] (in podspec)
then as a workaround you can set:
install! 'cocoapods', :disable_input_output_paths => true (in Podfile)
as was already mentioned above.
This will download your resources from pods, but will not copy those assets to apps bundle during build.
To get resources to the app bundle as a workaround you will need to manually reference them in your project structure from Pods folder.

@BalkiX This answer works for me, but is there a downside of putting this in my Podfile?

Hi cgossain, if you are using pods only for distributing assets this workaround will be fine for you, but I had issue with other frameworks distributed through pods. I ended up using other workaround mentioned above https://github.com/CocoaPods/CocoaPods/issues/8122#issuecomment-531202439 which is not braking my other framework references. With this workaround I just have to call also pod install after pod update as the script is not ideal and I hope proper fix is coming soon.

what is the downside of putting this in my Podfile?

This workaround stops cocoapods from defining the dependencies (inputs and outputs) for the build phase step. When a build phase step has no input dependencies, Xcode must run that step every single build, even if you have changed nothing and just hit build again. For us that adds a massive wasted overhead for our incremental builds, as our asset catalogs take > 30secs to build. For smaller projects, simple asset catalogs, rebuilding them every time may be an acceptable cost to incur.

Just adding my experience here:
If we build our project with zero changes, the install! 'cocoapods', :disable_input_output_paths => true workaround results in our project rebuilding the asset catalog (24secs)+ running the Copy Pod Resources script (27secs) every time.
incremental-build
We're using (with great success) the patch to cocoapods from @dreampiggy here: https://github.com/dreampiggy/cocoapods-xcode-patch which selectively inserts ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Assets.car to the input file list files.

@dreampiggy have you attempted to make a PR to include this fix?

Even using the patch, the build still errors. Assets.car is still being added to both the input and output files. How is this supposed to work? Is this patch _only_ for 1.7.5? I tried using 1.8.4.

Hello all,

I've found a workaround to this problem that is working well for me, and allows me to keep using *.xcassets files.

Broken Setup:

_MyPod.podspec_:

s.resources = 'MyPod/Assets/Images/**/*'

_UIImage+Bundle.swift_ helper extension:

import UIKit

extension UIImage {
    /// Creates an image object using the named image asset from the current library bundle.
    static func makeLibraryImage(named: String) -> UIImage? {
        return UIImage(named: named, in: Bundle(for: SomeClassInMyLibrary.self), compatibleWith: nil)
    }
}

Working Setup:

_MyPod.podspec_:

s.resource_bundles = { 'MyPod-Images' => ['MyPod/Assets/Images/*.xcassets'] }

_UIImage+Bundle.swift_ helper extension:

import UIKit

extension UIImage {
    /// Creates an image object using the named image asset from the current library bundle.
    static func makeLibraryImage(named: String) -> UIImage? {
        guard let bundlePath = Bundle(for: SomeClassInMyLibrary.self).path(forResource: "MyPod-Images", ofType: "bundle") else {
            return nil
        }
        let bundle = Bundle(path: bundlePath)
        return UIImage(named: named, in: bundle, compatibleWith: nil)
    }
}

Summary

In summary, in my working solution I've reconfigured my .podspec to wrap my .xcassets file into a resource bundle, and I've updated my helper extension accordingly. This is currently working reliably for me and I don't need to add additional plugins or code into my Podfile.

Update - Nov 21, 2019

It seems like I still need to run pod install after a pod update for this solution to work.

Apparently the pod update command removes the paths to the ressource bundles from the [CP] Copy Pods Resources build phase script, but then pod install adds them back in.

Very sorry if this issue is not quite relating to this ticket but at the moment its the closest I can find.

My Issue:

Any changes I make to my Assets.xcassets folder (_i.e. add a new AR Reference Image for image tracking_) are not being picked up when I go to rerun the app.

I assumed they weren't being picked up by the Assets.xcassets folder so I decided to remove Assets.cassets folder from my build phase bundle resource, and then re add it.

The exception being thrown:
After re adding the folder and running my app again the application freezes outputting the following error:

2019-11-28 15:59:35.265955+0100 Image TrackAR[15721:1026007] [framework] CoreUI: RunTimeThemeRefForBundleIdentifierAndName() couldn't find Assets.car in bundle with identifier: 'com.{mybundleid}' 2019-11-28 15:59:35.266144+0100 Image TrackAR[15721:1026007] [framework] CoreUI: RunTimeThemeRefForBundleIdentifierAndName() couldn't find Assets.car in bundle with identifier: 'com.{mybundleid}' 2019-11-28 15:59:35.266613+0100 Image TrackAR[15721:1026007] [General] Error while opening catalog named "Assets" in bundle "(null)": Error Domain=NSCocoaErrorDomain Code=260 "RunTimeThemeRefForBundleIdentifierAndName() couldn't find Assets.car in bundle with identifier: com.sambowen" UserInfo={NSLocalizedDescription=RunTimeThemeRefForBundleIdentifierAndName() couldn't find Assets.car in bundle with identifier: com.{mybundleid}}

I really can't understand whats going wrong, any help would be really appreciated.

Currently working with the following:

  • Arkit 2.0
  • Xcode Version 11.2.1 (11B500)

Any update on this?

Having the same issuer with:

Pod version: 1.8.4
Xcode version: Xcode 11.3.1
macOS version: macOS 10.15.3

sorry, novice question: where should we add install! 'cocoapods', :disable_input_output_paths => true in the podfile?

@adamgins I put it just under platform :ios, '9.0'. But as commented buy many in this thread already it will probably slow down your incremental builds a lot. I'm using the legacy build system for now.

Adding this to podfile

install! 'cocoapods', :disable_input_output_paths => true

And changing the copy pods order worked for us

If you want to avoid the incremental compilation time hit, using resource_bundles rather than resources as mentioned above by @cgossain should help.

Yeap! The change you highlighted fixed a long standing issue also for development pods and dynamic frameworks https://github.com/CocoaPods/CocoaPods/issues/8073.

However, other issues regarding XCAssets are still remaining.

@dnkoutso @raven
Does this mean Xcode 12 fixes this whole issue (i.e. no more need for slow workarounds?)

So, legacy build system is being deprecated and we will not be able to use cocoapods with the new one. Is there any workaround without performance issues?

@zaptrem I can confirm we still have the same issue with Xcode 12 beta1 (12A6159)

If it helps anyone. So disable_input_output_paths slowed down our build times a lot. So I had to find another workaround, the pod which is causing assets.car error, install it as dynamic framework. Note: You also have to install pod's dependencies as dynamic framework.

use_frameworks! :linkage => :static

dynamic_frameworks = ['Pod1', 'dependentPod']
pre_install do |installer|
    installer.pod_targets.each do |pod|
        if dynamic_frameworks.include?(pod.name)
            puts "Overriding the build_as_dynamic_framework? method for #{pod.name}"
            def pod.build_as_dynamic_framework?;
                true
            end
            def pod.build_type;
                Pod::BuildType.dynamic_framework
            end
        end
    end
end

Hello all,

I've found a workaround to this problem that is working well for me, and allows me to keep using *.xcassets files.

Broken Setup:

_MyPod.podspec_:

s.resources = 'MyPod/Assets/Images/**/*'

_UIImage+Bundle.swift_ helper extension:

import UIKit

extension UIImage {
    /// Creates an image object using the named image asset from the current library bundle.
    static func makeLibraryImage(named: String) -> UIImage? {
        return UIImage(named: named, in: Bundle(for: SomeClassInMyLibrary.self), compatibleWith: nil)
    }
}

Working Setup:

_MyPod.podspec_:

s.resource_bundles = { 'MyPod-Images' => ['MyPod/Assets/Images/*.xcassets'] }

_UIImage+Bundle.swift_ helper extension:

import UIKit

extension UIImage {
    /// Creates an image object using the named image asset from the current library bundle.
    static func makeLibraryImage(named: String) -> UIImage? {
        guard let bundlePath = Bundle(for: SomeClassInMyLibrary.self).path(forResource: "MyPod-Images", ofType: "bundle") else {
            return nil
        }
        let bundle = Bundle(path: bundlePath)
        return UIImage(named: named, in: bundle, compatibleWith: nil)
    }
}

Summary

In summary, in my working solution I've reconfigured my .podspec to wrap my .xcassets file into a resource bundle, and I've updated my helper extension accordingly. This is currently working reliably for me and I don't need to add additional plugins or code into my Podfile.

Update - Nov 21, 2019

It seems like I still need to run pod install after a pod update for this solution to work.

Apparently the pod update command removes the paths to the ressource bundles from the [CP] Copy Pods Resources build phase script, but then pod install adds them back in.

this solution worked for me as well. only need to check that all the Pod dependencies that you're using are also implementing resource_bundles instead of resources. this is also a better solution to avoid naming collisions between your assets and assets from 3rd party dependencies.

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

Still not working properly

Was this page helpful?
0 / 5 - 0 ratings