Skip to content

Instantly share code, notes, and snippets.

@matnogaj
Last active June 23, 2017 10:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matnogaj/1a4c1d10bfc458a25f86e2946f7cae53 to your computer and use it in GitHub Desktop.
Save matnogaj/1a4c1d10bfc458a25f86e2946f7cae53 to your computer and use it in GitHub Desktop.
Adds adhoc config to projects found in node_modules
require 'xcodeproj'
require 'find'
require 'yaml'
require 'set'
class XCodeProject
def initialize(path)
unless File.exists?(path)
raise Errno::ENOENT, "#{path} does not exist."
end
@path = path
@_name = File.basename(path, '.xcodeproj')
@proj = Xcodeproj::Project.open(path)
@build_config_names = @proj.build_configurations.collect(&:name).to_set
@debug_bc = build_config_named 'Debug'
@release_bc = build_config_named 'Release'
end
def project_name
@_name
end
def deep_dup(object)
case object
when Hash
new_hash = {}
object.each do |key, value|
new_hash[key] = deep_dup(value)
end
new_hash
when Array
object.map { |value| deep_dup(value) }
else
object.dup
end
end
def build_configurations
@proj.build_configurations
end
def mirror_settings(from_bc, to_bc)
to_bc.build_settings = deep_dup(from_bc.build_settings)
end
def duplicate_debug_as(name)
bc = @proj.add_build_configuration(name, :debug)
mirror_settings(@debug_bc, bc)
end
def duplicate_release_as(name)
bc = @proj.add_build_configuration(name, :release)
mirror_settings(@release_bc, bc)
end
def ensure_build_config(name, kind)
base_bc = kind == :debug ? @debug_bc : @release_bc
if has_config_named name
puts " Configuration '#{name}' already exists."
puts " Ensuring settings are properly mirrored."
mirror_settings(base_bc, build_config_named(name))
else
puts " Not Found: '#{name}'."
puts " Creating new one based off of #{base_bc.name}."
if kind == :debug
duplicate_debug_as(name)
else
duplicate_release_as(name)
end
end
end
def ensure_build_config_in_targets(name, kind)
@proj.targets.each do |target|
names = target.build_configurations.collect(&:name).to_set
if !names.include?(name)
puts "Target #{target} is missing #{name}"
new_bc = target.add_build_configuration(name, kind)
config_name = (kind == :debug) ? 'Debug' : 'Release'
from_bc = target.build_configurations.find { |bc| bc.name == config_name }
mirror_settings(from_bc, new_bc)
# save
end
end
end
def build_config_named(name)
@proj.build_configurations.find { |bc| bc.name == name }
end
def all_build_phases
@proj.targets.map{|t|t.build_phases}.flatten
end
def has_config_named(name)
@build_config_names.include?(name)
end
def find_run_script_phase
all_build_phases.find do |bp|
bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && yield(bp)
end
end
def save
@proj.save
end
end
class BuildConfigSynchronizer
def initialize(search_path=File.join(File.dirname(__FILE__), '../node_modules'))
@search_path = search_path
# if you need more configs then add them here
@mappings = {:debug => ["Debug"], :release => ["Release", "AdHoc"]}
find_and_fix_projects
end
def fix_project(project)
puts "Fixing #{project.project_name}..."
puts " Ensuring all build configs are properly mapped"
@mappings.each do |kind,names|
names.each do |name|
# first fix targets and later project
project.ensure_build_config_in_targets(name, kind)
project.ensure_build_config(name, kind)
end
end
puts " Making sure run scripts have correct conditionals."
bp = project.find_run_script_phase do |rs_phase|
rs_phase.shell_script.include?('"Debug"')
end
if bp
puts " Run script needs updating."
ss_text = bp.shell_script.split("\n").map{|s| " #{s}"}.join("\n")
puts " Found:\n#{ss_text}\n"
bp.shell_script = bp.shell_script.sub('"Debug"', '*Debug')
ss_text = bp.shell_script.split("\n").map{|s| " #{s}"}.join("\n")
puts " Replaced with:\n#{ss_text}\n"
else
puts " Run script seems in order."
end
puts "Finished fixing #{project.project_name}.\n\n"
project.save
end
def find_and_fix_projects
puts "Searching #{@search_path} for relevant xcodeproj's...\n\n"
Find.find(@search_path) do |e|
if e =~ /\.xcodeproj\Z/
puts "Found SOME xcodeproj file. #{e}"
fix_project(XCodeProject.new(e))
end
end
end
end
BuildConfigSynchronizer.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment