-
Notifications
You must be signed in to change notification settings - Fork 207
/
Copy pathPrebuild.rb
241 lines (192 loc) · 9.53 KB
/
Prebuild.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
232
233
234
235
236
237
238
239
240
241
require_relative 'rome/build_framework'
require_relative 'helper/passer'
require_relative 'helper/target_checker'
# patch prebuild ability
module Pod
class Installer
private
def local_manifest
if not @local_manifest_inited
@local_manifest_inited = true
raise "This method should be call before generate project" unless self.analysis_result == nil
@local_manifest = self.sandbox.manifest
end
@local_manifest
end
# @return [Analyzer::SpecsState]
def prebuild_pods_changes
return nil if local_manifest.nil?
if @prebuild_pods_changes.nil?
changes = local_manifest.detect_changes_with_podfile(podfile)
@prebuild_pods_changes = Analyzer::SpecsState.new(changes)
# save the chagnes info for later stage
Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes
end
@prebuild_pods_changes
end
public
# check if need to prebuild
def have_exact_prebuild_cache?
# check if need build frameworks
return false if local_manifest == nil
changes = prebuild_pods_changes
added = changes.added
changed = changes.changed
unchanged = changes.unchanged
deleted = changes.deleted
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
missing = unchanged.select do |pod_name|
not exsited_framework_pod_names.include?(pod_name)
end
needed = (added + changed + deleted + missing)
return needed.empty?
end
# The install method when have completed cache
def install_when_cache_hit!
# just print log
self.sandbox.exsited_framework_target_names.each do |name|
UI.puts "Using #{name}"
end
end
# Build the needed framework files
def prebuild_frameworks!
# build options
sandbox_path = sandbox.root
existed_framework_folder = sandbox.generate_framework_path
bitcode_enabled = Pod::Podfile::DSL.bitcode_enabled
targets = []
if local_manifest != nil
changes = prebuild_pods_changes
added = changes.added
changed = changes.changed
unchanged = changes.unchanged
deleted = changes.deleted
existed_framework_folder.mkdir unless existed_framework_folder.exist?
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
# additions
missing = unchanged.select do |pod_name|
not exsited_framework_pod_names.include?(pod_name)
end
root_names_to_update = (added + changed + missing)
# transform names to targets
cache = []
targets = root_names_to_update.map do |pod_name|
tars = Pod.fast_get_targets_for_pod_name(pod_name, self.pod_targets, cache)
if tars.nil? || tars.empty?
raise "There's no target named (#{pod_name}) in Pod.xcodeproj.\n #{self.pod_targets.map(&:name)}" if t.nil?
end
tars
end.flatten
# add the dendencies
dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
targets = (targets + dependency_targets).uniq
else
targets = self.pod_targets
end
targets = targets.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
# build!
Pod::UI.puts "Prebuild frameworks (total #{targets.count})"
Pod::Prebuild.remove_build_dir(sandbox_path)
targets.each do |target|
if !target.should_build?
UI.puts "Prebuilding #{target.label}"
next
end
output_path = sandbox.framework_folder_path_for_target_name(target.name)
output_path.mkpath unless output_path.exist?
min_deployment_target = aggregate_targets
.select { |t| t.pod_targets.include?(target) }
.map(&:platform)
.map(&:deployment_target)
.max
Pod::Prebuild.build(sandbox_path, target, min_deployment_target, output_path, bitcode_enabled, Podfile::DSL.custom_build_options, Podfile::DSL.custom_build_options_simulator)
# save the resource paths for later installing
if target.static_framework? and !target.resource_paths.empty?
framework_path = output_path + target.framework_name
standard_sandbox_path = sandbox.standard_sanbox_path
resources = begin
if Pod::VERSION.start_with? "1.5"
target.resource_paths
else
# resource_paths is Hash{String=>Array<String>} on 1.6 and above
# (use AFNetworking to generate a demo data)
# https://github.com/leavez/cocoapods-binary/issues/50
target.resource_paths.values.flatten
end
end
raise "Wrong type: #{resources}" unless resources.kind_of? Array
path_objects = resources.map do |path|
object = Prebuild::Passer::ResourcePath.new
object.real_file_path = framework_path + File.basename(path)
object.target_file_path = path.gsub('${PODS_ROOT}', standard_sandbox_path.to_s) if path.start_with? '${PODS_ROOT}'
object.target_file_path = path.gsub("${PODS_CONFIGURATION_BUILD_DIR}", standard_sandbox_path.to_s) if path.start_with? "${PODS_CONFIGURATION_BUILD_DIR}"
object
end
Prebuild::Passer.resources_to_copy_for_static_framework[target.name] = path_objects
end
end
Pod::Prebuild.remove_build_dir(sandbox_path)
# copy vendored libraries and frameworks
targets.each do |target|
root_path = self.sandbox.pod_dir(target.name)
target_folder = sandbox.framework_folder_path_for_target_name(target.name)
# If target shouldn't build, we copy all the original files
# This is for target with only .a and .h files
if not target.should_build?
Prebuild::Passer.target_names_to_skip_integration_framework << target.name
FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
next
end
target.spec_consumers.each do |consumer|
file_accessor = Sandbox::FileAccessor.new(root_path, consumer)
lib_paths = file_accessor.vendored_frameworks || []
lib_paths += file_accessor.vendored_libraries
# @TODO dSYM files
lib_paths.each do |lib_path|
relative = lib_path.relative_path_from(root_path)
destination = target_folder + relative
destination.dirname.mkpath unless destination.dirname.exist?
FileUtils.cp_r(lib_path, destination, :remove_destination => true)
end
end
end
# save the pod_name for prebuild framwork in sandbox
targets.each do |target|
sandbox.save_pod_name_for_target target
end
# Remove useless files
# remove useless pods
all_needed_names = self.pod_targets.map(&:name).uniq
useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
all_needed_names.include? name
end
useless_target_names.each do |name|
path = sandbox.framework_folder_path_for_target_name(name)
path.rmtree if path.exist?
end
if not Podfile::DSL.dont_remove_source_code
# only keep manifest.lock and framework folder in _Prebuild
to_remain_files = ["Manifest.lock", File.basename(existed_framework_folder)]
to_delete_files = sandbox_path.children.select do |file|
filename = File.basename(file)
not to_remain_files.include?(filename)
end
to_delete_files.each do |path|
path.rmtree if path.exist?
end
else
# just remove the tmp files
path = sandbox.root + 'Manifest.lock.tmp'
path.rmtree if path.exist?
end
end
# patch the post install hook
old_method2 = instance_method(:run_plugins_post_install_hooks)
define_method(:run_plugins_post_install_hooks) do
old_method2.bind(self).()
if Pod::is_prebuild_stage
self.prebuild_frameworks!
end
end
end
end