pod-builder 2.0.0.beta.24 ā†’ 2.0.0.beta.29

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.
@@ -10,7 +10,9 @@ module PodBuilder
10
10
  installer, analyzer = Analyze.installer_at(PodBuilder::basepath, false)
11
11
  all_buildable_items = Analyze.podfile_items(installer, analyzer)
12
12
 
13
- Podspec::generate(all_buildable_items, analyzer)
13
+ install_using_frameworks = Podfile::install_using_frameworks(analyzer)
14
+
15
+ Podspec::generate(all_buildable_items, analyzer, install_using_frameworks)
14
16
 
15
17
  puts "\n\nšŸŽ‰ done!\n".green
16
18
  return 0
@@ -22,17 +22,8 @@ module PodBuilder
22
22
  FileUtils.mkdir_p("#{OPTIONS[:prebuild_path]}/.pod_builder")
23
23
  FileUtils.touch("#{OPTIONS[:prebuild_path]}/.pod_builder/pod_builder")
24
24
 
25
- source_path_rel_path = "Sources"
26
- development_pods_config_rel_path = Configuration.dev_pods_configuration_filename
27
-
28
- git_ignores = ["Pods/",
29
- "*.xcworkspace",
30
- "*.xcodeproj",
31
- "Podfile.lock",
32
- source_path_rel_path,
33
- development_pods_config_rel_path]
34
-
35
- File.write("#{OPTIONS[:prebuild_path]}/.gitignore", git_ignores.join("\n"))
25
+ write_gitignore
26
+ write_gitattributes
36
27
 
37
28
  project_podfile_path = PodBuilder::project_path("Podfile")
38
29
  prebuilt_podfile_path = File.join(OPTIONS[:prebuild_path], "Podfile")
@@ -61,6 +52,27 @@ module PodBuilder
61
52
 
62
53
  private
63
54
 
55
+ def self.write_gitignore
56
+ source_path_rel_path = "Sources"
57
+ development_pods_config_rel_path = Configuration.dev_pods_configuration_filename
58
+
59
+ git_ignores = ["Pods/",
60
+ "*.xcworkspace",
61
+ "*.xcodeproj",
62
+ "Podfile.lock",
63
+ Configuration.lldbinit_name,
64
+ source_path_rel_path,
65
+ development_pods_config_rel_path]
66
+
67
+ File.write("#{OPTIONS[:prebuild_path]}/.gitignore", git_ignores.join("\n"))
68
+ end
69
+
70
+ def self.write_gitattributes
71
+ git_attributes = ["#{Configuration.prebuilt_info_filename} binary"]
72
+
73
+ File.write("#{OPTIONS[:prebuild_path]}/.gitattributes", git_attributes.join("\n"))
74
+ end
75
+
64
76
  def self.podfile_path_transform(path)
65
77
  use_absolute_paths = false
66
78
  podfile_path = File.join(OPTIONS[:prebuild_path], "Podfile")
@@ -22,12 +22,12 @@ module PodBuilder
22
22
  framework_files.each do |path|
23
23
  rel_path = Pathname.new(path).relative_path_from(Pathname.new(base_path)).to_s
24
24
 
25
- if podfile_spec = podfile_items.detect { |x| x.prebuilt_rel_path == rel_path }
25
+ if podfile_spec = podfile_items.detect { |x| "#{x.root_name}/#{x.prebuilt_rel_path}" == rel_path }
26
26
  update_repo(podfile_spec)
27
27
  end
28
28
  end
29
29
 
30
- Command::Clean::clean_sources(podspec_names)
30
+ Clean::install_sources(podfile_items)
31
31
 
32
32
  ARGV << PodBuilder::basepath("Sources")
33
33
 
@@ -17,13 +17,30 @@ module PodBuilder
17
17
  DEFAULT_SPEC_OVERRIDE = {
18
18
  "Google-Mobile-Ads-SDK" => {
19
19
  "module_name": "GoogleMobileAds"
20
+ },
21
+ "React-jsiexecutor" => {
22
+ "remove_module_maps": ["glog"]
23
+ },
24
+ "React-Core" => {
25
+ "remove_module_maps": ["glog"]
26
+ },
27
+ "React-Core/Default" => {
28
+ "public_headers": "React/**/*.{h}"
29
+ },
30
+ "React-jsi" => {
31
+ "remove_module_maps": ["glog"]
32
+ },
33
+ "React-cxxreact" => {
34
+ "remove_module_maps": ["glog"]
35
+ },
36
+ "Folly" => {
37
+ "remove_module_maps": ["glog"]
20
38
  }
21
39
  }.freeze
22
- DEFAULT_SKIP_PODS = ["GoogleMaps", "Flipper", "FlipperKit", "Flipper-DoubleConversion", "Flipper-Folly", "Flipper-Glog", "Flipper-PeerTalk", "Flipper-RSocket", "React-cxxreact"]
23
- DEFAULT_FORCE_PREBUILD_PODS = ["Firebase", "GoogleTagManager"]
40
+ DEFAULT_SKIP_PODS = ["GoogleMaps"]
41
+ DEFAULT_FORCE_PREBUILD_PODS = ["GoogleTagManager"]
24
42
  DEFAULT_BUILD_SYSTEM = "Legacy".freeze # either Latest (New build system) or Legacy (Standard build system)
25
43
  DEFAULT_LIBRARY_EVOLUTION_SUPPORT = false
26
- MIN_LFS_SIZE_KB = 256.freeze
27
44
  DEFAULT_PLATFORMS = ["iphoneos", "iphonesimulator", "appletvos", "appletvsimulator"].freeze
28
45
  DEFAULT_BUILD_FOR_APPLE_SILICON = false
29
46
  DEFAULT_BUILD_USING_REPO_PATHS = false
@@ -31,7 +48,6 @@ module PodBuilder
31
48
  private_constant :DEFAULT_BUILD_SETTINGS
32
49
  private_constant :DEFAULT_BUILD_SYSTEM
33
50
  private_constant :DEFAULT_LIBRARY_EVOLUTION_SUPPORT
34
- private_constant :MIN_LFS_SIZE_KB
35
51
 
36
52
  class <<self
37
53
  attr_accessor :allow_building_development_pods
@@ -51,9 +67,6 @@ module PodBuilder
51
67
  attr_accessor :build_path
52
68
  attr_accessor :configuration_filename
53
69
  attr_accessor :dev_pods_configuration_filename
54
- attr_accessor :lfs_min_file_size
55
- attr_accessor :lfs_update_gitattributes
56
- attr_accessor :lfs_include_pods_folder
57
70
  attr_accessor :project_name
58
71
  attr_accessor :restore_enabled
59
72
  attr_accessor :prebuilt_info_filename
@@ -65,6 +78,7 @@ module PodBuilder
65
78
  attr_accessor :build_for_apple_silicon
66
79
  attr_accessor :build_using_repo_paths
67
80
  attr_accessor :react_native_project
81
+ attr_accessor :lldbinit_name
68
82
  end
69
83
 
70
84
  @allow_building_development_pods = false
@@ -84,14 +98,12 @@ module PodBuilder
84
98
  @build_path = build_base_path
85
99
  @configuration_filename = "PodBuilder.json".freeze
86
100
  @dev_pods_configuration_filename = "PodBuilderDevPodsPaths.json".freeze
87
- @lfs_min_file_size = MIN_LFS_SIZE_KB
88
- @lfs_update_gitattributes = false
89
- @lfs_include_pods_folder = false
90
101
  @project_name = ""
91
102
  @restore_enabled = true
92
103
  @prebuilt_info_filename = "PodBuilder.json"
93
104
  @lockfile_name = "PodBuilder.lock"
94
105
  @lockfile_path = "/tmp/#{lockfile_name}"
106
+ @lldbinit_name = "lldbinit".freeze
95
107
 
96
108
  @use_bundler = false
97
109
  @deterministic_build = false
@@ -173,16 +185,6 @@ module PodBuilder
173
185
  Configuration.subspecs_to_split = value
174
186
  end
175
187
  end
176
- if value = json["lfs_update_gitattributes"]
177
- if [TrueClass, FalseClass].include?(value.class)
178
- Configuration.lfs_update_gitattributes = value
179
- end
180
- end
181
- if value = json["lfs_include_pods_folder"]
182
- if [TrueClass, FalseClass].include?(value.class)
183
- Configuration.lfs_include_pods_folder = value
184
- end
185
- end
186
188
  if value = json["project_name"]
187
189
  if value.is_a?(String) && value.length > 0
188
190
  Configuration.project_name = value
@@ -262,8 +264,6 @@ module PodBuilder
262
264
  config["library_evolution_support"] = Configuration.library_evolution_support
263
265
  config["license_filename"] = Configuration.license_filename
264
266
  config["subspecs_to_split"] = Configuration.subspecs_to_split
265
- config["lfs_update_gitattributes"] = Configuration.lfs_update_gitattributes
266
- config["lfs_include_pods_folder"] = Configuration.lfs_include_pods_folder
267
267
  config["restore_enabled"] = Configuration.restore_enabled
268
268
  config["allow_building_development_pods"] = Configuration.allow_building_development_pods
269
269
  config["use_bundler"] = Configuration.use_bundler
@@ -10,29 +10,29 @@ require 'highline/import'
10
10
  # - https://github.com/leavez/cocoapods-binary/issues/50
11
11
  begin
12
12
  require 'cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb'
13
-
13
+
14
14
  class Pod::Specification
15
15
  Pod::Specification.singleton_class.send(:alias_method, :swz_from_hash, :from_hash)
16
16
  Pod::Specification.singleton_class.send(:alias_method, :swz_from_string, :from_string)
17
-
17
+
18
18
  def self.from_string(*args)
19
19
  spec = swz_from_string(*args)
20
-
20
+
21
21
  if overrides = PodBuilder::Configuration.spec_overrides[spec.name]
22
22
  overrides.each do |k, v|
23
23
  spec.attributes_hash[k] = v
24
24
  end
25
25
  end
26
-
26
+
27
27
  spec
28
28
  end
29
29
  end
30
-
30
+
31
31
  class Pod::Target
32
32
  attr_accessor :mock_dynamic_framework
33
-
33
+
34
34
  alias_method :swz_build_type, :build_type
35
-
35
+
36
36
  def build_type
37
37
  if mock_dynamic_framework == true
38
38
  if defined?(Pod::BuildType) # CocoaPods 1.9 and later
@@ -47,23 +47,23 @@ begin
47
47
  end
48
48
  end
49
49
  end
50
-
50
+
51
51
  # Starting from CocoaPods 1.10.0 and later resources are no longer copied inside the .framework
52
52
  # when building static frameworks. While this is correct when using CP normally, for redistributable
53
53
  # frameworks we require resources to be shipped along the binary
54
54
  class Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller
55
55
  alias_method :swz_add_files_to_build_phases, :add_files_to_build_phases
56
-
56
+
57
57
  def add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
58
58
  target.mock_dynamic_framework = target.build_as_static_framework?
59
59
  swz_add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
60
60
  target.mock_dynamic_framework = false
61
61
  end
62
62
  end
63
-
63
+
64
64
  class Pod::Installer::Xcode::PodTargetDependencyInstaller
65
65
  alias_method :swz_wire_resource_bundle_targets, :wire_resource_bundle_targets
66
-
66
+
67
67
  def wire_resource_bundle_targets(resource_bundle_targets, native_target, pod_target)
68
68
  pod_target.mock_dynamic_framework = pod_target.build_as_static_framework?
69
69
  res = swz_wire_resource_bundle_targets(resource_bundle_targets, native_target, pod_target)
@@ -71,48 +71,110 @@ begin
71
71
  return res
72
72
  end
73
73
  end
74
+
75
+ class Pod::Target::BuildSettings
76
+ alias_method :swz_save_as, :save_as
77
+
78
+ @specs_remove_module_maps = Hash.new
79
+
80
+ class << self
81
+ attr_accessor :specs_remove_module_maps
82
+ end
83
+
84
+ def save_as(path)
85
+ Pod::Target::BuildSettings.specs_remove_module_maps.each do |root_name, module_maps_to_remove|
86
+ if target.name == root_name
87
+ module_maps_to_remove.each do |module_map_to_remove|
88
+ xcconfig.attributes["OTHER_CFLAGS"] = xcconfig.attributes["OTHER_CFLAGS"].gsub(/-fmodule-map-file=\S*#{module_map_to_remove}.modulemap.*?(\s|$)/, '')
89
+ end
90
+ end
91
+ end
92
+
93
+ swz_save_as(path)
94
+ end
95
+ end
74
96
  rescue LoadError
75
97
  # CocoaPods 1.6.2 or earlier
76
98
  end
77
99
 
78
100
  module PodBuilder
101
+ class InstallResult
102
+ # @return [Array<Hash>] The installed licenses
103
+ #
104
+ attr_reader :licenses
105
+
106
+ # @return [Hash] A hash containing the expected prebuilt_info filename and content
107
+ #
108
+ attr_reader :prebuilt_info
109
+
110
+ def initialize(licenses = [], prebuilt_info = Hash.new)
111
+ @licenses = licenses
112
+ @prebuilt_info = prebuilt_info
113
+ end
114
+
115
+ def +(obj)
116
+ merged_licenses = @licenses.dup + obj.licenses
117
+ merged_prebuilt_info = @prebuilt_info.dup
118
+
119
+ merged_prebuilt_info.each do |key, value|
120
+ if obj.prebuilt_info.has_key?(key)
121
+ specs = merged_prebuilt_info[key]["specs"] || []
122
+ specs += (obj.prebuilt_info[key]["specs"] || [])
123
+ merged_prebuilt_info[key]["specs"] = specs.uniq
124
+ end
125
+ end
126
+
127
+ merged_prebuilt_info = obj.prebuilt_info.merge(merged_prebuilt_info)
128
+
129
+ return InstallResult.new(merged_licenses, merged_prebuilt_info)
130
+ end
131
+
132
+ def write_prebuilt_info_files
133
+ prebuilt_info.each do |file_path, file_content|
134
+ File.write(file_path, JSON.pretty_generate(file_content))
135
+ end
136
+ end
137
+ end
138
+
79
139
  class Install
80
140
  # This method will generate prebuilt data by building from "/tmp/pod_builder/Podfile"
81
141
  def self.podfile(podfile_content, podfile_items, build_configuration)
82
142
  puts "Preparing build Podfile".yellow
83
-
143
+
84
144
  PodBuilder::safe_rm_rf(Configuration.build_path)
85
145
  FileUtils.mkdir_p(Configuration.build_path)
86
146
 
87
147
  init_git(Configuration.build_path) # this is needed to be able to call safe_rm_rf
88
-
148
+
89
149
  podfile_content = copy_development_pods_source_code(podfile_content, podfile_items)
90
-
150
+
91
151
  podfile_content = Podfile.update_path_entries(podfile_content, Install.method(:podfile_path_transform))
92
152
  podfile_content = Podfile.update_project_entries(podfile_content, Install.method(:podfile_path_transform))
93
153
  podfile_content = Podfile.update_require_entries(podfile_content, Install.method(:podfile_path_transform))
94
-
154
+
95
155
  podfile_path = File.join(Configuration.build_path, "Podfile")
96
156
  File.write(podfile_path, podfile_content)
97
-
157
+
98
158
  begin
99
159
  lock_file = "#{Configuration.build_path}/pod_builder.lock"
100
160
  FileUtils.touch(lock_file)
161
+
162
+ prebuilt_entries = use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
101
163
 
102
- use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
103
-
164
+ prepare_for_static_framework_workarounds(podfile_content, podfile_items)
165
+
104
166
  install
167
+
168
+ copy_prebuilt_items(podfile_items - prebuilt_entries)
105
169
 
106
- copy_prebuilt_items(podfile_items)
107
- add_prebuilt_info_file(podfile_items)
108
-
170
+ prebuilt_info = prebuilt_info(podfile_items)
109
171
  licenses = license_specifiers()
110
-
172
+
111
173
  if !OPTIONS.has_key?(:debug)
112
174
  PodBuilder::safe_rm_rf(Configuration.build_path)
113
175
  end
114
-
115
- return licenses
176
+
177
+ return InstallResult.new(licenses, prebuilt_info)
116
178
  rescue Exception => e
117
179
  if File.directory?("#{Configuration.build_path}/Pods/Pods.xcodeproj")
118
180
  if ENV['DEBUGGING']
@@ -124,89 +186,165 @@ module PodBuilder
124
186
  end
125
187
  end
126
188
  end
127
-
189
+
128
190
  raise e
129
191
  ensure
130
192
  FileUtils.rm(lock_file) if File.exist?(lock_file)
131
193
  end
132
194
  end
133
195
 
196
+ def self.prebuilt_info(podfile_items)
197
+ gitignored_files = PodBuilder::gitignoredfiles
198
+
199
+ swift_version = PodBuilder::system_swift_version
200
+
201
+ write_prebuilt_info_filename_gitattributes
202
+
203
+ ret = Hash.new
204
+ root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
205
+ root_names.each do |prebuilt_name|
206
+ path = PodBuilder::prebuiltpath(prebuilt_name)
207
+
208
+ unless File.directory?(path)
209
+ puts "Prebuilt items for #{prebuilt_name} not found".blue
210
+ next
211
+ end
212
+
213
+ unless podfile_item = podfile_items.detect { |t| t.name == prebuilt_name } || podfile_items.detect { |t| t.root_name == prebuilt_name }
214
+ puts "Prebuilt items for #{prebuilt_name} not found #2".blue
215
+ next
216
+ end
217
+
218
+ podbuilder_file = File.join(path, Configuration.prebuilt_info_filename)
219
+ entry = podfile_item.entry(true, false)
220
+ if Configuration.subspecs_to_split.include?(podfile_item.name)
221
+ entry.gsub!("'#{podfile_item.name}'", "'#{podfile_item.root_name}'")
222
+ end
223
+
224
+ data = {}
225
+ data["entry"] = entry
226
+ data["is_prebuilt"] = podfile_item.is_prebuilt
227
+ if Dir.glob(File.join(path, "#{podfile_item.prebuilt_rel_path}/Headers/*-Swift.h")).count > 0
228
+ data["swift_version"] = swift_version
229
+ end
230
+
231
+ specs = podfile_items.select { |x| x.module_name == podfile_item.module_name }
232
+ subspecs_deps = specs.map(&:dependency_names).flatten
233
+ subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{prebuilt_name}/") }
234
+ data["specs"] = (specs.map(&:name) + subspec_self_deps).uniq
235
+ data["is_static"] = podfile_item.is_static
236
+ data["original_compile_path"] = Pathname.new(Configuration.build_path).realpath.to_s
237
+ if hash = build_folder_hash(podfile_item, gitignored_files)
238
+ data["build_folder_hash"] = hash
239
+ end
240
+
241
+ ret.merge!({ podbuilder_file => data })
242
+ end
243
+
244
+ return ret
245
+ end
134
246
  private
135
247
 
248
+ def self.prepare_for_static_framework_workarounds(podfile_content, podfile_items)
249
+ unless podfile_content.include?("use_modular_headers!")
250
+ return
251
+ end
252
+
253
+ podfile_items.each do |podfile_item|
254
+ Pod::Target::BuildSettings.specs_remove_module_maps[podfile_item.root_name] = podfile_item.remove_module_maps
255
+ end
256
+ end
257
+
136
258
  def self.license_specifiers
137
259
  acknowledge_file = "#{Configuration.build_path}/Pods/Target Support Files/Pods-DummyTarget/Pods-DummyTarget-acknowledgements.plist"
138
260
  unless File.exist?(acknowledge_file)
139
261
  raise "\n\nLicense file not found".red
140
262
  end
141
-
263
+
142
264
  plist = CFPropertyList::List.new(:file => acknowledge_file)
143
265
  data = CFPropertyList.native_types(plist.value)
144
-
266
+
145
267
  return data["PreferenceSpecifiers"] || []
146
268
  end
147
-
269
+
148
270
  def self.copy_development_pods_source_code(podfile_content, podfile_items)
149
271
  if Configuration.build_using_repo_paths
150
272
  return podfile_content
151
273
  end
152
-
274
+
153
275
  # Development pods are normally built/integrated without moving files from their original paths.
154
276
  # It is important that CocoaPods compiles the files under Configuration.build_path in order that
155
277
  # DWARF debug info reference to this constant path. Doing otherwise breaks the assumptions that
156
- # makes the `update_lldbinit` command work.
278
+ # makes the `generate_lldbinit` command work.
157
279
  development_pods = podfile_items.select { |x| x.is_development_pod }
158
280
  development_pods.each do |podfile_item|
159
281
  destination_path = "#{Configuration.build_path}/Pods/#{podfile_item.name}"
160
282
  FileUtils.mkdir_p(destination_path)
161
-
283
+
162
284
  if Pathname.new(podfile_item.path).absolute?
163
285
  FileUtils.cp_r("#{podfile_item.path}/.", destination_path)
164
286
  else
165
287
  FileUtils.cp_r("#{PodBuilder::basepath(podfile_item.path)}/.", destination_path)
166
288
  end
167
-
289
+
168
290
  podfile_content.gsub!("'#{podfile_item.path}'", "'#{destination_path}'")
169
291
  end
170
-
292
+
171
293
  return podfile_content
172
294
  end
173
-
295
+
174
296
  def self.use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
175
- if OPTIONS.has_key?(:force_rebuild)
176
- return
177
- end
178
-
179
- download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
180
-
181
297
  podfile_content = File.read(podfile_path)
298
+
299
+ replaced_items = []
182
300
 
183
- gitignored_files = PodBuilder::gitignoredfiles
184
-
185
- # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
186
- items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
187
- items.each do |item|
188
- podspec_path = item.prebuilt_podspec_path
189
- if last_build_folder_hash = build_folder_hash_in_prebuilt_info_file(item)
190
- if last_build_folder_hash == build_folder_hash(item, gitignored_files)
191
- puts "No changes detected to '#{item.root_name}', will skip rebuild".blue
192
- podfile_items.select { |t| t.root_name == item.root_name }.each do |replace_item|
193
- replace_regex = "pod '#{Regexp.quote(replace_item.name)}', .*"
194
- replace_line_found = podfile_content =~ /#{replace_regex}/i
195
- raise "\n\nFailed finding pod entry for '#{replace_item.name}'".red unless replace_line_found
196
- podfile_content.gsub!(/#{replace_regex}/, replace_item.prebuilt_entry(true, true))
301
+ if OPTIONS.has_key?(:force_rebuild)
302
+ podfile_content.gsub!("%%%prebuilt_root_paths%%%", "{}")
303
+ else
304
+ download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
305
+
306
+ gitignored_files = PodBuilder::gitignoredfiles
307
+
308
+ prebuilt_root_paths = Hash.new
309
+
310
+ # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
311
+ items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
312
+ items.each do |item|
313
+ podspec_path = item.prebuilt_podspec_path
314
+ if last_build_folder_hash = build_folder_hash_in_prebuilt_info_file(item)
315
+ if last_build_folder_hash == build_folder_hash(item, gitignored_files)
316
+ if Configuration.subspecs_to_split.include?(item.name)
317
+ puts "No changes detected to '#{item.name}', will skip rebuild".blue
318
+ else
319
+ puts "No changes detected to '#{item.root_name}', will skip rebuild".blue
320
+ end
321
+ replaced_items.push(item)
322
+
323
+ podfile_items.select { |t| t.root_name == item.root_name }.each do |replace_item|
324
+ replace_regex = "pod '#{Regexp.quote(replace_item.name)}', .*"
325
+ replace_line_found = podfile_content =~ /#{replace_regex}/i
326
+ raise "\n\nFailed finding pod entry for '#{replace_item.name}'".red unless replace_line_found
327
+ podfile_content.gsub!(/#{replace_regex}/, replace_item.prebuilt_entry(true, true))
328
+
329
+ prebuilt_root_paths[replace_item.root_name] = PodBuilder::prebuiltpath
330
+ end
197
331
  end
198
332
  end
199
333
  end
334
+
335
+ podfile_content.gsub!("%%%prebuilt_root_paths%%%", prebuilt_root_paths.to_s)
200
336
  end
201
337
 
202
338
  File.write(podfile_path, podfile_content)
203
- end
204
339
 
340
+ return replaced_items
341
+ end
342
+
205
343
  def self.install
206
344
  puts "Prebuilding items".yellow
207
-
345
+
208
346
  CLAide::Command::PluginManager.load_plugins("cocoapods")
209
-
347
+
210
348
  Dir.chdir(Configuration.build_path) do
211
349
  config = Pod::Config.new()
212
350
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
@@ -214,21 +352,22 @@ module PodBuilder
214
352
  installer.update = false
215
353
 
216
354
  install_start_time = Time.now
355
+
217
356
  installer.install!
218
357
  install_time = Time.now - install_start_time
219
-
358
+
220
359
  puts "Build completed in #{install_time.to_i} seconds".blue
221
360
  end
222
361
  end
223
-
362
+
224
363
  def self.download
225
364
  puts "Downloading Pods source code".yellow
226
-
365
+
227
366
  CLAide::Command::PluginManager.load_plugins("cocoapods")
228
-
367
+
229
368
  Dir.chdir(Configuration.build_path) do
230
369
  Pod::UserInterface::config.silent = true
231
-
370
+
232
371
  config = Pod::Config.new()
233
372
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
234
373
  installer.repo_update = false
@@ -236,88 +375,92 @@ module PodBuilder
236
375
  installer.prepare
237
376
  installer.resolve_dependencies
238
377
  installer.download_dependencies
239
-
378
+
240
379
  Pod::UserInterface::config.silent = false
241
380
  end
242
381
  end
243
-
382
+
244
383
  def self.copy_prebuilt_items(podfile_items)
245
384
  FileUtils.mkdir_p(PodBuilder::prebuiltpath)
246
385
 
247
- root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
248
- root_names.each do |prebuilt_name|
249
- source_path = PodBuilder::buildpath_prebuiltpath(prebuilt_name)
250
- unless File.directory?(source_path)
251
- puts "Prebuilt items for #{prebuilt_name} not found".blue
252
- next
253
- end
254
- if Dir.empty?(source_path)
255
- next # When using prebuilt items we end up with empty folders
256
- end
386
+ non_prebuilt_items = podfile_items.reject(&:is_prebuilt)
257
387
 
258
- PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath(prebuilt_name))
259
- FileUtils.cp_r(source_path, PodBuilder::prebuiltpath)
260
- end
388
+ splitted_pods = non_prebuilt_items.map { |t| splitted_pod(t, podfile_items) }.flatten.uniq
389
+ splitted_pods_root_name = splitted_pods.map { |t| t.root_name }.uniq
261
390
 
262
- # Folder won't exist if no dSYM were generated (all static libs)
263
- if File.directory?(PodBuilder::buildpath_dsympath)
264
- FileUtils.mkdir_p(PodBuilder::dsympath)
265
- FileUtils.cp_r(PodBuilder::buildpath_dsympath, PodBuilder::basepath)
266
- end
267
- end
391
+ pod_names = non_prebuilt_items.reject { |t| splitted_pods_root_name.include?(t.root_name) }.map(&:root_name).uniq + splitted_pods.map(&:name)
268
392
 
269
- def self.add_prebuilt_info_file(podfile_items)
270
- gitignored_files = PodBuilder::gitignoredfiles
393
+ pod_names.reject! { |t|
394
+ folder_path = PodBuilder::buildpath_prebuiltpath(t)
395
+ File.directory?(folder_path) && Dir.empty?(folder_path) # When using prebuilt items we end up with empty folders
396
+ }
271
397
 
272
- swift_version = PodBuilder::system_swift_version
273
-
274
- root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
275
- root_names.each do |prebuilt_name|
276
- path = PodBuilder::prebuiltpath(prebuilt_name)
398
+ # Selectively delete destination folder.
399
+ # If it's a splitted spec we just need to wipe the Subspecs/#{pod_name}
400
+ # If it's not we need to wipe everything except the Subspecs folder
401
+ pod_names.each do |pod_name|
402
+ root_name = pod_name.split("/").first
403
+ if pod_name.include?("/") # Splitted pod
404
+ PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath("#{root_name}/Subspecs/#{pod_name.gsub("/", "_") }"))
405
+ else
406
+ items_to_delete = Dir.glob("#{PodBuilder::prebuiltpath(root_name)}/**/*")
407
+ items_to_delete.reject! { |t| t.include?(PodBuilder::prebuiltpath("#{root_name}/Subspecs")) }
277
408
 
278
- unless File.directory?(path)
279
- puts "Prebuilt items for #{prebuilt_name} not found".blue
280
- next
409
+ items_to_delete.each { |t| PodBuilder::safe_rm_rf(t) }
281
410
  end
411
+ end
282
412
 
283
- unless podfile_item = podfile_items.detect { |t| t.name == prebuilt_name } || podfile_items.detect { |t| t.root_name == prebuilt_name }
284
- puts "Prebuilt items for #{prebuilt_name} not found #2".blue
413
+ # Now copy
414
+ splitted_items_copied = false
415
+ pod_names.each do |pod_name|
416
+ root_name = pod_name.split("/").first
417
+ source_path = PodBuilder::buildpath_prebuiltpath(root_name)
418
+
419
+ unless File.directory?(source_path)
420
+ puts "Prebuilt items for #{pod_name} not found".blue
285
421
  next
286
422
  end
287
423
 
288
- podbuilder_file = File.join(path, Configuration.prebuilt_info_filename)
289
- entry = podfile_item.entry(true, false)
290
-
291
- data = {}
292
- data['entry'] = entry
293
- data['is_prebuilt'] = podfile_item.is_prebuilt
294
- if Dir.glob(File.join(path, "#{podfile_item.module_name}/Headers/*-Swift.h")).count > 0
295
- data['swift_version'] = swift_version
424
+ if Configuration.subspecs_to_split.include?(pod_name)
425
+ destination_folder = PodBuilder::prebuiltpath("#{root_name}/Subspecs/#{pod_name.gsub("/", "_") }")
426
+ FileUtils.mkdir_p(destination_folder)
427
+ unless splitted_items_copied
428
+ FileUtils.cp_r("#{source_path}/.", destination_folder)
429
+ splitted_items_copied = true
430
+ end
431
+ else
432
+ destination_folder = PodBuilder::prebuiltpath(root_name)
433
+ FileUtils.mkdir_p(destination_folder)
434
+ FileUtils.cp_r("#{source_path}/.", destination_folder)
296
435
  end
297
-
298
- specs = podfile_items.select { |x| x.module_name == podfile_item.module_name }
299
- subspecs_deps = specs.map(&:dependency_names).flatten
300
- subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{prebuilt_name}/") }
301
- data['specs'] = (specs.map(&:name) + subspec_self_deps).uniq
302
- data['is_static'] = podfile_item.is_static
303
- data['original_compile_path'] = Pathname.new(Configuration.build_path).realpath.to_s
304
- data['build_folder_hash'] = build_folder_hash(podfile_item, gitignored_files)
305
-
306
- File.write(podbuilder_file, JSON.pretty_generate(data))
436
+ end
437
+
438
+ # Folder won't exist if no dSYM were generated (all static libs)
439
+ if File.directory?(PodBuilder::buildpath_dsympath)
440
+ FileUtils.mkdir_p(PodBuilder::dsympath)
441
+ FileUtils.cp_r(PodBuilder::buildpath_dsympath, PodBuilder::basepath)
307
442
  end
308
443
  end
309
444
 
445
+ def self.write_prebuilt_info_filename_gitattributes
446
+ gitattributes_path = PodBuilder::basepath(".gitattributes")
447
+ expected_attributes = ["#{Configuration.configuration_filename} binary"].join
448
+ unless File.exists?(gitattributes_path) && File.read(gitattributes_path).include?(expected_attributes)
449
+ File.write(gitattributes_path, expected_attributes, mode: 'a')
450
+ end
451
+ end
452
+
310
453
  def self.init_git(path)
311
454
  current_dir = Dir.pwd
312
-
455
+
313
456
  Dir.chdir(path)
314
457
  system("git init")
315
458
  Dir.chdir(current_dir)
316
459
  end
317
-
460
+
318
461
  def self.build_folder_hash_in_prebuilt_info_file(podfile_item)
319
462
  prebuilt_info_path = PodBuilder::prebuiltpath(File.join(podfile_item.root_name, Configuration.prebuilt_info_filename))
320
-
463
+
321
464
  if File.exist?(prebuilt_info_path)
322
465
  data = JSON.parse(File.read(prebuilt_info_path))
323
466
  return data['build_folder_hash']
@@ -325,7 +468,7 @@ module PodBuilder
325
468
  return nil
326
469
  end
327
470
  end
328
-
471
+
329
472
  def self.build_folder_hash(podfile_item, exclude_files)
330
473
  if podfile_item.is_development_pod
331
474
  if Pathname.new(podfile_item.path).absolute?
@@ -333,7 +476,7 @@ module PodBuilder
333
476
  else
334
477
  item_path = PodBuilder::basepath(podfile_item.path)
335
478
  end
336
-
479
+
337
480
  rootpath = PodBuilder::git_rootpath
338
481
  file_hashes = []
339
482
  Dir.glob("#{item_path}/**/*", File::FNM_DOTMATCH) do |path|
@@ -345,16 +488,18 @@ module PodBuilder
345
488
  rel_path = path.gsub(rootpath, "")[1..]
346
489
  unless exclude_files.include?(rel_path)
347
490
  file_hashes.push(Digest::MD5.hexdigest(File.read(path)))
348
- else
349
- puts path
350
491
  end
351
492
  end
352
-
493
+
353
494
  return Digest::MD5.hexdigest(file_hashes.join)
354
495
  else
355
496
  # Pod folder might be under .gitignore
356
497
  item_path = "#{Configuration.build_path}/Pods/#{podfile_item.root_name}"
357
- return `find '#{item_path}' -type f -print0 | sort -z | xargs -0 shasum | shasum | cut -d' ' -f1`.strip()
498
+ if File.directory?(item_path)
499
+ return `find '#{item_path}' -type f -print0 | sort -z | xargs -0 shasum | shasum | cut -d' ' -f1`.strip()
500
+ else
501
+ return nil
502
+ end
358
503
  end
359
504
  end
360
505
 
@@ -365,17 +510,21 @@ module PodBuilder
365
510
  use_absolute_paths = true
366
511
  podfile_path = File.join(Configuration.build_path, "Podfile")
367
512
  original_basepath = PodBuilder::basepath
368
-
513
+
369
514
  podfile_base_path = Pathname.new(File.dirname(podfile_path))
370
-
515
+
371
516
  original_path = Pathname.new(File.join(original_basepath, path))
372
517
  replace_path = original_path.relative_path_from(podfile_base_path)
373
518
  if use_absolute_paths
374
519
  replace_path = replace_path.expand_path(podfile_base_path)
375
520
  end
376
-
521
+
377
522
  return replace_path
378
523
  end
379
- end
524
+ end
525
+
526
+ def self.splitted_pod(podfile_item, podfile_items)
527
+ return podfile_items.select { |t| t.root_name == podfile_item.root_name && Configuration.subspecs_to_split.include?(t.name) }
528
+ end
380
529
  end
381
530
  end