vendor 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/CHANGELOG.md +6 -0
  2. data/Gemfile.lock +1 -1
  3. data/LICENSE +1 -1
  4. data/Readme.markdown +2 -1
  5. data/VERSION +1 -1
  6. data/lib/vendor/cli/app.rb +13 -17
  7. data/lib/vendor/spec.rb +244 -55
  8. data/lib/vendor/vendor_file/library/base.rb +43 -63
  9. data/lib/vendor/vendor_file/loader.rb +8 -0
  10. data/lib/vendor/vendor_spec/builder.rb +19 -8
  11. data/lib/vendor/xcode.rb +0 -1
  12. data/lib/vendor/xcode/project.rb +198 -469
  13. data/spec/lib/vendor/spec_spec.rb +34 -10
  14. data/spec/lib/vendor/vendor_file/library/base_spec.rb +41 -49
  15. data/spec/lib/vendor/vendor_spec/builder_spec.rb +26 -0
  16. data/spec/support/resources/cache/base/DKBenchmark-0.1-Manifest/vendor.json +1 -1
  17. data/spec/support/resources/cache/base/DKBenchmark-0.1-Vendorspec/DKBenchmark.vendorspec +2 -0
  18. data/spec/support/resources/vendors/DKBenchmark/DKBenchmark.vendorspec +2 -0
  19. data/spec/support/resources/vendors/DKBenchmarkFramework/DKBenchmark.framework/DKBenchmark +0 -0
  20. data/spec/support/resources/vendors/DKBenchmarkFramework/DKBenchmark.framework/Versions/A/DKBenchmark +0 -0
  21. data/spec/support/resources/vendors/DKBenchmarkFramework/DKBenchmark.framework/Versions/A/Headers/DKBenchmark.h +18 -0
  22. data/spec/support/resources/vendors/DKBenchmarkFramework/DKBenchmark.vendorspec +23 -0
  23. data/vendor.gemspec +1 -0
  24. metadata +111 -63
  25. data/lib/vendor/xcode/proxy.rb +0 -31
  26. data/lib/vendor/xcode/proxy/base.rb +0 -129
  27. data/lib/vendor/xcode/proxy/pbx_aggregate_target.rb +0 -11
  28. data/lib/vendor/xcode/proxy/pbx_build_file.rb +0 -9
  29. data/lib/vendor/xcode/proxy/pbx_container_item_proxy.rb +0 -8
  30. data/lib/vendor/xcode/proxy/pbx_file_reference.rb +0 -41
  31. data/lib/vendor/xcode/proxy/pbx_frameworks_build_phase.rb +0 -15
  32. data/lib/vendor/xcode/proxy/pbx_group.rb +0 -35
  33. data/lib/vendor/xcode/proxy/pbx_native_target.rb +0 -11
  34. data/lib/vendor/xcode/proxy/pbx_project.rb +0 -12
  35. data/lib/vendor/xcode/proxy/pbx_reference_proxy.rb +0 -7
  36. data/lib/vendor/xcode/proxy/pbx_resources_build_phase.rb +0 -15
  37. data/lib/vendor/xcode/proxy/pbx_shell_script_build_phase.rb +0 -15
  38. data/lib/vendor/xcode/proxy/pbx_sources_build_phase.rb +0 -15
  39. data/lib/vendor/xcode/proxy/pbx_target_dependency.rb +0 -7
  40. data/lib/vendor/xcode/proxy/pbx_variant_group.rb +0 -7
  41. data/lib/vendor/xcode/proxy/unknown.rb +0 -8
  42. data/lib/vendor/xcode/proxy/xc_build_configuration.rb +0 -7
  43. data/lib/vendor/xcode/proxy/xc_configuration_list.rb +0 -9
  44. data/lib/vendor/xcode/proxy/xc_version_group.rb +0 -7
  45. data/spec/lib/vendor/xcode/project_spec.rb +0 -635
  46. data/spec/lib/vendor/xcode/proxy/base_spec.rb +0 -88
  47. data/spec/lib/vendor/xcode/proxy/pbx_file_reference_spec.rb +0 -26
  48. data/spec/lib/vendor/xcode/proxy/pbx_group_spec.rb +0 -27
  49. data/spec/lib/vendor/xcode/proxy/pbx_project_spec.rb +0 -29
@@ -23,6 +23,14 @@ module Vendor
23
23
  self.libraries = @dsl.libraries
24
24
  end
25
25
 
26
+ def libraries_to_install
27
+ unless @graph.version_conflicts?
28
+ @graph.libraries_to_install.each do |library,targets|
29
+ yield library, targets if block_given?
30
+ end
31
+ end
32
+ end
33
+
26
34
  def install(project)
27
35
  unless @graph.version_conflicts?
28
36
  @graph.libraries_to_install.each do |lib|
@@ -43,37 +43,48 @@ module Vendor
43
43
 
44
44
  private
45
45
 
46
+ # Find all the files within the vendor spec to install
47
+ def vendor_spec_files_to_install
48
+ Array(@vendor_spec.files) + Array(@vendor_spec.resources)
49
+ end
50
+
46
51
  def copy_files(data_dir)
47
52
  data_files = []
48
53
 
49
54
  raise NoFilesError.new("No file definition found for #{@name}") if @vendor_spec.files.nil?
50
55
 
51
- # Remove files that are within folders with a ".", such as ".bundle"
52
- # and ".frameworks"
53
- copy_files = @vendor_spec.files.reject { |file| file =~ /\/?[^\/]+\.[^\/]+\// }
56
+ copy_files = vendor_spec_files_to_install
54
57
 
55
58
  raise NoFilesError.new("No files found for packaging") if copy_files.empty?
56
59
 
57
60
  copy_files.each do |file|
58
61
  dir = File.dirname(file)
59
62
  path = File.join(@folder, file)
60
- copy_to_dir = File.expand_path(File.join(data_dir, dir))
61
- copy_to_file = File.join(copy_to_dir, File.basename(file))
63
+ if File.directory? path
64
+ copy_to_dir = File.expand_path(File.join(data_dir, dir, File.basename(file)))
65
+ copy_to_file = File.expand_path(copy_to_dir)
66
+ else
67
+ copy_to_dir = File.expand_path(File.join(data_dir, dir))
68
+ copy_to_file = File.join(copy_to_dir, File.basename(file))
69
+ end
62
70
 
63
71
  Vendor.ui.debug "Creating dir #{copy_to_dir}"
64
72
  FileUtils.mkdir_p copy_to_dir
65
73
 
66
74
  Vendor.ui.debug "Copying #{path} to #{copy_to_file}"
67
- FileUtils.cp_r path, copy_to_file
75
+ FileUtils.copy_entry path, copy_to_file
68
76
 
69
77
  data_files << copy_to_file
78
+ if File.directory?(path)
79
+ data_files.concat(Dir.glob(File.join(copy_to_file, "**", "*")))
80
+ end
70
81
  end
71
-
82
+
72
83
  data_files
73
84
  end
74
85
 
75
86
  def zip_file(filename, files, base_dir)
76
- Zip::ZipFile.open(filename, Zip::ZipFile::CREATE)do |zipfile|
87
+ Zip::ZipFile.open(filename, Zip::ZipFile::CREATE) do |zipfile|
77
88
 
78
89
  files.each do |file|
79
90
  path = file.gsub(base_dir, '').gsub(/^\//, '')
@@ -2,7 +2,6 @@ module Vendor
2
2
 
3
3
  module XCode
4
4
 
5
- autoload :Proxy, "vendor/xcode/proxy"
6
5
  autoload :Project, "vendor/xcode/project"
7
6
 
8
7
  end
@@ -1,503 +1,232 @@
1
- require 'json'
1
+ require 'xcoder'
2
2
 
3
3
  module Vendor::XCode
4
4
 
5
5
  class Project
6
6
 
7
- # Build settings and the format that they should be stored in
8
- BUILD_SETTING_TYPES = {
9
- "OTHER_LDFLAGS" => :array
10
- }
11
-
12
- require 'fileutils'
13
-
14
- attr_reader :name
15
- attr_reader :object_version
16
- attr_reader :archive_version
17
- attr_reader :objects
18
- attr_reader :root_object
19
- attr_reader :project_folder
20
-
21
- attr_accessor :dirty
7
+ attr_reader :project
22
8
 
23
9
  def initialize(project_folder)
24
- @project_folder = project_folder
25
- @pbxproject = ::File.join(project_folder, "project.pbxproj")
26
- @name = File.basename(project_folder).split(".").first
27
- @dirty = false
28
-
29
- reload
30
- end
31
-
32
- def reload
33
- # We switch between our custom PList converter and the JSON format
34
- # because the custom implementation isn't very reliable. We use it mainly
35
- # so the gem can run on systems that don't have plutil installed (like our
36
- # CI server). The plutil app is far more reliable.
37
- if RUBY_PLATFORM !~ /darwin/ || ENV['PARSER'] == 'custom'
38
- contents = File.readlines(@pbxproject).join("\n")
39
- parsed = Vendor::Plist.parse_ascii(contents)
40
- else
41
- parsed = JSON.parse(`plutil -convert json -o - "#{@pbxproject}"`)
42
- end
43
-
44
- @object_version = parsed['objectVersion'].to_i
45
- @archive_version = parsed['archiveVersion'].to_i
46
-
47
- @objects_by_id = {}
48
-
49
- @objects = parsed['objects'].map do |id, attributes|
50
- begin
51
- klass = Vendor::XCode::Proxy.const_get(attributes['isa'])
52
- rescue NameError => e
53
- klass = Vendor::XCode::Proxy::Unknown
54
- end
55
-
56
- @objects_by_id[id] = klass.new(:project => self, :id => id, :attributes => attributes)
57
- end
58
-
59
- @objects.each { |object| object.send(:after_initialize) }
60
-
61
- @root_object = @objects_by_id[parsed['rootObject']]
62
- end
63
-
64
- def find_object(id)
65
- @objects_by_id[id]
66
- end
67
-
68
- def find_target(t)
69
- # Are we already a target?
70
- if t.kind_of?(Vendor::XCode::Proxy::Base)
71
- t
10
+ @project = Xcode.project project_folder
11
+ end
12
+
13
+ #
14
+ # Install the library into the project for the selected targets.
15
+ #
16
+ # @param [Library] library the instance that conveys the requirements to
17
+ # install.
18
+ # @param [Array<Symbols>] targets to install this library; The value :all
19
+ # is a special target name that means all targets.
20
+ #
21
+ def install(library,targets)
22
+
23
+ Vendor.ui.info "## Installing __#{library.name} (#{library.version})__\n\n"
24
+
25
+ project_targets = project_targets_from_specified_targets(targets)
26
+
27
+ if project_targets.empty?
28
+ Vendor.ui.warn "* The project '#{project.name}' does not have any matching targets: #{targets.join(", ")}"
29
+ return
30
+ end
31
+
32
+ library_pathname = "Vendor/#{library.name}"
33
+
34
+ files_added = create_library_folders_and_groups library_pathname, library.files
35
+
36
+ resources_added = create_library_folders_and_groups library_pathname, library.resources, 'resource'
37
+
38
+ frameworks_added = add_required_frameworks_to_project library.frameworks
39
+
40
+
41
+ source_files = files_added.find_all {|file| File.extname(file.path.to_s) =~ /\.mm?$/ }
42
+
43
+ framework_files = frameworks_added + files_added.find_all {|file| File.extname(file.path.to_s) =~ /\.a$|\.framework$/ }
44
+
45
+
46
+ project_targets.each do |target|
47
+
48
+ Vendor.ui.info "\n### Configuring Build Target '__#{target.name}__'\n\n"
49
+
50
+ add_source_files_to_sources_build_phase source_files, target.sources_build_phase, library.per_file_flag
51
+
52
+ add_resource_files_to_resources_build_phase resources_added, target.resources_build_phase
53
+
54
+ add_frameworks_to_frameworks_build_phase framework_files, target.framework_build_phase
55
+
56
+ add_build_settings_to_target_configurations target, library.build_settings
57
+
58
+ end
59
+
60
+ project.save!
61
+
62
+ end
63
+
64
+ private
65
+
66
+
67
+ #
68
+ # Convert the target names to the actual target objects within the project
69
+ #
70
+ # @param [Array<Symbols>] targets to install this library; The value :all
71
+ # is a special target name that means all targets.
72
+ #
73
+ # @return [Array<Target>] the targets that match the specified target names.
74
+ #
75
+ def project_targets_from_specified_targets(specified_targets)
76
+
77
+ if specified_targets == [:all]
78
+
79
+ project.targets
80
+
72
81
  else
73
- root_object.targets.find { |x| x.name == t }
74
- end
75
- end
76
-
77
- def find_group(path)
78
- current = root_object.main_group
79
-
80
- path.split("/").each do |name|
81
- current = current.children.find { |x| (x.respond_to?(:name) ? x.name : x.path) == name }
82
- return nil unless current
83
- end
84
-
85
- current
86
- end
87
-
88
- def create_group(path)
89
- current = root_object.main_group
90
-
91
- path.split("/").each do |name|
92
- group = current.children.find { |x| (x.respond_to?(:name) ? x.name : x.path) == name }
93
-
94
- unless group
95
- group = Vendor::XCode::Proxy::PBXGroup.new(:project => self,
96
- :id => Vendor::XCode::Proxy::Base.generate_id,
97
- :attributes => { 'path' => name, 'sourceTree' => '<group>', 'children' => [] })
98
-
99
- # Set the parent
100
- group.parent = current
101
-
102
- @objects_by_id[group.id] = group
103
-
104
- # This is hacky
105
- current.attributes['children'] << group.id
106
- end
107
-
108
- current = group
109
- end
110
-
111
- # Mark as dirty
112
- @dirty = true
113
-
114
- current
115
- end
116
-
117
- def remove_group(path)
118
- group = find_group(path)
119
-
120
- # If we have the group
121
- if group
122
-
123
- ids_to_remove = []
124
-
125
- # Remove the children from the file system
126
- group.children.each do |child|
127
- if child.group? # Is it a group?
128
- remove_group child.full_path # Recursivley remove the child group
129
- elsif child.file? # Or a file
130
- file = File.expand_path(File.join(@project_folder, "..", child.full_path))
131
-
132
- # Remove the file from the filesystem
133
- if File.exist?(file)
134
- FileUtils.rm_rf file
135
- end
136
- else
137
- Vendor.ui.error "Couldn't remove object: #{child}"
138
- end
139
-
140
- # Remove from the targets (if we can)
141
- root_object.targets.each { |t| remove_file_from_target(child, t) }
142
-
143
- # Remove the file from the parent
144
- child.parent.attributes['children'].delete child.id
145
-
146
- # Add the id to the list of stuff to remove. If we do this
147
- # during the loop, bad things happen - not sure why.
148
- ids_to_remove << child.id
149
- end
150
-
151
- # Remove the group from the parent
152
- group.parent.attributes['children'].delete group.id
153
-
154
- # Add to the list of stuff to remove
155
- ids_to_remove << group.id
156
-
157
- ids_to_remove.each do |id|
158
- @objects_by_id.delete id
82
+
83
+ # Take each specified target names and compare those with the targets
84
+ # specified within the project. Find all that match and return them,
85
+ # ignoring aggregate targets that may match the name as they are
86
+ # not capable of love that comes with bearing files.
87
+
88
+ # @note project#target(name) seems like it would be a better choice,
89
+ # however, the Xcoder implementation raises an error when a target
90
+ # does not match the specified name.
91
+
92
+ specified_targets.uniq.map do |name|
93
+
94
+ project.targets.reject {|target| target.isa == "PBXAggregateTarget" }.find_all {|target| target.name == name }
95
+
96
+ end.flatten
97
+ end
98
+
99
+ end
100
+
101
+ #
102
+ #
103
+ # @param [String] pathname the path to create for the library
104
+ # @param [Array<String>] files to copy into the project and create in the
105
+ # project.
106
+ # @return [Array<FileReference>] an array of all the files that were added
107
+ # to the project.
108
+ #
109
+ def create_library_folders_and_groups(pathname,files,section="")
110
+
111
+ # Create the physical path for the library
112
+
113
+ FileUtils.mkdir_p pathname
114
+
115
+ # Create the project's logical group for the library
116
+
117
+ library_group = project.group pathname
118
+
119
+ Vendor.ui.info "* Installing #{files.count} #{section} file(s)\n\n"
120
+
121
+ files.map do |file|
122
+
123
+ target_filepath = "#{pathname}/#{File.basename(file)}"
124
+
125
+ Vendor.ui.debug " > from: #{file}\n\n"
126
+ Vendor.ui.debug " > to: #{target_filepath}\n\n"
127
+
128
+ # Copy the physical file to the library path
129
+
130
+ FileUtils.cp_r file, target_filepath
131
+
132
+ # Copy the project's logical files
133
+
134
+ library_group.create_file 'name' => File.basename(file), 'path' => target_filepath, 'sourceTree' => 'SOURCE_ROOT'
135
+
136
+ end.compact
137
+
138
+ end
139
+
140
+ #
141
+ # @param [Array<String>] frameworks to add to the frameworks section of the
142
+ # project.
143
+ # @return [Array<FileReference>] an array of all the frameworks and system
144
+ # libraries that were added to the project.
145
+ #
146
+ def add_required_frameworks_to_project(frameworks)
147
+ frameworks.map do |framework_name|
148
+ if File.extname(framework_name) =~ /^\.dylib$/
149
+ project.frameworks_group.create_system_library(framework_name)
150
+ else
151
+ project.frameworks_group.create_system_framework(framework_name)
159
152
  end
160
-
161
- # Mark as dirty
162
- @dirty = true
163
-
164
- else
165
- false
166
153
  end
167
154
  end
168
-
169
- def add_framework(framework, options = {})
170
- # Find targets and filter out aggregate targets (we can't add files to
171
- # those bad boys)
172
- targets = targets_from_options(options, :ignore_aggregates => true)
173
-
174
- Vendor.ui.debug %{Adding #{framework} to targets "#{targets.map(&:name)}"}
175
-
176
- path = if framework.match(/\.dylib/)
177
- "usr/lib/#{framework}"
178
- else
179
- "System/Library/Frameworks/#{framework}"
180
- end
181
-
182
- targets.each do |t|
183
- # Does the framework already exist?
184
- build_phase = build_phase_for_file("wrapper.framework", t)
185
-
186
- if build_phase
187
- # Does a framework already exist?
188
- existing_framework = build_phase.files.map(&:file_ref).find do |file|
189
- # Some files have names, some done. Framework references
190
- # have names...
191
- if file.respond_to?(:name)
192
- file.name == framework
193
- end
194
- end
195
-
196
- # If an existing framework was found, don't add it again
197
- unless existing_framework
198
- add_file :targets => t, :file => path, :name => framework,
199
- :path => "Frameworks", :source_tree => :sdkroot
200
- end
201
- end
155
+
156
+
157
+ def add_source_files_to_sources_build_phase files, sources_build_phase, per_file_flag
158
+
159
+ unless sources_build_phase
160
+ Vendor.ui.warn "* No sources build phase exists for this target\n"
161
+ return
202
162
  end
203
- end
204
-
205
- def add_build_setting(name, value, options = {})
206
-
207
- targets_from_options(options).each do |target|
208
-
209
- target.build_configuration_list.build_configurations.each do |config|
210
-
211
- build_settings = config.build_settings
212
-
213
- debug_key = "#{target.name}/#{config.name}".inspect
214
-
215
- # If the build setting already has the key
216
- if build_settings.has_key?(name)
217
-
218
- # Is this setting known to have multiple values?
219
- if (setting_type = BUILD_SETTING_TYPES[name])
220
-
221
- # If its an array
222
- if setting_type == :array
223
- # Is it already an array, if so, check to see if
224
- # it already exists, and if it doesn't add it.
225
- if build_settings[name].kind_of?(Array)
226
- unless build_settings[name].include?
227
- Vendor.ui.debug(" Added build setting (#{name.inspect} = #{value.inspect}) to #{debug_key}")
228
-
229
- build_settings[name] << value
230
- end
231
- else
232
- Vendor.ui.debug(" Added build setting (#{name.inspect} = #{value.inspect}) to #{debug_key}")
233
-
234
- # Don't add it if the single build value is already there
235
- unless build_settings[name].strip == value.strip
236
- build_settings[name] = [ build_settings[name], value ]
237
- end
238
- end
239
- end
240
-
241
- else
242
- # If its an unknown type, then we should just throw a warning
243
- # because we should'nt just change stuff willy, nilly.
244
- Vendor.ui.warn(" Build setting #{name.inspect} wanted to change to #{value.inspect}, but it was already #{build_settings[name].inspect} in #{debug_key}")
245
- end
246
-
247
- else
248
- Vendor.ui.debug(" Added build setting (#{name.inspect} = #{value.inspect}) to #{debug_key}")
249
163
 
250
- build_settings[name] = value
251
- end
164
+ Vendor.ui.info "* Sources Build Phase - adding #{files.count} file(s)\n\n"
165
+
166
+ files.each do |file|
252
167
 
168
+ Vendor.ui.debug " > #{file.path}\n\n"
169
+
170
+ if per_file_flag
171
+ sources_build_phase.add_build_file file, { 'COMPILER_FLAGS' => per_file_flag }
172
+ else
173
+ sources_build_phase.add_build_file file
253
174
  end
254
-
255
175
  end
256
-
257
- @dirty = true
258
-
259
176
  end
177
+
178
+ def add_resource_files_to_resources_build_phase files, resources_build_phase
260
179
 
261
- def add_file(options)
262
- require_options options, :path, :file, :source_tree
263
-
264
- # Ensure file exists if we'nre not using the sdk root source tree.
265
- # The SDKROOT source tree has a virtual file on the system, so
266
- # File.exist checks will always return false.
267
- unless options[:source_tree] == :sdkroot
268
- raise StandardError.new("Could not find file `#{options[:file]}`") unless File.exists?(options[:file])
180
+ unless resources_build_phase
181
+ Vendor.ui.warn "* No resources build phase exists for this target\n"
182
+ return
269
183
  end
184
+
185
+ Vendor.ui.info "* Resources Build Phase - adding #{files.count} file(s)\n\n"
186
+
187
+ files.each do |file|
270
188
 
271
- # Find targets and filter out aggregate targets (we can't add files to
272
- # those bad boys)
273
- targets = targets_from_options(options, :ignore_aggregates => true)
274
-
275
- # Create the group
276
- group = create_group(options[:path])
277
-
278
- # File type
279
- type = Vendor::XCode::Proxy::PBXFileReference.file_type_from_extension(File.extname(options[:file]))
280
-
281
- # The file name
282
- name = File.basename(options[:file])
283
-
284
- attributes = {
285
- 'lastKnownFileType' => type,
286
- 'sourceTree' => "<#{options[:source_tree].to_s}>"
287
- }
288
-
289
- # Handle the different source tree types
290
- if options[:source_tree] == :group
291
-
292
- # Ensure the path exists on the filesystem
293
- path = File.join(@project_folder, "..", options[:path])
294
- FileUtils.mkdir_p path
295
-
296
- # Copy the file
297
- FileUtils.cp_r options[:file], File.join(path, name)
298
-
299
- # Set the path of the file
300
- attributes['path'] = name
301
-
302
- elsif options[:source_tree] == :absolute
303
-
304
- # Set the path and the name of the file
305
- attributes['name'] = name
306
- attributes['path'] = options[:file]
307
-
308
- elsif options[:source_tree] == :sdkroot
309
-
310
- # Set the path and the name of the framework
311
- attributes['name'] = name
312
- attributes['path'] = options[:file]
313
- attributes['sourceTree'] = "SDKROOT"
314
-
315
- else
316
-
317
- # Could not handle that option
318
- raise StandardError.new("Invalid :source_tree option `#{options[:source_tree].to_s}`")
319
-
320
- end
321
-
322
- # Add the file to XCode
323
- file = Vendor::XCode::Proxy::PBXFileReference.new(:project => self,
324
- :id => Vendor::XCode::Proxy::Base.generate_id,
325
- :attributes => attributes)
326
-
327
- # Set the parent
328
- file.parent = group
329
-
330
- # Add the file id to the groups children
331
- group.attributes['children'] << file.id
332
-
333
- # Add the file to targets
334
- targets.each do |t|
335
- add_file_to_target file, t
189
+ Vendor.ui.debug " > #{file.path}\n\n"
190
+
191
+ resources_build_phase.add_build_file file
336
192
  end
337
-
338
- # Mark as dirty
339
- @dirty = true
340
-
341
- # Add the file to the internal index
342
- @objects_by_id[file.id] = file
343
193
  end
194
+
195
+ def add_frameworks_to_frameworks_build_phase frameworks, framework_build_phase
344
196
 
345
- def remove_file_from_target(file, target)
346
-
347
- # Search through all the build phases for references to the file
348
- build_files = []
349
- target.build_phases.each do |phase|
350
- build_files << phase.files.find_all do |build_file|
351
- build_file.attributes['fileRef'] == file.id
352
- end
197
+ unless framework_build_phase
198
+ Vendor.ui.warn "* No framework build phase exists for this target\n"
199
+ return
353
200
  end
354
201
 
355
- # Remove the build files from the references
356
- build_files.flatten.each do |build_file|
357
- build_file.parent.attributes['files'].delete build_file.id
358
- @objects_by_id.delete build_file.id
359
- end
360
-
361
- end
362
-
363
- def add_file_to_target(file, target)
364
-
365
- build_phase = build_phase_for_file(file.last_known_file_type, target)
366
-
367
- if build_phase
368
-
369
- Vendor.ui.debug "Adding #{file.attributes} to #{target.name} (build_phase = #{build_phase.class.name})"
370
-
371
- # Add the file to XCode
372
- build_file = Vendor::XCode::Proxy::PBXBuildFile.new(:project => self,
373
- :id => Vendor::XCode::Proxy::Base.generate_id,
374
- :attributes => { 'fileRef' => file.id })
375
-
376
- # Set the parent
377
- build_file.parent = build_phase
378
-
379
- # Add the file to the internal index
380
- @objects_by_id[build_file.id] = build_file
381
-
382
- # Add the file to the build phase
383
- build_phase.attributes['files'] << build_file.id
384
-
202
+ Vendor.ui.info "* Frameworks Build Phase - adding #{frameworks.count} framework(s)\n\n"
203
+
204
+ frameworks.each do |framework|
205
+
206
+ Vendor.ui.debug " > #{framework.name}\n\n"
207
+
208
+ framework_build_phase.add_build_file framework
385
209
  end
386
-
387
- end
388
-
389
- def to_ascii_plist
390
- plist = { :archiveVersion => archive_version,
391
- :classes => {},
392
- :objectVersion => object_version,
393
- :objects => @objects_by_id,
394
- :rootObject => @root_object.id }.to_ascii_plist
395
-
396
- "// !$*UTF8*$!\n" << plist
397
- end
398
-
399
- def save
400
- backup
401
- open(@pbxproject, 'w+') do |f|
402
- f << to_ascii_plist
403
- end if valid?
404
-
405
- # Not dirty anymore
406
- @dirty = false
407
210
  end
211
+
212
+ def add_build_settings_to_target_configurations target, build_settings
213
+
214
+ Vendor.ui.info "* Build Configuration Settings\n\n"
215
+
216
+ target.configs.each do |config|
217
+
218
+ Vendor.ui.debug " > #{config.name} Configuration\n\n"
219
+
220
+ build_settings.each do |name,value|
221
+
222
+ Vendor.ui.debug " > Setting `#{name}` to `#{value}`\n\n"
223
+
224
+ config.append name, value
408
225
 
409
- def backup
410
- dir = File.dirname(@project_folder)
411
- backup_name = "#{@name}.vendorbackup"
412
- backups = Dir[File.join(dir, "#{backup_name}*")].sort
413
-
414
- unless backups.empty?
415
- if backups.last.match(/([\d]+)$/)
416
- backup_name += ".#{$1.to_i + 1}"
417
- else
418
- backup_name += ".1"
419
226
  end
420
227
  end
421
-
422
- backup_to = File.join(dir, backup_name)
423
-
424
- Vendor.ui.warn "Backup created #{backup_to}"
425
- FileUtils.cp_r @project_folder, backup_to
426
- end
427
-
428
- def dirty?
429
- @dirty
430
228
  end
431
-
432
- def valid?
433
- begin
434
- # Try and parse the plist again. If it parses, then we've
435
- # got valid syntax, if it fails, it will raise a parse error. We
436
- # know we've done something bad at this point.
437
- Vendor::Plist.parse_ascii(to_ascii_plist)
438
-
439
- true
440
- rescue Vendor::Plist::AsciiParser::ParseError => e
441
- Vendor.ui.error "There was an error converting the XCode project back to a Plist"
442
- Vendor.ui.error e.inspect
443
- Vendor.ui.debug to_ascii_plist
444
-
445
- false
446
- end
447
- end
448
-
449
- private
450
-
451
- def build_phase_for_file(file_type, target)
452
- # Which build phase does this file belong?
453
- klass = case file_type
454
- when "sourcecode.c.objc", "sourcecode.c.c"
455
- Vendor::XCode::Proxy::PBXSourcesBuildPhase
456
- when "wrapper.framework"
457
- Vendor::XCode::Proxy::PBXFrameworksBuildPhase
458
- when "compiled.mach-o.dylib"
459
- Vendor::XCode::Proxy::PBXFrameworksBuildPhase
460
- end
461
-
462
- if klass
463
- # Find the build phase
464
- build_phase = target.build_phases.find { |phase| phase.kind_of?(klass) }
465
- unless build_phase
466
- Vendor.ui.error "Could not find '#{klass.name}' build phase for target '#{target.name}'"
467
- exit 1
468
- end
469
- build_phase
470
- else
471
- false
472
- end
473
- end
474
-
475
- def require_options(options, *keys)
476
- keys.each { |k| raise StandardError.new("Missing :#{k} option") unless options[k] }
477
- end
478
-
479
- def targets_from_options(options, opts = {})
480
- targets = if options[:targets]
481
- [ *options[:targets] ].map do |t|
482
- if t == :all
483
- root_object.targets
484
- else
485
- target = find_target(t)
486
- raise StandardError.new("Could not find target '#{t}' in project '#{name}'") unless target
487
- target
488
- end
489
- end.flatten.uniq
490
- else
491
- root_object.targets
492
- end
493
-
494
- if opts[:ignore_aggregates]
495
- targets.reject { |t| t.kind_of? Vendor::XCode::Proxy::PBXAggregateTarget }
496
- else
497
- targets
498
- end
499
- end
500
-
229
+
501
230
  end
502
231
 
503
232
  end