Skip to content

Instantly share code, notes, and snippets.

@Jon889
Created June 16, 2025 21:18
Show Gist options
  • Save Jon889/f824d8e95510284fa1ed36f325d0fc03 to your computer and use it in GitHub Desktop.
Save Jon889/f824d8e95510284fa1ed36f325d0fc03 to your computer and use it in GitHub Desktop.
A tool to list or set a build setting in every Xcode project within the current directory hierarchy
#!/usr/bin/env ruby
require 'xcodeproj'
require 'find'
require 'pathname'
require 'optparse'
options = { show_projects: false }
OptionParser.new do |opts|
opts.banner = "Usage: ruby buildsetting.rb [options] <BUILD_SETTING_KEY> [NEW_VALUE]"
opts.separator ""
opts.separator "Description:"
opts.separator " This tool searches all Xcode projects in the current directory (recursively),"
opts.separator " excluding any that contain 'Pods', and reports the value of the specified"
opts.separator " build setting across all targets and configurations."
opts.separator ""
opts.separator " If a NEW_VALUE is provided, the tool will set that build setting to the"
opts.separator " given value for all configurations of all targets, then report the result."
opts.separator ""
opts.separator " Written by Copilot"
opts.separator ""
opts.separator "Options:"
opts.on("--projects", "Print project paths in the output") do
options[:show_projects] = true
end
end.parse!
if ARGV.empty?
puts "Usage: ruby buildsetting.rb [options] <BUILD_SETTING_KEY> [NEW_VALUE]"
exit 1
end
setting_key = ARGV[0]
new_value = ARGV[1]
base_dir = Dir.pwd
def find_xcode_projects(base_dir)
projects = []
Find.find(base_dir) do |path|
next if path.include?('Pods')
projects << path if path.end_with?('.xcodeproj')
end
projects
end
def set_build_setting(projects, setting_key, new_value)
projects.each do |project_path|
project = Xcodeproj::Project.open(project_path)
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings[setting_key] = new_value
end
end
project.save
end
end
def extract_all_targets(projects, setting_key, base_dir)
all_targets = Hash.new { |h, k| h[k] = [] }
projects.each do |project_path|
project = Xcodeproj::Project.open(project_path)
relative_path = Pathname.new(project_path).relative_path_from(Pathname.new(base_dir)).to_s
project.targets.each do |target|
values = target.build_configurations.map { |config| config.build_settings[setting_key] }.compact.uniq
values.each do |value|
all_targets[value] << "#{relative_path}/#{target.name}"
end
end
end
all_targets
end
def extract_grouped_results(projects, setting_key, base_dir)
results = {}
projects.each do |project_path|
project = Xcodeproj::Project.open(project_path)
relative_path = Pathname.new(project_path).relative_path_from(Pathname.new(base_dir)).to_s
project.targets.each do |target|
target.build_configurations.each do |config|
value = config.build_settings[setting_key]
next unless value
results[value] ||= {}
results[value][relative_path] ||= {}
results[value][relative_path][target.name] ||= {}
results[value][relative_path][target.name][config.name] = value
end
end
end
results
end
def print_results(results, target_counts, options)
results.each do |value, projects|
count = target_counts[value].uniq.size
label = count == 1 ? "value" : "values"
puts "#{count} Build Setting #{label}: #{value}"
projects.each do |project, targets|
puts " 📁 #{project}" if options[:show_projects]
targets.each do |target, _configs|
puts " 🎯 #{target}"
end
end
puts
end
end
projects = find_xcode_projects(base_dir)
# If a new value is provided, set it first
set_build_setting(projects, setting_key, new_value) if new_value
# Then extract and print results
target_counts = extract_all_targets(projects, setting_key, base_dir)
grouped_results = extract_grouped_results(projects, setting_key, base_dir)
print_results(grouped_results, target_counts, options)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment