Can't assign xcassets to the main target on Xcode 11 - ios

On Xcode 11 my .xcassets, that don't cause any issue on Xcode 10, cause the compilation to fail with the following message:
error: Multiple commands produce '/Users/user/Library/Developer/Xcode/DerivedData/project-enjiypsgxtcdbnaripixgtnjlagx/Build/Products/Debug-iphonesimulator/project.app/Assets.car':
1) Target 'project' (project 'project') has compile command with input '/Users/user/sandbox/project/Resources/buttons.xcassets'
2) That command depends on command in Target 'project' (project 'project'): script phase “[CP] Copy Pods Resources”
The only way I'm able to compile the project is by removing the .xcassets from the target with the obvious downside of having them not available on the build.
PS: This is happening for 2 ObjC projects.

Add below line at the top of your pod file, right after platform :ios
install! 'cocoapods', :disable_input_output_paths => true
Reference

The answer above is only partially correct: yes, this happens because the pod phase produces Assets.car as an output file, which coincides with the output name for your xcassets - hence Multiple commands produce... error: one command being the script phase [CP] Copy Pods Resources and another - your own project's compile command.
But removing Assets.car from output files will cause the build system to fail to see that the script processes the file, thus it skips it (read this for more details). So what we can do is add Assets.car to the input files - this will create a dependency for the script, telling the build system to wait for the file before executing the script.
NB: like the solution above, you will have to do this every time after updating your pods, since [CP] Copy Pods Resources is generated every time you run pod install or pod update

To be sure that all build steps are performed in the correct order, yet as many steps in parallel as possible, Xcode needs to know for every build step which input files it depends on and which output files it will generate.
E.g. if step A depends on an input file that is the output file of step B, step B surely has to run before step A. If neither step requires the output file of the other step, they can both run in parallel.
While several steps can surely depend on the same input file, it cannot be the case that multiple steps produce the same output file as in that case, whichever step runs last would overwrite the output file of whichever step runs first and this means the resulting output file content would be unpredictable and that is an error in a build process that shall created predictable results!
In your case the problem is that your Copy Resources build phase contains one (or more) .xcassets bundle(s). Xcode won't just copy these bundles, instead it will combine them, convert and optimize their content, and create a file called Assets.car that contains the content of all the assets catalogs in your project.
Yet if you integrate a Pod and this Pod also has an asset catalog, exactly the same thing will happen and a second Assets.car file is created and now Xcode has a problem: Two build steps both say they create an Assets.car file. Which one shall win? Which of these two files shall end up in the final application? And what about other steps that depend on this file? After which of the build steps do they have to run? This is a serious problem that Xcode cannot resolve.
There are currently two possibly solutions:
Use frameworks. When you use frameworks instead of static libraries, the resources of Pods don't end up in the resources folder of your main application but in the resources folder of the built framework. All you need to do is to add use_frameworks! to your Podfile, either top level or just for a specific target. The downside is that your overall app size will grow a bit and app start time will increase a bit.
Have the Pod-author fix the Pod. Instead of resources s/he shall use resources_bundle as the Podspec documentation also strongly recommends. Using resources actually has other disadvantages (resource files are not optimized, name conflicts can arise between different Pods), whereas using a resource bundle is safe, regardless if Pods are embedded as static libraries or as dynamic frameworks. Note, though, that it is not enough to just alter the Podspec, all code that loads bundle resources must be adopted to load them from the correct bundle (the name will be known as when using resources_bundle in a Podspec file, you also must give the bundle(s) a name).
There is an on-going bug report for this issue, you can find it here:
https://github.com/CocoaPods/CocoaPods/issues/8122
Yet the problem currently is, that every possible solution other than the two mentioned above would basically be an ugly hack and the Cocoapods developers are not happy implementing ugly hacks. The best solution, as hard as it seems, is probably to not fix that problem at all but to stop supporting resources in Podspec files and make resources_bundle mandatory for Pods that contain own resources.

In your library project, such as "LADetailPage", open Targets' "Build Phases", create a predefined phase named "Copy Files", then drag your *.xcassets to the new phase.
Then the library won't make Assets.car from *.xcassets files when building, instead, cocoapods copies the *.xcassets to your main project which imports the lib, and the main project builds all *.xcassets into a single Assets.car file.

Please check your dependencies if there is some pods use 'resources'(not 'resources_bundle') to link its own xcassets in podspec.
This way has beed deprecated, because its output file name is 'Assets.car'. It is same with your project xcassets' compile output name.

Xcode->File->Workspace settings->Building System-> Legacy Build System
example

Related

Xcode SwiftGen: build fails in project with multiple targets

How should I configure SwiftGen when using Cocoapods and multiple targets?
I have a project with two targets (MyProject and MyProject Dev) which has SwiftGen integrated with Cocoapods.
I can build the first target with no problems whatsoever. However the 'Dev' target always fails. The script phase is the last step in Build Phases, however running it earlier or later seems to make no difference.
On failure, I've observed the following:
The generated .swift file has an import statement, 'import MyProject' which shouldn't be there
'No type named [ClassName] in module [MyProject]' OR 'No such module [MyProject]'
SwiftGen version I'm using is 5.2.1
Xcode 9.2, targeting iOS 10.0
SwiftGen from version 5 onwards requires a configuration file, so I've set one up as follows:
output_paths: Sources/Generated
storyboards:
- paths: MyProject/Storyboards/Base.lproj
templateName: swift4
output: MyProject/Storyboards/Storyboards.swift
params:
ignoreTargetModule: true
So far I've looked up documentation and the following issue:
https://github.com/SwiftGen/SwiftGen/issues/273
However the difference is that I'm using a different type of SG installation and my project fails to build (rather than simply not generating any resources)
Cleaning project, build folder and deleting derived data had no effect. I'm assuming that I may have missed something in configuration setup, but I can't see what that would be.
First question on here, so apologies if I missed something, will be happy to edit.
I had the same issue with generating Storyboard file. Try to modify your config file:
params:
ignoreTargetModule: true
module: <YOUR_PROJECT_NAME>
Hope it will help.
Hesitant to call this a solution, it's more of a workaround, but the following approach has at least allowed the projects to be built and run.
Remove the SwiftGen script phase from the 'Dev' target
Build the project using the main scheme that includes SwiftGen to generate all the necessary objects and constructs
Switch to Dev scheme and run the project.
The Strings.swift file created by SwiftGen is linked to both targets, so even after running the script in one scheme the resources within that file will be available to both regular and Dev targets.
Hope this helps someone.

Invalid bundle structure - The app may contain only one executable file.

This question is similar if not identical but there is no solution. I've looked inside the archive and there's only one executable, so I am at a loss as to how to proceed. Any ideas greatly appreciates.
Invalid Build Structure
The binary file 'YourApp.app/libYourLibrary.a' is not permitted.
Your app may contain only one executable file.
This error occurs when a static library file is mistakenly copied into the app bundle.
You should link the libYourLibrary.a static library via a Link Binary with Libraries build phase.
It should NOT be added to the target's Copy Bundle Resources build phase.
My app was rejected with the same error message. It turned out that I was copying a third party framework (Fiksu) in the 'Copy Bundle Resources' build phase. The framework contained an executable and was already linked to in the 'Link Binary With Libraries' build phase. I deleted the framework from the 'Copy Bundle Resources' build phase. The framework continued to work normally in a release build. I resubmitted the app and it passed validation. Similar solution was posted here:
https://devforums.apple.com/message/1020254#1020254
In hindsight the error is straightforward. An executable file was accidentally added to the project. In my case "Develop!.app/Xcode" meant that Xcode was the executable. Checking the list of files in the project I found a symlink to Xcode. (Maybe I dragged it from the dock somehow and dropped it into the project).
If you are getting this error look at the files in your project -- there is an executable there somewhere.
I had this issue for the first time on an app I'd submitted over several versions with no issues.
I found that somehow that although I'd linked to one of my own libraries, one of the source files from that same library appeared in the list of files in the "Copy Bundle Resources" list. I have no idea how it got there but removing it meant that my app build, archived and was submitted successfully. :-)
If you are getting error in following format:
"Invalid Bundle Structure - The binary file 'Abc.app/AnyFileName.o' is not permitted.
Build Phases > Copy Bundle Resources > check your file AnyFileName.swift will be added too here. (Remove it)
validate it with XCode. Error gone !!
In my case I tried to remove references but nothing worked for me. Then I uninstall particular pod, remove references as mentioned here and then install that particular pod again. It worked for me.
For those who required elaboration check below:
1)
In Podfile comment the particular pod by adding # in the beginning and save it:
On command line run: pod install // It will uninstall that framework
2) Removed references of that framework from:
Link Binary with Libraries // In Build Phase
Copy Bundle Resources // In Build Phase
Embed Frameworks
3) Now install Pod again, Remove # which you added before and save it.
On command line run: pod install // It will install that framework again
Just delete the exec file from your bundle and delete the "Executable file" key from your bundle resources.
After that archive and validate the the the build it will work.

Looking for an Xcode build script to copy files between targets

Does anyone have a script that can copy files from one target to another, during the build process?
I have a project with one target that builds an app and another target that builds a library. The library needs to contain a large subset of the files from the app and I want to avoid manually copying them over.
In the build phase of an XCode 4.x project you can add a build phase to either copy files or just run a script (that does your copying for you)
See this SO question adding-external-scripts-to-xcode4, for additional details

How to force XCode 4 to always update resources?

I am adding resources (lots of .pngs and other) to my iPhone project dragging the folder to it and choosing "Create Folder references for any added Folder", to retain the folder structure.
They are correctly added to the Copy Resources build phase.
Problem is, I am wasting A LOT of time because when I create/delete/update a new resource, it will often ignore changed files and stick with the older version.
Looks like it tries to only updates resources when they are changed, but it fails to see the changes.
In the simulator it was possible to manually update the files in the .app, but when working on the device it will complain that the code sign of some resources has changed!
The only reliable way I've found to force it to update everything is deleting the build products, the app and the device app some times, until it finally decides to forget about the old version, but doing this for each resource change is wasting me an insane amount of time (game content changes more than often).
So, in short: how do I force XCode to disable "versioning" and to just scrap all the resources and copy them all each time?
Thanks!
EDIT: I have found that deleting the .app folder built in "build" folder always forces XCode to add new files...
I still have no clue on where it keeps the old files when I delete that folder, but this is for the better as it only copies new resources as intended.
So a simple script like
rm -rf "$CODESIGNING_FOLDER_PATH"
Does the trick of deleting the folder at each build...
Unfortunately, XCode apparently runs the codesigning BEFORE anything in the Build Phases tab is executed, so it updates the old target, the script deletes the old target, and then it crashes complaining that no Code Signing Resources were found.
So... I have to stick with manually deleting the file, or is there a way to run a script before code signing?
I had this kind of issue as well, about files not getting updated when I built my project (A PhoneGap project, but that should not matter).
What I did, was add this to the Build Phase of my project:
find "${PROJECT_DIR}/www/." -exec touch -cm {} \;
That will make sure the files are being picked up as updated when XCode builds the project. Of course, you should modify the command to your needs - my needs were to update the www folder on build, as I am editing my files using Visual Studio, running in a VM.
Ok, I finally found a (somewhat ugly) workaround against this.
In you project, create two aggregate targets, say Clean Build and Cleaner.
In Cleaner, add a "Run Script" Phase with rm -rf "$CODESIGNING_FOLDER_PATH" that will purge the temporary app from the build folder.
In Clean Build, add first Cleaner, and then your normal app target to the Target Dependencies.
Select Clean Build from the run list, then Edit Scheme and set your app target as the executable. Hit run, and it should work :)
You might want to use the Clean option under the Product menu (or hold down shift and command and press K) after you update a resource and before you build the updated app. I have noticed that this has helped me out at times when I update a resource or a user-defined build setting.

Xcode linked project header files not found

Here is the situation I have:
ProjectA - Xcode static library project.
ProjectA contains logical code group ExternLib with file ExternLib.h. ExternLib.h itself is in the folder Classes/lib/ExternLib (relative to ProjectA folder). Within ProjectA, I use ExternLib.h simply as: #import "ExternLib.h". This works fine.
Next I have ProjectB. This includes ProjectA as a linked Xcode project. The target has been added correctly etc. However, when I include a file in ProjectB which in turn includes ExternLib.h, upon building ProjectB, I get an error saying that the file ExternLib.h cannot be found.
I have tried adding the path to ExternLib.h to the header search path (all types: relative, absolute, with recursion etc.) but to no avail. I have checked that static library target has the copy headers step and the file ExternLib.h is included in it.
Anybody able to shed some light on how to get around this?
Add a Run Script Build Phase to the target for ExternLib that executes
mkdir -p "${BUILT_PRODUCTS_DIR}ExternLibHeaders"
Add a Copy Files build phase that copies the ExternLib header files into ${BUILT_PRODUCTS_DIR}ExternLibHeaders, and add all of ExternLib's headers into that phase.
In the app target for ProjectB, add ${BUILT_PRODUCTS_DIR}/ExternLibHeaders/ to the Header Search Paths for all configurations.
In Xcode > Preferences > Build, set the Build Products Directory to some common location.
The fourth step is crucial; it ensures that BUILT_PRODUCTS_DIR is the same for both projects.
It's really hard to say what might have gone wrong.
I'd start from scratch with a tutorial on building and using static libraries, and see if any of the steps jog any ideas out of you.

Resources