Skip to content

Instantly share code, notes, and snippets.

@forest
Created January 22, 2010 17:25
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 forest/283939 to your computer and use it in GitHub Desktop.
Save forest/283939 to your computer and use it in GitHub Desktop.
Rakefile to build xcode projects in nested directory structure. #xcode
###########################################################################
# XCode Tasks
###########################################################################
XCODE_PROJECTS_CACHE = 'xcode_projects_cache.yml'
def xcode_projects
projects = []
if File.exist?(XCODE_PROJECTS_CACHE)
File.open( XCODE_PROJECTS_CACHE ) do |yml_in|
projects = YAML.load( yml_in )
end
else
puts "Dynamically generating xcode tasks and caching..."
fl = FileList.new("**/*.xcodeproj")
# fl.exclude(Regexp.new(exclude, true)) unless exclude.nil?
fl.each do |xcodeproj|
project = { :xcodeproj => xcodeproj }
dir, base = File.split(xcodeproj)
FileUtils.cd(dir, :verbose => false) do
out = %x{ xcodebuild -list }
# targets
targets = []
out.scan(/.*Targets:\s+(.*)Build Configurations:.*/m)
$1.each_line do |l|
l = l.strip.sub(' (Active)', '')
targets << l unless l.nil? or l.empty?
end
project[:targets] = targets
# configurations
configurations = []
out.scan(/.*Build Configurations:\s+(.*)If no build configuration.*/m)
$1.each_line do |l|
l = l.strip.sub(' (Active)', '')
configurations << l unless l.nil? or l.empty?
end
project[:configurations] = configurations
end
projects << project
end
# cache projects so we don't have to do this every time
File.open( XCODE_PROJECTS_CACHE, 'w' ) do |out|
YAML.dump( projects, out )
end
end
projects
end
namespace :xcode do
projects = xcode_projects
desc "clean the XCode project cache so it will be recreated next run"
task :clearcache do |t|
if File.exist?(XCODE_PROJECTS_CACHE)
File.delete(XCODE_PROJECTS_CACHE) rescue nil
end
end
# removed install
%w{build clean}.each do |action|
namespace "#{action}" do
projects.each do |project|
xcodeproj = project[:xcodeproj]
targets = project[:targets]
configs = project[:configurations]
targets.each do |target|
desc "#{action} #{target}"
task "#{target}" do |t|
FileUtils.cd(File.dirname(xcodeproj)) do
cmd = "xcodebuild -target '#{target}' #{action} OBJROOT=build/ SYMROOT=build/ DSTROOT=/"
# need to handle result from sh because the default behavior is to 'fail'
# if the command returns a failure error code (i.e. not 0)
sh(cmd) do |ok, res|
unless ok
puts "Failed to execute '#{cmd}'"
puts "ERRORLEVEL=#{res.exitstatus}"
end
end
end
end
# alias the task above using a massaged name
massaged_target = target.downcase.gsub(/[\s*|\-]/, '_')
task "#{massaged_target}" => "xcode:#{action}:#{target}"
namespace "#{target}" do
configs.each do |config|
desc "#{action} #{target} #{config}"
task "#{config}" do |t|
FileUtils.cd(File.dirname(xcodeproj)) do
cmd = "xcodebuild -target '#{target}' -configuration '#{config}' #{action} SYMROOT=build/ OBJROOT=build/ DSTROOT=/"
# need to handle result from sh because the default behavior is to 'fail'
# if the command returns a failure error code (i.e. not 0)
sh(cmd) do |ok, res|
unless ok
puts "Failed to execute '#{cmd}'"
puts "ERRORLEVEL=#{res.exitstatus}"
end
end
end
end
end
end
# namespace+task aliases of the above using massaged names
namespace "#{massaged_target}" do
configs.each { |conf| task "#{conf.downcase.gsub(/[\s*|\-]/, '_')}" => "xcode:#{action}:#{target}:#{conf}" }
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment