cocoapods-modularization 0.0.2
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 +7 -0
- data/lib/cocoapods-modularization/command/install.rb +98 -0
- data/lib/cocoapods-modularization/command/mod/add.rb +97 -0
- data/lib/cocoapods-modularization/command/mod/base.rb +35 -0
- data/lib/cocoapods-modularization/command/mod/binary.rb +82 -0
- data/lib/cocoapods-modularization/command/mod/config.rb +51 -0
- data/lib/cocoapods-modularization/command/mod/create.rb +34 -0
- data/lib/cocoapods-modularization/command/mod/inspect.rb +26 -0
- data/lib/cocoapods-modularization/command/mod/source.rb +81 -0
- data/lib/cocoapods-modularization/command/mod/sync.rb +29 -0
- data/lib/cocoapods-modularization/command/mod/update.rb +64 -0
- data/lib/cocoapods-modularization/command/mod.rb +28 -0
- data/lib/cocoapods-modularization/command.rb +2 -0
- data/lib/cocoapods-modularization/gem_version.rb +3 -0
- data/lib/cocoapods-modularization/generate/configuration.rb +364 -0
- data/lib/cocoapods-modularization/generate/installer.rb +388 -0
- data/lib/cocoapods-modularization/generate/podfile_generator.rb +398 -0
- data/lib/cocoapods-modularization/generate.rb +7 -0
- data/lib/cocoapods-modularization/meta/meta_accessor.rb +134 -0
- data/lib/cocoapods-modularization/meta/meta_constants.rb +135 -0
- data/lib/cocoapods-modularization/meta/meta_reference.rb +255 -0
- data/lib/cocoapods-modularization/meta.rb +7 -0
- data/lib/cocoapods-modularization/private/private_cache.rb +277 -0
- data/lib/cocoapods-modularization/private.rb +5 -0
- data/lib/cocoapods-modularization.rb +1 -0
- data/lib/cocoapods_plugin.rb +1 -0
- metadata +96 -0
@@ -0,0 +1,388 @@
|
|
1
|
+
module Pod
|
2
|
+
module Generate
|
3
|
+
# Responsible for creating a workspace for a single specification,
|
4
|
+
# given a configuration and a generated podfile.
|
5
|
+
#
|
6
|
+
class Installer
|
7
|
+
# @return [Configuration]
|
8
|
+
# the configuration to use when installing
|
9
|
+
#
|
10
|
+
attr_reader :configuration
|
11
|
+
|
12
|
+
# @return [Specification]
|
13
|
+
# the spec whose workspace is being created
|
14
|
+
#
|
15
|
+
attr_reader :spec
|
16
|
+
|
17
|
+
# @return [Podfile]
|
18
|
+
# the podfile to install
|
19
|
+
#
|
20
|
+
attr_reader :podfile
|
21
|
+
|
22
|
+
def initialize(configuration, spec, podfile)
|
23
|
+
@configuration = configuration
|
24
|
+
@spec = spec
|
25
|
+
@podfile = podfile
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Pathname]
|
29
|
+
# The directory that pods will be installed into
|
30
|
+
#
|
31
|
+
def install_directory
|
32
|
+
@install_directory ||= podfile.defined_in_file.dirname
|
33
|
+
end
|
34
|
+
|
35
|
+
# Installs the {podfile} into the {install_directory}
|
36
|
+
#
|
37
|
+
# @return [void]
|
38
|
+
#
|
39
|
+
def install!
|
40
|
+
UI.title "Generating #{spec.name} in #{UI.path install_directory}" do
|
41
|
+
clean! if configuration.clean?
|
42
|
+
install_directory.mkpath
|
43
|
+
|
44
|
+
UI.message 'Creating stub application' do
|
45
|
+
create_app_project
|
46
|
+
end
|
47
|
+
|
48
|
+
UI.message 'Writing Podfile' do
|
49
|
+
podfile.defined_in_file.open('w') { |f| f << podfile.to_yaml }
|
50
|
+
end
|
51
|
+
|
52
|
+
installer = nil
|
53
|
+
UI.section 'Installing...' do
|
54
|
+
configuration.pod_config.with_changes(installation_root: install_directory, podfile: podfile,
|
55
|
+
lockfile: configuration.lockfile, sandbox: nil,
|
56
|
+
sandbox_root: install_directory + 'Pods',
|
57
|
+
podfile_path: podfile.defined_in_file,
|
58
|
+
silent: !configuration.pod_config.verbose?, verbose: false,
|
59
|
+
lockfile_path: nil) do
|
60
|
+
installer = ::Pod::Installer.new(configuration.pod_config.sandbox, podfile, configuration.lockfile)
|
61
|
+
installer.use_default_plugins = configuration.use_default_plugins
|
62
|
+
installer.install!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
UI.section 'Performing post-installation steps' do
|
67
|
+
should_perform_post_install = if installer.respond_to?(:generated_aggregate_targets) # CocoaPods 1.7.0
|
68
|
+
!installer.generated_aggregate_targets.empty?
|
69
|
+
else
|
70
|
+
true
|
71
|
+
end
|
72
|
+
perform_post_install_steps(open_app_project, installer) if should_perform_post_install
|
73
|
+
end
|
74
|
+
|
75
|
+
print_post_install_message
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Removes the {install_directory}
|
82
|
+
#
|
83
|
+
# @return [void]
|
84
|
+
#
|
85
|
+
def clean!
|
86
|
+
UI.message 'Cleaning gen install directory' do
|
87
|
+
FileUtils.rm_rf install_directory
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def open_app_project(recreate: false)
|
92
|
+
app_project_path = install_directory.join("#{configuration.project_name_for_spec(spec)}.xcodeproj")
|
93
|
+
if !recreate && app_project_path.exist?
|
94
|
+
Xcodeproj::Project.open(app_project_path)
|
95
|
+
else
|
96
|
+
Xcodeproj::Project.new(app_project_path)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Creates an app project that CocoaPods will integrate into
|
101
|
+
#
|
102
|
+
# @return [Xcodeproj::Project]
|
103
|
+
#
|
104
|
+
def create_app_project
|
105
|
+
app_project = open_app_project(recreate: !configuration.incremental_installation?)
|
106
|
+
|
107
|
+
spec_platforms = spec.available_platforms.flatten.reject do |platform|
|
108
|
+
!configuration.platforms.nil? && !configuration.platforms.include?(platform.string_name.downcase)
|
109
|
+
end
|
110
|
+
|
111
|
+
if spec_platforms.empty?
|
112
|
+
Pod::Command::Gen.help! Pod::StandardError.new "No available platforms in #{spec.name}.podspec match requested platforms: #{configuration.platforms}"
|
113
|
+
end
|
114
|
+
|
115
|
+
spec_platforms
|
116
|
+
.map do |platform|
|
117
|
+
consumer = spec.consumer(platform)
|
118
|
+
target_name = "App-#{Platform.string_name(consumer.platform_name)}"
|
119
|
+
next if app_project.targets.map(&:name).include? target_name
|
120
|
+
native_app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name,
|
121
|
+
deployment_target(consumer), target_name)
|
122
|
+
# Temporarily set Swift version to pass validator checks for pods which do not specify Swift version.
|
123
|
+
# It will then be re-set again within #perform_post_install_steps.
|
124
|
+
Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, Pod::Validator::DEFAULT_SWIFT_VERSION)
|
125
|
+
native_app_target
|
126
|
+
end
|
127
|
+
.compact.tap do
|
128
|
+
app_project.recreate_user_schemes do |scheme, target|
|
129
|
+
installation_result = installation_result_from_target(target)
|
130
|
+
next unless installation_result
|
131
|
+
installation_result.test_native_targets.each do |test_native_target|
|
132
|
+
scheme.add_test_target(test_native_target)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
.each do |target|
|
137
|
+
Xcodeproj::XCScheme.share_scheme(app_project.path, target.name) if target
|
138
|
+
end
|
139
|
+
app_project.save
|
140
|
+
end
|
141
|
+
|
142
|
+
def deployment_target(consumer)
|
143
|
+
deployment_target = consumer.spec.deployment_target(consumer.platform_name)
|
144
|
+
if consumer.platform_name == :ios && configuration.use_frameworks?
|
145
|
+
minimum = Version.new('8.0')
|
146
|
+
deployment_target = [Version.new(deployment_target), minimum].max.to_s
|
147
|
+
end
|
148
|
+
deployment_target
|
149
|
+
end
|
150
|
+
|
151
|
+
def perform_post_install_steps(app_project, installer)
|
152
|
+
app_project.native_targets.each do |native_app_target|
|
153
|
+
remove_script_phase_from_target(native_app_target, 'Check Pods Manifest.lock')
|
154
|
+
|
155
|
+
pod_target = installer.pod_targets.find { |pt| pt.platform.name == native_app_target.platform_name && pt.pod_name == spec.name }
|
156
|
+
raise "Unable to find a pod target for #{native_app_target} / #{spec}" unless pod_target
|
157
|
+
|
158
|
+
native_app_target.source_build_phase.clear
|
159
|
+
native_app_target.resources_build_phase.clear
|
160
|
+
|
161
|
+
if (app_host_source_dir = configuration.app_host_source_dir)
|
162
|
+
relative_app_host_source_dir = app_host_source_dir.relative_path_from(installer.sandbox.root)
|
163
|
+
groups = {}
|
164
|
+
|
165
|
+
app_host_source_dir.find do |file|
|
166
|
+
relative_path = file.relative_path_from(app_host_source_dir)
|
167
|
+
|
168
|
+
if file.directory?
|
169
|
+
groups[relative_path] =
|
170
|
+
if (base_group = groups[relative_path.dirname])
|
171
|
+
basename = relative_path.basename
|
172
|
+
base_group.new_group(basename.to_s, basename)
|
173
|
+
else
|
174
|
+
app_project.new_group(native_app_target.name, relative_app_host_source_dir)
|
175
|
+
end
|
176
|
+
|
177
|
+
next
|
178
|
+
elsif file.to_s.end_with?('-Bridging-Header.h')
|
179
|
+
native_app_target.build_configurations.each do |bc|
|
180
|
+
if (old_bridging_header = bc.build_settings['SWIFT_OBJC_BRIDGING_HEADER'])
|
181
|
+
raise Informative, "Conflicting Swift ObjC bridging headers specified, got #{old_bridging_header} and #{relative_path}. Only one `-Bridging-Header.h` file may be specified in the app host source dir."
|
182
|
+
end
|
183
|
+
|
184
|
+
bc.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] = relative_path.to_s
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
group = groups[relative_path.dirname]
|
189
|
+
source_file_ref = group.new_file(file.basename)
|
190
|
+
native_app_target.add_file_references([source_file_ref])
|
191
|
+
end
|
192
|
+
elsif Pod::Generator::AppTargetHelper.method(:add_app_project_import).arity == -5 # CocoaPods >= 1.6
|
193
|
+
# If we are doing incremental installation then the file might already be there.
|
194
|
+
platform_name = Platform.string_name(native_app_target.platform_name)
|
195
|
+
group = group_for_platform_name(app_project, platform_name)
|
196
|
+
main_file_ref = group.files.find { |f| f.display_name == 'main.m' }
|
197
|
+
if main_file_ref.nil?
|
198
|
+
Pod::Generator::AppTargetHelper.add_app_project_import(app_project, native_app_target, pod_target,
|
199
|
+
pod_target.platform.name, native_app_target.name)
|
200
|
+
else
|
201
|
+
native_app_target.add_file_references([main_file_ref])
|
202
|
+
end
|
203
|
+
else
|
204
|
+
Pod::Generator::AppTargetHelper.add_app_project_import(app_project, native_app_target, pod_target,
|
205
|
+
pod_target.platform.name,
|
206
|
+
pod_target.requires_frameworks?,
|
207
|
+
native_app_target.name)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Set `PRODUCT_BUNDLE_IDENTIFIER`
|
211
|
+
native_app_target.build_configurations.each do |bc|
|
212
|
+
bc.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods-generate.${PRODUCT_NAME:rfc1034identifier}'
|
213
|
+
end
|
214
|
+
|
215
|
+
case native_app_target.platform_name
|
216
|
+
when :ios
|
217
|
+
make_ios_app_launchable(app_project, native_app_target)
|
218
|
+
end
|
219
|
+
|
220
|
+
Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, pod_target.swift_version) unless pod_target.swift_version.blank?
|
221
|
+
if installer.pod_targets.any? { |pt| pt.spec_consumers.any? { |c| c.frameworks.include?('XCTest') } }
|
222
|
+
Pod::Generator::AppTargetHelper.add_xctest_search_paths(native_app_target)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Share the pods xcscheme only if it exists. For pre-built vendored pods there is no xcscheme generated.
|
226
|
+
if installer.respond_to?(:generated_projects) # CocoaPods 1.7.0
|
227
|
+
installer.generated_projects.each do |project|
|
228
|
+
Xcodeproj::XCScheme.share_scheme(project.path, pod_target.label) if File.exist?(project.path + pod_target.label)
|
229
|
+
end
|
230
|
+
elsif File.exist?(installer.pods_project.path + pod_target.label)
|
231
|
+
Xcodeproj::XCScheme.share_scheme(installer.pods_project.path, pod_target.label)
|
232
|
+
end
|
233
|
+
|
234
|
+
add_test_spec_schemes_to_app_scheme(installer, app_project)
|
235
|
+
end
|
236
|
+
|
237
|
+
app_project.save
|
238
|
+
end
|
239
|
+
|
240
|
+
def installation_result_from_target(target)
|
241
|
+
return unless target.respond_to?(:symbol_type)
|
242
|
+
library_product_types = %i[framework dynamic_library static_library]
|
243
|
+
return unless library_product_types.include? target.symbol_type
|
244
|
+
|
245
|
+
results_by_native_target[target]
|
246
|
+
end
|
247
|
+
|
248
|
+
def remove_script_phase_from_target(native_target, script_phase_name)
|
249
|
+
script_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(script_phase_name) }
|
250
|
+
return unless script_phase.present?
|
251
|
+
native_target.build_phases.delete(script_phase)
|
252
|
+
end
|
253
|
+
|
254
|
+
def add_test_spec_schemes_to_app_scheme(installer, app_project)
|
255
|
+
test_native_targets =
|
256
|
+
if installer.respond_to?(:target_installation_results) # CocoaPods >= 1.6
|
257
|
+
installer
|
258
|
+
.target_installation_results
|
259
|
+
.pod_target_installation_results
|
260
|
+
.values
|
261
|
+
.flatten(1)
|
262
|
+
.select { |installation_result| installation_result.target.pod_name == spec.root.name }
|
263
|
+
else
|
264
|
+
installer
|
265
|
+
.pod_targets
|
266
|
+
.select { |pod_target| pod_target.pod_name == spec.root.name }
|
267
|
+
end
|
268
|
+
.flat_map(&:test_native_targets)
|
269
|
+
.group_by(&:platform_name)
|
270
|
+
|
271
|
+
workspace_path = install_directory + "#{spec.name}.xcworkspace"
|
272
|
+
Xcodeproj::Plist.write_to_path(
|
273
|
+
{ 'IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded' => false },
|
274
|
+
workspace_path.join('xcshareddata').tap(&:mkpath).join('WorkspaceSettings.xcsettings')
|
275
|
+
)
|
276
|
+
|
277
|
+
test_native_targets.each do |platform_name, test_targets|
|
278
|
+
app_scheme_path = Xcodeproj::XCScheme.shared_data_dir(app_project.path).join("App-#{Platform.string_name(platform_name)}.xcscheme")
|
279
|
+
raise "Missing app scheme for #{platform_name}: #{app_scheme_path.inspect}" unless app_scheme_path.file?
|
280
|
+
|
281
|
+
app_scheme = Xcodeproj::XCScheme.new(app_scheme_path)
|
282
|
+
test_action = app_scheme.test_action
|
283
|
+
existing_test_targets = test_action.testables.flat_map(&:buildable_references).map(&:target_name)
|
284
|
+
|
285
|
+
test_targets.sort_by(&:name).each do |target|
|
286
|
+
next if existing_test_targets.include?(target.name)
|
287
|
+
|
288
|
+
testable = Xcodeproj::XCScheme::TestAction::TestableReference.new(target)
|
289
|
+
testable.buildable_references.each do |buildable|
|
290
|
+
buildable.xml_element.attributes['ReferencedContainer'] = 'container:Pods.xcodeproj'
|
291
|
+
end
|
292
|
+
test_action.add_testable(testable)
|
293
|
+
end
|
294
|
+
|
295
|
+
app_scheme.save!
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def make_ios_app_launchable(app_project, native_app_target)
|
300
|
+
platform_name = Platform.string_name(native_app_target.platform_name)
|
301
|
+
generated_source_dir = install_directory.join("App-#{platform_name}").tap(&:mkpath)
|
302
|
+
|
303
|
+
# Add `LaunchScreen.storyboard`
|
304
|
+
launch_storyboard = generated_source_dir.join('LaunchScreen.storyboard')
|
305
|
+
launch_storyboard.write <<-XML.strip_heredoc
|
306
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
307
|
+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
308
|
+
<dependencies>
|
309
|
+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
310
|
+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
311
|
+
</dependencies>
|
312
|
+
<scenes>
|
313
|
+
<!--View Controller-->
|
314
|
+
<scene sceneID="EHf-IW-A2E">
|
315
|
+
<objects>
|
316
|
+
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
317
|
+
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
318
|
+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
319
|
+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
320
|
+
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
321
|
+
</view>
|
322
|
+
</viewController>
|
323
|
+
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
324
|
+
</objects>
|
325
|
+
<point key="canvasLocation" x="53" y="375"/>
|
326
|
+
</scene>
|
327
|
+
</scenes>
|
328
|
+
</document>
|
329
|
+
XML
|
330
|
+
|
331
|
+
# Add & wire `Info.plist`
|
332
|
+
info_plist_contents = {
|
333
|
+
'CFBundleDevelopmentRegion' => '$(DEVELOPMENT_LANGUAGE)',
|
334
|
+
'CFBundleExecutable' => '$(EXECUTABLE_NAME)',
|
335
|
+
'CFBundleIdentifier' => '$(PRODUCT_BUNDLE_IDENTIFIER)',
|
336
|
+
'CFBundleInfoDictionaryVersion' => '6.0',
|
337
|
+
'CFBundleName' => '$(PRODUCT_NAME)',
|
338
|
+
'CFBundlePackageType' => 'APPL',
|
339
|
+
'CFBundleShortVersionString' => '1.0',
|
340
|
+
'CFBundleVersion' => '1',
|
341
|
+
'LSRequiresIPhoneOS' => true,
|
342
|
+
'UILaunchStoryboardName' => 'LaunchScreen',
|
343
|
+
'UIRequiredDeviceCapabilities' => [
|
344
|
+
'armv7'
|
345
|
+
],
|
346
|
+
'UISupportedInterfaceOrientations' => %w[
|
347
|
+
UIInterfaceOrientationPortrait
|
348
|
+
UIInterfaceOrientationLandscapeLeft
|
349
|
+
UIInterfaceOrientationLandscapeRight
|
350
|
+
],
|
351
|
+
'UISupportedInterfaceOrientations~ipad' => %w[
|
352
|
+
UIInterfaceOrientationPortrait
|
353
|
+
UIInterfaceOrientationPortraitUpsideDown
|
354
|
+
UIInterfaceOrientationLandscapeLeft
|
355
|
+
UIInterfaceOrientationLandscapeRight
|
356
|
+
]
|
357
|
+
}
|
358
|
+
info_plist_path = generated_source_dir.join('Info.plist')
|
359
|
+
Xcodeproj::Plist.write_to_path(info_plist_contents, info_plist_path)
|
360
|
+
|
361
|
+
native_app_target.build_configurations.each do |bc|
|
362
|
+
bc.build_settings['INFOPLIST_FILE'] = "${SRCROOT}/App-#{platform_name}/Info.plist"
|
363
|
+
end
|
364
|
+
|
365
|
+
group = group_for_platform_name(app_project, platform_name)
|
366
|
+
group.files.find { |f| f.display_name == 'Info.plist' } || group.new_file(info_plist_path)
|
367
|
+
launch_storyboard_file_ref = group.files.find { |f| f.display_name == 'LaunchScreen.storyboard' } || group.new_file(launch_storyboard)
|
368
|
+
native_app_target.resources_build_phase.add_file_reference(launch_storyboard_file_ref)
|
369
|
+
end
|
370
|
+
|
371
|
+
def group_for_platform_name(project, platform_name, should_create = true)
|
372
|
+
project.main_group.find_subpath("App-#{platform_name}", should_create)
|
373
|
+
end
|
374
|
+
|
375
|
+
def print_post_install_message
|
376
|
+
workspace_path = install_directory.join(podfile.workspace_path)
|
377
|
+
|
378
|
+
if configuration.auto_open?
|
379
|
+
configuration.pod_config.with_changes(verbose: true) do
|
380
|
+
Executable.execute_command 'open', [workspace_path]
|
381
|
+
end
|
382
|
+
else
|
383
|
+
UI.info "Open #{UI.path workspace_path} to work on #{spec.name}"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|