cocoapods-tt 0.0.1

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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-tt/command/native/install.rb +56 -0
  3. data/lib/cocoapods-tt/command/native/update.rb +157 -0
  4. data/lib/cocoapods-tt/command/tt/make.rb +92 -0
  5. data/lib/cocoapods-tt/command/tt.rb +115 -0
  6. data/lib/cocoapods-tt/command.rb +1 -0
  7. data/lib/cocoapods-tt/gem_version.rb +3 -0
  8. data/lib/cocoapods-tt/native/command.rb +185 -0
  9. data/lib/cocoapods-tt/native/config.rb +366 -0
  10. data/lib/cocoapods-tt/native/core_overrides.rb +1 -0
  11. data/lib/cocoapods-tt/native/downloader/cache.rb +322 -0
  12. data/lib/cocoapods-tt/native/downloader/request.rb +86 -0
  13. data/lib/cocoapods-tt/native/downloader/response.rb +16 -0
  14. data/lib/cocoapods-tt/native/downloader.rb +192 -0
  15. data/lib/cocoapods-tt/native/executable.rb +247 -0
  16. data/lib/cocoapods-tt/native/external_sources/abstract_external_source.rb +205 -0
  17. data/lib/cocoapods-tt/native/external_sources/downloader_source.rb +30 -0
  18. data/lib/cocoapods-tt/native/external_sources/path_source.rb +55 -0
  19. data/lib/cocoapods-tt/native/external_sources/podspec_source.rb +54 -0
  20. data/lib/cocoapods-tt/native/external_sources.rb +57 -0
  21. data/lib/cocoapods-tt/native/gem_version.rb +5 -0
  22. data/lib/cocoapods-tt/native/generator/acknowledgements/markdown.rb +44 -0
  23. data/lib/cocoapods-tt/native/generator/acknowledgements/plist.rb +94 -0
  24. data/lib/cocoapods-tt/native/generator/acknowledgements.rb +107 -0
  25. data/lib/cocoapods-tt/native/generator/app_target_helper.rb +363 -0
  26. data/lib/cocoapods-tt/native/generator/bridge_support.rb +22 -0
  27. data/lib/cocoapods-tt/native/generator/constant.rb +19 -0
  28. data/lib/cocoapods-tt/native/generator/copy_dsyms_script.rb +56 -0
  29. data/lib/cocoapods-tt/native/generator/copy_resources_script.rb +223 -0
  30. data/lib/cocoapods-tt/native/generator/copy_xcframework_script.rb +227 -0
  31. data/lib/cocoapods-tt/native/generator/dummy_source.rb +31 -0
  32. data/lib/cocoapods-tt/native/generator/embed_frameworks_script.rb +196 -0
  33. data/lib/cocoapods-tt/native/generator/file_list.rb +39 -0
  34. data/lib/cocoapods-tt/native/generator/header.rb +103 -0
  35. data/lib/cocoapods-tt/native/generator/info_plist_file.rb +128 -0
  36. data/lib/cocoapods-tt/native/generator/module_map.rb +99 -0
  37. data/lib/cocoapods-tt/native/generator/prefix_header.rb +60 -0
  38. data/lib/cocoapods-tt/native/generator/script_phase_constants.rb +100 -0
  39. data/lib/cocoapods-tt/native/generator/umbrella_header.rb +46 -0
  40. data/lib/cocoapods-tt/native/hooks_manager.rb +132 -0
  41. data/lib/cocoapods-tt/native/installer/analyzer/analysis_result.rb +87 -0
  42. data/lib/cocoapods-tt/native/installer/analyzer/locking_dependency_analyzer.rb +103 -0
  43. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant.rb +87 -0
  44. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant_set.rb +175 -0
  45. data/lib/cocoapods-tt/native/installer/analyzer/podfile_dependency_cache.rb +55 -0
  46. data/lib/cocoapods-tt/native/installer/analyzer/sandbox_analyzer.rb +268 -0
  47. data/lib/cocoapods-tt/native/installer/analyzer/specs_state.rb +108 -0
  48. data/lib/cocoapods-tt/native/installer/analyzer/target_inspection_result.rb +58 -0
  49. data/lib/cocoapods-tt/native/installer/analyzer/target_inspector.rb +258 -0
  50. data/lib/cocoapods-tt/native/installer/analyzer.rb +1204 -0
  51. data/lib/cocoapods-tt/native/installer/base_install_hooks_context.rb +135 -0
  52. data/lib/cocoapods-tt/native/installer/installation_options.rb +195 -0
  53. data/lib/cocoapods-tt/native/installer/pod_source_installer.rb +224 -0
  54. data/lib/cocoapods-tt/native/installer/pod_source_preparer.rb +77 -0
  55. data/lib/cocoapods-tt/native/installer/podfile_validator.rb +168 -0
  56. data/lib/cocoapods-tt/native/installer/post_install_hooks_context.rb +9 -0
  57. data/lib/cocoapods-tt/native/installer/post_integrate_hooks_context.rb +9 -0
  58. data/lib/cocoapods-tt/native/installer/pre_install_hooks_context.rb +51 -0
  59. data/lib/cocoapods-tt/native/installer/pre_integrate_hooks_context.rb +9 -0
  60. data/lib/cocoapods-tt/native/installer/project_cache/project_cache.rb +11 -0
  61. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analysis_result.rb +53 -0
  62. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analyzer.rb +200 -0
  63. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_version.rb +43 -0
  64. data/lib/cocoapods-tt/native/installer/project_cache/project_installation_cache.rb +103 -0
  65. data/lib/cocoapods-tt/native/installer/project_cache/project_metadata_cache.rb +73 -0
  66. data/lib/cocoapods-tt/native/installer/project_cache/target_cache_key.rb +176 -0
  67. data/lib/cocoapods-tt/native/installer/project_cache/target_metadata.rb +74 -0
  68. data/lib/cocoapods-tt/native/installer/sandbox_dir_cleaner.rb +105 -0
  69. data/lib/cocoapods-tt/native/installer/sandbox_header_paths_installer.rb +45 -0
  70. data/lib/cocoapods-tt/native/installer/source_provider_hooks_context.rb +34 -0
  71. data/lib/cocoapods-tt/native/installer/target_uuid_generator.rb +34 -0
  72. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +179 -0
  73. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator.rb +815 -0
  74. data/lib/cocoapods-tt/native/installer/user_project_integrator.rb +280 -0
  75. data/lib/cocoapods-tt/native/installer/xcode/multi_pods_project_generator.rb +82 -0
  76. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +66 -0
  77. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_installer.rb +192 -0
  78. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/app_host_installer.rb +154 -0
  79. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/file_references_installer.rb +329 -0
  80. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +195 -0
  81. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_installer.rb +1239 -0
  82. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_integrator.rb +312 -0
  83. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pods_project_writer.rb +90 -0
  84. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/project_generator.rb +120 -0
  85. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installation_result.rb +140 -0
  86. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer.rb +257 -0
  87. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer_helper.rb +110 -0
  88. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator.rb +291 -0
  89. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator_result.rb +54 -0
  90. data/lib/cocoapods-tt/native/installer/xcode/single_pods_project_generator.rb +38 -0
  91. data/lib/cocoapods-tt/native/installer/xcode/target_validator.rb +170 -0
  92. data/lib/cocoapods-tt/native/installer/xcode.rb +11 -0
  93. data/lib/cocoapods-tt/native/installer.rb +1044 -0
  94. data/lib/cocoapods-tt/native/native_target_extension.rb +60 -0
  95. data/lib/cocoapods-tt/native/open-uri.rb +33 -0
  96. data/lib/cocoapods-tt/native/podfile.rb +13 -0
  97. data/lib/cocoapods-tt/native/project.rb +544 -0
  98. data/lib/cocoapods-tt/native/resolver/lazy_specification.rb +88 -0
  99. data/lib/cocoapods-tt/native/resolver/resolver_specification.rb +41 -0
  100. data/lib/cocoapods-tt/native/resolver.rb +600 -0
  101. data/lib/cocoapods-tt/native/sandbox/file_accessor.rb +532 -0
  102. data/lib/cocoapods-tt/native/sandbox/headers_store.rb +163 -0
  103. data/lib/cocoapods-tt/native/sandbox/path_list.rb +242 -0
  104. data/lib/cocoapods-tt/native/sandbox/pod_dir_cleaner.rb +71 -0
  105. data/lib/cocoapods-tt/native/sandbox/podspec_finder.rb +23 -0
  106. data/lib/cocoapods-tt/native/sandbox.rb +470 -0
  107. data/lib/cocoapods-tt/native/sources_manager.rb +221 -0
  108. data/lib/cocoapods-tt/native/target/aggregate_target.rb +558 -0
  109. data/lib/cocoapods-tt/native/target/build_settings.rb +1385 -0
  110. data/lib/cocoapods-tt/native/target/pod_target.rb +1168 -0
  111. data/lib/cocoapods-tt/native/target.rb +378 -0
  112. data/lib/cocoapods-tt/native/user_interface/error_report.rb +204 -0
  113. data/lib/cocoapods-tt/native/user_interface/inspector_reporter.rb +102 -0
  114. data/lib/cocoapods-tt/native/user_interface.rb +463 -0
  115. data/lib/cocoapods-tt/native/validator.rb +1170 -0
  116. data/lib/cocoapods-tt/native/version_metadata.rb +26 -0
  117. data/lib/cocoapods-tt/native/xcode/framework_paths.rb +54 -0
  118. data/lib/cocoapods-tt/native/xcode/linkage_analyzer.rb +22 -0
  119. data/lib/cocoapods-tt/native/xcode/xcframework/xcframework_slice.rb +138 -0
  120. data/lib/cocoapods-tt/native/xcode/xcframework.rb +99 -0
  121. data/lib/cocoapods-tt/native/xcode.rb +7 -0
  122. data/lib/cocoapods-tt.rb +1 -0
  123. data/lib/cocoapods_plugin.rb +17 -0
  124. metadata +193 -0
@@ -0,0 +1,154 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Installs an app host target to a given project.
6
+ #
7
+ class AppHostInstaller
8
+ include TargetInstallerHelper
9
+
10
+ # @return [Sandbox]
11
+ # The sandbox used for this installation.
12
+ #
13
+ attr_reader :sandbox
14
+
15
+ # @return [Pod::Project]
16
+ # The project to install the app host into.
17
+ #
18
+ attr_reader :project
19
+
20
+ # @return [Platform] the platform to use for this app host.
21
+ #
22
+ attr_reader :platform
23
+
24
+ # @return [String] the name of the sub group.
25
+ #
26
+ attr_reader :subgroup_name
27
+
28
+ # @return [String] the name of the group the app host installer will be installing within.
29
+ #
30
+ attr_reader :group_name
31
+
32
+ # @return [String] the name of the app target label that will be used.
33
+ #
34
+ attr_reader :app_target_label
35
+
36
+ # @return [Boolean] whether the app host installer should add main.m
37
+ #
38
+ attr_reader :add_main
39
+
40
+ # @return [Boolean] whether the app host installer should add a launch screen storyboard
41
+ #
42
+ attr_reader :add_launchscreen_storyboard
43
+
44
+ # @return [Hash] Info.plist entries for the app host
45
+ #
46
+ attr_reader :info_plist_entries
47
+
48
+ # @return [String] product_basename
49
+ # The product basename to use for the target.
50
+ #
51
+ attr_reader :product_basename
52
+
53
+ # Initialize a new instance
54
+ #
55
+ # @param [Sandbox] sandbox @see #sandbox
56
+ # @param [Pod::Project] project @see #project
57
+ # @param [Platform] platform @see #platform
58
+ # @param [String] subgroup_name @see #subgroup_name
59
+ # @param [String] group_name @see #group_name
60
+ # @param [String] app_target_label see #app_target_label
61
+ # @param [Boolean] add_main see #add_main
62
+ # @param [Hash] info_plist_entries see #info_plist_entries
63
+ # @param [String] product_basename see #product_basename
64
+ #
65
+ def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true,
66
+ add_launchscreen_storyboard: platform == :ios, info_plist_entries: {}, product_basename: nil)
67
+ @sandbox = sandbox
68
+ @project = project
69
+ @platform = platform
70
+ @subgroup_name = subgroup_name
71
+ @group_name = group_name
72
+ @app_target_label = app_target_label
73
+ @add_main = add_main
74
+ @add_launchscreen_storyboard = add_launchscreen_storyboard
75
+ @info_plist_entries = info_plist_entries
76
+ @product_basename = product_basename || app_target_label
77
+ target_group = project.pod_group(group_name)
78
+ @group = target_group[subgroup_name] || target_group.new_group(subgroup_name)
79
+ end
80
+
81
+ # @return [PBXNativeTarget] the app host native target that was installed.
82
+ #
83
+ def install!
84
+ platform_name = platform.name
85
+ app_host_target = Pod::Generator::AppTargetHelper.add_app_target(project, platform_name, deployment_target,
86
+ app_target_label, product_basename)
87
+ app_host_target.build_configurations.each do |configuration|
88
+ configuration.build_settings['PRODUCT_NAME'] = product_basename
89
+ configuration.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
90
+ if platform == :osx
91
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = ''
92
+ elsif platform == :ios
93
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = 'iPhone Developer'
94
+ end
95
+ configuration.build_settings['CURRENT_PROJECT_VERSION'] = '1'
96
+ end
97
+
98
+ Pod::Generator::AppTargetHelper.add_app_host_main_file(project, app_host_target, platform_name, @group, app_target_label) if add_main
99
+ Pod::Generator::AppTargetHelper.add_launchscreen_storyboard(project, app_host_target, @group, deployment_target, app_target_label) if add_launchscreen_storyboard
100
+ create_info_plist_file_with_sandbox(sandbox, app_host_info_plist_path, app_host_target, '1.0.0', platform,
101
+ :appl, :additional_entries => additional_info_plist_entries)
102
+ @group.new_file(app_host_info_plist_path)
103
+ app_host_target
104
+ end
105
+
106
+ private
107
+
108
+ ADDITIONAL_INFO_PLIST_ENTRIES = {
109
+ 'NSAppTransportSecurity' => {
110
+ 'NSAllowsArbitraryLoads' => true,
111
+ },
112
+ }.freeze
113
+
114
+ ADDITIONAL_IOS_INFO_PLIST_ENTRIES = {
115
+ 'UILaunchStoryboardName' => 'LaunchScreen',
116
+ 'UISupportedInterfaceOrientations' => %w(
117
+ UIInterfaceOrientationPortrait
118
+ UIInterfaceOrientationLandscapeLeft
119
+ UIInterfaceOrientationLandscapeRight
120
+ ),
121
+ 'UISupportedInterfaceOrientations~ipad' => %w(
122
+ UIInterfaceOrientationPortrait
123
+ UIInterfaceOrientationPortraitUpsideDown
124
+ UIInterfaceOrientationLandscapeLeft
125
+ UIInterfaceOrientationLandscapeRight
126
+ ),
127
+ }.freeze
128
+
129
+ # @return [Hash] the additional Info.plist entries to be included
130
+ #
131
+ def additional_info_plist_entries
132
+ result = {}
133
+ result.merge!(ADDITIONAL_INFO_PLIST_ENTRIES)
134
+ result.merge!(ADDITIONAL_IOS_INFO_PLIST_ENTRIES) if platform == :ios
135
+ result.merge!(info_plist_entries) if info_plist_entries
136
+ result
137
+ end
138
+
139
+ # @return [Pathname] The absolute path of the Info.plist to use for an app host.
140
+ #
141
+ def app_host_info_plist_path
142
+ project.path.dirname.+(subgroup_name).+("#{app_target_label}-Info.plist")
143
+ end
144
+
145
+ # @return [String] The deployment target.
146
+ #
147
+ def deployment_target
148
+ platform.deployment_target.to_s
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,329 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Controller class responsible of installing the file references of the
6
+ # specifications in the Pods project.
7
+ #
8
+ class FileReferencesInstaller
9
+ # Regex for extracting the region portion of a localized file path. Ex. `Resources/en.lproj` --> `en`
10
+ LOCALIZATION_REGION_FILEPATTERN_REGEX = /(\/|^)(?<region>[^\/]*?)\.lproj(\/|$)/
11
+
12
+ # @return [Sandbox] The sandbox of the installation.
13
+ #
14
+ attr_reader :sandbox
15
+
16
+ # @return [Array<PodTarget>] The pod targets of the installation.
17
+ #
18
+ attr_reader :pod_targets
19
+
20
+ # @return [Project] The project to install the file references into.
21
+ #
22
+ attr_reader :pods_project
23
+
24
+ # @return [Bool] add support for preserving the file structure of externally sourced pods, in addition to local pods.
25
+ #
26
+ attr_reader :preserve_pod_file_structure
27
+
28
+ # Initialize a new instance
29
+ #
30
+ # @param [Sandbox] sandbox @see #sandbox
31
+ # @param [Array<PodTarget>] pod_targets @see #pod_targets
32
+ # @param [Project] pods_project @see #pods_project
33
+ # @param [Bool] preserve_pod_file_structure @see #preserve_pod_file_structure
34
+ #
35
+ def initialize(sandbox, pod_targets, pods_project, preserve_pod_file_structure = false)
36
+ @sandbox = sandbox
37
+ @pod_targets = pod_targets
38
+ @pods_project = pods_project
39
+ @preserve_pod_file_structure = preserve_pod_file_structure
40
+ end
41
+
42
+ # Installs the file references.
43
+ #
44
+ # @return [void]
45
+ #
46
+ def install!
47
+ refresh_file_accessors
48
+ prepare_pod_groups
49
+ add_source_files_references
50
+ add_frameworks_bundles
51
+ add_vendored_libraries
52
+ add_resources
53
+ add_developer_files unless sandbox.development_pods.empty?
54
+ link_headers
55
+ end
56
+
57
+ #-----------------------------------------------------------------------#
58
+
59
+ private
60
+
61
+ # @!group Installation Steps
62
+
63
+ # Reads the file accessors contents from the file system.
64
+ #
65
+ # @note The contents of the file accessors are modified by the clean
66
+ # step of the #{PodSourceInstaller} and by the pre install hooks.
67
+ #
68
+ # @return [void]
69
+ #
70
+ def refresh_file_accessors
71
+ file_accessors.reject do |file_accessor|
72
+ pod_name = file_accessor.spec.name
73
+ sandbox.local?(pod_name)
74
+ end.map(&:path_list).uniq.each(&:read_file_system)
75
+ end
76
+
77
+ # Prepares the main groups to which all files will be added for the respective target
78
+ #
79
+ def prepare_pod_groups
80
+ file_accessors.each do |file_accessor|
81
+ pod_name = file_accessor.spec.name
82
+ next unless sandbox.local?(pod_name)
83
+ root_name = Specification.root_name(pod_name)
84
+ path = file_accessor.root
85
+ group = pods_project.group_for_spec(root_name)
86
+ group.set_path(path) unless group.path == path
87
+ end
88
+ end
89
+
90
+ # Adds the source files of the Pods to the Pods project.
91
+ #
92
+ # @note The source files are grouped by Pod and in turn by subspec
93
+ # (recursively).
94
+ #
95
+ # @return [void]
96
+ #
97
+ def add_source_files_references
98
+ UI.message '- Adding source files' do
99
+ add_file_accessors_paths_to_pods_group(:source_files, nil, true)
100
+ end
101
+ end
102
+
103
+ # Adds the bundled frameworks to the Pods project
104
+ #
105
+ # @return [void]
106
+ #
107
+ def add_frameworks_bundles
108
+ UI.message '- Adding frameworks' do
109
+ add_file_accessors_paths_to_pods_group(:vendored_frameworks, :frameworks)
110
+ end
111
+ end
112
+
113
+ # Adds the bundled libraries to the Pods project
114
+ #
115
+ # @return [void]
116
+ #
117
+ def add_vendored_libraries
118
+ UI.message '- Adding libraries' do
119
+ add_file_accessors_paths_to_pods_group(:vendored_libraries, :frameworks)
120
+ end
121
+ end
122
+
123
+ # Adds the resources of the Pods to the Pods project.
124
+ #
125
+ # @note The source files are grouped by Pod and in turn by subspec
126
+ # (recursively) in the resources group.
127
+ #
128
+ # @return [void]
129
+ #
130
+ def add_resources
131
+ UI.message '- Adding resources' do
132
+ refs = add_file_accessors_paths_to_pods_group(:resources, :resources, true)
133
+ refs.concat add_file_accessors_paths_to_pods_group(:resource_bundle_files, :resources, true)
134
+ add_known_regions(refs)
135
+ end
136
+ end
137
+
138
+ def add_developer_files
139
+ UI.message '- Adding development pod helper files' do
140
+ file_accessors.each do |file_accessor|
141
+ pod_name = file_accessor.spec.name
142
+ next unless sandbox.local?(pod_name)
143
+ root_name = Specification.root_name(pod_name)
144
+ paths = file_accessor.developer_files
145
+ next if paths.empty?
146
+ group = pods_project.group_for_spec(root_name, :developer)
147
+ paths.each do |path|
148
+ ref = pods_project.add_file_reference(path, group, false)
149
+ if path.extname == '.podspec'
150
+ pods_project.mark_ruby_file_ref(ref)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ # Creates the link to the headers of the Pod in the sandbox.
158
+ #
159
+ # @return [void]
160
+ #
161
+ def link_headers
162
+ UI.message '- Linking headers' do
163
+ pod_targets.each do |pod_target|
164
+ # When integrating Pod as frameworks, built Pods are built into
165
+ # frameworks, whose headers are included inside the built
166
+ # framework. Those headers do not need to be linked from the
167
+ # sandbox.
168
+ next if pod_target.build_as_framework? && pod_target.should_build?
169
+
170
+ pod_target_header_mappings = pod_target.header_mappings_by_file_accessor.values
171
+ pod_target_header_mappings.each do |header_mappings|
172
+ header_mappings.each do |namespaced_path, files|
173
+ pod_target.build_headers.add_files(namespaced_path, files)
174
+ end
175
+ end
176
+
177
+ public_header_mappings = pod_target.public_header_mappings_by_file_accessor.values
178
+ public_header_mappings.each do |header_mappings|
179
+ header_mappings.each do |namespaced_path, files|
180
+ sandbox.public_headers.add_files(namespaced_path, files)
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ #-----------------------------------------------------------------------#
188
+
189
+ private
190
+
191
+ # @!group Private Helpers
192
+
193
+ # @return [Array<Sandbox::FileAccessor>] The file accessors for all the
194
+ # specs platform combinations.
195
+ #
196
+ def file_accessors
197
+ @file_accessors ||= pod_targets.flat_map(&:file_accessors).compact
198
+ end
199
+
200
+ # Adds file references to the list of the paths returned by the file
201
+ # accessor with the given key to the given group of the Pods project.
202
+ #
203
+ # @param [Symbol] file_accessor_key
204
+ # The method of the file accessor which would return the list of
205
+ # the paths.
206
+ #
207
+ # @param [Symbol] group_key
208
+ # The key of the group of the Pods project.
209
+ #
210
+ # @param [Bool] reflect_file_system_structure
211
+ # Whether organizing a local pod's files in subgroups inside
212
+ # the pod's group is allowed.
213
+ #
214
+ # @return [Array<PBXFileReference>] the added file references
215
+ #
216
+ def add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil, reflect_file_system_structure = false)
217
+ file_accessors.flat_map do |file_accessor|
218
+ paths = file_accessor.send(file_accessor_key)
219
+ paths = allowable_project_paths(paths)
220
+ next [] if paths.empty?
221
+
222
+ pod_name = file_accessor.spec.name
223
+ preserve_pod_file_structure_flag = (sandbox.local?(pod_name) || preserve_pod_file_structure) && reflect_file_system_structure
224
+ base_path = preserve_pod_file_structure_flag ? common_path(paths) : nil
225
+ actual_group_key = preserve_pod_file_structure_flag ? nil : group_key
226
+ group = pods_project.group_for_spec(pod_name, actual_group_key)
227
+ paths.map do |path|
228
+ pods_project.add_file_reference(path, group, preserve_pod_file_structure_flag, base_path)
229
+ end
230
+ end
231
+ end
232
+
233
+ # Filters a list of paths down to those paths which can be added to
234
+ # the Xcode project. Some paths are intermediates and only their children
235
+ # should be added, while some paths are treated as bundles and their
236
+ # children should not be added directly.
237
+ #
238
+ # @param [Array<Pathname>] paths
239
+ # The paths to files or directories on disk.
240
+ #
241
+ # @return [Array<Pathname>] The paths which can be added to the Xcode project
242
+ #
243
+ def allowable_project_paths(paths)
244
+ lproj_paths = Set.new
245
+ lproj_paths_with_files = Set.new
246
+ allowable_paths = paths.select do |path|
247
+ path_str = path.to_s
248
+
249
+ # We add the directory for a Core Data model, but not the items in it.
250
+ next if path_str =~ /.*\.xcdatamodeld\/.+/i
251
+
252
+ # We add the directory for a Core Data migration mapping, but not the items in it.
253
+ next if path_str =~ /.*\.xcmappingmodel\/.+/i
254
+
255
+ # We add the directory for an asset catalog, but not the items in it.
256
+ next if path_str =~ /.*\.xcassets\/.+/i
257
+
258
+ if path_str =~ /\.lproj(\/|$)/i
259
+ # If the element is an .lproj directory then save it and potentially
260
+ # add it later if we don't find any contained items.
261
+ if path_str =~ /\.lproj$/i && path.directory?
262
+ lproj_paths << path
263
+ next
264
+ end
265
+
266
+ # Collect the paths for the .lproj directories that contain files.
267
+ lproj_path = /(^.*\.lproj)\/.*/i.match(path_str)[1]
268
+ lproj_paths_with_files << Pathname(lproj_path)
269
+
270
+ # Directories nested within an .lproj directory are added as file
271
+ # system references so their contained items are not added directly.
272
+ next if path.dirname.dirname == lproj_path
273
+ end
274
+
275
+ true
276
+ end
277
+
278
+ # Only add the path for the .lproj directories that do not have anything
279
+ # within them added as well. This generally happens if the glob within the
280
+ # resources directory was not a recursive glob.
281
+ allowable_paths + lproj_paths.subtract(lproj_paths_with_files).to_a
282
+ end
283
+
284
+ # Returns a Pathname of the nearest parent from which all the given paths descend.
285
+ # Converts each Pathname to a list of path components and finds the longest common prefix
286
+ #
287
+ # @param [Array<Pathname>] paths
288
+ # The paths to files or directories on disk. Must be absolute paths
289
+ #
290
+ # @return [Pathname] Pathname of the nearest parent shared by paths, or nil if none exists
291
+ #
292
+ def common_path(paths)
293
+ return nil if paths.empty?
294
+ strs = paths.map do |path|
295
+ unless path.absolute?
296
+ raise ArgumentError, "Paths must be absolute #{path}"
297
+ end
298
+ path.dirname.to_s
299
+ end
300
+ min, max = strs.minmax
301
+ min = min.split('/')
302
+ max = max.split('/')
303
+ idx = min.size.times { |i| break i if min[i] != max[i] }
304
+ result = Pathname.new(min[0...idx].join('/'))
305
+ # Don't consider "/" a common path
306
+ return result unless result.to_s == '' || result.to_s == '/'
307
+ end
308
+
309
+ # Adds the known localization regions to the root of the project
310
+ #
311
+ # @param [Array<PBXFileReferences>] file_references the resource file references
312
+ #
313
+ def add_known_regions(file_references)
314
+ pattern = LOCALIZATION_REGION_FILEPATTERN_REGEX
315
+ regions = file_references.map do |ref|
316
+ if (match = ref.path.to_s.match(pattern))
317
+ match[:region]
318
+ end
319
+ end.compact
320
+
321
+ pods_project.root_object.known_regions = (pods_project.root_object.known_regions | regions).sort
322
+ end
323
+
324
+ #-----------------------------------------------------------------------#
325
+ end
326
+ end
327
+ end
328
+ end
329
+ end
@@ -0,0 +1,195 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ # Wires up the dependencies between targets from the target installation results
5
+ #
6
+ class PodTargetDependencyInstaller
7
+ require 'cocoapods/native_target_extension.rb'
8
+
9
+ # @return [Sandbox] The sandbox used for this installation.
10
+ #
11
+ attr_reader :sandbox
12
+
13
+ # @return [TargetInstallationResults] The target installation results for pod targets.
14
+ #
15
+ attr_reader :pod_target_installation_results
16
+
17
+ # @return [ProjectMetadataCache] The metadata cache for targets.
18
+ #
19
+ attr_reader :metadata_cache
20
+
21
+ # Initialize a new instance.
22
+ #
23
+ # @param [Sandbox] sandbox @see #sandbox
24
+ # @param [TargetInstallationResults] pod_target_installation_results @see #pod_target_installation_results
25
+ # @param [ProjectMetadataCache] metadata_cache @see #metadata_cache
26
+ #
27
+ def initialize(sandbox, pod_target_installation_results, metadata_cache)
28
+ @sandbox = sandbox
29
+ @pod_target_installation_results = pod_target_installation_results
30
+ @metadata_cache = metadata_cache
31
+ end
32
+
33
+ def install!
34
+ # Wire up pod targets
35
+ pod_target_installation_results.values.each do |pod_target_installation_result|
36
+ pod_target = pod_target_installation_result.target
37
+ native_target = pod_target_installation_result.native_target
38
+ project = native_target.project
39
+
40
+ # First, wire up all resource bundles.
41
+ wire_resource_bundle_targets(pod_target_installation_result.resource_bundle_targets,
42
+ native_target, pod_target)
43
+ # Wire up all dependencies to this pod target, if any.
44
+ wire_target_dependencies(pod_target, native_target, project, pod_target_installation_results,
45
+ metadata_cache)
46
+
47
+ # Wire up test native targets.
48
+ unless pod_target_installation_result.test_native_targets.empty?
49
+ wire_test_native_targets(pod_target, pod_target_installation_result, pod_target_installation_results,
50
+ project, metadata_cache)
51
+ end
52
+
53
+ # Wire up app native targets.
54
+ unless pod_target_installation_result.app_native_targets.empty?
55
+ wire_app_native_targets(pod_target, pod_target_installation_result, pod_target_installation_results,
56
+ project, metadata_cache)
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def wire_resource_bundle_targets(resource_bundle_targets, native_target, pod_target)
64
+ resource_bundle_targets.each do |resource_bundle_target|
65
+ native_target.add_dependency(resource_bundle_target)
66
+ if pod_target.build_as_dynamic_framework? && pod_target.should_build?
67
+ native_target.add_resources([resource_bundle_target.product_reference])
68
+ end
69
+ end
70
+ end
71
+
72
+ def wire_target_dependencies(pod_target, native_target, project, pod_target_installation_results, metadata_cache)
73
+ dependent_targets = pod_target.dependent_targets
74
+ dependent_targets.each do |dependent_target|
75
+ is_local = sandbox.local?(dependent_target.pod_name)
76
+ if installation_result = pod_target_installation_results[dependent_target.name]
77
+ dependent_project = installation_result.native_target.project
78
+ if dependent_project != project
79
+ project.add_pod_subproject(dependent_project, is_local)
80
+ end
81
+ native_target.add_dependency(installation_result.native_target)
82
+ else
83
+ # Hit the cache
84
+ cached_dependency = metadata_cache.target_label_by_metadata[dependent_target.label]
85
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
86
+ Project.add_cached_dependency(sandbox, native_target, cached_dependency)
87
+ end
88
+ end
89
+ end
90
+
91
+ def wire_test_native_targets(pod_target, installation_result, pod_target_installation_results, project, metadata_cache)
92
+ installation_result.test_specs_by_native_target.each do |test_native_target, test_spec|
93
+ resource_bundle_native_targets = installation_result.test_resource_bundle_targets[test_spec.name] || []
94
+ resource_bundle_native_targets.each do |test_resource_bundle_target|
95
+ test_native_target.add_dependency(test_resource_bundle_target)
96
+ end
97
+
98
+ test_dependent_targets = pod_target.test_dependent_targets_by_spec_name.fetch(test_spec.name, []).+([pod_target]).uniq
99
+ test_dependent_targets.each do |test_dependent_target|
100
+ is_local = sandbox.local?(test_dependent_target.pod_name)
101
+ if dependency_installation_result = pod_target_installation_results[test_dependent_target.name]
102
+ dependent_test_project = dependency_installation_result.native_target.project
103
+ if dependent_test_project != project
104
+ project.add_pod_subproject(dependent_test_project, is_local)
105
+ end
106
+ test_native_target.add_dependency(dependency_installation_result.native_target)
107
+ else
108
+ # Hit the cache
109
+ cached_dependency = metadata_cache.target_label_by_metadata[test_dependent_target.label]
110
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
111
+ Project.add_cached_dependency(sandbox, test_native_target, cached_dependency)
112
+ end
113
+ end
114
+
115
+ if app_host_target_label = pod_target.app_host_target_label(test_spec)
116
+ app_host_pod_target_label, app_host_target_label = *app_host_target_label
117
+ wire_test_native_target_app_host(test_native_target, pod_target, pod_target_installation_results, project, metadata_cache, app_host_pod_target_label, app_host_target_label)
118
+ end
119
+ end
120
+ end
121
+
122
+ def wire_test_native_target_app_host(test_native_target, pod_target, pod_target_installation_results, project, metadata_cache, app_host_pod_target_label, app_host_target_label)
123
+ if dependency_installation_result = pod_target_installation_results[app_host_pod_target_label]
124
+ unless app_native_target = dependency_installation_result.app_host_target_labelled(app_host_target_label)
125
+ raise Informative, "Did not find target with label #{app_host_target_label} in the set of targets installed for #{app_host_pod_target_label}."
126
+ end
127
+
128
+ dependent_test_project = app_native_target.project
129
+ if dependent_test_project != project
130
+ project.add_subproject_reference(dependent_test_project, project.dependencies_group)
131
+ end
132
+
133
+ app_host_target_names = app_native_target.resolved_build_setting('PRODUCT_NAME', true)
134
+ test_native_target.build_configurations.each do |configuration|
135
+ app_host_target_name = app_host_target_names[configuration.name] || target.name
136
+ case test_native_target.symbol_type
137
+ when :unit_test_bundle
138
+ test_host = "$(BUILT_PRODUCTS_DIR)/#{app_host_target_name}.app/"
139
+ test_host << 'Contents/MacOS/' if pod_target.platform == :osx
140
+ test_host << app_host_target_name.to_s
141
+ configuration.build_settings['BUNDLE_LOADER'] = '$(TEST_HOST)'
142
+ configuration.build_settings['TEST_HOST'] = test_host
143
+ when :ui_test_bundle
144
+ configuration.build_settings['TEST_TARGET_NAME'] = app_host_target_name
145
+ end
146
+ end
147
+ target_attributes = project.root_object.attributes['TargetAttributes'] || {}
148
+ target_attributes[test_native_target.uuid.to_s] = { 'TestTargetID' => app_native_target.uuid.to_s }
149
+ project.root_object.attributes['TargetAttributes'] = target_attributes
150
+ test_native_target.add_dependency(app_native_target)
151
+ elsif cached_dependency = metadata_cache.target_label_by_metadata[app_host_target_label]
152
+ # Hit the cache
153
+ project.add_cached_subproject_reference(sandbox, cached_dependency, project.dependencies_group)
154
+ Project.add_cached_dependency(sandbox, test_native_target, cached_dependency)
155
+ else
156
+ raise "Expected to either have an installation or cache result for #{app_host_target_label} (from pod #{app_host_pod_target_label}) " \
157
+ "for target #{test_native_target.name} in project #{project.project_name}"
158
+ end
159
+ end
160
+
161
+ def wire_app_native_targets(pod_target, installation_result, pod_target_installation_results, project, metadata_cache)
162
+ installation_result.app_specs_by_native_target.each do |app_native_target, app_spec|
163
+ resource_bundle_native_targets = installation_result.app_resource_bundle_targets[app_spec.name] || []
164
+ resource_bundle_native_targets.each do |app_resource_bundle_target|
165
+ app_native_target.add_dependency(app_resource_bundle_target)
166
+ end
167
+
168
+ app_dependent_targets = pod_target.app_dependent_targets_by_spec_name.fetch(app_spec.name, []).unshift(pod_target).uniq
169
+ app_dependent_targets.each do |app_dependent_target|
170
+ is_local = sandbox.local?(app_dependent_target.pod_name)
171
+ if dependency_installation_result = pod_target_installation_results[app_dependent_target.name]
172
+ resource_bundle_native_targets = dependency_installation_result.app_resource_bundle_targets[app_spec.name]
173
+ unless resource_bundle_native_targets.nil?
174
+ resource_bundle_native_targets.each do |app_resource_bundle_target|
175
+ app_native_target.add_dependency(app_resource_bundle_target)
176
+ end
177
+ end
178
+ dependency_project = dependency_installation_result.native_target.project
179
+ if dependency_project != project
180
+ project.add_pod_subproject(dependency_project, is_local)
181
+ end
182
+ app_native_target.add_dependency(dependency_installation_result.native_target)
183
+ else
184
+ # Hit the cache
185
+ cached_dependency = metadata_cache.target_label_by_metadata[app_dependent_target.label]
186
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
187
+ Project.add_cached_dependency(sandbox, app_native_target, cached_dependency)
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end