cocoapods-util 0.0.16 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cocoapods-util/binary/Intergation.rb +300 -0
- data/lib/cocoapods-util/binary/config.rb +36 -7
- data/lib/cocoapods-util/binary/helper/names.rb +78 -0
- data/lib/cocoapods-util/binary/helper/podfile_options.rb +120 -0
- data/lib/cocoapods-util/binary/helper/target_checker.rb +49 -0
- data/lib/cocoapods-util/binary/hooks/CocoapodsUtilHook.rb +3 -2
- data/lib/cocoapods-util/binary/hooks/pre_install.rb +10 -9
- data/lib/cocoapods-util/binary/podfile_dsl.rb +3 -20
- data/lib/cocoapods-util/binary/prebuild.rb +63 -0
- data/lib/cocoapods-util/binary/targets/pod_target.rb +29 -1
- data/lib/cocoapods-util/command/xcframework/xcframework.rb +2 -6
- data/lib/cocoapods-util/command/xcframework/xcframework_build.rb +13 -29
- data/lib/cocoapods-util/gem_version.rb +1 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 656f35fa8c5fb7c2994fb8b454f010a9c3166b2b3a56ad75b9ccdfba7768829b
|
4
|
+
data.tar.gz: 33ff55946a88e29bfaaa0a0112af003702e0e33cee42449af79284fcaa8ebe90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed695aae86dc40ab0a1661e4aefbe61c363a2c89eb15b401d238e489570c3a15f048f7e3422060ceff1b2159e5a9c1c07f777e50fc1d324bece09fddbe32234c
|
7
|
+
data.tar.gz: b51419985404992c9ddaaa707240c2ce0b61f2fce48cdb98f160e2f71148f1303be14d9b4c1c03b04f103928fef2598234489be674e375aa553fd11543a17ded
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require_relative 'helper/podfile_options'
|
2
|
+
require_relative 'helper/names'
|
3
|
+
require_relative 'helper/target_checker'
|
4
|
+
|
5
|
+
|
6
|
+
# NOTE:
|
7
|
+
# This file will only be loaded on normal pod install step
|
8
|
+
# so there's no need to check is_prebuild_stage
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
# Provide a special "download" process for prebuilded pods.
|
13
|
+
#
|
14
|
+
# As the frameworks is already exsited in local folder. We
|
15
|
+
# just create a symlink to the original target folder.
|
16
|
+
#
|
17
|
+
module Pod
|
18
|
+
class Installer
|
19
|
+
class PodSourceInstaller
|
20
|
+
|
21
|
+
def install_for_prebuild!(standard_sanbox)
|
22
|
+
prebuild_sandbox = BinaryPrebuild::Sandbox.from_sandbox(standard_sanbox)
|
23
|
+
return if prebuild_sandbox.nil?
|
24
|
+
target_names = prebuild_sandbox.existed_target_names(self.name)
|
25
|
+
|
26
|
+
def walk(path, &action)
|
27
|
+
return unless path.exist?
|
28
|
+
path.children.each do |child|
|
29
|
+
result = action.call(child, &action)
|
30
|
+
if child.directory?
|
31
|
+
walk(child, &action) if result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
def make_link(source, target)
|
36
|
+
source = Pathname.new(source)
|
37
|
+
target = Pathname.new(target)
|
38
|
+
target.parent.mkpath unless target.parent.exist?
|
39
|
+
relative_source = source.relative_path_from(target.parent)
|
40
|
+
FileUtils.ln_sf(relative_source, target)
|
41
|
+
end
|
42
|
+
def mirror_with_symlink(source, basefolder, target_folder)
|
43
|
+
relative_path = source.relative_path_from(basefolder)
|
44
|
+
if relative_path.to_s =~ /^(Debug|Release)\/.*/
|
45
|
+
new_relative_path = relative_path.to_s.gsub!(/^(Debug|Release)/) { |match| "#{BinaryPrebuild.config.xcconfig_replace_path}-#{match}" }
|
46
|
+
target = Pathname.new("#{target_folder}/#{new_relative_path}")
|
47
|
+
make_link(source, target)
|
48
|
+
else
|
49
|
+
target = Pathname.new("#{target_folder}/#{relative_path}")
|
50
|
+
make_link(source, target)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
target_names.each do |name|
|
55
|
+
|
56
|
+
# symbol link copy all substructure
|
57
|
+
real_file_folder = prebuild_sandbox.framework_folder_path_for_target_name(name)
|
58
|
+
|
59
|
+
# If have only one platform, just place int the root folder of this pod.
|
60
|
+
# If have multiple paths, we use a sperated folder to store different
|
61
|
+
# platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework
|
62
|
+
|
63
|
+
target_folder = standard_sanbox.pod_dir(self.name) + "_Prebuild"
|
64
|
+
target_folder.rmtree if target_folder.exist?
|
65
|
+
target_folder.mkpath
|
66
|
+
|
67
|
+
|
68
|
+
walk(real_file_folder) do |child|
|
69
|
+
source = child
|
70
|
+
# only make symlink to file and `.framework` folder
|
71
|
+
if child.directory? and [".framework", ".xcframework", ".bundle", ".dSYM"].include? child.extname
|
72
|
+
mirror_with_symlink(source, real_file_folder, target_folder)
|
73
|
+
next false # return false means don't go deeper
|
74
|
+
elsif child.file?
|
75
|
+
mirror_with_symlink(source, real_file_folder, target_folder)
|
76
|
+
next true
|
77
|
+
else
|
78
|
+
next true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end # of for each
|
82
|
+
|
83
|
+
end # of method
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Let cocoapods use the prebuild framework files in install process.
|
91
|
+
#
|
92
|
+
# the code only effect the second pod install process.
|
93
|
+
#
|
94
|
+
module Pod
|
95
|
+
class Installer
|
96
|
+
# Modify specification to use only the prebuild framework after analyzing
|
97
|
+
old_method2 = instance_method(:resolve_dependencies)
|
98
|
+
define_method(:resolve_dependencies) do
|
99
|
+
# call original
|
100
|
+
old_method2.bind(self).()
|
101
|
+
# ...
|
102
|
+
# ...
|
103
|
+
# ...
|
104
|
+
# after finishing the very complex orginal function
|
105
|
+
|
106
|
+
# check the pods
|
107
|
+
# Although we have did it in prebuild stage, it's not sufficient.
|
108
|
+
# Same pod may appear in another target in form of source code.
|
109
|
+
# Prebuild.check_one_pod_should_have_only_one_target(self.prebuild_pod_targets)
|
110
|
+
# self.validate_every_pod_only_have_one_form
|
111
|
+
|
112
|
+
# prepare
|
113
|
+
cache = []
|
114
|
+
|
115
|
+
def add_vendered_framework(spec, platform, added_framework_file_path)
|
116
|
+
if spec.attributes_hash[platform] == nil
|
117
|
+
spec.attributes_hash[platform] = {}
|
118
|
+
end
|
119
|
+
vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
|
120
|
+
vendored_frameworks = [vendored_frameworks] if vendored_frameworks.kind_of?(String)
|
121
|
+
vendored_frameworks += [added_framework_file_path]
|
122
|
+
spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
|
123
|
+
end
|
124
|
+
def empty_source_files(spec)
|
125
|
+
spec.attributes_hash["source_files"] = []
|
126
|
+
spec.attributes_hash["public_header_files"] = []
|
127
|
+
spec.attributes_hash["private_header_files"] = []
|
128
|
+
["ios", "watchos", "tvos", "osx"].each do |plat|
|
129
|
+
if spec.attributes_hash[plat] != nil
|
130
|
+
spec.attributes_hash[plat]["source_files"] = []
|
131
|
+
spec.attributes_hash[plat]["public_header_files"] = []
|
132
|
+
spec.attributes_hash[plat]["private_header_files"] = []
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
prebuild_sandbox = BinaryPrebuild::Sandbox.from_sandbox(self.sandbox)
|
138
|
+
return if prebuild_sandbox.nil?
|
139
|
+
|
140
|
+
specs = self.analysis_result.specifications
|
141
|
+
prebuilt_specs = (specs.select do |spec|
|
142
|
+
# rmtree
|
143
|
+
target_prebuild_files = self.sandbox.root + spec.root.name + "_Prebuild"
|
144
|
+
target_prebuild_files.rmtree if target_prebuild_files.exist?
|
145
|
+
|
146
|
+
self.prebuild_pod_names.include? spec.root.name
|
147
|
+
end)
|
148
|
+
|
149
|
+
prebuilt_specs.each do |spec|
|
150
|
+
|
151
|
+
# Use the prebuild framworks as vendered frameworks
|
152
|
+
# get_corresponding_targets
|
153
|
+
targets = Pod.fast_get_targets_for_pod_name(spec.root.name, self.pod_targets, cache)
|
154
|
+
targets.each do |target|
|
155
|
+
# the framework_file_path rule is decided when `install_for_prebuild`,
|
156
|
+
# as to compitable with older version and be less wordy.
|
157
|
+
prebuild_sandbox.prebuild_vendored_frameworks(spec.root.name).each do |frame_file_path|
|
158
|
+
framework_file_path = "_Prebuild/" + frame_file_path
|
159
|
+
add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
# Clean the source files
|
163
|
+
# we just add the prebuilt framework to specific platform and set no source files
|
164
|
+
# for all platform, so it doesn't support the sence that 'a pod perbuild for one
|
165
|
+
# platform and not for another platform.'
|
166
|
+
empty_source_files(spec)
|
167
|
+
|
168
|
+
# to remove the resurce bundle target.
|
169
|
+
# When specify the "resource_bundles" in podspec, xcode will generate a bundle
|
170
|
+
# target after pod install. But the bundle have already built when the prebuit
|
171
|
+
# phase and saved in the framework folder. We will treat it as a normal resource
|
172
|
+
# file.
|
173
|
+
# https://github.com/leavez/cocoapods-binary/issues/29
|
174
|
+
if spec.attributes_hash["resource_bundles"]
|
175
|
+
# bundle_names = spec.attributes_hash["resource_bundles"].keys
|
176
|
+
spec.attributes_hash["resource_bundles"] = nil
|
177
|
+
spec.attributes_hash["resources"] ||= []
|
178
|
+
resources = spec.attributes_hash["resources"] || []
|
179
|
+
resources = [resources] if resources.kind_of?(String)
|
180
|
+
spec.attributes_hash["resources"] = resources
|
181
|
+
# spec.attributes_hash["resources"] += bundle_names.map{|n| n+".bundle"}
|
182
|
+
prebuild_bundles = prebuild_sandbox.prebuild_bundles(spec.root.name).each.map do |bundle_path|
|
183
|
+
"_Prebuild/" + bundle_path
|
184
|
+
end
|
185
|
+
spec.attributes_hash["resources"] += prebuild_bundles
|
186
|
+
end
|
187
|
+
|
188
|
+
# to avoid the warning of missing license
|
189
|
+
spec.attributes_hash["license"] = {}
|
190
|
+
spec.attributes_hash["preserve_paths"] = "**/*"
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
# Override the download step to skip download and prepare file in target folder
|
198
|
+
old_method = instance_method(:install_source_of_pod)
|
199
|
+
define_method(:install_source_of_pod) do |pod_name|
|
200
|
+
|
201
|
+
# copy from original
|
202
|
+
pod_installer = create_pod_installer(pod_name)
|
203
|
+
# \copy from original
|
204
|
+
|
205
|
+
# copy from original
|
206
|
+
pod_installer.install!
|
207
|
+
# \copy from original
|
208
|
+
|
209
|
+
if self.prebuild_pod_names.include? pod_name
|
210
|
+
pod_installer.install_for_prebuild!(self.sandbox)
|
211
|
+
end
|
212
|
+
|
213
|
+
# copy from original
|
214
|
+
@installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
|
215
|
+
# \copy from original
|
216
|
+
end
|
217
|
+
|
218
|
+
alias_method :old_create_pod_installer, :create_pod_installer
|
219
|
+
def create_pod_installer(pod_name)
|
220
|
+
pod_installer = old_create_pod_installer(pod_name)
|
221
|
+
|
222
|
+
pods_to_install = sandbox_state.added | sandbox_state.changed
|
223
|
+
unless pods_to_install.include?(pod_name)
|
224
|
+
pod_installer.install_for_prebuild!(self.sandbox) if self.prebuild_pod_names.include? pod_name
|
225
|
+
end
|
226
|
+
pod_installer
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# A fix in embeded frameworks script.
|
232
|
+
#
|
233
|
+
# The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
|
234
|
+
# to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
|
235
|
+
# we override the `readlink` to a fixed version.
|
236
|
+
#
|
237
|
+
module Pod
|
238
|
+
module Generator
|
239
|
+
class EmbedFrameworksScript
|
240
|
+
|
241
|
+
old_method = instance_method(:script)
|
242
|
+
define_method(:script) do
|
243
|
+
|
244
|
+
script = old_method.bind(self).()
|
245
|
+
patch = <<-SH.strip_heredoc
|
246
|
+
#!/bin/sh
|
247
|
+
|
248
|
+
# ---- this is added by cocoapods-binary ---
|
249
|
+
# Readlink cannot handle relative symlink well, so we override it to a new one
|
250
|
+
# If the path isn't an absolute path, we add a realtive prefix.
|
251
|
+
old_read_link=`which readlink`
|
252
|
+
readlink () {
|
253
|
+
path=`$old_read_link "$1"`;
|
254
|
+
if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
|
255
|
+
echo $path;
|
256
|
+
else
|
257
|
+
echo "`dirname $1`/$path";
|
258
|
+
fi
|
259
|
+
}
|
260
|
+
# ---
|
261
|
+
SH
|
262
|
+
|
263
|
+
# patch the rsync for copy dSYM symlink
|
264
|
+
script = script.gsub "rsync --delete", "rsync --copy-links --delete"
|
265
|
+
|
266
|
+
patch + script
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
module Pod
|
273
|
+
module Generator
|
274
|
+
class CopyXCFrameworksScript
|
275
|
+
|
276
|
+
alias_method :old_install_xcframework_args, :install_xcframework_args
|
277
|
+
def install_xcframework_args(xcframework, slices)
|
278
|
+
args = old_install_xcframework_args(xcframework, slices)
|
279
|
+
xcconfig_replace_path = BinaryPrebuild.config.xcconfig_replace_path
|
280
|
+
args.gsub!(/#{xcconfig_replace_path}-(Debug|Release)/, "#{xcconfig_replace_path}-${CONFIGURATION}")
|
281
|
+
args
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
module Pod
|
288
|
+
module Generator
|
289
|
+
class CopyResourcesScript
|
290
|
+
|
291
|
+
alias_method :old_script, :script
|
292
|
+
def script
|
293
|
+
script = old_script
|
294
|
+
xcconfig_replace_path = BinaryPrebuild.config.xcconfig_replace_path
|
295
|
+
script.gsub!(/#{xcconfig_replace_path}-(Debug|Release)/, "#{xcconfig_replace_path}-${CONFIGURATION}")
|
296
|
+
script
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
@@ -4,20 +4,49 @@ module BinaryPrebuild
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class Config
|
7
|
-
attr_accessor :
|
8
|
-
|
7
|
+
attr_accessor :dsl_config
|
8
|
+
|
9
|
+
APPLICABLE_DSL_CONFIG = [
|
10
|
+
:all_binary,
|
11
|
+
:binary_dir,
|
12
|
+
:dev_pods_enabled,
|
13
|
+
:xcconfig_replace_path,
|
14
|
+
].freeze
|
15
|
+
|
9
16
|
def initialize()
|
10
|
-
@
|
11
|
-
@enable_targets = []
|
17
|
+
@dsl_config = {}
|
12
18
|
end
|
13
19
|
|
14
20
|
def self.instance
|
15
21
|
@instance ||= new()
|
16
22
|
end
|
17
23
|
|
18
|
-
def
|
19
|
-
@
|
20
|
-
|
24
|
+
def validate_dsl_config
|
25
|
+
inapplicable_options = @dsl_config.keys - APPLICABLE_DSL_CONFIG
|
26
|
+
return if inapplicable_options.empty?
|
27
|
+
|
28
|
+
message = <<~HEREDOC
|
29
|
+
[WARNING] The following options (in `config_cocoapods_util`) are not correct: #{inapplicable_options}.
|
30
|
+
Available options: #{APPLICABLE_DSL_CONFIG}.
|
31
|
+
HEREDOC
|
32
|
+
|
33
|
+
Pod::UI.puts message.yellow
|
34
|
+
end
|
35
|
+
|
36
|
+
def all_binary_enable?
|
37
|
+
@dsl_config[:all_binary] || false
|
38
|
+
end
|
39
|
+
|
40
|
+
def dev_pods_enabled?
|
41
|
+
@dsl_config[:dev_pods_enabled] || false
|
42
|
+
end
|
43
|
+
|
44
|
+
def binary_dir
|
45
|
+
@dsl_config[:binary_dir] || '_Prebuild'
|
46
|
+
end
|
47
|
+
|
48
|
+
def xcconfig_replace_path
|
49
|
+
@dsl_config[:xcconfig_replace_path] || "cocoapods-util-binary"
|
21
50
|
end
|
22
51
|
end
|
23
52
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# ABOUT NAMES
|
2
|
+
#
|
3
|
+
# There are many kinds of name in cocoapods. Two main names are widely used in this plugin.
|
4
|
+
# - root_spec.name (spec.root_name, targe.pod_name):
|
5
|
+
# aka "pod_name"
|
6
|
+
# the name we use in podfile. the concept.
|
7
|
+
#
|
8
|
+
# - target.name:
|
9
|
+
# aka "target_name"
|
10
|
+
# the name of the final target in xcode project. the final real thing.
|
11
|
+
#
|
12
|
+
# One pod may have multiple targets in xcode project, due to one pod can be used in mutiple
|
13
|
+
# platform simultaneously. So one `root_spec.name` may have multiple coresponding `target.name`s.
|
14
|
+
# Therefore, map a spec to/from targets is a little complecated. It's one to many.
|
15
|
+
#
|
16
|
+
|
17
|
+
# Tool to transform Pod_name to target efficiently
|
18
|
+
module Pod
|
19
|
+
def self.fast_get_targets_for_pod_name(pod_name, targets, cache)
|
20
|
+
pod_name_to_targets_hash = nil
|
21
|
+
if cache.empty?
|
22
|
+
pod_name_to_targets_hash = targets.reduce({}) do |sum, target|
|
23
|
+
array = sum[target.pod_name] || []
|
24
|
+
array << target
|
25
|
+
sum[target.pod_name] = array
|
26
|
+
sum
|
27
|
+
end
|
28
|
+
cache << pod_name_to_targets_hash
|
29
|
+
else
|
30
|
+
pod_name_to_targets_hash = cache.first
|
31
|
+
end
|
32
|
+
|
33
|
+
pod_name_to_targets_hash[pod_name] || []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
# Target:
|
43
|
+
|
44
|
+
# def pod_name
|
45
|
+
# root_spec.name
|
46
|
+
# end
|
47
|
+
|
48
|
+
# def name
|
49
|
+
# pod_name + #{scope_suffix}
|
50
|
+
# end
|
51
|
+
|
52
|
+
# def product_module_name
|
53
|
+
# root_spec.module_name
|
54
|
+
# end
|
55
|
+
|
56
|
+
# def framework_name
|
57
|
+
# "#{product_module_name}.framework"
|
58
|
+
# end
|
59
|
+
|
60
|
+
# def product_name
|
61
|
+
# if requires_frameworks?
|
62
|
+
# framework_name
|
63
|
+
# else
|
64
|
+
# static_library_name
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
|
68
|
+
# def product_basename
|
69
|
+
# if requires_frameworks?
|
70
|
+
# product_module_name
|
71
|
+
# else
|
72
|
+
# label
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
|
76
|
+
# def framework_name
|
77
|
+
# "#{product_module_name}.framework"
|
78
|
+
# end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
|
2
|
+
module Pod
|
3
|
+
class Podfile
|
4
|
+
class TargetDefinition
|
5
|
+
def detect_prebuilt_pod(name, requirements)
|
6
|
+
options = requirements.last || {}
|
7
|
+
|
8
|
+
# prebuild
|
9
|
+
@explicit_prebuild_pod_names ||= []
|
10
|
+
@reject_prebuild_pod_names ||= []
|
11
|
+
@explicit_prebuild_pod_names << Specification.root_name(name) if options.is_a?(Hash) && options[:binary]
|
12
|
+
@reject_prebuild_pod_names << Specification.root_name(name) if options.is_a?(Hash) && options.include?(:binary) && !options[:binary]
|
13
|
+
|
14
|
+
# header search path
|
15
|
+
@explicit_header_search_pod_names ||= []
|
16
|
+
@reject_header_search_pod_names ||= []
|
17
|
+
@explicit_header_search_pod_names << Specification.root_name(name) if options.is_a?(Hash) && options[:framework_search_header]
|
18
|
+
@reject_header_search_pod_names << Specification.root_name(name) if options.is_a?(Hash) && options.include?(:framework_search_header) && !options[:framework_search_header]
|
19
|
+
|
20
|
+
options.delete(:binary) if options.is_a?(Hash)
|
21
|
+
options.delete(:framework_search_header) if options.is_a?(Hash)
|
22
|
+
requirements.pop if options.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the names of pod targets explicitly declared as prebuilt in Podfile using `:binary => true`.
|
26
|
+
def explicit_prebuild_pod_names
|
27
|
+
names = @explicit_prebuild_pod_names || []
|
28
|
+
names += parent.explicit_prebuild_pod_names if !parent.nil? && parent.is_a?(TargetDefinition)
|
29
|
+
names
|
30
|
+
end
|
31
|
+
|
32
|
+
def reject_prebuild_pod_names
|
33
|
+
names = @reject_prebuild_pod_names || []
|
34
|
+
names += parent.reject_prebuild_pod_names if !parent.nil? && parent.is_a?(TargetDefinition)
|
35
|
+
names
|
36
|
+
end
|
37
|
+
|
38
|
+
def explicit_header_search_pod_names
|
39
|
+
names = @explicit_header_search_pod_names || []
|
40
|
+
names += parent.explicit_header_search_pod_names if !parent.nil? && parent.is_a?(TargetDefinition)
|
41
|
+
names
|
42
|
+
end
|
43
|
+
|
44
|
+
def reject_header_search_pod_names
|
45
|
+
names = @reject_header_search_pod_names || []
|
46
|
+
names += parent.reject_header_search_pod_names if !parent.nil? && parent.is_a?(TargetDefinition)
|
47
|
+
names
|
48
|
+
end
|
49
|
+
|
50
|
+
# ---- patch method ----
|
51
|
+
# We want modify `store_pod` method, but it's hard to insert a line in the
|
52
|
+
# implementation. So we patch a method called in `store_pod`.
|
53
|
+
original_parse_inhibit_warnings = instance_method(:parse_inhibit_warnings)
|
54
|
+
define_method(:parse_inhibit_warnings) do |name, requirements|
|
55
|
+
detect_prebuilt_pod(name, requirements)
|
56
|
+
original_parse_inhibit_warnings.bind(self).call(name, requirements)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Pod
|
63
|
+
class Installer
|
64
|
+
# Returns the names of pod targets detected as prebuilt, including
|
65
|
+
# those declared in Podfile and their dependencies
|
66
|
+
def prebuild_pod_names
|
67
|
+
prebuilt_pod_targets.map(&:name).to_set
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the pod targets detected as prebuilt, including
|
71
|
+
# those declared in Podfile and their dependencies
|
72
|
+
def prebuilt_pod_targets
|
73
|
+
@prebuilt_pod_targets ||= begin
|
74
|
+
explicit_prebuild_pod_names = aggregate_targets.flat_map { |target|
|
75
|
+
target.target_definition.explicit_prebuild_pod_names
|
76
|
+
}.uniq
|
77
|
+
|
78
|
+
reject_prebuild_pod_names = aggregate_targets.flat_map { |target|
|
79
|
+
target.target_definition.reject_prebuild_pod_names
|
80
|
+
}.uniq
|
81
|
+
|
82
|
+
available_pod_names = []
|
83
|
+
prebuild_sandbox = BinaryPrebuild::Sandbox.from_sandbox(self.sandbox)
|
84
|
+
available_pod_names = prebuild_sandbox.target_paths.map {|path| path.basename.to_s } unless prebuild_sandbox.nil?
|
85
|
+
if BinaryPrebuild.config.all_binary_enable?
|
86
|
+
explicit_prebuild_pod_names = available_pod_names
|
87
|
+
else
|
88
|
+
explicit_prebuild_pod_names = (explicit_prebuild_pod_names & available_pod_names).uniq
|
89
|
+
end
|
90
|
+
explicit_prebuild_pod_names -= reject_prebuild_pod_names
|
91
|
+
|
92
|
+
targets = pod_targets.select { |target|
|
93
|
+
explicit_prebuild_pod_names.include?(target.pod_name)
|
94
|
+
}
|
95
|
+
targets = targets.reject { |target| sandbox.local?(target.pod_name) } unless BinaryPrebuild.config.dev_pods_enabled?
|
96
|
+
targets.map { |target| target.use_binary = true }
|
97
|
+
targets
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module Pod
|
104
|
+
class Target
|
105
|
+
attr_accessor :use_binary
|
106
|
+
|
107
|
+
def frame_header_search_paths_enable?
|
108
|
+
return true if self.use_binary
|
109
|
+
header_search_pod_names.include? self.name
|
110
|
+
end
|
111
|
+
|
112
|
+
def header_search_pod_names
|
113
|
+
@explicit_header_search_pod_names ||= begin
|
114
|
+
target_definitions.flat_map { |target_definition|
|
115
|
+
target_definition.explicit_header_search_pod_names - target_definition.reject_header_search_pod_names
|
116
|
+
}.uniq
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
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
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require_relative '
|
2
|
-
require_relative 'post_install'
|
1
|
+
require_relative '../helper/podfile_options'
|
3
2
|
|
4
3
|
module CocoapodsUtilHook
|
5
4
|
Pod::HooksManager.register('cocoapods-util', :pre_install) do |installer_context, _|
|
5
|
+
require_relative 'pre_install'
|
6
6
|
BinaryPrebuild::PreInstall.new(installer_context).run
|
7
7
|
end
|
8
8
|
|
@@ -11,6 +11,7 @@ module CocoapodsUtilHook
|
|
11
11
|
end
|
12
12
|
|
13
13
|
Pod::HooksManager.register('cocoapods-util', :post_install) do |context, _|
|
14
|
+
require_relative 'post_install'
|
14
15
|
BinaryPrebuild::PostInstall.new(context).run
|
15
16
|
end
|
16
17
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative '../targets/pod_target'
|
2
|
-
|
3
1
|
module BinaryPrebuild
|
4
2
|
class PreInstall
|
5
3
|
def initialize(installer_context)
|
@@ -8,13 +6,16 @@ module BinaryPrebuild
|
|
8
6
|
|
9
7
|
def run
|
10
8
|
# [Check Environment]
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
podfile = @installer_context.podfile
|
10
|
+
podfile.target_definition_list.each do |target_definition|
|
11
|
+
if not target_definition.uses_frameworks?
|
12
|
+
STDERR.puts "[!] Cocoapods-binary requires `use_frameworks!`".red
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative '../targets/pod_target'
|
18
|
+
require_relative '../Intergation'
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -1,26 +1,9 @@
|
|
1
1
|
module Pod
|
2
2
|
class Podfile
|
3
3
|
module DSL
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def enable_all_framework_header!(enable: true)
|
9
|
-
BinaryPrebuild.config.enable_all = enable
|
10
|
-
end
|
11
|
-
|
12
|
-
# hook
|
13
|
-
old_method = instance_method(:pod)
|
14
|
-
define_method(:pod) do |name, *args|
|
15
|
-
enable = BinaryPrebuild.config.enable_all
|
16
|
-
options = args.last
|
17
|
-
keyword = DSL.enable_framework_header_keyword
|
18
|
-
if options.is_a?(Hash) && options[keyword] != nil
|
19
|
-
enable = options.delete(keyword)
|
20
|
-
args.pop if options.empty?
|
21
|
-
end
|
22
|
-
BinaryPrebuild.config.add_enable_target name.to_s.gsub(/\/.*$/, '') if enable
|
23
|
-
old_method.bind(self).(name, *args)
|
4
|
+
def config_cocoapods_util(options)
|
5
|
+
BinaryPrebuild.config.dsl_config = options
|
6
|
+
BinaryPrebuild.config.validate_dsl_config
|
24
7
|
end
|
25
8
|
end
|
26
9
|
end
|
@@ -1,3 +1,66 @@
|
|
1
1
|
module BinaryPrebuild
|
2
|
+
class Sandbox
|
3
|
+
def initialize(path)
|
4
|
+
@sandbox_path = path
|
5
|
+
end
|
2
6
|
|
7
|
+
def self.from_sandbox(sandbox)
|
8
|
+
root = sandbox.root
|
9
|
+
search_path = BinaryPrebuild.config.binary_dir
|
10
|
+
if !search_path.nil? && !search_path.empty?
|
11
|
+
path = File.expand_path(root + search_path)
|
12
|
+
if File.exist? path
|
13
|
+
return Sandbox.new(path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def binary_dir
|
19
|
+
@binary_dir ||= Pathname.new(@sandbox_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def target_paths
|
23
|
+
return [] unless binary_dir.exist?
|
24
|
+
@targets ||= binary_dir.children().map do |target_path|
|
25
|
+
if target_path.directory? && (not target_path.children.empty?)
|
26
|
+
target_path
|
27
|
+
end
|
28
|
+
end.reject(&:nil?).uniq
|
29
|
+
@targets
|
30
|
+
end
|
31
|
+
|
32
|
+
def existed_target_names(name)
|
33
|
+
target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.map { |pair| pair.basename }
|
34
|
+
end
|
35
|
+
|
36
|
+
def framework_folder_path_for_target_name(name)
|
37
|
+
target_paths.select { |pair| pair.basename == name }.last
|
38
|
+
end
|
39
|
+
|
40
|
+
def prebuild_vendored_frameworks(name)
|
41
|
+
target_path = target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.last
|
42
|
+
return [] if target_path.nil?
|
43
|
+
|
44
|
+
configuration_enable = target_path.children().select { |path| "#{path.basename}" == 'Debug' || "#{path.basename}" == 'Release' }.count == 2
|
45
|
+
if configuration_enable
|
46
|
+
xcconfig_replace_path = BinaryPrebuild.config.xcconfig_replace_path
|
47
|
+
["#{xcconfig_replace_path}-Release/*.{framework,xcframework}"]
|
48
|
+
else
|
49
|
+
["*.{framework,xcframework}"]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def prebuild_bundles(name)
|
54
|
+
target_path = target_paths.select { |pair| "#{pair.basename}" == "#{name}" }.last
|
55
|
+
return [] if target_path.nil?
|
56
|
+
|
57
|
+
configuration_enable = target_path.children().select { |path| "#{path.basename}" == 'Debug' || "#{path.basename}" == 'Release' }.count == 2
|
58
|
+
if configuration_enable
|
59
|
+
xcconfig_replace_path = BinaryPrebuild.config.xcconfig_replace_path
|
60
|
+
["#{xcconfig_replace_path}-Release/*.bundle"]
|
61
|
+
else
|
62
|
+
["*.bundle"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
3
66
|
end
|
@@ -4,7 +4,7 @@ module Pod
|
|
4
4
|
class BuildSettings
|
5
5
|
# missing framework header search paths
|
6
6
|
def missing_framework_header_search_path(pt)
|
7
|
-
return [] unless
|
7
|
+
return [] unless pt.frame_header_search_paths_enable?
|
8
8
|
|
9
9
|
paths = []
|
10
10
|
pt.file_accessors.each do |file_accessor|
|
@@ -47,9 +47,27 @@ module Pod
|
|
47
47
|
paths.push "${PODS_ROOT}/#{header_path.relative_path_from(pt.sandbox.root)}"
|
48
48
|
}
|
49
49
|
end
|
50
|
+
replace_xcconfig_configuration_paths(paths)
|
50
51
|
paths.uniq
|
51
52
|
end
|
52
53
|
|
54
|
+
# replace different configuration xcconfig
|
55
|
+
def replace_xcconfig_configuration_paths(paths)
|
56
|
+
xcconfig_replace_path = BinaryPrebuild.config.xcconfig_replace_path
|
57
|
+
paths.map! { |path|
|
58
|
+
if path =~ /#{xcconfig_replace_path}-(Debug|Release)/
|
59
|
+
configuration = @configuration.to_s.downcase
|
60
|
+
if configuration == 'debug'
|
61
|
+
path.gsub!(/#{xcconfig_replace_path}-(Debug|Release)/, "#{xcconfig_replace_path}-Debug")
|
62
|
+
elsif configuration == 'release'
|
63
|
+
path.gsub!(/#{xcconfig_replace_path}-(Debug|Release)/, "#{xcconfig_replace_path}-Release")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
path
|
67
|
+
}
|
68
|
+
paths
|
69
|
+
end
|
70
|
+
|
53
71
|
# A subclass that generates build settings for a `PodTarget`
|
54
72
|
class AggregateTargetSettings
|
55
73
|
# @return [Array<String>]
|
@@ -70,6 +88,16 @@ module Pod
|
|
70
88
|
header_search_paths.concat dependent_targets.flat_map { |pt| missing_framework_header_search_path(pt) } if target.should_build?
|
71
89
|
header_search_paths.uniq
|
72
90
|
end
|
91
|
+
|
92
|
+
# 按照规则替换framework_search_paths,兼容不同的configuration
|
93
|
+
# 从编译上来说,仅仅替换了framework_search_paths的路径就够了
|
94
|
+
# @return [Array<String>]
|
95
|
+
alias_method :old_raw_framework_search_paths, :_raw_framework_search_paths
|
96
|
+
def _raw_framework_search_paths
|
97
|
+
framework_search_paths = old_raw_framework_search_paths
|
98
|
+
replace_xcconfig_configuration_paths(framework_search_paths)
|
99
|
+
framework_search_paths
|
100
|
+
end
|
73
101
|
end
|
74
102
|
end
|
75
103
|
end
|
@@ -15,16 +15,13 @@ module Pod
|
|
15
15
|
|
16
16
|
def self.options
|
17
17
|
[
|
18
|
-
['--force', '覆盖已经存在的文件']
|
19
|
-
['--create-swiftinterface', '有编译swift文件的framework,如果不包含swiftinterface则无法生成xcframework。
|
20
|
-
设置该参数会生成一个swiftinterface文件解决create失败的问题。']
|
18
|
+
['--force', '覆盖已经存在的文件']
|
21
19
|
]
|
22
20
|
end
|
23
21
|
|
24
22
|
def initialize(argv)
|
25
23
|
@file_path = argv.shift_argument
|
26
24
|
@force = argv.flag?('force')
|
27
|
-
@create_swiftinterface = argv.flag?('create-swiftinterface')
|
28
25
|
super
|
29
26
|
end
|
30
27
|
|
@@ -55,8 +52,7 @@ module Pod
|
|
55
52
|
|
56
53
|
builder = XCFrameworkBuilder.new(
|
57
54
|
framework_name,
|
58
|
-
source_dir
|
59
|
-
@create_swiftinterface
|
55
|
+
source_dir
|
60
56
|
)
|
61
57
|
builder.build_static_xcframework
|
62
58
|
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module Pod
|
2
2
|
class XCFrameworkBuilder
|
3
|
-
def initialize(name, source_dir
|
3
|
+
def initialize(name, source_dir)
|
4
4
|
@name = name
|
5
5
|
@source_dir = source_dir
|
6
|
-
@create_swiftinterface = create_swiftinterface
|
7
6
|
end
|
8
7
|
|
9
8
|
def build_static_xcframework
|
@@ -57,7 +56,7 @@ module Pod
|
|
57
56
|
# 2. copy os framework
|
58
57
|
if os_archs.count > 0
|
59
58
|
path = Pathname.new("#{@source_dir}/#{os_target_path}")
|
60
|
-
path
|
59
|
+
FileUtils.mkdir_p(path) unless path.exist?
|
61
60
|
`cp -a #{framework_path} #{path}/`
|
62
61
|
|
63
62
|
fwk_path = "#{path}/#{@name}.framework"
|
@@ -67,7 +66,7 @@ module Pod
|
|
67
66
|
# 3. copy simulation framework
|
68
67
|
if sim_archs.count > 0
|
69
68
|
path = Pathname.new("#{@source_dir}/#{simulator_target_path}")
|
70
|
-
path
|
69
|
+
FileUtils.mkdir_p(path) unless path.exist?
|
71
70
|
`cp -a #{framework_path} #{path}/`
|
72
71
|
|
73
72
|
fwk_path = "#{path}/#{@name}.framework"
|
@@ -86,23 +85,8 @@ module Pod
|
|
86
85
|
def generate_xcframework(framework_paths)
|
87
86
|
UI.puts("Generate #{@name}.xcframework")
|
88
87
|
|
89
|
-
|
90
|
-
|
91
|
-
swiftmodule_path = Dir.glob("#{framework_path}/Modules/*.swiftmodule").first
|
92
|
-
unless swiftmodule_path.nil?
|
93
|
-
if Dir.glob("#{swiftmodule_path}/*.swiftinterface").empty?
|
94
|
-
unless @create_swiftinterface
|
95
|
-
UI.puts "Framework中包含swiftmodule文件,但是没有swiftinterface,无法创建xcframework,请检查Framework文件。或者使用`--create-swiftinterface`参数"
|
96
|
-
return
|
97
|
-
end
|
98
|
-
arm_swiftinterface = Pathname.new("#{swiftmodule_path}/arm.swiftinterface")
|
99
|
-
File.new(arm_swiftinterface, "w+").close
|
100
|
-
end
|
101
|
-
end
|
102
|
-
}
|
103
|
-
|
104
|
-
# build xcframework
|
105
|
-
command = "xcodebuild -create-xcframework -framework #{framework_paths.join(' -framework ')} -output #{@source_dir}/#{@name}.xcframework 2>&1"
|
88
|
+
# create xcframework
|
89
|
+
command = "xcodebuild -create-xcframework -allow-internal-distribution -framework #{framework_paths.join(' -framework ')} -output #{@source_dir}/#{@name}.xcframework 2>&1"
|
106
90
|
output = `#{command}`.lines.to_a
|
107
91
|
result = $?
|
108
92
|
# show error
|
@@ -115,19 +99,19 @@ module Pod
|
|
115
99
|
|
116
100
|
private
|
117
101
|
def clean_intermediate_path
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
102
|
+
file_path = "#{@source_dir}/#{temp_intermediate_path}"
|
103
|
+
FileUtils.rm_rf(file_path) if File.exist? file_path
|
104
|
+
end
|
105
|
+
|
106
|
+
def temp_intermediate_path
|
107
|
+
"__temp_create_xcframework_dir"
|
124
108
|
end
|
125
109
|
|
126
110
|
def os_target_path
|
127
|
-
"#{@name}
|
111
|
+
"#{temp_intermediate_path}/#{@name}_os"
|
128
112
|
end
|
129
113
|
def simulator_target_path
|
130
|
-
"#{@name}
|
114
|
+
"#{temp_intermediate_path}/#{@name}_simulator"
|
131
115
|
end
|
132
116
|
end
|
133
117
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- guojiashuang
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cocoapods
|
@@ -68,7 +68,11 @@ files:
|
|
68
68
|
- LICENSE
|
69
69
|
- README.md
|
70
70
|
- lib/cocoapods-util.rb
|
71
|
+
- lib/cocoapods-util/binary/Intergation.rb
|
71
72
|
- lib/cocoapods-util/binary/config.rb
|
73
|
+
- lib/cocoapods-util/binary/helper/names.rb
|
74
|
+
- lib/cocoapods-util/binary/helper/podfile_options.rb
|
75
|
+
- lib/cocoapods-util/binary/helper/target_checker.rb
|
72
76
|
- lib/cocoapods-util/binary/hooks/CocoapodsUtilHook.rb
|
73
77
|
- lib/cocoapods-util/binary/hooks/post_install.rb
|
74
78
|
- lib/cocoapods-util/binary/hooks/pre_install.rb
|
@@ -103,7 +107,7 @@ homepage: https://github.com/CaryGo/cocoapods-util
|
|
103
107
|
licenses:
|
104
108
|
- MIT
|
105
109
|
metadata: {}
|
106
|
-
post_install_message:
|
110
|
+
post_install_message:
|
107
111
|
rdoc_options: []
|
108
112
|
require_paths:
|
109
113
|
- lib
|
@@ -119,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
123
|
version: '0'
|
120
124
|
requirements: []
|
121
125
|
rubygems_version: 3.1.2
|
122
|
-
signing_key:
|
126
|
+
signing_key:
|
123
127
|
specification_version: 4
|
124
128
|
summary: 一个常用插件功能的集合,致力于解决日常开发中遇到的一些问题。
|
125
129
|
test_files: []
|