cocoapods-binary-gcp 0.0.1

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.
@@ -0,0 +1,199 @@
1
+ # encoding: UTF-8
2
+ require_relative 'helper/podfile_options'
3
+ require_relative 'tool/tool'
4
+
5
+ module Pod
6
+ class Podfile
7
+ module DSL
8
+
9
+ # Enable prebuiding for all pods
10
+ # it has a lower priority to other binary settings
11
+ def all_binary!
12
+ DSL.prebuild_all = true
13
+ end
14
+
15
+ # - excepts: an array of name
16
+ def all_binary_except(excepts)
17
+ DSL.prebuild_all = true
18
+ DSL.except_binary_list = excepts
19
+ end
20
+
21
+ # Enable bitcode for prebuilt frameworks
22
+ def enable_bitcode_for_prebuilt_frameworks!
23
+ DSL.bitcode_enabled = true
24
+ end
25
+
26
+ # Don't remove source code of prebuilt pods
27
+ # It may speed up the pod install if git didn't
28
+ # include the `Pods` folder
29
+ def keep_source_code_for_prebuilt_frameworks!
30
+ DSL.dont_remove_source_code = true
31
+ end
32
+
33
+ # Enable shared cache of prebuild frameworks
34
+ # Frameworks are stored inside cocoapods cache folder
35
+ #
36
+ # Location: ~/Library/Caches/CocoaPods/Prebuilt/
37
+ # Structure: <xcode-version>/<framework-name>/<framework-version>/<options hash>/
38
+ # Options hash depends on:
39
+ # - bitcode(enable_bitcode_for_prebuilt_frameworks!);
40
+ # - custom options(set_custom_xcodebuild_options_for_prebuilt_frameworks);
41
+ # - platform name(ios, osx);
42
+ # def use_shared_cache!
43
+ # DSL.shared_cache_enabled = true
44
+ # end
45
+
46
+
47
+ # Options hash depends on:
48
+ # - bucket: bucketName
49
+ def use_gcp_cache(options)
50
+ DSL.shared_cache_enabled = true
51
+ DSL.shared_gcp_cache_enabled = true
52
+ DSL.gcp_options = options
53
+ end
54
+
55
+ # Add custom xcodebuild option to the prebuilding action
56
+ #
57
+ # You may use this for your special demands. For example: the default archs in dSYMs
58
+ # of prebuilt frameworks is 'arm64 armv7 x86_64', and no 'i386' for 32bit simulator.
59
+ # It may generate a warning when building for a 32bit simulator. You may add following
60
+ # to your podfile
61
+ #
62
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks :simulator => "ARCHS=$(ARCHS_STANDARD)" `
63
+ #
64
+ # Another example to disable the generating of dSYM file:
65
+ #
66
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks "DEBUG_INFORMATION_FORMAT=dwarf"`
67
+ #
68
+ #
69
+ # @param [String or Hash] options
70
+ #
71
+ # If is a String, it will apply for device and simulator. Use it just like in the commandline.
72
+ # If is a Hash, it should be like this: { :device => "XXXXX", :simulator => "XXXXX" }
73
+ #
74
+ def set_custom_xcodebuild_options_for_prebuilt_frameworks(options)
75
+ if options.kind_of? Hash
76
+ DSL.custom_build_options = [ options[:device] ] unless options[:device].nil?
77
+ DSL.custom_build_options_simulator = [ options[:simulator] ] unless options[:simulator].nil?
78
+ elsif options.kind_of? String
79
+ DSL.custom_build_options = [options]
80
+ DSL.custom_build_options_simulator = [options]
81
+ else
82
+ raise "Wrong type."
83
+ end
84
+ end
85
+
86
+ private
87
+ class_attr_accessor :prebuild_all
88
+ prebuild_all = false
89
+
90
+ class_attr_accessor :bitcode_enabled
91
+ bitcode_enabled = false
92
+
93
+ class_attr_accessor :dont_remove_source_code
94
+ dont_remove_source_code = false
95
+
96
+ class_attr_accessor :shared_cache_enabled
97
+ shared_cache_enabled = false
98
+
99
+ class_attr_accessor :shared_gcp_cache_enabled
100
+ shared_gcp_cache_enabled = false
101
+
102
+ class_attr_accessor :gcp_options
103
+ gcp_options = {}
104
+
105
+ class_attr_accessor :custom_build_options
106
+ class_attr_accessor :custom_build_options_simulator
107
+ self.custom_build_options = []
108
+ self.custom_build_options_simulator = []
109
+
110
+ class_attr_accessor :except_binary_list
111
+ self.except_binary_list = []
112
+ end
113
+ end
114
+ end
115
+
116
+ Pod::HooksManager.register('cocoapods-binary', :pre_install) do |installer_context|
117
+
118
+ require_relative 'helper/feature_switches'
119
+ if Pod.is_prebuild_stage
120
+ next
121
+ end
122
+
123
+ # [Check Environment]
124
+ # check user_framework is on
125
+ podfile = installer_context.podfile
126
+ podfile.target_definition_list.each do |target_definition|
127
+ next if target_definition.prebuild_framework_pod_names.empty?
128
+ if not target_definition.uses_frameworks?
129
+ STDERR.puts "[!] Cocoapods-binary requires `use_frameworks!`".red
130
+ exit
131
+ end
132
+ end
133
+
134
+
135
+ # -- step 1: prebuild framework ---
136
+ # Execute a sperated pod install, to generate targets for building framework,
137
+ # then compile them to framework files.
138
+ require_relative 'helper/prebuild_sandbox'
139
+ require_relative 'Prebuild'
140
+
141
+ Pod::UI.puts "🚀 Prebuild frameworks"
142
+
143
+ # Fetch original installer (which is running this pre-install hook) options,
144
+ # then pass them to our installer to perform update if needed
145
+ # Looks like this is the most appropriate way to figure out that something should be updated
146
+
147
+ update = nil
148
+ repo_update = nil
149
+
150
+ include ObjectSpace
151
+ ObjectSpace.each_object(Pod::Installer) { |installer|
152
+ update = installer.update
153
+ repo_update = installer.repo_update
154
+ }
155
+
156
+ # control features
157
+ Pod.is_prebuild_stage = true
158
+ Pod::Podfile::DSL.enable_prebuild_patch true # enable sikpping for prebuild targets
159
+ Pod::Installer.force_disable_integration true # don't integrate targets
160
+ Pod::Config.force_disable_write_lockfile true # disbale write lock file for perbuild podfile
161
+ Pod::Installer.disable_install_complete_message true # disable install complete message
162
+
163
+ # make another custom sandbox
164
+ standard_sandbox = installer_context.sandbox
165
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
166
+
167
+ # get the podfile for prebuild
168
+ prebuild_podfile = Pod::Podfile.from_ruby(podfile.defined_in_file)
169
+
170
+ # install
171
+ lockfile = installer_context.lockfile
172
+ binary_installer = Pod::Installer.new(prebuild_sandbox, prebuild_podfile, lockfile)
173
+
174
+ if binary_installer.have_exact_prebuild_cache? && !update
175
+ binary_installer.install_when_cache_hit!
176
+ else
177
+ binary_installer.update = update
178
+ binary_installer.repo_update = repo_update
179
+ binary_installer.install!
180
+ end
181
+
182
+
183
+ # reset the environment
184
+ Pod.is_prebuild_stage = false
185
+ Pod::Installer.force_disable_integration false
186
+ Pod::Podfile::DSL.enable_prebuild_patch false
187
+ Pod::Config.force_disable_write_lockfile false
188
+ Pod::Installer.disable_install_complete_message false
189
+ Pod::UserInterface.warnings = [] # clean the warning in the prebuild step, it's duplicated.
190
+
191
+
192
+ # -- step 2: pod install ---
193
+ # install
194
+ Pod::UI.puts "\n"
195
+ Pod::UI.puts "🤖 Pod Install"
196
+ require_relative 'Integration'
197
+ # go on the normal install step ...
198
+ end
199
+
@@ -0,0 +1,273 @@
1
+ require_relative 'rome/build_framework'
2
+ require_relative 'helper/passer'
3
+ require_relative 'helper/target_checker'
4
+ require_relative 'helper/shared_cache'
5
+
6
+
7
+ # patch prebuild ability
8
+ module Pod
9
+ class Installer
10
+
11
+
12
+ private
13
+
14
+ def local_manifest
15
+ if not @local_manifest_inited
16
+ @local_manifest_inited = true
17
+ raise "This method should be call before generate project" unless self.analysis_result == nil
18
+ @local_manifest = self.sandbox.manifest
19
+ end
20
+ @local_manifest
21
+ end
22
+
23
+ # @return [Analyzer::SpecsState]
24
+ def prebuild_pods_changes
25
+ return nil if local_manifest.nil?
26
+ if @prebuild_pods_changes.nil?
27
+ changes = local_manifest.detect_changes_with_podfile(podfile)
28
+ @prebuild_pods_changes = Analyzer::SpecsState.new(changes)
29
+ # save the chagnes info for later stage
30
+ Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes
31
+ end
32
+ @prebuild_pods_changes
33
+ end
34
+
35
+
36
+ public
37
+
38
+ # check if need to prebuild
39
+ def have_exact_prebuild_cache?
40
+ # check if need build frameworks
41
+ return false if local_manifest == nil
42
+
43
+ changes = prebuild_pods_changes
44
+ added = changes.added
45
+ changed = changes.changed
46
+ unchanged = changes.unchanged
47
+ deleted = changes.deleted
48
+
49
+ exsited_framework_pod_names = sandbox.exsited_framework_pod_names
50
+ missing = unchanged.select do |pod_name|
51
+ not exsited_framework_pod_names.include?(pod_name)
52
+ end
53
+
54
+ needed = (added + changed + deleted + missing)
55
+ return needed.empty?
56
+ end
57
+
58
+
59
+ # The install method when have completed cache
60
+ def install_when_cache_hit!
61
+ # just print log
62
+ self.sandbox.exsited_framework_target_names.each do |name|
63
+ UI.puts "Using #{name}"
64
+ end
65
+ end
66
+
67
+
68
+ # Build the needed framework files
69
+ def prebuild_frameworks!
70
+
71
+ # build options
72
+ sandbox_path = sandbox.root
73
+ existed_framework_folder = sandbox.generate_framework_path
74
+
75
+ options = [
76
+ Podfile::DSL.bitcode_enabled,
77
+ Podfile::DSL.custom_build_options,
78
+ Podfile::DSL.custom_build_options_simulator
79
+ ]
80
+ targets = []
81
+
82
+ if local_manifest != nil
83
+
84
+ changes = prebuild_pods_changes
85
+ added = changes.added
86
+ changed = changes.changed
87
+ unchanged = changes.unchanged
88
+ deleted = changes.deleted
89
+
90
+ existed_framework_folder.mkdir unless existed_framework_folder.exist?
91
+ exsited_framework_pod_names = sandbox.exsited_framework_pod_names
92
+
93
+ # additions
94
+ missing = unchanged.select do |pod_name|
95
+ not exsited_framework_pod_names.include?(pod_name)
96
+ end
97
+
98
+
99
+ root_names_to_update = (added + changed + missing)
100
+
101
+ # transform names to targets
102
+ cache = []
103
+ targets = root_names_to_update.map do |pod_name|
104
+ tars = Pod.fast_get_targets_for_pod_name(pod_name, self.pod_targets, cache)
105
+ if tars.nil? || tars.empty?
106
+ raise "There's no target named (#{pod_name}) in Pod.xcodeproj.\n #{self.pod_targets.map(&:name)}" if t.nil?
107
+ end
108
+ tars
109
+ end.flatten
110
+
111
+ # add the dependencies
112
+ dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
113
+ # filter already built dependencies
114
+ dependency_targets = dependency_targets.reject { |t|
115
+ local_manifest.version(t.name).to_s.eql? t.version.to_s
116
+ }
117
+
118
+ targets = (targets + dependency_targets).uniq
119
+ else
120
+ targets = self.pod_targets
121
+ end
122
+
123
+ # frameworks which mark binary true, should be filtered before prebuild
124
+
125
+ prebuild_framework_pod_names = []
126
+ podfile.target_definition_list.each do |target_definition|
127
+ next if target_definition.prebuild_framework_pod_names.empty?
128
+ prebuild_framework_pod_names += target_definition.prebuild_framework_pod_names
129
+ end
130
+
131
+
132
+ targets = targets
133
+ .reject {|pod_target| sandbox.local?(pod_target.pod_name) }
134
+ .select {|pod_target| prebuild_framework_pod_names.include?(pod_target.pod_name) }
135
+
136
+ # if not Pod::Podfile::DSL.except_binary_list.nil?
137
+ # targets = targets.reject { |pod_target| Pod::Podfile::DSL.except_binary_list.include?(pod_target.pod_name) }
138
+ # end
139
+
140
+ # build!
141
+ Pod::UI.puts "Prebuild frameworks (total #{targets.count})"
142
+ Pod::Prebuild.remove_build_dir(sandbox_path)
143
+ targets.each do |target|
144
+ if !target.should_build?
145
+ UI.puts "Prebuilding #{target.label}"
146
+ next
147
+ end
148
+
149
+ output_path = sandbox.framework_folder_path_for_target_name(target.name)
150
+ output_path.mkpath unless output_path.exist?
151
+
152
+ if Prebuild::SharedCache.has?(target, options)
153
+ framework_cache_path = Prebuild::SharedCache.framework_cache_path_for(target, options)
154
+ UI.puts "Using #{target.label} from cache"
155
+ FileUtils.cp_r "#{framework_cache_path}/.", output_path
156
+ else
157
+ min_deployment_target = aggregate_targets
158
+ .select { |t| t.pod_targets.include?(target) }
159
+ .map(&:platform)
160
+ .map(&:deployment_target)
161
+ .max
162
+
163
+ Pod::Prebuild.build(sandbox_path, target, output_path, min_deployment_target, *options)
164
+ Prebuild::SharedCache.cache(target, output_path, options)
165
+ end
166
+
167
+ # save the resource paths for later installing
168
+ if target.static_framework? and !target.resource_paths.empty?
169
+ framework_path = output_path + target.framework_name
170
+ standard_sandbox_path = sandbox.standard_sanbox_path
171
+
172
+ resources = begin
173
+ if Pod::VERSION.start_with? "1.5"
174
+ target.resource_paths
175
+ else
176
+ # resource_paths is Hash{String=>Array<String>} on 1.6 and above
177
+ # (use AFNetworking to generate a demo data)
178
+ # https://github.com/leavez/cocoapods-binary/issues/50
179
+ target.resource_paths.values.flatten
180
+ end
181
+ end
182
+ raise "Wrong type: #{resources}" unless resources.kind_of? Array
183
+
184
+ path_objects = resources.map do |path|
185
+ object = Prebuild::Passer::ResourcePath.new
186
+ object.real_file_path = framework_path + File.basename(path)
187
+ object.target_file_path = path.gsub('${PODS_ROOT}', standard_sandbox_path.to_s) if path.start_with? '${PODS_ROOT}'
188
+ object.target_file_path = path.gsub("${PODS_CONFIGURATION_BUILD_DIR}", standard_sandbox_path.to_s) if path.start_with? "${PODS_CONFIGURATION_BUILD_DIR}"
189
+ object
190
+ end
191
+ Prebuild::Passer.resources_to_copy_for_static_framework[target.name] = path_objects
192
+ end
193
+
194
+ end
195
+ Pod::Prebuild.remove_build_dir(sandbox_path)
196
+
197
+
198
+ # copy vendored libraries and frameworks
199
+ targets.each do |target|
200
+ root_path = self.sandbox.pod_dir(target.name)
201
+ target_folder = sandbox.framework_folder_path_for_target_name(target.name)
202
+
203
+ # If target shouldn't build, we copy all the original files
204
+ # This is for target with only .a and .h files
205
+ if not target.should_build?
206
+ Prebuild::Passer.target_names_to_skip_integration_framework << target.name
207
+ FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
208
+ next
209
+ end
210
+
211
+ target.spec_consumers.each do |consumer|
212
+ file_accessor = Sandbox::FileAccessor.new(root_path, consumer)
213
+ lib_paths = file_accessor.vendored_frameworks || []
214
+ lib_paths += file_accessor.vendored_libraries
215
+ # @TODO dSYM files
216
+ lib_paths.each do |lib_path|
217
+ relative = lib_path.relative_path_from(root_path)
218
+ destination = target_folder + relative
219
+ destination.dirname.mkpath unless destination.dirname.exist?
220
+ FileUtils.cp_r(lib_path, destination, :remove_destination => true)
221
+ end
222
+ end
223
+ end
224
+
225
+ # save the pod_name for prebuild framwork in sandbox
226
+ targets.each do |target|
227
+ sandbox.save_pod_name_for_target target
228
+ end
229
+
230
+ # Remove useless files
231
+ # remove useless pods
232
+ all_needed_names = self.pod_targets.map(&:name).uniq
233
+ useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
234
+ all_needed_names.include? name
235
+ end
236
+ useless_target_names.each do |name|
237
+ path = sandbox.framework_folder_path_for_target_name(name)
238
+ path.rmtree if path.exist?
239
+ end
240
+
241
+ if not Podfile::DSL.dont_remove_source_code
242
+ # only keep manifest.lock and framework folder in _Prebuild
243
+ to_remain_files = ["Manifest.lock", File.basename(existed_framework_folder)]
244
+ to_delete_files = sandbox_path.children.select do |file|
245
+ filename = File.basename(file)
246
+ not to_remain_files.include?(filename)
247
+ end
248
+ to_delete_files.each do |path|
249
+ path.rmtree if path.exist?
250
+ end
251
+ else
252
+ # just remove the tmp files
253
+ path = sandbox.root + 'Manifest.lock.tmp'
254
+ path.rmtree if path.exist?
255
+ end
256
+
257
+
258
+
259
+ end
260
+
261
+
262
+ # patch the post install hook
263
+ old_method2 = instance_method(:run_plugins_post_install_hooks)
264
+ define_method(:run_plugins_post_install_hooks) do
265
+ old_method2.bind(self).()
266
+ if Pod::is_prebuild_stage
267
+ self.prebuild_frameworks!
268
+ end
269
+ end
270
+
271
+
272
+ end
273
+ end