cocoapods-binary-bel 0.5.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,292 @@
1
+ require_relative 'helper/podfile_options'
2
+ require_relative 'helper/feature_switches'
3
+ require_relative 'helper/prebuild_sandbox'
4
+ require_relative 'helper/passer'
5
+ require_relative 'helper/names'
6
+ require_relative 'helper/target_checker'
7
+
8
+
9
+ # NOTE:
10
+ # This file will only be loaded on normal pod install step
11
+ # so there's no need to check is_prebuild_stage
12
+
13
+
14
+
15
+ # Provide a special "download" process for prebuilded pods.
16
+ #
17
+ # As the frameworks is already exsited in local folder. We
18
+ # just create a symlink to the original target folder.
19
+ #
20
+ module Pod
21
+ class Installer
22
+ class PodSourceInstaller
23
+
24
+ def install_for_prebuild!(standard_sanbox)
25
+ return if standard_sanbox.local? self.name
26
+
27
+ # make a symlink to target folder
28
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
29
+ # if spec used in multiple platforms, it may return multiple paths
30
+ target_names = prebuild_sandbox.existed_target_names_for_pod_name(self.name)
31
+
32
+ def walk(path, &action)
33
+ return unless path.exist?
34
+ path.children.each do |child|
35
+ result = action.call(child, &action)
36
+ if child.directory?
37
+ walk(child, &action) if result
38
+ end
39
+ end
40
+ end
41
+ def make_link(source, target)
42
+ source = Pathname.new(source)
43
+ target = Pathname.new(target)
44
+ target.parent.mkpath unless target.parent.exist?
45
+ relative_source = source.relative_path_from(target.parent)
46
+ FileUtils.ln_sf(relative_source, target)
47
+ end
48
+ def mirror_with_symlink(source, basefolder, target_folder)
49
+ target = target_folder + source.relative_path_from(basefolder)
50
+ make_link(source, target)
51
+ end
52
+
53
+ target_names.each do |name|
54
+
55
+ # symbol link copy all substructure
56
+ real_file_folder = prebuild_sandbox.framework_folder_path_for_target_name(name)
57
+
58
+ # If have only one platform, just place int the root folder of this pod.
59
+ # If have multiple paths, we use a sperated folder to store different
60
+ # platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework
61
+
62
+ target_folder = standard_sanbox.pod_dir(self.name)
63
+ if target_names.count > 1
64
+ target_folder += real_file_folder.basename
65
+ end
66
+ target_folder.rmtree if target_folder.exist?
67
+ target_folder.mkpath
68
+
69
+
70
+ walk(real_file_folder) do |child|
71
+ source = child
72
+ # only make symlink to file and `.framework` folder
73
+ if child.directory? and [".framework", ".dSYM"].include? child.extname
74
+ mirror_with_symlink(source, real_file_folder, target_folder)
75
+ next false # return false means don't go deeper
76
+ elsif child.file?
77
+ mirror_with_symlink(source, real_file_folder, target_folder)
78
+ next true
79
+ else
80
+ next true
81
+ end
82
+ end
83
+
84
+
85
+ # symbol link copy resource for static framework
86
+ hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}
87
+
88
+ path_objects = hash[name]
89
+ if path_objects != nil
90
+ path_objects.each do |object|
91
+ make_link(object.real_file_path, object.target_file_path)
92
+ end
93
+ end
94
+ end # of for each
95
+
96
+ end # of method
97
+
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ # Let cocoapods use the prebuild framework files in install process.
104
+ #
105
+ # the code only effect the second pod install process.
106
+ #
107
+ module Pod
108
+ class Installer
109
+
110
+
111
+ # Remove the old target files if prebuild frameworks changed
112
+ def remove_target_files_if_needed
113
+
114
+ changes = Pod::Prebuild::Passer.prebuild_pods_changes
115
+ updated_names = []
116
+ if changes == nil
117
+ updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_pod_names
118
+ else
119
+ added = changes.added
120
+ changed = changes.changed
121
+ deleted = changes.deleted
122
+ updated_names = added + changed + deleted
123
+ end
124
+
125
+ updated_names.each do |name|
126
+ root_name = Specification.root_name(name)
127
+ next if self.sandbox.local?(root_name)
128
+
129
+ # delete the cached files
130
+ target_path = self.sandbox.pod_dir(root_name)
131
+ target_path.rmtree if target_path.exist?
132
+
133
+ support_path = sandbox.target_support_files_dir(root_name)
134
+ support_path.rmtree if support_path.exist?
135
+ end
136
+
137
+ end
138
+
139
+
140
+ # Modify specification to use only the prebuild framework after analyzing
141
+ old_method2 = instance_method(:resolve_dependencies)
142
+ define_method(:resolve_dependencies) do
143
+
144
+ # Remove the old target files, else it will not notice file changes
145
+ self.remove_target_files_if_needed
146
+
147
+ # call original
148
+ old_method2.bind(self).()
149
+ # ...
150
+ # ...
151
+ # ...
152
+ # after finishing the very complex orginal function
153
+
154
+ # check the pods
155
+ # Although we have did it in prebuild stage, it's not sufficient.
156
+ # Same pod may appear in another target in form of source code.
157
+ # Prebuild.check_one_pod_should_have_only_one_target(self.prebuild_pod_targets)
158
+ self.validate_every_pod_only_have_one_form
159
+
160
+
161
+ # prepare
162
+ cache = []
163
+
164
+ def add_vendered_framework(spec, platform, added_framework_file_path)
165
+ if spec.attributes_hash[platform] == nil
166
+ spec.attributes_hash[platform] = {}
167
+ end
168
+ vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
169
+ vendored_frameworks = [vendored_frameworks] if vendored_frameworks.kind_of?(String)
170
+ vendored_frameworks += [added_framework_file_path]
171
+ spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
172
+ end
173
+ def empty_source_files(spec)
174
+ spec.attributes_hash["source_files"] = []
175
+ ["ios", "watchos", "tvos", "osx"].each do |plat|
176
+ if spec.attributes_hash[plat] != nil
177
+ spec.attributes_hash[plat]["source_files"] = []
178
+ end
179
+ end
180
+ end
181
+
182
+
183
+ specs = self.analysis_result.specifications
184
+
185
+ prebuilt_specs = (specs.select do |spec|
186
+
187
+ self.prebuild_pod_names.include? spec.root.name
188
+ end)
189
+
190
+ prebuilt_specs.each do |spec|
191
+
192
+ # Use the prebuild framworks as vendered frameworks
193
+ # get_corresponding_targets
194
+ targets = Pod.fast_get_targets_for_pod_name(spec.root.name, self.pod_targets, cache)
195
+
196
+ targets.each do |target|
197
+ # the framework_file_path rule is decided when `install_for_prebuild`,
198
+ # as to compitable with older version and be less wordy.
199
+ framework_file_path = target.framework_name
200
+ framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
201
+ add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
202
+ end
203
+ # Clean the source files
204
+ # we just add the prebuilt framework to specific platform and set no source files
205
+ # for all platform, so it doesn't support the sence that 'a pod perbuild for one
206
+ # platform and not for another platform.'
207
+ empty_source_files(spec)
208
+
209
+ # to remove the resurce bundle target.
210
+ # When specify the "resource_bundles" in podspec, xcode will generate a bundle
211
+ # target after pod install. But the bundle have already built when the prebuit
212
+ # phase and saved in the framework folder. We will treat it as a normal resource
213
+ # file.
214
+ # https://github.com/leavez/cocoapods-binary/issues/29
215
+ if spec.attributes_hash["resource_bundles"]
216
+ bundle_names = spec.attributes_hash["resource_bundles"].keys
217
+ spec.attributes_hash["resource_bundles"] = nil
218
+ spec.attributes_hash["resources"] ||= []
219
+ spec.attributes_hash["resources"] += bundle_names.map{|n| n+".bundle"}
220
+ end
221
+
222
+ # to avoid the warning of missing license
223
+ spec.attributes_hash["license"] = {}
224
+
225
+ end
226
+
227
+ end
228
+
229
+
230
+ # Override the download step to skip download and prepare file in target folder
231
+ old_method = instance_method(:install_source_of_pod)
232
+ define_method(:install_source_of_pod) do |pod_name|
233
+
234
+ # copy from original
235
+ pod_installer = create_pod_installer(pod_name)
236
+ # \copy from original
237
+
238
+ if self.prebuild_pod_names.include? pod_name
239
+ pod_installer.install_for_prebuild!(self.sandbox)
240
+ else
241
+ pod_installer.install!
242
+ end
243
+
244
+ # copy from original
245
+ @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
246
+ # \copy from original
247
+ end
248
+
249
+
250
+ end
251
+ end
252
+
253
+ # A fix in embeded frameworks script.
254
+ #
255
+ # The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
256
+ # to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
257
+ # we override the `readlink` to a fixed version.
258
+ #
259
+ module Pod
260
+ module Generator
261
+ class EmbedFrameworksScript
262
+
263
+ old_method = instance_method(:script)
264
+ define_method(:script) do
265
+
266
+ script = old_method.bind(self).()
267
+ patch = <<-SH.strip_heredoc
268
+ #!/bin/sh
269
+
270
+ # ---- this is added by cocoapods-binary ---
271
+ # Readlink cannot handle relative symlink well, so we override it to a new one
272
+ # If the path isn't an absolute path, we add a realtive prefix.
273
+ old_read_link=`which readlink`
274
+ readlink () {
275
+ path=`$old_read_link "$1"`;
276
+ if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
277
+ echo $path;
278
+ else
279
+ echo "`dirname $1`/$path";
280
+ fi
281
+ }
282
+ # ---
283
+ SH
284
+
285
+ # patch the rsync for copy dSYM symlink
286
+ script = script.gsub "rsync --delete", "rsync --copy-links --delete"
287
+
288
+ patch + script
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,178 @@
1
+ # encoding: UTF-8
2
+ require_relative 'helper/podfile_options'
3
+ require_relative 'tool/tool'
4
+ require_relative 'gem_version'
5
+ require_relative 'command_option/command_option'
6
+
7
+ module Pod
8
+ class Podfile
9
+ module DSL
10
+
11
+ # Enable prebuiding for all pods
12
+ # it has a lower priority to other binary settings
13
+ def all_binary!
14
+ DSL.prebuild_all = true
15
+ end
16
+
17
+ def all_source!
18
+ DSL.framework_source_all = true
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
+ # Add custom xcodebuild option to the prebuilding action
34
+ #
35
+ # You may use this for your special demands. For example: the default archs in dSYMs
36
+ # of prebuilt frameworks is 'arm64 armv7 x86_64', and no 'i386' for 32bit simulator.
37
+ # It may generate a warning when building for a 32bit simulator. You may add following
38
+ # to your podfile
39
+ #
40
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks :simulator => "ARCHS=$(ARCHS_STANDARD)" `
41
+ #
42
+ # Another example to disable the generating of dSYM file:
43
+ #
44
+ # ` set_custom_xcodebuild_options_for_prebuilt_frameworks "DEBUG_INFORMATION_FORMAT=dwarf"`
45
+ #
46
+ #
47
+ # @param [String or Hash] options
48
+ #
49
+ # If is a String, it will apply for device and simulator. Use it just like in the commandline.
50
+ # If is a Hash, it should be like this: { :device => "XXXXX", :simulator => "XXXXX" }
51
+ #
52
+ def set_custom_xcodebuild_options_for_prebuilt_frameworks(options)
53
+ if options.kind_of? Hash
54
+ DSL.custom_build_options = [ options[:device] ] unless options[:device].nil?
55
+ DSL.custom_build_options_simulator = [ options[:simulator] ] unless options[:simulator].nil?
56
+ elsif options.kind_of? String
57
+ DSL.custom_build_options = [options]
58
+ DSL.custom_build_options_simulator = [options]
59
+ else
60
+ raise "Wrong type."
61
+ end
62
+ end
63
+
64
+ private
65
+ class_attr_accessor :prebuild_all
66
+ prebuild_all = false
67
+
68
+ class_attr_accessor :framework_source_all
69
+ framework_source_all = false
70
+
71
+ class_attr_accessor :bitcode_enabled
72
+ bitcode_enabled = false
73
+
74
+ class_attr_accessor :dont_remove_source_code
75
+ dont_remove_source_code = false
76
+
77
+ class_attr_accessor :custom_build_options
78
+ class_attr_accessor :custom_build_options_simulator
79
+ self.custom_build_options = []
80
+ self.custom_build_options_simulator = []
81
+ end
82
+ end
83
+ end
84
+
85
+ Pod::HooksManager.register('cocoapods-binary-bel', :pre_install) do |installer_context|
86
+
87
+ require_relative 'helper/feature_switches'
88
+ if Pod.is_prebuild_stage
89
+ next
90
+ end
91
+
92
+ Pod::UI.puts("当前版本: #{CocoapodsBinaryBel::VERSION}")
93
+
94
+ # [Check Environment]
95
+ # check user_framework is on
96
+ podfile = installer_context.podfile
97
+ podfile.target_definition_list.each do |target_definition|
98
+ next if target_definition.prebuild_framework_pod_names.empty?
99
+ if not target_definition.uses_frameworks?
100
+ STDERR.puts "[!] Cocoapods-binary-bel requires `use_frameworks!`".red
101
+ exit
102
+ end
103
+ end
104
+
105
+
106
+ # -- step 1: prebuild framework ---
107
+ # Execute a sperated pod install, to generate targets for building framework,
108
+ # then compile them to framework files.
109
+ require_relative 'helper/prebuild_sandbox'
110
+ require_relative 'Prebuild'
111
+
112
+ Pod::UI.puts "🚀 Prebuild frameworks"
113
+
114
+ # Fetch original installer (which is running this pre-install hook) options,
115
+ # then pass them to our installer to perform update if needed
116
+ # Looks like this is the most appropriate way to figure out that something should be updated
117
+
118
+ update = nil
119
+ repo_update = nil
120
+
121
+ include ObjectSpace
122
+ ObjectSpace.each_object(Pod::Installer) { |installer|
123
+ update = installer.update
124
+ repo_update = installer.repo_update
125
+ }
126
+
127
+ # control features
128
+ Pod.is_prebuild_stage = true
129
+ Pod::Podfile::DSL.enable_prebuild_patch true # enable sikpping for prebuild targets
130
+ Pod::Installer.force_disable_integration true # don't integrate targets
131
+ Pod::Config.force_disable_write_lockfile true # disbale write lock file for perbuild podfile
132
+ Pod::Installer.disable_install_complete_message true # disable install complete message
133
+
134
+ Pod::Podfile::DSL.framework_source_all = Pod::Podfile::DSL.framework_source_all || Pod::Command::Install::all_use_source
135
+ Pod::UI.puts("全部使用源码") if Pod::Podfile::DSL.framework_source_all
136
+
137
+ # make another custom sandbox
138
+ standard_sandbox = installer_context.sandbox
139
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
140
+
141
+ # get the podfile for prebuild
142
+ prebuild_podfile = Pod::Podfile.from_ruby(podfile.defined_in_file)
143
+
144
+ # install
145
+ lockfile = installer_context.lockfile
146
+ binary_installer = Pod::Installer.new(prebuild_sandbox, prebuild_podfile, lockfile)
147
+
148
+ binary_installer.delete_all_standard_sandbox_pod(standard_sandbox)
149
+
150
+ if binary_installer.have_exact_prebuild_cache? && !update
151
+ binary_installer.install_when_cache_hit!
152
+ else
153
+ binary_installer.update = update
154
+ binary_installer.repo_update = repo_update
155
+ binary_installer.install!
156
+ end
157
+
158
+
159
+ # reset the environment
160
+ Pod.is_prebuild_stage = false
161
+ Pod::Installer.force_disable_integration false
162
+ Pod::Podfile::DSL.enable_prebuild_patch false
163
+ Pod::Config.force_disable_write_lockfile false
164
+ Pod::Installer.disable_install_complete_message false
165
+ Pod::UserInterface.warnings = [] # clean the warning in the prebuild step, it's duplicated.
166
+
167
+
168
+
169
+
170
+
171
+ # -- step 2: pod install ---
172
+ # install
173
+ Pod::UI.puts "\n"
174
+ Pod::UI.puts "🤖 Pod Install"
175
+ require_relative 'Integration'
176
+ # go on the normal install step ...
177
+ end
178
+