cocoapods-modularization 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|