Automate copying resources from dependency project - ios

I have a static library which
Creates .a file
Exports public headers
Creates a .bundle containing resources
I have a workspace containing my project which depends on this lib. Library is also part of the workspace. I am able to work out the build dependencies on .a file and public headers. For the bundle, I have to manually add/update the bundle to my applications copy bundle resources build phase.
I want to automate this such that the bundle created in the $(BUILT_PRODUCTS_DIR) gets copied in the application bundle.
Is there a way to do this, may be a run script?
Appreciate your help.

Figured it out.
I added a run script phase to my application. Script to copy the generated bundle to my application,
cp -R ${BUILT_PRODUCTS_DIR}/Mybundle.bundle ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Mybundle.bundle
Hope this helps!

Related

Creating Swift Package from XCFramework: should .bundle be part of xcframework?

I'm trying to create a swift package from xcframework, the question is if the framework need to load certain resources from a .bundle file, should the bundle be part of the framework, ie. xcframework? I had the following files in the single zip file:
MyPackage.xcframework
MyPackage.bundle
And uploaded it to a host server, in my Package.swift:
targets: [
.binaryTarget(name: "MyPackage", url: "HOST/MyPackage.xcframework.zip", checksum: "CHECKSUM")
]
I can add the Swift Package to my project and use it, but at runtime it cannot find the .bundle file.
I found someone having the same problem:
https://devforum.zoom.us/t/bundling-the-zoom-sdk-within-a-swift-package/48400
Even having the .bundle file as dependency in the Package.swift, it doesn't work, unless the bundle file is manually copied into the project.
So my question is, should this bundle be part of the .xcframework file instead of being a standalone .bundle file along with the .xcframework file? Or if there's something else I can do?
Thanks!
You can use the new approach introduced in Swift 5.3 for bundling resources with your swift package as described here.
Currently, there are two rules that are supported: process rule and copy rule, process rule applies specific processing rules to your resource files depending on whether it is xib, storyboard etc.
In your case, you need to use copy rule to copy the .bundle resource in your app. By default copy rule will copy your file to the root directory of your app, you can decide to provide path to a folder instead if you want to copy your file with specific folder structure.

Automate the process of including generated proto files into an Xcode project

Our iOS app currently is using Google protobuffer gRPC as our API layer to communicate between App and backend. And so we have these .proto files in our backend directory which will be converting to .grpc.swift and .pb.swift files by gRPC-Swift-Plugins and then consumed by the App.
This works okay, but the process of converting is very tedious, and we would like to automate the whole process.
Below is how we're doing it:
Delete previously copied directory, and copy all .proto files from backend (.proto files are maintained by backend devs) to App directory named "Protos" via a shell script
We already set up Build rules and include .proto files in Compile Sources. Following the steps from an answer here on SO
Screenshot of the current setup in Xcode Build Rules:
Whenever we build the project, .pb.swift and .grpc.swift are generated and putting into a directory named "generated" under the "Protos" folder.
Here are the problems:
If the backend added a new .proto files into the source directory, my script will only copy the files into the Protos directory but not included news files in the Compile Sources list.
Similar to the first problem, we need to manually set up Compile Sources in Xcode and that means if a new dev joins our team, he/she also needs to do the same setup again.
We sometimes need to refer to the .grpc.swift and .ph.swift files while coding. But If we add these files into Xcode and build the project again, Xcode will complain that these generated files are there like (Sorry, we're working on a private repo, so the project name and file names are replaced):
Multiple commands produce '${user_path}/${proto_name}.pb.o':
Target '${my_project_name}' (project '${my_project_name}') has compile command for Swift source files
Target '${my_project_name}' (project '${my_project_name}') has compile command for Swift source files
Any answers or comments and suggestions are greatly appreciated!
It's interesting I didn't have those problems with Swift if I use the $DERIVED_FILE_DIR
protoc "$INPUT_FILE_NAME" --swift_out="$DERIVED_FILE_DIR" --proto_path="Your/proto/path"
I don't use the plugin because I've got the plugin installed in my /usr/local/bin
But I have exactly those problems when we use the output for cpp files.

Is there a way to copy bundle resource to app folder when built finished?

Actually I have a xcode workspace, containing several projects, for example, projectA and projectB, projectA is the main project, and projectB will generate a bundle file which projectA will use, is there a way to copy the bundle file to the main app folder? I know one way to do this is to drag the generated bundle file here like the below image shows, but as we have several team members and use git to manage the project, this method will use my personal folder path, and when others want to build the project, they will have to drag the bundle again. Is there a way to copy the generated bundle using relative path? Or can I use a script to do this? So everyone can just checkout the code directly without dragging the bundle manually? Thanks.
In Target -> Build Phases can you just Run Script after that target is done to copy it to the other place?

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.

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