cocoapods-hd 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,130 @@
1
+ module Pod
2
+
3
+ class Prebuild
4
+ def self.keyword
5
+ :binary
6
+ end
7
+ end
8
+
9
+ class Podfile
10
+ class TargetDefinition
11
+
12
+ ## --- option for setting using prebuild framework ---
13
+ def parse_prebuild_framework(name, requirements)
14
+ should_prebuild = Pod::Podfile::DSL.is_all_binary
15
+
16
+ options = requirements.last
17
+ if options.is_a?(Hash) && options[Pod::Prebuild.keyword] != nil
18
+ should_prebuild = options.delete(Pod::Prebuild.keyword)
19
+ requirements.pop if options.empty?
20
+ end
21
+
22
+ pod_name = Specification.root_name(name)
23
+ set_prebuild_for_pod(pod_name, should_prebuild)
24
+ end
25
+
26
+ def set_prebuild_for_pod(pod_name, should_prebuild)
27
+
28
+ if should_prebuild == true
29
+ @prebuild_framework_pod_names ||= []
30
+ Pod::UI.puts "prebuild_framework_pod_names -------- :#{@prebuild_framework_pod_names}"
31
+ @prebuild_framework_pod_names.push pod_name
32
+ else
33
+ @should_not_prebuild_framework_pod_names ||= []
34
+ @should_not_prebuild_framework_pod_names.push pod_name
35
+ end
36
+ end
37
+
38
+ def prebuild_framework_pod_names
39
+ names = @prebuild_framework_pod_names || []
40
+ if parent != nil and parent.kind_of? TargetDefinition
41
+ names += parent.prebuild_framework_pod_names
42
+ end
43
+ names
44
+ end
45
+ def should_not_prebuild_framework_pod_names
46
+ names = @should_not_prebuild_framework_pod_names || []
47
+ if parent != nil and parent.kind_of? TargetDefinition
48
+ names += parent.should_not_prebuild_framework_pod_names
49
+ end
50
+ names
51
+ end
52
+
53
+ # ---- patch method ----
54
+ # We want modify `store_pod` method, but it's hard to insert a line in the
55
+ # implementation. So we patch a method called in `store_pod`.
56
+ # old_method = instance_method(:parse_inhibit_warnings)
57
+ #
58
+ # define_method(:parse_inhibit_warnings) do |name, requirements|
59
+ # parse_prebuild_framework(name, requirements)
60
+ # old_method.bind(self).(name, requirements)
61
+ # end
62
+
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ module Pod
69
+ class Installer
70
+
71
+ def prebuild_pod_targets
72
+ @prebuild_pod_targets ||= (
73
+ all = []
74
+
75
+ aggregate_targets = self.aggregate_targets
76
+ aggregate_targets.each do |aggregate_target|
77
+ target_definition = aggregate_target.target_definition
78
+ targets = aggregate_target.pod_targets || []
79
+
80
+ # filter prebuild
81
+ prebuild_names = target_definition.prebuild_framework_pod_names
82
+ if not Podfile::DSL.is_all_binary
83
+ targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) }
84
+ end
85
+ dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
86
+ targets = (targets + dependency_targets).uniq
87
+
88
+ # filter should not prebuild
89
+ explict_should_not_names = target_definition.should_not_prebuild_framework_pod_names
90
+ targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) }
91
+
92
+ all += targets
93
+ end
94
+
95
+ all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
96
+ all.uniq
97
+ )
98
+ end
99
+
100
+ # the root names who needs prebuild, including dependency pods.
101
+ def prebuild_pod_names
102
+ @prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
103
+ end
104
+
105
+
106
+ def validate_every_pod_only_have_one_form
107
+
108
+ multi_targets_pods = self.pod_targets.group_by do |t|
109
+ t.pod_name
110
+ end.select do |k, v|
111
+ v.map{|t| t.platform.name }.count > 1
112
+ end
113
+
114
+ multi_targets_pods = multi_targets_pods.reject do |name, targets|
115
+ contained = targets.map{|t| self.prebuild_pod_targets.include? t }
116
+ contained.uniq.count == 1 # all equal
117
+ end
118
+
119
+ return if multi_targets_pods.empty?
120
+
121
+ warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
122
+ warnings += multi_targets_pods.map{|name, targets| " #{name}: #{targets.map{|t|t.platform.name}}"}.join("\n")
123
+ raise Informative, warnings
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+
130
+
@@ -0,0 +1,73 @@
1
+ require_relative "names"
2
+
3
+ module Pod
4
+ class PrebuildSandbox < Sandbox
5
+
6
+ # [String] standard_sandbox_path
7
+ def self.from_standard_sanbox_path(path)
8
+ prebuild_sandbox_path = Pathname.new(path).realpath + "_Prebuild"
9
+ self.new(prebuild_sandbox_path)
10
+ end
11
+
12
+ def self.from_standard_sandbox(sandbox)
13
+ self.from_standard_sanbox_path(sandbox.root)
14
+ end
15
+
16
+ def standard_sanbox_path
17
+ self.root.parent
18
+ end
19
+
20
+ def generate_framework_path
21
+ self.root + "GeneratedFrameworks"
22
+ end
23
+
24
+ # @param name [String] pass the target.name (may containing platform suffix)
25
+ # @return [Pathname] the folder containing the framework file.
26
+ def framework_folder_path_for_target_name(name)
27
+ self.generate_framework_path + name
28
+ end
29
+
30
+ def exsited_framework_target_names
31
+ exsited_framework_name_pairs.map { |pair| pair[0] }.uniq
32
+ end
33
+
34
+ def exsited_framework_pod_names
35
+ exsited_framework_name_pairs.map { |pair| pair[1] }.uniq
36
+ end
37
+
38
+ def existed_target_names_for_pod_name(pod_name)
39
+ exsited_framework_name_pairs.select { |pair| pair[1] == pod_name }.map { |pair| pair[0] }
40
+ end
41
+
42
+ def save_pod_name_for_target(target)
43
+ folder = framework_folder_path_for_target_name(target.name)
44
+ return unless folder.exist?
45
+ # flag_file_path: /Users/xingyong/Desktop/debug-binary/HDTestKit/Example/Pods/_Prebuild/GeneratedFrameworks/SVProgressHUD/SVProgressHUD.pod_name
46
+ flag_file_path = folder + "#{target.pod_name}.pod_name"
47
+
48
+ File.write(flag_file_path.to_s, "")
49
+ end
50
+
51
+ private
52
+
53
+ def pod_name_for_target_folder(target_folder_path)
54
+ name = Pathname.new(target_folder_path).children.find do |child|
55
+ child.to_s.end_with? ".pod_name"
56
+ end
57
+ name = name.basename(".pod_name").to_s unless name.nil?
58
+ name ||= Pathname.new(target_folder_path).basename.to_s # for compatibility with older version
59
+ end
60
+
61
+ # Array<[target_name, pod_name]>
62
+ def exsited_framework_name_pairs
63
+ return [] unless generate_framework_path.exist?
64
+ generate_framework_path.children().map do |framework_path|
65
+ if framework_path.directory? && (not framework_path.children.empty?)
66
+ [framework_path.basename.to_s, pod_name_for_target_folder(framework_path)]
67
+ else
68
+ nil
69
+ end
70
+ end.reject(&:nil?).uniq
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+
2
+ module Pod
3
+ class Prebuild
4
+
5
+ # Check the targets, for the current limitation of the plugin
6
+ #
7
+ # @param [Array<PodTarget>] prebuilt_targets
8
+ def self.check_one_pod_should_have_only_one_target(prebuilt_targets)
9
+
10
+ targets_have_different_platforms = prebuilt_targets.select {|t| t.pod_name != t.name }
11
+
12
+ if targets_have_different_platforms.count > 0
13
+ names = targets_have_different_platforms.map(&:pod_name)
14
+ raw_names = targets_have_different_platforms.map(&:name)
15
+ message = "Oops, you came across a limitation of cocoapods-binary.
16
+
17
+ The plugin requires that one pod should have ONLY ONE target in the 'Pod.xcodeproj'. There are mainly 2 situations \
18
+ causing this problem:
19
+
20
+ 1. One pod integrates in 2 or more different platforms' targets. e.g.
21
+ ```
22
+ target 'iphoneApp' do
23
+ pod 'A', :binary => true
24
+ end
25
+ target 'watchApp' do
26
+ pod 'A'
27
+ end
28
+ ```
29
+
30
+ 2. Use different subspecs in multiple targets. e.g.
31
+ ```
32
+ target 'iphoneApp' do
33
+ pod 'A/core'
34
+ pod 'A/network'
35
+ end
36
+ target 'iphoneAppTest' do
37
+ pod 'A/core'
38
+ end
39
+ ```
40
+
41
+ Related pods: #{names}, target names: #{raw_names}
42
+ "
43
+ raise Informative, message
44
+ end
45
+ end
46
+
47
+
48
+ end
49
+ end
@@ -0,0 +1,226 @@
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 hd_all_binary!
12
+ DSL.is_all_binary = true
13
+ end
14
+
15
+ def hd_use_source_pods(pods)
16
+ DSL.source_pods = Array(pods)
17
+ end
18
+
19
+ # Enable bitcode for prebuilt frameworks
20
+ def enable_bitcode_for_prebuilt_frameworks!
21
+ DSL.bitcode_enabled = true
22
+ end
23
+
24
+ # Don't remove source code of prebuilt pods
25
+ # It may speed up the pod install if git didn't
26
+ # include the `Pods` folder
27
+ def keep_source_code_for_prebuilt_frameworks!
28
+ DSL.dont_remove_source_code = 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
+
64
+ # 是否全部二进库
65
+ class_attr_accessor :is_all_binary
66
+ is_all_binary = false
67
+
68
+ class_attr_accessor :bitcode_enabled
69
+ bitcode_enabled = false
70
+
71
+ class_attr_accessor :dont_remove_source_code
72
+ dont_remove_source_code = false
73
+
74
+ class_attr_accessor :custom_build_options
75
+ class_attr_accessor :custom_build_options_simulator
76
+ self.custom_build_options = []
77
+ self.custom_build_options_simulator = []
78
+
79
+ # 用户指定源码集合
80
+ class_attr_accessor :source_pods
81
+ source_pods = []
82
+
83
+ end
84
+ end
85
+ end
86
+
87
+ def run_pod_install
88
+ podfile = Pathname.new('Podfile')
89
+ if !podfile.exist?
90
+ STDERR.puts "[!] Podfile file did not exist".red
91
+ exit
92
+ end
93
+ argvs = []
94
+ gen = Pod::Command::Install.new(CLAide::ARGV.new(argvs))
95
+ gen.validate!
96
+ gen.run
97
+ end
98
+
99
+ # Pod::HooksManager.register('cocoapods-hd', :post_install) do |installer_context|
100
+ #
101
+ # Pod::UI.puts "cocoapods-hd: post_install"
102
+ # if Pod.is_ignore_hook_install == nil || Pod.is_ignore_hook_install == true
103
+ # Pod::UI.puts "cocoapods-hd: hook post_install"
104
+ # next
105
+ # end
106
+ # # installer_context.pods_project -> Xcodeproj::Project
107
+ # installer_context.pods_project.targets.each do |target|
108
+ # target.build_configurations.each do |config|
109
+ # if config.name == 'Release'
110
+ # config.build_settings['ARCHS'] = "$(ARCHS_STANDARD)"
111
+ # end
112
+ # end
113
+ # end
114
+ # installer_context.pods_project.save
115
+ # Pod::UI.puts "cocoapods-hd: set build configurations"
116
+ # end
117
+ #
118
+ Pod::HooksManager.register('cocoapods-hd', :pre_install) do |installer_context|
119
+
120
+ require_relative 'helper/feature_switches'
121
+ require_relative 'resolver'
122
+
123
+ Pod::UI.puts "cocoapods-hd: pre_install"
124
+
125
+ if !Pod.is_prebuild_stage
126
+ Pod::UI.puts "cocoapods-hd: update repo"
127
+
128
+ sources_manager = Pod::Config.instance.sources_manager
129
+ argvs = [sources_manager.binary_source.name]
130
+ repo_update = Pod::Command::Repo::Update.new(CLAide::ARGV.new(argvs))
131
+ repo_update.validate!
132
+ repo_update.run
133
+ end
134
+
135
+ if Pod.is_ignore_hook_install == nil || Pod.is_ignore_hook_install == true
136
+ Pod::UI.puts "cocoapods-hd: hook pre_install"
137
+ next
138
+ end
139
+
140
+ if Pod.is_prebuild_stage
141
+ next
142
+ end
143
+
144
+ # [Check Environment]
145
+ # check user_framework is on
146
+ podfile = installer_context.podfile
147
+ podfile.target_definition_list.each do |target_definition|
148
+
149
+ next if target_definition.prebuild_framework_pod_names.empty?
150
+ if not target_definition.uses_frameworks?
151
+ STDERR.puts "[!] Cocoapods-hd requires `use_frameworks!`".red
152
+ exit
153
+ end
154
+ end
155
+
156
+ # -- step 1: prebuild framework ---
157
+ # Execute a sperated pod install, to generate targets for building framework,
158
+ # then compile them to framework files.
159
+ require_relative 'helper/prebuild_sandbox'
160
+ require_relative 'prebuild'
161
+
162
+ Pod::UI.puts "️🍎 Prebuild frameworks"
163
+
164
+ # Fetch original installer (which is running this pre-install hook) options,
165
+ # then pass them to our installer to perform update if needed
166
+ # Looks like this is the most appropriate way to figure out that something should be updated
167
+
168
+ update = nil
169
+ repo_update = nil
170
+
171
+ include ObjectSpace
172
+ ObjectSpace.each_object(Pod::Installer) { |installer|
173
+ update = installer.update
174
+ repo_update = installer.repo_update
175
+ }
176
+
177
+ # control features
178
+ Pod.is_prebuild_stage = true
179
+ Pod::Podfile::DSL.enable_prebuild_patch true # enable sikpping for prebuild targets
180
+ Pod::Installer.force_disable_integration true # don't integrate targets
181
+ Pod::Config.force_disable_write_lockfile true # disbale write lock file for perbuild podfile
182
+ Pod::Installer.disable_install_complete_message true # disable install complete message
183
+
184
+ # make another custom sandbox
185
+ standard_sandbox = installer_context.sandbox
186
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
187
+
188
+ # get the podfile for prebuild
189
+ prebuild_podfile = Pod::Podfile.from_ruby(podfile.defined_in_file)
190
+ prebuild_podfile.use_frameworks!(:linkage => :static)
191
+ # Pod::UI.puts "prebuild_podfile --------- : #{prebuild_podfile}"
192
+
193
+ # install
194
+ lockfile = installer_context.lockfile
195
+ # Pod::UI.puts "lockfile --------- : #{lockfile}"
196
+
197
+ binary_installer = Pod::Installer.new(prebuild_sandbox, prebuild_podfile, lockfile)
198
+ # Pod::UI.puts "binary_installer --------- : #{binary_installer}"
199
+
200
+ binary_installer.have_exact_prebuild_cache?
201
+ binary_installer.install!
202
+
203
+ # if binary_installer.have_exact_prebuild_cache? && !update
204
+ # binary_installer.install_when_cache_hit!
205
+ # else
206
+ # binary_installer.update = update
207
+ # binary_installer.repo_update = repo_update
208
+ # binary_installer.install!
209
+ # end
210
+
211
+ # reset the environment
212
+ Pod.is_prebuild_stage = false
213
+ Pod::Installer.force_disable_integration false
214
+ Pod::Podfile::DSL.enable_prebuild_patch false
215
+ Pod::Config.force_disable_write_lockfile false
216
+ Pod::Installer.disable_install_complete_message false
217
+ Pod::UserInterface.warnings = [] # clean the warning in the prebuild step, it's duplicated.
218
+
219
+ # -- step 2: pod install ---
220
+ # install
221
+ Pod::UI.puts "\n"
222
+ Pod::UI.puts "🍓 Pod Install"
223
+ require_relative 'Integration'
224
+ # go on the normal install step ...
225
+ end
226
+