Rakefile 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  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. # Usage: rake sync (only intended to be used in a fork with remote 'upstream' set to urho3d/Urho3D)
  26. desc 'Fetch and merge upstream urho3d/Urho3D to a Urho3D fork'
  27. task :sync do
  28. 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
  29. end
  30. # Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]
  31. desc 'Create a new project using Urho3D as external library'
  32. task :scaffolding do
  33. abort 'Usage: rake scaffolding dir=/path/to/new/project/root [project=Scaffolding] [target=Main]' unless ENV['dir']
  34. abs_path = (ENV['OS'] ? ENV['dir'][1, 1] == ':' : ENV['dir'][0, 1] == '/') ? ENV['dir'] : "#{Dir.pwd}/#{ENV['dir']}"
  35. project = ENV['project'] || 'Scaffolding'
  36. target = ENV['target'] || 'Main'
  37. scaffolding(abs_path, project, target)
  38. abs_path = Pathname.new(abs_path).realpath
  39. puts "\nNew project created in #{abs_path}\n\n"
  40. 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."
  41. puts "Please see http://urho3d.github.io/documentation/HEAD/_using_library.html for more detail. For example:\n\n"
  42. if ENV['OS']
  43. puts "set \"URHO3D_HOME=/path/to/Urho3D/build-tree/or/SDK\"\ncd #{abs_path}\nrake cmake URHO3D_LUAJIT=1\nrake make\n\n"
  44. 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"
  45. else
  46. puts "export 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 shell scripts directly, such as, ./cmake_generic.sh ../native-Build -DURHO3D_LUAJIT=1 && cd ../native-Build && make"
  48. end
  49. puts "to get a similar result as the last two rake tasks above.\n\n"
  50. end
  51. # Usage: rake cmake [<generator>] [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [fix_scm]
  52. # 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
  53. #
  54. # To avoid repeating the customized build tree locations, you can set and export them as environment variables.
  55. # 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
  56. # rake cmake rpi URHO3D_LUAJIT=1 URHO3D_LUAJIT_AMALG=1 && rake make rpi
  57. # The RPI build tree will be generated in the ~/custom-rpi-Build and then build from there
  58. desc 'Invoke one of the build scripts with the build tree location predetermined based on the target platform'
  59. task :cmake do
  60. script = 'cmake_generic'
  61. platform = 'native'
  62. build_options = ''
  63. ARGV.each { |option|
  64. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  65. case option
  66. when 'cmake', 'generic'
  67. # do nothing
  68. when 'clean', 'codeblocks', 'eclipse', 'macosx', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015'
  69. script = "cmake_#{option}" unless script == 'cmake_clean'
  70. when 'android', 'emscripten', 'ios', 'mingw', 'rpi'
  71. platform = option
  72. build_options = "#{build_options} -D#{option == 'mingw' ? 'WIN32' : option.upcase}=1" unless script == 'cmake_clean'
  73. script = 'cmake_macosx' if option == 'ios'
  74. script = 'cmake_mingw' if option == 'mingw' && ENV['OS']
  75. when 'fix_scm'
  76. build_options = "#{build_options} --fix-scm" if script == 'cmake_eclipse'
  77. else
  78. build_options = "#{build_options} -D#{option}" unless /build_tree=.*/ =~ option || script == 'cmake_clean'
  79. end
  80. }
  81. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  82. unless ENV['OS']
  83. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  84. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  85. end
  86. system "#{ccache_envvar} ./#{script}#{ENV['OS'] ? '.bat' : '.sh'} \"#{build_tree}\" #{build_options}" or abort
  87. end
  88. # Usage: rake make [<platform>] [<option>=<value> [<option>=<value>]] [[<platform>_]build_tree=/path/to/build-tree] [numjobs=n] [clean_first] [unfilter]
  89. # e.g.: rake make android; or rake make android doc; or rake make ios config=Debug sdk=iphonesimulator build_tree=~/ios-Build
  90. desc 'Build the generated project in its corresponding build tree'
  91. task :make do
  92. numjobs = ENV['numjobs'] || ''
  93. platform = 'native'
  94. cmake_build_options = ''
  95. build_options = ''
  96. unfilter = false
  97. ARGV.each { |option|
  98. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  99. case option
  100. when 'codeblocks', 'eclipse', 'generic', 'macosx', 'make', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015'
  101. # do nothing
  102. when 'android', 'emscripten', 'ios', 'mingw', 'rpi'
  103. platform = option
  104. when 'clean_first'
  105. cmake_build_options = "#{cmake_build_options} --clean-first"
  106. when 'unfilter'
  107. unfilter = true
  108. else
  109. if /(?:config|target)=.*/ =~ option
  110. cmake_build_options = "#{cmake_build_options} --#{option.gsub(/=/, ' ')}"
  111. elsif /(?:build_tree|numjobs)=.*/ !~ option
  112. build_options = "#{build_options} #{/=/ =~ option ? '-' + option.gsub(/=/, ' ') : option}"
  113. end
  114. end
  115. }
  116. build_tree = ENV["#{platform}_build_tree"] || ENV['build_tree'] || "../#{platform}-Build"
  117. unless ENV['OS']
  118. ccache_envvar = ENV['CCACHE_SLOPPINESS'] ? '' : 'CCACHE_SLOPPINESS=pch_defines,time_macros' # Only attempt to do the right thing when user hasn't done it
  119. ccache_envvar = "#{ccache_envvar} CCACHE_COMPRESS=1" unless ENV['CCACHE_COMPRESS']
  120. end
  121. if !Dir.glob("#{build_tree}/*.xcodeproj").empty?
  122. # xcodebuild
  123. if !numjobs.empty?
  124. build_options = "-jobs #{numjobs}#{build_options}"
  125. end
  126. filter = !unfilter && system('xcpretty -v >/dev/null 2>&1') ? '|xcpretty -c && exit ${PIPESTATUS[0]}' : ''
  127. elsif !Dir.glob("#{build_tree}/*.sln").empty?
  128. # msbuild
  129. numjobs = ":#{numjobs}" unless numjobs.empty?
  130. build_options = "/maxcpucount#{numjobs}#{build_options}"
  131. filter = unfilter ? '' : '/nologo /verbosity:minimal'
  132. filter = filter + ' /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"' if ENV['APPVEYOR']
  133. elsif !Dir.glob("#{build_tree}/*.ninja").empty?
  134. # ninja
  135. if !numjobs.empty?
  136. build_options = "-j#{numjobs}#{build_options}"
  137. end
  138. filter = ''
  139. else
  140. # make
  141. if numjobs.empty?
  142. case RUBY_PLATFORM
  143. when /linux/
  144. numjobs = (platform == 'emscripten' ? `grep 'core id' /proc/cpuinfo |sort |uniq |wc -l` : `grep -c processor /proc/cpuinfo`).chomp
  145. when /darwin/
  146. numjobs = `sysctl -n hw.#{platform == 'emscripten' ? 'physical' : 'logical'}cpu`.chomp
  147. when /win32|mingw|mswin/
  148. require 'win32ole'
  149. WIN32OLE.connect('winmgmts://').ExecQuery("select NumberOf#{platform == 'emscripten' ? '' : 'Logical'}Processors from Win32_ComputerSystem").each { |out| numjobs = platform == 'emscripten' ? out.NumberOfProcessors : out.NumberOfLogicalProcessors }
  150. else
  151. numjobs = 1
  152. end
  153. end
  154. build_options = "-j#{numjobs}#{build_options}"
  155. filter = ''
  156. end
  157. system "cd \"#{build_tree}\" && #{ccache_envvar} cmake --build . #{cmake_build_options} -- #{build_options} #{filter}" or abort
  158. end
  159. # 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] [install]
  160. desc 'Test run APK in Android (virtual) device, default to Urho3D Samples APK if no parameter is given'
  161. task :android do
  162. parameter = ENV['parameter'] || '--es pickedLibrary Urho3DPlayer'
  163. intent = ENV['intent'] || '.SampleLauncher'
  164. package = ENV['package'] || 'com.github.urho3d'
  165. success_indicator = ENV['success_indicator'] || 'Initialized engine'
  166. payload = ENV['payload'] || 'sleep 30'
  167. api = ENV['api'] || 19
  168. abi = ENV['abi'] || 'armeabi-v7a'
  169. avd = ENV['avd'] || "test_#{api}_#{abi}"
  170. retries = ENV['retries'] || 10 # minutes
  171. retry_interval = ENV['retry_interval'] || 10 # seconds
  172. build_tree = ENV['android_build_tree'] || ENV['build_tree'] || '../android-Build'
  173. install = false
  174. ARGV.each { |option|
  175. task option.to_sym do ; end; Rake::Task[option].clear # No-op hack
  176. case option
  177. when 'install'
  178. install = true
  179. end
  180. }
  181. android_prepare_device api, abi, avd or abort 'Failed to prepare Android (virtual) device for test run'
  182. if install
  183. system "cd \"#{build_tree}\" && android update project -p . -t $(android list target |grep android-#{api} |cut -d ' ' -f2) && ant debug" or abort 'Failed to generate APK'
  184. end
  185. android_wait_for_device retries, retry_interval or abort 'Failed to start Android (virtual) device'
  186. if install
  187. system "cd \"#{build_tree}\" && ant -Dadb.device.arg='-s #{$specific_device}' installd" or abort 'Failed to install APK'
  188. end
  189. android_test_run parameter, intent, package, success_indicator, payload or abort "Failed to test run #{package}/#{intent}"
  190. end
  191. # Usage: NOT intended to be used manually
  192. desc 'Build and run the Annotate tool (temporary)'
  193. task :ci_annotate do
  194. system 'rake cmake URHO3D_CLANG_TOOLS=1 && rake make annotate' or abort 'Failed to annotate'
  195. 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 && if git fetch origin clang-tools:clang-tools 2>/dev/null; then git push -qf origin --delete clang-tools; fi && git checkout -B clang-tools && git stash -q && git reset --hard HEAD~ && git stash pop -q && sed -i \"s/COVERITY_SCAN_THRESHOLD/URHO3D_PCH=0 URHO3D_BINDINGS=1 COVERITY_SCAN_THRESHOLD/g\" .travis.yml && git add -A .travis.yml Source/Urho3D && if git commit -qm 'Result of Annotator tool. [ci only: clang-tools]'; then git push -q -u origin clang-tools >/dev/null 2>&1; fi" or abort 'Failed to push clang-tools branch'
  196. end
  197. # Usage: NOT intended to be used manually
  198. desc 'Push the generated binding source files to clang-tools branch (temporary)'
  199. task :ci_push_bindings do
  200. abort "Skipped pushing to #{ENV['TRAVIS_BRANCH']} branch 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']
  201. 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 && git add -A Source/Urho3D && if git commit -qm 'Result of AutoBinder tool. [ci skip]'; then git push -q origin HEAD:#{ENV['TRAVIS_BRANCH']} >/dev/null 2>&1; fi" or abort "Failed to push #{ENV['TRAVIS_BRANCH']} branch"
  202. end
  203. # Usage: NOT intended to be used manually (if you insist then try: rake ci)
  204. desc 'Configure, build, and test Urho3D project'
  205. task :ci do
  206. # Skip if only performing CI for selected branches and the current branch is not in the list
  207. unless ENV['RELEASE_TAG']
  208. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  209. next if matched && !matched[1].split(/[ ,]/).reject!(&:empty?).map { |i| /#{i}/ =~ ENV['TRAVIS_BRANCH'] }.any?
  210. end
  211. # Obtain our custom data, if any
  212. data = YAML::load(File.open(".travis.yml"))['data']
  213. data['excluded_sample'].each { |name| ENV["EXCLUDE_SAMPLE_#{name}"] = '1' } if data && data['excluded_sample']
  214. # Unshallow the clone's history when necessary
  215. if ENV['CI'] && ENV['PACKAGE_UPLOAD'] && !ENV['RELEASE_TAG']
  216. system 'git fetch --unshallow' or abort 'Failed to unshallow cloned repository'
  217. end
  218. # Packaging always use Release configuration
  219. if ENV['PACKAGE_UPLOAD']
  220. $configuration = 'Release'
  221. $testing = 0
  222. else
  223. $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
  224. # 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
  225. $testing = (ENV['LINUX'] && !ENV['URHO3D_64BIT']) || (ENV['OSX'] && ENV['IOS'].to_i != 1) || ENV['HTML5'] ? 1 : 0
  226. if $testing
  227. ENV['URHO3D_PREFIX_PATH'] = `pwd`.chomp + '/bin'
  228. end
  229. end
  230. # Define the build option string only when the override environment variable is given
  231. $build_options = "-DWIN32=#{ENV['WINDOWS']}" if ENV['WINDOWS']
  232. $build_options = "-DEMSCRIPTEN=#{ENV['HTML5']}" if ENV['HTML5']
  233. $build_options = "#{$build_options} -DANDROID_ABI=#{ENV['ABI']}" if ENV['ABI']
  234. $build_options = "#{$build_options} -DANDROID_NATIVE_API_LEVEL=#{ENV['API']}" if ENV['API']
  235. ['URHO3D_64BIT', 'URHO3D_LIB_TYPE', 'URHO3D_PCH', 'URHO3D_BINDINGS', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_TEST_TIMEOUT', 'URHO3D_UPDATE_SOURCE_TREE', 'ANDROID', 'RPI', 'RPI_ABI', 'EMSCRIPTEN_SHARE_DATA', 'EMSCRIPTEN_EMRUN_BROWSER'].each { |var| $build_options = "#{$build_options} -D#{var}=\"#{ENV[var]}\"" if ENV[var] }
  236. if ENV['XCODE']
  237. # xcodebuild
  238. xcode_ci
  239. else
  240. # GCC or Clang
  241. makefile_ci
  242. end
  243. end
  244. # Usage: NOT intended to be used manually
  245. desc 'Setup build cache'
  246. task :ci_setup_cache do
  247. clear = /\[ccache clear\]/ =~ ENV['COMMIT_MESSAGE']
  248. # Use internal cache store instead of using Travis CI one (this is a workaround for using ccache on Travis CI legacy build infra)
  249. if ENV['USE_CCACHE'].to_i == 2
  250. puts 'Setting up build cache'
  251. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  252. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  253. matched = /.*-([^-]+-[^-]+)$/.match(ENV['TRAVIS_BRANCH'])
  254. base_mirror = matched ? matched[1] : nil
  255. # Do not abort even when it fails here
  256. 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"
  257. # Preserving .git directory before clearing the cache on Linux host system (ccache on Mac OSX does not have this problem)
  258. `mv ~/.ccache/.git /tmp` if clear && ENV['OSX'].to_i != 1
  259. end
  260. # Clear ccache on demand
  261. system "ccache -z -M #{ENV['CCACHE_MAXSIZE']} #{clear ? '-C' : ''}"
  262. # Restoring .git directory if its backup exists
  263. `if [ -e /tmp/.git ]; then mv /tmp/.git ~/.ccache; fi`
  264. end
  265. # Usage: NOT intended to be used manually
  266. desc 'Teardown build cache'
  267. task :ci_teardown_cache do
  268. # Upload cache to internal cache store if it is our own
  269. if ENV['USE_CCACHE'].to_i == 2
  270. puts 'Storing build cache'
  271. job_number = ".#{ENV['TRAVIS_JOB_NUMBER'].split('.').last}"
  272. repo_slug = "#{ENV['TRAVIS_REPO_SLUG'].split('/').first}/cache-store.git"
  273. # Do not abort even when it fails here
  274. 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"
  275. end
  276. system 'ccache -s'
  277. end
  278. # Usage: NOT intended to be used manually
  279. desc 'Update site documentation to GitHub Pages'
  280. task :ci_site_update do
  281. # Skip when :ci rake task was skipped
  282. next unless File.exist?('../Build/CMakeCache.txt')
  283. # Pull or clone
  284. 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'
  285. # Update credits from README.md to about.yml
  286. 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(/(?<=contributors:\n).*?\n\n/m, credits)' ../doc-Build/_data/about.yml" or abort 'Failed to update credits'
  287. # Setup doxygen to use minimal theme
  288. 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/generated/Doxyfile" or abort 'Failed to setup doxygen configuration file'
  289. system 'cp ../doc-Build/_includes/Doxygen/minimal-* ../Build/Docs' or abort 'Failed to copy minimal-themed template'
  290. release = ENV['RELEASE_TAG'] || 'HEAD'
  291. unless release == 'HEAD'
  292. system "mkdir -p ../doc-Build/documentation/#{release}" or abort 'Failed to create directory for new document version'
  293. 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'
  294. append_new_release release or abort 'Failed to add new release to document data file'
  295. end
  296. # Generate and sync doxygen pages
  297. 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'
  298. # Supply GIT credentials and push site documentation to urho3d/urho3d.github.io.git
  299. 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'
  300. unless ENV['RELEASE_TAG'] || `git fetch -qf origin #{ENV['TRAVIS_BRANCH']}; git log -1 --pretty=format:'%H' FETCH_HEAD` != ENV['TRAVIS_COMMIT']
  301. # Supply GIT credentials and push API documentation to urho3d/Urho3D.git (only when changes are detected)
  302. 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*'
  303. if system("git commit -qm 'Test commit to detect API changes'")
  304. # Automatically give instruction to do packaging when API has changed, unless the instruction is already given in this commit
  305. bump_soversion 'Source/Urho3D/.soversion' or abort 'Failed to bump soversion'
  306. system "git add Source/Urho3D/.soversion && git commit --amend -qm \"Travis CI: API documentation update at #{Time.now.utc}.\n#{ENV['PACKAGE_UPLOAD'] ? '' : '[ci package]'}\n\nCommit: https://github.com/$TRAVIS_REPO_SLUG/commit/$TRAVIS_COMMIT\n\nMessage: $COMMIT_MESSAGE\"" or abort 'Failed to stage .soversion file'
  307. system "git push origin HEAD:#{ENV['TRAVIS_BRANCH']} -q >/dev/null 2>&1" or abort 'Failed to update API documentation'
  308. end
  309. end
  310. end
  311. # Usage: NOT intended to be used manually
  312. desc 'Update Emscripten HTML5 samples to GitHub Pages'
  313. task :ci_emscripten_samples_update do
  314. puts "\nUpdating Emscripten samples in main website..."
  315. # Pull or clone
  316. 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'
  317. # Sync Emscripten samples
  318. system "rsync -a --delete --exclude tool ../Build/bin/ ../doc-Build/samples" or abort 'Failed to rsync Emscripten samples'
  319. # Update Emscripten json data file
  320. update_emscripten_data or abort 'Failed to update Emscripten json data file'
  321. root_commit, _ = get_root_commit_and_recipients
  322. 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/#{root_commit}\n\nMessage: #{`git log --format=%B -n 1 #{root_commit}`}\" || true) && git push -q >/dev/null 2>&1" or abort 'Failed to update Emscripten samples'
  323. end
  324. # Usage: NOT intended to be used manually
  325. desc 'Create all CI mirror branches'
  326. task :ci_create_mirrors do
  327. # Skip if there are more commits since this one
  328. 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']
  329. 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'
  330. # Limit the scanning to only master branch and limit the frequency of scanning
  331. scan = ENV['TRAVIS_BRANCH'] == 'master' && ((/\[ccache clear\]/ !~ ENV['COMMIT_MESSAGE'] && `ccache -s |grep 'cache miss'`.split.last.to_i >= ENV['COVERITY_SCAN_THRESHOLD'].to_i) || /\[ci scan\]/ =~ ENV['COMMIT_MESSAGE'])
  332. # Check if it is time to generate annotation
  333. annotate = ENV['TRAVIS_BRANCH'] == 'master' && (ENV['PACKAGE_UPLOAD'] || /\[ci annotate\]/ =~ ENV['COMMIT_MESSAGE'])
  334. # Determine which CI mirror branches to be auto created
  335. unless ENV['RELEASE_TAG']
  336. matched = /\[ci only:(.*?)\]/.match(ENV['COMMIT_MESSAGE'])
  337. ci_only = matched ? matched[1].split(/[ ,]/).reject!(&:empty?) : nil
  338. if ci_only
  339. ci_only.push('Coverity-Scan') if scan
  340. ci_only.push('Annotate') if annotate
  341. end
  342. else
  343. ci_only = nil
  344. end
  345. # Obtain the whole stream and process the rest of documents except the first one since travis-build does not do that at the moment
  346. stream = YAML::load_stream(File.open('.travis.yml'))
  347. notifications = stream[0]['notifications']
  348. notifications['email']['recipients'] = get_root_commit_and_recipients().last unless notifications['email']['recipients']
  349. 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) || (annotate && /Annotate/ =~ 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 '#{ENV['COMMIT_MESSAGE']}' && git push -qf -u origin #{ci_branch} >/dev/null 2>&1 && git checkout -q -" or abort "Failed to create #{ci_branch} mirror branch" }
  350. end
  351. # Usage: NOT intended to be used manually
  352. desc 'Delete CI mirror branch'
  353. task :ci_delete_mirror do
  354. # Skip if there are more commits since this one or if this is a release build
  355. matched = /(.*)-[^-]+-[^-]+$/.match(ENV['TRAVIS_BRANCH'])
  356. base_branch = matched ? matched[1] : 'master' # Assume 'master' is the default branch name
  357. 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']
  358. 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'
  359. system "git push -qf origin --delete #{ENV['TRAVIS_BRANCH']}" or abort "Failed to delete #{ENV['TRAVIS_BRANCH']} mirror branch"
  360. end
  361. # Usage: NOT intended to be used manually
  362. desc 'Make binary package and upload it to a designated central hosting server'
  363. task :ci_package_upload do
  364. # Skip when :ci rake task was skipped
  365. next unless File.exist?('../Build/CMakeCache.txt')
  366. if ENV['XCODE']
  367. $configuration = 'Release'
  368. $testing = 0
  369. end
  370. # Generate the documentation if necessary
  371. if ENV['SITE_UPDATE']
  372. if File.exist?('.site_updated')
  373. # Skip if site is already updated before
  374. ENV['SITE_UPDATE'] = nil
  375. end
  376. else
  377. system 'echo Generating documentation...'
  378. if ENV['XCODE']
  379. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj', 'doc', '>/dev/null') or abort 'Failed to generate documentation'
  380. else
  381. system 'cd ../Build && make -j$NUMJOBS doc >/dev/null' or abort 'Failed to generate documentation'
  382. end
  383. end
  384. # Make the package
  385. if ENV['IOS']
  386. # 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
  387. if ENV['CI_START_TIME'] then
  388. elapsed_time = (Time.now - Time.at(ENV['CI_START_TIME'].to_i)) / 60
  389. puts "\niOS checkpoint reached, elapsed time: #{elapsed_time}\n\n"
  390. end
  391. if !ENV['CI_START_TIME'] || elapsed_time < 25 # minutes
  392. # 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)
  393. system 'echo Rebuilding Urho3D library as Mach-O universal binary...'
  394. xcode_build(0, '../Build/Urho3D.xcodeproj', 'Urho3D_universal') or abort 'Failed to build Mach-O universal binary'
  395. end
  396. # There is a bug in CMake/CPack that causes the 'package' target failed to build for IOS platform, workaround by calling cpack directly
  397. system 'cd ../Build && cpack -G TGZ 2>/dev/null' or abort 'Failed to make binary package'
  398. elsif ENV['XCODE']
  399. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj', 'package') or abort 'Failed to make binary package'
  400. else
  401. if ENV['ANDROID'] && !ENV['NO_SDK_SYSIMG']
  402. 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'
  403. end
  404. if ENV['URHO3D_USE_LIB64_RPM']
  405. system "cd ../Build && cmake . -DURHO3D_USE_LIB64_RPM=#{ENV['URHO3D_USE_LIB64_RPM']}" or abort 'Failed to reconfigure to generate 64-bit RPM package'
  406. end
  407. wrapper = ENV['URHO3D_64BIT'] || ENV['RPI'] ? 'setarch i686' : ''
  408. system "cd ../Build && #{wrapper} make package" or abort 'Failed to make binary package'
  409. end
  410. # Determine the upload location
  411. setup_digital_keys
  412. unless ENV['RELEASE_TAG']
  413. upload_dir = "/home/frs/project/#{ENV['TRAVIS_REPO_SLUG']}/Snapshots"
  414. if ENV['SITE_UPDATE']
  415. # Download source packages from GitHub
  416. 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'
  417. # Only keep the snapshots from the last 30 revisions
  418. system "for v in $(sftp [email protected] <<EOF |tr ' ' '\n' |grep Urho3D- |cut -d '-' -f1,2 |uniq |tail -n +31
  419. cd #{upload_dir}
  420. ls -1r
  421. bye
  422. EOF
  423. ); do echo rm #{upload_dir}/${v}*; done |sftp -b - [email protected] >/dev/null 2>&1" or abort 'Failed to housekeep snapshots'
  424. end
  425. else
  426. upload_dir = "/home/frs/project/#{ENV['TRAVIS_REPO_SLUG']}/#{ENV['RELEASE_TAG']}"
  427. if ENV['SITE_UPDATE']
  428. # Download source packages from GitHub
  429. 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'
  430. end
  431. # 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
  432. system "sftp [email protected] <<EOF >/dev/null 2>&1
  433. mkdir #{upload_dir}
  434. bye
  435. EOF" or abort 'Failed to create release directory remotely'
  436. end
  437. if ENV['SITE_UPDATE']
  438. # Upload the source package
  439. system "scp Urho3D-* [email protected]:#{upload_dir}" or abort 'Failed to upload source package'
  440. if ENV['RELEASE_TAG']
  441. # Mark the source tarball as default download for host systems other than Windows/Mac/Linux
  442. system "curl -H 'Accept: application/json' -X PUT -d 'default=bsd&default=solaris&default=others' -d \"api_key=$SF_API\" https://sourceforge.net/projects/%s/files/%s/#{ENV['RELEASE_TAG']}/Urho3D-#{ENV['RELEASE_TAG']}-Source.tar.gz" % ENV['TRAVIS_REPO_SLUG'].split('/') or abort 'Failed to set source tarball as default download'
  443. end
  444. # Sync readme and license files, just in case they are updated in the repo
  445. 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'
  446. 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'
  447. # Mark that the site has been updated
  448. File.open('.site_updated', 'w') {}
  449. end
  450. # Upload the binary package
  451. system "scp ../Build/Urho3D-* [email protected]:#{upload_dir} && rm ../Build/Urho3D-*" or abort 'Failed to upload binary package'
  452. if ENV['RELEASE_TAG'] && ENV['SF_DEFAULT']
  453. # Mark the corresponding binary package as default download for each Windows/Mac/Linux host systems
  454. system "curl -H 'Accept: application/json' -X PUT -d 'default=%s' -d \"api_key=$SF_API\" https://sourceforge.net/projects/%s/files/%s/#{ENV['RELEASE_TAG']}/Urho3D-#{ENV['RELEASE_TAG']}-%s" % ENV['SF_DEFAULT'].split(':').insert(1, ENV['TRAVIS_REPO_SLUG'].split('/')).flatten or abort 'Failed to set binary tarball/zip as default download'
  455. end
  456. end
  457. # Usage: NOT intended to be used manually
  458. desc 'Make binary package and upload it to a designated central hosting server'
  459. task :ci_appveyor_package_upload do
  460. # Generate the documentation
  461. system 'echo Generating documentation...'
  462. system "bash -c 'rake make config=$Configuration target=doc >/dev/null'" # Ignore the exit status from 'make doc' as Doxygen on Windows host system does not return exit status correctly
  463. # Make the package
  464. system "bash -c 'rake make config=$Configuration target=package'" or abort 'Failed to make binary package'
  465. # Determine the upload location
  466. setup_digital_keys
  467. unless ENV['RELEASE_TAG']
  468. upload_dir = "/home/frs/project/#{ENV['APPVEYOR_REPO_NAME']}/Snapshots"
  469. else
  470. upload_dir = "/home/frs/project/#{ENV['APPVEYOR_REPO_NAME']}/#{ENV['RELEASE_TAG']}"
  471. # 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
  472. system "bash -c 'sftp [email protected] <<EOF >/dev/null 2>&1
  473. mkdir #{upload_dir}
  474. bye
  475. EOF'" or abort 'Failed to create release directory remotely'
  476. end
  477. # Upload the binary package
  478. system "bash -c 'scp #{ENV['build_tree']}/Urho3D-* [email protected]:#{upload_dir}'" or abort 'Failed to upload binary package'
  479. if ENV['RELEASE_TAG'] && ENV['SF_DEFAULT']
  480. # Mark the corresponding binary package as default download for each Windows/Mac/Linux host systems
  481. system "bash -c \"curl -H 'Accept: application/json' -X PUT -d 'default=%s' -d \"api_key=$SF_API\" https://sourceforge.net/projects/%s/files/%s/#{ENV['RELEASE_TAG']}/Urho3D-#{ENV['RELEASE_TAG']}-%s\"" % ENV['SF_DEFAULT'].split(':').insert(1, ENV['APPVEYOR_REPO_NAME'].split('/')).flatten or abort 'Failed to set binary tarball/zip as default download'
  482. end
  483. end
  484. def scaffolding dir, project = 'Scaffolding', target = 'Main'
  485. build_script = <<EOF
  486. # Set project name
  487. project (#{project})
  488. # Set minimum version
  489. cmake_minimum_required (VERSION 2.8.6)
  490. if (COMMAND cmake_policy)
  491. cmake_policy (SET CMP0003 NEW)
  492. if (CMAKE_VERSION VERSION_GREATER 2.8.12 OR CMAKE_VERSION VERSION_EQUAL 2.8.12)
  493. # INTERFACE_LINK_LIBRARIES defines the link interface
  494. cmake_policy (SET CMP0022 NEW)
  495. endif ()
  496. if (CMAKE_VERSION VERSION_GREATER 3.0.0 OR CMAKE_VERSION VERSION_EQUAL 3.0.0)
  497. # Disallow use of the LOCATION target property - therefore we set to OLD as we still need it
  498. cmake_policy (SET CMP0026 OLD)
  499. # MACOSX_RPATH is enabled by default
  500. cmake_policy (SET CMP0042 NEW)
  501. endif ()
  502. endif ()
  503. # Set CMake modules search path
  504. set (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
  505. # Include Urho3D CMake common module
  506. include (Urho3D-CMake-common)
  507. # Find Urho3D library
  508. find_package (Urho3D REQUIRED)
  509. include_directories (${URHO3D_INCLUDE_DIRS})
  510. # Define target name
  511. set (TARGET_NAME #{target})
  512. # Define source files
  513. define_source_files ()
  514. # Setup target with resource copying
  515. setup_main_executable ()
  516. # Setup test cases
  517. if (URHO3D_ANGELSCRIPT)
  518. setup_test (NAME ExternalLibAS OPTIONS Scripts/12_PhysicsStressTest.as -w)
  519. endif ()
  520. if (URHO3D_LUA)
  521. setup_test (NAME ExternalLibLua OPTIONS LuaScripts/12_PhysicsStressTest.lua -w)
  522. endif ()
  523. EOF
  524. # TODO: Rewrite in pure Ruby when it supports symlink creation on Windows platform
  525. if ENV['OS']
  526. 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'
  527. else
  528. 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'
  529. end
  530. end
  531. def makefile_ci
  532. if (ENV['WINDOWS'] && ENV['TRAVIS']) || (ENV['ANDROID'] && ENV['ABI'] == 'arm64-v8a') || ENV['HTML5']
  533. # LuaJIT on MinGW build is not possible on Travis-CI with Ubuntu 12.04 LTS as its GCC cross-compiler version is too old
  534. # The upstream LuaJIT library does not support Android arm64-v8a ABI at the moment
  535. # LuaJIT on Emscripten is not possible
  536. # Fallback to use Lua library instead
  537. jit = ''
  538. amalg = ''
  539. else
  540. jit = 'JIT'
  541. amalg = '-DURHO3D_LUAJIT_AMALG=1'
  542. end
  543. system "./cmake_generic.sh ../Build #{$build_options} -DURHO3D_DATABASE_SQLITE=1 -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'
  544. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD'] # Skip APK test run when packaging
  545. android_prepare_device ENV['API'], ENV['ABI'], ENV['AVD'] or abort 'Failed to prepare Android (virtual) device for test run'
  546. end
  547. # Temporarily put the logic here for clang-tools migration until everything else are in their places
  548. if ENV['URHO3D_BINDINGS']
  549. system "cd ../Build && make -j$NUMJOBS" or abort 'Failed to build or test Urho3D library with annotated source files'
  550. system 'rake ci_push_bindings' or abort
  551. return 0
  552. end
  553. # For Emscripten CI build, skip make test and/or scaffolding test if CI VM took too long to get here, as otherwise overall build time may exceed 50 minutes time limit
  554. test = $testing == 1 ? '&& make test' : ''
  555. system "cd ../Build && make -j$NUMJOBS #{test}" or abort 'Failed to build or test Urho3D library'
  556. unless ENV['CI'] && ENV['HTML5'] && ENV['PACKAGE_UPLOAD'] # For Emscripten, skip scaffolding test when packaging
  557. # Create a new project on the fly that uses newly built Urho3D library in the build tree
  558. scaffolding "../Build/generated/UsingBuildTree"
  559. 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'
  560. ENV['DESTDIR'] = ENV['HOME'] || Dir.home
  561. puts "\nInstalling Urho3D SDK to #{ENV['DESTDIR']}/usr/local...\n" # The default CMAKE_INSTALL_PREFIX is /usr/local
  562. system 'cd ../Build && make -j$NUMJOBS install >/dev/null' or abort 'Failed to install Urho3D SDK'
  563. # Create a new project on the fly that uses newly installed Urho3D SDK
  564. scaffolding "../Build/generated/UsingSDK"
  565. 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'
  566. end
  567. # Make, deploy, and test run Android APK in an Android (virtual) device
  568. if ENV['AVD'] && !ENV['PACKAGE_UPLOAD']
  569. 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'
  570. if android_wait_for_device
  571. system "cd ../Build && ant -Dadb.device.arg='-s #{$specific_device}' installd" or abort 'Failed to deploy Urho3D Samples APK'
  572. android_test_run or abort 'Failed to test run Urho3D Samples APK'
  573. else
  574. puts 'Skipped test running Urho3D Samples APK as emulator failed to start in time'
  575. end
  576. end
  577. end
  578. def get_root_commit_and_recipients
  579. # Root commit is a commit submitted by human
  580. root_commit = `git show -s --format='%H' #{ENV['TRAVIS_COMMIT']}`.rstrip
  581. recipients = `git show -s --format='%ae %ce' #{root_commit}`.chomp.split.uniq
  582. if recipients.include? '[email protected]'
  583. matched = /Commit:.*commit\/(.*?)\n/.match(ENV['COMMIT_MESSAGE'])
  584. if (matched)
  585. root_commit = matched[1]
  586. recipients = `git show -s --format='%ae %ce' #{root_commit}`.chomp.split.uniq
  587. end
  588. end
  589. return root_commit, recipients
  590. end
  591. def android_find_device api = nil, abi = nil
  592. # Return the previously found matching device or if not found yet then try to find the matching device now
  593. return $specific_device if $specific_device
  594. $specific_api = api.to_s if api
  595. $specific_abi = abi.to_s if abi
  596. loop do
  597. for i in `adb devices |tail -n +2`.split "\n"
  598. device = i.split.first
  599. 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
  600. return $specific_device = device
  601. end
  602. end
  603. break if api
  604. end
  605. nil
  606. end
  607. def android_prepare_device api, abi = 'armeabi-v7a', name = 'test'
  608. system 'if ! ps |grep -cq adb; then adb start-server; fi'
  609. if !android_find_device api, abi
  610. # Don't have any matching (virtual) device attached, try to attach the named device (create the named device as AVD if necessary)
  611. if !system "android list avd |grep -cq 'Name: #{name}$'"
  612. system "echo 'no' |android create avd -n #{name} -t android-#{api} --abi #{abi}" or abort "Failed to create '#{name}' Android virtual device"
  613. end
  614. 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 &"
  615. end
  616. return 0
  617. end
  618. def android_wait_for_device retries = -1, retry_interval = 10, package = 'android.process.acore' # Waiting for HOME by default
  619. # 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)
  620. str = "\nWaiting for device..."
  621. thread = Thread.new { android_find_device }; sleep 0.5
  622. process_ready = false
  623. retries = retries * 60 / retry_interval unless retries == -1
  624. until retries == 0
  625. if thread.status == false
  626. thread.join
  627. break if process_ready
  628. 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
  629. next
  630. end
  631. 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
  632. sleep retry_interval
  633. retries -= 1 if retries > 0
  634. end
  635. puts "\n\n" if str == '.'; $stdout.flush
  636. return retries == 0 ? nil : 0
  637. end
  638. def android_test_run parameter = '--es pickedLibrary Urho3DPlayer', intent = '.SampleLauncher', package = 'com.github.urho3d', success_indicator = 'Added resource path /apk/CoreData/', payload = 'sleep 30'
  639. # The device should have been found at this point
  640. return nil unless $specific_device
  641. # Capture adb's stdout and interpret it because adb neither uses stderr nor returns proper exit code on error
  642. begin
  643. IO.popen("adb -s #{$specific_device} shell <<EOF
  644. # Try to unlock the device just in case it is locked
  645. input keyevent 82; input keyevent 4
  646. # Clear the log
  647. logcat -c
  648. # Start the app
  649. am start -a android.intent.action.MAIN -n #{package}/#{intent} #{parameter}
  650. # Wait until the process is running
  651. until ps |grep -c #{package} 1>/dev/null; do sleep 1; done
  652. # Execute the payload
  653. #{payload}
  654. # Exit and stop the app
  655. input keyevent 4 && am force-stop #{package}
  656. # Dump the log
  657. logcat -d
  658. # Bye bye
  659. exit
  660. ##
  661. 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 }
  662. # Result of the test run is determined based on the presence of the success indicator string in the log
  663. system "adb -s #{$specific_device} logcat -d |grep -cq '#{success_indicator}'"
  664. rescue
  665. nil
  666. end
  667. end
  668. def wait_for_block comment = '', retries = -1, retry_interval = 60, exit_code_sym = 'exit_code', &block
  669. # 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)
  670. thread = Thread.new &block
  671. str = comment
  672. retries = retries * 60 / retry_interval unless retries == -1
  673. until retries == 0
  674. if thread.status == false
  675. thread.join
  676. break
  677. end
  678. 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
  679. sleep retry_interval
  680. retries -= 1 if retries > 0
  681. end
  682. puts "\n" if str == '.'; $stdout.flush
  683. return retries == 0 ? nil : (exit_code_sym ? thread[exit_code_sym] : 0)
  684. end
  685. def xcode_ci
  686. if ENV['IOS']
  687. # IOS platform does not support LuaJIT
  688. jit = ''
  689. amalg = ''
  690. deployment_target = "-DIPHONEOS_DEPLOYMENT_TARGET=#{ENV['DEPLOYMENT_TARGET']}"
  691. else
  692. jit = 'JIT'
  693. amalg = '-DURHO3D_LUAJIT_AMALG=1'
  694. deployment_target = "-DCMAKE_OSX_DEPLOYMENT_TARGET=#{ENV['DEPLOYMENT_TARGET']}"
  695. end
  696. system "./cmake_macosx.sh ../Build -DIOS=$IOS #{deployment_target} #{$build_options} -DURHO3D_DATABASE_SQLITE=1 -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'
  697. xcode_build(ENV['IOS'], '../Build/Urho3D.xcodeproj') or abort 'Failed to build or test Urho3D library'
  698. unless ENV['CI'] && ENV['IOS'] && ENV['PACKAGE_UPLOAD'] # Skip scaffolding test when packaging for iOS
  699. # Create a new project on the fly that uses newly built Urho3D library in the build tree
  700. scaffolding "../Build/generated/UsingBuildTree"
  701. 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'
  702. xcode_build(ENV['IOS'], '../Build/generated/UsingBuildTree/Scaffolding.xcodeproj') or abort 'Failed to build/test temporary project using Urho3D as external library'
  703. ENV['DESTDIR'] = ENV['HOME'] || Dir.home
  704. 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'
  705. # Create a new project on the fly that uses newly installed Urho3D SDK
  706. scaffolding "../Build/generated/UsingSDK"
  707. 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'
  708. xcode_build(ENV['IOS'], '../Build/generated/UsingSDK/Scaffolding.xcodeproj') or abort 'Failed to build/test temporary project using Urho3D as external library'
  709. end
  710. end
  711. def xcode_build ios, project, target = 'ALL_BUILD', extras = ''
  712. sdk = ios.to_i == 1 ? '-sdk iphonesimulator' : ''
  713. # Use xcpretty to filter output from xcodebuild when building
  714. system "xcodebuild -project #{project} -target #{target} -configuration #{$configuration} #{sdk} |xcpretty -c #{extras} && exit ${PIPESTATUS[0]}" or return nil
  715. if $testing == 1 && target == 'ALL_BUILD' # Disable testing for other targets such as 'doc', 'package', etc
  716. # Use vanila xcodebuild when testing as its output is instantaneous (ensure Travis-CI does not kill the process during testing)
  717. system "xcodebuild -project #{project} -target RUN_TESTS -configuration #{$configuration} #{sdk} #{extras}" or return nil
  718. end
  719. return 0
  720. end
  721. def append_new_release release, filename = '../doc-Build/_data/urho3d.json'
  722. begin
  723. urho3d_hash = JSON.parse File.read filename
  724. unless urho3d_hash['releases'].last == release
  725. urho3d_hash['releases'] << release
  726. end
  727. File.open(filename, 'w') { |file| file.puts urho3d_hash.to_json }
  728. return 0
  729. rescue
  730. nil
  731. end
  732. end
  733. def update_emscripten_data dir = '../doc-Build/samples', filename = '../doc-Build/_data/emscripten.json'
  734. begin
  735. emscripten_hash = JSON.parse File.read filename
  736. Dir.chdir(dir) { emscripten_hash['samples'] = Dir['*.html'].sort }
  737. File.open(filename, 'w') { |file| file.puts emscripten_hash.to_json }
  738. return 0
  739. rescue
  740. nil
  741. end
  742. end
  743. def bump_soversion filename
  744. begin
  745. version = File.read(filename).split '.'
  746. bump_version version, 2
  747. File.open(filename, 'w') { |file| file.puts version.join '.' }
  748. return 0
  749. rescue
  750. nil
  751. end
  752. end
  753. def bump_version version, index
  754. if index > 0 && version[index].to_i == 255
  755. version[index] = 0
  756. bump_version version, index - 1
  757. else
  758. version[index] = version[index].to_i + 1
  759. end
  760. end
  761. def setup_digital_keys
  762. system "bash -c 'mkdir -p ~/.ssh && chmod 700 ~/.ssh'" or abort 'Failed to create ~/.ssh directory'
  763. system "bash -c 'ssh-keyscan frs.sourceforge.net >>~/.ssh/known_hosts 2>/dev/null'" or abort 'Failed to append frs.sourceforge.net server public key to known_hosts'
  764. # 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.
  765. system "bash -c 'cat <<EOF >~/.ssh/id_rsa
  766. -----BEGIN RSA PRIVATE KEY-----
  767. MIIEpQIBAAKCAQEAnZGzFEypdXKY3KDT0Q3NLY4Bv74yKgJ4LIgbXothx8w4CfM0
  768. VeWBL/AE2iRISEWGB07LruM9y+U/wt58WlCVu001GuJuvXwWenlljsvH8qQlErYi
  769. oXlCwAeVVeanILGL8CPS7QlyzOwwnVF6NdcmfDJjTthBVFbvHrWGo5if86zcZyMR
  770. 2BB5QVEr5fU0yOPFp0+2p7J3cA6HQSKwjUiDtJ+lM62UQp7InCCT3qeh5KYHQcYb
  771. KVJTyj5iycVuBujHDwNAivLq82ojG7LcKjP+Ia8fblardCOQyFk6pSDM79NJJ2Dg
  772. 3ZbYIJeUmqSqFhRW/13Bro7Z1aNGrdh/XZkkHwIDAQABAoIBACHcBFJxYtzVIloO
  773. yVWcFKIcaO3OLjNu0monWVJIu1tW3BfvRijLJ6aoejJyJ4I4RmPdn9FWDZp6CeiT
  774. LL+vn21fWvELBWb8ekwZOCSmT7IpaboKn4h5aUmgl4udA/73iC2zVQkQxbWZb5zu
  775. vEdDk4aOwV5ZBDjecYX01hjjnEOdZHGJlF/H/Xs0hYX6WDG3/r9QCJJ0nfd1/Fk2
  776. zdbZRtAbyRz6ZHiYKnFQ441qRRaEbzunkvTBEwu9iqzlE0s/g49LJL0mKEp7rt/J
  777. 4iS3LZTQbJNx5J0ti8ZJKHhvoWb5RJxNimwKvVHC0XBZKTiLMrhnADmcpjLz53F8
  778. $SF_KEY
  779. sx27yCaeBeKXV0tFOeZmgK664VM9EgesjIX4sVOJ5mA3xBJBOtz9n66LjoIlIM58
  780. dvsAnJt7MUBdclL/RBHEjbUxgGBDcazfWSuJe0sGczhnXMN94ox4MSECgYEAx5cv
  781. cs/2KurjtWPanDGSz71LyGNdL/xQrAud0gi49H0tyYr0XmzNoe2CbZ/T5xGSZB92
  782. PBcz4rnHQ/oujo/qwjNpDD0xVLEU70Uy/XiY5/v2111TFC4clfE/syZPywKAztt3
  783. y2l5z+QdsNigRPDhKw+7CFYaAnYBEISxR6nabT8CgYEAqHrM8fdn2wsCNE6XvkZQ
  784. O7ZANHNIKVnaRqW/8HW7EFAWQrlQTgzFbtR4uNBIqAtPsvwSx8Pk652+OR1VKfSv
  785. ya3dtqY3rY/ErXWyX0nfPQEbYj/oh8LbS6zPw75yIorP3ACIwMw3GRNWIvkdAGTn
  786. BMUgpWHUDLWWpWRrSzNi90ECgYEAkxxzQ6vW5OFGv17/NdswO+BpqCTc/c5646SY
  787. ScRWFxbhFclOvv5xPqYiWYzRkmIYRaYO7tGnU7jdD9SqVjfrsAJWrke4QZVYOdgG
  788. cl9eTLchxLGr15b5SOeNrQ1TCO4qZM3M6Wgv+bRI0h2JW+c0ABpTIBzehOvXcwZq
  789. 6MhgD98CgYEAtOPqc4aoIRUy+1oijpWs+wU7vAc8fe4sBHv5fsv7naHuPqZgyQYY
  790. 32a54xZxlsBw8T5P4BDy40OR7fu+6miUfL+WxUdII4fD3grlIPw6bpNE0bCDykv5
  791. RLq28S11hDrKf/ZetXNuIprfTlhl6ISBy+oWQibhXmFZSxEiXNV6hCQ=
  792. -----END RSA PRIVATE KEY-----
  793. EOF'" or abort 'Failed to create user private key to id_rsa'
  794. system "bash -c 'chmod 600 ~/.ssh/id_rsa'" or abort 'Failed to change id_rsa file permission'
  795. end
  796. # Load custom rake scripts
  797. Dir['.rake/*.rake'].each { |r| load r }
  798. # vi: set ts=2 sw=2 expandtab: