dependencies.rb 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. require 'ceedling/plugin'
  2. require 'ceedling/constants'
  3. DEPENDENCIES_ROOT_NAME = 'dependencies'
  4. DEPENDENCIES_TASK_ROOT = DEPENDENCIES_ROOT_NAME + ':'
  5. DEPENDENCIES_SYM = DEPENDENCIES_ROOT_NAME.to_sym
  6. class Dependencies < Plugin
  7. def setup
  8. @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
  9. # Set up a fast way to look up dependencies by name or static lib path
  10. @dependencies = {}
  11. @dynamic_libraries = []
  12. DEPENDENCIES_LIBRARIES.each do |deplib|
  13. @dependencies[ deplib[:name] ] = deplib.clone
  14. all_deps = get_static_libraries_for_dependency(deplib) +
  15. get_dynamic_libraries_for_dependency(deplib) +
  16. get_include_directories_for_dependency(deplib) +
  17. get_source_files_for_dependency(deplib)
  18. all_deps.each do |key|
  19. @dependencies[key] = @dependencies[ deplib[:name] ]
  20. end
  21. @dynamic_libraries += get_dynamic_libraries_for_dependency(deplib)
  22. end
  23. end
  24. def config
  25. updates = {
  26. :collection_paths_include => COLLECTION_PATHS_INCLUDE,
  27. :collection_all_headers => COLLECTION_ALL_HEADERS,
  28. }
  29. @ceedling[DEPENDENCIES_SYM].get_include_directories_for_dependency(deplib).each do |incpath|
  30. updates[:collection_paths_include] << incpath
  31. Dir[ File.join(incpath, "*#{EXTENSION_HEADER}") ].each do |f|
  32. updates[:collection_all_headers] << f
  33. end
  34. end
  35. return updates
  36. end
  37. def get_name(deplib)
  38. raise "Each dependency must have a name!" if deplib[:name].nil?
  39. return deplib[:name].gsub(/\W*/,'')
  40. end
  41. def get_source_path(deplib)
  42. return deplib[:source_path] || File.join('dependencies', get_name(deplib))
  43. end
  44. def get_build_path(deplib)
  45. return deplib[:build_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
  46. end
  47. def get_artifact_path(deplib)
  48. return deplib[:artifact_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
  49. end
  50. def get_working_paths(deplib)
  51. paths = [deplib[:source_path], deplib[:build_path], deplib[:artifact_paths]].compact.uniq
  52. paths = [ File.join('dependencies', get_name(deplib)) ] if (paths.empty?)
  53. return paths
  54. end
  55. def get_static_libraries_for_dependency(deplib)
  56. (deplib[:artifacts][:static_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  57. end
  58. def get_dynamic_libraries_for_dependency(deplib)
  59. (deplib[:artifacts][:dynamic_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  60. end
  61. def get_source_files_for_dependency(deplib)
  62. (deplib[:artifacts][:source] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  63. end
  64. def get_include_directories_for_dependency(deplib)
  65. paths = (deplib[:artifacts][:includes] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  66. @ceedling[:file_system_utils].collect_paths(paths)
  67. end
  68. def set_env_if_required(lib_path)
  69. blob = @dependencies[lib_path]
  70. raise "Could not find dependency '#{lib_path}'" if blob.nil?
  71. return if (blob[:environment].nil?)
  72. return if (blob[:environment].empty?)
  73. blob[:environment].each do |e|
  74. m = e.match(/^(\w+)\s*(\+?\-?=)\s*(.*)$/)
  75. unless m.nil?
  76. case m[2]
  77. when "+="
  78. ENV[m[1]] = (ENV[m[1]] || "") + m[3]
  79. when "-="
  80. ENV[m[1]] = (ENV[m[1]] || "").gsub(m[3],'')
  81. else
  82. ENV[m[1]] = m[3]
  83. end
  84. end
  85. end
  86. end
  87. def fetch_if_required(lib_path)
  88. blob = @dependencies[lib_path]
  89. raise "Could not find dependency '#{lib_path}'" if blob.nil?
  90. return if (blob[:fetch].nil?)
  91. return if (blob[:fetch][:method].nil?)
  92. return if (directory(blob[:source_path]) && !Dir.empty?(blob[:source_path]))
  93. steps = case blob[:fetch][:method]
  94. when :none
  95. return
  96. when :zip
  97. [ "gzip -d #{blob[:fetch][:source]}" ]
  98. when :git
  99. branch = blob[:fetch][:tag] || blob[:fetch][:branch] || ''
  100. branch = ("-b " + branch) unless branch.empty?
  101. unless blob[:fetch][:hash].nil?
  102. # Do a deep clone to ensure the commit we want is available
  103. retval = [ "git clone #{branch} #{blob[:fetch][:source]} ." ]
  104. # Checkout the specified commit
  105. retval << "git checkout #{blob[:fetch][:hash]}"
  106. else
  107. # Do a thin clone
  108. retval = [ "git clone #{branch} --depth 1 #{blob[:fetch][:source]} ." ]
  109. end
  110. when :svn
  111. revision = blob[:fetch][:revision] || ''
  112. revision = ("--revision " + branch) unless branch.empty?
  113. retval = [ "svn checkout #{revision} #{blob[:fetch][:source]} ." ]
  114. retval
  115. when :custom
  116. blob[:fetch][:executable]
  117. else
  118. raise "Unknown fetch method '#{blob[:fetch][:method].to_s}' for dependency '#{blob[:name]}'"
  119. end
  120. # Perform the actual fetching
  121. @ceedling[:streaminator].stdout_puts("Fetching dependency #{blob[:name]}...", Verbosity::NORMAL)
  122. Dir.chdir(get_source_path(blob)) do
  123. steps.each do |step|
  124. @ceedling[:tool_executor].exec( step )
  125. end
  126. end
  127. end
  128. def build_if_required(lib_path)
  129. blob = @dependencies[lib_path]
  130. raise "Could not find dependency '#{lib_path}'" if blob.nil?
  131. # We don't clean anything unless we know how to fetch a new copy
  132. if (blob[:build].nil? || blob[:build].empty?)
  133. @ceedling[:streaminator].stdout_puts("Nothing to build for dependency #{blob[:name]}", Verbosity::NORMAL)
  134. return
  135. end
  136. # Perform the build
  137. @ceedling[:streaminator].stdout_puts("Building dependency #{blob[:name]}...", Verbosity::NORMAL)
  138. Dir.chdir(get_build_path(blob)) do
  139. blob[:build].each do |step|
  140. @ceedling[:tool_executor].exec( step )
  141. end
  142. end
  143. end
  144. def clean_if_required(lib_path)
  145. blob = @dependencies[lib_path]
  146. raise "Could not find dependency '#{lib_path}'" if blob.nil?
  147. # We don't clean anything unless we know how to fetch a new copy
  148. if (blob[:fetch].nil? || blob[:fetch][:method].nil? || (blob[:fetch][:method] == :none))
  149. @ceedling[:streaminator].stdout_puts("Nothing to clean for dependency #{blob[:name]}", Verbosity::NORMAL)
  150. return
  151. end
  152. # Perform the actual Cleaning
  153. @ceedling[:streaminator].stdout_puts("Cleaning dependency #{blob[:name]}...", Verbosity::NORMAL)
  154. get_working_paths(blob).each do |path|
  155. FileUtils.rm_rf(path) if File.directory?(path)
  156. end
  157. end
  158. def deploy_if_required(lib_path)
  159. blob = @dependencies[lib_path]
  160. raise "Could not find dependency '#{lib_path}'" if blob.nil?
  161. # We don't need to deploy anything if there isn't anything to deploy
  162. if (blob[:artifacts].nil? || blob[:artifacts][:dynamic_libraries].nil? || blob[:artifacts][:dynamic_libraries].empty?)
  163. @ceedling[:streaminator].stdout_puts("Nothing to deploy for dependency #{blob[:name]}", Verbosity::NORMAL)
  164. return
  165. end
  166. # Perform the actual Deploying
  167. @ceedling[:streaminator].stdout_puts("Deploying dependency #{blob[:name]}...", Verbosity::NORMAL)
  168. FileUtils.cp( lib_path, File.dirname(PROJECT_RELEASE_BUILD_TARGET) )
  169. end
  170. def add_headers_and_sources()
  171. # Search for header file paths and files to add to our collections
  172. DEPENDENCIES_LIBRARIES.each do |deplib|
  173. get_include_directories_for_dependency(deplib).each do |header|
  174. cfg = @ceedling[:configurator].project_config_hash
  175. cfg[:collection_paths_include] << header
  176. cfg[:collection_paths_source_and_include] << header
  177. cfg[:collection_paths_test_support_source_include] << header
  178. cfg[:collection_paths_test_support_source_include_vendor] << header
  179. cfg[:collection_paths_release_toolchain_include] << header
  180. Dir[ File.join(header, "*#{EXTENSION_HEADER}") ].each do |f|
  181. cfg[:collection_all_headers] << f
  182. end
  183. end
  184. get_source_files_for_dependency(deplib).each do |source|
  185. cfg = @ceedling[:configurator].project_config_hash
  186. cfg[:collection_paths_source_and_include] << source
  187. cfg[:collection_paths_test_support_source_include] << source
  188. cfg[:collection_paths_test_support_source_include_vendor] << source
  189. cfg[:collection_paths_release_toolchain_include] << source
  190. Dir[ File.join(source, "*#{EXTENSION_SOURCE}") ].each do |f|
  191. cfg[:collection_all_source] << f
  192. end
  193. end
  194. end
  195. # Make all these updated files findable by Ceedling
  196. @ceedling[:file_finder].prepare_search_sources()
  197. end
  198. end
  199. # end blocks always executed following rake run
  200. END {
  201. }