summaryrefslogtreecommitdiff
path: root/test/unit-test/vendor/ceedling/plugins/dependencies/lib/dependencies.rb
blob: fc8ae996807ddccce92cabd95546c03cab3d71f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
require 'ceedling/plugin'
require 'ceedling/constants'

DEPENDENCIES_ROOT_NAME         = 'dependencies'
DEPENDENCIES_TASK_ROOT         = DEPENDENCIES_ROOT_NAME + ':'
DEPENDENCIES_SYM               = DEPENDENCIES_ROOT_NAME.to_sym

class Dependencies < Plugin

  def setup
    @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))

    # Set up a fast way to look up dependencies by name or static lib path
    @dependencies = {}
    @dynamic_libraries = []
    DEPENDENCIES_LIBRARIES.each do |deplib|

      @dependencies[ deplib[:name] ] = deplib.clone
      all_deps = get_static_libraries_for_dependency(deplib) +
                 get_dynamic_libraries_for_dependency(deplib) +
                 get_include_directories_for_dependency(deplib) +
                 get_source_files_for_dependency(deplib)
      all_deps.each do |key|
        @dependencies[key] = @dependencies[ deplib[:name] ]
      end

      @dynamic_libraries += get_dynamic_libraries_for_dependency(deplib)
    end
  end

  def config
    updates = {
      :collection_paths_include => COLLECTION_PATHS_INCLUDE,
      :collection_all_headers => COLLECTION_ALL_HEADERS,
    }

    @ceedling[DEPENDENCIES_SYM].get_include_directories_for_dependency(deplib).each do |incpath|
      updates[:collection_paths_include] << incpath
      Dir[ File.join(incpath, "*#{EXTENSION_HEADER}") ].each do |f|
        updates[:collection_all_headers] << f
      end
    end

    return updates
  end

  def get_name(deplib)
    raise "Each dependency must have a name!" if deplib[:name].nil?
    return deplib[:name].gsub(/\W*/,'')
  end

  def get_source_path(deplib)
    return deplib[:source_path] || File.join('dependencies', get_name(deplib))
  end

  def get_build_path(deplib)
    return deplib[:build_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
  end

  def get_artifact_path(deplib)
    return deplib[:artifact_path] || deplib[:source_path] || File.join('dependencies', get_name(deplib))
  end

  def get_working_paths(deplib)
    paths = [deplib[:source_path], deplib[:build_path], deplib[:artifact_paths]].compact.uniq
    paths = [ File.join('dependencies', get_name(deplib)) ] if (paths.empty?)
    return paths
  end

  def get_static_libraries_for_dependency(deplib)
    (deplib[:artifacts][:static_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  end

  def get_dynamic_libraries_for_dependency(deplib)
    (deplib[:artifacts][:dynamic_libraries] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  end

  def get_source_files_for_dependency(deplib)
    (deplib[:artifacts][:source] || []).map {|path| File.join(get_artifact_path(deplib), path)}
  end

  def get_include_directories_for_dependency(deplib)
    paths = (deplib[:artifacts][:includes] || []).map {|path| File.join(get_artifact_path(deplib), path)}
    @ceedling[:file_system_utils].collect_paths(paths)
  end

  def set_env_if_required(lib_path)
    blob = @dependencies[lib_path]
    raise "Could not find dependency '#{lib_path}'" if blob.nil?
    return if (blob[:environment].nil?)
    return if (blob[:environment].empty?)

    blob[:environment].each do |e|
      m = e.match(/^(\w+)\s*(\+?\-?=)\s*(.*)$/)
      unless m.nil?
        case m[2]
        when "+="
          ENV[m[1]] = (ENV[m[1]] || "") + m[3]
        when "-="
          ENV[m[1]] = (ENV[m[1]] || "").gsub(m[3],'')
        else
          ENV[m[1]] = m[3]
        end
      end
    end
  end

  def fetch_if_required(lib_path)
    blob = @dependencies[lib_path]
    raise "Could not find dependency '#{lib_path}'" if blob.nil?
    return if (blob[:fetch].nil?)
    return if (blob[:fetch][:method].nil?)
    return if (directory(blob[:source_path]) && !Dir.empty?(blob[:source_path]))

    steps = case blob[:fetch][:method]
            when :none
              return
            when :zip
              [ "gzip -d #{blob[:fetch][:source]}" ]
            when :git
              branch = blob[:fetch][:tag] || blob[:fetch][:branch] || ''
              branch = ("-b " + branch) unless branch.empty?
              unless blob[:fetch][:hash].nil?
                # Do a deep clone to ensure the commit we want is available
                retval = [ "git clone #{branch} #{blob[:fetch][:source]} ." ]
                # Checkout the specified commit
                retval << "git checkout #{blob[:fetch][:hash]}"
              else
                # Do a thin clone
                retval = [ "git clone #{branch} --depth 1 #{blob[:fetch][:source]} ." ]
              end
            when :svn
              revision = blob[:fetch][:revision] || ''
              revision = ("--revision " + branch) unless branch.empty?
              retval = [ "svn checkout #{revision} #{blob[:fetch][:source]} ." ]
              retval
            when :custom
              blob[:fetch][:executable]
            else
              raise "Unknown fetch method '#{blob[:fetch][:method].to_s}' for dependency '#{blob[:name]}'"
            end

    # Perform the actual fetching
    @ceedling[:streaminator].stdout_puts("Fetching dependency #{blob[:name]}...", Verbosity::NORMAL)
    Dir.chdir(get_source_path(blob)) do
      steps.each do |step|
        @ceedling[:tool_executor].exec( step )
      end
    end
  end

  def build_if_required(lib_path)
    blob = @dependencies[lib_path]
    raise "Could not find dependency '#{lib_path}'" if blob.nil?

    # We don't clean anything unless we know how to fetch a new copy
    if (blob[:build].nil? || blob[:build].empty?)
      @ceedling[:streaminator].stdout_puts("Nothing to build for dependency #{blob[:name]}", Verbosity::NORMAL)
      return
    end

    # Perform the build
    @ceedling[:streaminator].stdout_puts("Building dependency #{blob[:name]}...", Verbosity::NORMAL)
    Dir.chdir(get_build_path(blob)) do
      blob[:build].each do |step|
        @ceedling[:tool_executor].exec( step )
      end
    end
  end

  def clean_if_required(lib_path)
    blob = @dependencies[lib_path]
    raise "Could not find dependency '#{lib_path}'" if blob.nil?

    # We don't clean anything unless we know how to fetch a new copy
    if (blob[:fetch].nil? || blob[:fetch][:method].nil? || (blob[:fetch][:method] == :none))
      @ceedling[:streaminator].stdout_puts("Nothing to clean for dependency #{blob[:name]}", Verbosity::NORMAL)
      return
    end

    # Perform the actual Cleaning
    @ceedling[:streaminator].stdout_puts("Cleaning dependency #{blob[:name]}...", Verbosity::NORMAL)
    get_working_paths(blob).each do |path|
      FileUtils.rm_rf(path) if File.directory?(path)
    end
  end

  def deploy_if_required(lib_path)
    blob = @dependencies[lib_path]
    raise "Could not find dependency '#{lib_path}'" if blob.nil?

    # We don't need to deploy anything if there isn't anything to deploy
    if (blob[:artifacts].nil? || blob[:artifacts][:dynamic_libraries].nil?  || blob[:artifacts][:dynamic_libraries].empty?)
      @ceedling[:streaminator].stdout_puts("Nothing to deploy for dependency #{blob[:name]}", Verbosity::NORMAL)
      return
    end

    # Perform the actual Deploying
    @ceedling[:streaminator].stdout_puts("Deploying dependency #{blob[:name]}...", Verbosity::NORMAL)
    FileUtils.cp( lib_path, File.dirname(PROJECT_RELEASE_BUILD_TARGET) )
  end

  def add_headers_and_sources()
    # Search for header file paths and files to add to our collections
    DEPENDENCIES_LIBRARIES.each do |deplib|
      get_include_directories_for_dependency(deplib).each do |header|
        cfg = @ceedling[:configurator].project_config_hash
        cfg[:collection_paths_include] << header
        cfg[:collection_paths_source_and_include] << header
        cfg[:collection_paths_test_support_source_include] << header
        cfg[:collection_paths_test_support_source_include_vendor] << header
        cfg[:collection_paths_release_toolchain_include] << header
        Dir[ File.join(header, "*#{EXTENSION_HEADER}") ].each do |f|
          cfg[:collection_all_headers] << f
        end
      end

      get_source_files_for_dependency(deplib).each do |source|
        cfg = @ceedling[:configurator].project_config_hash
        cfg[:collection_paths_source_and_include] << source
        cfg[:collection_paths_test_support_source_include] << source
        cfg[:collection_paths_test_support_source_include_vendor] << source
        cfg[:collection_paths_release_toolchain_include] << source
        Dir[ File.join(source, "*#{EXTENSION_SOURCE}") ].each do |f|
          cfg[:collection_all_source] << f
        end
      end
    end

    # Make all these updated files findable by Ceedling
    @ceedling[:file_finder].prepare_search_sources()
  end
end

# end blocks always executed following rake run
END {
}