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
Related
I'm interested on Running this GitHub repository of an iOS Application: https://github.com/septadev/SEPTA-iOS I opened the iSEPTA.xcodeproj file on XCode from the iSEPTA folder, but I'm getting these Buildtime Errors. For example: No such module 'ReSwift', and this is the window I get prompted when I select any of the yellow alerts, I'm not sure if I should perform these changes, yet.
Could it be some incomparability with my XCode and Swift versions?
Please, help!!
This project uses Carthage as a dependency management system for using external dependencies.
You should install Carthage to your computer and then run carthage update from the terminal in the root directory of the project. This will instal the dependencies and will allow you to run the project.
Take a look at Cartfile: it indicates this repo is using Carthage package manager. Follow their instructions to install dependent libraries
This repository requires Carthage ( https://github.com/Carthage/Carthage ) - this is a dependency manager. You can install it using Homebrew (https://brew.sh/)
brew install carthage
then you have to run carthageBuild.sh script (which runs carthage update):
./carthageBuild.sh
and then you have to open: Septa.xcworkspace file
This would be the correct solution if the project used Cocoapods. Since it uses Carthage, look to others answers unless you are referencing this answer to a similar issue.
You need to use Cocoapods to integrate the pods attached to the project. Often times projects will not come with them precompiled. Either you opened the blue project file with the *.xcodeproj extension instead of the white project file with the *.xcworkspace extension.... or you don't have the pods installed at all. In which case read below.
Instructions as follows:
cd to project directory
Install Cocoapods
sudo gem install cocoapods
Ensure the you have the given pods in your repo collection for install
pod repo update
Install the pods
pod install
Validate Project Settings
This is necessary until cocoapods v1.6 release (beta is out).
Open the white project file with the *.xcworkspace extension
After those steps are complete, the project should run normally.
I am trying to link a new framework downloaded via Carthage to one of my project but getting a linker error:
I'm following these steps:
Updated the Cartfile with the framework location.
Run carthage update command to fetch the framework.
Under project target -> Build Phase added a new Run script and renamed it to Framework Copy.
Added the script to copy the framework from the file system : $(SRCROOT)/Carthage/Build/iOS/CleanroomLogger.framework.
Dragged and dropped the framework from the mentioned location under Link Binary With Libraries section of project target -> Build Phase.
Double checked the Framework Search Path under build settings and it seems to be set correctly : $(PROJECT_DIR)/Carthage/Build/iOS.
Am I missing something?
Eventually it turned out to be deployment target issue. The framework I was linking was supported with minimum deployment target as 8 and I was running with 7 :). I wish the build error could be more descriptive.
I get the "No such module" compilation error in Xcode 8.2.1 in my Swift project. I use Carthage with two modules: Alamofire and Fuzi. The Carthage/Build/iOS directory exists with the two framework files. The Build Settings/Framework Search Paths points to that directory. I have embedded the two framework files in General/Embedded Binaries. What am I missing?
You shouldn't need to embed the libraries; they should be added to Linked Frameworks and Libraries underneath the "General/Embedded Binaries" section. Make sure you have the Carthage copy-frameworks script added to your Build Phases.
From the Carthage documentation:
On your application targets’ “General” settings tab, in the “Linked
Frameworks and Libraries” section, drag and drop each framework you
want to use from the Carthage/Build folder on disk. On your
application targets’ “Build Phases” settings tab, click the “+” icon
and choose “New Run Script Phase”. Create a Run Script in which you
specify your shell (ex: bin/sh), add the following contents to the
script area below the shell:
/usr/local/bin/carthage copy-frameworks
and add the paths to the frameworks you want to use under “Input
Files”, e.g.:
$(SRCROOT)/Carthage/Build/iOS/Box.framework
$(SRCROOT)/Carthage/Build/iOS/Result.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework
This script works around an App Store submission bug triggered by
universal binaries and ensures that necessary bitcode-related files
and dSYMs are copied when archiving.
Firstly you check Carthage installed or not in your machine like the following command in your terminal
carthage version
If carthage is not installed in your machine try the following.
Download the latest release of Carthage, and double-click Carthage.pkg to run the installer. Click Continue, select a location to install to, then click Continue again, and finally click Install.
Then you can check carthage version.
If you are using existing project then move to project folder like
cd ~/Path/To/Starter/Project
Try the following command for update cartfile
carthage update —platform iOS
After installation/updation completed then try the following command
open carthage
You should see a Finder window pop up that contains two directories: Build and Checkouts.
In the Carthage Finder window, navigate into Build\iOS. Now, drag Alamofire.framework(for example) into the Linked Frameworks and Libraries section in Xcode:
Next, switch over to Build Phases and add a new Run Script build phase. Add the following command:
/usr/local/bin/carthage copy-frameworks
Click the + under Input Files and add an entry for each framework:
$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
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/
I had cocoapods in my project and it worked fine. But now that I upgraded my xCode and everything else, I get a linker error about the pods when I try to archive the project.
I was trying to follow the solutions in this answer but the steps they mention are not quite what I see on my screen.
What are the steps to configure my cocoapods correctly?
Here is a screenshot of how things are appearing for me with the libraries in red on the left side, and some configurations on the main area of the screen.
Make a backup of your .pod config file that has all your third party project references in it. Delete pods folder and delete workspace that Cocopods creates by default.
This is the file to backup
$ sudo gem install cocoapods
Navigate to where project lives:
cd /Users/yourUserFolder/LocationOfProject/
Then Run:
$ pod install
Open Workspace
$ open App.xcworkspace
**Make sure you open the workspace file. Not the .project file.
Image of what my .pod file looks like, just for your reference to make sure you have the correct format.