Last active
November 14, 2019 21:19
-
-
Save JoeMatt/5e0218cdd27fcc38de0b81900d4c969e to your computer and use it in GitHub Desktop.
Improve Carthage performance with Per-target manifest caching and optional Fastlane usage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set -e | |
# carthage.sh : smarter carthage updating and caching by Joe Mattiello | |
# | |
# Inspired from http://shashikantjagtap.net/cache-carthage-speed-ios-continuous-integration/ | |
# | |
# The purpose of this script is to reduce the amount of checkouts Carthage runs. | |
# I use this script in an XCode 'run script' build phase as the first phase before compiling | |
# If you have mutliple targets, projects, frameworks etc, you can include this script in each and it will selec | |
# the correct Carthage folder for each target. | |
# | |
# There's also an optional fastlane integration if it's installed. | |
# For my project we make fastlane optional, this script will choose which ever is availabe. | |
# An example Fastfile will be included with this gist. | |
# | |
# Usage: | |
# $ ./carthage.sh platform | |
# * platform: Cant be a single platform, 'tvOS', or command seperated multiples, 'tvOS,iOS' | |
# If not online, we just quit successfully. | |
# If the user hasn't bootstap'd carthage locally they will most likely get a build error next. | |
if nc -zw1 github.com 443 > /dev/null; then | |
echo "Online" | |
else | |
echo "Not Online" | |
exit 0; | |
fi | |
# Check for xcodebuild. Alert user if missing | |
if which xcodebuild > /dev/null; then | |
echo "Has XCode command line tools" | |
else | |
echo "error: Missing XCode command line tools. Intall with 'xcode-select --install' from terminal then restart XCode." | |
osascript -e 'tell app "System Events" to display dialog "Error. Missing XCode command line tools. Intall with xcode-select --install from terminal then restart XCode." buttons {"OK"} with icon caution with title "Missing XCode command line tools"' | |
exit 1 | |
fi | |
function runCarthageAndCopyResolved { | |
echo "Running Carthage.." | |
if which fastlane > /dev/null; then | |
echo "Setting up Carthage for platform $1 using fastlane" | |
bundle exec fastlane carthage_bootstrap platform:"$1" | |
/usr/local/bin/carthage outdated --xcode-warnings | |
elif which carthage > /dev/null; then | |
echo "Setting up Carthage for platform $1" | |
/usr/local/bin/carthage bootstrap --no-use-binaries --cache-builds --platform $1 --project-directory "$SRCROOT" | |
/usr/local/bin/carthage outdated --xcode-warnings | |
# Example how to enable different command for different build styles. | |
# ie; carthage build, will force a rebuild. Might be preferred for safety for ad-hoc and app store builds | |
# if [ "${BUILD_STYLE}" == "Ad Hoc Distribution" ] || [ "${BUILD_STYLE}" == "App Store" ]; | |
# then | |
# /usr/local/bin/carthage build --verbose --no-use-binaries --cache-builds --platform $1 --project-directory "$SRCROOT" | |
# fi | |
else | |
echo "error: Carthage is not installed, download from https://github.com/Carthage/Carthage#installing-carthage" | |
osascript -e 'tell app "System Events" to display dialog "Error. Carthage is not installed, download from \nhttps://github.com/Carthage/Carthage#installing-carthage" buttons {"OK"} with icon caution with title "Missing Carthage"' | |
exit 1 | |
fi | |
# Copies the Cartfile.resolved file to /Carthage directory | |
local sourceCartfile="$SRCROOT/Cartfile.resolved" | |
local destCartfile="$SRCROOT/Carthage/.Cartfile.$1.resolved" | |
cp "$sourceCartfile" "$destCartfile" | |
echo "Copied $sourceCartfile to $destCartfile" | |
echo "This will be used to check Carthage dependency updates in the future." | |
} | |
# Carthage is required, check if installed and alert user how to install | |
command -v carthage >/dev/null 2>&1 || { | |
echo "error: Carthage is not installed, download from https://github.com/Carthage/Carthage#installing-carthage" | |
osascript -e 'tell app "System Events" to display dialog "Error. Carthage is not installed, download from \nhttps://github.com/Carthage/Carthage#installing-carthage" buttons {"OK"} with icon caution with title "Missing Carthage"' | |
exit 1; | |
} | |
# Function to iterate comma seperated list of targets and | |
# check that a Carthage/Build/${Platform} exists. | |
function carthageBuildPathNotExist { | |
echo "carthageBuildPathNotExist $1" | |
for i in $(echo $1 | tr "," "\n") | |
do | |
local path="$SRCROOT/Carthage/Build/$i" | |
echo "Testing for $path" | |
if [ ! -d $path ]; then | |
echo "Fail: No path found for $i" | |
return 0 | |
else | |
echo "Success: Path found for $i" | |
fi | |
done | |
echo "Success: Build paths exist for all targets $1" | |
return 1 | |
} | |
# Function to iterate comma seperated list of targets and | |
# check that a Carthage/.Cartfile.${Platform}.resolved exists. | |
# and matches the current Carthage.resolved file | |
function carthageManifestUpToDate { | |
echo "carthageManifestUpToDate $1" | |
for i in $(echo $1 | tr "," "\n") | |
do | |
local path="$SRCROOT/Carthage/.Cartfile.$1.resolved" | |
echo "Testing for $path" | |
if [ -f $path ] && \ | |
diff $path \ | |
$SRCROOT/Cartfile.resolved >/dev/null ; then | |
echo "$file matches $SRCROOT/Cartfile.resolved." | |
else | |
echo "Fail: manifest mismatch found for $path AND $SRCROOT/Cartfile.resolved" | |
return 1 | |
fi | |
done | |
echo "Success: Manifests match for all targets $1" | |
return 0 | |
} | |
# The main execution starts here | |
if carthageBuildPathNotExist $1; then | |
echo "Carthage build required for $1" | |
runCarthageAndCopyResolved $1 | |
elif carthageManifestUpToDate $1; then | |
echo "Cartfile.resolved has not changed. Will move on to building project." | |
else | |
echo "Cartfile.resolved not up to date or not found." | |
runCarthageAndCopyResolved $1 | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example Fastfile that works with carthage.sh | |
# Default platforms are set to tvOS,iOS. Valid values are: | |
# iOS, Mac, tvOS, watchOS | |
default_platform(:ios) | |
platform :ios do | |
desc "Lane to run bootstrap carthage in new checkout" | |
desc "Option: `platform` tvOS,iOS" | |
lane :carthage_bootstrap do |options| | |
platform = options.fetch(:platform, 'tvOS,iOS') | |
carthage_private( | |
command: "bootstrap", | |
platform: platform, | |
project_directory: "PVSupport" | |
) | |
carthage_private( | |
command: "bootstrap", | |
platform: platform, | |
project_directory: "PVLibrary" | |
) | |
carthage_private( | |
command: "bootstrap", | |
platform: platform, | |
project_directory: "./" | |
) | |
end | |
desc "Lane to run build all carthage dependencies" | |
desc "Option: `platform` tvOS,iOS" | |
lane :carthage_build do |options| | |
platform = options.fetch(:platform, 'tvOS,iOS') | |
carthage_private( | |
command: "build", | |
platform: platform, | |
project_directory: "PVSupport" | |
) | |
carthage_private( | |
command: "build", | |
platform: platform, | |
project_directory: "PVLibrary" | |
) | |
carthage_private( | |
command: "build", | |
platform: platform, | |
project_directory: "./" | |
) | |
end | |
desc "Lane to update all carthage dependencies to latest versions" | |
desc "Option: `platform` tvOS,iOS" | |
lane :carthage_update do |options| | |
platform = options.fetch(:platform, 'tvOS,iOS') | |
carthage_private( | |
command: "update", | |
platform: platform, | |
project_directory: "PVSupport" | |
) | |
carthage_private( | |
command: "update", | |
platform: platform, | |
project_directory: "PVLibrary" | |
) | |
carthage_private( | |
command: "update", | |
platform: platform, | |
project_directory: "./" | |
) | |
end | |
private_lane :carthage_private do |options| | |
command = options.fetch(:command, 'bootstrap') | |
platform = options.fetch(:platform, 'tvOS,iOS') | |
project_directory = options.fetch(:project_directory, './') | |
puts "Running Carthage command '#{command}' for platform(s) '#{platform}' in directory '#{project_directory}'" | |
carthage( | |
command: command, | |
platform: platform, | |
use_binaries: false, | |
cache_builds: true, | |
project_directory: project_directory | |
) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example gitignore rules that work well with these scripts | |
# Don't upload built frameworks | |
# !Recomended otherwise your gitrepo will blow up with binaries | |
/Carthage/Build | |
# Ignore the cached local user resolutions !Required | |
.Cartfile.resolved | |
.Cartfile.tvOS.resolved | |
.Cartfile.iOS.resolved | |
# Ignore checked out dependency sources | |
# !Not recmended - If the repo disapears it's nice to have dependencies store locally | |
# Use --use-submodule instead with carthage if you don't want source files uploaded to your repo | |
#/Carthage/Checkouts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment