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.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/Example/{Frameworks → PodBuilder}/.gitignore +0 -0
- data/Example/{Frameworks → PodBuilder}/.pod_builder/pod_builder +0 -0
- data/Example/{Frameworks → PodBuilder}/PodBuilder.json +0 -0
- data/Example/{Frameworks → PodBuilder}/Podfile +0 -0
- data/Example/{Frameworks → PodBuilder}/Podfile.restore +0 -0
- data/Example/Podfile +27 -29
- data/Example/Podfile.lock +42 -42
- data/README.md +13 -13
- data/exe/pod_builder +27 -16
- data/lib/pod_builder/command/build.rb +28 -159
- data/lib/pod_builder/command/build_all.rb +2 -2
- data/lib/pod_builder/command/clean.rb +34 -53
- data/lib/pod_builder/command/clear_lldbinit.rb +6 -2
- data/lib/pod_builder/command/deintegrate.rb +27 -6
- data/lib/pod_builder/command/generate_lfs.rb +1 -1
- data/lib/pod_builder/command/generate_podspec.rb +3 -2
- data/lib/pod_builder/command/info.rb +1 -1
- data/lib/pod_builder/command/init.rb +37 -14
- data/lib/pod_builder/command/install_sources.rb +20 -13
- data/lib/pod_builder/command/none.rb +2 -2
- data/lib/pod_builder/command/restore_all.rb +4 -4
- data/lib/pod_builder/command/switch.rb +56 -14
- data/lib/pod_builder/command/sync_podfile.rb +3 -2
- data/lib/pod_builder/command/update.rb +5 -6
- data/lib/pod_builder/command/update_lldbinit.rb +10 -8
- data/lib/pod_builder/configuration.rb +27 -7
- data/lib/pod_builder/core.rb +35 -9
- data/lib/pod_builder/info.rb +11 -11
- data/lib/pod_builder/install.rb +178 -184
- data/lib/pod_builder/licenses.rb +4 -4
- data/lib/pod_builder/podfile.rb +226 -85
- data/lib/pod_builder/podfile/post_actions.rb +9 -14
- data/lib/pod_builder/podfile_cp.rb +93 -0
- data/lib/pod_builder/podfile_item.rb +41 -20
- data/lib/pod_builder/podspec.rb +33 -16
- data/lib/pod_builder/rome/post_install.rb +121 -129
- data/lib/pod_builder/rome/pre_install.rb +1 -1
- data/lib/pod_builder/templates/build_podfile.template +2 -2
- data/lib/pod_builder/version.rb +1 -1
- metadata +8 -7
@@ -3,26 +3,21 @@ require 'pod_builder/core'
|
|
3
3
|
|
4
4
|
module PodBuilder
|
5
5
|
class Podfile
|
6
|
-
def self.
|
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
|
-
|
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
|
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
|
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
|
-
|
360
|
-
if
|
361
|
-
|
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
|
399
|
+
def prebuilt_podspec_path(absolute_path = true)
|
400
|
+
podspec_path = PodBuilder::prebuiltpath("#{@root_name}/#{@root_name}.podspec")
|
391
401
|
if absolute_path
|
392
|
-
|
402
|
+
return podspec_path
|
393
403
|
else
|
394
|
-
pod_path = Pathname.new(
|
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 => '#{
|
412
|
+
entry = "pod '#{podspec_name}', :path => '#{podspec_dirname}'"
|
400
413
|
else
|
401
|
-
entry = "pod '#{name}', :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 ==
|
488
|
-
|
489
|
-
if
|
490
|
-
|
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
|
data/lib/pod_builder/podspec.rb
CHANGED
@@ -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
|
31
|
-
existing_vendored_frameworks_basename = vendored_frameworks.map { |t| File.basename(t) }.select
|
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
|
36
|
-
existing_vendored_libraries_basename = vendored_libraries.map { |t| File.basename(
|
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.
|
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
|
-
|
135
|
-
|
136
|
-
|
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 =
|
169
|
-
File.
|
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 "
|
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
|
-
|
18
|
-
device_lib = "#{
|
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
|
-
|
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
|
-
|
45
|
+
`xcrun lipo -remove arm64 #{simulator_lib} -o #{simulator_lib}`
|
36
46
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
56
|
-
|
57
|
-
FileUtils.
|
58
|
-
|
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
|
-
|
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
|
-
|
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 "
|
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
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
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
|
+
|