Rakefile 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. #
  2. # Copyright (c) 2008-2015 the Urho3D project.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. require 'pathname'
  23. require 'json'
  24. require 'yaml'
  25. if ENV['IOS'] || ENV['EMSCRIPTEN']
  26. require 'time'
  27. end
  28. # Usage: rake sync (only intended to be used in a fork with remote 'upstream' set to urho3d/Urho3D)
  29. desc 'Fetch and merge upstream urho3d/Urho3D to a Urho3D fork'
  30. task :sync do
  31. system "git fetch upstream && git checkout master && git pull && git merge -m 'Sync at #{Time.now.localtime}.' upstream/master && git push && git checkout -" or abort
  32. end
  33. # Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]
  34. desc 'Create a new project using Urho3D as external library'
  35. task :scaffolding do
  36. abort 'Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]' unless ENV['dir']
  37. abs_path = (ENV['OS'] ? ENV['dir'][1, 1] == ':' : ENV['dir'][0, 1] == '/') ? ENV['dir'] : "#{Dir.pwd}/#{ENV['dir']}"
  38. project = ENV['project'] || 'Scaffolding'
  39. target = ENV['target'] || 'Main'
  40. scaffolding(abs_path, project, target)
  41. abs_path = Pathname.new(abs_path).realpath
  42. puts "\nNew project created in #{abs_path}\n\n"
  43. puts "You may need to first set 'URHO3D_HOME' environment variable or use 'URHO3D_HOME' build option to point to your Urho3D build tree or your custom Urho3D SDK installation location."
  44. puts "Please see http://urho3d.github.io/documentation/HEAD/_using_library.html for more detail. For example:\n\n"
  45. if ENV['OS']
  46. puts "set \"URHO3D_HOME=/path/to/Urho3D/build-tree/or/SDK\"\ncd #{abs_path}\nrake cmake URHO3D_LUAJIT=1\nrake make\n\n"
  47. puts "Alternatively you can call one of the batch files directly, such as, cmake_generic.bat ../native-Build -DURHO3D_LUAJIT=1 and build using VS IDE"
  48. else
  49. puts "export URHO3D_HOME=/path/to/Urho3D/build-tree/or/SDK\ncd #{abs_path}\nrake cmake URHO3D_LUAJIT=1\nrake make\n\n"
  50. puts "Alternatively you can call one of the shell scripts directly, such as, ./cmake_generic.sh ../native-Build -DURHO3D_LUAJIT=1 && cd ../native-Build && make"
  51. end
  52. puts "to get a similar result as the last two rake tasks above.\n\n"
  53. end
  54. # Usage: rake cmake [<generator>] [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [fix_scm]
  55. # e.g.: rake cmake clean android; or rake cmake android URHO3D_LIB_TYPE=SHARED; or rake cmake ios URHO3D_LUA=1 build_tree=~/ios-Build
  56. #
  57. # To avoid repeating the customized build tree locations, you can set and export them as environment variables.
  58. # e.g.: export native_build_tree=~/custom-native-Build android_build_tree=~/custom-android-Build mingw_build_tree=~/custom-mingw-Build rpi_build_tree=~/custom-rpi-Build
  59. # rake cmake rpi URHO3D_LUAJIT=1 URHO3D_LUAJIT_AMALG=1 && rake make rpi
  60. # The RPI build tree will be generated in the ~/custom-rpi-Build and then build from there
  61. desc 'Invoke one of the build scripts with the build tree location predetermined based on the target platform'
  62. task :cmake do
  63. script = 'cmake_generic'
  64. platform = 'native'
  65. build_options = ''
  66. ARGV.each { |option|
  67. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  68. case option
  69. when 'cmake', 'generic'
  70. # do nothing
  71. when 'clean', 'codeblocks', 'eclipse', 'macosx', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015'
  72. script = "cmake_#{option}" unless script == 'cmake_clean'
  73. when 'android', 'emscripten', 'ios', 'mingw', 'rpi'
  74. platform = option
  75. build_options = "#{build_options} -D#{option == 'mingw' ? 'WIN32' : option.upcase}=1" unless script == 'cmake_clean'
  76. script = 'cmake_macosx' if option == 'ios'
  77. script = 'cmake_mingw' if option == 'mingw' && ENV['OS']
  78. when 'fix_scm'
  79. build_options = "#{build_options} --fix-scm" if script == 'cmake_eclipse'
  80. else
  81. build_options = "#{build_options} -D#{option}" unless /build_tree=.*/ =~ option || script == 'cmake_clean'
  82. end
  83. }
  84. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  85. unless ENV['OS']
  86. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  87. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  88. end
  89. system "#{ccache_envvar} ./#{script}#{ENV['OS'] ? '.bat' : '.sh'} \"#{build_tree}\" #{build_options}" or abort
  90. end
  91. # Usage: rake make [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [numjobs=n] [clean_first] [unfilter]
  92. # e.g.: rake make android; or rake make android doc; or rake make ios config=Debug sdk=iphonesimulator build_tree=~/ios-Build
  93. desc 'Build the generated project in its corresponding build tree'
  94. task :make do
  95. numjobs = ENV['numjobs'] || ''
  96. platform = 'native'
  97. cmake_build_options = ''
  98. build_options = ''
  99. unfilter = false
  100. ARGV.each { |option|
  101. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  102. case option
  103. when 'codeblocks', 'eclipse', 'generic', 'macosx', 'make', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015'
  104. # do nothing
  105. when 'android', 'emscripten', 'ios', 'mingw', 'rpi'
  106. platform = option
  107. when 'clean_first'
  108. cmake_build_options = "#{cmake_build_options} --clean-first"
  109. when 'unfilter'
  110. unfilter = true
  111. else
  112. if /(?:config|target)=.*/ =~ option
  113. cmake_build_options = "#{cmake_build_options} --#{option.gsub(/=/, ' ')}"
  114. elsif /(?:build_tree|numjobs)=.*/ !~ option
  115. build_options = "#{build_options} #{/=/ =~ option ? '-' + option.gsub(/=/, ' ') : option}"
  116. end
  117. end
  118. }
  119. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  120. unless ENV['OS']
  121. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  122. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  123. end
  124. if !Dir.glob("#{build_tree}/*.xcodeproj").empty?
  125. # xcodebuild
  126. if !numjobs.empty?
  127. build_options = "-jobs #{numjobs}#{build_options}"
  128. end
  129. filter = !unfilter && system('xcpretty -v >/dev/null 2>&1') ? '|xcpretty -c && exit ${PIPESTATUS[0]}' : ''
  130. elsif !Dir.glob("#{build_tree}/*.sln").empty?
  131. # msbuild
  132. numjobs = ":#{numjobs}" unless numjobs.empty?
  133. build_options = "/maxcpucount#{numjobs}#{build_options}"
  134. filter = unfilter ? '' : '/nologo /verbosity:minimal'
  135. elsif !Dir.glob("#{build_tree}/*.ninja").empty?
  136. # ninja
  137. if !numjobs.empty?
  138. build_options = "-j#{numjobs}#{build_options}"
  139. end
  140. filter = ''
  141. else
  142. # make
  143. if numjobs.empty?
  144. case RUBY_PLATFORM
  145. when /linux/
  146. numjobs = (platform == 'emscripten' ? `grep 'core id' /proc/cpuinfo |sort |uniq |wc -l` : `grep -c processor /proc/cpuinfo`).chomp
  147. when /darwin/
  148. numjobs = `sysctl -n hw.#{platform == 'emscripten' ? 'physical' : 'logical'}cpu`.chomp
  149. when /win32|mingw|mswin/
  150. require 'win32ole'
  151. WIN32OLE.connect('winmgmts://').ExecQuery("select NumberOf#{platform == 'emscripten' ? '' : 'Logical'}Processors from Win32_ComputerSystem").each { |out| numjobs = platform == 'emscripten' ? out.NumberOfProcessors : out.NumberOfLogicalProcessors }
  152. else
  153. numjobs = 1
  154. end
  155. end
  156. build_options = "-j#{numjobs}#{build_options}"
  157. filter = ''
  158. end
  159. system "cd \"#{build_tree}\" && #{ccache_envvar} cmake --build . #{cmake_build_options} -- #{build_options} #{filter}" or abort
  160. end
  161. # Usage: rake android [parameter='--es pickedLibrary Urho3DPlayer'] [intent=.SampleLauncher] [package=com.github.urho3d] [success_indicator='Initialized engine'] [payload='sleep 30'] [api=19] [abi=armeabi-v7a] [avd=test_#{api}_#{abi}] [retries=10] [retry_interval=10]
  162. desc 'Test run already installed APK in Android (virtual) device, default to Urho3D Samples APK if no parameter is given'
  163. task :android do
  164. parameter = ENV['parameter'] || '--es pickedLibrary Urho3DPlayer'
  165. intent = ENV['intent'] || '.SampleLauncher'
  166. package = ENV['package'] || 'com.github.urho3d'
  167. success_indicator = ENV['success_indicator'] || 'Initialized engine'
  168. payload = ENV['payload'] || 'sleep 30'
  169. api = ENV['api'] || 19
  170. abi = ENV['abi'] || 'armeabi-v7a'
  171. avd = ENV['avd'] || "test_#{api}_#{abi}"
  172. retries = ENV['retries'] || 10 # minutes
  173. retry_interval = ENV['retry_interval'] || 10 # seconds
  174. android_prepare_device api, abi, avd or abort 'Failed to prepare Android (virtual) device for test run'
  175. android_wait_for_device retries, retry_interval or abort 'Failed to start Android (virtual) device'
  176. android_test_run parameter, intent, package, success_indicator, payload or abort "Failed to test run #{package}/#{intent}, make sure the APK has been installed"
  177. end
  178. # Usage: NOT intended to be used manually (if you insist then try: rake ci)
  179. desc 'Configure, build, and test Urho3D project'
  180. task :ci do
  181. # Skip if only performing CI for selected branches and the current branch is not in the list
  182. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  183. next if matched && !matched[1].split(/[ ,]/).reject!(&:empty?).map { |i| /#{i}/ =~ ENV['TRAVIS_BRANCH'] }.any?
  184. # Obtain our custom data, if any
  185. data = YAML::load(File.open(".travis.yml"))['data']
  186. data['excluded_sample'].each { |name| ENV["EXCLUDE_SAMPLE_#{name}"] = '1' } if data && data['excluded_sample']
  187. # Unshallow the clone's history when necessary
  188. if ENV['CI'] && ENV['PACKAGE_UPLOAD'] && !ENV['RELEASE_TAG']
  189. system 'git fetch --unshallow' or abort 'Failed to unshallow cloned repository'
  190. end
  191. # Packaging always use Release configuration
  192. if ENV['PACKAGE_UPLOAD']
  193. $configuration = 'Release'
  194. $testing = 0
  195. else
  196. $configuration = ENV['CI'] && ENV['USE_CCACHE'].to_i > 0 ? 'Release' : 'Debug' # Aways use a same build configuration to keep ccache's cache size small when on Travis CI
  197. # Only 64-bit Linux environment with virtual framebuffer X server support and not MinGW build; or OSX build environment and not iOS build; or Emscripten build environment are capable to run tests
  198. $testing = (ENV['LINUX'] && !ENV['URHO3D_64BIT']) || (ENV['OSX'] && ENV['IOS'].to_i != 1) || ENV['EMSCRIPTEN'] ? 1 : 0
  199. if $testing
  200. ENV['URHO3D_PREFIX_PATH'] = `pwd`.chomp + '/bin'
  201. end
  202. end
  203. # Define the build option string only when the override environment variable is given
  204. $build_options = "-DWIN32=#{ENV['WINDOWS']}" if ENV['WINDOWS']
  205. $build_options = "#{$build_options} -DANDROID_ABI=#{ENV['ABI']}" if ENV['ABI']
  206. $build_options = "#{$build_options} -DANDROID_NATIVE_API_LEVEL=#{ENV['API']}" if ENV['API']
  207. ['URHO3D_64BIT', 'URHO3D_LIB_TYPE', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_TEST_TIMEOUT', 'ANDROID', 'RPI', 'RPI_ABI', 'EMSCRIPTEN', 'EMSCRIPTEN_SHARE_DATA', 'EMSCRIPTEN_EMRUN_BROWSER'].each { |var| $build_options = "#{$build_options} -D#{var}=#{ENV[var]}" if ENV[var] }
  208. if ENV['XCODE']
  209. # xcodebuild
  210. xcode_ci
  211. else
  212. # GCC or Clang
  213. makefile_ci
  214. end
  215. end
  216. # Usage: NOT intended to be used manually
  217. desc 'Setup build cache'
  218. task :ci_setup_cache do
  219. # Use internal cache store instead of using Travis CI one (this is a workaround for using ccache on Travis CI legacy build infra)
  220. if ENV['USE_CCACHE'].to_i == 2
  221. puts 'Setting up build cache'
  222. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  223. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  224. matched = /.*-([^-]+-[^-]+)$/.match(ENV['TRAVIS_BRANCH'])
  225. base_mirror = matched ? matched[1] : nil
  226. # Do not abort even when it fails here
  227. system "if ! `git clone -q --depth 1 --branch #{ENV['TRAVIS_BRANCH']}#{job_number} https://github.com/#{repo_slug} ~/.ccache 2>/dev/null`; then if ! [ #{base_mirror} ] || ! `git clone -q --depth 1 --branch #{base_mirror}#{job_number} https://github.com/#{repo_slug} ~/.ccache 2>/dev/null`; then git clone -q --depth 1 https://github.com/#{repo_slug} ~/.ccache 2>/dev/null; fi && cd ~/.ccache && git checkout -qf -b #{ENV['TRAVIS_BRANCH']}#{job_number}; fi && find ~/.ccache -type f |xargs touch -r $(which ccache)"
  228. end
  229. # Clear ccache on demand
  230. system "ccache -z -M 100M #{/\[ccache clear\]/ =~ ENV['COMMIT_MESSAGE'] ? '-C' : ''}"
  231. end
  232. # Usage: NOT intended to be used manually
  233. desc 'Teardown build cache'
  234. task :ci_teardown_cache do
  235. # Upload cache to internal cache store if it is our own
  236. if ENV['USE_CCACHE'].to_i == 2
  237. puts 'Storing build cache'
  238. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  239. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  240. # Do not abort even when it fails here
  241. system "cd ~/.ccache && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/#{repo_slug} && git add -A . && git commit --amend -qm 'Travis CI: cache update at #{Time.now.utc}.' && git push -qf -u origin #{ENV['TRAVIS_BRANCH']}#{job_number} >/dev/null 2>&1"
  242. end
  243. system 'ccache -s'
  244. end
  245. # Usage: NOT intended to be used manually
  246. desc 'Update site documentation to GitHub Pages'
  247. task :ci_site_update do
  248. # Skip when :ci rake task was skipped
  249. next unless Dir.exists?('../Build')
  250. # Pull or clone
  251. system 'cd ../doc-Build 2>/dev/null && git pull -q -r || git clone --depth 1 -q https://github.com/urho3d/urho3d.github.io.git ../doc-Build' or abort 'Failed to pull/clone'
  252. # Update credits from README.md to about.md
  253. system "ruby -lne 'BEGIN { credits = false }; puts $_ if credits; credits = true if /bugfixes by:/; credits = false if /^$/' README.md |ruby -i -le 'credits = STDIN.read; puts ARGF.read.gsub(/(?<=bugfixes by\n).*?(?=##)/m, credits)' ../doc-Build/about.md" or abort 'Failed to update credits'
  254. # Setup doxygen to use minimal theme
  255. system "ruby -i -pe 'BEGIN { a = {%q{HTML_HEADER} => %q{minimal-header.html}, %q{HTML_FOOTER} => %q{minimal-footer.html}, %q{HTML_STYLESHEET} => %q{minimal-doxygen.css}, %q{HTML_COLORSTYLE_HUE} => 200, %q{HTML_COLORSTYLE_SAT} => 0, %q{HTML_COLORSTYLE_GAMMA} => 20, %q{DOT_IMAGE_FORMAT} => %q{svg}, %q{INTERACTIVE_SVG} => %q{YES}} }; a.each {|k, v| gsub(/\#{k}\s*?=.*?\n/, %Q{\#{k} = \#{v}\n}) }' ../Build/Docs/Doxyfile" or abort 'Failed to setup doxygen configuration file'
  256. system 'cp ../doc-Build/_includes/Doxygen/minimal-* ../Build/Docs' or abort 'Failed to copy minimal-themed template'
  257. release = ENV['RELEASE_TAG'] || 'HEAD'
  258. unless release == 'HEAD'
  259. system "mkdir -p ../doc-Build/documentation/#{release}" or abort 'Failed to create directory for new document version'
  260. system "ruby -i -pe 'gsub(/HEAD/, %q{#{release}})' ../Build/Docs/minimal-header.html" or abort 'Failed to update document version in YAML Front Matter block'
  261. append_new_release release or abort 'Failed to add new release to document data file'
  262. end
  263. # Generate and sync doxygen pages
  264. system "cd ../Build && make -j$NUMJOBS doc >/dev/null 2>&1 && ruby -i -pe 'gsub(/(<\\/?h)3([^>]*?>)/, %q{\\14\\2}); gsub(/(<\\/?h)2([^>]*?>)/, %q{\\13\\2}); gsub(/(<\\/?h)1([^>]*?>)/, %q{\\12\\2})' Docs/html/_*.html && rsync -a --delete Docs/html/ ../doc-Build/documentation/#{release}" or abort 'Failed to generate/rsync doxygen pages'
  265. # Supply GIT credentials and push site documentation to urho3d/urho3d.github.io.git
  266. system "cd ../doc-Build && pwd && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/urho3d/urho3d.github.io.git && git add -A . && ( git commit -qm \"Travis CI: site documentation update at #{Time.now.utc}.\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT\n\nMessage: $COMMIT_MESSAGE\" || true) && git push -q >/dev/null 2>&1" or abort 'Failed to update site'
  267. unless ENV['RELEASE_TAG'] || `git fetch -qf origin #{ENV['TRAVIS_BRANCH']}; git log -1 --pretty=format:'%H' FETCH_HEAD` != ENV['TRAVIS_COMMIT']
  268. # Automatically give instruction to do packaging when API has changed, unless the instruction is already given in this commit
  269. if ENV['PACKAGE_UPLOAD']
  270. instruction = 'skip'
  271. else
  272. instruction = 'package'
  273. end
  274. # Supply GIT credentials and push API documentation to urho3d/Urho3D.git
  275. system 'pwd && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git && git add Docs/*API*'
  276. if system("git commit -qm 'Travis CI: API documentation update at #{Time.now.utc}.\n[ci #{instruction}]'") && !ENV['PACKAGE_UPLOAD']
  277. bump_soversion 'Source/Urho3D/.soversion' or abort 'Failed to bump soversion'
  278. system "git add Source/Urho3D/.soversion && git commit --amend -qm 'Travis CI: API documentation update at #{Time.now.utc}.\n[ci #{instruction}]'" or abort 'Failed to stage .soversion file'
  279. system "git push origin HEAD:#{ENV['TRAVIS_BRANCH']} -q >/dev/null 2>&1" or abort 'Failed to update API documentation'
  280. end
  281. end
  282. end
  283. # Usage: NOT intended to be used manually
  284. desc 'Update Emscripten HTML5 samples to GitHub Pages'
  285. task :ci_emscripten_samples_update do
  286. # Pull or clone
  287. system 'cd ../doc-Build 2>/dev/null && git pull -q -r || git clone --depth 1 -q https://github.com/urho3d/urho3d.github.io.git ../doc-Build' or abort 'Failed to pull/clone'
  288. # Sync Emscripten samples
  289. system "rsync -a --delete --exclude tool ../Build/bin/ ../doc-Build/samples" or abort 'Failed to rsync Emscripten samples'
  290. # Update Emscripten json data file
  291. update_emscripten_data or abort 'Failed to update Emscripten json data file'
  292. # Supply GIT credentials and push the changes to urho3d/urho3d.github.io.git
  293. system "cd ../doc-Build && git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/urho3d/urho3d.github.io.git && git add -A . && ( git commit -qm \"Travis CI: Emscripten samples update at #{Time.now.utc}.\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT\n\nMessage: $COMMIT_MESSAGE\" || true) && git push -q >/dev/null 2>&1" or abort 'Failed to update Emscripten samples'
  294. end
  295. # Usage: NOT intended to be used manually
  296. desc 'Create all CI mirror branches'
  297. task :ci_create_mirrors do
  298. # Skip if there are more commits since this one
  299. abort 'Skipped creating mirror branches due to moving HEAD' unless `git fetch -qf origin #{ENV['TRAVIS_PULL_REQUEST'] == 'false' ? ENV['TRAVIS_BRANCH'] : %Q{+refs/pull/#{ENV['TRAVIS_PULL_REQUEST']}/head'}}; git log -1 --pretty=format:'%H' FETCH_HEAD` == ENV['TRAVIS_COMMIT']
  300. system 'git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git'
  301. scan = ENV['PACKAGE_UPLOAD'] || /\[ci scan\]/ =~ ENV['COMMIT_MESSAGE'] # Limit the frequency of scanning
  302. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  303. ci_only = matched ? matched[1].split(/[ ,]/).reject!(&:empty?) : nil
  304. ci_only.push('Coverity-Scan') if ci_only && scan
  305. stream = YAML::load_stream(File.open('.travis.yml'))
  306. notifications = stream[0]['notifications']
  307. notifications['email']['recipients'] = `git show -s --format='%ae %ce' #{ENV['TRAVIS_COMMIT']}`.chomp.split.uniq unless notifications['email']['recipients']
  308. stream.drop(1).each { |doc| branch = doc.delete('branch'); ci = branch['name']; ci_branch = ENV['RELEASE_TAG'] || (ENV['TRAVIS_BRANCH'] == 'master' && ENV['TRAVIS_PULL_REQUEST'] == 'false') ? ci : (ENV['TRAVIS_PULL_REQUEST'] == 'false' ? "#{ENV['TRAVIS_BRANCH']}-#{ci}" : "PR ##{ENV['TRAVIS_PULL_REQUEST']}-#{ci}"); unless (ci_only && ci_only.map { |i| /#{i}/ =~ ci }.any?) || (!ci_only && (branch['active'] || (scan && /Scan/ =~ ci))); system "if git fetch origin #{ci_branch}:#{ci_branch} 2>/dev/null; then git push -qf origin --delete #{ci_branch}; fi"; next; end; lastjob = doc['matrix'] && doc['matrix']['include'] ? doc['matrix']['include'].length : (doc['env']['matrix'] ? doc['env']['matrix'].length : 1); doc['after_script'] = [*doc['after_script']] << (lastjob == 1 ? '%s' : "if [ ${TRAVIS_JOB_NUMBER##*.} == #{lastjob} ]; then %s; fi") % 'rake ci_delete_mirror'; doc['notifications'] = notifications unless doc['notifications']; File.open('.travis.yml.doc', 'w') { |file| file.write doc.to_yaml }; system "git checkout -B #{ci_branch} && rm .travis.yml && mv .travis.yml.doc .travis.yml && git add -A . && git commit -qm '#{branch['description']}' && git push -qf -u origin #{ci_branch} >/dev/null 2>&1 && git checkout -q -" or abort "Failed to create #{ci_branch} mirror branch" }
  309. end
  310. # Usage: NOT intended to be used manually
  311. desc 'Delete CI mirror branch'
  312. task :ci_delete_mirror do
  313. # Skip if there are more commits since this one or if this is a release build
  314. matched = /(.*)-[^-]+-[^-]+$/.match(ENV['TRAVIS_BRANCH'])
  315. base_branch = matched ? matched[1] : 'master' # Assume 'master' is the default branch name
  316. abort "Skipped deleting #{ENV['TRAVIS_BRANCH']} mirror branch" unless `git fetch -qf origin #{/^PR #/ =~ base_branch ? %Q{+refs/pull/#{ENV['TRAVIS_PULL_REQUEST']}/merge'} : base_branch}; git log -1 --pretty=format:'%H' FETCH_HEAD` == `git show -s --format='%H' #{ENV['TRAVIS_COMMIT']}`.rstrip && !ENV['RELEASE_TAG']
  317. system 'git config user.name $GIT_NAME && git config user.email $GIT_EMAIL && git remote set-url --push origin https://[email protected]/$TRAVIS_REPO_SLUG.git'
  318. system "git push -qf origin --delete #{ENV['TRAVIS_BRANCH']}" or abort "Failed to delete #{ENV['TRAVIS_BRANCH']} mirror branch"
  319. end
  320. # Usage: NOT intended to be used manually
  321. desc 'Make binary package and upload it to a designated central hosting server'
  322. task :ci_package_upload do
  323. # Skip when :ci rake task was skipped
  324. next unless Dir.exists?('../Build')
  325. if ENV['XCODE']
  326. $configuration = 'Release'
  327. $testing = 0
  328. end
  329. # Generate the documentation if necessary
  330. if ENV['SITE_UPDATE']
  331. if File.exist?('.site_updated')
  332. # Skip if site is already updated before
  333. ENV['SITE_UPDATE'] = nil
  334. end
  335. else
  336. system 'echo Generate documentation'
  337. if ENV['XCODE']
  338. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj', 'doc', '>/dev/null') or abort 'Failed to generate documentation'
  339. else
  340. system 'cd ../Build && make -j$NUMJOBS doc >/dev/null' or abort 'Failed to generate documentation'
  341. end
  342. end
  343. # Make the package
  344. if ENV['IOS']
  345. # Skip Mach-O universal binary build if Travis-CI VM took too long to get here, as otherwise overall build time may exceed 50 minutes time limit
  346. if ENV['CI_START_TIME'] then
  347. elapsed_time = (Time.now - Time.at(ENV['CI_START_TIME'].to_i)) / 60
  348. puts "\niOS checkpoint reached, elapsed time: #{elapsed_time}\n\n"
  349. end
  350. if !ENV['CI_START_TIME'] || elapsed_time < 15 # minutes
  351. # Build Mach-O universal binary consisting of iphoneos (universal ARM archs including 'arm64' if 64-bit is enabled) and iphonesimulator (i386 arch and also x86_64 arch if 64-bit is enabled)
  352. system 'echo Rebuild Urho3D library as Mach-O universal binary'
  353. xcode_build(0, '../Build/Urho3D.xcodeproj', 'Urho3D_universal') or abort 'Failed to build Mach-O universal binary'
  354. end
  355. # There is a bug in CMake/CPack that causes the 'package' target failed to build for IOS platform, workaround by calling cpack directly
  356. system 'cd ../Build && cpack -G TGZ 2>/dev/null' or abort 'Failed to make binary package'
  357. elsif ENV['XCODE']
  358. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj', 'package') or abort 'Failed to make binary package'
  359. else
  360. if ENV['ANDROID'] && !ENV['NO_SDK_SYSIMG']
  361. system "cd ../Build && android update project -p . -t $(android list target |grep android-$API |cut -d ' ' -f2) && ant debug" or abort 'Failed to make Urho3D Samples APK'
  362. end
  363. if ENV['URHO3D_USE_LIB64_RPM']
  364. system "cd ../Build && cmake . -DURHO3D_USE_LIB64_RPM=#{ENV['URHO3D_USE_LIB64_RPM']}" or abort 'Failed to reconfigure to generate 64-bit RPM package'
  365. end
  366. wrapper = ENV['URHO3D_64BIT'] || ENV['RPI'] ? 'setarch i686' : ''
  367. system "cd ../Build && #{wrapper} make package" or abort 'Failed to make binary package'
  368. end
  369. # Determine the upload location
  370. setup_digital_keys
  371. if !ENV['RELEASE_TAG']
  372. upload_dir = "/home/frs/project/#{ENV['TRAVIS_REPO_SLUG']}/Snapshots"
  373. if ENV['SITE_UPDATE']
  374. # Download source packages from GitHub
  375. system "export SNAPSHOT_VER=$(git describe $TRAVIS_COMMIT |ruby -pe 'gsub(/-(?!g)/, %q{.})'); wget -q https://github.com/$TRAVIS_REPO_SLUG/tarball/$TRAVIS_COMMIT -O Urho3D-$SNAPSHOT_VER-Source-snapshot.tar.gz && wget -q https://github.com/$TRAVIS_REPO_SLUG/zipball/$TRAVIS_COMMIT -O Urho3D-$SNAPSHOT_VER-Source-snapshot.zip" or abort 'Failed to get source packages'
  376. # Only keep the snapshots from the last 30 revisions
  377. system "for v in $(sftp [email protected] <<EOF |tr ' ' '\n' |grep Urho3D- |cut -d '-' -f1,2 |uniq |tail -n +31
  378. cd #{upload_dir}
  379. ls -1r
  380. bye
  381. EOF
  382. ); do echo rm #{upload_dir}/${v}*; done |sftp -b - [email protected]" or abort 'Failed to housekeep snapshots'
  383. end
  384. else
  385. upload_dir = "/home/frs/project/#{ENV['TRAVIS_REPO_SLUG']}/#{ENV['RELEASE_TAG']}"
  386. if ENV['SITE_UPDATE']
  387. # Download source packages from GitHub
  388. system 'wget -q https://github.com/$TRAVIS_REPO_SLUG/archive/$RELEASE_TAG.tar.gz -O Urho3D-$RELEASE_TAG-Source.tar.gz && wget -q https://github.com/$TRAVIS_REPO_SLUG/archive/$RELEASE_TAG.zip -O Urho3D-$RELEASE_TAG-Source.zip' or abort 'Failed to get source packages'
  389. end
  390. # Make sure the release directory exists remotely, do this in all the build jobs as we don't know which one would start uploading first
  391. system "sftp [email protected] <<EOF >/dev/null 2>&1
  392. mkdir #{upload_dir}
  393. bye
  394. EOF" or abort 'Failed to create release directory remotely'
  395. end
  396. if ENV['SITE_UPDATE']
  397. # Upload the source package
  398. system "scp Urho3D-* [email protected]:#{upload_dir}" or abort 'Failed to upload source package'
  399. # Sync readme and license files, just in case they are updated in the repo
  400. system 'for f in README.md License.txt; do mtime=$(git log --format=%ai -n1 $f); touch -d "$mtime" $f; done' or abort 'Failed to acquire file modified time'
  401. system 'rsync -e ssh -az README.md License.txt [email protected]:/home/frs/project/$TRAVIS_REPO_SLUG' or abort 'Failed to sync readme and license files'
  402. # Mark that the site has been updated
  403. File.open('.site_updated', 'w') {}
  404. end
  405. # Upload the package
  406. system "scp ../Build/Urho3D-* [email protected]:#{upload_dir} && rm ../Build/Urho3D-*" or abort 'Failed to upload binary package'
  407. end
  408. def scaffolding(dir, project = 'Scaffolding', target = 'Main')
  409. build_script = <<EOF
  410. # Set project name
  411. project (#{project})
  412. # Set minimum version
  413. cmake_minimum_required (VERSION 2.8.6)
  414. if (COMMAND cmake_policy)
  415. cmake_policy (SET CMP0003 NEW)
  416. if (CMAKE_VERSION VERSION_GREATER 2.8.12 OR CMAKE_VERSION VERSION_EQUAL 2.8.12)
  417. # INTERFACE_LINK_LIBRARIES defines the link interface
  418. cmake_policy (SET CMP0022 NEW)
  419. endif ()
  420. if (CMAKE_VERSION VERSION_GREATER 3.0.0 OR CMAKE_VERSION VERSION_EQUAL 3.0.0)
  421. # Disallow use of the LOCATION target property - therefore we set to OLD as we still need it
  422. cmake_policy (SET CMP0026 OLD)
  423. # MACOSX_RPATH is enabled by default
  424. cmake_policy (SET CMP0042 NEW)
  425. endif ()
  426. endif ()
  427. # Set CMake modules search path
  428. set (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
  429. # Include Urho3D CMake common module
  430. include (Urho3D-CMake-common)
  431. # Find Urho3D library
  432. find_package (Urho3D REQUIRED)
  433. include_directories (${URHO3D_INCLUDE_DIRS})
  434. # Define target name
  435. set (TARGET_NAME #{target})
  436. # Define source files
  437. define_source_files ()
  438. # Setup target with resource copying
  439. setup_main_executable ()
  440. # Setup test cases
  441. if (URHO3D_ANGELSCRIPT)
  442. setup_test (NAME ExternalLibAS OPTIONS Scripts/12_PhysicsStressTest.as -w)
  443. endif ()
  444. if (URHO3D_LUA)
  445. setup_test (NAME ExternalLibLua OPTIONS LuaScripts/12_PhysicsStressTest.lua -w)
  446. endif ()
  447. EOF
  448. # TODO: Rewrite in pure Ruby when it supports symlink creation on Windows platform
  449. if ENV['OS']
  450. system("@echo off && mkdir '#{dir}'\\bin && copy Source\\Tools\\Urho3DPlayer\\Urho3DPlayer.* '#{dir}' >nul && (for %f in (*.bat Rakefile) do mklink '#{dir}'\\%f %cd%\\%f >nul) && mklink /D '#{dir}'\\CMake %cd%\\CMake && (for %d in (CoreData,Data) do mklink /D '#{dir}'\\bin\\%d %cd%\\bin\\%d >nul)") && File.write("#{dir}/CMakeLists.txt", build_script) or abort 'Failed to create new project using Urho3D as external library'
  451. else
  452. system("bash -c \"mkdir -p '#{dir}'/bin && cp Source/Tools/Urho3DPlayer/Urho3DPlayer.* '#{dir}' && for f in {.,}*.sh Rakefile CMake; do ln -sf `pwd`/\\$f '#{dir}'; done && ln -sf `pwd`/bin/{Core,}Data '#{dir}'/bin\"") && File.write("#{dir}/CMakeLists.txt", build_script) or abort 'Failed to create new project using Urho3D as external library'
  453. end
  454. end
  455. def makefile_ci
  456. if (ENV['WINDOWS'] && ENV['CI']) || (ENV['ANDROID'] && ENV['ABI'] == 'arm64-v8a') || ENV['EMSCRIPTEN']
  457. # LuaJIT on MinGW build is not possible on Ubuntu 12.04 LTS as its GCC cross-compiler version is too old
  458. # The upstream LuaJIT library does not support Android arm64-v8a ABI at the moment
  459. # LuaJIT on Emscripten is not possible
  460. # Fallback to use Lua library instead
  461. jit = ''
  462. amalg = ''
  463. else
  464. jit = 'JIT'
  465. amalg = '-DURHO3D_LUAJIT_AMALG=1'
  466. end
  467. system "./cmake_generic.sh ../Build #{$build_options} -DURHO3D_LUA#{jit}=1 #{amalg} -DURHO3D_SAMPLES=1 -DURHO3D_TOOLS=1 -DURHO3D_EXTRAS=1 -DURHO3D_TESTING=#{$testing} -DCMAKE_BUILD_TYPE=#{$configuration}" or abort 'Failed to configure Urho3D library build'
  468. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD'] # Skip APK test run when packaging
  469. android_prepare_device ENV['API'], ENV['ABI'], ENV['AVD'] or abort 'Failed to prepare Android (virtual) device for test run'
  470. end
  471. # For Emscripten CI build, skip make test and/or scaffolding test if Travis-CI VM took too long to get here, as otherwise overall build time may exceed 50 minutes time limit
  472. test = $testing == 1 ? (ENV['CI'] && ENV['EMSCRIPTEN'] ? '&& if (( $((($(date +%%s)-$CI_START_TIME)/60)) < 25 )); then %s; fi' : '&& %s') % 'make test' : ''
  473. system "cd ../Build && make -j$NUMJOBS #{test}" or abort 'Failed to build or test Urho3D library'
  474. if ENV['CI_START_TIME'] then
  475. elapsed_time = (Time.now - Time.at(ENV['CI_START_TIME'].to_i)) / 60
  476. puts "\nEmscripten checkpoint reached, elapsed time: #{elapsed_time}\n"
  477. end
  478. unless ENV['CI'] && ENV['EMSCRIPTEN'] && (ENV['PACKAGE_UPLOAD'] || elapsed_time > 40) # For Emscripten, skip scaffolding test when packaging or running out of time
  479. # Create a new project on the fly that uses newly built Urho3D library in the build tree
  480. test.sub!(/< 25/, '< 43')
  481. scaffolding "../Build/generated/UsingBuildTree"
  482. system "cd ../Build/generated/UsingBuildTree && echo '\nExternal project referencing Urho3D library in its build tree' && ./cmake_generic.sh . #{$build_options} -DURHO3D_HOME=../.. -DURHO3D_LUA#{jit}=1 -DURHO3D_TESTING=#{$testing} -DCMAKE_BUILD_TYPE=#{$configuration} && make -j$NUMJOBS #{test}" or abort 'Failed to configure/build/test temporary project using Urho3D as external library'
  483. ENV['DESTDIR'] = ENV['HOME'] || Dir.home
  484. puts "\nInstalling Urho3D SDK to #{ENV['DESTDIR']}/usr/local...\n" # The default CMAKE_INSTALL_PREFIX is /usr/local
  485. system 'cd ../Build && make -j$NUMJOBS install >/dev/null' or abort 'Failed to install Urho3D SDK'
  486. # Create a new project on the fly that uses newly installed Urho3D SDK
  487. test.sub!(/< 43/, '< 48')
  488. scaffolding "../Build/generated/UsingSDK"
  489. system "export URHO3D_HOME=~/usr/local && cd ../Build/generated/UsingSDK && echo '\nExternal project referencing Urho3D SDK' && ./cmake_generic.sh . #{$build_options} -DURHO3D_LUA#{jit}=1 -DURHO3D_TESTING=#{$testing} -DCMAKE_BUILD_TYPE=#{$configuration} && make -j$NUMJOBS #{test}" or abort 'Failed to configure/build/test temporary project using Urho3D as external library'
  490. end
  491. # Make, deploy, and test run Android APK in an Android (virtual) device
  492. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD']
  493. system "echo '\nTest deploying and running Urho3D Samples APK...' && cd ../Build && android update project -p . -t $( android list target |grep android-$API |cut -d ' ' -f2 ) && ant debug" or abort 'Failed to make Urho3D Samples APK'
  494. if android_wait_for_device
  495. system "cd ../Build && ant -Dadb.device.arg='-s #{$specific_device}' installd" or abort 'Failed to deploy Urho3D Samples APK'
  496. android_test_run or abort 'Failed to test run Urho3D Samples APK'
  497. else
  498. puts 'Skipped test running Urho3D Samples APK as emulator failed to start in time'
  499. end
  500. end
  501. end
  502. def android_find_device api = nil, abi = nil
  503. # Return the previously found matching device or if not found yet then try to find the matching device now
  504. return $specific_device if $specific_device
  505. wait = api ? '' : 'wait-for-device'
  506. $specific_api = api.to_s if api
  507. $specific_abi = abi.to_s if abi
  508. for i in `adb #{wait} devices |tail -n +2`.split "\n"
  509. device = i.split.first
  510. if `adb -s #{device} wait-for-device shell getprop ro.build.version.sdk`.chomp == $specific_api && `adb -s #{device} shell getprop ro.product.cpu.abi`.chomp == $specific_abi
  511. return $specific_device = device
  512. end
  513. end
  514. nil
  515. end
  516. def android_prepare_device api, abi = 'armeabi-v7a', name = 'test'
  517. system 'if ! ps |grep -cq adb; then adb start-server; fi'
  518. if !android_find_device api, abi
  519. # Don't have any matching (virtual) device attached, try to attach the named device (create the named device as AVD if necessary)
  520. if !system "android list avd |grep -cq 'Name: #{name}$'"
  521. system "echo 'no' |android create avd -n #{name} -t android-#{api} --abi #{abi}" or abort "Failed to create '#{name}' Android virtual device"
  522. end
  523. system "if [ $CI ]; then export OPTS='-no-skin -no-audio -no-window -no-boot-anim -gpu off'; else export OPTS='-gpu on'; fi; emulator -avd #{name} $OPTS &"
  524. end
  525. return 0
  526. end
  527. def android_wait_for_device retries = -1, retry_interval = 10, package = 'android.process.acore' # Waiting for HOME by default
  528. # Wait until the indicator process is running or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
  529. str = "\nWaiting for device..."
  530. thread = Thread.new { android_find_device }; sleep 0.5
  531. process_ready = false
  532. retries = retries * 60 / retry_interval unless retries == -1
  533. until retries == 0
  534. if thread.status == false
  535. thread.join
  536. break if process_ready
  537. process_ready = thread = Thread.new { `adb -s #{$specific_device} shell 'until ps |grep -c #{package} >/dev/null; do sleep #{retry_interval}; done; while ps |grep -c bootanimation >/dev/null; do sleep 1; done'` }; sleep 0.5
  538. next
  539. end
  540. print str; str = '.'; $stdout.flush # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
  541. sleep retry_interval
  542. retries -= 1 if retries > 0
  543. end
  544. puts "\n\n" if str == '.'; $stdout.flush
  545. return retries == 0 ? nil : 0
  546. end
  547. def android_test_run parameter = '--es pickedLibrary Urho3DPlayer', intent = '.SampleLauncher', package = 'com.github.urho3d', success_indicator = 'Added resource path /apk/CoreData/', payload = 'sleep 30'
  548. # The device should have been found at this point
  549. return nil unless $specific_device
  550. # Capture adb's stdout and interpret it because adb neither uses stderr nor returns proper exit code on error
  551. begin
  552. IO.popen("adb -s #{$specific_device} shell <<EOF
  553. # Try to unlock the device just in case it is locked
  554. input keyevent 82; input keyevent 4
  555. # Clear the log
  556. logcat -c
  557. # Start the app
  558. am start -a android.intent.action.MAIN -n #{package}/#{intent} #{parameter}
  559. # Wait until the process is running
  560. until ps |grep -c #{package} 1>/dev/null; do sleep 1; done
  561. # Execute the payload
  562. #{payload}
  563. # Exit and stop the app
  564. input keyevent 4 && am force-stop #{package}
  565. # Dump the log
  566. logcat -d
  567. # Bye bye
  568. exit
  569. ##
  570. EOF") { |stdout| echo = false; while output = stdout.gets do if echo && /#\s#/ !~ output then puts output else echo = true if /^##/ =~ output end; return nil if /^error/i =~ output end }
  571. # Result of the test run is determined based on the presence of the success indicator string in the log
  572. system "adb -s #{$specific_device} logcat -d |grep -cq '#{success_indicator}'"
  573. rescue
  574. nil
  575. end
  576. end
  577. def wait_for_block comment = '', retries = -1, retry_interval = 60, exit_code_sym = 'exit_code', &block
  578. # Wait until the code block is completed or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
  579. thread = Thread.new &block
  580. str = comment
  581. retries = retries * 60 / retry_interval unless retries == -1
  582. until retries == 0
  583. if thread.status == false
  584. thread.join
  585. break
  586. end
  587. print str; str = '.'; $stdout.flush # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
  588. sleep retry_interval
  589. retries -= 1 if retries > 0
  590. end
  591. puts "\n" if str == '.'; $stdout.flush
  592. return retries == 0 ? nil : (exit_code_sym ? thread[exit_code_sym] : 0)
  593. end
  594. def xcode_ci
  595. if ENV['IOS']
  596. # IOS platform does not support LuaJIT
  597. jit = ''
  598. amalg = ''
  599. deployment_target = "-DIPHONEOS_DEPLOYMENT_TARGET=#{ENV['DEPLOYMENT_TARGET']}"
  600. else
  601. jit = 'JIT'
  602. amalg = '-DURHO3D_LUAJIT_AMALG=1'
  603. deployment_target = "-DCMAKE_OSX_DEPLOYMENT_TARGET=#{ENV['DEPLOYMENT_TARGET']}"
  604. end
  605. system "./cmake_macosx.sh ../Build -DIOS=$IOS #{deployment_target} #{$build_options} -DURHO3D_LUA#{jit}=1 #{amalg} -DURHO3D_SAMPLES=1 -DURHO3D_TOOLS=1 -DURHO3D_EXTRAS=1 -DURHO3D_TESTING=#{$testing}" or abort 'Failed to configure Urho3D library build'
  606. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj') or abort 'Failed to build or test Urho3D library'
  607. unless ENV['CI'] && ENV['IOS'] && ENV['PACKAGE_UPLOAD'] # Skip scaffolding test when packaging for iOS
  608. # Create a new project on the fly that uses newly built Urho3D library in the build tree
  609. scaffolding "../Build/generated/UsingBuildTree"
  610. system "cd ../Build/generated/UsingBuildTree && echo '\nExternal project referencing Urho3D library in its build tree' && ./cmake_macosx.sh . -DIOS=$IOS #{deployment_target} #{$build_options} -DURHO3D_HOME=../.. -DURHO3D_LUA#{jit}=1 -DURHO3D_TESTING=#{$testing}" or abort 'Failed to configure temporary project using Urho3D as external library'
  611. xcode_build(ENV['IOS'], '../Build/generated/UsingBuildTree/Scaffolding.xcodeproj') or abort 'Failed to build/test temporary project using Urho3D as external library'
  612. ENV['DESTDIR'] = ENV['HOME'] || Dir.home
  613. wait_for_block("\nInstalling Urho3D SDK to #{ENV['DESTDIR']}/usr/local...") { Thread.current[:exit_code] = xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj', 'install', '>/dev/null') } or abort 'Failed to install Urho3D SDK'
  614. # Create a new project on the fly that uses newly installed Urho3D SDK
  615. scaffolding "../Build/generated/UsingSDK"
  616. system "export URHO3D_HOME=~/usr/local && cd ../Build/generated/UsingSDK && echo '\nExternal project referencing Urho3D SDK' && ./cmake_macosx.sh . -DIOS=$IOS #{deployment_target} #{$build_options} -DURHO3D_LUA#{jit}=1 -DURHO3D_TESTING=#{$testing}" or abort 'Failed to configure temporary project using Urho3D as external library'
  617. xcode_build(ENV['IOS'], '../Build/generated/UsingSDK/Scaffolding.xcodeproj') or abort 'Failed to build/test temporary project using Urho3D as external library'
  618. end
  619. end
  620. def xcode_build ios, project, target = 'ALL_BUILD', extras = ''
  621. sdk = ios.to_i == 1 ? '-sdk iphonesimulator' : ''
  622. # Use xcpretty to filter output from xcodebuild when building
  623. system "xcodebuild -project #{project} -target #{target} -configuration #{$configuration} #{sdk} |xcpretty -c #{extras} && exit ${PIPESTATUS[0]}" or return nil
  624. if $testing == 1 && target == 'ALL_BUILD' # Disable testing for other targets such as 'doc', 'package', etc
  625. # Use vanila xcodebuild when testing as its output is instantaneous (ensure Travis-CI does not kill the process during testing)
  626. system "xcodebuild -project #{project} -target RUN_TESTS -configuration #{$configuration} #{sdk} #{extras}" or return nil
  627. end
  628. return 0
  629. end
  630. def append_new_release release, filename = '../doc-Build/_data/urho3d.json'
  631. begin
  632. urho3d_hash = JSON.parse File.read filename
  633. unless urho3d_hash['releases'].last == release
  634. urho3d_hash['releases'] << release
  635. end
  636. File.open(filename, 'w') { |file| file.puts urho3d_hash.to_json }
  637. return 0
  638. rescue
  639. nil
  640. end
  641. end
  642. def update_emscripten_data dir = '../doc-Build/samples', filename = '../doc-Build/_data/emscripten.json'
  643. begin
  644. emscripten_hash = JSON.parse File.read filename
  645. Dir.chdir(dir) { emscripten_hash['samples'] = Dir['*.html'].sort }
  646. File.open(filename, 'w') { |file| file.puts emscripten_hash.to_json }
  647. return 0
  648. rescue
  649. nil
  650. end
  651. end
  652. def bump_soversion filename
  653. begin
  654. version = File.read(filename).split '.'
  655. bump_version version, 2
  656. File.open(filename, 'w') { |file| file.puts version.join '.' }
  657. return 0
  658. rescue
  659. nil
  660. end
  661. end
  662. def bump_version version, index
  663. if index > 0 && version[index].to_i == 255
  664. version[index] = 0
  665. bump_version version, index - 1
  666. else
  667. version[index] = version[index].to_i + 1
  668. end
  669. end
  670. def setup_digital_keys
  671. system 'mkdir -p ~/.ssh && chmod 700 ~/.ssh' or abort 'Failed to create ~/.ssh directory'
  672. system 'cat <<EOF >>~/.ssh/known_hosts
  673. frs.sourceforge.net,216.34.181.57 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2uifHZbNexw6cXbyg1JnzDitL5VhYs0E65Hk/tLAPmcmm5GuiGeUoI/B0eUSNFsbqzwgwrttjnzKMKiGLN5CWVmlN1IXGGAfLYsQwK6wAu7kYFzkqP4jcwc5Jr9UPRpJdYIK733tSEmzab4qc5Oq8izKQKIaxXNe7FgmL15HjSpatFt9w/ot/CHS78FUAr3j3RwekHCm/jhPeqhlMAgC+jUgNJbFt3DlhDaRMa0NYamVzmX8D47rtmBbEDU3ld6AezWBPUR5Lh7ODOwlfVI58NAf/aYNlmvl2TZiauBCTa7OPYSyXJnIPbQXg6YQlDknNCr0K769EjeIlAfY87Z4tw==
  674. EOF' or abort 'Failed to append frs.sourceforge.net server public key to known_hosts'
  675. # Workaround travis encryption key size limitation. Rather than using the solution in their FAQ (using AES to encrypt/decrypt the file and check in the encrypted file into repo), our solution is more pragmatic. The private key below is incomplete. Only the missing portion is encrypted. Much less secure than the original 2048-bit RSA has to offer but good enough for our case.
  676. system 'cat <<EOF >~/.ssh/id_rsa
  677. -----BEGIN RSA PRIVATE KEY-----
  678. MIIEpQIBAAKCAQEAnZGzFEypdXKY3KDT0Q3NLY4Bv74yKgJ4LIgbXothx8w4CfM0
  679. VeWBL/AE2iRISEWGB07LruM9y+U/wt58WlCVu001GuJuvXwWenlljsvH8qQlErYi
  680. oXlCwAeVVeanILGL8CPS7QlyzOwwnVF6NdcmfDJjTthBVFbvHrWGo5if86zcZyMR
  681. 2BB5QVEr5fU0yOPFp0+2p7J3cA6HQSKwjUiDtJ+lM62UQp7InCCT3qeh5KYHQcYb
  682. KVJTyj5iycVuBujHDwNAivLq82ojG7LcKjP+Ia8fblardCOQyFk6pSDM79NJJ2Dg
  683. 3ZbYIJeUmqSqFhRW/13Bro7Z1aNGrdh/XZkkHwIDAQABAoIBACHcBFJxYtzVIloO
  684. yVWcFKIcaO3OLjNu0monWVJIu1tW3BfvRijLJ6aoejJyJ4I4RmPdn9FWDZp6CeiT
  685. LL+vn21fWvELBWb8ekwZOCSmT7IpaboKn4h5aUmgl4udA/73iC2zVQkQxbWZb5zu
  686. vEdDk4aOwV5ZBDjecYX01hjjnEOdZHGJlF/H/Xs0hYX6WDG3/r9QCJJ0nfd1/Fk2
  687. zdbZRtAbyRz6ZHiYKnFQ441qRRaEbzunkvTBEwu9iqzlE0s/g49LJL0mKEp7rt/J
  688. 4iS3LZTQbJNx5J0ti8ZJKHhvoWb5RJxNimwKvVHC0XBZKTiLMrhnADmcpjLz53F8
  689. $SF_KEY
  690. sx27yCaeBeKXV0tFOeZmgK664VM9EgesjIX4sVOJ5mA3xBJBOtz9n66LjoIlIM58
  691. dvsAnJt7MUBdclL/RBHEjbUxgGBDcazfWSuJe0sGczhnXMN94ox4MSECgYEAx5cv
  692. cs/2KurjtWPanDGSz71LyGNdL/xQrAud0gi49H0tyYr0XmzNoe2CbZ/T5xGSZB92
  693. PBcz4rnHQ/oujo/qwjNpDD0xVLEU70Uy/XiY5/v2111TFC4clfE/syZPywKAztt3
  694. y2l5z+QdsNigRPDhKw+7CFYaAnYBEISxR6nabT8CgYEAqHrM8fdn2wsCNE6XvkZQ
  695. O7ZANHNIKVnaRqW/8HW7EFAWQrlQTgzFbtR4uNBIqAtPsvwSx8Pk652+OR1VKfSv
  696. ya3dtqY3rY/ErXWyX0nfPQEbYj/oh8LbS6zPw75yIorP3ACIwMw3GRNWIvkdAGTn
  697. BMUgpWHUDLWWpWRrSzNi90ECgYEAkxxzQ6vW5OFGv17/NdswO+BpqCTc/c5646SY
  698. ScRWFxbhFclOvv5xPqYiWYzRkmIYRaYO7tGnU7jdD9SqVjfrsAJWrke4QZVYOdgG
  699. cl9eTLchxLGr15b5SOeNrQ1TCO4qZM3M6Wgv+bRI0h2JW+c0ABpTIBzehOvXcwZq
  700. 6MhgD98CgYEAtOPqc4aoIRUy+1oijpWs+wU7vAc8fe4sBHv5fsv7naHuPqZgyQYY
  701. 32a54xZxlsBw8T5P4BDy40OR7fu+6miUfL+WxUdII4fD3grlIPw6bpNE0bCDykv5
  702. RLq28S11hDrKf/ZetXNuIprfTlhl6ISBy+oWQibhXmFZSxEiXNV6hCQ=
  703. -----END RSA PRIVATE KEY-----
  704. EOF' or abort 'Failed to create user private key to id_rsa'
  705. system 'chmod 600 ~/.ssh/id_rsa' or abort 'Failed to change id_rsa file permission'
  706. end
  707. # Load custom rake scripts
  708. Dir['.rake/*.rake'].each { |r| load r }
  709. # vi: set ts=2 sw=2 expandtab: