Xcode framework Versions/Current/Headers/ error - ios

I am confused about adding a third party framework into Xcode project.
Here are the steps:
1) I copy the framework into project subfolder called "Frameworks". So framework is added to repository.
Everything works fine, app compiles, here is the screenshot:
2) I push the changes into repository (I use mercurial)
3) If I pull the changes on other machines or just switch between branches then project doesn't recognize this framework any more.
Here is the screenshot:
The question is why it happens and how to solve this problem? I there any specific way to add a framework in this case?
Thanks in advance!

I had this problem today and it was because the 3rd party framework was delivered as a .zip file and symbolic links inside of the framework were lost at some point.
Here is Apple's documentation on the anatomy of a framework:
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
The document explains that multiple framework versions might exist inside of the framework bundle, so the bundle contains some symlinks pointing to the current version of some directories.
MyFramework.framework/
MyFramework -> Versions/Current/MyFramework
Resources -> Versions/Current/Resources
Versions/
A/
MyFramework
Resources/
English.lproj/
InfoPlist.strings
Info.plist
B/
MyFramework
Resources/
English.lproj/
InfoPlist.strings
Info.plist
Current -> B
The problem you have is exactly like mine. Confirm that the three symlinks that Apple documented (MyFramework, Resources, Versions/Current) are not symlinks, but are tiny files. Then delete the tiny files and replace them with symlinks to the current framework version. For example, if the current version is 'A':
cd NewRelicAgent.framework
rm Headers
rm NewRelicAgent
rm Versions/Current
ln -s Versions/Current Versions/A
ln -s Headers Versions/A/Headers
ln -s NewRelicAgent Versions/A/NewRelicAgent
If there are multiple versions in your framework, then the text in Versions/Current might contain the current version. This would be an artifact where the compression tool is storing the symlink as text instead of an actual link.

We are facing a similar kind of issue. The result we get is the same, but the setup is different.
Posting our findings here, incase someone else finds it useful.
Our apps high level setup
React Native app
Git repo
npm for package management (npm install)
lots of .xcodeproj under one .workspace
one of those .xcodeproj have a .framework that shows the issue mentioned above
Our findings (so far)
it's not the actually git checkout thats causing this stripping out of symlinks in .framework behaviour
it's actually how our package manager (npm) installs the said sub repo. It might be npm is doing something to strip out symlinks in install or post install phase.
If we download or git checkout the said sub repo manually, framework symlinks are in tact.
Our initial approach to fix the issue
Include a symlinks intact version of the framework (Valid.framework) in the main project.
use npm install to install the packages as normal (this would strip out the symlinks in the framework Broken.framework file thats in the sub repo)
have a post install script copy and/or override Broken.framework with Valid.framework
cp -Rf <path_to_working_framework>/Valid.framework/* node_modules/<path_to_broken_framework>/Broken.framework/

Related

How to install node_modules only one time for one React JS project?

As I am implementing release automation of React JS project using Jenkins, it is required to download node_modules for a project only once and update successively. It doesn't mean one node_ modules for all projects. But one-time install for one project.
For example, Let's consider a project LoginReactApp.
I have to maintain a workspace like D:/jenkins/workspace/LoginReactApp.
So, I have to check out the source under D:/jenkins/workspace/LoginReactApp/LoginReactApp
and based on the package.json file, I need to download it under D:/jenkins/workspace/LoginReactApp/.
After the release process, the LoginReactApp project source will be deleted under D:/jenkins/workspace/LoginReactApp/ and the node_modules folder will not be deleted.
So, next time it is enough to check out only LoginReactApp project source D:/jenkins/workspace/LoginReactApp/ and it refers to already installed node_modules.
I have tried in command prompt below.
D:/jenkins/workspace/LoginReactApp/LoginReactApp>npm install
--production --f --prefix D:/jenkins/workspace/LoginReactApp/
Is it right? For next time it behaves differently.
How to install node_modules only one time for one React JS project?

Cyclic dependency error J2OBJC archive build?

I am having cyclic dependency issues with my Ionic/iOS project using J2OBJC as a internal Xcode settings built in.
I've set my build rules and settings in my ionic project as stated in the J2OBJC documentations. I have added the Library, User Header and framework search paths as required (firstly only app target, and also tried it with both app target and workspace) and created user defined $J2OBJC_HOME and (this probably isn't part of the requirements) I added a $PROJECT_DIR too. I also added the java build rule as such
"if [ ! -f "${J2OBJC_HOME}/j2objc" ]; then echo "J2OBJC_HOME not
correctly defined in Settings.xcconfig, currently set to
'${J2OBJC_HOME}'"; exit 1; fi; "${J2OBJC_HOME}/j2objc" -d
${DERIVED_FILE_DIR} -sourcepath "${PROJECT_DIR}/App"
--no-package-directories -use-arc --prefix Flowers=JOE -g ${INPUT_FILE_PATH};"
I have build both simulator and iPhone and ran them on both and they seem to be working. However, when I go to archive (so I can create the .ipa) for the project. I get a cyclic dependency error. I have tried numerous things, such as, fresh start of project, using different URLs for the search paths, using recursive and non-recursive, checked the documentations a few times, looked at forums and still have no solution. Any ideas would be greatly appreciated!
Xcode can no longer handle the same header search path in Header Search Paths and User Header Search Paths. You probably have "$(J2OBJC_HOME)/include" in both of these. So remove it from Header Search Paths and leave it in User Header Search Paths.
I've had this cyclic dependency issue for a good month and a half. I've tried almost everything.
I've looked everywhere.. and got 2 replies from Tom Ball. When it comes to a big project converted from java to Objc using the tool, xcode won't recognize the sub-directories made. I figured out the best fix is to create your own script using bash. I did some research and figured out how to recursively find all java files and apply the j2objc script to them and it will output all of your Objc files in the same directory layout. (Keeping a nice layout for you instead of the messy-everything-in-one folder like j2objc script rule on Xcode works).
My build.sh file is as follows, feel free to copy it-
!/bin/bash
Clean out Objective C folder
rm -rf /ObjC_Output
Move into Java Folder
cd Java
Run j2objc and output everything into ObjC
j2objc -d ../ObjC_Output $(find . -name "*.java")
Jump out of Java folder
cd ..
Delete previous org
rm -rf /Users/me/Projects/project-name/mobile-app-front-end/app/ios/app/app/org
cd to ObjC_Output
Copy new ObjC Project files over to the XCode project..
cp -R ./ObjC_Output/* /Users/me/Projects/project-name/mobile-app-front-end/app/ios/app/app/org
I automatically copy all my files back to my Xcode project.. feel free to do it anyway you want. Also don't forget to add j2objc to your path. and run your script as such ./builder.sh in terminal..
Also for Xcode to recognize your objC project folder you must add the top directory of your Xcode project and make it recursive.
In this case, you don't need to include the j2objc script in Xcode.. Just make sure you include all the default Linker paths, Library search paths and User Header search path as usual (shown in the j2objc documentation).
I've had to pull my hair out for this solution.. So feel free to ask for help if needed.

What's the equivalent of "development pods" under Carthage?

The teams developing frameworks for our iOS app are migrating from Cocoapods to Carthage.
Under Cocoapods, I could set up dependencies as "development pods". For example, instead of having the main app download a specific version of an xyzzy dependency, I could set up xyzzy as a development pod and point it to my local directory where I had checked out xyzzy from its Git repo. While I was working in the main app's project, any edits I'd do to xyzzy's files would be made in that directory. This let me build and test changes immediately, and when I was ready to check them in, Git would find them in the xyzzy project's directory.
Under Carthage I haven't found a way to do this. I see http://allocinit.io/ios/debugging-carthage-dependencies/ which explains how to create symbolic links so that I can see the dependency source files to make debugging easier, but any edits I make to them are under the main application's Carthage/Builds directory.
How do I set up the equivalent of development pods under Carthage?
I believe Carthage doesn't have something similar to "development pods" yet.
But you could simulate "development pods" just following these steps:
Steps:
Add the .xcodeproj to your workspace
Remove all the dependencies you have in your project of the framework you added in step 1. (probably you may need to remove it from Build Phases -> Run Script -> Input Files too )
Go to General tab of the target you want to run, add the framework under Linked Frameworks and Libraries (it is going to take the one added from the .xcoproj)
(optional) you may need to run carthage bootstrap in the framework's repo you want to add locally.
That's it.
After that you will be able to run your project and update framework's code in the same workspace.
This works just as well as development pods for me, as of Xcode 8.3.3 and Carthage 0.24.0:
In app path, rm -rf Carthage
Point at the appropriate branch or tag in Cartfile
carthage update --use-submodules (generates .gitmodules and clones repo into Carthage/Checkouts)
In Xcode under project -> Build Phases -> Run Script, comment out the line that ends with carthage update --cache-builds if present.
Change to the General tab and remove the lib from Embedded Binaries
Right-click project, Add Files to app..., add lib from Carthage/Checkouts
Under project -> General, re-add the library, choosing the one you added in the previous step.
App should now build with the local lib. Make sure that your .gitignore has Carthage/{Build,Checkouts} and .gitmodules.
This answer is a summary of a successful implementation of the solution introduced here.
A cleaner solution is using local paths for dependencies in Cartfile.
Environment
Xcode 10.1
macOS 10.13.6
Step 1. Symbolic linking
1.1 Change $(SRCROOT_MAIN)/Carthage/Checkouts/$(DEVELOPING_FRAMEWORK_NAME) directory to a symbolic link pointing to source root directory of your developing framework $(SRCROOT_DEVELOPING_FRAMEWORK), where $(SRCROOT_MAIN) is source root directory of your main app. Backup existing directories before this change.
This linking enables version-controlled changes in your developing framework.
Syntax when using ln utility,
$ ln -s "$SRCROOT_DEVELOPING_FRAMEWORK" "$SRCROOT_MAIN/Carthage/Checkouts/$DEVELOPING_FRAMEWORK_NAME"
1.2 Change $(SRCROOT_DEVELOPING_FRAMEWORK)/Carthage/Build directory in your framework to a symbolic link pointing to $(SRCROOT_MAIN)/Carthage/Build directory. Backup existing directories before this change.
This linking enables access to all frameworks built by Carthage from both your developing framework and your main app.
Syntax when using ln utility,
$ ln -s "$SRCROOT_MAIN/Carthage/Build" "$SRCROOT_DEVELOPING_FRAMEWORK/Carthage/Build"
Step 2. Framework Replacement

2.1 Remove your developing framework in Xcode > YOUR_MAIN_APP > General > Linked Frameworks and Libraries (that is, the one located in $(SRCROOT_MAIN)/Carthage/Build/iOS).
2.2 Add $(DEVELOPING_FRAMEWORK_NAME).xcodeproj (found in directory pointed by $(SRCROOT_MAIN)/Carthage/Checkouts/$(DEVELOPING_FRAMEWORK_NAME) symbolic link) into your main app
2.3 Build the developing framework product for device and simulator
2.4 Add the new developing framework auto-detected by Xcode in Xcode > YOUR_MAIN_APP > General > Linked Frameworks and Libraries.
2.5 Add $(DEVELOPING_FRAMEWORK_NAME).framework as a target dependency by adding $(DEVELOPING_FRAMEWORK_NAME).framework in Xcode > YOUR_MAIN_APP > Build Phases > Target Dependencies.
2.6 Copy $(BUILT_PRODUCTS_DIR)/$(DEVELOPING_FRAMEWORK_NAME).framework to $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/$(DEVELOPING_FRAMEWORK_NAME).framework by adding a new input file $(BUILT_PRODUCTS_DIR)/$(DEVELOPING_FRAMEWORK_NAME).framework and a new output file $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/$(DEVELOPING_FRAMEWORK_NAME).framework in Xcode > YOUR_MAIN_APP > Build Phases > Run Script of Carthage Embed Framework.
Reference
Debugging Carthage Dependencies
https://allocinit.io/ios/debugging-carthage-dependencies/
Build Setting Reference
https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html

CMake: How can I copy a directory into the ios application bundle

I have an ios project that builds with CMake 3.1.1, but I am stuck on the last problem - getting CMake to copy the asset directory into the right location for the app.
I have this, which works when running the app in the simulator. However, it does not work, and in fact causes a build failure when archiving because the destination directory it constructs does not exist.
get_target_property(APPLICATION_BIN ${APPLICATION_NAME} LOCATION)
get_dotapp_dir(${APPLICATION_BIN} APPLICATION_APP_LOCATION)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND cp -r "${CMAKE_SOURCE_DIR}/assets" "${APPLICATION_APP_LOCATION}")
The directory I am copying has many subdirectories and I need them all preserved. Essentially I want to accomplish with cmake the same thing that happens when I drag the "assets" folder into the ios project underneath "Resources".
Use ${CMAKE_COMMAND} -E copy_directory instead of calling cp.
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP} DEPENDS "${PROJECT_SOURCE_DIR}/assets" COMMAND -E copy_directory ${PROJECT_SOURCE_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP})
add_custom_target(${CMAKE_CURRENT_BINARY_DIR}/${LOCATION_FOR_THE_APP} DEPENDS
My solution to this is similar to this answer. The goal of my project was to get googletests running on a cross-platform library, in which I had to wrap googletests into an XCTest Bundle. The build tool we are converting to is CMake for obvious reasons.
I ended up doing this as a pre-build step:
add_custom_command(TARGET ExampleTestTarget PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_LIST_DIR}/resources $<TARGET_FILE_DIR:ExampleTestTarget>
)
Essentially, at prebuild, CMake will copy everything in the resources folder into the root of the target's bundle. For some reason (probably a CMake thing), XCode picked these resource files up with no issue, so I didn't have to set the files to be RESOURCE files explicitly.
If you're using MacOS Bundles/Packages/etc., you'll have to copy-paste these files into $<TARGET_FILE_DIR:ExampleTestTarget>/Resources instead since this is the default resource location for MacOS xcodeproj's generated by CMake. (There are so many loopholes to get XCTests working in CMake that I advise everyone doing cross-platform gtests to create an executable instead for MacOS so you won't get into any trouble like this anyway).
Note, you won't see the files in XCode unless you add the files in target_sources(), but who cares... it works anyway! Who develops C++ exclusively in iOS? ....

Issues Using GIT with Xcode projects

I know git and use it to manage a lot of my Repos on other projects. However I run into issues when it comes to xcode projects.
I start a project on Machine 'A' - when I push up to a repo and pull to let say machine 'B' I always receive compiling errors. Normally the errors have to do with files not being found. Literally "no such file or directory" followed by a path.
I'm working with the same version of Xcode on both mac's A and B. I also use the threetwenty framework.
When I zip the project up and send via email - the same results occur.
Many times these files that xcode can't find and that fail the build, are media files, like a image or video. Sometimes I see the three20 framework too.
My question is - how in xcode should I set a project up to play nice with git and or code sharing in general. Let me know if you need more information, I know the above is a little vague.
The first thing I always do is set up the .gitignore file before adding any other files from the project. Problems can occur when loading project settings for two different machines that may have the same User account name. You have to make sure some settings aren't added to the repo whilst others are.
I set up my .gitignore by adding the following:
.DS_Store
*/.DS_Store
*.swp
*~.nib
build/
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
Documentation/Generated
doxygenWarnings.txt
*.xcodeproj/xcuserdata/*.xcuserdatad
*.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad
*/*.xcodeproj/xcuserdata/*.xcuserdatad
*/*.xcodeproj/project.xcworkspace/xcuserdata/*.xcuserdatad
If you create the repos from scratch or run git rm --cached <filethatshouldbeignore> to each file that should be ignored and then commit, see if the problem still occurs.
Problems will occur in the .pbxproj file, so make sure all conflicts are corrected too.
Regarding files that cannot be found, remember to import the libraries etc. into the project folders and reference them from there. Apple's own iOS libraries should be fine, but others won't be. For example, in your project folder, copy your images from there and reference them only within the project folder.

Resources