cocoapods 0.20.2 → 0.21.0.rc1

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.
@@ -0,0 +1,132 @@
1
+ module Pod
2
+ class Installer
3
+
4
+ # Creates the targets which aggregate the Pods libraries in the Pods
5
+ # project and the relative support files.
6
+ #
7
+ class AggregateTargetInstaller < TargetInstaller
8
+
9
+ # Creates the target in the Pods project and the relative support files.
10
+ #
11
+ # @return [void]
12
+ #
13
+ def install!
14
+ UI.message "- Installing target `#{library.name}` #{library.platform}" do
15
+ add_target
16
+ create_suport_files_group
17
+ create_xcconfig_file
18
+ create_target_environment_header
19
+ create_bridge_support_file
20
+ create_copy_resources_script
21
+ create_acknowledgements
22
+ create_dummy_source
23
+ end
24
+ end
25
+
26
+ #-----------------------------------------------------------------------#
27
+
28
+ private
29
+
30
+ # Generates the contents of the xcconfig file and saves it to disk.
31
+ #
32
+ # @note The `ALWAYS_SEARCH_USER_PATHS` flag is enabled to support
33
+ # libraries like `EmbedReader`.
34
+ #
35
+ # @return [void]
36
+ #
37
+ def create_xcconfig_file
38
+ path = library.xcconfig_path
39
+ UI.message "- Generating xcconfig file at #{UI.path(path)}" do
40
+ gen = Generator::AggregateXCConfig.new(library)
41
+ gen.save_as(path)
42
+ library.xcconfig = gen.xcconfig
43
+ xcconfig_file_ref = add_file_to_support_group(path)
44
+
45
+ target.build_configurations.each do |c|
46
+ c.base_configuration_reference = xcconfig_file_ref
47
+ end
48
+ end
49
+ end
50
+
51
+ # Generates a header which allows to inspect at compile time the installed
52
+ # pods and the installed specifications of a pod.
53
+ #
54
+ def create_target_environment_header
55
+ path = library.target_environment_header_path
56
+ UI.message "- Generating target environment header at #{UI.path(path)}" do
57
+ generator = Generator::TargetEnvironmentHeader.new(library.pod_targets.map { |l| l.specs }.flatten)
58
+ generator.save_as(path)
59
+ add_file_to_support_group(path)
60
+ end
61
+ end
62
+
63
+ # Generates the bridge support metadata if requested by the {Podfile}.
64
+ #
65
+ # @note The bridge support metadata is added to the resources of the
66
+ # library because it is needed for environments interpreted at
67
+ # runtime.
68
+ #
69
+ # @return [void]
70
+ #
71
+ def create_bridge_support_file
72
+ if target_definition.podfile.generate_bridge_support?
73
+ path = library.bridge_support_path
74
+ UI.message "- Generating BridgeSupport metadata at #{UI.path(path)}" do
75
+ headers = target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
76
+ generator = Generator::BridgeSupport.new(headers)
77
+ generator.save_as(path)
78
+ add_file_to_support_group(path)
79
+ @bridge_support_file = path.relative_path_from(sandbox.root)
80
+ end
81
+ end
82
+ end
83
+
84
+ # Creates a script that copies the resources to the bundle of the client
85
+ # target.
86
+ #
87
+ # @note The bridge support file needs to be created before the prefix
88
+ # header, otherwise it will not be added to the resources script.
89
+ #
90
+ # @return [void]
91
+ #
92
+ def create_copy_resources_script
93
+ path = library.copy_resources_script_path
94
+ UI.message "- Generating copy resources script at #{UI.path(path)}" do
95
+ file_accessors = library.pod_targets.map(&:file_accessors).flatten
96
+ resources = file_accessors.map { |accessor| accessor.resources.flatten.map {|res| project.relativize(res)} }.flatten
97
+ resources << bridge_support_file if bridge_support_file
98
+ generator = Generator::CopyResourcesScript.new(resources, library.platform)
99
+ generator.save_as(path)
100
+ add_file_to_support_group(path)
101
+ end
102
+ end
103
+
104
+ # Generates the acknowledgement files (markdown and plist) for the target.
105
+ #
106
+ # @return [void]
107
+ #
108
+ def create_acknowledgements
109
+ basepath = library.acknowledgements_basepath
110
+ Generator::Acknowledgements.generators.each do |generator_class|
111
+ path = generator_class.path_from_basepath(basepath)
112
+ UI.message "- Generating acknowledgements at #{UI.path(path)}" do
113
+ file_accessors = library.pod_targets.map(&:file_accessors).flatten
114
+ generator = generator_class.new(file_accessors)
115
+ generator.save_as(path)
116
+ add_file_to_support_group(path)
117
+ end
118
+ end
119
+ end
120
+
121
+ # @return [Pathname] the path of the bridge support file relative to the
122
+ # sandbox.
123
+ #
124
+ # @return [Nil] if no bridge support file was generated.
125
+ #
126
+ attr_reader :bridge_support_file
127
+
128
+ #-----------------------------------------------------------------------#
129
+
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,160 @@
1
+ module Pod
2
+ class Installer
3
+
4
+ # Creates the target for the Pods libraries in the Pods project and the
5
+ # relative support files.
6
+ #
7
+ class PodTargetInstaller < TargetInstaller
8
+
9
+ # Creates the target in the Pods project and the relative support files.
10
+ #
11
+ # @return [void]
12
+ #
13
+ def install!
14
+ UI.message "- Installing target `#{library.name}` #{library.platform}" do
15
+ add_target
16
+ add_files_to_build_phases
17
+ create_suport_files_group
18
+ create_xcconfig_file
19
+ create_prefix_header
20
+ create_dummy_source
21
+ end
22
+ end
23
+
24
+ #-----------------------------------------------------------------------#
25
+
26
+ private
27
+
28
+ # Adds the build files of the pods to the target and adds a reference to
29
+ # the frameworks of the Pods.
30
+ #
31
+ # @note The Frameworks are used only for presentation purposes as the
32
+ # xcconfig is the authoritative source about their information.
33
+ #
34
+ # @return [void]
35
+ #
36
+ def add_files_to_build_phases
37
+ UI.message "- Adding Build files" do
38
+ library.file_accessors.each do |file_accessor|
39
+ consumer = file_accessor.spec_consumer
40
+ flags = compiler_flags_for_consumer(consumer)
41
+ source_files = file_accessor.source_files
42
+ file_refs = source_files.map { |sf| project.file_reference(sf) }
43
+ target.add_file_references(file_refs, flags)
44
+
45
+ file_accessor.spec_consumer.frameworks.each do |framework|
46
+ project.add_system_framework(framework, target)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Generates the contents of the xcconfig file and saves it to disk.
53
+ #
54
+ # @note The `ALWAYS_SEARCH_USER_PATHS` flag is enabled to support
55
+ # libraries like `EmbedReader`.
56
+ #
57
+ # @return [void]
58
+ #
59
+ def create_xcconfig_file
60
+ path = library.xcconfig_path
61
+ UI.message "- Generating public xcconfig file at #{UI.path(path)}" do
62
+ gen = Generator::PublicPodXCConfig.new(library)
63
+ gen.save_as(path)
64
+ add_file_to_support_group(path)
65
+ end
66
+
67
+ path = library.xcconfig_private_path
68
+ UI.message "- Generating private xcconfig file at #{UI.path(path)}" do
69
+ gen = Generator::PrivatePodXCConfig.new(library)
70
+ gen.save_as(path)
71
+ xcconfig_file_ref = add_file_to_support_group(path)
72
+
73
+ target.build_configurations.each do |c|
74
+ c.base_configuration_reference = xcconfig_file_ref
75
+ end
76
+ end
77
+ end
78
+
79
+ # Creates a prefix header file which imports `UIKit` or `Cocoa` according
80
+ # to the platform of the target. This file also include any prefix header
81
+ # content reported by the specification of the pods.
82
+ #
83
+ # @return [void]
84
+ #
85
+ def create_prefix_header
86
+ path = library.prefix_header_path
87
+ UI.message "- Generating prefix header at #{UI.path(path)}" do
88
+ generator = Generator::PrefixHeader.new(library.file_accessors, library.platform)
89
+ generator.imports << library.target_environment_header_path.basename
90
+ generator.save_as(path)
91
+ add_file_to_support_group(path)
92
+
93
+ target.build_configurations.each do |c|
94
+ relative_path = path.relative_path_from(sandbox.root)
95
+ c.build_settings['GCC_PREFIX_HEADER'] = relative_path.to_s
96
+ end
97
+ end
98
+ end
99
+
100
+ ENABLE_OBJECT_USE_OBJC_FROM = {
101
+ :ios => Version.new('6'),
102
+ :osx => Version.new('10.8')
103
+ }
104
+
105
+ # Returns the compiler flags for the source files of the given specification.
106
+ #
107
+ # The following behavior is regarding the `OS_OBJECT_USE_OBJC` flag. When
108
+ # set to `0`, it will allow code to use `dispatch_release()` on >= iOS 6.0
109
+ # and OS X 10.8.
110
+ #
111
+ # * New libraries that do *not* require ARC don’t need to care about this
112
+ # issue at all.
113
+ #
114
+ # * New libraries that *do* require ARC _and_ have a deployment target of
115
+ # >= iOS 6.0 or OS X 10.8:
116
+ #
117
+ # These no longer use `dispatch_release()` and should *not* have the
118
+ # `OS_OBJECT_USE_OBJC` flag set to `0`.
119
+ #
120
+ # **Note:** this means that these libraries *have* to specify the
121
+ # deployment target in order to function well.
122
+ #
123
+ # * New libraries that *do* require ARC, but have a deployment target of
124
+ # < iOS 6.0 or OS X 10.8:
125
+ #
126
+ # These contain `dispatch_release()` calls and as such need the
127
+ # `OS_OBJECT_USE_OBJC` flag set to `1`.
128
+ #
129
+ # **Note:** libraries that do *not* specify a platform version are
130
+ # assumed to have a deployment target of < iOS 6.0 or OS X 10.8.
131
+ #
132
+ # For more information, see: http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h
133
+ #
134
+ # @param [Specification::Consumer] consumer
135
+ # The consumer for the specification for which the compiler flags
136
+ # are needed.
137
+ #
138
+ # @return [String] The compiler flags.
139
+ #
140
+ def compiler_flags_for_consumer(consumer)
141
+ flags = consumer.compiler_flags.dup
142
+ if consumer.requires_arc
143
+ flags << '-fobjc-arc'
144
+ platform_name = consumer.platform_name
145
+ spec_deployment_target = consumer.spec.deployment_target(platform_name)
146
+ if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name]
147
+ flags << '-DOS_OBJECT_USE_OBJC=0'
148
+ end
149
+ end
150
+ if target_definition.inhibits_warnings_for_pod?(consumer.spec.root.name)
151
+ flags << '-w -Xanalyzer -analyzer-disable-checker'
152
+ end
153
+ flags * " "
154
+ end
155
+
156
+ #-----------------------------------------------------------------------#
157
+
158
+ end
159
+ end
160
+ end
@@ -35,9 +35,9 @@ module Pod
35
35
  #
36
36
  attr_reader :installation_root
37
37
 
38
- # @return [Library] the libraries generated by the installer.
38
+ # @return [Array<Target>] the targets represented in the Podfile.
39
39
  #
40
- attr_reader :libraries
40
+ attr_reader :targets
41
41
 
42
42
  # @param [Podfile] podfile @see #podfile
43
43
  # @param [Sandbox] sandbox @see #sandbox
@@ -46,11 +46,11 @@ module Pod
46
46
  #
47
47
  # @todo Too many initialization arguments
48
48
  #
49
- def initialize(podfile, sandbox, installation_root, libraries)
49
+ def initialize(podfile, sandbox, installation_root, targets)
50
50
  @podfile = podfile
51
51
  @sandbox = sandbox
52
52
  @installation_root = installation_root
53
- @libraries = libraries
53
+ @targets = targets
54
54
  end
55
55
 
56
56
  # Integrates the user projects associated with the {TargetDefinitions}
@@ -110,8 +110,8 @@ module Pod
110
110
  # @return [void]
111
111
  #
112
112
  def integrate_user_targets
113
- libraries_to_integrate.sort_by(&:name).each do |lib|
114
- TargetIntegrator.new(lib).integrate!
113
+ targets_to_integrate.sort_by(&:name).each do |target|
114
+ TargetIntegrator.new(target).integrate!
115
115
  end
116
116
  end
117
117
 
@@ -128,7 +128,7 @@ module Pod
128
128
  #
129
129
  def warn_about_empty_podfile
130
130
  if podfile.target_definitions.values.all?{ |td| td.empty? }
131
- UI.warn "[!] The Podfile does not contain any dependency."
131
+ UI.warn "[!] The Podfile does not contain any dependencies."
132
132
  end
133
133
  end
134
134
 
@@ -163,14 +163,14 @@ module Pod
163
163
  # @note Empty target definitions are ignored.
164
164
  #
165
165
  def user_project_paths
166
- libraries.map do |lib|
167
- lib.user_project_path
166
+ targets.map do |target|
167
+ target.user_project_path
168
168
  end.compact.uniq
169
169
  end
170
170
 
171
171
 
172
- def libraries_to_integrate
173
- libraries.reject { |lib| lib.target_definition.empty? }
172
+ def targets_to_integrate
173
+ targets.reject { |target| target.target_definition.empty? }
174
174
  end
175
175
 
176
176
  #-----------------------------------------------------------------------#
@@ -9,14 +9,14 @@ module Pod
9
9
  #
10
10
  class TargetIntegrator
11
11
 
12
- # @return [Library] the library that should be integrated.
12
+ # @return [Target] the target that should be integrated.
13
13
  #
14
- attr_reader :library
14
+ attr_reader :target
15
15
 
16
- # @param [Library] library @see #target_definition
16
+ # @param [Target] target @see #target_definition
17
17
  #
18
- def initialize(library)
19
- @library = library
18
+ def initialize(target)
19
+ @target = target
20
20
  end
21
21
 
22
22
  # Integrates the user project targets. Only the targets that do **not**
@@ -26,7 +26,7 @@ module Pod
26
26
  # @return [void]
27
27
  #
28
28
  def integrate!
29
- return if targets.empty?
29
+ return if native_targets.empty?
30
30
  UI.section(integration_message) do
31
31
  add_xcconfig_base_configuration
32
32
  add_pods_library
@@ -36,46 +36,50 @@ module Pod
36
36
  end
37
37
  end
38
38
 
39
- # @return [Array<PBXNativeTarget>] the list of targets that the Pods
40
- # lib that need to be integrated.
39
+ # @return [Array<PBXNativeTarget>] the user targets for integration.
41
40
  #
42
- # @note A target is considered integrated if it already references
43
- #
44
- def targets
45
- unless @targets
46
- target_uuids = library.user_target_uuids
47
- targets = target_uuids.map do |uuid|
48
- target = user_project.objects_by_uuid[uuid]
49
- unless target
41
+ def native_targets
42
+ unless @native_targets
43
+ target_uuids = target.user_target_uuids
44
+ native_targets = target_uuids.map do |uuid|
45
+ native_target = user_project.objects_by_uuid[uuid]
46
+ unless native_target
50
47
  raise Informative, "[Bug] Unable to find the target with " \
51
- "the `#{uuid}` UUID for the `#{library}` library"
48
+ "the `#{uuid}` UUID for the `#{target}` integration library"
52
49
  end
53
- target
50
+ native_target
54
51
  end
55
- non_integrated = targets.reject do |target|
56
- target.frameworks_build_phase.files.any? do |build_file|
52
+ non_integrated = native_targets.reject do |native_target|
53
+ native_target.frameworks_build_phase.files.any? do |build_file|
57
54
  file_ref = build_file.file_ref
58
55
  file_ref &&
59
56
  file_ref.isa == 'PBXFileReference' &&
60
- file_ref.display_name == library.product_name
57
+ file_ref.display_name == target.product_name
61
58
  end
62
59
  end
63
- @targets = non_integrated
60
+ @native_targets = non_integrated
64
61
  end
65
- @targets
62
+ @native_targets
66
63
  end
67
64
 
68
65
  # Read the project from the disk to ensure that it is up to date as
69
66
  # other TargetIntegrators might have modified it.
70
67
  #
71
68
  def user_project
72
- @user_project ||= Xcodeproj::Project.new(library.user_project_path)
69
+ @user_project ||= Xcodeproj::Project.new(target.user_project_path)
70
+ end
71
+
72
+ # Read the pods project from the disk to ensure that it is up to date as
73
+ # other TargetIntegrators might have modified it.
74
+ #
75
+ def pods_project
76
+ @pods_project ||= Xcodeproj::Project.new(target.sandbox.project_path)
73
77
  end
74
78
 
75
79
  # @return [String] a string representation suitable for debugging.
76
80
  #
77
81
  def inspect
78
- "#<#{self.class} for target `#{target_definition.label}'>"
82
+ "#<#{self.class} for target `#{target.label}'>"
79
83
  end
80
84
 
81
85
  #---------------------------------------------------------------------#
@@ -84,6 +88,12 @@ module Pod
84
88
 
85
89
  private
86
90
 
91
+ # @return [Specification::Consumer] the consumer for the specifications.
92
+ #
93
+ def spec_consumers
94
+ @spec_consumers ||= target.pod_targets.map(&:file_accessors).flatten.map(&:spec_consumer)
95
+ end
96
+
87
97
  # Adds the `xcconfig` configurations files generated for the current
88
98
  # {TargetDefinition} to the build configurations of the targets that
89
99
  # should be integrated.
@@ -98,25 +108,31 @@ module Pod
98
108
  # @return [void]
99
109
  #
100
110
  def add_xcconfig_base_configuration
101
- xcconfig = user_project.new_file(library.xcconfig_relative_path)
102
- targets.each do |target|
103
- check_overridden_build_settings(library.xcconfig, target)
104
- target.build_configurations.each do |config|
111
+ xcconfig = user_project.files.select { |f| f.path == target.xcconfig_relative_path }.first ||
112
+ user_project.new_file(target.xcconfig_relative_path)
113
+ native_targets.each do |native_target|
114
+ check_overridden_build_settings(target.xcconfig, native_target)
115
+ native_target.build_configurations.each do |config|
105
116
  config.base_configuration_reference = xcconfig
106
117
  end
107
118
  end
108
119
  end
109
120
 
110
- # Adds a file reference to the library of the {TargetDefinition} and
111
- # adds it to the frameworks build phase of the targets.
121
+ # Adds spec libraries to the frameworks build phase of the
122
+ # {TargetDefinition} integration libraries. Adds a file reference to
123
+ # the library of the {TargetDefinition} and adds it to the frameworks
124
+ # build phase of the targets.
112
125
  #
113
126
  # @return [void]
114
127
  #
115
128
  def add_pods_library
116
129
  frameworks = user_project.frameworks_group
117
- pods_library = frameworks.new_static_library(library.label)
118
- targets.each do |target|
119
- target.frameworks_build_phase.add_file_reference(pods_library)
130
+ native_targets.each do |native_target|
131
+ library = frameworks.files.select { |f| f.path == target.product_name }.first ||
132
+ frameworks.new_static_library(target.name)
133
+ unless native_target.frameworks_build_phase.files_references.include?(library)
134
+ native_target.frameworks_build_phase.add_file_reference(library)
135
+ end
120
136
  end
121
137
  end
122
138
 
@@ -127,9 +143,11 @@ module Pod
127
143
  # @return [void]
128
144
  #
129
145
  def add_copy_resources_script_phase
130
- targets.each do |target|
131
- phase = target.new_shell_script_build_phase('Copy Pods Resources')
132
- path = library.copy_resources_script_relative_path
146
+ phase_name = "Copy Pods Resources"
147
+ native_targets.each do |native_target|
148
+ phase = native_target.shell_script_build_phases.select { |bp| bp.name == phase_name }.first ||
149
+ native_target.new_shell_script_build_phase(phase_name)
150
+ path = target.copy_resources_script_relative_path
133
151
  phase.shell_script = %{"#{path}"\n}
134
152
  end
135
153
  end
@@ -144,10 +162,12 @@ module Pod
144
162
  # @return [void]
145
163
  #
146
164
  def add_check_manifest_lock_script_phase
147
- targets.each do |target|
148
- phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
149
- target.build_phases.unshift(phase)
150
- phase.name = 'Check Pods Manifest.lock'
165
+ phase_name = 'Check Pods Manifest.lock'
166
+ native_targets.each do |native_target|
167
+ next if native_target.shell_script_build_phases.any? { |phase| phase.name == phase_name }
168
+ phase = native_target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
169
+ native_target.build_phases.unshift(phase)
170
+ phase.name = phase_name
151
171
  phase.shell_script = <<-EOS.strip_heredoc
152
172
  diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
153
173
  if [[ $? != 0 ]] ; then
@@ -165,7 +185,7 @@ module Pod
165
185
  # @return [void]
166
186
  #
167
187
  def save_user_project
168
- user_project.save_as(library.user_project_path)
188
+ user_project.save_as(target.user_project_path)
169
189
  end
170
190
 
171
191
  #---------------------------------------------------------------------#
@@ -179,11 +199,11 @@ module Pod
179
199
  #
180
200
  # @return [void]
181
201
  #
182
- def check_overridden_build_settings(xcconfig, target)
202
+ def check_overridden_build_settings(xcconfig, native_target)
183
203
  return unless xcconfig
184
204
 
185
205
  configs_by_overridden_key = {}
186
- target.build_configurations.each do |config|
206
+ native_target.build_configurations.each do |config|
187
207
  xcconfig.attributes.keys.each do |key|
188
208
  target_value = config.build_settings[key]
189
209
 
@@ -194,13 +214,13 @@ module Pod
194
214
  end
195
215
 
196
216
  configs_by_overridden_key.each do |key, config_names|
197
- name = "#{target.name} [#{config_names.join(' - ')}]"
217
+ name = "#{native_target.name} [#{config_names.join(' - ')}]"
198
218
  actions = [
199
219
  "Use the `$(inherited)` flag, or",
200
220
  "Remove the build settings from the target."
201
221
  ]
202
222
  UI.warn("The target `#{name}` overrides the `#{key}` build " \
203
- "setting defined in `#{library.xcconfig_relative_path}'.",
223
+ "setting defined in `#{target.xcconfig_relative_path}'.",
204
224
  actions)
205
225
  end
206
226
  end
@@ -210,10 +230,10 @@ module Pod
210
230
  # integration.
211
231
  #
212
232
  def integration_message
213
- "Integrating `#{library.product_name}` into " \
214
- "#{'target'.pluralize(targets.size)} " \
215
- "`#{targets.map(&:name).to_sentence}` " \
216
- "of project #{UI.path library.user_project_path}."
233
+ "Integrating Pod #{'target'.pluralize(target.pod_targets.size)} " \
234
+ "`#{target.pod_targets.map(&:name).to_sentence}` " \
235
+ "into aggregate target #{target.name} " \
236
+ "of project #{UI.path target.user_project_path}."
217
237
  end
218
238
 
219
239
  #---------------------------------------------------------------------#