pod-builder 2.0.0.beta.26 → 2.0.0.beta.27

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 026afc87b8f1c1b60367e611927d1e958f9eab4fa8b362fe5530b8f364b73469
4
- data.tar.gz: d20a47f60ffea78ad81acb3b7e015bbd62c081ac0b5e493d652a56c24ff07704
3
+ metadata.gz: 44ff676a26caedcecf597f47315839aa7b6785d34f77c61d72fba8125473fdac
4
+ data.tar.gz: 761a04159150170ee9f826d05e0664d18b679252820c582f4ddb5fef925feb18
5
5
  SHA512:
6
- metadata.gz: 9ecececb6dca35557797fade2be225d7212d2090a5b2a94883842f7f1bf0d0cb9272eaf3abb721e92f50db8e6e7384453b0c9e5e6929a26a96310ba761dc0d45
7
- data.tar.gz: b0f464538c82dc152c388a3cc20ab7b8b14a0a4e28469fea60ee7f7ecc314ea4475895b7fdecd387da8e12be437b4ccea005bd7bb148a9f16458d0a2c53ecd96
6
+ metadata.gz: 84fed9f6fdbeed8adc3b79c7dab9d037d67c066437be938823a0feb3257c1dce27fe74800cfb5f8672c06a568f02a766325840ca54acc471eea40acd54c05c2b
7
+ data.tar.gz: 92ce97f49e9dd1a10604a7b6cafe30c47d9c202afad83aef212eab025a756c8ec70d99eb8bcff90b14ae0d4a18bdac0eb9e0f9f80e309e69b94e93619dd20f13
@@ -71,7 +71,7 @@ Options:
71
71
  OPTIONS[:update_repos] = false
72
72
  end
73
73
  opts.on("-f", "--force", "Rebuild items even when no code change is detected") do |o|
74
- OPTIONS[:force_rebuild] = false
74
+ OPTIONS[:force_rebuild] = true
75
75
  end
76
76
  opts.on("-w", "--allow-warnings", "Allow warnings") do |o|
77
77
  OPTIONS[:allow_warnings] = o
@@ -375,7 +375,7 @@ begin
375
375
  rescue Exception => e
376
376
  error = e.to_s
377
377
 
378
- if error.length < 1000
378
+ if error.length < 1000 || !File.directory?(PodBuilder::Configuration.build_path)
379
379
  puts "#{error.red}\n"
380
380
  puts e.backtrace.join("\n\t").red
381
381
  puts "\n\nCommand failed!".red
@@ -49,7 +49,7 @@ module PodBuilder
49
49
 
50
50
  restore_file_error = Podfile.restore_file_sanity_check
51
51
 
52
- check_splitted_subspecs_are_static(all_buildable_items)
52
+ check_splitted_subspecs_are_buildable(all_buildable_items, installer)
53
53
  check_pods_exists(argument_pods, all_buildable_items)
54
54
 
55
55
  pods_to_build = resolve_pods_to_build(argument_pods, buildable_items)
@@ -62,41 +62,44 @@ module PodBuilder
62
62
 
63
63
  check_not_building_development_pods(pods_to_build)
64
64
 
65
- pods_to_build_subspecs = pods_to_build.select { |x| x.is_subspec && Configuration.subspecs_to_split.include?(x.name) }
65
+ pods_to_build_subspecs = splitted_pods_to_build(pods_to_build, installer)
66
66
 
67
67
  # Remove dependencies from pods to build
68
68
  all_dependencies_name = pods_to_build.map(&:dependency_names).flatten.uniq
69
69
  pods_to_build.select! { |x| !all_dependencies_name.include?(x.name) }
70
70
 
71
- pods_to_build -= pods_to_build_subspecs
71
+ pods_to_build -= pods_to_build_subspecs.flatten
72
72
  pods_to_build_debug = pods_to_build.select { |x| x.build_configuration == "debug" }
73
73
  pods_to_build_release = pods_to_build - pods_to_build_debug
74
74
 
75
75
  check_dependencies_build_configurations(all_buildable_items)
76
76
 
77
- podfiles_items = pods_to_build_subspecs.map { |x| [x] }
77
+ podfiles_items = pods_to_build_subspecs
78
78
  podfiles_items.push(pods_to_build_debug)
79
79
  podfiles_items.push(pods_to_build_release)
80
80
 
81
- licenses = []
81
+ install_using_frameworks = Podfile::install_using_frameworks(analyzer)
82
82
 
83
- podfiles_items.select { |x| x.count > 0 }.each do |podfile_items|
83
+ install_result = InstallResult.new
84
+ podfiles_items.reject { |x| x.empty? }.each do |podfile_items|
84
85
  build_configuration = podfile_items.map(&:build_configuration).uniq.first
85
86
 
86
87
  podfile_items = podfile_items.map { |t| t.recursive_dependencies(all_buildable_items) }.flatten.uniq
87
- podfile_content = Podfile.from_podfile_items(podfile_items, analyzer, build_configuration)
88
+ podfile_content = Podfile.from_podfile_items(podfile_items, analyzer, build_configuration, install_using_frameworks)
88
89
 
89
- licenses += Install.podfile(podfile_content, podfile_items, podfile_items.first.build_configuration)
90
+ install_result += Install.podfile(podfile_content, podfile_items, podfile_items.first.build_configuration)
90
91
 
91
92
  # remove lockfile which gets unexplicably created
92
93
  FileUtils.rm_f(PodBuilder::basepath("Podfile.lock"))
93
94
  end
94
95
 
96
+ install_result.write_prebuilt_info_files
97
+
95
98
  Clean::prebuilt_items(all_buildable_items)
96
99
 
97
- Licenses::write(licenses, all_buildable_items)
100
+ Licenses::write(install_result.licenses, all_buildable_items)
98
101
 
99
- Podspec::generate(all_buildable_items, analyzer)
102
+ Podspec::generate(all_buildable_items, analyzer, install_using_frameworks)
100
103
 
101
104
  builded_pods = podfiles_items.flatten
102
105
 
@@ -122,6 +125,20 @@ module PodBuilder
122
125
 
123
126
  private
124
127
 
128
+ def self.splitted_pods_to_build(pods_to_build, installer)
129
+ specs_by_target = installer.analysis_result.specs_by_target
130
+
131
+ pods_to_build_subspecs = pods_to_build.select { |x| x.is_subspec && Configuration.subspecs_to_split.include?(x.name) }
132
+
133
+ pods = []
134
+ specs_by_target.each do |target, specs|
135
+ grouped = pods_to_build_subspecs.group_by { |t| specs.map(&:name).include?(t.name) }
136
+ pods.push(grouped[true])
137
+ end
138
+
139
+ return pods.compact
140
+ end
141
+
125
142
  def self.check_not_building_subspecs(pods_to_build)
126
143
  pods_to_build.each do |pod_to_build|
127
144
  if pod_to_build.include?("/")
@@ -139,6 +156,37 @@ module PodBuilder
139
156
  end
140
157
  end
141
158
 
159
+ def self.check_splitted_subspecs_are_buildable(all_buildable_items, installer)
160
+ check_splitted_subspecs_are_static(all_buildable_items)
161
+ check_splitted_subspecs_have_valid_dependencies(all_buildable_items)
162
+ check_splitted_subspecs_not_in_multiple_targets(all_buildable_items, installer)
163
+ end
164
+
165
+ def self.check_splitted_subspecs_have_valid_dependencies(all_buildable_items)
166
+ splitted_items = all_buildable_items.select { |t| Configuration.subspecs_to_split.include?(t.name) }
167
+ splitted_items.each do |splitted_item|
168
+ common_deps = splitted_item.dependency_names.select { |t| t.start_with?(splitted_item.root_name) }
169
+
170
+ if common_deps.count > 0
171
+ raise "\n\nSubspecs included in 'subspecs_to_split' cannot have dependencies to other subspecs within the spec.\n\n#{splitted_item.name} has dependencies to: '#{common_deps.join(', ')}'\n\n".red
172
+ end
173
+ end
174
+ end
175
+
176
+ def self.check_splitted_subspecs_not_in_multiple_targets(all_buildable_items, installer)
177
+ specs_by_target = installer.analysis_result.specs_by_target
178
+
179
+ flat_item_names = specs_by_target.values.flatten.map(&:name)
180
+
181
+ splitted_items = all_buildable_items.select { |t| Configuration.subspecs_to_split.include?(t.name) }
182
+
183
+ splitted_items.each do |splitted_item|
184
+ if flat_item_names.count(splitted_item.name) > 1
185
+ raise "\n\n'#{splitted_item.name}' is included in 'subspecs_to_split' but it is used in multiple targets. This is unsupported.\nIf possible duplicate the subspec '#{splitted_item.name}' in the podspec using different names for each target.\n".red
186
+ end
187
+ end
188
+ end
189
+
142
190
  def self.check_splitted_subspecs_are_static(all_buildable_items)
143
191
  non_static_subspecs = all_buildable_items.select { |x| x.is_subspec && x.is_static == false }
144
192
  non_static_subspecs_names = non_static_subspecs.map(&:name)
@@ -151,9 +199,9 @@ module PodBuilder
151
199
 
152
200
  warn_message = "The following pods `#{invalid_subspecs.join(" ")}` are non static binaries which are being splitted over different targets. Beware that this is an unsafe setup as per https://github.com/CocoaPods/CocoaPods/issues/5708 and https://github.com/CocoaPods/CocoaPods/issues/5643\n\nYou can ignore this error by passing the `--allow-warnings` flag to the build command\n"
153
201
  if OPTIONS[:allow_warnings]
154
- puts "\n\n⚠️ #{warn_message}".yellow
202
+ puts "\n\n#{warn_message}".yellow
155
203
  else
156
- raise "\n\n🚨️ #{warn_message}".red
204
+ raise "\n\n#{warn_message}".red
157
205
  end
158
206
  end
159
207
 
@@ -196,9 +244,9 @@ module PodBuilder
196
244
  if !expected_stripped.all? { |x| stripped_lines.include?(x) }
197
245
  warn_message = "PodBuilder's post install actions missing from application Podfile!\n"
198
246
  if OPTIONS[:allow_warnings]
199
- puts "\n\n⚠️ #{warn_message}".yellow
247
+ puts "\n\n#{warn_message}".yellow
200
248
  else
201
- raise "\n\n🚨️ #{warn_message}".red
249
+ raise "\n\n#{warn_message}".red
202
250
  end
203
251
  end
204
252
  end
@@ -23,7 +23,7 @@ module PodBuilder
23
23
  puts "Cleaning prebuilt folder".yellow
24
24
 
25
25
  root_names = buildable_items.map(&:root_name).uniq
26
- Dir.glob(File.join(PodBuilder::prebuiltpath, "*")).each do |path|
26
+ Dir.glob(PodBuilder::prebuiltpath("*")).each do |path|
27
27
  basename = File.basename(path)
28
28
  unless root_names.include?(basename)
29
29
  puts "Cleanining up `#{basename}`, no longer found among dependencies".blue
@@ -31,6 +31,19 @@ module PodBuilder
31
31
  end
32
32
  end
33
33
 
34
+ splitted_specs = buildable_items.select { |t| Configuration.subspecs_to_split.include?(t.name) }
35
+ splitted_specs.each do |splitted_spec|
36
+ root_name = splitted_spec.root_name
37
+
38
+ Dir.glob(PodBuilder::prebuiltpath("#{root_name}/Subspecs/*")).each do |path|
39
+ basename = File.basename(path)
40
+ unless splitted_specs.map(&:podspec_name).include?(basename)
41
+ puts "Cleanining up `#{root_name}/#{basename}`, no longer found among dependencies".blue
42
+ PodBuilder::safe_rm_rf(path)
43
+ end
44
+ end
45
+ end
46
+
34
47
  puts "Cleaning dSYM folder".yellow
35
48
  module_names = buildable_items.map(&:module_name).uniq
36
49
  Dir.glob(File.join(PodBuilder::dsympath, "**/*.dSYM")).each do |path|
@@ -43,7 +43,7 @@ module PodBuilder
43
43
  end
44
44
 
45
45
  source_map_lines = []
46
- Dir.glob("#{PodBuilder::prebuiltpath}/**/Podbuilder.json").each do |path|
46
+ Dir.glob("#{PodBuilder::prebuiltpath}/**/#{Configuration.prebuilt_info_filename}").each do |path|
47
47
  data = JSON.parse(File.read(path))
48
48
  next if data.fetch("is_prebuilt", true)
49
49
 
@@ -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,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,10 +17,28 @@ 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
44
  DEFAULT_PLATFORMS = ["iphoneos", "iphonesimulator", "appletvos", "appletvsimulator"].freeze
@@ -71,29 +71,26 @@ begin
71
71
  return res
72
72
  end
73
73
  end
74
-
74
+
75
75
  class Pod::Target::BuildSettings
76
- class <<self
77
- attr_accessor :patch_static_library_generation
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
78
82
  end
79
-
80
- alias_method :swz_add_inherited_to_plural, :add_inherited_to_plural
81
-
82
- def add_inherited_to_plural(hash)
83
- # There's probably a better place to monkey patch this
84
- h = swz_add_inherited_to_plural(hash)
85
- if Pod::Target::BuildSettings.patch_static_library_generation
86
- # Static frameworks should NOT import underlying modules to simplify integration of the produced
87
- # artifacts. Without these build options you can integrate the static library the same way you
88
- # would do with a vanilla static library target in Xcode: you just copy the .a and set the Swift
89
- # import path to point to the module map file (which doesn't seem to be needed).
90
- flags = h["OTHER_SWIFT_FLAGS"].dup
91
- flags.gsub!("-import-underlying-module", "")
92
- flags.gsub!("-Xcc -fmodule-map-file=\"${SRCROOT}/${MODULEMAP_FILE}\"", "")
93
- h["OTHER_SWIFT_FLAGS"] = flags
94
- end
95
83
 
96
- return h
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)
97
94
  end
98
95
  end
99
96
  rescue LoadError
@@ -101,6 +98,44 @@ rescue LoadError
101
98
  end
102
99
 
103
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
+
104
139
  class Install
105
140
  # This method will generate prebuilt data by building from "/tmp/pod_builder/Podfile"
106
141
  def self.podfile(podfile_content, podfile_items, build_configuration)
@@ -124,20 +159,22 @@ module PodBuilder
124
159
  lock_file = "#{Configuration.build_path}/pod_builder.lock"
125
160
  FileUtils.touch(lock_file)
126
161
 
127
- use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
162
+ prebuilt_entries = use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
163
+
164
+ prepare_for_static_framework_workarounds(podfile_content, podfile_items)
128
165
 
129
166
  install
130
167
 
131
- copy_prebuilt_items(podfile_items)
132
- add_prebuilt_info_file(podfile_items)
133
-
168
+ copy_prebuilt_items(podfile_items - prebuilt_entries)
169
+
170
+ prebuilt_info = prebuilt_info(podfile_items)
134
171
  licenses = license_specifiers()
135
172
 
136
173
  if !OPTIONS.has_key?(:debug)
137
174
  PodBuilder::safe_rm_rf(Configuration.build_path)
138
175
  end
139
176
 
140
- return licenses
177
+ return InstallResult.new(licenses, prebuilt_info)
141
178
  rescue Exception => e
142
179
  if File.directory?("#{Configuration.build_path}/Pods/Pods.xcodeproj")
143
180
  if ENV['DEBUGGING']
@@ -155,8 +192,68 @@ module PodBuilder
155
192
  FileUtils.rm(lock_file) if File.exist?(lock_file)
156
193
  end
157
194
  end
158
-
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"] = Configuration.build_path.gsub(/^\/private/, "") # Use realpath for /private/tmp
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
159
246
  private
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
160
257
 
161
258
  def self.license_specifiers
162
259
  acknowledge_file = "#{Configuration.build_path}/Pods/Target Support Files/Pods-DummyTarget/Pods-DummyTarget-acknowledgements.plist"
@@ -197,34 +294,50 @@ module PodBuilder
197
294
  end
198
295
 
199
296
  def self.use_prebuilt_entries_for_unchanged_pods(podfile_path, podfile_items)
200
- if OPTIONS.has_key?(:force_rebuild)
201
- return
202
- end
203
-
204
- download # Copy files under #{Configuration.build_path}/Pods so that we can determine build folder hashes
205
-
206
297
  podfile_content = File.read(podfile_path)
207
298
 
208
- gitignored_files = PodBuilder::gitignoredfiles
209
-
210
- # Replace prebuilt entries in Podfile for Pods that have no changes in source code which will avoid rebuilding them
211
- items = podfile_items.group_by { |t| t.root_name }.map { |k, v| v.first } # Return one podfile_item per root_name
212
- items.each do |item|
213
- podspec_path = item.prebuilt_podspec_path
214
- if last_build_folder_hash = build_folder_hash_in_prebuilt_info_file(item)
215
- if last_build_folder_hash == build_folder_hash(item, gitignored_files)
216
- puts "No changes detected to '#{item.root_name}', will skip rebuild".blue
217
- podfile_items.select { |t| t.root_name == item.root_name }.each do |replace_item|
218
- replace_regex = "pod '#{Regexp.quote(replace_item.name)}', .*"
219
- replace_line_found = podfile_content =~ /#{replace_regex}/i
220
- raise "\n\nFailed finding pod entry for '#{replace_item.name}'".red unless replace_line_found
221
- podfile_content.gsub!(/#{replace_regex}/, replace_item.prebuilt_entry(true, true))
299
+ replaced_items = []
300
+
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
222
331
  end
223
332
  end
224
333
  end
334
+
335
+ podfile_content.gsub!("%%%prebuilt_root_paths%%%", prebuilt_root_paths.to_s)
225
336
  end
226
-
337
+
227
338
  File.write(podfile_path, podfile_content)
339
+
340
+ return replaced_items
228
341
  end
229
342
 
230
343
  def self.install
@@ -240,8 +353,6 @@ module PodBuilder
240
353
 
241
354
  install_start_time = Time.now
242
355
 
243
- monkey_patch_static_library_generation()
244
-
245
356
  installer.install!
246
357
  install_time = Time.now - install_start_time
247
358
 
@@ -271,20 +382,57 @@ module PodBuilder
271
382
 
272
383
  def self.copy_prebuilt_items(podfile_items)
273
384
  FileUtils.mkdir_p(PodBuilder::prebuiltpath)
274
-
275
- root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
276
- root_names.each do |prebuilt_name|
277
- source_path = PodBuilder::buildpath_prebuiltpath(prebuilt_name)
385
+
386
+ non_prebuilt_items = podfile_items.reject(&:is_prebuilt)
387
+
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
390
+
391
+ pod_names = non_prebuilt_items.reject { |t| splitted_pods_root_name.include?(t.root_name) }.map(&:root_name).uniq + splitted_pods.map(&:name)
392
+
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
+ }
397
+
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")) }
408
+
409
+ items_to_delete.each { |t| PodBuilder::safe_rm_rf(t) }
410
+ end
411
+ end
412
+
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
+
278
419
  unless File.directory?(source_path)
279
- puts "Prebuilt items for #{prebuilt_name} not found".blue
420
+ puts "Prebuilt items for #{pod_name} not found".blue
280
421
  next
281
422
  end
282
- if Dir.empty?(source_path)
283
- next # When using prebuilt items we end up with empty folders
423
+
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)
284
435
  end
285
-
286
- PodBuilder::safe_rm_rf(PodBuilder::prebuiltpath(prebuilt_name))
287
- FileUtils.cp_r(source_path, PodBuilder::prebuiltpath)
288
436
  end
289
437
 
290
438
  # Folder won't exist if no dSYM were generated (all static libs)
@@ -293,49 +441,6 @@ module PodBuilder
293
441
  FileUtils.cp_r(PodBuilder::buildpath_dsympath, PodBuilder::basepath)
294
442
  end
295
443
  end
296
-
297
- def self.add_prebuilt_info_file(podfile_items)
298
- gitignored_files = PodBuilder::gitignoredfiles
299
-
300
- swift_version = PodBuilder::system_swift_version
301
-
302
- write_prebuilt_info_filename_gitattributes
303
-
304
- root_names = podfile_items.reject(&:is_prebuilt).map(&:root_name).uniq
305
- root_names.each do |prebuilt_name|
306
- path = PodBuilder::prebuiltpath(prebuilt_name)
307
-
308
- unless File.directory?(path)
309
- puts "Prebuilt items for #{prebuilt_name} not found".blue
310
- next
311
- end
312
-
313
- unless podfile_item = podfile_items.detect { |t| t.name == prebuilt_name } || podfile_items.detect { |t| t.root_name == prebuilt_name }
314
- puts "Prebuilt items for #{prebuilt_name} not found #2".blue
315
- next
316
- end
317
-
318
- podbuilder_file = File.join(path, Configuration.prebuilt_info_filename)
319
- entry = podfile_item.entry(true, false)
320
-
321
- data = {}
322
- data['entry'] = entry
323
- data['is_prebuilt'] = podfile_item.is_prebuilt
324
- if Dir.glob(File.join(path, "#{podfile_item.prebuilt_rel_path}/Headers/*-Swift.h")).count > 0
325
- data['swift_version'] = swift_version
326
- end
327
-
328
- specs = podfile_items.select { |x| x.module_name == podfile_item.module_name }
329
- subspecs_deps = specs.map(&:dependency_names).flatten
330
- subspec_self_deps = subspecs_deps.select { |x| x.start_with?("#{prebuilt_name}/") }
331
- data['specs'] = (specs.map(&:name) + subspec_self_deps).uniq
332
- data['is_static'] = podfile_item.is_static
333
- data['original_compile_path'] = Pathname.new(Configuration.build_path).realpath.to_s
334
- data['build_folder_hash'] = build_folder_hash(podfile_item, gitignored_files)
335
-
336
- File.write(podbuilder_file, JSON.pretty_generate(data))
337
- end
338
- end
339
444
 
340
445
  def self.write_prebuilt_info_filename_gitattributes
341
446
  gitattributes_path = PodBuilder::basepath(".gitattributes")
@@ -390,7 +495,11 @@ module PodBuilder
390
495
  else
391
496
  # Pod folder might be under .gitignore
392
497
  item_path = "#{Configuration.build_path}/Pods/#{podfile_item.root_name}"
393
- 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
394
503
  end
395
504
  end
396
505
 
@@ -413,11 +522,9 @@ module PodBuilder
413
522
  return replace_path
414
523
  end
415
524
  end
416
-
417
- def self.monkey_patch_static_library_generation()
418
- podfile_path = File.join(Configuration.build_path, "Podfile")
419
525
 
420
- Pod::Target::BuildSettings.patch_static_library_generation = !File.read(podfile_path).include?("use_frameworks!")
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) }
421
528
  end
422
529
  end
423
530
  end