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.
@@ -7,7 +7,7 @@ module PodBuilder
7
7
  PRE_INSTALL_ACTIONS = ["Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_duplicate_framework_and_library_names) {}"].freeze
8
8
  private_constant :PRE_INSTALL_ACTIONS
9
9
 
10
- def self.from_podfile_items(items, analyzer, build_configuration)
10
+ def self.from_podfile_items(items, analyzer, build_configuration, install_using_frameworks)
11
11
  raise "\n\nno items".red unless items.count > 0
12
12
 
13
13
  sources = analyzer.sources
@@ -17,9 +17,7 @@ module PodBuilder
17
17
 
18
18
  platform = analyzer.instance_variable_get("@result").targets.first.platform
19
19
 
20
- install_using_frameworks = install_using_frameworks(analyzer)
21
-
22
- podfile.sub!("%%%use_frameworks%%%", install_using_frameworks ? "use_frameworks!" : "")
20
+ podfile.sub!("%%%use_frameworks%%%", install_using_frameworks ? "use_frameworks!" : "use_modular_headers!")
23
21
  podfile.sub!("%%%uses_frameworks%%%", install_using_frameworks ? "true" : "false")
24
22
 
25
23
  podfile.sub!("%%%platform_name%%%", platform.name.to_s)
@@ -386,6 +384,22 @@ module PodBuilder
386
384
  resolved_names.uniq
387
385
  end
388
386
 
387
+ def self.install_using_frameworks(analyzer)
388
+ target_settings = analyzer.podfile.target_definition_list.map(&:uses_frameworks?).uniq
389
+ if target_settings.count == 1
390
+ if target_settings.first == false && ENV['DEBUGGING'].nil?
391
+ raise "\n\nOnly framework packaging currently supported. Please add 'use_frameworks!' at Podfile root level (not nested in targets)".red
392
+ end
393
+ return target_settings.first
394
+ elsif target_settings.count > 1
395
+ raise "\n\n'use_frameworks!' should be declared only once at Podfile root level (not nested in targets)".red
396
+ else
397
+ raise "\n\nFailed detecting use_frameworks!"
398
+ end
399
+
400
+ return true
401
+ end
402
+
389
403
  private
390
404
 
391
405
  def self.podfile_path_transform(path)
@@ -593,7 +607,7 @@ module PodBuilder
593
607
  base = File.expand_path(File.join(PodBuilder::project_path, ".."))
594
608
  bin_js = Dir.glob("#{base}/node_modules/@react-native-community/cli/build/bin.js")
595
609
 
596
- raise "\n\nReact native cli bin_js not found!".red unless bin_js.count == 1
610
+ raise "\n\nReact native cli bin_js not found! Did you run yarn install?".red unless bin_js.count == 1
597
611
  bin_js = bin_js.first
598
612
 
599
613
  config_dest_path = PodBuilder::basepath("rn_config.json")
@@ -678,21 +692,5 @@ module PodBuilder
678
692
 
679
693
  return podfile_content
680
694
  end
681
-
682
- def self.install_using_frameworks(analyzer)
683
- target_settings = analyzer.podfile.target_definition_list.map(&:uses_frameworks?).uniq
684
- if target_settings.count == 1
685
- if target_settings.first == false && ENV['DEBUGGING'].nil?
686
- raise "\n\nOnly framework packaging currently supported. Please add 'use_frameworks!' at Podfile root level (not nested in targets)".red
687
- end
688
- return target_settings.first
689
- elsif target_settings.count > 1
690
- raise "\n\n'use_frameworks!' should be declared only once at Podfile root level (not nested in targets)".red
691
- else
692
- raise "\n\nFailed detecting use_frameworks!"
693
- end
694
-
695
- return true
696
- end
697
695
  end
698
696
  end
@@ -3,7 +3,7 @@ require 'cocoapods/podfile.rb'
3
3
  module Pod
4
4
  class Podfile
5
5
  class TargetDefinition
6
- def pb_to_s(all_buildable_items, indent_level = 0)
6
+ def pb_to_s(all_buildable_items, indent_level = 0, parent_pods = [])
7
7
  indentation = " " * indent_level
8
8
  target_s = "#{indentation}target '#{self.name}' do\n"
9
9
 
@@ -15,7 +15,8 @@ module Pod
15
15
  prebuild_entries = []
16
16
  self.dependencies.each do |dep|
17
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
18
+ is_prebuilt = all_buildable_items.select { |t| t.root_name == dep.root_name}.all?(&:is_prebuilt)
19
+ if File.exist?(podfile_item.prebuilt_podspec_path) && !is_prebuilt
19
20
  prebuild_entries.push(podfile_item)
20
21
  else
21
22
  pod_entries.push(podfile_item)
@@ -34,7 +35,8 @@ module Pod
34
35
  non_explicit_dependencies.each do |dep|
35
36
  dep_item = all_buildable_items.detect { |x| x.name == dep.name }
36
37
 
37
- if File.exist?(dep_item.prebuilt_podspec_path) && !dep_item.is_prebuilt
38
+ is_prebuilt = all_buildable_items.select { |t| t.root_name == dep.root_name}.all?(&:is_prebuilt)
39
+ if File.exist?(dep_item.prebuilt_podspec_path) && !is_prebuilt
38
40
  prebuild_entries.push(dep_item)
39
41
  else
40
42
  pod_entries.push(dep_item)
@@ -47,6 +49,10 @@ module Pod
47
49
 
48
50
  prebuild_entries = prebuild_entries.uniq.sort_by { |t| t.name }
49
51
  pod_entries = pod_entries.uniq.sort_by { |t| t.name }
52
+
53
+ # Don't include inherited pods
54
+ prebuild_entries.reject! { |t| parent_pods.include?(t) }
55
+ pod_entries.reject! { |t| parent_pods.include?(t) }
50
56
 
51
57
  prebuild_entries.each do |pod|
52
58
  target_s += "#{child_indentation}#{pod.prebuilt_entry(false, false)}\n"
@@ -57,7 +63,7 @@ module Pod
57
63
 
58
64
  if self.children.count > 0
59
65
  target_s += "\n"
60
- target_s += @children.map { |t| t.pb_to_s(all_buildable_items, indent_level + 1) }.join("\n\n")
66
+ target_s += @children.map { |t| t.pb_to_s(all_buildable_items, indent_level + 1, parent_pods + pod_entries + prebuild_entries) }.join("\n\n")
61
67
  end
62
68
 
63
69
  target_s += "#{indentation}end\n"
@@ -79,6 +79,10 @@ module PodBuilder
79
79
  #
80
80
  attr_accessor :build_configuration
81
81
 
82
+ # @return [Array<String>] When building static frameworks we sometimes have to remove module maps from Other C flags to make compilation succeed
83
+ #
84
+ attr_accessor :remove_module_maps
85
+
82
86
  # @return [String] The pod's vendored frameworks
83
87
  #
84
88
  attr_accessor :vendored_frameworks
@@ -180,7 +184,11 @@ module PodBuilder
180
184
 
181
185
  @default_subspecs = extract_array(spec, "default_subspecs")
182
186
  if default_subspec = spec.attributes_hash["default_subspec"]
183
- @default_subspecs.push(default_subspec)
187
+ @default_subspecs.push(default_subspec)
188
+ end
189
+
190
+ if @name == @root_name && @default_subspecs.empty?
191
+ @default_subspecs += all_specs.select { |t| t.name.include?("/") && t.name.split("/").first == @root_name }.map { |t| t.name.split("/").last }
184
192
  end
185
193
 
186
194
  @dependency_names = spec.attributes_hash.fetch("dependencies", {}).keys + default_subspecs.map { |t| "#{@root_name}/#{t}" }
@@ -194,11 +202,18 @@ module PodBuilder
194
202
  @is_static = spec.root.attributes_hash["static_framework"] || false
195
203
  @xcconfig = spec.root.attributes_hash["xcconfig"] || {}
196
204
 
197
- @source_files = source_files_from(spec)
205
+ default_subspecs_specs ||= begin
206
+ subspecs = all_specs.select { |t| t.name.split("/").first == @root_name }
207
+ subspecs.select { |t| @default_subspecs.include?(t.name.split("/").last) }
208
+ end
209
+ root_spec = all_specs.detect { |t| t.name == @root_name } || spec
210
+ @source_files = source_files_from([spec, root_spec] + default_subspecs_specs)
198
211
 
199
212
  @build_configuration = spec.root.attributes_hash.dig("pod_target_xcconfig", "prebuild_configuration") || "release"
200
213
  @build_configuration.downcase!
201
214
 
215
+ @remove_module_maps = spec.root.attributes_hash["remove_module_maps"] || []
216
+
202
217
  default_license = "MIT"
203
218
  @license = spec.root.attributes_hash.fetch("license", {"type"=>"#{default_license}"})["type"] || default_license
204
219
  @summary = spec.root.attributes_hash.fetch("summary", "A summary for #{@name}")
@@ -287,7 +302,7 @@ module PodBuilder
287
302
  #
288
303
  # When building PodA we need to build both DepA subspecs because they might
289
304
  # contain different code
290
- deps += available_pods.select { |t| root_names.include?(t.root_name) }
305
+ deps += available_pods.select { |t| root_names.include?(t.root_name) && t.root_name != t.name }
291
306
 
292
307
  deps.uniq!
293
308
 
@@ -389,11 +404,7 @@ module PodBuilder
389
404
  end
390
405
 
391
406
  def prebuilt_rel_path
392
- if is_subspec && Configuration.subspecs_to_split.include?(name)
393
- return "#{name}/#{module_name}.framework"
394
- else
395
- return "#{module_name}.framework"
396
- end
407
+ return "#{module_name}.framework"
397
408
  end
398
409
 
399
410
  def prebuilt_podspec_path(absolute_path = true)
@@ -408,11 +419,7 @@ module PodBuilder
408
419
  def prebuilt_entry(include_pb_entry = true, absolute_path = false)
409
420
  podspec_dirname = File.dirname(prebuilt_podspec_path(absolute_path = absolute_path))
410
421
 
411
- if Configuration.subspecs_to_split.include?(name)
412
- entry = "pod '#{podspec_name}', :path => '#{podspec_dirname}'"
413
- else
414
- entry = "pod '#{name}', :path => '#{podspec_dirname}'"
415
- end
422
+ entry = "pod '#{name}', :path => '#{podspec_dirname}'"
416
423
 
417
424
  if include_pb_entry && !is_prebuilt
418
425
  entry += prebuilt_marker()
@@ -518,28 +525,9 @@ module PodBuilder
518
525
  end
519
526
  end
520
527
 
521
- def source_files_from(spec)
522
- files = spec.root.attributes_hash.fetch("source_files", [])
523
- root_source_files = source_files_from_string(files)
524
-
525
- files = spec.attributes_hash.fetch("source_files", [])
526
- source_files = source_files_from_string(files)
527
-
528
- subspec_source_files = []
529
- if spec.name == spec.root.name
530
- default_podspecs = spec.attributes_hash.fetch("default_subspecs", [])
531
- if default_podspecs.is_a? String
532
- default_podspecs = [default_podspecs]
533
- end
534
- default_podspecs.each do |subspec_name|
535
- if subspec = spec.subspecs.detect { |x| x.name == "#{spec.root.name}/#{subspec_name}" }
536
- files = subspec.attributes_hash.fetch("source_files", [])
537
- subspec_source_files += source_files_from_string(files)
538
- end
539
- end
540
- end
541
-
542
- return source_files + root_source_files + subspec_source_files
528
+ def source_files_from(specs)
529
+ files = specs.map { |t| t.attributes_hash.fetch("source_files", []) }.flatten
530
+ return source_files_from_string(files).uniq
543
531
  end
544
532
  end
545
533
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  module PodBuilder
5
5
  class Podspec
6
- def self.generate(all_buildable_items, analyzer)
6
+ def self.generate(all_buildable_items, analyzer, install_using_frameworks)
7
7
  unless all_buildable_items.count > 0
8
8
  return
9
9
  end
@@ -11,12 +11,12 @@ module PodBuilder
11
11
  puts "Generating PodBuilder's local podspec".yellow
12
12
 
13
13
  platform = analyzer.instance_variable_get("@result").targets.first.platform
14
- generate_podspec_from(all_buildable_items, platform)
14
+ generate_podspec_from(all_buildable_items, platform, install_using_frameworks)
15
15
  end
16
16
 
17
17
  private
18
18
 
19
- def self.generate_spec_keys_for(item, name, all_buildable_items)
19
+ def self.generate_spec_keys_for(item, name, all_buildable_items, install_using_frameworks)
20
20
  podspec = ""
21
21
  valid = false
22
22
 
@@ -24,46 +24,80 @@ module PodBuilder
24
24
  indentation = " " * slash_count
25
25
  spec_var = "p#{slash_count}"
26
26
 
27
+ if spec_var == "p1" && item.default_subspecs.count > 0
28
+ podspec += "#{indentation}#{spec_var}.default_subspecs = '#{item.default_subspecs.join("', '")}'\n"
29
+ end
30
+
27
31
  if item.name == name
28
32
  if_exists = lambda { |t| File.exist?(PodBuilder::prebuiltpath("#{item.root_name}/#{t}") || "") }
29
33
 
30
- vendored_frameworks = item.vendored_frameworks + ["#{item.module_name}.framework"]
34
+ vendored_frameworks = item.vendored_frameworks
35
+ if item.default_subspecs.count == 0 && install_using_frameworks
36
+ vendored_frameworks += ["#{item.module_name}.framework"]
37
+ end
38
+
31
39
  existing_vendored_frameworks = vendored_frameworks.select(&if_exists)
32
40
  existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select(&if_exists)
33
41
  vendored_frameworks = (existing_vendored_frameworks + existing_vendored_frameworks_basename).uniq
34
42
 
35
43
  vendored_libraries = item.vendored_libraries
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
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)
41
- vendored_libraries.reject! { |t| t.end_with?(".a") }
42
-
43
- frameworks = all_buildable_items.select { |t| vendored_frameworks.include?("#{t.module_name}.framework") }.uniq
44
- static_frameworks = frameworks.select { |x| x.is_static }
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
47
- exclude_files = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
44
+ if install_using_frameworks
45
+ existing_vendored_libraries = vendored_libraries.map { |t| "#{item.module_name}/#{t}" }.select(&if_exists)
46
+ existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename(t) }.select(&if_exists)
47
+ vendored_libraries = (existing_vendored_libraries + existing_vendored_libraries_basename).uniq
48
+
49
+ # .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)
50
+ vendored_libraries.reject! { |t| t.end_with?(".a") }
51
+
52
+ frameworks = all_buildable_items.select { |t| vendored_frameworks.include?("#{t.module_name}.framework") }.uniq
53
+ static_frameworks = frameworks.select { |x| x.is_static }
54
+
55
+ 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
56
+
57
+ exclude_files = static_frameworks.map { |x| x.vendored_framework_path.nil? ? nil : "#{x.vendored_framework_path}/Info.plist" }.compact.flatten.uniq
58
+ public_headers = []
59
+ else
60
+ public_headers = Dir.glob(PodBuilder::prebuiltpath("#{item.root_name}/#{item.root_name}/Headers/**/*.h"))
61
+ vendored_libraries += ["#{item.root_name}/lib#{item.root_name}.a"]
62
+ vendored_libraries.map! { |t| "#{item.root_name}/#{t}" }.select(&if_exists)
63
+
64
+ resources = ["#{item.root_name}/*.{nib,bundle,xcasset,strings,png,jpg,tif,tiff,otf,ttf,ttc,plist,json,caf,wav,p12,momd}"]
65
+
66
+ exclude_files = ["*.modulemap"]
67
+ unless item.swift_version.nil?
68
+ exclude_files += ["Swift Compatibility Header/*", "*.swiftmodule"]
69
+ end
70
+ exclude_files.map! { |t| "#{item.root_name}/#{t}" }
71
+ end
72
+
73
+ entries = lambda { |spec_key, spec_value|
74
+ key = "#{indentation}#{spec_var}.#{spec_key}"
75
+ joined_values = spec_value.map { |t| "#{t}" }.uniq.sort.join("', '")
76
+ "#{key} = '#{joined_values}'\n"
77
+ }
48
78
 
49
79
  if vendored_frameworks.count > 0
50
- podspec += "#{indentation}#{spec_var}.vendored_frameworks = '#{vendored_frameworks.uniq.sort.join("','")}'\n"
80
+ podspec += entries.call("vendored_frameworks", vendored_frameworks)
51
81
  end
52
82
  if vendored_libraries.count > 0
53
- podspec += "#{indentation}#{spec_var}.vendored_libraries = '#{vendored_libraries.uniq.sort.join("','")}'\n"
83
+ podspec += entries.call("vendored_libraries", vendored_libraries)
54
84
  end
55
85
  if item.frameworks.count > 0
56
- podspec += "#{indentation}#{spec_var}.frameworks = '#{item.frameworks.uniq.sort.join("', '")}'\n"
86
+ podspec += entries.call("frameworks", item.frameworks)
57
87
  end
58
88
  if item.libraries.count > 0
59
- podspec += "#{indentation}#{spec_var}.libraries = '#{item.libraries.uniq.sort.join("', '")}'\n"
89
+ podspec += entries.call("libraries", item.libraries)
60
90
  end
61
91
  if resources.count > 0
62
- podspec += "#{indentation}#{spec_var}.resources = '#{resources.uniq.sort.join("', '")}'\n"
92
+ podspec += entries.call("resources", resources)
63
93
  end
64
94
  if exclude_files.count > 0
65
- podspec += "#{indentation}#{spec_var}.exclude_files = '#{exclude_files.uniq.sort.join("', '")}'\n"
95
+ podspec += entries.call("exclude_files", exclude_files)
96
+ end
97
+ if public_headers.count > 0
98
+ podspec += "#{indentation}#{spec_var}.public_header_files = '#{item.root_name}/Headers/**/*.h'\n"
66
99
  end
100
+
67
101
  if item.xcconfig.keys.count > 0
68
102
  xcconfig = Hash.new
69
103
  item.xcconfig.each do |k, v|
@@ -88,6 +122,21 @@ module PodBuilder
88
122
  podspec += "#{indentation}#{spec_var}.xcconfig = #{xcconfig.to_s}\n"
89
123
  end
90
124
  end
125
+ if !install_using_frameworks && spec_var == "p1"
126
+ module_path_files = Dir.glob(PodBuilder.prebuiltpath("#{item.root_name}/**/#{item.root_name}.modulemap"))
127
+ raise "\n\nToo many module maps found for #{item.root_name}".red if module_path_files.count > 1
128
+ if module_path_file = module_path_files.first
129
+ rel_path = Pathname.new(PodBuilder::prebuiltpath).relative_path_from(Pathname.new(PodBuilder::project_path("Pods"))).to_s
130
+ prebuilt_root_var = "#{item.root_name.upcase.gsub("-", "_")}_PREBUILT_ROOT"
131
+ module_map_rel = module_path_file.gsub(PodBuilder::prebuiltpath("#{item.root_name}/#{item.root_name}/"), "")
132
+ static_cfg = { prebuilt_root_var => "$(PODS_ROOT)/#{rel_path}",
133
+ "SWIFT_INCLUDE_PATHS" => "$(inherited) \"$(#{prebuilt_root_var})/#{item.root_name}/#{item.root_name}\"",
134
+ "OTHER_CFLAGS" => "$(inherited) -fmodule-map-file=\"$(#{prebuilt_root_var})/#{item.root_name}/#{item.root_name}/#{module_map_rel}\"",
135
+ "OTHER_SWIFT_FLAGS" => "$(inherited) -Xcc -fmodule-map-file=\"$(#{prebuilt_root_var})/#{item.root_name}/#{item.root_name}/#{module_map_rel}\""
136
+ }
137
+ podspec += "#{indentation}#{spec_var}.xcconfig = #{static_cfg.to_s}\n"
138
+ end
139
+ end
91
140
 
92
141
  deps = item.dependency_names.sort
93
142
  if name == item.root_name
@@ -103,7 +152,7 @@ module PodBuilder
103
152
  end
104
153
  end
105
154
 
106
- valid = valid || vendored_frameworks.count > 0
155
+ valid = valid || (install_using_frameworks ? vendored_frameworks.count > 0 : vendored_libraries.count > 0)
107
156
  end
108
157
 
109
158
  subspec_names = all_buildable_items.map(&:name).select { |t| t.start_with?("#{name}/") }
@@ -117,7 +166,7 @@ module PodBuilder
117
166
  podspec += "\n"
118
167
  end
119
168
 
120
- subspec_keys, subspec_valid = generate_spec_keys_for(subspec_item, subspec, all_buildable_items)
169
+ subspec_keys, subspec_valid = generate_spec_keys_for(subspec_item, subspec, all_buildable_items, install_using_frameworks)
121
170
  valid = valid || subspec_valid
122
171
 
123
172
  if subspec_keys.length > 0
@@ -130,7 +179,7 @@ module PodBuilder
130
179
  return podspec, valid
131
180
  end
132
181
 
133
- def self.generate_podspec_from(all_buildable_items, platform)
182
+ def self.generate_podspec_from(all_buildable_items, platform, install_using_frameworks)
134
183
  prebuilt_podspec_path = all_buildable_items.map(&:prebuilt_podspec_path)
135
184
  prebuilt_podspec_path.each do |path|
136
185
  if File.exist?(path)
@@ -165,7 +214,7 @@ module PodBuilder
165
214
  podspec += " p1.#{platform.safe_string_name.downcase}.deployment_target = '#{platform.deployment_target.version}'\n"
166
215
  podspec += "\n"
167
216
 
168
- main_keys, valid = generate_spec_keys_for(item, item.root_name, all_buildable_items)
217
+ main_keys, valid = generate_spec_keys_for(item, item.root_name, all_buildable_items, install_using_frameworks)
169
218
  if !valid
170
219
  next
171
220
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'fourflusher'
4
4
  require 'colored'
5
+ require 'pathname'
5
6
 
6
7
  module PodBuilder
7
8
  def self.build_for_iosish_platform_framework(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon)
@@ -15,9 +16,9 @@ module PodBuilder
15
16
  deployment_target = target.platform_deployment_target
16
17
  target_label = target.cocoapods_target_label
17
18
 
18
- xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [])
19
+ xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [], {})
19
20
  excluded_archs = build_for_apple_silicon ? [] : ["arm64"]
20
- xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs)
21
+ xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs, {})
21
22
 
22
23
  spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
23
24
  spec_names.each do |root_name, module_name|
@@ -47,29 +48,17 @@ module PodBuilder
47
48
 
48
49
  raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
49
50
 
50
- # Merge swift headers as per Xcode 10.2 release notes
51
- if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
52
- device_content = File.read(device_swift_header_path)
53
- simulator_content = File.read(simulator_swift_header_path)
54
- merged_content = %{
55
- #if TARGET_OS_SIMULATOR
56
- #{simulator_content}
57
- #else
58
- #{device_content}
59
- #endif
60
- }
61
- File.write(device_swift_header_path, merged_content)
62
- end
51
+ merge_header_into(device_swift_header_path, simulator_swift_header_path)
63
52
 
64
53
  # Merge device framework into simulator framework (so that e.g swift Module folder is merged)
65
54
  # letting device framework files overwrite simulator ones
66
55
  FileUtils.cp_r(File.join(device_framework_lib, "."), simulator_framework_lib)
67
56
  source_lib = File.dirname(simulator_framework_lib)
68
57
 
69
- FileUtils.cp_r(source_lib, build_dir)
58
+ FileUtils.mv(device_dsym, dsym_device_folder) if File.exist?(device_dsym)
59
+ FileUtils.mv(simulator_dsym, dsym_simulator_folder) if File.exist?(simulator_dsym)
70
60
 
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)
61
+ FileUtils.mv(source_lib, build_dir)
73
62
 
74
63
  # Remove frameworks leaving dSYMs
75
64
  FileUtils.rm_rf(device_framework_lib)
@@ -77,165 +66,130 @@ module PodBuilder
77
66
  end
78
67
  end
79
68
 
80
- def self.build_for_iosish_platform_lib(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon)
69
+ def self.build_for_iosish_platform_lib(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, build_for_apple_silicon, prebuilt_root_paths)
81
70
  raise "\n\nApple silicon hardware still unsupported since it requires to migrate to xcframeworks".red if build_for_apple_silicon
82
-
83
- device_headers_folder = File.join(build_dir, "Headers", device)
84
- simulator_headers_folder = File.join(build_dir, "Headers", simulator)
85
- FileUtils.mkdir_p(device_headers_folder)
86
- FileUtils.mkdir_p(simulator_headers_folder)
87
71
 
88
72
  deployment_target = target.platform_deployment_target
89
73
  target_label = target.cocoapods_target_label
90
74
 
91
75
  spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
92
76
 
93
- xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [])
94
- spec_names.each do |root_name, module_name|
95
- headers_private = "#{sandbox.headers_root.to_s}/Private/#{root_name}/#{module_name}"
96
- headers_public = "#{sandbox.headers_root.to_s}/Public/#{root_name}/#{module_name}"
97
-
98
- device_base = "#{build_dir}/#{configuration}-#{device}/#{root_name}"
99
- device_lib = "#{device_base}/lib#{module_name}.a"
100
-
101
- FileUtils.cp headers_private, device_headers_folder
102
- FileUtils.cp headers_public, device_headers_folder
103
- end
104
-
77
+ xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [], prebuilt_root_paths)
105
78
  excluded_archs = build_for_apple_silicon ? [] : ["arm64"]
106
- xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs)
79
+ xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs, prebuilt_root_paths)
80
+
107
81
  spec_names.each do |root_name, module_name|
108
- headers_private = "#{sandbox.headers_root.to_s}/Private/#{root_name}/#{module_name}"
109
- headers_public = "#{sandbox.headers_root.to_s}/Public/#{root_name}/#{module_name}"
110
-
111
82
  simulator_base = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}"
112
83
  simulator_lib = "#{simulator_base}/lib#{module_name}.a"
113
84
 
114
- FileUtils.cp headers_private, simulator_headers_folder
115
- FileUtils.cp headers_public, simulator_headers_folder
116
- end
117
-
118
- spec_names.each do |root_name, module_name|
119
- device_headers_private = ""
120
- device_headers_public = ""
121
- simulator_headers_private = ""
122
- simulator_headers_public = ""
123
-
124
85
  device_base = "#{build_dir}/#{configuration}-#{device}/#{root_name}"
125
- device_lib = "#{device_base}/lib#{module_name}.a"
126
- simulator_base = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}"
127
- simulator_lib = "#{simulator_base}/lib#{module_name}.a"
86
+ device_lib = "#{device_base}/lib#{root_name}.a"
128
87
 
129
- next unless File.file?(device_lib) && File.file?(simulator_lib)
130
-
131
- # Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
132
- # when creating the fat library. A naive workaround is to remove the arm64 from the simulator_lib however this is wrong because
133
- # we might actually need to have 2 separated arm64 slices, one for simulator and one for device each built with different
134
- # compile time directives (e.g #if targetEnvironment(simulator))
135
- #
136
- # For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
137
- if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
138
- `xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
139
- end
140
-
141
- raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
142
-
143
- # Merge swift headers as per Xcode 10.2 release notes
144
- if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
145
- device_content = File.read(device_swift_header_path)
146
- simulator_content = File.read(simulator_swift_header_path)
147
- merged_content = %{
148
- #if TARGET_OS_SIMULATOR
149
- #{simulator_content}
150
- #else
151
- #{device_content}
152
- #endif
153
- }
154
- File.write(device_swift_header_path, merged_content)
88
+ if File.file?(device_lib) && File.file?(simulator_lib)
89
+ # Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
90
+ # when creating the fat library. A naive workaround is to remove the arm64 from the simulator_lib however this is wrong because
91
+ # we might actually need to have 2 separated arm64 slices, one for simulator and one for device each built with different
92
+ # compile time directives (e.g #if targetEnvironment(simulator))
93
+ #
94
+ # For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
95
+ if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
96
+ `xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
97
+ end
98
+
99
+ raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
155
100
  end
156
101
 
102
+ device_headers = Dir.glob("#{device_base}/**/*.h")
103
+ simulator_headers = Dir.glob("#{simulator_base}/**/*.h")
104
+ device_headers.each do |device_path|
105
+ simulator_path = device_path.gsub(device_base, simulator_base)
106
+
107
+ merge_header_into(device_path, simulator_path)
108
+ end
109
+ simulator_only_headers = simulator_headers - device_headers.map { |t| t.gsub(device_base, simulator_base) }
110
+ simulator_only_headers.each do |path|
111
+ add_simulator_conditional(path)
112
+ dir_name = File.dirname(path)
113
+ destination_folder = dir_name.gsub(simulator_base, device_base)
114
+ FileUtils.mkdir_p(destination_folder)
115
+ FileUtils.cp(path, destination_folder)
116
+ end
157
117
 
158
- end
159
-
160
-
118
+ swiftmodule_path = "#{simulator_base}/#{root_name}.swiftmodule"
119
+ if File.directory?(swiftmodule_path)
120
+ FileUtils.cp_r("#{swiftmodule_path}/.", "#{device_base}/#{root_name}.swiftmodule")
121
+ end
161
122
 
162
- spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
163
- spec_names.each do |root_name, module_name|
164
- device_base = "#{build_dir}/#{configuration}-#{device}/#{root_name}"
165
- device_lib = "#{device_base}/#{module_name}.framework/#{module_name}"
166
- device_dsym = "#{device_base}/#{module_name}.framework.dSYM"
167
- device_framework_lib = File.dirname(device_lib)
168
- device_swift_header_path = "#{device_framework_lib}/Headers/#{module_name}-Swift.h"
169
-
170
- simulator_base = "#{build_dir}/#{configuration}-#{simulator}/#{root_name}"
171
- simulator_lib = "#{simulator_base}/#{module_name}.framework/#{module_name}"
172
- simulator_dsym = "#{simulator_base}/#{module_name}.framework.dSYM"
173
- simulator_framework_lib = File.dirname(simulator_lib)
174
- simulator_swift_header_path = "#{simulator_framework_lib}/Headers/#{module_name}-Swift.h"
175
-
176
- next unless File.file?(device_lib) && File.file?(simulator_lib)
177
-
178
- # Starting with Xcode 12b3 the simulator binary contains an arm64 slice as well which conflict with the one in the device_lib
179
- # when creating the fat library. A naive workaround is to remove the arm64 from the simulator_lib however this is wrong because
180
- # we might actually need to have 2 separated arm64 slices, one for simulator and one for device each built with different
181
- # compile time directives (e.g #if targetEnvironment(simulator))
182
- #
183
- # For the time being we remove the arm64 slice bacause otherwise the `xcrun lipo -create -output ...` would fail.
184
- if `xcrun lipo -info #{simulator_lib}`.include?("arm64")
185
- `xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
123
+ if File.exist?("#{device_base}/#{root_name}.swiftmodule")
124
+ # This is a swift pod with a swiftmodule in the root of the prebuilt folder
125
+ else
126
+ # Objective-C pods have the swiftmodule generated under Pods/Headers/Public
127
+ public_headers_path = "#{Configuration.build_path}/Pods/Headers/Public/#{root_name}"
128
+ module_public_headers_path = "#{Configuration.build_path}/Pods/Headers/Public/#{module_name}"
129
+ if public_headers_path.downcase != module_public_headers_path.downcase && File.directory?(public_headers_path) && File.directory?(module_public_headers_path)
130
+ # For pods with module_name != name we have to move the modulemap files to the root_name one
131
+ module_public_headers_path = "#{Configuration.build_path}/Pods/Headers/Public/#{module_name}"
132
+ FileUtils.cp_r("#{module_public_headers_path}/.", public_headers_path)
133
+ end
134
+ Dir.glob("#{public_headers_path}/**/*.*").each do |path|
135
+ destination_folder = "#{device_base}/Headers" + path.gsub(public_headers_path, "")
136
+ destination_folder = File.dirname(destination_folder)
137
+ FileUtils.mkdir_p(destination_folder)
138
+ FileUtils.cp(path, destination_folder)
139
+ end
186
140
  end
187
-
188
- raise "Lipo failed on #{device_lib}" unless system("xcrun lipo -create -output #{device_lib} #{device_lib} #{simulator_lib}")
189
-
190
- # Merge swift headers as per Xcode 10.2 release notes
191
- if File.exist?(device_swift_header_path) && File.exist?(simulator_swift_header_path)
192
- device_content = File.read(device_swift_header_path)
193
- simulator_content = File.read(simulator_swift_header_path)
194
- merged_content = %{
195
- #if TARGET_OS_SIMULATOR
196
- #{simulator_content}
197
- #else
198
- #{device_content}
199
- #endif
200
- }
201
- File.write(device_swift_header_path, merged_content)
141
+
142
+ destination_path = "#{build_dir}/#{root_name}"
143
+ if Dir.glob("#{device_base}/**/*.{a,framework,h}").count > 0
144
+ FileUtils.mv(device_base, destination_path)
145
+
146
+ module_maps = Dir.glob("#{destination_path}/**/*.modulemap")
147
+ module_map_device_base = device_base.gsub(/^\/private/, "") + "/"
148
+ module_maps.each do |module_map|
149
+ content = File.read(module_map)
150
+ content.gsub!(module_map_device_base, "")
151
+ File.write(module_map, content)
152
+ end
202
153
  end
203
-
204
- # # Merge device framework into simulator framework (so that e.g swift Module folder is merged)
205
- # # letting device framework files overwrite simulator ones
206
- # FileUtils.cp_r(File.join(device_framework_lib, "."), simulator_framework_lib)
207
- # source_lib = File.dirname(simulator_framework_lib)
208
-
209
- # FileUtils.cp_r(source_lib, build_dir)
210
-
211
- # FileUtils.cp_r(device_dsym, dsym_device_folder) if File.exist?(device_dsym)
212
- # FileUtils.cp_r(simulator_dsym, dsym_simulator_folder) if File.exist?(simulator_dsym)
213
-
214
- # # Remove frameworks leaving dSYMs
215
- # FileUtils.rm_rf(device_framework_lib)
216
- # FileUtils.rm_rf(simulator_framework_lib)
217
154
  end
218
155
  end
219
156
 
157
+ def self.merge_header_into(device_file, simulator_file)
158
+ unless File.exist?(device_file) || File.exist?(simulator_file)
159
+ return
160
+ end
161
+
162
+ device_content = File.file?(device_file) ? File.read(device_file) : ""
163
+ simulator_content = File.file?(simulator_file) ? File.read(simulator_file) : ""
164
+ merged_content = %{
165
+ #if TARGET_OS_SIMULATOR
166
+ // ->
167
+
168
+ #{simulator_content}
169
+
170
+ // ->
171
+ #else
172
+ // ->
173
+
174
+ #{device_content}
175
+
176
+ // ->
177
+ #endif
178
+ }
179
+ File.write(device_file, merged_content)
180
+ end
181
+
182
+ def self.add_simulator_conditional(path)
183
+ file_content = File.read(path)
184
+ content = %{
185
+ #if TARGET_OS_SIMULATOR
186
+ #{file_content}
187
+ #endif
188
+ }
189
+ File.write(path, content)
190
+ end
220
191
 
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
- def self.xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, configuration, deterministic_build, exclude_archs)
192
+ def self.xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, configuration, deterministic_build, exclude_archs, prebuilt_root_paths)
239
193
  args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk})
240
194
  supported_platforms = { 'iphonesimulator' => 'iOS', 'appletvsimulator' => 'tvOS', 'watchsimulator' => 'watchOS' }
241
195
  if platform = supported_platforms[sdk]
@@ -246,6 +200,9 @@ module PodBuilder
246
200
  if exclude_archs.count > 0 && xcodebuild_version >= 12.0
247
201
  args += ["EXCLUDED_ARCHS=#{exclude_archs.join(" ")}"]
248
202
  end
203
+ prebuilt_root_paths.each do |k, v|
204
+ args += ["#{k.upcase.gsub("-", "_")}_PREBUILT_ROOT=#{v.gsub(/ /, '\ ')}"]
205
+ end
249
206
 
250
207
  environmental_variables = {}
251
208
  if deterministic_build
@@ -306,8 +263,6 @@ module PodBuilder
306
263
  end
307
264
  project.save
308
265
  end
309
-
310
-
311
266
  end
312
267
 
313
268
  Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_context, user_options|
@@ -317,6 +272,8 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
317
272
  if user_options["pre_compile"]
318
273
  user_options["pre_compile"].call(installer_context)
319
274
  end
275
+
276
+ prebuilt_root_paths = JSON.parse(user_options["prebuilt_root_paths"].gsub('=>', ':'))
320
277
 
321
278
  sandbox_root = Pathname(installer_context.sandbox_root)
322
279
  sandbox = Pod::Sandbox.new(sandbox_root)
@@ -331,19 +288,20 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
331
288
  targets.each do |target|
332
289
  case [target.platform_name, uses_frameworks]
333
290
  when [:ios, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
334
- when [:osx, true] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
291
+ when [:osx, true] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon, {})
335
292
  when [:tvos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
336
293
  when [:watchos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
337
- when [:ios, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
338
- when [:osx, false] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
339
- when [:tvos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
340
- when [:watchos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon)
294
+ when [:ios, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon, prebuilt_root_paths)
295
+ when [:osx, false] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon, prebuilt_root_paths)
296
+ when [:tvos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon, prebuilt_root_paths)
297
+ when [:watchos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, PodBuilder::Configuration.build_for_apple_silicon, prebuilt_root_paths)
341
298
  else raise "\n\nUnknown platform '#{target.platform_name}'".red end
342
299
  end
343
300
 
344
301
  raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
345
302
 
346
- built_count = installer_context.umbrella_targets.map { |t| t.specs.map(&:name) }.flatten.map { |t| t.split("/").first }.uniq.count
303
+ specs = installer_context.umbrella_targets.map { |t| t.specs.map(&:name) }.flatten.map { |t| t.split("/").first }.uniq
304
+ built_count = Dir["#{build_dir}/*"].select { |t| specs.include?(File.basename(t)) }.count
347
305
  Pod::UI.puts "Built #{built_count} #{'items'.pluralize(built_count)}, copying..."
348
306
 
349
307
  base_destination.rmtree if base_destination.directory?
@@ -351,20 +309,23 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
351
309
  installer_context.umbrella_targets.each do |umbrella|
352
310
  umbrella.specs.each do |spec|
353
311
  root_name = spec.name.split("/").first
312
+
313
+ if uses_frameworks
314
+ destination = File.join(base_destination, root_name)
315
+ else
316
+ destination = File.join(base_destination, root_name, root_name)
317
+ end
354
318
  # Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
355
319
  # can get upset about Info.plist containing references to the simulator SDK
356
- frameworks = Pathname.glob("build/#{root_name}/*.framework").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
357
-
320
+ files = Pathname.glob("build/#{root_name}/*").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
321
+
358
322
  consumer = spec.consumer(umbrella.platform_name)
359
323
  file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
360
- frameworks += file_accessor.vendored_libraries
361
- frameworks += file_accessor.vendored_frameworks
362
- resources = file_accessor.resources
363
-
364
- destination = File.join(base_destination, root_name)
365
- FileUtils.mkdir_p(destination)
366
-
367
- files = frameworks + resources
324
+ files += file_accessor.vendored_libraries
325
+ files += file_accessor.vendored_frameworks
326
+ files += file_accessor.resources
327
+
328
+ FileUtils.mkdir_p(destination)
368
329
  files.each do |file|
369
330
  FileUtils.cp_r(file, destination)
370
331
  end
@@ -389,7 +350,10 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
389
350
  end
390
351
 
391
352
  if enable_dsym
392
- FileUtils.mv("#{build_dir}/dSYM", sandbox_root.parent)
353
+ dsym_source = "#{build_dir}/dSYM"
354
+ if File.directory?(dsym_source)
355
+ FileUtils.mv(dsym_source, sandbox_root.parent)
356
+ end
393
357
  else
394
358
  raise "Not implemented"
395
359
  end