Skip to content

Instantly share code, notes, and snippets.

@rnkyr
Created April 2, 2018 22:15
Show Gist options
  • Select an option

  • Save rnkyr/ecaae345ed223117942717b9dc9b761c to your computer and use it in GitHub Desktop.

Select an option

Save rnkyr/ecaae345ed223117942717b9dc9b761c to your computer and use it in GitHub Desktop.
An semi-automation script for Carthage dependency manager
#!/usr/bin/ruby
# An semi-automation script for Carthage dependency manager
# It performs linking and copy-frameworks phase creation
# Basic usage examples:
# ruby ~/dev/cart.rb -d "~/Desktop/MyProject" -l
# ruby ~/dev/cart.rb -d "~/Desktop/MyProject" -tar "Core" -t "RxSwift, Bolts-Swift"
# ruby ~/dev/cart.rb -d "~/Desktop/MyProject" -s "RxSwift, Bolts-Swift"
# Or you can create a Run Script phase (in dedicated Aggregate Target) which will run carthage as well.
# Run Script Phase:
=begin
if which xcodeproj >/dev/null; then
if which carthage >/dev/null; then
carthage update --platform "iOS" --cache-builds
/usr/bin/ruby ~/dev/cart.rb --dir $PWD --target "Core" -t "APIClient, APIClientAlamofire, APIClientObjectMapper, BoltsSwift, ObjectMapper" -v
/usr/bin/ruby ~/dev/cart.rb --dir $PWD --take "RxSwift, RxCocoa, NSObject_Rx" -v
else
echo "warning: Carthage line tool is required. 'https://github.com/Carthage/Carthage'"
fi
else
echo "warning: xcodeproj gem is required. Please run 'sudo /usr/bin/gem install xcodeproj'"
fi
=end
require 'optparse'
require 'fileutils'
require 'xcodeproj'
def spit(input)
puts "\e[33m#{input}\e[0m" if $v
end
def info(input)
puts "\e[32m#{input}\e[0m"
end
def error(input)
puts "\e[31m#{input}\e[0m"
info 'Interrupting...'
exit
end
options = {
:dir => File.dirname(__FILE__),
:platform => 'iOS',
:verbose => false,
:backup => false,
:skip => [],
:take => [],
:target => nil,
:list => false
}
parser = OptionParser.new do |opts|
opts.banner = 'Usage: cart.rb [options]'
opts.on('-d', '--dir dir', 'Directory of the project') do |dir|
options[:dir] = dir.sub('~', Dir.home)
end
opts.on('-p', '--platform platform', 'Platform') do |platform|
options[:platform] = platform
end
opts.on('-b', '--backup', 'Backups files before modifying') do
options[:backup] = true
end
opts.on('-v', '--verbose', 'Prints debug info') do
options[:verbose] = true
end
opts.on('--target target', 'Target name') do |target|
options[:target] = target
end
opts.on('-s', '--skip f1,f2,f3,...', 'Skip given list of frameworks (comma separated)') do |list|
options[:skip] = list.split(',').map { |f| f.strip + '.framework' }
end
opts.on('-t', '--take f1,f2,...', 'Takes only given list of frameworks (comma separated') do |list|
options[:take] = list.split(',').map { |f| f.strip + '.framework' }
end
opts.on('-l', '--list', 'List frameworks found in Carthage build directory and terminates') do
options[:list] = true
end
opts.on('-h', '--help', 'Displays Help') do
info opts.to_s
info "Example: ruby ~/dev/cart.rb -d \"~/dev/iOS/jet-journal\" -tar \"Core\" -s \"RxTesting,RxBlocking\""
exit
end
end
parser.parse!
project_name = options[:dir].split('/').last
options[:target] = project_name unless options[:target]
target_name = options[:target]
carthage_build_path = options[:dir] + '/Carthage/Build/' + options[:platform] + '/'
file_path = options[:dir] + '/' + project_name + '.xcodeproj'
$v = options[:verbose]
spit 'Input: ' + options.to_s
frameworks = Dir[carthage_build_path + '/*.framework'].map { |p| p.split('/').last }
if options[:list]
info frameworks.map { |f| f.split('.').first }.to_s
exit
end
spit 'Found: ' + frameworks.map { |f| f.split('.').first }.to_s
error ('No Frameworks found in ' + carthage_build_path) if frameworks.length == 0
if options[:take].length != 0
take = options[:take]
frameworks = frameworks.reject { |f| !take.include?(f) }
spit 'Take: ' + frameworks.map { |f| f.split('.').first }.to_s
end
if options[:skip].length != 0
skip = options[:skip]
frameworks = frameworks.reject { |f| skip.include?(f) }
spit 'Take: ' + frameworks.map { |f| f.split('.').first }.to_s
end
error 'No Frameworks satisfies given criterion' if frameworks.length == 0
spit "Modifying #{file_path}:"
error('File not found ' + file_path) unless File.directory?(file_path)
# @type [Project]
project = Xcodeproj::Project.open(file_path)
# @type [PBXGroup]
group = project['Frameworks']
if group.nil?
group = project.new_group('Frameworks')
spit 'Created Frameworks group'
end
# @type [Array<PBXFileReference>]
references = []
frameworks.each do |f|
path = carthage_build_path + f
ref = group[f]
if ref.nil?
ref = group.new_reference(path)
end
references << ref
end
# @type [AbstractTarget]
target = nil
project.targets.each do |t|
if t.name.eql? target_name
target = t
break
end
end
if target.nil?
error 'Target not found ' + target_name
end
target.build_configurations.each do |config|
setting = config.build_settings['FRAMEWORK_SEARCH_PATHS']
path = '$(PROJECT_DIR)/Carthage/Build/iOS'
setting << path unless setting.include? path
end
# @type [PBXFrameworksBuildPhase]
frameworks_build_phase = target.frameworks_build_phase
references.each do |ref|
unless frameworks_build_phase.include?(ref)
frameworks_build_phase.add_file_reference(ref)
end
end
# @type [PBXShellScriptBuildPhase]
run_script_phase = nil
target.shell_script_build_phases.each do |scp|
if scp.shell_script == '/usr/local/bin/carthage copy-frameworks'
run_script_phase = scp
break
end
end
if run_script_phase.nil?
run_script_phase = target.new_shell_script_build_phase('carthage copy frameworks')
run_script_phase.shell_script = '/usr/local/bin/carthage copy-frameworks'
spit 'Added Run Script Phase'
end
frameworks.each do |f|
input_path = '$(SRCROOT)/Carthage/Build/iOS/' + f
output_path = '$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/' + f
unless run_script_phase.input_paths.include?(input_path)
run_script_phase.input_paths << input_path
end
unless run_script_phase.output_paths.include?(output_path)
run_script_phase.output_paths << output_path
end
end
if options[:backup]
backup_file = options[:dir] + '/' + options[:dir].split('/').last + '.xcodeproj/project.pbxproj.backup'
spit 'Creating backup file ' + backup_file
FileUtils.cp(file_path, backup_file)
end
project.save
info 'Successfully saved!'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment