pod-builder 2.0.0 → 2.3.0
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/README.md +5 -5
- data/lib/pod_builder/analyze.rb +2 -22
- data/lib/pod_builder/command/build.rb +14 -8
- data/lib/pod_builder/command/generate_lldbinit.rb +83 -106
- data/lib/pod_builder/configuration.rb +9 -9
- data/lib/pod_builder/podfile.rb +11 -11
- data/lib/pod_builder/podfile/pre_actions_swizzles.rb +84 -0
- data/lib/pod_builder/podfile_item.rb +0 -18
- data/lib/pod_builder/podspec.rb +28 -11
- data/lib/pod_builder/rome/post_install.rb +148 -69
- data/lib/pod_builder/templates/build_podfile.template +1 -1
- data/lib/pod_builder/version.rb +1 -1
- metadata +3 -3
- data/lib/pod_builder/podfile/post_actions.rb +0 -136
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bb2a7642ff281371f45e15c62966fd461fc47d79c573d553926e8ac37327b34
|
|
4
|
+
data.tar.gz: b4ea4ef42a12bdeb1b23a4824c07ecdf7f24d459e2c4ed00a39e3ab664961214
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b686f329d928e794cf6809eb6c51078692e6e9fdf8f522e345c6bedfc8a1f68fa883613c0e86f7faf202246eb278478a194c60155916996edf24c2b5d3619e2
|
|
7
|
+
data.tar.gz: 0df40657505a0d8fc5af1319d695929a883ba304acb79ece94caeaaebe454a7285f183f9a2fa9284915a315e1756f077b35f689d73f7b09aa1843b5c602594f8
|
data/README.md
CHANGED
|
@@ -280,9 +280,13 @@ Like `build_settings` but per pod. Pod name can also refer to subspec.
|
|
|
280
280
|
|
|
281
281
|
Specify which build system to use to compile frameworks. Either `Legacy` (standard build system) or `Latest` (new build system). Default value: `Latest`.
|
|
282
282
|
|
|
283
|
+
#### `build_xcframeworks`
|
|
284
|
+
|
|
285
|
+
Specify if PodBuilder will build .xcframeworks. Will enable `library_evolution_support`. Default value: false
|
|
286
|
+
|
|
283
287
|
#### `library_evolution_support`
|
|
284
288
|
|
|
285
|
-
Specify if Swift frameworks should be compiled with library evolution support (BUILD_LIBRARY_FOR_DISTRIBUTION).
|
|
289
|
+
Specify if Swift frameworks should be compiled with library evolution support (BUILD_LIBRARY_FOR_DISTRIBUTION). Default value: false
|
|
286
290
|
|
|
287
291
|
#### `license_filename`
|
|
288
292
|
|
|
@@ -310,10 +314,6 @@ PodBuilder writes a plist and markdown license files of pods specified in the Po
|
|
|
310
314
|
|
|
311
315
|
If you use bundler to pin the version of CocoaPods in your project set this to true. Default false.
|
|
312
316
|
|
|
313
|
-
#### `build_for_apple_silicon`
|
|
314
|
-
|
|
315
|
-
If set to true built frameworks will include iPhone simulator slices for Apple silicon based hardware. Default false.
|
|
316
|
-
|
|
317
317
|
|
|
318
318
|
# Behind the scenes
|
|
319
319
|
|
data/lib/pod_builder/analyze.rb
CHANGED
|
@@ -52,28 +52,8 @@ module PodBuilder
|
|
|
52
52
|
all_specs = analysis_result.specifications
|
|
53
53
|
|
|
54
54
|
supported_platforms = analyzer.instance_variable_get("@result").targets.map { |t| t.platform.safe_string_name.downcase }
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
names = analyzer.explicit_pods().map(&:name)
|
|
58
|
-
|
|
59
|
-
podfile_pods = []
|
|
60
|
-
last_count = -1
|
|
61
|
-
while podfile_pods.count != last_count do
|
|
62
|
-
last_count = podfile_pods.count
|
|
63
|
-
|
|
64
|
-
updated_names = []
|
|
65
|
-
names.each do |name|
|
|
66
|
-
if pod = all_podfile_items.detect { |t| t.name == name }
|
|
67
|
-
podfile_pods.push(pod)
|
|
68
|
-
updated_names += pod.dependency_names
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
names = updated_names.uniq
|
|
73
|
-
podfile_pods.uniq!
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
return podfile_pods.sort_by(&:name)
|
|
55
|
+
|
|
56
|
+
return all_specs.map { |spec| PodfileItem.new(spec, all_specs, checkout_options, supported_platforms) }.sort_by(&:name)
|
|
77
57
|
end
|
|
78
58
|
end
|
|
79
59
|
end
|
|
@@ -60,10 +60,6 @@ module PodBuilder
|
|
|
60
60
|
|
|
61
61
|
check_not_building_development_pods(pods_to_build)
|
|
62
62
|
|
|
63
|
-
# Remove dependencies from pods to build
|
|
64
|
-
all_dependencies_name = pods_to_build.map(&:dependency_names).flatten.uniq
|
|
65
|
-
pods_to_build.select! { |x| !all_dependencies_name.include?(x.name) }
|
|
66
|
-
|
|
67
63
|
pods_to_build_debug = pods_to_build.select { |x| x.build_configuration == "debug" }
|
|
68
64
|
pods_to_build_release = pods_to_build - pods_to_build_debug
|
|
69
65
|
|
|
@@ -83,16 +79,17 @@ module PodBuilder
|
|
|
83
79
|
end
|
|
84
80
|
end
|
|
85
81
|
|
|
82
|
+
build_catalyst = should_build_catalyst(installer)
|
|
83
|
+
|
|
86
84
|
install_result = InstallResult.new
|
|
87
85
|
podfiles_items.reject { |x| x.empty? }.each do |podfile_items|
|
|
88
86
|
build_configuration = podfile_items.map(&:build_configuration).uniq.first
|
|
89
87
|
|
|
90
88
|
podfile_items = podfile_items.map { |t| t.recursive_dependencies(all_buildable_items) }.flatten.uniq
|
|
91
|
-
podfile_content = Podfile.from_podfile_items(podfile_items, analyzer, build_configuration, install_using_frameworks)
|
|
89
|
+
podfile_content = Podfile.from_podfile_items(podfile_items, analyzer, build_configuration, install_using_frameworks, build_catalyst, Configuration.build_xcframeworks)
|
|
92
90
|
|
|
93
91
|
install_result += Install.podfile(podfile_content, podfile_items, podfile_items.first.build_configuration)
|
|
94
92
|
|
|
95
|
-
# remove lockfile which gets unexplicably created
|
|
96
93
|
FileUtils.rm_f(PodBuilder::basepath("Podfile.lock"))
|
|
97
94
|
end
|
|
98
95
|
|
|
@@ -128,6 +125,15 @@ module PodBuilder
|
|
|
128
125
|
|
|
129
126
|
private
|
|
130
127
|
|
|
128
|
+
def self.should_build_catalyst(installer)
|
|
129
|
+
build_settings = installer.analysis_result.targets.map { |t| t.user_project.root_object.targets.map { |u| u.build_configuration_list.build_configurations.map { |v| v.build_settings } } }.flatten
|
|
130
|
+
build_catalyst = build_settings.detect { |t| t["SUPPORTS_MACCATALYST"] == "YES" } != nil
|
|
131
|
+
|
|
132
|
+
puts "\nTo support Catalyst you should enable 'build_xcframeworks' in PodBuilder.json\n".red if build_catalyst && !Configuration.build_xcframeworks
|
|
133
|
+
|
|
134
|
+
return build_catalyst
|
|
135
|
+
end
|
|
136
|
+
|
|
131
137
|
def self.prepare_defines_modules_override(all_buildable_items)
|
|
132
138
|
all_buildable_items.each do |item|
|
|
133
139
|
unless item.defines_module.nil?
|
|
@@ -187,10 +193,10 @@ module PodBuilder
|
|
|
187
193
|
lines = File.read(PodBuilder::project_path("Podfile")).split("\n")
|
|
188
194
|
stripped_lines = lines.map { |x| Podfile.strip_line(x) }.select { |x| !x.start_with?("#")}
|
|
189
195
|
|
|
190
|
-
expected_stripped = Podfile::
|
|
196
|
+
expected_stripped = Podfile::PRE_INSTALL_ACTIONS.map { |x| Podfile.strip_line(x) }
|
|
191
197
|
|
|
192
198
|
if !expected_stripped.all? { |x| stripped_lines.include?(x) }
|
|
193
|
-
warn_message = "PodBuilder's
|
|
199
|
+
warn_message = "PodBuilder's pre install actions missing from application Podfile!\n"
|
|
194
200
|
if OPTIONS[:allow_warnings]
|
|
195
201
|
puts "\n\n#{warn_message}".yellow
|
|
196
202
|
else
|
|
@@ -9,142 +9,119 @@ module PodBuilder
|
|
|
9
9
|
if Configuration.build_using_repo_paths
|
|
10
10
|
raise "\n\nlldb shenanigans not supported when 'build_using_repo_paths' is enabled".red
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
arguments = ARGV.dup
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
if arguments.count > 0
|
|
16
16
|
source_path = arguments[0]
|
|
17
17
|
if !is_absolute_path(source_path)
|
|
18
18
|
source_path = PodBuilder::basepath(source_path)
|
|
19
19
|
end
|
|
20
20
|
source_path = File.expand_path(source_path)
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
raise "\n\nSpecified path does not exists" unless File.directory?(source_path)
|
|
23
23
|
end
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
base_path = PodBuilder::basepath
|
|
26
|
-
|
|
27
26
|
app_podfile_content = File.read(PodBuilder::project_path("Podfile"))
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
|
|
30
28
|
lldbinit_path = File.expand_path(PodBuilder::basepath(Configuration.lldbinit_name))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if lldbinit_content.include?("# <pb_md5:#{base_path}:#{podfile_hash}")
|
|
34
|
-
puts "\n\n🎉 already in sync!\n".green
|
|
35
|
-
return 0
|
|
36
|
-
end
|
|
37
|
-
|
|
29
|
+
|
|
38
30
|
puts "Extracting debug information".yellow
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
source_map_lines = []
|
|
46
|
-
Dir.glob("#{PodBuilder::prebuiltpath}/**/#{Configuration.prebuilt_info_filename}").each do |path|
|
|
47
|
-
data = JSON.parse(File.read(path))
|
|
48
|
-
next if data.fetch("is_prebuilt", true)
|
|
32
|
+
FileUtils.mkdir_p(Configuration.build_path)
|
|
33
|
+
compilation_base_path = Pathname.new(Configuration.build_path).realpath.to_s
|
|
34
|
+
|
|
35
|
+
pods_mappings = Hash.new
|
|
49
36
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
app_podfile_content.each_line do |line|
|
|
38
|
+
unless (name_match = line.match(/^\s*pod ['|"](.*?)['|"](.*)/)) && name_match.size == 3
|
|
39
|
+
next
|
|
40
|
+
end
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
podspec_path = "#{File.dirname(path)}/#{podspec_name}.podspec"
|
|
42
|
+
pod_name = name_match[1].split("/").first
|
|
56
43
|
|
|
57
|
-
|
|
44
|
+
source = nil
|
|
45
|
+
destination = PodBuilder::basepath # puts some existing path, see lldbinit_content.reverse! comment
|
|
46
|
+
if (path_match = line.match(/:path\s?=>\s?['|"](.*?)['|"]/)) && path_match.size == 2
|
|
47
|
+
pod_path = path_match[1]
|
|
48
|
+
if !is_absolute_path(pod_path)
|
|
49
|
+
pod_path = File.expand_path("#{base_path}/#{pod_path}")
|
|
50
|
+
end
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
is_prebuilt = pod_path.start_with?(PodBuilder::prebuiltpath(pod_name))
|
|
53
|
+
if is_prebuilt
|
|
54
|
+
source = "#{compilation_base_path}/Pods/#{pod_name}"
|
|
55
|
+
destination = PodBuilder::prebuiltpath(pod_name)
|
|
56
|
+
|
|
57
|
+
info_path = "#{pod_path}/#{Configuration.prebuilt_info_filename}"
|
|
58
|
+
next unless File.exists?(info_path)
|
|
59
|
+
data = JSON.parse(File.read(info_path))
|
|
60
|
+
|
|
61
|
+
build_source_path_matches = data["entry"].match(/:path => '(.*?)'/)
|
|
62
|
+
if build_source_path_matches&.size == 2
|
|
63
|
+
build_source_path = build_source_path_matches[1]
|
|
64
|
+
if !is_absolute_path(build_source_path)
|
|
65
|
+
build_source_path = PodBuilder::basepath(build_source_path)
|
|
66
|
+
end
|
|
67
|
+
destination = File.expand_path(build_source_path)
|
|
68
|
+
end
|
|
69
|
+
elsif File.directory?(pod_path)
|
|
70
|
+
source = pod_path
|
|
71
|
+
destination = pod_path
|
|
65
72
|
end
|
|
66
|
-
build_source_path = File.expand_path(build_source_path)
|
|
67
|
-
elsif source_path.nil?
|
|
68
|
-
next
|
|
69
73
|
else
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
pod_path = PodBuilder::project_path("Pods/#{pod_name}")
|
|
75
|
+
if File.directory?(pod_path)
|
|
76
|
+
source = pod_path
|
|
77
|
+
destination = pod_path
|
|
78
|
+
end
|
|
73
79
|
end
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
unless source_map_lines.include?("settings append target.source-map '#{original_compile_path}'")
|
|
78
|
-
source_map_lines.push("# <pb:#{base_path}>\n", "settings append target.source-map '#{original_compile_path}' '#{build_source_path}'\n")
|
|
79
|
-
end
|
|
80
|
+
|
|
81
|
+
if !source.nil? && File.directory?(destination)
|
|
82
|
+
pods_mappings[source] = destination
|
|
80
83
|
end
|
|
81
84
|
end
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
prebuilt_source_map_entries = []
|
|
87
|
+
other_source_map_entries = []
|
|
88
|
+
pods_mappings.each do |source, destination|
|
|
89
|
+
if source.include?(compilation_base_path)
|
|
90
|
+
prebuilt_source_map_entries.push("settings append target.source-map '#{source}/' '#{destination}/'")
|
|
91
|
+
else
|
|
92
|
+
other_source_map_entries.push("settings append target.source-map '#{source}/' '#{destination}/'")
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# There is a bug/unexpected behavior related to the target.source-map command
|
|
97
|
+
#
|
|
98
|
+
# If I have debug symbols for the following files:
|
|
99
|
+
# /tmp/pod_builder/Pods/SomeName/... which are now under /new/path/SomeName/
|
|
100
|
+
# /tmp/pod_builder/Pods/SomeNameCommon/... which are now under /new/path/SomeNameCommon/
|
|
101
|
+
#
|
|
102
|
+
# adding a remap as follows
|
|
103
|
+
# settings append '/tmp/pod_builder/Pods/SomeName/' '/new/path/SomeName/'
|
|
104
|
+
#
|
|
105
|
+
# causes breakpoints added to files under /new/path/SomeNameCommon/ to be incorrectly added to
|
|
106
|
+
# /tmp/pod_builder/Pods/SomeName/Common/Somefile
|
|
107
|
+
#
|
|
108
|
+
# LLDB evaluates remap in order so to workaround this issue we have to add a remap of
|
|
109
|
+
# /tmp/pod_builder/Pods/SomeNameCommon/ before remapping /tmp/pod_builder/Pods/SomeName/
|
|
110
|
+
# even if the remap isn't needed!
|
|
111
|
+
lldbinit_content = other_source_map_entries.sort.reverse + prebuilt_source_map_entries.sort.reverse
|
|
112
|
+
|
|
113
|
+
lldbinit_content.insert(0, "settings clear target.source-map\n")
|
|
114
|
+
|
|
115
|
+
File.write(lldbinit_path, lldbinit_content.join("\n"))
|
|
84
116
|
|
|
85
117
|
puts "\n\n🎉 done!\n".green
|
|
86
118
|
return 0
|
|
87
119
|
end
|
|
88
|
-
|
|
120
|
+
|
|
89
121
|
private
|
|
90
|
-
|
|
91
|
-
def self.is_absolute_path(path)
|
|
92
|
-
return ["~", "/"].any? { |t| t.start_with?(t) }
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def self.is_prebuilt_pod(podspec_path, app_podfile_content)
|
|
96
|
-
development_path = Pathname.new(podspec_path).relative_path_from(Pathname.new(PodBuilder::project_path)).parent.to_s
|
|
97
|
-
|
|
98
|
-
return app_podfile_content.include?(":path => '#{development_path}'")
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def self.rewrite_lldinit(lldbinit_path, source_map_lines, base_path, podfile_hash)
|
|
102
|
-
puts "Writing #{lldbinit_path}".yellow
|
|
103
|
-
|
|
104
|
-
FileUtils.touch(lldbinit_path)
|
|
105
|
-
raise "\n\nDestination file should be a file".red unless File.exist?(lldbinit_path)
|
|
106
|
-
|
|
107
|
-
lldbinit_lines = []
|
|
108
|
-
skipNext = false
|
|
109
|
-
File.read(lldbinit_path).each_line do |line|
|
|
110
|
-
if line.include?("# <pb:#{base_path}>") || line.include?("# <pb>")
|
|
111
|
-
skipNext = true
|
|
112
|
-
next
|
|
113
|
-
elsif skipNext
|
|
114
|
-
skipNext = false
|
|
115
|
-
next
|
|
116
|
-
elsif line != "\n"
|
|
117
|
-
if line.include?("settings set target.source-map")
|
|
118
|
-
raise "\n\n#{lldbinit_destination_path} already includes a manual `settings set target.source-map`. This is unsupported and you'll have to manually remove that entry\n".red
|
|
119
|
-
end
|
|
120
|
-
lldbinit_lines.push(line)
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
source_map_lines.insert(0, "# <pb>\n")
|
|
125
|
-
source_map_lines.insert(1, "settings clear target.source-map\n")
|
|
126
|
-
source_map_lines.insert(2, "# <pb:#{base_path}>\n")
|
|
127
|
-
source_map_lines.insert(3, "# <pb_md5:#{base_path}:#{podfile_hash}>\n")
|
|
128
|
-
|
|
129
|
-
lldbinit_lines += source_map_lines
|
|
130
122
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def self.find_podspec_path_for(name, podspec_paths, podspec_contents)
|
|
135
|
-
if (path = podspec_paths.detect { |t| File.basename(t, ".podspec") == name.gsub("_", "-") })
|
|
136
|
-
return path
|
|
137
|
-
elsif (path_index = podspec_contents.find_index { |t| t.include?(".module_name='#{name}'") })
|
|
138
|
-
return podspec_paths[path_index]
|
|
139
|
-
elsif (path_index = podspec_contents.find_index { |t| t.include?(".name='#{name}") }) # kind of optimistic,, but a last resort
|
|
140
|
-
return podspec_paths[path_index]
|
|
141
|
-
elsif (path_index = podspec_contents.find_index { |t| t.include?("'module_name':'#{name}'") }) # [json podspec]
|
|
142
|
-
return podspec_paths[path_index]
|
|
143
|
-
elsif (path_index = podspec_contents.find_index { |t| t.include?("'name':'#{name}") }) # [json podspec] kind of optimistic,, but a last resort
|
|
144
|
-
return podspec_paths[path_index]
|
|
145
|
-
else
|
|
146
|
-
return nil
|
|
147
|
-
end
|
|
123
|
+
def self.is_absolute_path(path)
|
|
124
|
+
return ["~", "/"].any? { |t| path.start_with?(t) }
|
|
148
125
|
end
|
|
149
126
|
end
|
|
150
127
|
end
|
|
@@ -45,8 +45,8 @@ module PodBuilder
|
|
|
45
45
|
DEFAULT_BUILD_SYSTEM = "Latest".freeze # either Latest (New build system) or Legacy (Standard build system)
|
|
46
46
|
DEFAULT_LIBRARY_EVOLUTION_SUPPORT = false
|
|
47
47
|
DEFAULT_PLATFORMS = ["iphoneos", "iphonesimulator", "appletvos", "appletvsimulator"].freeze
|
|
48
|
-
DEFAULT_BUILD_FOR_APPLE_SILICON = false
|
|
49
48
|
DEFAULT_BUILD_USING_REPO_PATHS = false
|
|
49
|
+
DEFAULT_BUILD_XCFRAMEWORKS = false
|
|
50
50
|
|
|
51
51
|
private_constant :DEFAULT_BUILD_SETTINGS
|
|
52
52
|
private_constant :DEFAULT_BUILD_SETTINGS_OVERRIDES
|
|
@@ -78,10 +78,10 @@ module PodBuilder
|
|
|
78
78
|
attr_accessor :use_bundler
|
|
79
79
|
attr_accessor :deterministic_build
|
|
80
80
|
attr_accessor :supported_platforms
|
|
81
|
-
attr_accessor :build_for_apple_silicon
|
|
82
81
|
attr_accessor :build_using_repo_paths
|
|
83
82
|
attr_accessor :react_native_project
|
|
84
83
|
attr_accessor :lldbinit_name
|
|
84
|
+
attr_accessor :build_xcframeworks
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
@allow_building_development_pods = false
|
|
@@ -111,9 +111,10 @@ module PodBuilder
|
|
|
111
111
|
@deterministic_build = false
|
|
112
112
|
|
|
113
113
|
@supported_platforms = DEFAULT_PLATFORMS
|
|
114
|
-
@build_for_apple_silicon = DEFAULT_BUILD_FOR_APPLE_SILICON
|
|
115
114
|
@build_using_repo_paths = DEFAULT_BUILD_USING_REPO_PATHS
|
|
116
115
|
@react_native_project = false
|
|
116
|
+
|
|
117
|
+
@build_xcframeworks = DEFAULT_BUILD_XCFRAMEWORKS
|
|
117
118
|
|
|
118
119
|
def self.check_inited
|
|
119
120
|
raise "\n\nNot inited, run `pod_builder init`\n".red if podbuilder_path.nil?
|
|
@@ -207,11 +208,6 @@ module PodBuilder
|
|
|
207
208
|
Configuration.deterministic_build = value
|
|
208
209
|
end
|
|
209
210
|
end
|
|
210
|
-
if value = json["build_for_apple_silicon"]
|
|
211
|
-
if [TrueClass, FalseClass].include?(value.class)
|
|
212
|
-
Configuration.build_for_apple_silicon = value
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
211
|
if value = json["build_using_repo_paths"]
|
|
216
212
|
if [TrueClass, FalseClass].include?(value.class)
|
|
217
213
|
Configuration.build_using_repo_paths = value
|
|
@@ -222,6 +218,11 @@ module PodBuilder
|
|
|
222
218
|
Configuration.react_native_project = value
|
|
223
219
|
end
|
|
224
220
|
end
|
|
221
|
+
if value = json["build_xcframeworks"]
|
|
222
|
+
if [TrueClass, FalseClass].include?(value.class)
|
|
223
|
+
Configuration.build_xcframeworks = value
|
|
224
|
+
end
|
|
225
|
+
end
|
|
225
226
|
|
|
226
227
|
Configuration.build_settings.freeze
|
|
227
228
|
|
|
@@ -264,7 +265,6 @@ module PodBuilder
|
|
|
264
265
|
config["allow_building_development_pods"] = Configuration.allow_building_development_pods
|
|
265
266
|
config["use_bundler"] = Configuration.use_bundler
|
|
266
267
|
config["deterministic_build"] = Configuration.deterministic_build
|
|
267
|
-
config["build_for_apple_silicon"] = Configuration.build_for_apple_silicon
|
|
268
268
|
config["build_using_repo_paths"] = Configuration.build_using_repo_paths
|
|
269
269
|
config["react_native_project"] = Configuration.react_native_project
|
|
270
270
|
|
data/lib/pod_builder/podfile.rb
CHANGED
|
@@ -2,12 +2,10 @@ require 'json'
|
|
|
2
2
|
module PodBuilder
|
|
3
3
|
class Podfile
|
|
4
4
|
PODBUILDER_LOCK_ACTION = ["raise \"\\n🚨 Do not launch 'pod install' manually, use `pod_builder` instead!\\n\" if !File.exist?('pod_builder.lock')"].freeze
|
|
5
|
-
POST_INSTALL_ACTIONS = ["require 'pod_builder/podfile/post_actions'", "PodBuilder::Podfile::pod_builder_post_process"].freeze
|
|
6
5
|
|
|
7
|
-
PRE_INSTALL_ACTIONS = ["Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_duplicate_framework_and_library_names) {}"].freeze
|
|
8
|
-
private_constant :PRE_INSTALL_ACTIONS
|
|
6
|
+
PRE_INSTALL_ACTIONS = ["Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_duplicate_framework_and_library_names) {}", "require 'pod_builder/podfile/pre_actions_swizzles'"].freeze
|
|
9
7
|
|
|
10
|
-
def self.from_podfile_items(items, analyzer, build_configuration, install_using_frameworks)
|
|
8
|
+
def self.from_podfile_items(items, analyzer, build_configuration, install_using_frameworks, build_catalyst, build_xcframeworks)
|
|
11
9
|
raise "\n\nno items".red unless items.count > 0
|
|
12
10
|
|
|
13
11
|
sources = analyzer.sources
|
|
@@ -19,7 +17,9 @@ module PodBuilder
|
|
|
19
17
|
|
|
20
18
|
podfile.sub!("%%%use_frameworks%%%", install_using_frameworks ? "use_frameworks!" : "use_modular_headers!")
|
|
21
19
|
podfile.sub!("%%%uses_frameworks%%%", install_using_frameworks ? "true" : "false")
|
|
22
|
-
|
|
20
|
+
podfile.sub!("%%%build_xcframeworks%%%", build_xcframeworks ? "true" : "false")
|
|
21
|
+
podfile.sub!("%%%build_catalyst%%%", build_catalyst ? "true" : "false")
|
|
22
|
+
|
|
23
23
|
podfile.sub!("%%%platform_name%%%", platform.name.to_s)
|
|
24
24
|
podfile.sub!("%%%deployment_version%%%", platform.deployment_target.version)
|
|
25
25
|
|
|
@@ -41,6 +41,9 @@ module PodBuilder
|
|
|
41
41
|
build_settings["ONLY_ACTIVE_ARCH"] = "NO"
|
|
42
42
|
build_settings["DEBUG_INFORMATION_FORMAT"] = "dwarf-with-dsym"
|
|
43
43
|
|
|
44
|
+
# https://thi.imhttps://thi.im/posts/swift-serialize-debugging-options/
|
|
45
|
+
build_settings["SWIFT_SERIALIZE_DEBUGGING_OPTIONS"] = "NO"
|
|
46
|
+
|
|
44
47
|
build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = platform.deployment_target.version # Fix compilation warnings on Xcode 12
|
|
45
48
|
|
|
46
49
|
# Don't store .pcm info in binary, see https://forums.swift.org/t/swift-behavior-of-gmodules-and-dsyms/23211/3
|
|
@@ -61,6 +64,9 @@ module PodBuilder
|
|
|
61
64
|
elsif Configuration.library_evolution_support
|
|
62
65
|
build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES"
|
|
63
66
|
end
|
|
67
|
+
if Configuration.build_xcframeworks
|
|
68
|
+
build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES"
|
|
69
|
+
end
|
|
64
70
|
|
|
65
71
|
build_settings["SWIFT_VERSION"] = item_build_settings["SWIFT_VERSION"] || item.swift_version || project_swift_version(analyzer)
|
|
66
72
|
|
|
@@ -229,7 +235,6 @@ module PodBuilder
|
|
|
229
235
|
podfile_content = Podfile.update_require_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
|
230
236
|
|
|
231
237
|
podfile_content = add_pre_install_actions(podfile_content)
|
|
232
|
-
podfile_content = add_post_install_checks(podfile_content)
|
|
233
238
|
|
|
234
239
|
project_podfile_path = PodBuilder::project_path("Podfile")
|
|
235
240
|
File.write(project_podfile_path, podfile_content)
|
|
@@ -249,7 +254,6 @@ module PodBuilder
|
|
|
249
254
|
podfile_content = Podfile.update_require_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
|
250
255
|
|
|
251
256
|
podfile_content = add_pre_install_actions(podfile_content)
|
|
252
|
-
podfile_content = add_post_install_checks(podfile_content)
|
|
253
257
|
|
|
254
258
|
project_podfile_path = PodBuilder::project_path("Podfile")
|
|
255
259
|
File.write(project_podfile_path, podfile_content)
|
|
@@ -486,10 +490,6 @@ module PodBuilder
|
|
|
486
490
|
return add(PRE_INSTALL_ACTIONS + [" "], "pre_install", podfile_content)
|
|
487
491
|
end
|
|
488
492
|
|
|
489
|
-
def self.add_post_install_checks(podfile_content)
|
|
490
|
-
return add(POST_INSTALL_ACTIONS + [" "], "post_install", podfile_content)
|
|
491
|
-
end
|
|
492
|
-
|
|
493
493
|
def self.add(entries, marker, podfile_content)
|
|
494
494
|
file_indentation = indentation_from_string(podfile_content)
|
|
495
495
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'xcodeproj'
|
|
2
|
+
require 'pod_builder/core'
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
5
|
+
class Pod::Generator::FileList
|
|
6
|
+
alias_method :swz_initialize, :initialize
|
|
7
|
+
|
|
8
|
+
def initialize(paths)
|
|
9
|
+
paths.uniq!
|
|
10
|
+
swz_initialize(paths)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Pod::Generator::CopyXCFrameworksScript
|
|
15
|
+
alias_method :swz_initialize, :initialize
|
|
16
|
+
|
|
17
|
+
def initialize(xcframeworks, sandbox_root, platform)
|
|
18
|
+
xcframeworks.uniq! { |t| t.path }
|
|
19
|
+
swz_initialize(xcframeworks, sandbox_root, platform)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Pod::Generator::EmbedFrameworksScript
|
|
24
|
+
alias_method :swz_initialize, :initialize
|
|
25
|
+
|
|
26
|
+
def initialize(*args)
|
|
27
|
+
raise "Unsupported CocoaPods version" if (args.count == 0 || args.count > 2)
|
|
28
|
+
|
|
29
|
+
frameworks_by_config = args[0]
|
|
30
|
+
frameworks_by_config.keys.each do |key|
|
|
31
|
+
items = frameworks_by_config[key]
|
|
32
|
+
items.uniq! { |t| t.source_path }
|
|
33
|
+
frameworks_by_config[key] = items
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if args.count == 2
|
|
37
|
+
# CocoaPods 1.10.0 and newer
|
|
38
|
+
xcframeworks_by_config = args[1]
|
|
39
|
+
xcframeworks_by_config.keys.each do |key|
|
|
40
|
+
items = xcframeworks_by_config[key]
|
|
41
|
+
items.uniq! { |t| t.path }
|
|
42
|
+
xcframeworks_by_config[key] = items
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
swz_initialize(*args)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Pod::Generator::CopyResourcesScript
|
|
51
|
+
alias_method :swz_initialize, :initialize
|
|
52
|
+
|
|
53
|
+
def initialize(resources_by_config, platform)
|
|
54
|
+
resources_by_config.keys.each do |key|
|
|
55
|
+
items = resources_by_config[key]
|
|
56
|
+
items.uniq!
|
|
57
|
+
|
|
58
|
+
colliding_resources = items.group_by { |t| File.basename(t) }.values.select { |t| t.count > 1 }
|
|
59
|
+
|
|
60
|
+
unless colliding_resources.empty?
|
|
61
|
+
message = ""
|
|
62
|
+
colliding_resources.each do |resources|
|
|
63
|
+
resources.map! { |t| File.expand_path(t.gsub("${PODS_ROOT}", "#{Dir.pwd}/Pods")) }
|
|
64
|
+
# check that files are identical.
|
|
65
|
+
# For files with paths that are resolved (e.g containing ${PODS_ROOT}) we use the file hash
|
|
66
|
+
# we fallback to the filename for the others
|
|
67
|
+
hashes = resources.map { |t| File.exists?(t) ? Digest::MD5.hexdigest(File.read(t)) : File.basename(t) }
|
|
68
|
+
if hashes.uniq.count > 1
|
|
69
|
+
message += resources.join("\n") + "\n"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
unless message.empty?
|
|
74
|
+
message = "\n\nThe following resources have the same name and will collide once copied into application bundle:\n" + message
|
|
75
|
+
raise message
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
resources_by_config[key] = items
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
swz_initialize(resources_by_config, platform)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -459,24 +459,6 @@ module PodBuilder
|
|
|
459
459
|
return root_name == named.split("/").first
|
|
460
460
|
end
|
|
461
461
|
|
|
462
|
-
def vendored_framework_path
|
|
463
|
-
if File.exist?(PodBuilder::prebuiltpath("#{root_name}/#{vendored_subspec_framework_name}"))
|
|
464
|
-
return vendored_subspec_framework_name
|
|
465
|
-
elsif File.exist?(PodBuilder::prebuiltpath("#{root_name}/#{vendored_spec_framework_name}"))
|
|
466
|
-
return vendored_spec_framework_name
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
return nil
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
def vendored_subspec_framework_name
|
|
473
|
-
return "#{prebuilt_rel_path}"
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
def vendored_spec_framework_name
|
|
477
|
-
return "#{module_name}.framework"
|
|
478
|
-
end
|
|
479
|
-
|
|
480
462
|
private
|
|
481
463
|
|
|
482
464
|
def extract_vendored_frameworks(spec, all_specs)
|
data/lib/pod_builder/podspec.rb
CHANGED
|
@@ -32,8 +32,8 @@ module PodBuilder
|
|
|
32
32
|
if_exists = lambda { |t| File.exist?(PodBuilder::prebuiltpath("#{item.root_name}/#{t}") || "") }
|
|
33
33
|
|
|
34
34
|
vendored_frameworks = item.vendored_frameworks
|
|
35
|
-
if item.default_subspecs.count == 0 && install_using_frameworks
|
|
36
|
-
vendored_frameworks += ["#{item.module_name}.framework"]
|
|
35
|
+
if item.default_subspecs.reject { |t| "#{item.root_name}/#{t}" == item.name }.count == 0 && install_using_frameworks
|
|
36
|
+
vendored_frameworks += ["#{item.module_name}.framework", "#{item.module_name}.xcframework"].select(&if_exists)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
existing_vendored_frameworks = vendored_frameworks.select(&if_exists)
|
|
@@ -49,13 +49,23 @@ module PodBuilder
|
|
|
49
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
50
|
vendored_libraries.reject! { |t| t.end_with?(".a") }
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
public_headers = []
|
|
53
|
+
resources = []
|
|
54
|
+
exclude_files = []
|
|
55
|
+
vendored_frameworks.each do |vendored_framework|
|
|
56
|
+
binary_path = Dir.glob(PodBuilder::prebuiltpath("#{item.root_name}/#{vendored_framework}/**/#{File.basename(vendored_framework, ".*")}")).first
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
next if binary_path.nil?
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
is_static = `file '#{binary_path}'`.include?("current ar archive")
|
|
61
|
+
if is_static
|
|
62
|
+
parent_folder = File.expand_path("#{binary_path}/..")
|
|
63
|
+
rel_path = Pathname.new(parent_folder).relative_path_from(Pathname.new(PodBuilder::prebuiltpath(item.root_name))).to_s
|
|
64
|
+
|
|
65
|
+
resources.push("#{rel_path}/*.{nib,bundle,xcasset,strings,png,jpg,tif,tiff,otf,ttf,ttc,plist,json,caf,wav,p12,momd}")
|
|
66
|
+
exclude_files.push("#{rel_path}/Info.plist")
|
|
67
|
+
end
|
|
68
|
+
end
|
|
59
69
|
else
|
|
60
70
|
public_headers = Dir.glob(PodBuilder::prebuiltpath("#{item.root_name}/#{item.root_name}/Headers/**/*.h"))
|
|
61
71
|
vendored_libraries += ["#{item.root_name}/lib#{item.root_name}.a"]
|
|
@@ -152,6 +162,10 @@ module PodBuilder
|
|
|
152
162
|
if name == item.root_name
|
|
153
163
|
deps.reject! { |t| t.split("/").first == item.root_name }
|
|
154
164
|
end
|
|
165
|
+
|
|
166
|
+
deps.reject! { |t| t == item.name }
|
|
167
|
+
all_buildable_items_name = all_buildable_items.map(&:name)
|
|
168
|
+
deps.select! { |t| all_buildable_items_name.include?(t) }
|
|
155
169
|
|
|
156
170
|
if deps.count > 0
|
|
157
171
|
if podspec.count("\n") > 1
|
|
@@ -164,10 +178,12 @@ module PodBuilder
|
|
|
164
178
|
|
|
165
179
|
valid = valid || (install_using_frameworks ? vendored_frameworks.count > 0 : vendored_libraries.count > 0)
|
|
166
180
|
end
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
181
|
+
|
|
182
|
+
subspec_base = name.split("/").first(slash_count).join("/")
|
|
183
|
+
subspec_items = all_buildable_items.select { |t| t.name.start_with?("#{subspec_base}/") }
|
|
184
|
+
|
|
185
|
+
subspec_names = subspec_items.map { |t| t.name.split("/").drop(slash_count).first }.uniq
|
|
186
|
+
subspec_names.map! { |t| "#{subspec_base}/#{t}" }
|
|
171
187
|
|
|
172
188
|
subspec_names.each do |subspec|
|
|
173
189
|
subspec_item = all_buildable_items.detect { |t| t.name == subspec } || item
|
|
@@ -201,6 +217,7 @@ module PodBuilder
|
|
|
201
217
|
if item.is_prebuilt
|
|
202
218
|
next
|
|
203
219
|
end
|
|
220
|
+
|
|
204
221
|
if item.name != item.root_name
|
|
205
222
|
if all_buildable_items.map(&:name).include?(item.root_name)
|
|
206
223
|
next # will process root spec, skip subspecs
|
|
@@ -3,9 +3,27 @@ require 'colored'
|
|
|
3
3
|
require 'pathname'
|
|
4
4
|
|
|
5
5
|
module PodBuilder
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
class XcodeBuildSettings
|
|
7
|
+
attr_reader :platform_name
|
|
8
|
+
attr_reader :build_destination
|
|
9
|
+
|
|
10
|
+
def initialize(platform_name)
|
|
11
|
+
@platform_name = platform_name
|
|
12
|
+
|
|
13
|
+
case platform_name
|
|
14
|
+
when "iphoneos" then @build_destination = "generic/platform=iOS"
|
|
15
|
+
when "iphonesimulator" then @build_destination = "generic/platform=iOS Simulator"
|
|
16
|
+
when "catalyst" then @build_destination = "platform=macOS,arch=x86_64,variant=Mac Catalyst"
|
|
17
|
+
when "macos" then @build_destination = "generic/platform=OS X"
|
|
18
|
+
when "tvos" then @build_destination = "generic/platform=tvOS"
|
|
19
|
+
when "tvossimulator" then @build_destination = "generic/platform=tvOS Simulator"
|
|
20
|
+
when "watchos" then @build_destination = "generic/platform=watchOS"
|
|
21
|
+
when "watchossimulator" then @build_destination = "generic/platform=watchOS Simulator"
|
|
22
|
+
else raise "\n\nUnknown platform '#{platform_name}'".red end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.build_for_iosish_platform_framework(sandbox, build_dir, target, device, simulator, configuration, deterministic_build)
|
|
9
27
|
dsym_device_folder = File.join(build_dir, "dSYM", device)
|
|
10
28
|
dsym_simulator_folder = File.join(build_dir, "dSYM", simulator)
|
|
11
29
|
FileUtils.mkdir_p(dsym_device_folder)
|
|
@@ -16,7 +34,7 @@ module PodBuilder
|
|
|
16
34
|
|
|
17
35
|
xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [], {})
|
|
18
36
|
excluded_archs = ["i386"] # Fixes https://github.com/Subito-it/PodBuilder/issues/17
|
|
19
|
-
excluded_archs +=
|
|
37
|
+
excluded_archs += ["arm64"] # Exclude apple silicon slice
|
|
20
38
|
xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs, {})
|
|
21
39
|
|
|
22
40
|
spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
|
|
@@ -65,16 +83,14 @@ module PodBuilder
|
|
|
65
83
|
end
|
|
66
84
|
end
|
|
67
85
|
|
|
68
|
-
def self.build_for_iosish_platform_lib(sandbox, build_dir, target, device, simulator, configuration, deterministic_build,
|
|
69
|
-
raise "\n\nApple silicon hardware still unsupported since it requires to migrate to xcframeworks".red if build_for_apple_silicon
|
|
70
|
-
|
|
86
|
+
def self.build_for_iosish_platform_lib(sandbox, build_dir, target, device, simulator, configuration, deterministic_build, prebuilt_root_paths)
|
|
71
87
|
deployment_target = target.platform_deployment_target
|
|
72
88
|
target_label = target.cocoapods_target_label
|
|
73
89
|
|
|
74
90
|
spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
|
|
75
91
|
|
|
76
92
|
xcodebuild(sandbox, target_label, device, deployment_target, configuration, deterministic_build, [], prebuilt_root_paths)
|
|
77
|
-
excluded_archs =
|
|
93
|
+
excluded_archs = ["arm64"] # Exclude Apple silicon slice
|
|
78
94
|
xcodebuild(sandbox, target_label, simulator, deployment_target, configuration, deterministic_build, excluded_archs, prebuilt_root_paths)
|
|
79
95
|
|
|
80
96
|
spec_names.each do |root_name, module_name|
|
|
@@ -273,6 +289,8 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
|
|
|
273
289
|
if user_options["pre_compile"]
|
|
274
290
|
user_options["pre_compile"].call(installer_context)
|
|
275
291
|
end
|
|
292
|
+
build_catalyst = user_options.fetch('build_catalyst', false)
|
|
293
|
+
build_xcframeworks = user_options.fetch('build_xcframeworks', false)
|
|
276
294
|
|
|
277
295
|
prebuilt_root_paths = JSON.parse(user_options["prebuilt_root_paths"].gsub('=>', ':'))
|
|
278
296
|
|
|
@@ -285,82 +303,143 @@ Pod::HooksManager.register('podbuilder-rome', :post_install) do |installer_conte
|
|
|
285
303
|
base_destination = sandbox_root.parent + 'Prebuilt'
|
|
286
304
|
|
|
287
305
|
build_dir.rmtree if build_dir.directory?
|
|
306
|
+
|
|
288
307
|
targets = installer_context.umbrella_targets.select { |t| t.specs.any? }
|
|
289
|
-
targets.
|
|
308
|
+
raise "\n\nUnsupported target count".red unless targets.count == 1
|
|
309
|
+
target = targets.first
|
|
310
|
+
|
|
311
|
+
if build_xcframeworks
|
|
312
|
+
project_path = sandbox_root.parent + 'Pods/Pods.xcodeproj'
|
|
313
|
+
|
|
314
|
+
case target.platform_name
|
|
315
|
+
when :ios then
|
|
316
|
+
xcodebuild_settings = [PodBuilder::XcodeBuildSettings.new("iphoneos"), PodBuilder::XcodeBuildSettings.new("iphonesimulator")]
|
|
317
|
+
if build_catalyst
|
|
318
|
+
xcodebuild_settings += [PodBuilder::XcodeBuildSettings.new("catalyst")]
|
|
319
|
+
end
|
|
320
|
+
when :osx then xcodebuild_settings = [PodBuilder::XcodeBuildSettings.new("macos")]
|
|
321
|
+
when :tvos then xcodebuild_settings = [PodBuilder::XcodeBuildSettings.new("tvos"), PodBuilder::XcodeBuildSettings.new("tvossimulator")]
|
|
322
|
+
when :watchos then xcodebuild_settings = [PodBuilder::XcodeBuildSettings.new("watchos"), PodBuilder::XcodeBuildSettings.new("watchossimulator")]
|
|
323
|
+
else raise "\n\nUnknown platform '#{target.platform_name}'".red end
|
|
324
|
+
|
|
325
|
+
xcodebuild_settings.each do |xcodebuild_setting|
|
|
326
|
+
puts "Building xcframeworks for #{xcodebuild_setting.platform_name}".yellow
|
|
327
|
+
raise "\n\n#{build_destination} xcframework archive failed!".red if !system("xcodebuild archive -project #{project_path.to_s} -scheme Pods-DummyTarget -destination '#{xcodebuild_setting.build_destination}' -archivePath '#{build_dir}/#{xcodebuild_setting.platform_name}' SKIP_INSTALL=NO > /dev/null 2>&1")
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
built_items = Dir.glob("#{build_dir}/#{xcodebuild_settings[0].platform_name}.xcarchive/Products/Library/Frameworks/*").reject { |t| File.basename(t, ".*") == "Pods_DummyTarget" }
|
|
331
|
+
|
|
332
|
+
built_items.each do |built_item|
|
|
333
|
+
built_item_paths = [built_item]
|
|
334
|
+
xcodebuild_settings.drop(1).each do |xcodebuild_setting|
|
|
335
|
+
path = "#{build_dir}/#{xcodebuild_setting.platform_name}.xcarchive/Products/Library/Frameworks/#{File.basename(built_item)}"
|
|
336
|
+
if File.directory?(path)
|
|
337
|
+
built_item_paths.push(path)
|
|
338
|
+
else
|
|
339
|
+
built_item_paths = []
|
|
340
|
+
break
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
next if built_item_paths.count == 0
|
|
345
|
+
|
|
346
|
+
framework_name = File.basename(built_item_paths.first, ".*")
|
|
347
|
+
xcframework_path = "#{base_destination}/#{framework_name}/#{framework_name}.xcframework"
|
|
348
|
+
framework_params = built_item_paths.map { |t| "-framework '#{t}'"}.join(" ")
|
|
349
|
+
raise "\n\nFailed packing xcframework!".red if !system("xcodebuild -create-xcframework #{framework_params} -output '#{xcframework_path}' > /dev/null 2>&1")
|
|
350
|
+
|
|
351
|
+
if enable_dsym
|
|
352
|
+
xcodebuild_settings.each do |xcodebuild_setting|
|
|
353
|
+
dsym_source = "#{build_dir}/#{xcodebuild_setting.platform_name}.xcarchive/dSYMs/"
|
|
354
|
+
if File.directory?(dsym_source)
|
|
355
|
+
destination = sandbox_root.parent + "dSYMs"
|
|
356
|
+
FileUtils.mkdir_p(destination)
|
|
357
|
+
FileUtils.mv(dsym_source, destination)
|
|
358
|
+
FileUtils.mv("#{destination}/dSYMs", "#{destination}/#{xcodebuild_setting.platform_name}")
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
else
|
|
362
|
+
raise "Not implemented"
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
built_count = built_items.count
|
|
367
|
+
Pod::UI.puts "Built #{built_count} #{'item'.pluralize(built_count)}"
|
|
368
|
+
else
|
|
290
369
|
case [target.platform_name, uses_frameworks]
|
|
291
|
-
when [:ios, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build
|
|
292
|
-
when [:osx, true] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build,
|
|
293
|
-
when [:tvos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build
|
|
294
|
-
when [:watchos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build
|
|
295
|
-
when [:ios, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build,
|
|
296
|
-
when [:osx, false] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build,
|
|
297
|
-
when [:tvos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build,
|
|
298
|
-
when [:watchos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build,
|
|
370
|
+
when [:ios, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build)
|
|
371
|
+
when [:osx, true] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, {})
|
|
372
|
+
when [:tvos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build)
|
|
373
|
+
when [:watchos, true] then PodBuilder::build_for_iosish_platform_framework(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build)
|
|
374
|
+
when [:ios, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'iphoneos', 'iphonesimulator', configuration, PodBuilder::Configuration.deterministic_build, prebuilt_root_paths)
|
|
375
|
+
when [:osx, false] then PodBuilder::xcodebuild(sandbox, target.cocoapods_target_label, configuration, PodBuilder::Configuration.deterministic_build, prebuilt_root_paths)
|
|
376
|
+
when [:tvos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'appletvos', 'appletvsimulator', configuration, PodBuilder::Configuration.deterministic_build, prebuilt_root_paths)
|
|
377
|
+
when [:watchos, false] then PodBuilder::build_for_iosish_platform_lib(sandbox, build_dir, target, 'watchos', 'watchsimulator', configuration, PodBuilder::Configuration.deterministic_build, prebuilt_root_paths)
|
|
299
378
|
else raise "\n\nUnknown platform '#{target.platform_name}'".red end
|
|
300
|
-
|
|
379
|
+
|
|
380
|
+
raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
|
|
301
381
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
built_count = Dir["#{build_dir}/*"].select { |t| specs.include?(File.basename(t)) }.count
|
|
306
|
-
Pod::UI.puts "Built #{built_count} #{'items'.pluralize(built_count)}, copying..."
|
|
307
|
-
|
|
308
|
-
base_destination.rmtree if base_destination.directory?
|
|
382
|
+
specs = installer_context.umbrella_targets.map { |t| t.specs.map(&:name) }.flatten.map { |t| t.split("/").first }.uniq
|
|
383
|
+
built_count = Dir["#{build_dir}/*"].select { |t| specs.include?(File.basename(t)) }.count
|
|
384
|
+
Pod::UI.puts "Built #{built_count} #{'item'.pluralize(built_count)}, copying..."
|
|
309
385
|
|
|
310
|
-
|
|
311
|
-
umbrella.specs.each do |spec|
|
|
312
|
-
root_name = spec.name.split("/").first
|
|
386
|
+
base_destination.rmtree if base_destination.directory?
|
|
313
387
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
388
|
+
installer_context.umbrella_targets.each do |umbrella|
|
|
389
|
+
umbrella.specs.each do |spec|
|
|
390
|
+
root_name = spec.name.split("/").first
|
|
391
|
+
|
|
392
|
+
if uses_frameworks
|
|
393
|
+
destination = File.join(base_destination, root_name)
|
|
394
|
+
else
|
|
395
|
+
destination = File.join(base_destination, root_name, root_name)
|
|
396
|
+
end
|
|
397
|
+
# Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
|
|
398
|
+
# can get upset about Info.plist containing references to the simulator SDK
|
|
399
|
+
files = Pathname.glob("build/#{root_name}/*").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
|
|
400
|
+
|
|
401
|
+
consumer = spec.consumer(umbrella.platform_name)
|
|
402
|
+
file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
|
|
403
|
+
files += file_accessor.vendored_libraries
|
|
404
|
+
files += file_accessor.vendored_frameworks
|
|
405
|
+
files += file_accessor.resources
|
|
406
|
+
|
|
407
|
+
FileUtils.mkdir_p(destination)
|
|
408
|
+
files.each do |file|
|
|
409
|
+
FileUtils.cp_r(file, destination)
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Depending on the resource it may happen that it is present twice, both in the .framework and in the parent folder
|
|
415
|
+
Dir.glob("#{base_destination}/*") do |path|
|
|
416
|
+
unless File.directory?(path)
|
|
417
|
+
return
|
|
318
418
|
end
|
|
319
|
-
# Make sure the device target overwrites anything in the simulator build, otherwise iTunesConnect
|
|
320
|
-
# can get upset about Info.plist containing references to the simulator SDK
|
|
321
|
-
files = Pathname.glob("build/#{root_name}/*").reject { |f| f.to_s =~ /Pods[^.]+\.framework/ }
|
|
322
419
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
files += file_accessor.vendored_libraries
|
|
326
|
-
files += file_accessor.vendored_frameworks
|
|
327
|
-
files += file_accessor.resources
|
|
420
|
+
files = Dir.glob("#{path}/*")
|
|
421
|
+
framework_files = Dir.glob("#{path}/*.framework/**/*").map { |t| File.basename(t) }
|
|
328
422
|
|
|
329
|
-
FileUtils.mkdir_p(destination)
|
|
330
423
|
files.each do |file|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
# Depending on the resource it may happen that it is present twice, both in the .framework and in the parent folder
|
|
337
|
-
Dir.glob("#{base_destination}/*") do |path|
|
|
338
|
-
unless File.directory?(path)
|
|
339
|
-
return
|
|
424
|
+
filename = File.basename(file.gsub(/\.xib$/, ".nib"))
|
|
425
|
+
if framework_files.include?(filename)
|
|
426
|
+
FileUtils.rm_rf(file)
|
|
427
|
+
end
|
|
428
|
+
end
|
|
340
429
|
end
|
|
341
430
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
filename = File.basename(file.gsub(/\.xib$/, ".nib"))
|
|
347
|
-
if framework_files.include?(filename)
|
|
348
|
-
FileUtils.rm_rf(file)
|
|
431
|
+
if enable_dsym
|
|
432
|
+
dsym_source = "#{build_dir}/dSYM"
|
|
433
|
+
if File.directory?(dsym_source)
|
|
434
|
+
FileUtils.mv(dsym_source, sandbox_root.parent)
|
|
349
435
|
end
|
|
350
|
-
|
|
436
|
+
else
|
|
437
|
+
raise "Not implemented"
|
|
438
|
+
end
|
|
351
439
|
end
|
|
352
|
-
|
|
353
|
-
if enable_dsym
|
|
354
|
-
dsym_source = "#{build_dir}/dSYM"
|
|
355
|
-
if File.directory?(dsym_source)
|
|
356
|
-
FileUtils.mv(dsym_source, sandbox_root.parent)
|
|
357
|
-
end
|
|
358
|
-
else
|
|
359
|
-
raise "Not implemented"
|
|
360
|
-
end
|
|
361
|
-
|
|
440
|
+
|
|
362
441
|
build_dir.rmtree if build_dir.directory?
|
|
363
|
-
|
|
442
|
+
|
|
364
443
|
if user_options["post_compile"]
|
|
365
444
|
user_options["post_compile"].call(installer_context)
|
|
366
445
|
end
|
|
@@ -4,7 +4,7 @@ require 'cfpropertylist'
|
|
|
4
4
|
|
|
5
5
|
%%%use_frameworks%%%
|
|
6
6
|
|
|
7
|
-
plugin 'podbuilder-rome', { dsym: true, configuration: '%%%build_configuration%%%', uses_frameworks: %%%uses_frameworks%%%, prebuilt_root_paths: '%%%prebuilt_root_paths%%%', pre_compile: Proc.new { |installer|
|
|
7
|
+
plugin 'podbuilder-rome', { dsym: true, configuration: '%%%build_configuration%%%', uses_frameworks: %%%uses_frameworks%%%, build_catalyst: %%%build_catalyst%%%, build_xcframeworks: %%%build_xcframeworks%%%, prebuilt_root_paths: '%%%prebuilt_root_paths%%%', pre_compile: Proc.new { |installer|
|
|
8
8
|
|
|
9
9
|
def set_build_settings(target_name, build_configurations, installer)
|
|
10
10
|
installer.pods_project.targets.each do |target|
|
data/lib/pod_builder/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pod-builder
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tomas Camin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -204,7 +204,7 @@ files:
|
|
|
204
204
|
- lib/pod_builder/install.rb
|
|
205
205
|
- lib/pod_builder/licenses.rb
|
|
206
206
|
- lib/pod_builder/podfile.rb
|
|
207
|
-
- lib/pod_builder/podfile/
|
|
207
|
+
- lib/pod_builder/podfile/pre_actions_swizzles.rb
|
|
208
208
|
- lib/pod_builder/podfile_cp.rb
|
|
209
209
|
- lib/pod_builder/podfile_item.rb
|
|
210
210
|
- lib/pod_builder/podspec.rb
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
require 'xcodeproj'
|
|
2
|
-
require 'pod_builder/core'
|
|
3
|
-
|
|
4
|
-
module PodBuilder
|
|
5
|
-
class Podfile
|
|
6
|
-
def self.pod_builder_post_process
|
|
7
|
-
Configuration.load
|
|
8
|
-
|
|
9
|
-
targets = find_xcodeproj_targets
|
|
10
|
-
target_names = targets.map(&:name)
|
|
11
|
-
|
|
12
|
-
puts "[PodBuilder] Removing target support duplicated entries".yellow
|
|
13
|
-
# Frameworks and resources
|
|
14
|
-
target_names.each do |target|
|
|
15
|
-
remove_duplicate_entries("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-frameworks.sh")
|
|
16
|
-
remove_duplicate_entries("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-resources.sh")
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
puts "[PodBuilder] Checking target support resource collisions".yellow
|
|
20
|
-
target_names.each do |target|
|
|
21
|
-
check_for_colliding_resources("Pods/Target Support Files/Pods-#{target}/Pods-#{target}-resources.sh", target, targets)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def self.remove_duplicate_entries(path)
|
|
28
|
-
if !File.file?(path)
|
|
29
|
-
return
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Adding the same pod to multiple targets results in duplicate entries in Pods-TARGET-frameworks.sh and Pods-TARGET-resources.sh (Cocoapods 1.4.0)
|
|
33
|
-
# To avoid conflicts during parallel codesign we manually remove duplicates
|
|
34
|
-
in_section_to_update = false
|
|
35
|
-
processed_entries = []
|
|
36
|
-
lines = []
|
|
37
|
-
File.read(path).each_line do |line|
|
|
38
|
-
stripped_line = line.strip()
|
|
39
|
-
next if stripped_line.empty?
|
|
40
|
-
|
|
41
|
-
if stripped_line.include?("if [[ \"$CONFIGURATION\" == ")
|
|
42
|
-
in_section_to_update = true
|
|
43
|
-
elsif stripped_line == "fi"
|
|
44
|
-
in_section_to_update = false
|
|
45
|
-
processed_entries = []
|
|
46
|
-
end
|
|
47
|
-
if in_section_to_update
|
|
48
|
-
if processed_entries.include?(stripped_line)
|
|
49
|
-
if !line.include?("#")
|
|
50
|
-
line = "# #{line}"
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
processed_entries.push(stripped_line)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
lines.push(line)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
File.write(path, lines.join)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def self.check_for_colliding_resources(path, target_name, targets)
|
|
63
|
-
if !File.file?(path)
|
|
64
|
-
return
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
if target = targets.detect { |x| x.name == target_name }
|
|
68
|
-
resource_files = target.resources_build_phase.files.map { |i| i.file_ref.real_path.to_s }.to_set
|
|
69
|
-
resource_files = resource_files.map { |i| File.basename(i) }
|
|
70
|
-
resource_files = resource_files.map { |i| i.gsub(".xib", ".nib") }
|
|
71
|
-
else
|
|
72
|
-
raise "\n\n#{target} not found!".red
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Check that Pods-TARGET-resources.sh doesn't contain colliding entries (Cocoapods 1.4.0)
|
|
76
|
-
in_section_to_update = false
|
|
77
|
-
processed_entries = []
|
|
78
|
-
File.read(path).each_line do |line|
|
|
79
|
-
stripped_line = line.strip()
|
|
80
|
-
next if stripped_line.empty?
|
|
81
|
-
|
|
82
|
-
if stripped_line.include?("if [[ \"$CONFIGURATION\" == ")
|
|
83
|
-
in_section_to_update = true
|
|
84
|
-
next
|
|
85
|
-
elsif stripped_line == "fi"
|
|
86
|
-
in_section_to_update = false
|
|
87
|
-
|
|
88
|
-
processed_entries.each do |entry|
|
|
89
|
-
matches_other_framework = processed_entries.select { |t| t[0] == entry[0] }
|
|
90
|
-
|
|
91
|
-
# Check for static framework cross-collisions
|
|
92
|
-
if matches_other_framework.count > 1
|
|
93
|
-
error = "\n\nCross-framework resource collision detected:\n"
|
|
94
|
-
error += "#{entry[0]} found in\n"
|
|
95
|
-
error += matches_other_framework.map { |x| "- #{x[1]}" }.join("\n")
|
|
96
|
-
error += "\n\n"
|
|
97
|
-
|
|
98
|
-
raise error.red
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Check for collisions with app's resources
|
|
102
|
-
matches_app_resources = resource_files.select { |t| t == entry[0] }
|
|
103
|
-
if matches_app_resources.count > 0
|
|
104
|
-
error = "\n\nResource collision with app file detected:\n"
|
|
105
|
-
error += "#{entry[0]} found in app but also in\n"
|
|
106
|
-
error += matches_app_resources.map { |x| "- #{x[1]}" }.join("\n")
|
|
107
|
-
error += "\n\n"
|
|
108
|
-
|
|
109
|
-
raise error.red
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
processed_entries = []
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
next if stripped_line.start_with?("#") # skip commented lines
|
|
117
|
-
next if stripped_line.count("/..") > 2 # skip development pods
|
|
118
|
-
|
|
119
|
-
line.gsub!("\"", "")
|
|
120
|
-
line.gsub!("install_resource", "")
|
|
121
|
-
line.strip!()
|
|
122
|
-
|
|
123
|
-
if in_section_to_update
|
|
124
|
-
filename = File.basename(line)
|
|
125
|
-
processed_entries.push([filename, line])
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def self.find_xcodeproj_targets
|
|
131
|
-
project = Xcodeproj::Project.open(PodBuilder::find_xcodeproj)
|
|
132
|
-
|
|
133
|
-
return project.targets
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|