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