Class: Pod::Installer

Inherits:
Object
  • Object
show all
Includes:
Config::Mixin
Defined in:
lib/cocoapods-binary-bugfix/helper/feature_switches.rb,
lib/cocoapods-binary-bugfix/Prebuild.rb,
lib/cocoapods-binary-bugfix/Integration.rb,
lib/cocoapods-binary-bugfix/Integration.rb,
lib/cocoapods-binary-bugfix/helper/podfile_options.rb,
lib/cocoapods-binary-bugfix/helper/feature_switches.rb

Overview

a option to disable install complete message

Defined Under Namespace

Classes: PodSourceInstaller

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.disable_install_complete_message(value) ⇒ Object



69
70
71
# File 'lib/cocoapods-binary-bugfix/helper/feature_switches.rb', line 69

def self.disable_install_complete_message(value)
    @@disable_install_complete_message = value
end

.force_disable_integration(value) ⇒ Object



54
55
56
# File 'lib/cocoapods-binary-bugfix/helper/feature_switches.rb', line 54

def self.force_disable_integration(value)
    @@force_disable_integration = value
end

Instance Method Details

#delete_all_standard_sandbox_pod(standard_sanbox) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 172

def delete_all_standard_sandbox_pod(standard_sanbox)
    if lockfile
        changes = lockfile.detect_changes_with_podfile(podfile)
        need_update_pods = (changes[:added] + changes[:changed] + changes[:removed] + changes[:unchanged]).to_a
    
        need_update_pods.each do |pod_name|
            pod_path = Pathname.new(standard_sanbox.root.to_s + "/#{pod_name}")
            Pod::UI.puts("删除 #{pod_path.to_s}") if config.verbose
            pod_path.rmtree if pod_path.exist?
        end                
    end
end

#delete_standard_sand_box_pod(standard_sanbox) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 159

def delete_standard_sand_box_pod(standard_sanbox)
    if lockfile
        changes = lockfile.detect_changes_with_podfile(podfile)
        need_update_pods = (changes[:added] + changes[:changed] + changes[:removed]).to_a
    
        need_update_pods.each do |pod_name|
            pod_path = Pathname.new(standard_sanbox.root.to_s + "/#{pod_name}")
            Pod::UI.puts("删除 #{pod_path.to_s}") if config.verbose
            pod_path.rmtree if pod_path.exist?
        end                
    end
end

#handle_static_framework_resoucesObject

处理静态库资源



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
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 185

def handle_static_framework_resouces
    all_static_framework_targets = pod_targets.reject{|pod_target| not pod_target.static_framework? or pod_target.resource_paths.empty? }
    all_static_framework_targets.each do |target|        
        output_path = sandbox.framework_folder_path_for_target_name(target.name)
        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|
                prebuild_real_path = (path.gsub('${PODS_ROOT}', sandbox.root.to_s) if path.start_with? '${PODS_ROOT}')|| ""
                real_file_path = framework_path + File.basename(path)
                if Pathname.new(prebuild_real_path).exist? and
                     Pathname.new(framework_path).exist? and 
                     not Pathname.new(real_file_path).exist?
                    # 静态库的resource,拷贝至framework目录下
                    FileUtils.cp_r(prebuild_real_path, real_file_path, :remove_destination => true)
                end
                object = Prebuild::Passer::ResourcePath.new
                object.real_file_path = real_file_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
end

#have_exact_prebuild_cache?Boolean

check if need to prebuild

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 110

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

#install_when_cache_hit!Object

The install method when have completed cache



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 144

def install_when_cache_hit!
    # just print log
    self.sandbox.exsited_framework_target_names.each do |name|
        UI.puts "Using #{name}" if config.verbose
    end

    self.sandbox
     #处理静态库resources 资源文件
    self.resolve_dependencies
    self.download_dependencies
   
    self.handle_static_framework_resouces
    
end

#post_update_pods_changesObject

pod update 之后 lockfile 文件更新,更新lockfile对象,再次检查与预编译的版本是否一致



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
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 69

def post_update_pods_changes
    changes = lockfile.detect_changes_with_podfile(podfile)
    unchanged_pod_names = changes[:unchanged]
    changed_pod_names = changes[:changed]
    add_pod_names = changes[:added]
    removed_pod_names = changes[:removed]


    unchanged_pod_names.reverse_each do |name|
        mainfest_pod_version = lockfile.version(name).to_s
        already_prebuild_version = prebuilded_framework_version(name) || "未找到"
        if compare_version(mainfest_pod_version, already_prebuild_version)
            # 已经编译了
            removed_pod_names.delete(name) if removed_pod_names.include?(name)
            add_pod_names.delete(name) if add_pod_names.include?(name)
            changed_pod_names.delete(name) if changed_pod_names.include?(name)
       
        else
            # 未找到相对应的版本
            if already_prebuild_version == "99999.99999.99999"
                Pod::UI.puts("- #{name}: 未找到预编译文件, manifest中的版本: #{mainfest_pod_version}") if config.verbose
            else 
                Pod::UI.puts("- #{name}:  已编译版 #{already_prebuild_version}, manifest中的版本: #{mainfest_pod_version}") if config.verbose
            end
            changed_pod_names = changed_pod_names.push(name)
            unchanged_pod_names.delete(name) if unchanged_pod_names.include?(name)
        end
    end
    changes[:removed] = removed_pod_names
    changes[:added] = add_pod_names
    changes[:changed] = changed_pod_names
    changes[:unchanged] = unchanged_pod_names
    Pod::UI.puts("post 需要重编译的framework : #{(changed_pod_names + removed_pod_names + add_pod_names ).to_a}") if config.verbose
    @prebuild_pods_changes = Analyzer::SpecsState.new(changes)
    # save the chagnes info for later stage
    Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes 
    @prebuild_pods_changes

end

#prebuild_frameworks!(after_write_lock) ⇒ Object

Build the needed framework files



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 226

def prebuild_frameworks!(after_write_lock) 
    # 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

        if after_write_lock 
            changes = post_update_pods_changes
        elsif
            changes = prebuild_pods_changes
        end

        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.rmtree if output_path.exist?
        output_path.mkpath unless output_path.exist?
        Pod::Prebuild.build(sandbox_path, target, output_path, bitcode_enabled,  Podfile::DSL.custom_build_options,  Podfile::DSL.custom_build_options_simulator)
    end
    # check static_framework resources
    self.handle_static_framework_resouces
    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
    # 不删除已经编译好的framework
    # 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

#prebuild_pod_namesObject

the root names who needs prebuild, including dependency pods.



110
111
112
# File 'lib/cocoapods-binary-bugfix/helper/podfile_options.rb', line 110

def prebuild_pod_names 
   @prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
end

#prebuild_pod_targetsObject



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
# File 'lib/cocoapods-binary-bugfix/helper/podfile_options.rb', line 75

def prebuild_pod_targets
    @prebuild_pod_targets ||= (
    all = []

    aggregate_targets = self.aggregate_targets
    aggregate_targets.each do |aggregate_target|
        target_definition = aggregate_target.target_definition
        targets = aggregate_target.pod_targets || []
        # filter prebuild
        prebuild_names = target_definition.prebuild_framework_pod_names
        if not Podfile::DSL.prebuild_all
            targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) } 
        end
    
        dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
     
        targets = (targets + dependency_targets).uniq
        # filter should not prebuild
        explict_should_not_names = target_definition.should_not_prebuild_framework_pod_names
        Pod::UI.puts(">>>>>>> 不需要二进制的framework: #{explict_should_not_names} ") if config.verbose
        targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) } 

        all += targets
       
    end
    all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
    Pod::UI.puts(">>>>>>> 需要二进制的framework: #{all}") if config.verbose
    all.uniq

       
    
    )
end

#prebuilded_framework_version(name) ⇒ Object

当前已编译的framework的版本



131
132
133
134
135
136
137
138
139
140
# File 'lib/cocoapods-binary-bugfix/Prebuild.rb', line 131

def prebuilded_framework_version(name)
    path = self.sandbox.plist_path_for_target_name(name)
    framework_version = "99999.99999.99999"
    if Pathname.new(path).exist?
        plist_file = CFPropertyList::List.new(:file => path) 
        data = CFPropertyList.native_types(plist_file.value)
        framework_version = data["CFBundleShortVersionString"]
    end
    framework_version
end

#remove_target_files_if_neededObject

Remove the old target files if prebuild frameworks changed



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
# File 'lib/cocoapods-binary-bugfix/Integration.rb', line 112

def remove_target_files_if_needed

    changes = Pod::Prebuild::Passer.prebuild_pods_changes
    updated_names = []
    if changes == nil
        updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_pod_names
    else
        added = changes.added
        changed = changes.changed 
        deleted = changes.deleted 
        updated_names = added + changed + deleted
    end

    updated_names.each do |name|
        root_name = Specification.root_name(name)
        next if self.sandbox.local?(root_name)

        # delete the cached files
        target_path = self.sandbox.pod_dir(root_name)
        target_path.rmtree if target_path.exist?

        support_path = sandbox.target_support_files_dir(root_name)
        support_path.rmtree if support_path.exist?
    end

end

#validate_every_pod_only_have_one_formObject

Raises:

  • (Informative)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/cocoapods-binary-bugfix/helper/podfile_options.rb', line 115

def validate_every_pod_only_have_one_form

    multi_targets_pods = self.pod_targets.group_by do |t|
        t.pod_name
    end.select do |k, v|
        v.map{|t| t.platform.name }.count > 1
    end

    multi_targets_pods = multi_targets_pods.reject do |name, targets|
        contained = targets.map{|t| self.prebuild_pod_targets.include? t }
        contained.uniq.count == 1 # all equal
    end

    return if multi_targets_pods.empty?

    warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
    warnings += multi_targets_pods.map{|name, targets| "         #{name}: #{targets.map{|t|t.platform.name}}"}.join("\n")
    raise Informative, warnings
end