1require 'rake/loaders/makefile' 2 3@cc = 'cc' 4@linker = 'cc' 5@makedepend = 'makedepend' 6@frameworkPaths = %w(~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks) 7 8@commonflags = '' 9@cflags = '' 10@cxxflags = '' 11@objcflags = '' 12 13@includes = '' 14@defines = '' 15@ldflags = '' 16@frameworkFlags = '' 17@libs = '' 18@systemFrameworks = [] 19@frameworks = [] 20@cleanfiles = [] 21 22begin 23 unless NOT_UNIVERSAL 24 ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.4' 25 @commonflags += ' -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk ' 26 @ldflags += ' -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk ' 27 end 28rescue NameError 29 NOT_UNIVERSAL = false 30 retry 31end 32 33begin 34 if BUILDDIR 35 @includes += " -I#{BUILDDIR} " 36 end 37rescue NameError 38 BUILDDIR = '' 39end 40 41########### 42# Cleanup # 43########### 44 45task(:clean) do |task| 46 rm_rf(BUILDDIR) 47 rm_rf(@cleanfiles) 48 rm_rf(BUNDLEDIR) 49end 50 51################ 52# Installation # 53################ 54 55def installRule(dir, file) 56 target = File::join(dir, File::basename(file)) 57 file(target => [dir, file]) do |t| 58 cp(file, target) 59 end 60end 61 62def installTask(taskName, dir, files) 63 if files.is_a?(String) 64 files = [files] 65 end 66 67 array = [] 68 for f in files do 69 array << File::join(dir, File::basename(f)) 70 installRule(dir, f) 71 end 72 task(taskName => array) 73end 74 75def installTaskRecursive(taskName, dest, src) 76 target = File::join(dest, File::basename(src)) 77 file(target => [dest, src]) do |t| 78 rm_rf(t.name) 79 cp_r(t.prerequisites[1], t.prerequisites[0]) 80 end 81 task(taskName => target) 82end 83 84def bundleDir(dir) 85 file(dir) do |t| 86 sh("/Developer/Tools/SetFile -a B #{dir}") 87 end 88end 89 90def setCurrentVersion(taskName) 91 task(taskName => "#{VERSIONSDIR}/#{FRAMEWORKVERSION}") do |t| 92 for file in Dir::glob("#{t.prerequisites[0]}/*") do 93 filename = File::basename(file) 94 ln_s("Contents/Versions/#{FRAMEWORKVERSION}/#{filename}", "#{BUNDLEDIR}/#{filename}", :force => true) 95 end 96 end 97end 98 99begin 100 if FRAMEWORK 101 directory(BUNDLEDIR = "#{BUILDDIR}#{NAME}.framework") 102 directory(CONTENTSDIR = "#{BUNDLEDIR}/Contents") 103 directory(VERSIONSDIR = "#{CONTENTSDIR}/Versions") 104 directory(VERSIONDIR = "#{VERSIONSDIR}/#{FRAMEWORKVERSION}") 105 directory(RESOURCEDIR = "#{VERSIONDIR}/Resources") 106 directory(HEADERDIR = "#{VERSIONDIR}/Headers") 107 108 @ldflags += " -dynamiclib -install_name @executable_path/../Frameworks/#{VERSIONDIR}/#{NAME}" 109 else 110 directory(BUNDLEDIR = "#{BUILDDIR}#{NAME}.app") 111 directory(CONTENTSDIR = "#{BUNDLEDIR}/Contents") 112 directory(RESOURCEDIR = "#{CONTENTSDIR}/Resources") 113 directory(BINDIR = "#{CONTENTSDIR}/MacOS") 114 directory(FRAMEWORKDIR = "#{CONTENTSDIR}/Frameworks") 115 end 116rescue NameError => e 117 if e.name == :FRAMEWORK 118 FRAMEWORK = false 119 retry 120 else 121 raise e 122 end 123end 124 125bundleDir(BUNDLEDIR) 126task(:bundle => BUNDLEDIR) 127 128############## 129# Frameworks # 130############## 131 132def installFrameworks(task) 133 for name in [@frameworks, @systemFrameworks].flatten 134 framework = nil 135 for path in @frameworkPaths 136 try = "#{File::expand_path(path)}/#{name}.framework" 137 if File::directory?(try) 138 framework = try 139 break 140 end 141 end 142 143 if not framework 144 puts "Framework #{name} missing!" 145 exit(1) 146 end 147 148 @frameworkFlags += " -framework #{name} " 149 @includes += " -I#{framework}/Headers " 150 151 if @frameworks.include?(name) 152 installTaskRecursive(task, FRAMEWORKDIR, framework) 153 bundleDir("#{FRAMEWORKDIR}/#{name}.framework") 154 end 155 end 156 157 for dir in @frameworkPaths 158 @cflags += " -F#{File::expand_path(dir)} " 159 @ldflags += " -F#{File::expand_path(dir)} " 160 end 161end 162 163############### 164# Compilation # 165############### 166 167def cTask(object, source) 168 file(object => source) do |task| 169 sh("#{@cc} #{@commonflags} #{@cflags} #{@includes} #{@defines} -o \"#{task.name}\" -c #{task.prerequisites[0]}") 170 end 171end 172 173def objcTask(object, source) 174 file(object => source) do |task| 175 sh("#{@cc} #{@commonflags} #{@objcflags} #{@includes} #{@defines} -o \"#{task.name}\" -c #{task.prerequisites[0]}") 176 end 177end 178 179def objcxxTask(object, source) 180 file(object => source) do |task| 181 sh("#{@cc} #{@commonflags} #{@cxxflags} #{@objcflags} #{@includes} #{@defines} -o \"#{task.name}\" -c #{task.prerequisites[0]}") 182 end 183end 184 185def cxxTask(object, source) 186 file(object => source) do |task| 187 sh("#{@cc} #{@commonflags} #{@cxxflags} #{@includes} #{@defines} -o \"#{task.name}\" -c #{task.prerequisites[0]}") 188 end 189end 190 191def buildBinary(task, path, file, sources) 192 objects = [] 193 target = "#{path}/#{file}" 194 for source in sources 195 object = "#{BUILDDIR}#{File::dirname(source)}/#{File::basename(source, '.*')}.o" 196 if ['.m'].include?(File::extname(source)) 197 objcTask(object, source) 198 elsif ['.M', '.mm'].include?(File::extname(source)) 199 objcxxTask(object, source) 200 elsif ['.cxx', '.cc', '.cpp', '.C'].include?(File::extname(source)) 201 cxxTask(object, source) 202 else 203 cTask(object, source) 204 end 205 objects.push(object) 206 @cleanfiles.push(object) 207 208 deps = [source] 209 if BUILDDIR != '' 210 dir = "#{BUILDDIR}#{File::dirname(source)}" 211 directory(dir) 212 deps.push(dir) 213 end 214 depfile = "#{BUILDDIR}#{File::dirname(source)}/.#{File::basename(source, '.*')}.dep.mf" 215 file(depfile => deps) do |task| 216 prefix = File::join(File::dirname(task.prerequisites[0]), '') 217 sh("#{@makedepend} -p#{BUILDDIR}#{prefix} -f- -- #{@includes} #{@defines} -- #{task.prerequisites[0]} > #{task.name} 2> /dev/null") 218 end 219 import depfile 220 @cleanfiles.push(depfile) 221 end 222 223 file(target => [path, *objects]) do |task| 224 sh("#{@linker} #{@frameworkFlags} #{@ldflags} #{@libs} -o \"#{task.name}\" #{task.prerequisites[1..-1].join(' ')}") 225 end 226 227 task(task => target) 228end 229