pod-builder 2.0.0.beta.19 → 2.0.0.beta.21

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/Example/{Frameworks → PodBuilder}/.gitignore +0 -0
  4. data/Example/{Frameworks → PodBuilder}/.pod_builder/pod_builder +0 -0
  5. data/Example/{Frameworks → PodBuilder}/PodBuilder.json +0 -0
  6. data/Example/{Frameworks → PodBuilder}/Podfile +0 -0
  7. data/Example/{Frameworks → PodBuilder}/Podfile.restore +0 -0
  8. data/Example/Podfile +27 -29
  9. data/Example/Podfile.lock +42 -42
  10. data/README.md +13 -13
  11. data/exe/pod_builder +27 -16
  12. data/lib/pod_builder/command/build.rb +28 -159
  13. data/lib/pod_builder/command/build_all.rb +2 -2
  14. data/lib/pod_builder/command/clean.rb +34 -53
  15. data/lib/pod_builder/command/clear_lldbinit.rb +6 -2
  16. data/lib/pod_builder/command/deintegrate.rb +27 -6
  17. data/lib/pod_builder/command/generate_lfs.rb +1 -1
  18. data/lib/pod_builder/command/generate_podspec.rb +3 -2
  19. data/lib/pod_builder/command/info.rb +1 -1
  20. data/lib/pod_builder/command/init.rb +37 -14
  21. data/lib/pod_builder/command/install_sources.rb +20 -13
  22. data/lib/pod_builder/command/none.rb +2 -2
  23. data/lib/pod_builder/command/restore_all.rb +4 -4
  24. data/lib/pod_builder/command/switch.rb +56 -14
  25. data/lib/pod_builder/command/sync_podfile.rb +3 -2
  26. data/lib/pod_builder/command/update.rb +5 -6
  27. data/lib/pod_builder/command/update_lldbinit.rb +10 -8
  28. data/lib/pod_builder/configuration.rb +27 -7
  29. data/lib/pod_builder/core.rb +35 -9
  30. data/lib/pod_builder/info.rb +11 -11
  31. data/lib/pod_builder/install.rb +178 -184
  32. data/lib/pod_builder/licenses.rb +4 -4
  33. data/lib/pod_builder/podfile.rb +226 -85
  34. data/lib/pod_builder/podfile/post_actions.rb +9 -14
  35. data/lib/pod_builder/podfile_cp.rb +93 -0
  36. data/lib/pod_builder/podfile_item.rb +41 -20
  37. data/lib/pod_builder/podspec.rb +33 -16
  38. data/lib/pod_builder/rome/post_install.rb +121 -129
  39. data/lib/pod_builder/rome/pre_install.rb +1 -1
  40. data/lib/pod_builder/templates/build_podfile.template +2 -2
  41. data/lib/pod_builder/version.rb +1 -1
  42. metadata +8 -7
@@ -3,26 +3,21 @@ require 'pod_builder/core'
3
3
 
4
4
  module PodBuilder
5
5
  class Podfile
6
- def self.remove_target_support_duplicate_entries
7
- puts "[PodBuilder] Removing target support duplicated entries".yellow
8
-
6
+ def self.pod_builder_post_process
9
7
  Configuration.load
10
-
8
+
9
+ targets = find_xcodeproj_targets
10
+ target_names = targets.map(&:name)
11
+
12
+ puts "[PodBuilder] Removing target support duplicated entries".yellow
11
13
  # Frameworks and resources
12
- find_xcodeproj_targets.map(&:name).each do |target|
14
+ target_names.each do |target|
13
15
  remove_duplicate_entries("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-frameworks.sh")
14
16
  remove_duplicate_entries("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-resources.sh")
15
17
  end
16
- end
17
18
 
18
- def self.check_target_support_resource_collisions
19
19
  puts "[PodBuilder] Checking target support resource collisions".yellow
20
-
21
- Configuration.load
22
-
23
- targets = find_xcodeproj_targets
24
-
25
- targets.map(&:name).each do |target|
20
+ target_names.each do |target|
26
21
  check_for_colliding_resources("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-resources.sh", target, targets)
27
22
  end
28
23
  end
@@ -74,7 +69,7 @@ module PodBuilder
74
69
  resource_files = resource_files.map { |i| File.basename(i) }
75
70
  resource_files = resource_files.map { |i| i.gsub(".xib", ".nib") }
76
71
  else
77
- raise "#{target} not found!".red
72
+ raise "\n\n#{target} not found!".red
78
73
  end
79
74
 
80
75
  # Check that Pods-TARGET-resources.sh doesn't contain colliding entries (Cocoapods 1.4.0)
@@ -0,0 +1,93 @@
1
+ require 'cocoapods/podfile.rb'
2
+
3
+ module Pod
4
+ class Podfile
5
+ class TargetDefinition
6
+ def pb_to_s(all_buildable_items, indent_level = 0)
7
+ indentation = " " * indent_level
8
+ target_s = "#{indentation}target '#{self.name}' do\n"
9
+
10
+ child_indentation = " " * (indent_level + 1)
11
+
12
+ explicit_deps = self.dependencies.map { |t| all_buildable_items.detect { |u| u.name == t.name } }.compact
13
+
14
+ pod_entries = []
15
+ prebuild_entries = []
16
+ self.dependencies.each do |dep|
17
+ if podfile_item = all_buildable_items.detect { |t| t.name == dep.name }
18
+ if File.exist?(podfile_item.prebuilt_podspec_path) && !podfile_item.is_prebuilt
19
+ prebuild_entries.push(podfile_item)
20
+ else
21
+ pod_entries.push(podfile_item)
22
+ end
23
+
24
+ non_explicit_dependencies = podfile_item.recursive_dependencies(all_buildable_items) - explicit_deps
25
+ non_explicit_dependencies_root_names = non_explicit_dependencies.map(&:root_name).uniq.filter { |t| t != podfile_item.root_name }
26
+ non_explicit_dependencies = non_explicit_dependencies_root_names.map { |x|
27
+ if item = all_buildable_items.detect { |t| x == t.name }
28
+ item
29
+ else
30
+ item = all_buildable_items.detect { |t| x == t.root_name }
31
+ end
32
+ }.compact
33
+
34
+ non_explicit_dependencies.each do |dep|
35
+ dep_item = all_buildable_items.detect { |x| x.name == dep.name }
36
+
37
+ if File.exist?(dep_item.prebuilt_podspec_path) && !dep_item.is_prebuilt
38
+ prebuild_entries.push(dep_item)
39
+ else
40
+ pod_entries.push(dep_item)
41
+ end
42
+
43
+ explicit_deps.push(dep)
44
+ end
45
+ end
46
+ end
47
+
48
+ prebuild_entries = prebuild_entries.uniq.sort_by { |t| t.name }
49
+ pod_entries = pod_entries.uniq.sort_by { |t| t.name }
50
+
51
+ prebuild_entries.each do |pod|
52
+ target_s += "#{child_indentation}#{pod.prebuilt_entry(false)}\n"
53
+ end
54
+ pod_entries.each do |pod|
55
+ target_s += "#{child_indentation}#{pod.entry(true, false)}\n"
56
+ end
57
+
58
+ if self.children.count > 0
59
+ target_s += "\n"
60
+ target_s += @children.map { |t| t.pb_to_s(all_buildable_items, indent_level + 1) }.join("\n\n")
61
+ end
62
+
63
+ target_s += "#{indentation}end\n"
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ module Pod
70
+ class Podfile
71
+ def pb_to_s(all_buildable_items)
72
+ initial_targets = root_target_definitions.first.children
73
+
74
+ platform = @current_target_definition.platform
75
+
76
+ podfile_s = "platform :#{platform.to_sym}, '#{platform.deployment_target.to_s}'\n\n"
77
+ podfile_s += initial_targets.map { |t| t.pb_to_s(all_buildable_items) }.join("\n\n")
78
+
79
+ return podfile_s
80
+ end
81
+ end
82
+ end
83
+
84
+ class PodfileCP
85
+ def self.podfile_path_transform(path)
86
+ prebuilt_prefix = PodBuilder::prebuiltpath.gsub(PodBuilder::project_path, "")[1..] + "/"
87
+ if path.start_with?(prebuilt_prefix)
88
+ return path
89
+ else
90
+ return PodBuilder::Podfile.podfile_path_transform(path)
91
+ end
92
+ end
93
+ end
@@ -1,3 +1,6 @@
1
+ # This class is the model that PodBuilder uses for every pod spec. The model is instantiated
2
+ # from Pod::Specification
3
+
1
4
  module PodBuilder
2
5
  class PodfileItem
3
6
  # @return [String] The git repo
@@ -36,6 +39,10 @@ module PodBuilder
36
39
  #
37
40
  attr_accessor :path
38
41
 
42
+ # @return [String] Local podspec path, if any
43
+ #
44
+ attr_accessor :podspec_path
45
+
39
46
  # @return [String] The pinned commit of the pod, if any
40
47
  #
41
48
  attr_reader :commit
@@ -56,7 +63,7 @@ module PodBuilder
56
63
  #
57
64
  attr_reader :external_dependency_names
58
65
 
59
- # @return [Bool] True if the pod is shipped as a static framework
66
+ # @return [Bool] True if the pod is shipped as a static binary
60
67
  #
61
68
  attr_reader :is_static
62
69
 
@@ -139,6 +146,7 @@ module PodBuilder
139
146
  @tag = checkout_options[opts_key][:tag]
140
147
  @commit = checkout_options[opts_key][:commit]
141
148
  @path = checkout_options[opts_key][:path]
149
+ @podspec_path = checkout_options[opts_key][:podspec]
142
150
  @branch = checkout_options[opts_key][:branch]
143
151
  @is_external = true
144
152
  else
@@ -272,7 +280,7 @@ module PodBuilder
272
280
 
273
281
  root_names = deps.map(&:root_name).uniq
274
282
 
275
- # We need to build all other common subspecs to properly build the framework
283
+ # We need to build all other common subspecs to properly build the item
276
284
  # Ex.
277
285
  # PodA depends on DepA/subspec1
278
286
  # PodB depends on DepA/subspec2
@@ -309,7 +317,7 @@ module PodBuilder
309
317
  if !no_sources && !only_headers
310
318
  return false
311
319
  else
312
- return embedded_as_static_lib || embedded_as_vendored
320
+ return (no_sources || only_headers || embedded_as_static_lib || embedded_as_vendored)
313
321
  end
314
322
  end
315
323
 
@@ -337,6 +345,8 @@ module PodBuilder
337
345
  if is_external
338
346
  if @path
339
347
  e += ", :path => '#{@path}'"
348
+ elsif @podspec_path
349
+ e += ", :podspec => '#{@podspec_path}'"
340
350
  else
341
351
  if @repo
342
352
  e += ", :git => '#{@repo}'"
@@ -356,10 +366,9 @@ module PodBuilder
356
366
  end
357
367
 
358
368
  if include_pb_entry && !is_prebuilt
359
- plists = Dir.glob(PodBuilder::prebuiltpath("**/#{module_name}.framework/#{Configuration::framework_plist_filename}"))
360
- if plists.count > 0
361
- plist = CFPropertyList::List.new(:file => plists.first)
362
- data = CFPropertyList.native_types(plist.value)
369
+ prebuilt_info_path = PodBuilder::prebuiltpath("#{root_name}/#{Configuration::prebuilt_info_filename}")
370
+ if File.exist?(prebuilt_info_path)
371
+ data = JSON.parse(File.read(prebuilt_info_path))
363
372
  swift_version = data["swift_version"]
364
373
  is_static = data["is_static"] || false
365
374
 
@@ -387,18 +396,22 @@ module PodBuilder
387
396
  end
388
397
  end
389
398
 
390
- def prebuilt_entry(include_pb_entry = true, absolute_path = false)
399
+ def prebuilt_podspec_path(absolute_path = true)
400
+ podspec_path = PodBuilder::prebuiltpath("#{@root_name}/#{@root_name}.podspec")
391
401
  if absolute_path
392
- pod_path = PodBuilder::prebuiltpath
402
+ return podspec_path
393
403
  else
394
- pod_path = Pathname.new(Configuration.base_path).relative_path_from(Pathname.new(PodBuilder::project_path)).to_s
395
- pod_path += "/Rome"
404
+ pod_path = Pathname.new(podspec_path).relative_path_from(Pathname.new(PodBuilder::project_path)).to_s
396
405
  end
406
+ end
407
+
408
+ def prebuilt_entry(include_pb_entry = true, absolute_path = false)
409
+ podspec_dirname = File.dirname(prebuilt_podspec_path(absolute_path = absolute_path))
397
410
 
398
411
  if Configuration.subspecs_to_split.include?(name)
399
- entry = "pod '#{podspec_name}', :path => '#{pod_path}'"
412
+ entry = "pod '#{podspec_name}', :path => '#{podspec_dirname}'"
400
413
  else
401
- entry = "pod '#{name}', :path => '#{pod_path}'"
414
+ entry = "pod '#{name}', :path => '#{podspec_dirname}'"
402
415
  end
403
416
 
404
417
  if include_pb_entry && !is_prebuilt
@@ -425,9 +438,9 @@ module PodBuilder
425
438
  end
426
439
 
427
440
  def vendored_framework_path
428
- if File.exist?(PodBuilder::prebuiltpath(vendored_subspec_framework_name))
441
+ if File.exist?(PodBuilder::prebuiltpath("#{root_name}/#{vendored_subspec_framework_name}"))
429
442
  return vendored_subspec_framework_name
430
- elsif File.exist?(PodBuilder::prebuiltpath(vendored_spec_framework_name))
443
+ elsif File.exist?(PodBuilder::prebuiltpath("#{root_name}/#{vendored_spec_framework_name}"))
431
444
  return vendored_spec_framework_name
432
445
  end
433
446
 
@@ -481,18 +494,26 @@ module PodBuilder
481
494
  end
482
495
 
483
496
  def source_files_from_string(source)
497
+ # Transform source file entries
498
+ # "Networking{Response,Request}*.{h,m}" -> ["NetworkingResponse*.h", "NetworkingResponse*.m", "NetworkingRequest*.h", "NetworkingRequest*.m"]
484
499
  files = []
485
500
  if source.is_a? String
486
- matches = source.match(/(.*)({(.),?(.)?})/)
487
- if matches&.size == 5
488
- source = matches[1] + matches[3]
489
- if matches[4].length > 0
490
- source += "," + matches[1] + matches[4]
501
+ matches = source.match(/(.*){(.*)}(.*)/)
502
+ if matches&.size == 4
503
+ res = matches[2].split(",").map { |t| "#{matches[1]}#{t}#{matches[3]}" }
504
+ if res.any? { |t| t.include?("{") }
505
+ return res.map { |t| source_files_from_string(t) }.flatten
491
506
  end
507
+
508
+ return res
492
509
  end
493
510
 
494
511
  return source.split(",")
495
512
  else
513
+ if source.any? { |t| t.include?("{") }
514
+ return source.map { |t| source_files_from_string(t) }.flatten
515
+ end
516
+
496
517
  return source
497
518
  end
498
519
  end
@@ -1,3 +1,6 @@
1
+ # This file contains the logic that generates the .podspec files that are placed
2
+ # along to the prebuild frameworks under PodBuilder/Prebuilt
3
+
1
4
  module PodBuilder
2
5
  class Podspec
3
6
  def self.generate(all_buildable_items, analyzer)
@@ -10,10 +13,6 @@ module PodBuilder
10
13
  platform = analyzer.instance_variable_get("@result").targets.first.platform
11
14
  generate_podspec_from(all_buildable_items, platform)
12
15
  end
13
-
14
- def self.include?(pod_name)
15
- return File.exist?(PodBuilder::prebuiltpath("#{pod_name}.podspec"))
16
- end
17
16
 
18
17
  private
19
18
 
@@ -26,25 +25,26 @@ module PodBuilder
26
25
  spec_var = "p#{slash_count}"
27
26
 
28
27
  if item.name == name
28
+ if_exists = lambda { |t| File.exist?(PodBuilder::prebuiltpath("#{item.root_name}/#{t}") || "") }
29
+
29
30
  vendored_frameworks = item.vendored_frameworks + ["#{item.module_name}.framework"]
30
- existing_vendored_frameworks = vendored_frameworks.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
31
- existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
31
+ existing_vendored_frameworks = vendored_frameworks.select(&if_exists)
32
+ existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select(&if_exists)
32
33
  vendored_frameworks = (existing_vendored_frameworks + existing_vendored_frameworks_basename).uniq
33
34
 
34
35
  vendored_libraries = item.vendored_libraries
35
- existing_vendored_libraries = vendored_libraries.map { |t| "#{item.module_name}/#{t}" }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
36
- existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename("#{item.module_name}/#{t}") }.select { |t| File.exist?(PodBuilder::prebuiltpath(t) || "") }
37
- vendored_libraries = (existing_vendored_libraries + existing_vendored_libraries_basename).uniq
36
+ existing_vendored_libraries = vendored_libraries.map { |t| "#{item.module_name}/#{t}" }.select(&if_exists)
37
+ existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename(t) }.select(&if_exists)
38
+ vendored_libraries = (existing_vendored_libraries + existing_vendored_libraries_basename).uniq
38
39
 
39
40
  # .a are static libraries and should not be included again in the podspec to prevent duplicated symbols (in the app and in the prebuilt framework)
40
- vendored_libraries.select! { |t| !t.end_with?(".a") }
41
+ vendored_libraries.reject! { |t| t.end_with?(".a") }
41
42
 
42
43
  frameworks = all_buildable_items.select { |t| vendored_frameworks.include?("#{t.module_name}.framework") }.uniq
43
44
  static_frameworks = frameworks.select { |x| x.is_static }
44
45
 
45
46
  resources = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/*.{nib,bundle,xcasset,strings,png,jpg,tif,tiff,otf,ttf,ttc,plist,json,caf,wav,p12,momd}" }.compact.flatten.uniq
46
47
  exclude_files = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
47
- exclude_files += frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/#{Configuration.framework_plist_filename}" }.compact.flatten.uniq.sort
48
48
 
49
49
  if vendored_frameworks.count > 0
50
50
  podspec += "#{indentation}#{spec_var}.vendored_frameworks = '#{vendored_frameworks.uniq.sort.join("','")}'\n"
@@ -131,17 +131,25 @@ module PodBuilder
131
131
  end
132
132
 
133
133
  def self.generate_podspec_from(all_buildable_items, platform)
134
- specs = Dir.glob(PodBuilder::prebuiltpath("*.podspec"))
135
- specs.each do |s|
136
- FileUtils.rm(s)
134
+ prebuilt_podspec_path = all_buildable_items.map(&:prebuilt_podspec_path)
135
+ prebuilt_podspec_path.each do |path|
136
+ if File.exist?(path)
137
+ FileUtils.rm(path)
138
+ end
137
139
  end
138
140
 
139
141
  all_buildable_items.each do |item|
142
+ if item.is_prebuilt
143
+ next
144
+ end
140
145
  if item.name != item.root_name
141
146
  if all_buildable_items.map(&:name).include?(item.root_name)
142
147
  next # will process root spec, skip subspecs
143
148
  end
144
149
  end
150
+ if File.exist?(item.prebuilt_podspec_path)
151
+ next # skip if podspec was already generated
152
+ end
145
153
 
146
154
  podspec = "Pod::Spec.new do |p1|\n"
147
155
 
@@ -165,8 +173,17 @@ module PodBuilder
165
173
  podspec += main_keys
166
174
  podspec += "end"
167
175
 
168
- spec_path = PodBuilder::prebuiltpath("#{item.root_name}.podspec")
169
- File.write(spec_path, podspec)
176
+ spec_path = item.prebuilt_podspec_path
177
+ if File.directory?(File.dirname(spec_path))
178
+ File.write(spec_path, podspec)
179
+ else
180
+ message = "Prebuilt podspec destination not found for #{File.basename(spec_path)}".red
181
+ if ENV['DEBUGGING']
182
+ puts message
183
+ else
184
+ raise message
185
+ end
186
+ end
170
187
  end
171
188
  end
172
189
  end
@@ -1,28 +1,38 @@
1
+ # TODO: Add support when building without use_frameworks!
2
+
1
3
  require 'fourflusher'
2
4
  require 'colored'
3
5
 
4
6
  module PodBuilder
5
7
  def self.build_for_iosish_platform(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon)
6
- raise "Apple silicon hardware still unsupported since it requires to migrate to xcframeworks" if build_for_apple_silicon
7
-
8
+ raise "\n\nApple silicon hardware still unsupported since it requires to migrate to xcframeworks".red if build_for_apple_silicon
9
+
10
+ dsym_device_folder = File.join(build_dir, "dSYM", device)
11
+ dsym_simulator_folder = File.join(build_dir, "dSYM", simulator)
12
+ FileUtils.mkdir_p(dsym_device_folder)
13
+ FileUtils.mkdir_p(dsym_simulator_folder)
14
+
8
15
  deployment_target = target.platform_deployment_target
9
16
  target_label = target.cocoapods_target_label
10
-
17
+
11
18
  xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [])
12
19
  excluded_archs = build_for_apple_silicon ? [] : ["arm64"]
13
20
  xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs)
14
-
21
+
15
22
  spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
16
23
  spec_names.each do |root_name, module_name|
17
- executable_path = "#{build_dir}/#{root_name}"
18
- device_lib = "#{build_dir}/#{configuration}-#{device}/#{root_name}/#{module_name}.framework/#{module_name}"
24
+ device_base = "#{build_dir}/#{configuration}-#{device}/#{root_name}"
25
+ device_lib = "#{device_base}/#{module_name}.framework/#{module_name}"
26
+ device_dsym = "#{device_base}/#{module_name}.framework.dSYM"
19
27
  device_framework_lib = File.dirname(device_lib)
20
28
  device_swift_header_path = "#{device_framework_lib}/Headers/#{module_name}-Swift.h"
21
-
22
- simulator_lib = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}/#{module_name}.framework/#{module_name}"
29
+
30
+ simulator_base = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}"
31
+ simulator_lib = "#{simulator_base}/#{module_name}.framework/#{module_name}"
32
+ simulator_dsym = "#{simulator_base}/#{module_name}.framework.dSYM"
23
33
  simulator_framework_lib = File.dirname(simulator_lib)
24
34
  simulator_swift_header_path = "#{simulator_framework_lib}/Headers/#{module_name}-Swift.h"
25
-
35
+
26
36
  next unless File.file?(device_lib) && File.file?(simulator_lib)
27
37
 
28
38
  # Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
@@ -32,63 +42,71 @@ module PodBuilder
32
42
  #
33
43
  # For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
34
44
  if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
35
- `xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
45
+ `xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
36
46
  end
37
-
38
- lipo_log = `xcrun lipo -create -output #{executable_path} #{device_lib} #{simulator_lib}`
39
- puts lipo_log unless File.exist?(executable_path)
40
-
47
+
48
+ raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
49
+
41
50
  # Merge swift headers as per Xcode 10.2 release notes
42
51
  if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
43
52
  device_content = File.read(device_swift_header_path)
44
53
  simulator_content = File.read(simulator_swift_header_path)
45
54
  merged_content = %{
46
- #if TARGET_OS_SIMULATOR
47
- #{simulator_content}
48
- #else
49
- #{device_content}
50
- #endif
51
- }
55
+ #if TARGET_OS_SIMULATOR
56
+ #{simulator_content}
57
+ #else
58
+ #{device_content}
59
+ #endif
60
+ }
52
61
  File.write(device_swift_header_path, merged_content)
53
62
  end
54
-
55
- FileUtils.mv executable_path, device_lib, :force => true
56
- FileUtils.mv device_framework_lib, build_dir, :force => true
57
- FileUtils.rm simulator_lib if File.file?(simulator_lib)
58
- FileUtils.rm device_lib if File.file?(device_lib)
63
+
64
+ # Merge device framework into simulator framework (so that e.g swift Module folder is merged)
65
+ # letting device framework files overwrite simulator ones
66
+ FileUtils.cp_r(File.join(device_framework_lib, "."), simulator_framework_lib)
67
+ source_lib = File.dirname(simulator_framework_lib)
68
+
69
+ FileUtils.cp_r(source_lib, build_dir)
70
+
71
+ FileUtils.cp_r(device_dsym, dsym_device_folder) if File.exist?(device_dsym)
72
+ FileUtils.cp_r(simulator_dsym, dsym_simulator_folder) if File.exist?(simulator_dsym)
73
+
74
+ # Remove frameworks leaving dSYMs
75
+ FileUtils.rm_rf(device_framework_lib)
76
+ FileUtils.rm_rf(simulator_framework_lib)
59
77
  end
60
78
  end
61
-
79
+
62
80
  def self.xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, configuration, deterministic_build, exclude_archs)
63
81
  args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk})
64
82
  supported_platforms = { 'iphonesimulator' => 'iOS', 'appletvsimulator' => 'tvOS', 'watchsimulator' => 'watchOS' }
65
83
  if platform = supported_platforms[sdk]
66
84
  args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
67
85
  end
68
-
86
+
69
87
  xcodebuild_version = `xcodebuild -version | head -n1 | awk '{print $2}'`.strip().to_f
70
88
  if exclude_archs.count > 0 && xcodebuild_version >= 12.0
71
89
  args += ["EXCLUDED_ARCHS=#{exclude_archs.join(" ")}"]
72
90
  end
73
-
91
+
74
92
  environmental_variables = {}
75
93
  if deterministic_build
76
94
  environmental_variables["ZERO_AR_DATE"] = "1"
77
95
  end
78
-
96
+
79
97
  execute_command 'xcodebuild', args, true, environmental_variables
80
98
  end
81
-
99
+
82
100
  # Copy paste implementation from CocoaPods internals to be able to call poopen3 passing environmental variables
83
101
  def self.execute_command(executable, command, raise_on_failure = true, environmental_variables = {})
84
102
  bin = Pod::Executable.which!(executable)
85
-
103
+
86
104
  command = command.map(&:to_s)
87
105
  full_command = "#{bin} #{command.join(' ')}"
88
-
106
+
89
107
  stdout = Pod::Executable::Indenter.new
90
108
  stderr = Pod::Executable::Indenter.new
91
-
109
+
92
110
  status = popen3(bin, command, stdout, stderr, environmental_variables)
93
111
  stdout = stdout.join
94
112
  stderr = stderr.join
@@ -100,27 +118,27 @@ module PodBuilder
100
118
  UI.message("[!] Failed: #{full_command}".red)
101
119
  end
102
120
  end
103
-
121
+
104
122
  output
105
123
  end
106
-
124
+
107
125
  def self.popen3(bin, command, stdout, stderr, environmental_variables)
108
126
  require 'open3'
109
127
  Open3.popen3(environmental_variables, bin, *command) do |i, o, e, t|
110
128
  Pod::Executable::reader(o, stdout)
111
129
  Pod::Executable::reader(e, stderr)
112
130
  i.close
113
-
131
+
114
132
  status = t.value
115
-
133
+
116
134
  o.flush
117
135
  e.flush
118
136
  sleep(0.01)
119
-
137
+
120
138
  status
121
139
  end
122
140
  end
123
-
141
+
124
142
  def self.enable_debug_information(project_path, configuration)
125
143
  project = Xcodeproj::Project.open(project_path)
126
144
  project.targets.each do |target|
@@ -131,19 +149,7 @@ module PodBuilder
131
149
  project.save
132
150
  end
133
151
 
134
- def self.copy_dsym_files(dsym_destination, configuration)
135
- dsym_destination.rmtree if dsym_destination.directory?
136
-
137
- platforms = Configuration.supported_platforms
138
- platforms.each do |platform|
139
- dsym = Pathname.glob("build/#{configuration}-#{platform}/**/*.dSYM")
140
- dsym.each do |dsym|
141
- destination = dsym_destination + platform
142
- FileUtils.mkdir_p destination
143
- FileUtils.cp_r dsym, destination, :remove_destination => true
144
- end
145
- end
146
- end
152
+
147
153
  end
148
154
 
149
155
  Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_context, user_options|
@@ -152,15 +158,15 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
152
158
  if user_options["pre_compile"]
153
159
  user_options["pre_compile"].call(installer_context)
154
160
  end
155
-
161
+
156
162
  sandbox_root = Pathname(installer_context.sandbox_root)
157
163
  sandbox = Pod::Sandbox.new(sandbox_root)
158
-
164
+
159
165
  PodBuilder::enable_debug_information(sandbox.project_path, configuration)
160
-
166
+
161
167
  build_dir = sandbox_root.parent + 'build'
162
- destination = sandbox_root.parent + 'Rome'
163
-
168
+ base_destination = sandbox_root.parent + 'Prebuilt'
169
+
164
170
  build_dir.rmtree if build_dir.directory?
165
171
  targets = installer_context.umbrella_targets.select { |t| t.specs.any? }
166
172
  targets.each do |target|
@@ -169,80 +175,66 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
169
175
  when :osx then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
170
176
  when :tvos then PodBuilder::build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
171
177
  when :watchos then PodBuilder::build_for_iosish_platform(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
172
- else raise "Unknown platform '#{target.platform_name}'" end
173
- end
174
-
175
- raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
176
-
177
- # Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
178
- # can get upset about Info.plist containing references to the simulator SDK
179
- frameworks = Pathname.glob("build/*/*/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
180
- frameworks += Pathname.glob("build/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
181
-
182
- resources = []
183
-
184
- Pod::UI.puts "Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}"
185
-
186
- destination.rmtree if destination.directory?
187
-
188
- installer_context.umbrella_targets.each do |umbrella|
189
- umbrella.specs.each do |spec|
190
- consumer = spec.consumer(umbrella.platform_name)
191
- file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
192
- frameworks += file_accessor.vendored_libraries
193
- frameworks += file_accessor.vendored_frameworks
194
- resources += file_accessor.resources
178
+ else raise "\n\nUnknown platform '#{target.platform_name}'".red end
195
179
  end
196
- end
197
- frameworks.uniq!
198
- resources.uniq!
199
-
200
- Pod::UI.puts "Copying #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)} " \
201
- "to `#{destination.relative_path_from Pathname.pwd}`"
202
-
203
- FileUtils.mkdir_p destination
204
- (frameworks + resources).each do |file|
205
- FileUtils.cp_r file, destination, :remove_destination => true
206
- end
207
-
208
- if enable_dsym
209
- PodBuilder::copy_dsym_files(sandbox_root.parent + 'dSYM', configuration)
210
- else
211
- frameworks = Dir.glob(File.join(destination, "*.framework"))
212
-
213
- dsym_base_path = sandbox_root.parent + 'dSYM'
214
-
215
- # manually generate dSYMs
216
- frameworks.each do |framework|
217
- module_name = File.basename(framework, ".*")
218
- is_static = `file #{File.join(framework, module_name)} | grep 'ar archive' | wc -l`.strip() != "0"
219
-
220
- if !is_static
221
- destination_dSYM = File.join(dsym_base_path, "#{module_name}.dSYM")
222
- FileUtils.mkdir_p(dsym_base_path)
223
-
224
- module_path = "#{File.join(framework, module_name)}"
225
- system("xcrun dsymutil '#{module_path}' -no-swiftmodule-timestamp -o '#{destination_dSYM}' 2>/dev/null")
226
- if `xcrun codesign -v #{module_path} 2>&1 | grep 'code object is not signed at all' | wc -l`.strip() == "1"
227
- system("xcrun strip -x -S '#{module_path}'")
228
- else
229
- # Running strip on codesigned binaries triggers the following warning:
230
- # 'strip: changes being made to the file will invalidate the code signature in: path to binary'
231
- puts "#{module_name} appears to be codesigned, skipping stripping.".blue
180
+
181
+ raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
182
+
183
+ built_count = installer_context.umbrella_targets.map { |t| t.specs.map(&:name) }.flatten.map { |t| t.split("/").first }.uniq.count
184
+ Pod::UI.puts "Built #{built_count} #{'items'.pluralize(built_count)}, copying..."
185
+
186
+ base_destination.rmtree if base_destination.directory?
187
+
188
+ installer_context.umbrella_targets.each do |umbrella|
189
+ umbrella.specs.each do |spec|
190
+ root_name = spec.name.split("/").first
191
+ # Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
192
+ # can get upset about Info.plist containing references to the simulator SDK
193
+ frameworks = Pathname.glob("build/#{root_name}/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
194
+
195
+ consumer = spec.consumer(umbrella.platform_name)
196
+ file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
197
+ frameworks += file_accessor.vendored_libraries
198
+ frameworks += file_accessor.vendored_frameworks
199
+ resources = file_accessor.resources
200
+
201
+ destination = File.join(base_destination, root_name)
202
+ FileUtils.mkdir_p(destination)
203
+
204
+ files = frameworks + resources
205
+ files.each do |file|
206
+ FileUtils.cp_r(file, destination)
207
+ end
208
+ end
209
+ end
210
+
211
+ # Depending on the resource it may happen that it is present twice, both in the .framework and in the parent folder
212
+ Dir.glob("#{base_destination}/*") do |path|
213
+ unless File.directory?(path)
214
+ return
215
+ end
216
+
217
+ files = Dir.glob("#{path}/*")
218
+ framework_files = Dir.glob("#{path}/*.framework/**/*").map { |t| File.basename(t) }
219
+
220
+ files.each do |file|
221
+ filename = File.basename(file.gsub(/\.xib$/, ".nib"))
222
+ if framework_files.include?(filename)
223
+ FileUtils.rm_rf(file)
232
224
  end
233
-
234
- # Sanity check
235
- binary_uuid = `xcrun dwarfdump --uuid '#{module_path}' | cut -d" " -f2`
236
- dsym_uuid = `xcrun dwarfdump --uuid '#{File.join(destination_dSYM, "Contents", "Resources", "DWARF", module_name)}' | cut -d" " -f2`
237
-
238
- raise "dSYM sanity check failed for '#{framework}', UUID do not match!" unless binary_uuid == dsym_uuid
239
225
  end
240
226
  end
227
+
228
+ if enable_dsym
229
+ FileUtils.mv("#{build_dir}/dSYM", sandbox_root.parent)
230
+ else
231
+ raise "Not implemented"
232
+ end
233
+
234
+ build_dir.rmtree if build_dir.directory?
235
+
236
+ if user_options["post_compile"]
237
+ user_options["post_compile"].call(installer_context)
238
+ end
241
239
  end
242
-
243
- build_dir.rmtree if build_dir.directory?
244
-
245
- if user_options["post_compile"]
246
- user_options["post_compile"].call(installer_context)
247
- end
248
- end
240
+