cocoapods-project-gen 0.1.0 → 0.2.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/README.md +62 -23
- data/bin/xcframework +11 -0
- data/lib/cocoapods-project-gen/command/command.rb +25 -0
- data/lib/cocoapods-project-gen/command/gen.rb +120 -0
- data/lib/cocoapods-project-gen/gem_version.rb +1 -1
- data/lib/cocoapods-project-gen/gen/build/headers_store.rb +104 -0
- data/lib/cocoapods-project-gen/gen/build/xcode_build.rb +47 -0
- data/lib/cocoapods-project-gen/gen/constants.rb +71 -0
- data/lib/cocoapods-project-gen/gen/pod/pod_copy_cleaner.rb +50 -0
- data/lib/cocoapods-project-gen/gen/pod/project_gen_helper.rb +341 -0
- data/lib/cocoapods-project-gen/gen/pod/swift_module_helper.rb +134 -0
- data/lib/cocoapods-project-gen/gen/product/product_helper.rb +93 -0
- data/lib/cocoapods-project-gen/gen/product.rb +165 -0
- data/lib/cocoapods-project-gen/gen/project_builder.rb +144 -0
- data/lib/cocoapods-project-gen/gen/project_gen.rb +179 -128
- data/lib/cocoapods-project-gen/gen/results.rb +143 -0
- data/lib/cocoapods-project-gen/gen/utils.rb +35 -0
- data/lib/cocoapods-project-gen/gen/xcframework_gen.rb +44 -0
- data/lib/cocoapods-project-gen.rb +14 -7
- metadata +21 -6
- data/lib/cocoapods-project-gen/gen/swift_module_helper.rb +0 -52
@@ -0,0 +1,341 @@
|
|
1
|
+
module ProjectGen
|
2
|
+
module Helper
|
3
|
+
include Pod
|
4
|
+
|
5
|
+
def self.app_target_name(platform)
|
6
|
+
"App-#{platform.string_name}"
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# The specifications matching the specified pod name
|
12
|
+
#
|
13
|
+
# @param [String] pod_name the name of the pod
|
14
|
+
#
|
15
|
+
# @return [Hash{Specification => Array<Taget>}] the specifications grouped by platform
|
16
|
+
#
|
17
|
+
def specs_for_pods
|
18
|
+
@installer.pod_targets.each_with_object({}) do |pod_target, hash|
|
19
|
+
hash[pod_target.root_spec] ||= []
|
20
|
+
hash[pod_target.root_spec] << pod_target
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_gen_environment
|
25
|
+
project_gen_dir.rmtree if project_gen_dir.exist?
|
26
|
+
project_gen_dir.mkpath
|
27
|
+
@original_config = Pod::Config.instance.clone
|
28
|
+
config.installation_root = project_gen_dir
|
29
|
+
config.silent = !config.verbose
|
30
|
+
end
|
31
|
+
|
32
|
+
# !@group Lint steps
|
33
|
+
def perform_linting
|
34
|
+
podspecs.each do |podspec|
|
35
|
+
linter = Pod::Specification::Linter.new(podspec)
|
36
|
+
linter.lint
|
37
|
+
@results.results.concat(linter.results.to_a)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def podspecs
|
42
|
+
return @podspecs if defined? @podspecs
|
43
|
+
|
44
|
+
additional_podspec_pods = external_podspecs ? Dir.glob(external_podspecs) : []
|
45
|
+
additional_path_pods = include_podspecs ? Dir.glob(include_podspecs) : []
|
46
|
+
@podspecs = (additional_podspec_pods + additional_path_pods).uniq.each_with_object({}) do |path, hash|
|
47
|
+
spec = Pod::Specification.from_file(path)
|
48
|
+
old_spec = hash[spec.name]
|
49
|
+
if old_spec && use_latest
|
50
|
+
hash[spec.name] = [old_spec, spec].max { |old, new| old.version <=> new.version }
|
51
|
+
else
|
52
|
+
hash[spec.name] = spec
|
53
|
+
end
|
54
|
+
end.values
|
55
|
+
end
|
56
|
+
|
57
|
+
def include_specifications
|
58
|
+
(include_podspecs ? Dir.glob(include_podspecs) : []).map do |path|
|
59
|
+
Pod::Specification.from_file(path)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a list of platforms to lint for a given Specification
|
64
|
+
#
|
65
|
+
# @return [Array<Platform>] platforms to lint for the given specification
|
66
|
+
#
|
67
|
+
def determine_platforms
|
68
|
+
return @determine_platforms if defined?(@determine_platforms) && @determine_platforms == @platform
|
69
|
+
|
70
|
+
platforms = podspecs.flat_map(&:available_platforms).uniq
|
71
|
+
platforms = platforms.map do |platform|
|
72
|
+
default = Pod::Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform.name]
|
73
|
+
deployment_target = podspecs.flat_map do |library_spec|
|
74
|
+
subspecs = determine_subspecs[library_spec]
|
75
|
+
if subspecs && !subspecs.empty?
|
76
|
+
subspecs.map { |s| Pod::Version.new(s.deployment_target(platform.name) || default) }
|
77
|
+
else
|
78
|
+
Pod::Version.new(library_spec.deployment_target(platform.name) || default)
|
79
|
+
end
|
80
|
+
end.max
|
81
|
+
if platform.name == :ios && use_frameworks
|
82
|
+
minimum = Pod::Version.new('8.0')
|
83
|
+
deployment_target = [deployment_target, minimum].max
|
84
|
+
end
|
85
|
+
Pod::Platform.new(platform.name, deployment_target)
|
86
|
+
end.uniq
|
87
|
+
|
88
|
+
unless @platforms.empty?
|
89
|
+
# Validate that the platforms specified are actually supported by the spec
|
90
|
+
platforms = @platforms.map do |platform|
|
91
|
+
matching_platform = platforms.find { |p| p.name == platform.name }
|
92
|
+
unless matching_platform
|
93
|
+
raise Informative, "Platform `#{platform}` is not supported by specification `#{spec}`."
|
94
|
+
end
|
95
|
+
|
96
|
+
matching_platform
|
97
|
+
end.uniq
|
98
|
+
end
|
99
|
+
@platform = platforms
|
100
|
+
@determine_platforms = platforms
|
101
|
+
end
|
102
|
+
|
103
|
+
def determine_subspecs
|
104
|
+
return @determine_subspecs if defined? @determine_subspecs
|
105
|
+
return {} if @only_subspecs.nil?
|
106
|
+
|
107
|
+
subspecs = @only_subspecs.dup
|
108
|
+
ha = podspecs.each_with_object({}) do |podspec, hash|
|
109
|
+
return hash if subspecs.empty?
|
110
|
+
|
111
|
+
base_name = podspec.name
|
112
|
+
s_s = []
|
113
|
+
subspecs.delete_if { |ss| s_s << podspec.subspec_by_name(ss, false) if ss.split('/').shift == base_name }
|
114
|
+
s_s.compact!
|
115
|
+
hash[podspec] = s_s unless s_s.empty?
|
116
|
+
end
|
117
|
+
subspecs.each { |s| results.warning('subspecs', "#{s} should use NAME/NAME.") }
|
118
|
+
@determine_subspecs = ha
|
119
|
+
end
|
120
|
+
|
121
|
+
def validate_vendored_dynamic_frameworks
|
122
|
+
platform = determine_platforms.find { |pl| pl.name == :ios }
|
123
|
+
targets = relative_pod_targets_from_platfrom(platform)
|
124
|
+
targets.flat_map(&:file_accessors).each do |file_accessor|
|
125
|
+
deployment_target = platform.deployment_target
|
126
|
+
dynamic_frameworks = file_accessor.vendored_dynamic_frameworks
|
127
|
+
dynamic_libraries = file_accessor.vendored_dynamic_libraries
|
128
|
+
if (dynamic_frameworks.count.positive? || dynamic_libraries.count.positive?) && platform.name == :ios &&
|
129
|
+
(deployment_target.nil? || deployment_target.major < 8)
|
130
|
+
error('dynamic', 'Dynamic frameworks and libraries are only supported on iOS 8.0 and onwards.')
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def create_app_project
|
136
|
+
p_path = project_gen_dir + 'App.xcodeproj'
|
137
|
+
app_project = if p_path.exist?
|
138
|
+
Xcodeproj::Project.open(p_path)
|
139
|
+
else
|
140
|
+
Xcodeproj::Project.new(File.join(project_gen_dir, 'App.xcodeproj'))
|
141
|
+
end
|
142
|
+
determine_platforms.each do |platform|
|
143
|
+
app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, platform.name,
|
144
|
+
platform.deployment_target.to_s, Helper.app_target_name(platform))
|
145
|
+
sandbox = Pod::Sandbox.new(config.sandbox_root)
|
146
|
+
info_plist_path = app_project.path.dirname.+("App/#{Helper.app_target_name(platform)}-Info.plist")
|
147
|
+
Pod::Installer::Xcode::PodsProjectGenerator::TargetInstallerHelper.create_info_plist_file_with_sandbox(sandbox,
|
148
|
+
info_plist_path,
|
149
|
+
app_target,
|
150
|
+
'1.0.0',
|
151
|
+
Pod::Platform.new(platform.name),
|
152
|
+
:appl,
|
153
|
+
build_setting_value: "$(SRCROOT)/App/#{Helper.app_target_name(platform)}-Info.plist")
|
154
|
+
Pod::Generator::AppTargetHelper.add_swift_version(app_target, derived_swift_version)
|
155
|
+
app_target.build_configurations.each do |config|
|
156
|
+
# Lint will fail if a AppIcon is set but no image is found with such name
|
157
|
+
# Happens only with Static Frameworks enabled but shouldn't be set anyway
|
158
|
+
config.build_settings.delete('ASSETCATALOG_COMPILER_APPICON_NAME')
|
159
|
+
# Ensure this is set generally but we have seen an issue with ODRs:
|
160
|
+
# see: https://github.com/CocoaPods/CocoaPods/issues/10933
|
161
|
+
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
app_project.save
|
165
|
+
app_project.recreate_user_schemes
|
166
|
+
end
|
167
|
+
|
168
|
+
# It creates a podfile in memory and builds a library containing the pod
|
169
|
+
# for all available platforms with xcodebuild.
|
170
|
+
#
|
171
|
+
def install_pod
|
172
|
+
%i[validate_targets generate_pods_project integrate_user_project
|
173
|
+
perform_post_install_actions].each { |m| @installer.send(m) }
|
174
|
+
configure_pod_targets(@installer.target_installation_results)
|
175
|
+
|
176
|
+
determine_platforms.each do |platform|
|
177
|
+
validate_dynamic_framework_support(platform.name, @installer.aggregate_targets, platform.deployment_target.to_s)
|
178
|
+
end
|
179
|
+
@installer.pods_project.save
|
180
|
+
end
|
181
|
+
|
182
|
+
# @param [Array<Hash{String, TargetInstallationResult}>] target_installation_results
|
183
|
+
# The installation results to configure
|
184
|
+
#
|
185
|
+
def configure_pod_targets(target_installation_results)
|
186
|
+
target_installation_results.first.values.each do |pod_target_installation_result|
|
187
|
+
pod_target = pod_target_installation_result.target
|
188
|
+
native_target = pod_target_installation_result.native_target
|
189
|
+
native_target.build_configuration_list.build_configurations.each do |build_configuration|
|
190
|
+
(build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
|
191
|
+
next unless pod_target.uses_swift?
|
192
|
+
|
193
|
+
# The Swift version for the target being validated can be overridden by `--swift-version` or the
|
194
|
+
# `.swift-version` file so we always use the derived Swift version.
|
195
|
+
#
|
196
|
+
# For dependencies, if the derived Swift version is supported then it is the one used. Otherwise, the Swift
|
197
|
+
# version for dependencies is inferred by the target that is integrating them.
|
198
|
+
swift_version = pod_target.spec_swift_versions.map(&:to_s).find do |v|
|
199
|
+
v == derived_swift_version
|
200
|
+
end || pod_target.swift_version
|
201
|
+
build_configuration.build_settings['SWIFT_VERSION'] = swift_version
|
202
|
+
end
|
203
|
+
pod_target_installation_result.test_specs_by_native_target.each do |test_native_target, test_spec|
|
204
|
+
next unless pod_target.uses_swift_for_spec?(test_spec)
|
205
|
+
|
206
|
+
test_native_target.build_configuration_list.build_configurations.each do |build_configuration|
|
207
|
+
swift_version = pod_target == validation_pod_target ? derived_swift_version : pod_target.swift_version
|
208
|
+
build_configuration.build_settings['SWIFT_VERSION'] = swift_version
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Produces an error of dynamic frameworks were requested but are not supported by the deployment target
|
215
|
+
#
|
216
|
+
# @param [Array<AggregateTarget>] aggregate_targets
|
217
|
+
# The aggregate targets installed by the installer
|
218
|
+
#
|
219
|
+
# @param [String,Version] deployment_target
|
220
|
+
# The deployment target of the installation
|
221
|
+
#
|
222
|
+
def validate_dynamic_framework_support(platform_name, aggregate_targets, deployment_target)
|
223
|
+
return unless platform_name == :ios
|
224
|
+
return unless deployment_target.nil? || Pod::Version.new(deployment_target).major < 8
|
225
|
+
|
226
|
+
aggregate_targets.each do |target|
|
227
|
+
next unless target.pod_targets.any?(&:uses_swift?)
|
228
|
+
|
229
|
+
uses_xctest = target.spec_consumers.any? do |c|
|
230
|
+
(c.frameworks + c.weak_frameworks).include? 'XCTest'
|
231
|
+
end
|
232
|
+
unless uses_xctest
|
233
|
+
error('swift',
|
234
|
+
'Swift support uses dynamic frameworks and is therefore only supported on iOS > 8.')
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# @return [Boolean]
|
240
|
+
#
|
241
|
+
def validated?
|
242
|
+
results.result_type != :error && (results.result_type != :warning || allow_warnings)
|
243
|
+
end
|
244
|
+
|
245
|
+
# Returns the pod target for the pod being relatived. Installation must have occurred before this can be invoked.
|
246
|
+
#
|
247
|
+
def relative_pod_targets_from_platfrom(platform)
|
248
|
+
@installer.pod_targets.select { |pt| pt.platform.name == platform.name }
|
249
|
+
end
|
250
|
+
|
251
|
+
# @param [String] platform_name
|
252
|
+
# the name of the platform, which should be declared
|
253
|
+
# in the Podfile.
|
254
|
+
#
|
255
|
+
# @param [String] deployment_target
|
256
|
+
# the deployment target, which should be declared in
|
257
|
+
# the Podfile.
|
258
|
+
#
|
259
|
+
# @param [Boolean] use_frameworks
|
260
|
+
# whether frameworks should be used for the installation
|
261
|
+
#
|
262
|
+
# @param [Array<String>] test_spec_names
|
263
|
+
# the test spec names to include in the podfile.
|
264
|
+
#
|
265
|
+
# @return [Podfile] a podfile that requires the specification on the
|
266
|
+
# current platform.
|
267
|
+
#
|
268
|
+
# @note The generated podfile takes into account whether the linter is
|
269
|
+
# in local mode.
|
270
|
+
#
|
271
|
+
def podfile_from_spec(use_frameworks = true, use_modular_headers = false, use_static_frameworks = false)
|
272
|
+
urls = source_urls
|
273
|
+
all_podspec_pods = podspecs
|
274
|
+
platforms = determine_platforms
|
275
|
+
d_subspecs = determine_subspecs
|
276
|
+
Pod::Podfile.new do
|
277
|
+
install! 'cocoapods', deterministic_uuids: false, warn_for_unused_master_specs_repo: false
|
278
|
+
# By default inhibit warnings for all pods, except the one being validated.
|
279
|
+
inhibit_all_warnings!
|
280
|
+
urls.each { |u| source(u) }
|
281
|
+
platforms.each do |platform|
|
282
|
+
app_name = ProjectGen::Helper.app_target_name(platform)
|
283
|
+
target(app_name) do
|
284
|
+
if use_static_frameworks
|
285
|
+
use_frameworks!(linkage: :static)
|
286
|
+
else
|
287
|
+
use_frameworks!(use_frameworks)
|
288
|
+
end
|
289
|
+
use_modular_headers! if use_modular_headers
|
290
|
+
platform(platform.name, platform.deployment_target.to_s)
|
291
|
+
|
292
|
+
all_podspec_pods.each do |podspec|
|
293
|
+
subspecs = d_subspecs[podspec]
|
294
|
+
if subspecs && !subspecs.empty?
|
295
|
+
subspecs.each do |s|
|
296
|
+
if s.supported_on_platform?(platform)
|
297
|
+
pod s.name, podspec: s.defined_in_file.to_s,
|
298
|
+
inhibit_warnings: false
|
299
|
+
end
|
300
|
+
end
|
301
|
+
elsif podspec.supported_on_platform?(platform)
|
302
|
+
pod podspec.name, podspec: podspec.defined_in_file.to_s,
|
303
|
+
inhibit_warnings: false
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def add_app_project_import
|
312
|
+
app_project = Xcodeproj::Project.open(project_gen_dir + 'App.xcodeproj')
|
313
|
+
app_project.targets.each do |app_target|
|
314
|
+
platform = determine_platforms.find { |pl| pl.name == app_target.platform_name }
|
315
|
+
pod_targets = relative_pod_targets_from_platfrom(platform)
|
316
|
+
pod_targets.each do |pod_target|
|
317
|
+
Pod::Generator::AppTargetHelper.add_app_project_import(app_project, app_target, pod_target, platform.name,
|
318
|
+
Helper.app_target_name(platform))
|
319
|
+
end
|
320
|
+
Pod::Generator::AppTargetHelper.add_xctest_search_paths(app_target) if pod_targets.any? do |pt|
|
321
|
+
pt.spec_consumers.any? do |c|
|
322
|
+
c.frameworks.include?('XCTest') || c.weak_frameworks.include?('XCTest')
|
323
|
+
end
|
324
|
+
end
|
325
|
+
Pod::Generator::AppTargetHelper.add_empty_swift_file(app_project, app_target) if pod_targets.any?(&:uses_swift?)
|
326
|
+
app_project.save
|
327
|
+
Xcodeproj::XCScheme.share_scheme(app_project.path, Helper.app_target_name(platform))
|
328
|
+
pod_targets.each do |pod_target|
|
329
|
+
if shares_pod_target_xcscheme?(pod_target)
|
330
|
+
Xcodeproj::XCScheme.share_scheme(@installer.pods_project.path,
|
331
|
+
pod_target.label)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
def shares_pod_target_xcscheme?(pod_target)
|
338
|
+
Pathname.new(@installer.pods_project.path + pod_target.label).exist?
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module ProjectGen
|
2
|
+
module SwiftModule
|
3
|
+
# @return [String] the SWIFT_VERSION within the .swift-version file or nil.
|
4
|
+
#
|
5
|
+
def dot_swift_version(podspec)
|
6
|
+
file = podspec.defined_in_file
|
7
|
+
swift_version_path = file.dirname + '.swift-version'
|
8
|
+
return unless swift_version_path.exist?
|
9
|
+
|
10
|
+
swift_version_path.read.strip
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [String] The derived Swift version to use for validation. The order of precedence is as follows:
|
14
|
+
# - The `--swift-version` parameter is always checked first and honored if passed.
|
15
|
+
# - The `swift_versions` DSL attribute within the podspec, in which case the latest version is always chosen.
|
16
|
+
# - The Swift version within the `.swift-version` file if present.
|
17
|
+
# - If none of the above are set then the `#DEFAULT_SWIFT_VERSION` is used.
|
18
|
+
#
|
19
|
+
def derived_swift_version
|
20
|
+
@derived_swift_version ||= if swift_version
|
21
|
+
swift_version
|
22
|
+
else
|
23
|
+
version = podspecs.map do |podspec|
|
24
|
+
podspec.swift_versions.max || dot_swift_version(podspec)
|
25
|
+
end.compact.max
|
26
|
+
if version
|
27
|
+
version.to_s
|
28
|
+
else
|
29
|
+
Constants::DEFAULT_SWIFT_VERSION
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Performs validation for the version of Swift used during validation.
|
35
|
+
#
|
36
|
+
# An error will be displayed if the user has provided a `swift_versions` attribute within the podspec but is also
|
37
|
+
# using either `--swift-version` parameter or a `.swift-version` file with a Swift version that is not declared
|
38
|
+
# within the attribute.
|
39
|
+
#
|
40
|
+
# The user will be warned that the default version of Swift was used if the following things are true:
|
41
|
+
# - The project uses Swift at all
|
42
|
+
# - The user did not supply a Swift version via a parameter
|
43
|
+
# - There is no `swift_versions` attribute set within the specification
|
44
|
+
# - There is no `.swift-version` file present either.
|
45
|
+
#
|
46
|
+
def validate_swift_version
|
47
|
+
|
48
|
+
specs_for_pods.each_pair do |spec, pod_targets|
|
49
|
+
next unless pod_targets.any?(&:uses_swift?)
|
50
|
+
|
51
|
+
spec_swift_versions = spec.swift_versions.map(&:to_s)
|
52
|
+
|
53
|
+
dot_swift = dot_swift_version(spec)
|
54
|
+
unless spec_swift_versions.empty?
|
55
|
+
message = nil
|
56
|
+
if !dot_swift.nil? && !spec_swift_versions.include?(dot_swift)
|
57
|
+
message = "Specification `#{spec.name}` specifies inconsistent `swift_versions` (#{spec_swift_versions.map do |s|
|
58
|
+
"`#{s}`"
|
59
|
+
end.to_sentence}) compared to the one present in your `.swift-version` file (`#{dot_swift_version}`). " \
|
60
|
+
'Please remove the `.swift-version` file which is now deprecated and only use the `swift_versions` attribute within your podspec.'
|
61
|
+
elsif !swift_version.nil? && !spec_swift_versions.include?(swift_version)
|
62
|
+
message = "Specification `#{spec.name}` specifies inconsistent `swift_versions` (#{spec_swift_versions.map do |s|
|
63
|
+
"`#{s}`"
|
64
|
+
end.to_sentence}) compared to the one passed during gen (`#{swift_version}`)."
|
65
|
+
end
|
66
|
+
unless message.nil?
|
67
|
+
@results.error('swift', message)
|
68
|
+
break
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if swift_version.nil? && spec.swift_versions.empty?
|
73
|
+
if !dot_swift.nil?
|
74
|
+
# The user will be warned to delete the `.swift-version` file in favor of the `swift_versions` DSL attribute.
|
75
|
+
# This is intentionally not a lint warning since we do not want to break existing setups and instead just soft
|
76
|
+
# deprecate this slowly.
|
77
|
+
#
|
78
|
+
Pod::UI.warn 'Usage of the `.swift_version` file has been deprecated! Please delete the file and use the ' \
|
79
|
+
"`swift_versions` attribute within your podspec instead.\n".yellow
|
80
|
+
else
|
81
|
+
results.warning('swift',
|
82
|
+
'The generator used ' \
|
83
|
+
"Swift `#{Constants::DEFAULT_SWIFT_VERSION}` by default because no Swift version was specified. " \
|
84
|
+
'To specify a Swift version during validation, add the `swift_versions` attribute in your podspec. ' \
|
85
|
+
'Note that usage of a `.swift-version` file is now deprecated.')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
# Adds a shell script phase, intended only for library targets that contain swift,
|
91
|
+
# to copy the ObjC compatibility header (the -Swift.h file that the swift compiler generates)
|
92
|
+
# to the built products directory. Additionally, the script phase copies the module map, appending a `.Swift`
|
93
|
+
# submodule that references the (moved) compatibility header. Since the module map has been moved, the umbrella header
|
94
|
+
# is _also_ copied, so that it is sitting next to the module map. This is necessary for a successful archive build.
|
95
|
+
#
|
96
|
+
# @param [PBXNativeTarget] native_target
|
97
|
+
# the native target to add the Swift static library script phase into.
|
98
|
+
#
|
99
|
+
# @return [Void]
|
100
|
+
#
|
101
|
+
def add_swift_library_compatibility_header(targets)
|
102
|
+
targets.select(&:build_as_library?).each do |target|
|
103
|
+
relative_module_map_path = target.module_map_path.relative_path_from(target.sandbox.root)
|
104
|
+
relative_umbrella_header_path = target.umbrella_header_path.relative_path_from(target.sandbox.root)
|
105
|
+
shell_script = <<-SH.strip_heredoc
|
106
|
+
COMPATIBILITY_HEADER_ROOT_PATH="${SRCROOT}/${PRODUCT_MODULE_NAME}/#{Constants::COPY_LIBRARY_SWIFT_HEADERS}"
|
107
|
+
COPY_MODULE_MAP_PATH="${COMPATIBILITY_HEADER_ROOT_PATH}/${PRODUCT_MODULE_NAME}.modulemap"
|
108
|
+
ditto "${PODS_ROOT}/#{relative_module_map_path}" "${COPY_MODULE_MAP_PATH}"
|
109
|
+
UMBRELLA_HEADER_PATH="${PODS_ROOT}/#{relative_umbrella_header_path}"
|
110
|
+
if test -f "$UMBRELLA_HEADER_PATH"; then
|
111
|
+
ditto "$UMBRELLA_HEADER_PATH" "${COMPATIBILITY_HEADER_ROOT_PATH}"
|
112
|
+
fi
|
113
|
+
SH
|
114
|
+
|
115
|
+
target.root_spec.script_phases ||= []
|
116
|
+
target.root_spec.script_phases += [{ name: 'Copy Copy generated module header', script: shell_script }]
|
117
|
+
next unless target.uses_swift?
|
118
|
+
|
119
|
+
shell_script = <<-SH.strip_heredoc
|
120
|
+
COMPATIBILITY_HEADER_ROOT_PATH="${SRCROOT}/${PRODUCT_MODULE_NAME}/#{Constants::COPY_LIBRARY_SWIFT_HEADERS}"
|
121
|
+
COPY_COMPATIBILITY_HEADER_PATH="${COMPATIBILITY_HEADER_ROOT_PATH}/${PRODUCT_MODULE_NAME}-Swift.h"#{' '}
|
122
|
+
COPY_MODULE_MAP_PATH="${COMPATIBILITY_HEADER_ROOT_PATH}/${PRODUCT_MODULE_NAME}.modulemap"
|
123
|
+
ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${COPY_COMPATIBILITY_HEADER_PATH}"#{' '}
|
124
|
+
ditto "${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.swiftmodule" "${COMPATIBILITY_HEADER_ROOT_PATH}/${PRODUCT_MODULE_NAME}.swiftmodule"#{' '}
|
125
|
+
printf "\\n\\nmodule ${PRODUCT_MODULE_NAME}.Swift {\\n header \\"${PRODUCT_MODULE_NAME}-Swift.h\\"\\n requires objc\\n}\\n" >> "${COPY_MODULE_MAP_PATH}"
|
126
|
+
SH
|
127
|
+
target.root_spec.script_phases += [{
|
128
|
+
name: 'Copy Copy generated module and compatibility header',
|
129
|
+
script: shell_script
|
130
|
+
}]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'cocoapods/target/pod_target'
|
2
|
+
|
3
|
+
module ProjectGen
|
4
|
+
|
5
|
+
require 'delegate'
|
6
|
+
|
7
|
+
class GenTarget < DelegateClass(Pod::PodTarget)
|
8
|
+
def initialize(target)
|
9
|
+
super(target)
|
10
|
+
target.uses_swift?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ProductHelper
|
15
|
+
|
16
|
+
def version
|
17
|
+
root_spec.version
|
18
|
+
end
|
19
|
+
|
20
|
+
def label
|
21
|
+
target.label
|
22
|
+
end
|
23
|
+
|
24
|
+
def scope_suffix
|
25
|
+
target.scope_suffix
|
26
|
+
end
|
27
|
+
|
28
|
+
def static_library_name
|
29
|
+
"lib#{Utils.remove_target_scope_suffix(label, scope_suffix)}.a"
|
30
|
+
end
|
31
|
+
|
32
|
+
def pod_dir
|
33
|
+
root_name = module_basename
|
34
|
+
sandbox.sources_root + root_name
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_as_library?
|
38
|
+
target.build_as_library?
|
39
|
+
end
|
40
|
+
|
41
|
+
def uses_swift?
|
42
|
+
target.uses_swift?
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_as_framework?
|
46
|
+
target.build_as_framework?
|
47
|
+
end
|
48
|
+
|
49
|
+
def module_basename
|
50
|
+
Pod::Specification.root_name(pod_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def product_name
|
54
|
+
target.product_name
|
55
|
+
end
|
56
|
+
|
57
|
+
def pod_name
|
58
|
+
target.pod_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def product_type
|
62
|
+
target.product_type
|
63
|
+
end
|
64
|
+
|
65
|
+
def file_accessors
|
66
|
+
target.file_accessors
|
67
|
+
end
|
68
|
+
|
69
|
+
def sandbox
|
70
|
+
target.sandbox
|
71
|
+
end
|
72
|
+
|
73
|
+
def xcframework_product_name
|
74
|
+
"#{xcframework_name}.xcframework"
|
75
|
+
end
|
76
|
+
|
77
|
+
def xcframework_name
|
78
|
+
pod_name
|
79
|
+
end
|
80
|
+
|
81
|
+
def root_spec
|
82
|
+
target.root_spec
|
83
|
+
end
|
84
|
+
|
85
|
+
def product_path
|
86
|
+
product_root.join("#{module_basename}-#{product_type}-#{version}")
|
87
|
+
end
|
88
|
+
|
89
|
+
def xcframework_product_path
|
90
|
+
product_path.join(xcframework_product_name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|