cocoapods 0.35.0 → 0.36.0.beta.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +185 -6
  3. data/README.md +1 -1
  4. data/lib/cocoapods.rb +4 -0
  5. data/lib/cocoapods/command.rb +2 -2
  6. data/lib/cocoapods/command/inter_process_communication.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +3 -0
  8. data/lib/cocoapods/command/list.rb +0 -35
  9. data/lib/cocoapods/command/search.rb +1 -2
  10. data/lib/cocoapods/command/spec.rb +6 -3
  11. data/lib/cocoapods/config.rb +1 -20
  12. data/lib/cocoapods/external_sources/abstract_external_source.rb +4 -0
  13. data/lib/cocoapods/gem_version.rb +1 -1
  14. data/lib/cocoapods/generator/embed_frameworks_script.rb +107 -0
  15. data/lib/cocoapods/generator/header.rb +13 -1
  16. data/lib/cocoapods/generator/info_plist_file.rb +84 -0
  17. data/lib/cocoapods/generator/module_map.rb +49 -0
  18. data/lib/cocoapods/generator/umbrella_header.rb +44 -0
  19. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +69 -23
  20. data/lib/cocoapods/generator/xcconfig/private_pod_xcconfig.rb +12 -0
  21. data/lib/cocoapods/generator/xcconfig/public_pod_xcconfig.rb +1 -9
  22. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +79 -1
  23. data/lib/cocoapods/hooks_manager.rb +75 -13
  24. data/lib/cocoapods/installer.rb +59 -2
  25. data/lib/cocoapods/installer/analyzer.rb +115 -38
  26. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +6 -1
  27. data/lib/cocoapods/installer/file_references_installer.rb +11 -5
  28. data/lib/cocoapods/installer/migrator.rb +9 -0
  29. data/lib/cocoapods/installer/target_installer.rb +89 -5
  30. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +49 -5
  31. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +57 -9
  32. data/lib/cocoapods/installer/user_project_integrator.rb +3 -2
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +67 -6
  34. data/lib/cocoapods/project.rb +18 -2
  35. data/lib/cocoapods/resolver.rb +2 -2
  36. data/lib/cocoapods/sandbox/file_accessor.rb +23 -3
  37. data/lib/cocoapods/sandbox/headers_store.rb +4 -0
  38. data/lib/cocoapods/sources_manager.rb +5 -1
  39. data/lib/cocoapods/target.rb +117 -1
  40. data/lib/cocoapods/target/aggregate_target.rb +46 -4
  41. data/lib/cocoapods/target/pod_target.rb +39 -1
  42. data/lib/cocoapods/user_interface.rb +16 -21
  43. data/lib/cocoapods/user_interface/error_report.rb +2 -2
  44. data/lib/cocoapods/validator.rb +68 -23
  45. metadata +23 -19
@@ -12,8 +12,14 @@ module Pod
12
12
  UI.message "- Installing target `#{target.name}` #{target.platform}" do
13
13
  add_target
14
14
  create_support_files_dir
15
- create_suport_files_group
15
+ create_support_files_group
16
16
  create_xcconfig_file
17
+ if target.requires_frameworks?
18
+ create_info_plist_file
19
+ create_module_map
20
+ create_umbrella_header
21
+ create_embed_frameworks_script
22
+ end
17
23
  create_target_environment_header
18
24
  create_bridge_support_file
19
25
  create_copy_resources_script
@@ -26,12 +32,25 @@ module Pod
26
32
 
27
33
  private
28
34
 
35
+ # Ensure that vendored static frameworks and libraries are not linked
36
+ # twice to the aggregate target, which shares the xcconfig of the user
37
+ # target.
38
+ #
39
+ def custom_build_settings
40
+ settings = {
41
+ 'OTHER_LDFLAGS' => '',
42
+ 'OTHER_LIBTOOLFLAGS' => '',
43
+ 'PODS_ROOT' => '$(SRCROOT)',
44
+ }
45
+ super.merge(settings)
46
+ end
47
+
29
48
  # Creates the group that holds the references to the support files
30
49
  # generated by this installer.
31
50
  #
32
51
  # @return [void]
33
52
  #
34
- def create_suport_files_group
53
+ def create_support_files_group
35
54
  parent = project.support_files_group
36
55
  name = target.name
37
56
  dir = target.support_files_dir
@@ -92,9 +111,12 @@ module Pod
92
111
  #
93
112
  def create_copy_resources_script
94
113
  path = target.copy_resources_script_path
95
- file_accessors = target.pod_targets.map(&:file_accessors).flatten
96
- resource_paths = file_accessors.map { |accessor| accessor.resources.flatten.map { |res| res.relative_path_from(project.path.dirname) } }.flatten
97
- resource_bundles = file_accessors.map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }.flatten
114
+ library_targets = target.pod_targets.reject do |pod_target|
115
+ pod_target.should_build? && pod_target.requires_frameworks?
116
+ end
117
+ file_accessors = library_targets.flat_map(&:file_accessors)
118
+ resource_paths = file_accessors.flat_map { |accessor| accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) } }
119
+ resource_bundles = file_accessors.flat_map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }
98
120
  resources = []
99
121
  resources.concat(resource_paths)
100
122
  resources.concat(resource_bundles)
@@ -104,6 +126,28 @@ module Pod
104
126
  add_file_to_support_group(path)
105
127
  end
106
128
 
129
+ # Creates a script that embeds the frameworks to the bundle of the client
130
+ # target.
131
+ #
132
+ # @note We can't use Xcode default copy bundle resource phase, because
133
+ # we need to ensure that we only copy the resources, which are
134
+ # relevant for the current build configuration.
135
+ #
136
+ # @return [void]
137
+ #
138
+ def create_embed_frameworks_script
139
+ path = target.embed_frameworks_script_path
140
+ frameworks_by_config = {}
141
+ target.user_build_configurations.keys.each do |config|
142
+ frameworks_by_config[config] = target.pod_targets.select do |pod_target|
143
+ pod_target.include_in_build_config?(config) && pod_target.should_build?
144
+ end.map(&:product_name)
145
+ end
146
+ generator = Generator::EmbedFrameworksScript.new(target_definition, frameworks_by_config)
147
+ generator.save_as(path)
148
+ add_file_to_support_group(path)
149
+ end
150
+
107
151
  # Generates the acknowledgement files (markdown and plist) for the target.
108
152
  #
109
153
  # @return [void]
@@ -9,12 +9,24 @@ module Pod
9
9
  # @return [void]
10
10
  #
11
11
  def install!
12
+ unless target.should_build?
13
+ add_resources_bundle_targets
14
+ return
15
+ end
16
+
12
17
  UI.message "- Installing target `#{target.name}` #{target.platform}" do
13
18
  add_target
14
19
  create_support_files_dir
15
- add_files_to_build_phases
16
20
  add_resources_bundle_targets
21
+ add_files_to_build_phases
17
22
  create_xcconfig_file
23
+ if target.requires_frameworks?
24
+ create_info_plist_file
25
+ create_module_map
26
+ create_umbrella_header do |generator|
27
+ generator.imports += target.file_accessors.flat_map(&:public_headers).map(&:basename)
28
+ end
29
+ end
18
30
  create_prefix_header
19
31
  create_dummy_source
20
32
  end
@@ -36,20 +48,41 @@ module Pod
36
48
  target.file_accessors.each do |file_accessor|
37
49
  consumer = file_accessor.spec_consumer
38
50
 
51
+ headers = file_accessor.headers
52
+ public_headers = file_accessor.public_headers
39
53
  other_source_files = file_accessor.source_files.select { |sf| sf.extname == '.d' }
40
54
 
41
55
  {
42
56
  true => file_accessor.arc_source_files,
43
57
  false => file_accessor.non_arc_source_files,
44
58
  }.each do |arc, files|
45
- files = files - other_source_files
59
+ files = files - headers - other_source_files
46
60
  flags = compiler_flags_for_consumer(consumer, arc)
47
61
  regular_file_refs = files.map { |sf| project.reference_for_path(sf) }
48
62
  native_target.add_file_references(regular_file_refs, flags)
49
63
  end
50
64
 
65
+ header_file_refs = headers.map { |sf| project.reference_for_path(sf) }
66
+ native_target.add_file_references(header_file_refs) do |build_file|
67
+ # Set added headers as public if needed
68
+ if target.requires_frameworks?
69
+ if public_headers.include?(build_file.file_ref.real_path)
70
+ build_file.settings ||= {}
71
+ build_file.settings['ATTRIBUTES'] = ['Public']
72
+ end
73
+ end
74
+ end
75
+
51
76
  other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) }
52
77
  native_target.add_file_references(other_file_refs, nil)
78
+
79
+ next unless target.requires_frameworks?
80
+
81
+ resource_refs = file_accessor.resources.flatten.map do |res|
82
+ project.reference_for_path(res)
83
+ end
84
+
85
+ native_target.add_resources(resource_refs)
53
86
  end
54
87
  end
55
88
 
@@ -63,20 +96,35 @@ module Pod
63
96
  def add_resources_bundle_targets
64
97
  target.file_accessors.each do |file_accessor|
65
98
  file_accessor.resource_bundles.each do |bundle_name, paths|
66
- # Add a dependency on an existing Resource Bundle target if possible
67
- if bundle_target = project.targets.find { |target| target.name == bundle_name }
68
- native_target.add_dependency(bundle_target)
69
- next
70
- end
71
99
  file_references = paths.map { |sf| project.reference_for_path(sf) }
72
- bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name)
100
+ label = target.resources_bundle_target_label(bundle_name)
101
+ bundle_target = project.new_resources_bundle(label, file_accessor.spec_consumer.platform_name)
102
+ bundle_target.product_reference.tap do |bundle_product|
103
+ bundle_file_name = "#{bundle_name}.bundle"
104
+ bundle_product.name = bundle_file_name
105
+ bundle_product.path = bundle_file_name
106
+ end
73
107
  bundle_target.add_resources(file_references)
74
108
 
75
109
  target.user_build_configurations.each do |bc_name, type|
76
110
  bundle_target.add_build_configuration(bc_name, type)
77
111
  end
78
112
 
79
- native_target.add_dependency(bundle_target)
113
+ target.resource_bundle_targets << bundle_target
114
+
115
+ if target.should_build?
116
+ native_target.add_dependency(bundle_target)
117
+ if target.requires_frameworks?
118
+ native_target.add_resources([bundle_target.product_reference])
119
+ end
120
+ end
121
+
122
+ bundle_target.build_configurations.each do |c|
123
+ c.build_settings['PRODUCT_NAME'] = bundle_name
124
+ if target.requires_frameworks?
125
+ c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
126
+ end
127
+ end
80
128
  end
81
129
  end
82
130
  end
@@ -132,7 +132,8 @@ module Pod
132
132
  end
133
133
  end
134
134
 
135
- INHERITED_FLAGS = ['$(inherited)', '${inherited}']
135
+ IGNORED_KEYS = %w(CODE_SIGN_IDENTITY).freeze
136
+ INHERITED_FLAGS = %w($(inherited) ${inherited}).freeze
136
137
 
137
138
  # Checks whether the settings of the CocoaPods generated xcconfig are
138
139
  # overridden by the build configuration of a target and prints a
@@ -144,7 +145,7 @@ module Pod
144
145
  user_target.build_configurations.each do |config|
145
146
  xcconfig = aggregate_target.xcconfigs[config.name]
146
147
  if xcconfig
147
- xcconfig.to_hash.keys.each do |key|
148
+ (xcconfig.to_hash.keys - IGNORED_KEYS).each do |key|
148
149
  target_values = config.build_settings[key]
149
150
  if target_values &&
150
151
  !INHERITED_FLAGS.any? { |flag| target_values.include?(flag) }
@@ -31,8 +31,10 @@ module Pod
31
31
  project_is_dirty = [
32
32
  XCConfigIntegrator.integrate(target, native_targets),
33
33
  update_to_cocoapods_0_34,
34
+ remove_embed_frameworks_script_phases,
34
35
  unless native_targets_to_integrate.empty?
35
36
  add_pods_library
37
+ add_embed_frameworks_script_phase if target.requires_frameworks?
36
38
  add_copy_resources_script_phase
37
39
  add_check_manifest_lock_script_phase
38
40
  true
@@ -91,9 +93,9 @@ module Pod
91
93
  changes
92
94
  end
93
95
 
94
- # Adds spec libraries to the frameworks build phase of the
96
+ # Adds spec product reference to the frameworks build phase of the
95
97
  # {TargetDefinition} integration libraries. Adds a file reference to
96
- # the library of the {TargetDefinition} and adds it to the frameworks
98
+ # the frameworks group of the project and adds it to the frameworks
97
99
  # build phase of the targets.
98
100
  #
99
101
  # @return [void]
@@ -101,12 +103,71 @@ module Pod
101
103
  def add_pods_library
102
104
  frameworks = user_project.frameworks_group
103
105
  native_targets_to_integrate.each do |native_target|
104
- library = frameworks.files.select { |f| f.path == target.product_name }.first ||
105
- frameworks.new_product_ref_for_target(target.name, :static_library)
106
- unless native_target.frameworks_build_phase.files_references.include?(library)
107
- native_target.frameworks_build_phase.add_file_reference(library)
106
+ build_phase = native_target.frameworks_build_phase
107
+
108
+ # Find and delete possible reference for the other product type
109
+ old_product_name = target.requires_frameworks? ? target.static_library_name : target.framework_name
110
+ old_product_ref = frameworks.files.find { |f| f.path == old_product_name }
111
+ if old_product_ref.present?
112
+ UI.message("Removing old Pod product reference #{old_product_name} from project.")
113
+ build_phase.remove_file_reference(old_product_ref)
114
+ frameworks.remove_reference(old_product_ref)
115
+ end
116
+
117
+ # Find or create and add a reference for the current product type
118
+ target_basename = target.product_basename
119
+ new_product_ref = frameworks.files.find { |f| f.path == target.product_name } ||
120
+ frameworks.new_product_ref_for_target(target_basename, target.product_type)
121
+ build_file = build_phase.build_file(new_product_ref) ||
122
+ build_phase.add_file_reference(new_product_ref)
123
+ if target.requires_frameworks?
124
+ # Weak link the aggregate target's product, because as it contains
125
+ # no symbols, it isn't copied into the app bundle. dyld will so
126
+ # never try to find the missing executable at runtime.
127
+ build_file.settings ||= {}
128
+ build_file.settings['ATTRIBUTES'] = ['Weak']
129
+ end
130
+ end
131
+ end
132
+
133
+ # Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
134
+ #
135
+ # @return [void]
136
+ #
137
+ def add_embed_frameworks_script_phase
138
+ phase_name = 'Embed Pods Frameworks'
139
+ native_targets_to_integrate.each do |native_target|
140
+ embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
141
+ unless embed_build_phase.present?
142
+ UI.message("Adding Build Phase '#{phase_name}' to project.")
143
+ embed_build_phase = native_target.new_shell_script_build_phase(phase_name)
108
144
  end
145
+ script_path = target.embed_frameworks_script_relative_path
146
+ embed_build_phase.shell_script = %("#{script_path}"\n)
147
+ embed_build_phase.show_env_vars_in_log = '0'
148
+ end
149
+ end
150
+
151
+ # Delete 'Embed Pods Frameworks' Build Phases, if they exist
152
+ # and are not needed anymore due to not integrating the
153
+ # dependencies by frameworks.
154
+ #
155
+ # @return [Bool] whether any changes to the project were made.
156
+ #
157
+ def remove_embed_frameworks_script_phases
158
+ return false if target.requires_frameworks?
159
+
160
+ phase_name = 'Embed Pods Frameworks'
161
+ result = false
162
+
163
+ native_targets.each do |native_target|
164
+ embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
165
+ next unless embed_build_phase.present?
166
+ native_target.build_phases.delete(embed_build_phase)
167
+ result = true
109
168
  end
169
+
170
+ result
110
171
  end
111
172
 
112
173
  # Adds a shell script build phase responsible to copy the resources
@@ -59,6 +59,7 @@ module Pod
59
59
 
60
60
  parent_group = development ? development_pods : pods
61
61
  source_tree = absolute ? :absolute : :group
62
+
62
63
  group = parent_group.new_group(pod_name, path, source_tree)
63
64
  group
64
65
  end
@@ -144,13 +145,28 @@ module Pod
144
145
  # @param [PBXGroup] group
145
146
  # The group for the new file reference.
146
147
  #
148
+ # @param [Bool] reflect_file_system_structure
149
+ # Wether group structure should reflect the file system structure.
150
+ # If yes, where needed, intermediate groups are created, similar to
151
+ # how mkdir -p operates.
152
+ #
147
153
  # @return [PBXFileReference] The new file reference.
148
154
  #
149
- def add_file_reference(absolute_path, group)
150
- unless Pathname.new(absolute_path).absolute?
155
+ def add_file_reference(absolute_path, group, reflect_file_system_structure = false)
156
+ file_path_name = Pathname.new(absolute_path)
157
+ unless file_path_name.absolute?
151
158
  raise ArgumentError, "Paths must be absolute #{absolute_path}"
152
159
  end
153
160
 
161
+ if reflect_file_system_structure
162
+ relative_path = file_path_name.relative_path_from(group.real_path)
163
+ relative_dir = relative_path.dirname
164
+ relative_dir.each_filename do|name|
165
+ next if name == '.'
166
+ group = group[name] || group.new_group(name, name)
167
+ end
168
+ end
169
+
154
170
  if ref = reference_for_path(absolute_path)
155
171
  ref
156
172
  else
@@ -50,7 +50,7 @@ module Pod
50
50
  # definition.
51
51
  #
52
52
  def resolve
53
- dependencies = @podfile.target_definition_list.map(&:dependencies).flatten
53
+ dependencies = podfile.target_definition_list.map(&:dependencies).flatten
54
54
  @cached_sets = {}
55
55
  @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
56
56
  specs_by_target
@@ -78,7 +78,6 @@ module Pod
78
78
  uniq.
79
79
  sort_by(&:name).
80
80
  each do |spec|
81
- validate_platform(spec, target)
82
81
  sandbox.store_head_pod(spec.name) if spec.version.head?
83
82
  end
84
83
  end
@@ -408,6 +407,7 @@ module Pod
408
407
  # dependencies for `target`.
409
408
  #
410
409
  def valid_dependencies_for_target_from_node(target, node)
410
+ validate_platform(node.payload, target)
411
411
  dependency_nodes = node.outgoing_edges.select do |edge|
412
412
  edge_is_valid_for_target?(edge, target)
413
413
  end.map(&:destination)
@@ -12,7 +12,7 @@ module Pod
12
12
  GLOB_PATTERNS = {
13
13
  :readme => 'readme{*,.*}'.freeze,
14
14
  :license => 'licen{c,s}e{*,.*}'.freeze,
15
- :source_files => '*.{h,hpp,hh,m,mm,c,cpp}'.freeze,
15
+ :source_files => '*.{h,hpp,hh,m,mm,c,cpp,swift}'.freeze,
16
16
  :public_header_files => "*{#{HEADER_EXTENSIONS.join(',')}}".freeze,
17
17
  }.freeze
18
18
 
@@ -113,8 +113,8 @@ module Pod
113
113
  # @return [Array<Pathname>] the public headers of the specification.
114
114
  #
115
115
  def public_headers(include_frameworks = false)
116
- public_headers = paths_for_attribute(:public_header_files)
117
- private_headers = paths_for_attribute(:private_header_files)
116
+ public_headers = public_header_files
117
+ private_headers = private_header_files
118
118
  if public_headers.nil? || public_headers.empty?
119
119
  header_files = headers
120
120
  else
@@ -210,6 +210,26 @@ module Pod
210
210
 
211
211
  private
212
212
 
213
+ # @!group Private paths
214
+
215
+ # @return [Array<Pathname>] The paths of the user-specified public header
216
+ # files.
217
+ #
218
+ def public_header_files
219
+ paths_for_attribute(:public_header_files)
220
+ end
221
+
222
+ # @return [Array<Pathname>] The paths of the user-specified public header
223
+ # files.
224
+ #
225
+ def private_header_files
226
+ paths_for_attribute(:private_header_files)
227
+ end
228
+
229
+ #-----------------------------------------------------------------------#
230
+
231
+ private
232
+
213
233
  # @!group Private helpers
214
234
 
215
235
  # Returns the list of the paths founds in the file system for the
@@ -26,6 +26,10 @@ module Pod
26
26
  @search_paths = []
27
27
  end
28
28
 
29
+ # @param [Platform] platform
30
+ # the platform for which the header search paths should be
31
+ # returned
32
+ #
29
33
  # @return [Array<String>] All the search paths of the header directory in
30
34
  # xcconfig format. The paths are specified relative to the pods
31
35
  # root with the `${PODS_ROOT}` variable.
@@ -9,6 +9,7 @@ module Pod
9
9
  # known Pods.
10
10
  #
11
11
  def aggregate
12
+ return Source::Aggregate.new([]) unless config.repos_dir.exist?
12
13
  dirs = config.repos_dir.children.select(&:directory?)
13
14
  Source::Aggregate.new(dirs)
14
15
  end
@@ -60,6 +61,7 @@ module Pod
60
61
  # installation of CocoaPods.
61
62
  #
62
63
  def all
64
+ return [] unless config.repos_dir.exist?
63
65
  dirs = config.repos_dir.children.select(&:directory?)
64
66
  dirs.map { |repo| Source.new(repo) }
65
67
  end
@@ -393,7 +395,9 @@ module Pod
393
395
  #
394
396
  def source_with_url(url)
395
397
  url = url.downcase.gsub(/.git$/, '')
396
- aggregate.sources.find { |s| s.url.downcase.gsub(/.git$/, '') == url }
398
+ aggregate.sources.find do |source|
399
+ source.url && source.url.downcase.gsub(/.git$/, '') == url
400
+ end
397
401
  end
398
402
 
399
403
  # Returns a suitable repository name for `url`.