cocoapods-dykit 0.5.2 → 0.5.3
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.
- checksums.yaml +4 -4
- data/lib/pod/command.rb +2 -0
- data/lib/pod/command/dyinstall.rb +51 -0
- data/lib/pod/command/dyupdate.rb +106 -0
- data/lib/pod/command/fmwk.rb +4 -0
- data/lib/pod/command/lib/dylint.rb +1 -0
- data/lib/pod/gem_version.rb +1 -1
- data/lib/pod/installer.rb +715 -0
- data/lib/pod/installer/analyzer.rb +934 -0
- data/lib/pod/installer/analyzer/analysis_result.rb +57 -0
- data/lib/pod/installer/analyzer/locking_dependency_analyzer.rb +95 -0
- data/lib/pod/installer/analyzer/pod_variant.rb +68 -0
- data/lib/pod/installer/analyzer/pod_variant_set.rb +157 -0
- data/lib/pod/installer/analyzer/podfile_dependency_cache.rb +54 -0
- data/lib/pod/installer/analyzer/sandbox_analyzer.rb +251 -0
- data/lib/pod/installer/analyzer/specs_state.rb +84 -0
- data/lib/pod/installer/analyzer/target_inspection_result.rb +45 -0
- data/lib/pod/installer/analyzer/target_inspector.rb +254 -0
- data/lib/pod/installer/installation_options.rb +158 -0
- data/lib/pod/installer/pod_source_installer.rb +214 -0
- data/lib/pod/installer/pod_source_preparer.rb +77 -0
- data/lib/pod/installer/podfile_validator.rb +139 -0
- data/lib/pod/installer/post_install_hooks_context.rb +107 -0
- data/lib/pod/installer/pre_install_hooks_context.rb +42 -0
- data/lib/pod/installer/source_provider_hooks_context.rb +32 -0
- data/lib/pod/installer/user_project_integrator.rb +253 -0
- data/lib/pod/installer/user_project_integrator/target_integrator.rb +462 -0
- data/lib/pod/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
- data/lib/pod/installer/xcode.rb +8 -0
- data/lib/pod/installer/xcode/pods_project_generator.rb +353 -0
- data/lib/pod/installer/xcode/pods_project_generator/aggregate_target_installer.rb +172 -0
- data/lib/pod/installer/xcode/pods_project_generator/file_references_installer.rb +367 -0
- data/lib/pod/installer/xcode/pods_project_generator/pod_target_installer.rb +718 -0
- data/lib/pod/installer/xcode/pods_project_generator/pod_target_integrator.rb +111 -0
- data/lib/pod/installer/xcode/pods_project_generator/target_installer.rb +265 -0
- data/lib/pod/installer/xcode/target_validator.rb +141 -0
- data/lib/pod/resolver.rb +632 -0
- metadata +34 -2
@@ -0,0 +1,111 @@
|
|
1
|
+
module Pod
|
2
|
+
class DyInstaller
|
3
|
+
class Xcode
|
4
|
+
class PodsProjectGenerator
|
5
|
+
# This class is responsible for integrating a pod target. This includes integrating
|
6
|
+
# the test targets included by each pod target.
|
7
|
+
#
|
8
|
+
class PodTargetIntegrator
|
9
|
+
# @return [PodTarget] the target that should be integrated.
|
10
|
+
#
|
11
|
+
attr_reader :target
|
12
|
+
|
13
|
+
# Init a new PodTargetIntegrator.
|
14
|
+
#
|
15
|
+
# @param [PodTarget] target @see #target
|
16
|
+
#
|
17
|
+
def initialize(target)
|
18
|
+
@target = target
|
19
|
+
end
|
20
|
+
|
21
|
+
# Integrates the pod target.
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
#
|
25
|
+
def integrate!
|
26
|
+
UI.section(integration_message) do
|
27
|
+
target.test_specs_by_native_target.each do |native_target, test_specs|
|
28
|
+
add_embed_frameworks_script_phase(native_target)
|
29
|
+
add_copy_resources_script_phase(native_target)
|
30
|
+
UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(test_specs), native_target)
|
31
|
+
end
|
32
|
+
specs = target.non_test_specs
|
33
|
+
UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(specs), target.native_target)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String] a string representation suitable for debugging.
|
38
|
+
#
|
39
|
+
def inspect
|
40
|
+
"#<#{self.class} for target `#{target.label}'>"
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# @!group Integration steps
|
46
|
+
#---------------------------------------------------------------------#
|
47
|
+
|
48
|
+
# Find or create a 'Copy Pods Resources' build phase
|
49
|
+
#
|
50
|
+
# @return [void]
|
51
|
+
#
|
52
|
+
def add_copy_resources_script_phase(native_target)
|
53
|
+
test_type = target.test_type_for_product_type(native_target.symbol_type)
|
54
|
+
script_path = "${PODS_ROOT}/#{target.copy_resources_script_path_for_test_type(test_type).relative_path_from(target.sandbox.root)}"
|
55
|
+
resource_paths = target.all_dependent_targets.flat_map do |dependent_target|
|
56
|
+
include_test_spec_paths = dependent_target == target
|
57
|
+
dependent_target.resource_paths(include_test_spec_paths)
|
58
|
+
end
|
59
|
+
input_paths = []
|
60
|
+
output_paths = []
|
61
|
+
unless resource_paths.empty?
|
62
|
+
resource_paths_flattened = resource_paths.flatten.uniq
|
63
|
+
input_paths = [script_path, *resource_paths_flattened]
|
64
|
+
output_paths = UserProjectIntegrator::TargetIntegrator.resource_output_paths(resource_paths_flattened)
|
65
|
+
end
|
66
|
+
UserProjectIntegrator::TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
|
67
|
+
UserProjectIntegrator::TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths, output_paths)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
|
71
|
+
#
|
72
|
+
# @return [void]
|
73
|
+
#
|
74
|
+
def add_embed_frameworks_script_phase(native_target)
|
75
|
+
test_type = target.test_type_for_product_type(native_target.symbol_type)
|
76
|
+
script_path = "${PODS_ROOT}/#{target.embed_frameworks_script_path_for_test_type(test_type).relative_path_from(target.sandbox.root)}"
|
77
|
+
all_dependent_targets = target.all_dependent_targets
|
78
|
+
framework_paths = all_dependent_targets.flat_map do |dependent_target|
|
79
|
+
include_test_spec_paths = dependent_target == target
|
80
|
+
dependent_target.framework_paths(include_test_spec_paths)
|
81
|
+
end
|
82
|
+
input_paths = []
|
83
|
+
output_paths = []
|
84
|
+
unless framework_paths.empty?
|
85
|
+
input_paths = [script_path, *framework_paths.flat_map { |fw| [fw[:input_path], fw[:dsym_input_path]] }.compact]
|
86
|
+
output_paths = framework_paths.flat_map { |fw| [fw[:output_path], fw[:dsym_output_path]] }.compact
|
87
|
+
end
|
88
|
+
UserProjectIntegrator::TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
|
89
|
+
UserProjectIntegrator::TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths, output_paths)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [String] the message that should be displayed for the target
|
93
|
+
# integration.
|
94
|
+
#
|
95
|
+
def integration_message
|
96
|
+
"Integrating target `#{target.name}`"
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param [Array<Specification] specs
|
100
|
+
# the specs to return script phrases from.
|
101
|
+
#
|
102
|
+
# @return [Array<Hash<Symbol=>String>] an array of all combined script phases from the specs.
|
103
|
+
#
|
104
|
+
def script_phases_for_specs(specs)
|
105
|
+
specs.flat_map { |spec| spec.consumer(target.platform).script_phases }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
module Pod
|
2
|
+
class DyInstaller
|
3
|
+
class Xcode
|
4
|
+
class PodsProjectGenerator
|
5
|
+
# Controller class responsible of creating and configuring the static
|
6
|
+
# library target in Pods project. It also creates the support file needed
|
7
|
+
# by the target.
|
8
|
+
#
|
9
|
+
class TargetInstaller
|
10
|
+
# @return [Sandbox] sandbox
|
11
|
+
# The sandbox where the support files should be generated.
|
12
|
+
#
|
13
|
+
attr_reader :sandbox
|
14
|
+
|
15
|
+
# @return [Target] target
|
16
|
+
# The library whose target needs to be generated.
|
17
|
+
#
|
18
|
+
attr_reader :target
|
19
|
+
|
20
|
+
# Initialize a new instance
|
21
|
+
#
|
22
|
+
# @param [Sandbox] sandbox @see sandbox
|
23
|
+
# @param [Target] target @see target
|
24
|
+
#
|
25
|
+
def initialize(sandbox, target)
|
26
|
+
@sandbox = sandbox
|
27
|
+
@target = target
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
#-----------------------------------------------------------------------#
|
33
|
+
|
34
|
+
# @!group Installation steps
|
35
|
+
|
36
|
+
# Adds the target for the library to the Pods project with the
|
37
|
+
# appropriate build configurations.
|
38
|
+
#
|
39
|
+
# @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig.
|
40
|
+
#
|
41
|
+
# @return [void]
|
42
|
+
#
|
43
|
+
def add_target
|
44
|
+
product_type = target.product_type
|
45
|
+
name = target.label
|
46
|
+
platform = target.platform.name
|
47
|
+
language = target.uses_swift? ? :swift : :objc
|
48
|
+
@native_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
|
49
|
+
|
50
|
+
product_name = target.product_name
|
51
|
+
product = @native_target.product_reference
|
52
|
+
product.name = product_name
|
53
|
+
|
54
|
+
target.user_build_configurations.each do |bc_name, type|
|
55
|
+
@native_target.add_build_configuration(bc_name, type)
|
56
|
+
end
|
57
|
+
|
58
|
+
@native_target.build_configurations.each do |configuration|
|
59
|
+
configuration.build_settings.merge!(custom_build_settings)
|
60
|
+
end
|
61
|
+
|
62
|
+
target.native_target = @native_target
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [String] The deployment target.
|
66
|
+
#
|
67
|
+
def deployment_target
|
68
|
+
target.platform.deployment_target.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the customized build settings which are overridden in the build
|
72
|
+
# settings of the user target.
|
73
|
+
#
|
74
|
+
# @return [Hash{String => String}]
|
75
|
+
#
|
76
|
+
def custom_build_settings
|
77
|
+
settings = {}
|
78
|
+
|
79
|
+
unless target.archs.empty?
|
80
|
+
settings['ARCHS'] = target.archs
|
81
|
+
end
|
82
|
+
|
83
|
+
if target.requires_frameworks?
|
84
|
+
if target.static_framework?
|
85
|
+
settings['MACH_O_TYPE'] = 'staticlib'
|
86
|
+
end
|
87
|
+
else
|
88
|
+
settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
|
89
|
+
end
|
90
|
+
|
91
|
+
settings
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param [Generator] generator
|
95
|
+
# the generator to use for generating the content.
|
96
|
+
#
|
97
|
+
# @param [Pathname] path
|
98
|
+
# the pathname to save the content into.
|
99
|
+
#
|
100
|
+
# Saves the content the provided path unless the path exists and the contents are exactly the same.
|
101
|
+
#
|
102
|
+
# @return [Void]
|
103
|
+
#
|
104
|
+
def update_changed_file(generator, path)
|
105
|
+
path.dirname.mkpath
|
106
|
+
if path.exist?
|
107
|
+
generator.save_as(support_files_temp_dir)
|
108
|
+
unless FileUtils.identical?(support_files_temp_dir, path)
|
109
|
+
FileUtils.mv(support_files_temp_dir, path)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
generator.save_as(path)
|
113
|
+
end
|
114
|
+
clean_support_files_temp_dir if support_files_temp_dir.exist?
|
115
|
+
end
|
116
|
+
|
117
|
+
# Creates the directory where to store the support files of the target.
|
118
|
+
#
|
119
|
+
def create_support_files_dir
|
120
|
+
target.support_files_dir.mkpath
|
121
|
+
end
|
122
|
+
|
123
|
+
# Remove temp file whose store .prefix/config/dummy file.
|
124
|
+
#
|
125
|
+
def clean_support_files_temp_dir
|
126
|
+
support_files_temp_dir.rmtree
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return [String] The temp file path to store temporary files.
|
130
|
+
#
|
131
|
+
def support_files_temp_dir
|
132
|
+
sandbox.target_support_files_dir('generated_files_tmp')
|
133
|
+
end
|
134
|
+
|
135
|
+
# Creates the Info.plist file which sets public framework attributes
|
136
|
+
#
|
137
|
+
# @param [Pathname] path
|
138
|
+
# the path to save the generated Info.plist file.
|
139
|
+
#
|
140
|
+
# @param [PBXNativeTarget] native_target
|
141
|
+
# the native target to link the generated Info.plist file into.
|
142
|
+
#
|
143
|
+
# @param [Version] version
|
144
|
+
# the version to use for when generating this Info.plist file.
|
145
|
+
#
|
146
|
+
# @param [Platform] platform
|
147
|
+
# the platform to use for when generating this Info.plist file.
|
148
|
+
#
|
149
|
+
# @param [Symbol] bundle_package_type
|
150
|
+
# the CFBundlePackageType of the target this Info.plist file is for.
|
151
|
+
#
|
152
|
+
# @return [void]
|
153
|
+
#
|
154
|
+
def create_info_plist_file(path, native_target, version, platform, bundle_package_type = :fmwk)
|
155
|
+
UI.message "- Generating Info.plist file at #{UI.path(path)}" do
|
156
|
+
generator = Generator::InfoPlistFile.new(version, platform, bundle_package_type)
|
157
|
+
update_changed_file(generator, path)
|
158
|
+
add_file_to_support_group(path)
|
159
|
+
|
160
|
+
native_target.build_configurations.each do |c|
|
161
|
+
relative_path = path.relative_path_from(sandbox.root)
|
162
|
+
c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Creates the module map file which ensures that the umbrella header is
|
168
|
+
# recognized with a customized path
|
169
|
+
#
|
170
|
+
# @return [void]
|
171
|
+
#
|
172
|
+
def create_module_map
|
173
|
+
path = target.module_map_path
|
174
|
+
UI.message "- Generating module map file at #{UI.path(path)}" do
|
175
|
+
generator = Generator::ModuleMap.new(target)
|
176
|
+
yield generator if block_given?
|
177
|
+
update_changed_file(generator, path)
|
178
|
+
add_file_to_support_group(path)
|
179
|
+
|
180
|
+
native_target.build_configurations.each do |c|
|
181
|
+
relative_path = path.relative_path_from(sandbox.root)
|
182
|
+
c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Generates a header which ensures that all header files are exported
|
188
|
+
# in the module map
|
189
|
+
#
|
190
|
+
# @yield_param [Generator::UmbrellaHeader]
|
191
|
+
# yielded once to configure the imports
|
192
|
+
#
|
193
|
+
def create_umbrella_header
|
194
|
+
path = target.umbrella_header_path
|
195
|
+
UI.message "- Generating umbrella header at #{UI.path(path)}" do
|
196
|
+
generator = Generator::UmbrellaHeader.new(target)
|
197
|
+
yield generator if block_given?
|
198
|
+
update_changed_file(generator, path)
|
199
|
+
|
200
|
+
# Add the file to the support group and the native target,
|
201
|
+
# so it will been added to the header build phase
|
202
|
+
file_ref = add_file_to_support_group(path)
|
203
|
+
native_target.add_file_references([file_ref])
|
204
|
+
|
205
|
+
acl = target.requires_frameworks? ? 'Public' : 'Project'
|
206
|
+
build_file = native_target.headers_build_phase.build_file(file_ref)
|
207
|
+
build_file.settings ||= {}
|
208
|
+
build_file.settings['ATTRIBUTES'] = [acl]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Generates a dummy source file for each target so libraries that contain
|
213
|
+
# only categories build.
|
214
|
+
#
|
215
|
+
# @return [void]
|
216
|
+
#
|
217
|
+
def create_dummy_source
|
218
|
+
path = target.dummy_source_path
|
219
|
+
generator = Generator::DummySource.new(target.label)
|
220
|
+
update_changed_file(generator, path)
|
221
|
+
file_reference = add_file_to_support_group(path)
|
222
|
+
native_target.source_build_phase.add_file_reference(file_reference)
|
223
|
+
end
|
224
|
+
|
225
|
+
# @return [PBXNativeTarget] the target generated by the installation
|
226
|
+
# process.
|
227
|
+
#
|
228
|
+
# @note Generated by the {#add_target} step.
|
229
|
+
#
|
230
|
+
attr_reader :native_target
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
#-----------------------------------------------------------------------#
|
235
|
+
|
236
|
+
# @!group Private helpers.
|
237
|
+
|
238
|
+
# @return [Project] the Pods project of the sandbox.
|
239
|
+
#
|
240
|
+
def project
|
241
|
+
sandbox.project
|
242
|
+
end
|
243
|
+
|
244
|
+
# @return [PBXGroup] the group where the file references to the support
|
245
|
+
# files should be stored.
|
246
|
+
#
|
247
|
+
attr_reader :support_files_group
|
248
|
+
|
249
|
+
# Adds a reference to the given file in the support group of this target.
|
250
|
+
#
|
251
|
+
# @param [Pathname] path
|
252
|
+
# The path of the file to which the reference should be added.
|
253
|
+
#
|
254
|
+
# @return [PBXFileReference] the file reference of the added file.
|
255
|
+
#
|
256
|
+
def add_file_to_support_group(path)
|
257
|
+
support_files_group.new_file(path)
|
258
|
+
end
|
259
|
+
|
260
|
+
#-----------------------------------------------------------------------#
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Pod
|
2
|
+
class DyInstaller
|
3
|
+
class Xcode
|
4
|
+
# The {Xcode::TargetValidator} ensures that the pod and aggregate target
|
5
|
+
# configuration is valid for installation.
|
6
|
+
#
|
7
|
+
class TargetValidator
|
8
|
+
# @return [Array<AggregateTarget>] The aggregate targets that should be
|
9
|
+
# validated.
|
10
|
+
#
|
11
|
+
attr_reader :aggregate_targets
|
12
|
+
|
13
|
+
# @return [Array<PodTarget>] The pod targets that should be validated.
|
14
|
+
#
|
15
|
+
attr_reader :pod_targets
|
16
|
+
|
17
|
+
# Create a new TargetValidator with aggregate and pod targets to
|
18
|
+
# validate.
|
19
|
+
#
|
20
|
+
# @param [Array<AggregateTarget>] aggregate_targets
|
21
|
+
# The aggregate targets to validate.
|
22
|
+
#
|
23
|
+
# @param [Array<PodTarget>] pod_targets
|
24
|
+
# The pod targets to validate.
|
25
|
+
#
|
26
|
+
def initialize(aggregate_targets, pod_targets)
|
27
|
+
@aggregate_targets = aggregate_targets
|
28
|
+
@pod_targets = pod_targets
|
29
|
+
end
|
30
|
+
|
31
|
+
# Perform the validation steps for the provided aggregate and pod
|
32
|
+
# targets.
|
33
|
+
#
|
34
|
+
def validate!
|
35
|
+
verify_no_duplicate_framework_and_library_names
|
36
|
+
verify_no_static_framework_transitive_dependencies
|
37
|
+
verify_no_pods_used_with_multiple_swift_versions
|
38
|
+
verify_swift_pods_have_module_dependencies
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def verify_no_duplicate_framework_and_library_names
|
44
|
+
aggregate_targets.each do |aggregate_target|
|
45
|
+
aggregate_target.user_build_configurations.keys.each do |config|
|
46
|
+
pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
|
47
|
+
file_accessors = pod_targets.flat_map(&:file_accessors)
|
48
|
+
|
49
|
+
frameworks = file_accessors.flat_map(&:vendored_frameworks).uniq.map(&:basename)
|
50
|
+
frameworks += pod_targets.select { |pt| pt.should_build? && pt.requires_frameworks? }.map(&:product_module_name).uniq
|
51
|
+
verify_no_duplicate_names(frameworks, aggregate_target.label, 'frameworks')
|
52
|
+
|
53
|
+
libraries = file_accessors.flat_map(&:vendored_libraries).uniq.map(&:basename)
|
54
|
+
libraries += pod_targets.select { |pt| pt.should_build? && !pt.requires_frameworks? }.map(&:product_name)
|
55
|
+
verify_no_duplicate_names(libraries, aggregate_target.label, 'libraries')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def verify_no_duplicate_names(names, label, type)
|
61
|
+
duplicates = names.map { |n| n.to_s.downcase }.group_by { |f| f }.select { |_, v| v.size > 1 }.keys
|
62
|
+
|
63
|
+
unless duplicates.empty?
|
64
|
+
raise Informative, "The '#{label}' target has " \
|
65
|
+
"#{type} with conflicting names: #{duplicates.to_sentence}."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def verify_no_static_framework_transitive_dependencies
|
70
|
+
aggregate_targets.each do |aggregate_target|
|
71
|
+
next unless aggregate_target.requires_frameworks?
|
72
|
+
|
73
|
+
aggregate_target.user_build_configurations.keys.each do |config|
|
74
|
+
dynamic_pod_targets = aggregate_target.pod_targets_for_build_configuration(config).reject(&:static_framework?)
|
75
|
+
|
76
|
+
dependencies = dynamic_pod_targets.select(&:should_build?).flat_map(&:dependencies)
|
77
|
+
depended_upon_targets = dynamic_pod_targets.select { |t| dependencies.include?(t.pod_name) && !t.should_build? }
|
78
|
+
|
79
|
+
static_libs = depended_upon_targets.flat_map(&:file_accessors).flat_map(&:vendored_static_artifacts)
|
80
|
+
unless static_libs.empty?
|
81
|
+
raise Informative, "The '#{aggregate_target.label}' target has " \
|
82
|
+
"transitive dependencies that include static binaries: (#{static_libs.to_sentence})"
|
83
|
+
end
|
84
|
+
|
85
|
+
static_framework_deps = dynamic_pod_targets.select(&:should_build?).flat_map(&:recursive_dependent_targets).select(&:static_framework?)
|
86
|
+
unless static_framework_deps.empty?
|
87
|
+
raise Informative, "The '#{aggregate_target.label}' target has " \
|
88
|
+
"transitive dependencies that include static frameworks: (#{static_framework_deps.flat_map(&:name).to_sentence})"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def verify_no_pods_used_with_multiple_swift_versions
|
95
|
+
error_message_for_target = lambda do |target|
|
96
|
+
"#{target.name} (Swift #{target.swift_version})"
|
97
|
+
end
|
98
|
+
swift_pod_targets = pod_targets.select(&:uses_swift?)
|
99
|
+
error_messages = swift_pod_targets.map do |pod_target|
|
100
|
+
next unless pod_target.spec_swift_version.nil?
|
101
|
+
swift_target_definitions = pod_target.target_definitions.reject { |target| target.swift_version.blank? }
|
102
|
+
next if swift_target_definitions.empty? || swift_target_definitions.uniq(&:swift_version).count == 1
|
103
|
+
target_errors = swift_target_definitions.map(&error_message_for_target).join(', ')
|
104
|
+
"- #{pod_target.name} required by #{target_errors}"
|
105
|
+
end.compact
|
106
|
+
|
107
|
+
unless error_messages.empty?
|
108
|
+
raise Informative, 'The following pods are integrated into targets ' \
|
109
|
+
"that do not have the same Swift version:\n\n#{error_messages.join("\n")}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def verify_swift_pods_have_module_dependencies
|
114
|
+
error_messages = []
|
115
|
+
pod_targets.each do |pod_target|
|
116
|
+
next unless pod_target.uses_swift?
|
117
|
+
|
118
|
+
non_module_dependencies = []
|
119
|
+
pod_target.dependent_targets.each do |dependent_target|
|
120
|
+
next if !dependent_target.should_build? || dependent_target.defines_module?
|
121
|
+
non_module_dependencies << dependent_target.name
|
122
|
+
end
|
123
|
+
|
124
|
+
next if non_module_dependencies.empty?
|
125
|
+
|
126
|
+
error_messages << "The Swift pod `#{pod_target.name}` depends upon #{non_module_dependencies.map { |d| "`#{d}`" }.to_sentence}, " \
|
127
|
+
'which do not define modules. ' \
|
128
|
+
'To opt into those targets generating module maps '\
|
129
|
+
'(which is necessary to import them from Swift when building as static libraries), ' \
|
130
|
+
'you may set `use_modular_headers!` globally in your Podfile, '\
|
131
|
+
'or specify `:modular_headers => true` for particular dependencies.'
|
132
|
+
end
|
133
|
+
return if error_messages.empty?
|
134
|
+
|
135
|
+
raise Informative, 'The following Swift pods cannot yet be integrated '\
|
136
|
+
"as static libraries:\n\n#{error_messages.join("\n\n")}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|