pod-builder 2.0.0.beta.25 → 2.0.0.beta.30

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
@@ -45,15 +61,11 @@ module PodBuilder
45
61
  attr_accessor :skip_pods
46
62
  attr_accessor :force_prebuild_pods
47
63
  attr_accessor :license_filename
48
- attr_accessor :subspecs_to_split
49
64
  attr_accessor :development_pods_paths
50
65
  attr_accessor :build_base_path
51
66
  attr_accessor :build_path
52
67
  attr_accessor :configuration_filename
53
68
  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
69
  attr_accessor :project_name
58
70
  attr_accessor :restore_enabled
59
71
  attr_accessor :prebuilt_info_filename
@@ -65,6 +77,7 @@ module PodBuilder
65
77
  attr_accessor :build_for_apple_silicon
66
78
  attr_accessor :build_using_repo_paths
67
79
  attr_accessor :react_native_project
80
+ attr_accessor :lldbinit_name
68
81
  end
69
82
 
70
83
  @allow_building_development_pods = false
@@ -78,20 +91,17 @@ module PodBuilder
78
91
  @skip_pods = DEFAULT_SKIP_PODS
79
92
  @force_prebuild_pods = DEFAULT_FORCE_PREBUILD_PODS
80
93
  @license_filename = "Pods-acknowledgements"
81
- @subspecs_to_split = []
82
94
  @development_pods_paths = []
83
95
  @build_base_path = "/tmp/pod_builder".freeze
84
96
  @build_path = build_base_path
85
97
  @configuration_filename = "PodBuilder.json".freeze
86
98
  @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
99
  @project_name = ""
91
100
  @restore_enabled = true
92
101
  @prebuilt_info_filename = "PodBuilder.json"
93
102
  @lockfile_name = "PodBuilder.lock"
94
103
  @lockfile_path = "/tmp/#{lockfile_name}"
104
+ @lldbinit_name = "lldbinit".freeze
95
105
 
96
106
  @use_bundler = false
97
107
  @deterministic_build = false
@@ -168,21 +178,6 @@ module PodBuilder
168
178
  Configuration.license_filename = value
169
179
  end
170
180
  end
171
- if value = json["subspecs_to_split"]
172
- if value.is_a?(Array) && value.count > 0
173
- Configuration.subspecs_to_split = value
174
- end
175
- 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
181
  if value = json["project_name"]
187
182
  if value.is_a?(String) && value.length > 0
188
183
  Configuration.project_name = value
@@ -261,9 +256,6 @@ module PodBuilder
261
256
  config["build_system"] = Configuration.build_system
262
257
  config["library_evolution_support"] = Configuration.library_evolution_support
263
258
  config["license_filename"] = Configuration.license_filename
264
- 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
259
  config["restore_enabled"] = Configuration.restore_enabled
268
260
  config["allow_building_development_pods"] = Configuration.allow_building_development_pods
269
261
  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,142 +71,274 @@ 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']
119
181
  system("xed #{Configuration.build_path}/Pods")
120
- else
182
+ elsif !OPTIONS.has_key?(:no_stdin_available)
121
183
  confirm = ask("\n\nOh no! Something went wrong during prebuild phase! Do you want to open the prebuild project to debug the error, you will need to add and run the Pods-Dummy scheme? [Y/N] ".red) { |yn| yn.limit = 1, yn.validate = /[yn]/i }
122
184
  if confirm.downcase == 'y'
123
185
  system("xed #{Configuration.build_path}/Pods")
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
+
221
+ data = {}
222
+ data["entry"] = entry
223
+ data["is_prebuilt"] = podfile_item.is_prebuilt
224
+ if Dir.glob(File.join(path, "#{podfile_item.prebuilt_rel_path}/Headers/*-Swift.h")).count > 0
225
+ data["swift_version"] = swift_version
226
+ end
227
+
228
+ specs = podfile_items.select { |x| x.module_name == podfile_item.module_name }
229
+ subspecs_deps = specs.map(&:dependency_names).flatten
230
+ subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{prebuilt_name}/") }
231
+ data["specs"] = (specs.map(&:name) + subspec_self_deps).uniq
232
+ data["is_static"] = podfile_item.is_static
233
+ data["original_compile_path"] = Pathname.new(Configuration.build_path).realpath.to_s
234
+ if hash = build_folder_hash(podfile_item, gitignored_files)
235
+ data["build_folder_hash"] = hash
236
+ end
237
+
238
+ ret.merge!({ podbuilder_file => data })
239
+ end
240
+
241
+ return ret
242
+ end
134
243
  private
135
244
 
245
+ def self.prepare_for_static_framework_workarounds(podfile_content, podfile_items)
246
+ unless podfile_content.include?("use_modular_headers!")
247
+ return
248
+ end
249
+
250
+ podfile_items.each do |podfile_item|
251
+ Pod::Target::BuildSettings.specs_remove_module_maps[podfile_item.root_name] = podfile_item.remove_module_maps
252
+ end
253
+ end
254
+
136
255
  def self.license_specifiers
137
256
  acknowledge_file = "#{Configuration.build_path}/Pods/Target Support Files/Pods-DummyTarget/Pods-DummyTarget-acknowledgements.plist"
138
257
  unless File.exist?(acknowledge_file)
139
258
  raise "\n\nLicense file not found".red
140
259
  end
141
-
260
+
142
261
  plist = CFPropertyList::List.new(:file => acknowledge_file)
143
262
  data = CFPropertyList.native_types(plist.value)
144
-
263
+
145
264
  return data["PreferenceSpecifiers"] || []
146
265
  end
147
-
266
+
148
267
  def self.copy_development_pods_source_code(podfile_content, podfile_items)
149
268
  if Configuration.build_using_repo_paths
150
269
  return podfile_content
151
270
  end
152
-
271
+
153
272
  # Development pods are normally built/integrated without moving files from their original paths.
154
273
  # It is important that CocoaPods compiles the files under Configuration.build_path in order that
155
274
  # DWARF debug info reference to this constant path. Doing otherwise breaks the assumptions that
156
- # makes the `update_lldbinit` command work.
275
+ # makes the `generate_lldbinit` command work.
157
276
  development_pods = podfile_items.select { |x| x.is_development_pod }
158
277
  development_pods.each do |podfile_item|
159
278
  destination_path = "#{Configuration.build_path}/Pods/#{podfile_item.name}"
160
279
  FileUtils.mkdir_p(destination_path)
161
-
280
+
162
281
  if Pathname.new(podfile_item.path).absolute?
163
282
  FileUtils.cp_r("#{podfile_item.path}/.", destination_path)
164
283
  else
165
284
  FileUtils.cp_r("#{PodBuilder::basepath(podfile_item.path)}/.", destination_path)
166
285
  end
167
-
286
+
168
287
  podfile_content.gsub!("'#{podfile_item.path}'", "'#{destination_path}'")
169
288
  end
170
-
289
+
171
290
  return podfile_content
172
291
  end
173
-
292
+
174
293
  def self.use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
294
+ podfile_content = File.read(podfile_path)
295
+
296
+ replaced_items = []
297
+
175
298
  if OPTIONS.has_key?(:force_rebuild)
176
- return
177
- end
299
+ podfile_content.gsub!("%%%prebuilt_root_paths%%%", "{}")
300
+ else
301
+ download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
178
302
 
179
- download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
303
+ gitignored_files = PodBuilder::gitignoredfiles
180
304
 
181
- podfile_content = File.read(podfile_path)
305
+ prebuilt_root_paths = Hash.new
182
306
 
183
- gitignored_files = PodBuilder::gitignoredfiles
307
+ # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
308
+ items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
309
+ items.each do |item|
310
+ podspec_path = item.prebuilt_podspec_path
311
+ if last_build_folder_hash = build_folder_hash_in_prebuilt_info_file(item)
312
+ if last_build_folder_hash == build_folder_hash(item, gitignored_files)
313
+ puts "No changes detected to '#{item.root_name}', will skip rebuild".blue
314
+
315
+ replaced_items.push(item)
184
316
 
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))
317
+ podfile_items.select { |t| t.root_name == item.root_name }.each do |replace_item|
318
+ replace_regex = "pod '#{Regexp.quote(replace_item.name)}', .*"
319
+ replace_line_found = podfile_content =~ /#{replace_regex}/i
320
+ raise "\n\nFailed finding pod entry for '#{replace_item.name}'".red unless replace_line_found
321
+ podfile_content.gsub!(/#{replace_regex}/, replace_item.prebuilt_entry(true, true))
322
+
323
+ prebuilt_root_paths[replace_item.root_name] = PodBuilder::prebuiltpath
324
+ end
197
325
  end
198
326
  end
199
327
  end
328
+
329
+ podfile_content.gsub!("%%%prebuilt_root_paths%%%", prebuilt_root_paths.to_s)
200
330
  end
201
331
 
202
332
  File.write(podfile_path, podfile_content)
203
- end
204
333
 
334
+ return replaced_items
335
+ end
336
+
205
337
  def self.install
206
338
  puts "Prebuilding items".yellow
207
-
339
+
208
340
  CLAide::Command::PluginManager.load_plugins("cocoapods")
209
-
341
+
210
342
  Dir.chdir(Configuration.build_path) do
211
343
  config = Pod::Config.new()
212
344
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
@@ -214,21 +346,22 @@ module PodBuilder
214
346
  installer.update = false
215
347
 
216
348
  install_start_time = Time.now
349
+
217
350
  installer.install!
218
351
  install_time = Time.now - install_start_time
219
-
352
+
220
353
  puts "Build completed in #{install_time.to_i} seconds".blue
221
354
  end
222
355
  end
223
-
356
+
224
357
  def self.download
225
358
  puts "Downloading Pods source code".yellow
226
-
359
+
227
360
  CLAide::Command::PluginManager.load_plugins("cocoapods")
228
-
361
+
229
362
  Dir.chdir(Configuration.build_path) do
230
363
  Pod::UserInterface::config.silent = true
231
-
364
+
232
365
  config = Pod::Config.new()
233
366
  installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
234
367
  installer.repo_update = false
@@ -236,29 +369,45 @@ module PodBuilder
236
369
  installer.prepare
237
370
  installer.resolve_dependencies
238
371
  installer.download_dependencies
239
-
372
+
240
373
  Pod::UserInterface::config.silent = false
241
374
  end
242
375
  end
243
-
376
+
244
377
  def self.copy_prebuilt_items(podfile_items)
245
378
  FileUtils.mkdir_p(PodBuilder::prebuiltpath)
246
379
 
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)
380
+ non_prebuilt_items = podfile_items.reject(&:is_prebuilt)
381
+
382
+ pod_names = non_prebuilt_items.map(&:root_name).uniq
383
+
384
+ pod_names.reject! { |t|
385
+ folder_path = PodBuilder::buildpath_prebuiltpath(t)
386
+ File.directory?(folder_path) && Dir.empty?(folder_path) # When using prebuilt items we end up with empty folders
387
+ }
388
+
389
+ pod_names.each do |pod_name|
390
+ root_name = pod_name.split("/").first
391
+
392
+ items_to_delete = Dir.glob("#{PodBuilder::prebuiltpath(root_name)}/**/*")
393
+ items_to_delete.each { |t| PodBuilder::safe_rm_rf(t) }
394
+ end
395
+
396
+ # Now copy
397
+ pod_names.each do |pod_name|
398
+ root_name = pod_name.split("/").first
399
+ source_path = PodBuilder::buildpath_prebuiltpath(root_name)
400
+
250
401
  unless File.directory?(source_path)
251
- puts "Prebuilt items for #{prebuilt_name} not found".blue
402
+ puts "Prebuilt items for #{pod_name} not found".blue
252
403
  next
253
404
  end
254
- if Dir.empty?(source_path)
255
- next # When using prebuilt items we end up with empty folders
256
- end
257
405
 
258
- PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath(prebuilt_name))
259
- FileUtils.cp_r(source_path, PodBuilder::prebuiltpath)
406
+ destination_folder = PodBuilder::prebuiltpath(root_name)
407
+ FileUtils.mkdir_p(destination_folder)
408
+ FileUtils.cp_r("#{source_path}/.", destination_folder)
260
409
  end
261
-
410
+
262
411
  # Folder won't exist if no dSYM were generated (all static libs)
263
412
  if File.directory?(PodBuilder::buildpath_dsympath)
264
413
  FileUtils.mkdir_p(PodBuilder::dsympath)
@@ -266,58 +415,25 @@ module PodBuilder
266
415
  end
267
416
  end
268
417
 
269
- def self.add_prebuilt_info_file(podfile_items)
270
- gitignored_files = PodBuilder::gitignoredfiles
271
-
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)
277
-
278
- unless File.directory?(path)
279
- puts "Prebuilt items for #{prebuilt_name} not found".blue
280
- next
281
- end
282
-
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
285
- next
286
- end
287
-
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.prebuilt_rel_path}/Headers/*-Swift.h")).count > 0
295
- data['swift_version'] = swift_version
296
- 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))
418
+ def self.write_prebuilt_info_filename_gitattributes
419
+ gitattributes_path = PodBuilder::basepath(".gitattributes")
420
+ expected_attributes = ["#{Configuration.configuration_filename} binary"].join
421
+ unless File.exists?(gitattributes_path) && File.read(gitattributes_path).include?(expected_attributes)
422
+ File.write(gitattributes_path, expected_attributes, mode: 'a')
307
423
  end
308
424
  end
309
-
425
+
310
426
  def self.init_git(path)
311
427
  current_dir = Dir.pwd
312
-
428
+
313
429
  Dir.chdir(path)
314
430
  system("git init")
315
431
  Dir.chdir(current_dir)
316
432
  end
317
-
433
+
318
434
  def self.build_folder_hash_in_prebuilt_info_file(podfile_item)
319
435
  prebuilt_info_path = PodBuilder::prebuiltpath(File.join(podfile_item.root_name, Configuration.prebuilt_info_filename))
320
-
436
+
321
437
  if File.exist?(prebuilt_info_path)
322
438
  data = JSON.parse(File.read(prebuilt_info_path))
323
439
  return data['build_folder_hash']
@@ -325,7 +441,7 @@ module PodBuilder
325
441
  return nil
326
442
  end
327
443
  end
328
-
444
+
329
445
  def self.build_folder_hash(podfile_item, exclude_files)
330
446
  if podfile_item.is_development_pod
331
447
  if Pathname.new(podfile_item.path).absolute?
@@ -333,7 +449,7 @@ module PodBuilder
333
449
  else
334
450
  item_path = PodBuilder::basepath(podfile_item.path)
335
451
  end
336
-
452
+
337
453
  rootpath = PodBuilder::git_rootpath
338
454
  file_hashes = []
339
455
  Dir.glob("#{item_path}/**/*", File::FNM_DOTMATCH) do |path|
@@ -347,12 +463,16 @@ module PodBuilder
347
463
  file_hashes.push(Digest::MD5.hexdigest(File.read(path)))
348
464
  end
349
465
  end
350
-
466
+
351
467
  return Digest::MD5.hexdigest(file_hashes.join)
352
468
  else
353
469
  # Pod folder might be under .gitignore
354
470
  item_path = "#{Configuration.build_path}/Pods/#{podfile_item.root_name}"
355
- return `find '#{item_path}' -type f -print0 | sort -z | xargs -0 shasum | shasum | cut -d' ' -f1`.strip()
471
+ if File.directory?(item_path)
472
+ return `find '#{item_path}' -type f -print0 | sort -z | xargs -0 shasum | shasum | cut -d' ' -f1`.strip()
473
+ else
474
+ return nil
475
+ end
356
476
  end
357
477
  end
358
478
 
@@ -363,17 +483,17 @@ module PodBuilder
363
483
  use_absolute_paths = true
364
484
  podfile_path = File.join(Configuration.build_path, "Podfile")
365
485
  original_basepath = PodBuilder::basepath
366
-
486
+
367
487
  podfile_base_path = Pathname.new(File.dirname(podfile_path))
368
-
488
+
369
489
  original_path = Pathname.new(File.join(original_basepath, path))
370
490
  replace_path = original_path.relative_path_from(podfile_base_path)
371
491
  if use_absolute_paths
372
492
  replace_path = replace_path.expand_path(podfile_base_path)
373
493
  end
374
-
494
+
375
495
  return replace_path
376
496
  end
377
- end
497
+ end
378
498
  end
379
499
  end