cocoapods 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +329 -0
- data/lib/cocoapods/command/init.rb +6 -6
- data/lib/cocoapods/command/ipc/list.rb +40 -0
- data/lib/cocoapods/command/ipc/podfile.rb +31 -0
- data/lib/cocoapods/command/ipc/repl.rb +51 -0
- data/lib/cocoapods/command/ipc/spec.rb +29 -0
- data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
- data/lib/cocoapods/command/ipc.rb +18 -0
- data/lib/cocoapods/command/lib/create.rb +105 -0
- data/lib/cocoapods/command/lib/lint.rb +111 -0
- data/lib/cocoapods/command/lib.rb +3 -207
- data/lib/cocoapods/command/repo/push.rb +44 -20
- data/lib/cocoapods/command/setup.rb +2 -1
- data/lib/cocoapods/command/spec/lint.rb +4 -0
- data/lib/cocoapods/command.rb +2 -1
- data/lib/cocoapods/config.rb +4 -1
- data/lib/cocoapods/downloader/cache.rb +1 -0
- data/lib/cocoapods/downloader.rb +20 -0
- data/lib/cocoapods/executable.rb +1 -1
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/acknowledgements/plist.rb +4 -1
- data/lib/cocoapods/generator/copy_resources_script.rb +4 -10
- data/lib/cocoapods/generator/header.rb +2 -1
- data/lib/cocoapods/generator/prefix_header.rb +0 -12
- data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +38 -5
- data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +5 -4
- data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +5 -1
- data/lib/cocoapods/installer/analyzer/target_inspector.rb +24 -1
- data/lib/cocoapods/installer/analyzer.rb +161 -1
- data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +29 -9
- data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +204 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +314 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +401 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +214 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator.rb +265 -0
- data/lib/cocoapods/installer/xcode.rb +7 -0
- data/lib/cocoapods/installer.rb +50 -214
- data/lib/cocoapods/resolver.rb +15 -9
- data/lib/cocoapods/sandbox/headers_store.rb +4 -10
- data/lib/cocoapods/sandbox/path_list.rb +20 -9
- data/lib/cocoapods/sources_manager.rb +7 -10
- data/lib/cocoapods/target/aggregate_target.rb +20 -0
- data/lib/cocoapods/target/pod_target.rb +37 -7
- data/lib/cocoapods/user_interface/error_report.rb +7 -0
- data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
- data/lib/cocoapods/user_interface.rb +7 -5
- data/lib/cocoapods/validator.rb +59 -11
- metadata +112 -83
- data/lib/cocoapods/command/inter_process_communication.rb +0 -177
- data/lib/cocoapods/installer/file_references_installer.rb +0 -310
- data/lib/cocoapods/installer/migrator.rb +0 -86
- data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +0 -191
- data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +0 -368
- data/lib/cocoapods/installer/target_installer.rb +0 -210
data/lib/cocoapods/downloader.rb
CHANGED
@@ -33,11 +33,16 @@ module Pod
|
|
33
33
|
cache_path: Config.instance.cache_root + 'Pods'
|
34
34
|
)
|
35
35
|
can_cache &&= !Config.instance.skip_download_cache
|
36
|
+
|
37
|
+
request = preprocess_request(request)
|
38
|
+
|
36
39
|
if can_cache
|
37
40
|
raise ArgumentError, 'Must provide a `cache_path` when caching.' unless cache_path
|
38
41
|
cache = Cache.new(cache_path)
|
39
42
|
result = cache.download_pod(request)
|
40
43
|
else
|
44
|
+
raise ArgumentError, 'Must provide a `target` when caching is disabled.' unless target
|
45
|
+
|
41
46
|
require 'cocoapods/installer/pod_source_preparer'
|
42
47
|
result, = download_request(request, target)
|
43
48
|
Installer::PodSourcePreparer.new(result.spec, result.location).prepare!
|
@@ -110,6 +115,21 @@ module Pod
|
|
110
115
|
end
|
111
116
|
end
|
112
117
|
|
118
|
+
# Return a new request after preprocessing by the downloader
|
119
|
+
#
|
120
|
+
# @param [Request] request
|
121
|
+
# the request that needs preprocessing
|
122
|
+
#
|
123
|
+
# @return [Request] the preprocessed request
|
124
|
+
#
|
125
|
+
def self.preprocess_request(request)
|
126
|
+
Request.new(
|
127
|
+
:spec => request.spec,
|
128
|
+
:released => request.released_pod?,
|
129
|
+
:name => request.name,
|
130
|
+
:params => Downloader.preprocess_options(request.params))
|
131
|
+
end
|
132
|
+
|
113
133
|
public
|
114
134
|
|
115
135
|
class DownloaderError; include CLAide::InformativeError; end
|
data/lib/cocoapods/executable.rb
CHANGED
@@ -108,7 +108,7 @@ module Pod
|
|
108
108
|
#
|
109
109
|
def self.which!(program)
|
110
110
|
which(program).tap do |bin|
|
111
|
-
raise Informative, "Unable to locate the executable `#{
|
111
|
+
raise Informative, "Unable to locate the executable `#{program}`" unless bin
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -33,11 +33,14 @@ module Pod
|
|
33
33
|
|
34
34
|
def hash_for_spec(spec)
|
35
35
|
if (license = license_text(spec))
|
36
|
-
{
|
36
|
+
hash = {
|
37
37
|
:Type => 'PSGroupSpecifier',
|
38
38
|
:Title => sanitize_encoding(spec.name),
|
39
39
|
:FooterText => sanitize_encoding(license),
|
40
40
|
}
|
41
|
+
hash[:License] = sanitize_encoding(spec.license[:type]) if spec.license[:type]
|
42
|
+
|
43
|
+
hash
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
@@ -119,12 +119,6 @@ case "${TARGETED_DEVICE_FAMILY}" in
|
|
119
119
|
;;
|
120
120
|
esac
|
121
121
|
|
122
|
-
realpath() {
|
123
|
-
DIRECTORY="$(cd "${1%/*}" && pwd)"
|
124
|
-
FILENAME="${1##*/}"
|
125
|
-
echo "$DIRECTORY/$FILENAME"
|
126
|
-
}
|
127
|
-
|
128
122
|
install_resource()
|
129
123
|
{
|
130
124
|
if [[ "$1" = /* ]] ; then
|
@@ -144,8 +138,8 @@ EOM
|
|
144
138
|
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \\"$RESOURCE_PATH\\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
|
145
139
|
;;
|
146
140
|
*\.xib)
|
147
|
-
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \\"$RESOURCE_PATH\\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT}"
|
148
|
-
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \\"$RESOURCE_PATH\\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}"
|
141
|
+
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \\"$RESOURCE_PATH\\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
|
142
|
+
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \\"$RESOURCE_PATH\\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
|
149
143
|
;;
|
150
144
|
*.framework)
|
151
145
|
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
@@ -166,7 +160,7 @@ EOM
|
|
166
160
|
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
|
167
161
|
;;
|
168
162
|
*.xcassets)
|
169
|
-
ABSOLUTE_XCASSET_FILE
|
163
|
+
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
|
170
164
|
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
|
171
165
|
;;
|
172
166
|
*)
|
@@ -195,7 +189,7 @@ then
|
|
195
189
|
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
|
196
190
|
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
|
197
191
|
while read line; do
|
198
|
-
if [[ $line != "
|
192
|
+
if [[ $line != "${PODS_ROOT}*" ]]; then
|
199
193
|
XCASSET_FILES+=("$line")
|
200
194
|
fi
|
201
195
|
done <<<"$OTHER_XCASSETS"
|
@@ -55,18 +55,6 @@ module Pod
|
|
55
55
|
|
56
56
|
result
|
57
57
|
end
|
58
|
-
|
59
|
-
protected
|
60
|
-
|
61
|
-
# Generates the contents of the header according to the platform.
|
62
|
-
#
|
63
|
-
# @return [String]
|
64
|
-
#
|
65
|
-
def generate_platform_import_header
|
66
|
-
result = "#ifdef __OBJC__\n"
|
67
|
-
result << super
|
68
|
-
result << "#endif\n"
|
69
|
-
end
|
70
58
|
end
|
71
59
|
end
|
72
60
|
end
|
@@ -4,7 +4,7 @@ module Pod
|
|
4
4
|
# Generates the xcconfigs for the aggregate targets.
|
5
5
|
#
|
6
6
|
class AggregateXCConfig
|
7
|
-
# @return [
|
7
|
+
# @return [AggregateTarget] the target represented by this xcconfig.
|
8
8
|
#
|
9
9
|
attr_reader :target
|
10
10
|
|
@@ -60,10 +60,8 @@ module Pod
|
|
60
60
|
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
|
61
61
|
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
|
62
62
|
'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
|
63
|
-
}
|
64
|
-
|
65
|
-
config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES'
|
66
|
-
end
|
63
|
+
}.merge(embedded_content_settings)
|
64
|
+
|
67
65
|
@xcconfig = Xcodeproj::Config.new(config)
|
68
66
|
|
69
67
|
@xcconfig.merge!(merged_user_target_xcconfigs)
|
@@ -90,6 +88,41 @@ module Pod
|
|
90
88
|
|
91
89
|
protected
|
92
90
|
|
91
|
+
def target_swift_version
|
92
|
+
settings = target.native_target.resolved_build_setting('SWIFT_VERSION') unless target.native_target.nil?
|
93
|
+
settings.values.compact.uniq.first unless settings.nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION = Gem::Version.new('2.3')
|
97
|
+
|
98
|
+
# @return [Hash<String, String>] the build settings necessary for Swift
|
99
|
+
# targets to be correctly embedded in their host.
|
100
|
+
#
|
101
|
+
def embedded_content_settings
|
102
|
+
# For embedded targets, which live in a host target, CocoaPods
|
103
|
+
# copies all of the embedded target's pod_targets its host
|
104
|
+
# target. Therefore, this check will properly require the Swift
|
105
|
+
# libs in the host target, if the embedded target has any pod targets
|
106
|
+
# that use Swift. Setting this for the embedded target would
|
107
|
+
# cause an App Store rejection because frameworks cannot be embedded
|
108
|
+
# in embedded targets.
|
109
|
+
|
110
|
+
swift_version = Gem::Version.new(target_swift_version)
|
111
|
+
should_embed = !target.requires_host_target? && pod_targets.any?(&:uses_swift?)
|
112
|
+
embed_value = should_embed ? 'YES' : 'NO'
|
113
|
+
|
114
|
+
config = {
|
115
|
+
'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' => embed_value,
|
116
|
+
'EMBEDDED_CONTENT_CONTAINS_SWIFT' => embed_value,
|
117
|
+
}
|
118
|
+
|
119
|
+
if swift_version >= EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION || !should_embed
|
120
|
+
config.delete('EMBEDDED_CONTENT_CONTAINS_SWIFT')
|
121
|
+
end
|
122
|
+
|
123
|
+
config
|
124
|
+
end
|
125
|
+
|
93
126
|
# @return [Hash<String, String>] the build settings necessary to import
|
94
127
|
# the pod targets.
|
95
128
|
#
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/object/try'
|
2
|
+
|
1
3
|
module Pod
|
2
4
|
module Generator
|
3
5
|
module XCConfig
|
@@ -283,9 +285,9 @@ module Pod
|
|
283
285
|
#
|
284
286
|
def self.add_language_specific_settings(target, xcconfig)
|
285
287
|
if target.uses_swift?
|
286
|
-
|
287
|
-
|
288
|
-
}
|
288
|
+
other_swift_flags = ['$(inherited)', quote(%w(-D COCOAPODS))]
|
289
|
+
other_swift_flags << quote(%w(-suppress-warnings)) if target.try(:inhibit_warnings?)
|
290
|
+
build_settings = { 'OTHER_SWIFT_FLAGS' => other_swift_flags.join(' ') }
|
289
291
|
xcconfig.merge!(build_settings)
|
290
292
|
end
|
291
293
|
end
|
@@ -314,7 +316,6 @@ module Pod
|
|
314
316
|
search_paths << search_path
|
315
317
|
end
|
316
318
|
end
|
317
|
-
search_paths
|
318
319
|
end
|
319
320
|
end
|
320
321
|
|
@@ -23,7 +23,11 @@ module Pod
|
|
23
23
|
#
|
24
24
|
def scope_suffixes
|
25
25
|
return { variants.first => nil } if variants.count == 1
|
26
|
-
scope_by_specs
|
26
|
+
Hash[scope_by_specs.map do |variant, scope|
|
27
|
+
require 'digest'
|
28
|
+
scope = Digest::MD5.hexdigest(scope)[0..7] if !scope.nil? && scope.length >= 50
|
29
|
+
[variant, scope]
|
30
|
+
end]
|
27
31
|
end
|
28
32
|
|
29
33
|
# Groups the collection by result of the block.
|
@@ -44,6 +44,7 @@ module Pod
|
|
44
44
|
result.platform = compute_platform(targets)
|
45
45
|
result.archs = compute_archs(targets)
|
46
46
|
result.project = user_project
|
47
|
+
result.target_definition.swift_version = compute_swift_version_from_targets(targets)
|
47
48
|
result
|
48
49
|
end
|
49
50
|
|
@@ -72,7 +73,7 @@ module Pod
|
|
72
73
|
else
|
73
74
|
raise Informative, 'Could not automatically select an Xcode project. ' \
|
74
75
|
"Specify one in your Podfile like so:\n\n" \
|
75
|
-
"
|
76
|
+
" project 'path/to/Project.xcodeproj'\n"
|
76
77
|
end
|
77
78
|
end
|
78
79
|
path
|
@@ -205,6 +206,28 @@ module Pod
|
|
205
206
|
end
|
206
207
|
end
|
207
208
|
end
|
209
|
+
|
210
|
+
# Compute the Swift version for the target build configurations. If more
|
211
|
+
# than one Swift version is defined for a given target, then it will raise.
|
212
|
+
#
|
213
|
+
# @param [Array<PBXNativeTarget>] targets
|
214
|
+
# the targets that are checked for Swift versions.
|
215
|
+
#
|
216
|
+
# @return [String] the targets Swift version or nil
|
217
|
+
#
|
218
|
+
def compute_swift_version_from_targets(targets)
|
219
|
+
versions = targets.flat_map do |target|
|
220
|
+
target.resolved_build_setting('SWIFT_VERSION').values
|
221
|
+
end.flatten.compact.uniq
|
222
|
+
case versions.count
|
223
|
+
when 0
|
224
|
+
nil
|
225
|
+
when 1
|
226
|
+
versions.first
|
227
|
+
else
|
228
|
+
raise Informative, 'There may only be up to 1 unique SWIFT_VERSION per target.'
|
229
|
+
end
|
230
|
+
end
|
208
231
|
end
|
209
232
|
end
|
210
233
|
end
|
@@ -226,16 +226,142 @@ module Pod
|
|
226
226
|
|
227
227
|
private
|
228
228
|
|
229
|
+
# Copies the pod_targets of any of the app embedded aggregate targets into
|
230
|
+
# their potential host aggregate target, if that potential host aggregate target's
|
231
|
+
# user_target hosts any of the app embedded aggregate targets' user_targets
|
232
|
+
#
|
233
|
+
# @param [AggregateTarget] aggregate_target the aggregate target whose user_target
|
234
|
+
# might host one or more of the embedded aggregate targets' user_targets
|
235
|
+
#
|
236
|
+
# @param [Array<AggregateTarget>] embedded_aggregate_targets the aggregate targets
|
237
|
+
# representing the embedded targets to be integrated
|
238
|
+
#
|
239
|
+
def copy_embedded_target_pod_targets_to_host(aggregate_target, embedded_aggregate_targets)
|
240
|
+
return if aggregate_target.requires_host_target?
|
241
|
+
# Get the uuids of the aggregate_target's user_targets' embedded targets if any
|
242
|
+
embedded_uuids = Set.new(aggregate_target.user_targets.map do |target|
|
243
|
+
aggregate_target.user_project.embedded_targets_in_native_target(target).map(&:uuid)
|
244
|
+
end.flatten)
|
245
|
+
return if embedded_uuids.empty?
|
246
|
+
embedded_aggregate_targets.each do |embedded_target|
|
247
|
+
next unless embedded_target.user_targets.map(&:uuid).any? do |embedded_uuid|
|
248
|
+
embedded_uuids.include? embedded_uuid
|
249
|
+
end
|
250
|
+
pod_target_names = aggregate_target.pod_targets.map(&:name)
|
251
|
+
# This embedded target is hosted by the aggregate target's user_target; copy over the non-duplicate pod_targets
|
252
|
+
aggregate_target.pod_targets = aggregate_target.pod_targets + embedded_target.pod_targets.select do |pod_target|
|
253
|
+
!pod_target_names.include? pod_target.name
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Raises an error if there are embedded targets in the Podfile, but
|
259
|
+
# their host targets have not been declared in the Podfile. As it
|
260
|
+
# finds host targets, it collection information on host target types.
|
261
|
+
#
|
262
|
+
# @param [Array<AggregateTarget>] aggregate_targets the generated
|
263
|
+
# aggregate targets
|
264
|
+
#
|
265
|
+
# @param [Array<AggregateTarget>] embedded_aggregate_targets the aggregate targets
|
266
|
+
# representing the embedded targets to be integrated
|
267
|
+
#
|
268
|
+
def analyze_host_targets_in_podfile(aggregate_targets, embedded_aggregate_targets)
|
269
|
+
target_definitions_by_uuid = {}
|
270
|
+
# Collect aggregate target definitions by uuid to later lookup host target
|
271
|
+
# definitions and verify their compatiblity with their embedded targets
|
272
|
+
aggregate_targets.each do |target|
|
273
|
+
target.user_targets.map(&:uuid).each do |uuid|
|
274
|
+
target_definitions_by_uuid[uuid] = target.target_definition
|
275
|
+
end
|
276
|
+
end
|
277
|
+
aggregate_target_user_projects = aggregate_targets.map(&:user_project)
|
278
|
+
embedded_targets_missing_hosts = []
|
279
|
+
host_uuid_to_embedded_target_definitions = {}
|
280
|
+
# Search all of the known user projects for each embedded target's hosts
|
281
|
+
embedded_aggregate_targets.each do |target|
|
282
|
+
host_uuids = []
|
283
|
+
aggregate_target_user_projects.product(target.user_targets).each do |user_project, user_target|
|
284
|
+
host_uuids += user_project.host_targets_for_embedded_target(user_target).map(&:uuid)
|
285
|
+
end
|
286
|
+
# For each host, keep track of its embedded target definitions
|
287
|
+
# to later verify each embedded target's compatiblity with its host,
|
288
|
+
# ignoring the hosts that aren't known to CocoaPods (no target
|
289
|
+
# definitions in the Podfile)
|
290
|
+
host_uuids.each do |uuid|
|
291
|
+
(host_uuid_to_embedded_target_definitions[uuid] ||= []) << target.target_definition if target_definitions_by_uuid.key? uuid
|
292
|
+
end
|
293
|
+
# If none of the hosts are known to CocoaPods (no target definitions
|
294
|
+
# in the Podfile), add it to the list of targets missing hosts
|
295
|
+
embedded_targets_missing_hosts << target unless host_uuids.any? do |uuid|
|
296
|
+
target_definitions_by_uuid.key? uuid
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
unless embedded_targets_missing_hosts.empty?
|
301
|
+
embedded_targets_missing_hosts_product_types = embedded_targets_missing_hosts.map(&:user_targets).flatten.map(&:symbol_type).uniq
|
302
|
+
# If the targets missing hosts are only frameworks, then this is likely
|
303
|
+
# a project for doing framework development. In that case, just warn that
|
304
|
+
# the frameworks that these targets depend on won't be integrated anywhere
|
305
|
+
if embedded_targets_missing_hosts_product_types == [:framework]
|
306
|
+
UI.warn 'The Podfile contains framework targets, for which the Podfile does not contain host targets (targets which embed the framework).' \
|
307
|
+
"\n" \
|
308
|
+
'If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).'
|
309
|
+
else
|
310
|
+
target_names = embedded_targets_missing_hosts.map do |target|
|
311
|
+
target.name.sub('Pods-', '') # Make the target names more recognizable to the user
|
312
|
+
end.join ', '
|
313
|
+
raise Informative, "Unable to find host target(s) for #{target_names}. Please add the host targets for the embedded targets to the Podfile." \
|
314
|
+
"\n" \
|
315
|
+
'Certain kinds of targets require a host target. A host target is a "parent" target which embeds a "child" target. These are example types of targets that need a host target:' \
|
316
|
+
"\n- Framework" \
|
317
|
+
"\n- App Extension" \
|
318
|
+
"\n- Watch OS 1 Extension" \
|
319
|
+
"\n- Messages Extension (except when used with a Messages Application)"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
target_mismatches = []
|
324
|
+
check_prop = lambda do |target_definition1, target_definition2, attr, msg|
|
325
|
+
attr1 = target_definition1.send(attr)
|
326
|
+
attr2 = target_definition2.send(attr)
|
327
|
+
if attr1 != attr2
|
328
|
+
target_mismatches << "- #{target_definition1.name} (#{attr1}) and #{target_definition2.name} (#{attr2}) #{msg}."
|
329
|
+
end
|
330
|
+
end
|
331
|
+
host_uuid_to_embedded_target_definitions.each do |uuid, target_definitions|
|
332
|
+
host_target_definition = target_definitions_by_uuid[uuid]
|
333
|
+
target_definitions.each do |target_definition|
|
334
|
+
check_prop.call(host_target_definition, target_definition, :platform, 'do not use the same platform')
|
335
|
+
check_prop.call(host_target_definition, target_definition, :uses_frameworks?, 'do not both set use_frameworks!')
|
336
|
+
check_prop.call(host_target_definition, target_definition, :swift_version, 'do not use the same Swift version')
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
unless target_mismatches.empty?
|
341
|
+
heading = 'Unable to integrate the following embedded targets with their respective host targets (a host target is a "parent" target which embeds a "child" target like a framework or extension):'
|
342
|
+
raise Informative, heading + "\n\n" + target_mismatches.sort.uniq.join("\n")
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
229
346
|
# Creates the models that represent the targets generated by CocoaPods.
|
230
347
|
#
|
231
348
|
# @return [Array<AggregateTarget>]
|
232
349
|
#
|
233
350
|
def generate_targets
|
234
351
|
specs_by_target = result.specs_by_target.reject { |td, _| td.abstract? }
|
352
|
+
check_pod_target_swift_versions(specs_by_target)
|
235
353
|
pod_targets = generate_pod_targets(specs_by_target)
|
236
354
|
aggregate_targets = specs_by_target.keys.map do |target_definition|
|
237
355
|
generate_target(target_definition, pod_targets)
|
238
356
|
end
|
357
|
+
if installation_options.integrate_targets?
|
358
|
+
# Copy embedded target pods that cannot have their pods embedded as frameworks to their host targets
|
359
|
+
embedded_targets = aggregate_targets.select(&:requires_host_target?).select(&:requires_frameworks?)
|
360
|
+
analyze_host_targets_in_podfile(aggregate_targets, embedded_targets)
|
361
|
+
aggregate_targets.each do |target|
|
362
|
+
copy_embedded_target_pod_targets_to_host(target, embedded_targets)
|
363
|
+
end
|
364
|
+
end
|
239
365
|
aggregate_targets.each do |target|
|
240
366
|
target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
|
241
367
|
target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
|
@@ -277,11 +403,45 @@ module Pod
|
|
277
403
|
target.pod_targets = pod_targets.select do |pod_target|
|
278
404
|
pod_target.target_definitions.include?(target_definition)
|
279
405
|
end
|
406
|
+
|
280
407
|
target
|
281
408
|
end
|
282
409
|
|
410
|
+
# Verify that targets using a pod have the same swift version
|
411
|
+
#
|
412
|
+
# @param [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
|
413
|
+
# the resolved specifications grouped by target.
|
414
|
+
#
|
415
|
+
# @note raises Informative if targets using a pod do not have
|
416
|
+
# the same swift version
|
417
|
+
#
|
418
|
+
def check_pod_target_swift_versions(specs_by_target)
|
419
|
+
targets_by_spec = {}
|
420
|
+
specs_by_target.each do |target, specs|
|
421
|
+
specs.each do |spec|
|
422
|
+
(targets_by_spec[spec] ||= []) << target
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
error_message_for_target = lambda do |target|
|
427
|
+
"#{target.name} (Swift #{target.swift_version})"
|
428
|
+
end
|
429
|
+
|
430
|
+
error_messages = targets_by_spec.map do |spec, targets|
|
431
|
+
swift_targets = targets.reject { |target| target.swift_version.blank? }
|
432
|
+
next if swift_targets.empty? || swift_targets.uniq(&:swift_version).count == 1
|
433
|
+
target_errors = swift_targets.map(&error_message_for_target).join(', ')
|
434
|
+
"- #{spec.name} required by #{target_errors}"
|
435
|
+
end.compact
|
436
|
+
|
437
|
+
unless error_messages.empty?
|
438
|
+
raise Informative, 'The following pods are integrated into targets ' \
|
439
|
+
"that do not have the same Swift version:\n\n#{error_messages.join("\n")}"
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
283
443
|
# Setup the pod targets for an aggregate target. Deduplicates resulting
|
284
|
-
# targets by grouping by
|
444
|
+
# targets by grouping by platform and subspec by their root
|
285
445
|
# to create a {PodTarget} for each spec.
|
286
446
|
#
|
287
447
|
# @param [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
|
@@ -11,7 +11,7 @@ module Pod
|
|
11
11
|
|
12
12
|
# @return [String] the PACKAGE emoji to use as prefix for every build phase aded to the user project
|
13
13
|
#
|
14
|
-
BUILD_PHASE_PREFIX =
|
14
|
+
BUILD_PHASE_PREFIX = '[CP] '.freeze
|
15
15
|
|
16
16
|
# @return [String] the name of the check manifest phase
|
17
17
|
#
|
@@ -20,7 +20,12 @@ module Pod
|
|
20
20
|
# @return [Array<Symbol>] the symbol types, which require that the pod
|
21
21
|
# frameworks are embedded in the output directory / product bundle.
|
22
22
|
#
|
23
|
-
|
23
|
+
# @note This does not include :app_extension or :watch_extension because
|
24
|
+
# these types must have their frameworks embedded in their host targets.
|
25
|
+
# For messages extensions, this only applies if it's embedded in a messages
|
26
|
+
# application.
|
27
|
+
#
|
28
|
+
EMBED_FRAMEWORK_TARGET_TYPES = [:application, :unit_test_bundle, :ui_test_bundle, :watch2_extension, :messages_application].freeze
|
24
29
|
|
25
30
|
# @return [String] the name of the embed frameworks phase
|
26
31
|
#
|
@@ -54,6 +59,7 @@ module Pod
|
|
54
59
|
|
55
60
|
add_pods_library
|
56
61
|
add_embed_frameworks_script_phase
|
62
|
+
remove_embed_frameworks_script_phase_from_embedded_targets
|
57
63
|
add_copy_resources_script_phase
|
58
64
|
add_check_manifest_lock_script_phase
|
59
65
|
end
|
@@ -110,6 +116,21 @@ module Pod
|
|
110
116
|
end
|
111
117
|
end
|
112
118
|
|
119
|
+
# Removes the embed frameworks build phase from embedded targets
|
120
|
+
#
|
121
|
+
# @note Older versions of CocoaPods would add this build phase to embedded
|
122
|
+
# targets. They should be removed on upgrade because embedded targets
|
123
|
+
# will have their frameworks embedded in their host targets.
|
124
|
+
#
|
125
|
+
def remove_embed_frameworks_script_phase_from_embedded_targets
|
126
|
+
return unless target.requires_host_target?
|
127
|
+
native_targets.each do |native_target|
|
128
|
+
if AggregateTarget::EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES.include? native_target.symbol_type
|
129
|
+
remove_embed_frameworks_script_phase(native_target)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
113
134
|
def add_embed_frameworks_script_phase_to_target(native_target)
|
114
135
|
phase = create_or_update_build_phase(native_target, EMBED_FRAMEWORK_PHASE_NAME)
|
115
136
|
script_path = target.embed_frameworks_script_relative_path
|
@@ -121,7 +142,7 @@ module Pod
|
|
121
142
|
# @param [PBXNativeTarget] native_target
|
122
143
|
#
|
123
144
|
def remove_embed_frameworks_script_phase(native_target)
|
124
|
-
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name
|
145
|
+
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(EMBED_FRAMEWORK_PHASE_NAME) }
|
125
146
|
return unless embed_build_phase.present?
|
126
147
|
native_target.build_phases.delete(embed_build_phase)
|
127
148
|
end
|
@@ -157,10 +178,9 @@ module Pod
|
|
157
178
|
native_target.build_phases.unshift(phase).uniq! unless native_target.build_phases.first == phase
|
158
179
|
phase.shell_script = <<-SH.strip_heredoc
|
159
180
|
diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
|
160
|
-
if [
|
161
|
-
|
162
|
-
|
163
|
-
EOM
|
181
|
+
if [ $? != 0 ] ; then
|
182
|
+
# print error to STDERR
|
183
|
+
echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2
|
164
184
|
exit 1
|
165
185
|
fi
|
166
186
|
SH
|
@@ -184,6 +204,7 @@ module Pod
|
|
184
204
|
# directory / product bundle.
|
185
205
|
#
|
186
206
|
def native_targets_to_embed_in
|
207
|
+
return [] if target.requires_host_target?
|
187
208
|
native_targets.select do |target|
|
188
209
|
EMBED_FRAMEWORK_TARGET_TYPES.include?(target.symbol_type)
|
189
210
|
end
|
@@ -215,8 +236,7 @@ module Pod
|
|
215
236
|
def create_or_update_build_phase(target, phase_name, phase_class = Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
|
216
237
|
prefixed_phase_name = BUILD_PHASE_PREFIX + phase_name
|
217
238
|
build_phases = target.build_phases.grep(phase_class)
|
218
|
-
build_phases.find { |phase| phase.name
|
219
|
-
build_phases.find { |phase| phase.name == phase_name }.tap { |p| p.name = prefixed_phase_name if p } ||
|
239
|
+
build_phases.find { |phase| phase.name && phase.name.end_with?(phase_name) }.tap { |p| p.name = prefixed_phase_name if p } ||
|
220
240
|
target.project.new(phase_class).tap do |phase|
|
221
241
|
UI.message("Adding Build Phase '#{prefixed_phase_name}' to project.") do
|
222
242
|
phase.name = prefixed_phase_name
|