Carthage


My notes on Carthage for both using and creating your own carthage frameworks

Introduction:

Carthage lets you add dependencies to your Xcode project. Once your dependencies are configured correctly, you can call carthage update and all dependencies will be updated to the last compatible versions

Using a cartfile in a project:

  1. cd ~/Path/To/Starter/Project
  2. touch Cartfile
  3. open -a Xcode Cartfile
  4. add this to the cartfile: github "Alamofire/Alamofire" ~> 4.5.0
  5. carthage update --platform iOS (the platform flag, makes it only download iOS related code, it’s optional) --verbose flag gives more info
  6. In terminal: open Carthage opens the carthage folder
  7. In the /build/ folder drag and drop the .framework files into Xcode 👉 select your app in the tree-menu 👉 general 👉 linked frameworks

NOTE: App targets needs to have the framework refs in embedded libraries (framework targets does not)
NOTE: /carthage/ folder needs to be in the same folder as the .xcodeproj file

Creating your own carthage framework:

Creating a carthage compatible framework:

  1. make a 👉 framework 👈 project in Xcode
    img
  2. Share your scheme in Xcode
    img
  3. in terminal: (cd to the root of the framework project)
  4. in terminal: carthage build --no-skip-current This builds .framework and .dynlib (⚠️️this step is only needed if users wants to skip building from src ️⚠️️)
  5. Make the entire framework project available in your github repo. (use .gitignore to exclude unnecessary files)

NOTE: You can also make an App project first and then add a library target after.

.gitignore items:

Add these to your You can safely ignore these files when uploading files to github

# Carthage
Carthage

# xcode
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint
*.xcuserdatad
*.xcbkptlist

Commands:

carthage help build <– information about your build options
carthage help update <– info about update options etc
carthage update --no-build skips downloading .framework binaries, and just downloads the source .swift files
carthage build --no-skip-current tries to build the child dependencies before parents (or so it claims)
carthage bootstrap will simply look at Cartfile.resolved and fetch those particular commits

Using carthage:

github "Alamofire/Alamofire" == 2.0
github "SwiftyJSON/SwiftyJSON" ~> 2.3.0

These two lines tell Carthage that your project requires Alamofire version 2.0, and the latest version of SwiftyJSON that’s compatible with version 2.3.0.

Dependency Versioning:

Dependency Version: This is how you tell Carthage which version of a dependency you’d like to use. There are a number of options at your disposal, depending on how specific you want to be:

  1. == 1.0 means “Use exactly version 1.0”
  2. >= 1.0 means “Use version 1.0 or higher”
  3. ~> 1.0 means “Use any version that’s compatible with 1.0″, essentially meaning any version up until the next major release.
  4. == 0.0.0-alpha.3 means get exactly this version
  5. "branch-name" means use the latest commit from this branch 🔑
  6. q4k049 means use this commit
    If you specify ~> 1.7.5, then any version from 1.7.5 up to, but not including 2.0, is considered compatible.
    Likewise, if you specify ~> 2.0 then Carthage will use a version 2.0 or later, but less than 3.0. .
    Compatibility is based on Semantic Versioning – for more information check out our tutorial on Using CocoaPods with Swift. If you don’t specify a version, then Carthage will just use the latest version that’s compatible with your other dependencies

Flags:

The --platform iOS option ensures that frameworks are only built for iOS. If you don’t specify a platform, then by default Carthage will build frameworks for all platforms (often both Mac and iOS) supported by the library.

Uninstalling Carthage

sudo rm -rf /Library/Frameworks/CarthageKit.framework
rm -f /usr/local/bin/carthage

Installing Carthage:

Installing carthage 0.18.1 was a bit tricky. It worked flawlessly on my mac mini server but not so much on my macbook pro. After installing Carthage from the Carthage.pkg file . Terminal would not find carthage. So in order to make it work i had to hunt down the path where Carthage resided: and then figure out how to make an Alias in terminal.

  1. In terminal type: nano .bash_profile
  2. Then add this alias carthage="sudo /usr/local/bin/carthage"
  3. ctrl + o and then enter and then ctrl x Restart terminal
  4. type carthage version in terminal and you will be promted to type in your password.
  5. The drawback is that you have to type your password every time you want to use carthage.

Drawbacks:

  1. There is next to no information about how to use Carthage available on the net. You have to spend lots of time fumbling in the dark. I get that you figure it out in the end, but this time could be spent on more important things. More effort could be made to make it more approachable. Workflow tutorials, videos etc. Answering people on Stackoverflow. Most carthage questions are unanswered at present time 2017-Feb

  2. Hard to make projects carthage compatible. it requires the framework author to share a .xcodeproject file which has a deeply nested .xcscheme file inside. This is only possible through creating a complex set of rules in a .gitignore file. Which is not future proof, since apple may add new files to .xcodeproject at anytime, which you in-turn will need to add ignore cases in the .gitignore file. Carthage argues that its better to reuse information xcode already have. As apposed to cocoapod which creates a .podspec file in root. If only this information was easier to add to projects. It would be great if carthage could make this process a bit smoother. By either extracting the info on build and adding this info in a .carthage file in root or at least providing updated .gitignore information on each carthage update and and making sure .gitignore conformed to this standard.

  3. Close to impossible to nest frameworks. Which is the nr.1 reason why we need dependency managers in the first place, no? Modularity and all that? There are solutions for nesting frameworks but it requires scripts in obscure settings in xcode. “build phase” !?!? The phrase “XCode already have the information you need” seems not to fit anymore. Abstracting this information into a separate file would be 👌 There is also some talk about using git submodules to get nested frameworks working. But wasn’t that one of the arguments to use carthage in the first place. Avoiding git submodules and git subtrees. Lots of contradictories here.

  4. Clutters up your github repos. Carthage files, obscure XCode project files in obscure sub folders that makes no sense.

Gotchas:

  • Adding binaries (.framework and .dSYM) to releases section of github speeds up the process of adding frameworks to your project, because the local systems doesn’t have to build the .frameworks. A drawback is that binaries leak personal information and information about your computer file system. Which can be a security risk. An option is to build binaries off-site on a remote computer. Or use an anonymous computer.
  • Sometimes you have to point Xcode correctly: sudo xcode-select -s <path to Xcode 9 beta>/Xcode-beta.app/Contents/Developer

Carthage further reading:

https://realm.io/news/swift-dependency-management-with-carthage/
https://www.raywenderlich.com/109330/carthage-tutorial-getting-started
https://www.raywenderlich.com/416-carthage-tutorial-getting-started http://blog.mat.tc/how-to-make-a-carthage-compatible-framework/ http://basememara.com/creating-cross-platform-swift-frameworks-ios-watchos-tvos-via-carthage-cocoapods/
Avoiding .dragging frameworks into xcode after each update: https://stackoverflow.com/a/49787323/5389500 Using private repo https://samwize.com/2018/06/27/creating-a-private-framework-with-carthage/

Carthage video tutorial:

https://www.youtube.com/watch?v=0nMne7puV1Q (the basics)

Side-notes:

  • Add this to your search path: $(SRCROOT)/Carthage/Build relative paths for build phase 🔑 (Carthage adds aliases in this folder)
  • If you are using @testable import then search for testability in the build settings of your xcode project set this to yes 🔑
  • carthage bootstrap -> could possibly support nested frameworks
  • You can comment out lines in Cartfile via the #` char
  • `github “eonist/Element” “master” will default to the latest commit (as opposed to HEAD which will not) you can also use “master” if you have no tags in your repo
  • ⚠️️ Don’t forget to set your XCode framework project scheme to shared. ⚠️️ (btn right of the stop btn 👉 manage scheme 👉 shared checkbox)
  • CMD + I on a .framework will show the version of the framework in macOS Finder 👌 (🚫 seems to not work 🚫)
  • If you want to include assets like images etc into your .framework you can use Compile Source 👉 add the files you want to include in your framework.
  • Sometimes carthage doesnt wont to work correctly: rm -rf ~/Library/Caches/org.carthage.CarthageKit clear the cache
  • before you release your app on the app store you must: Work around the appstore submission bug

Tasks:

  • [] Figure out how you can order build process.