cocoapods-util 0.0.16 → 0.2.0
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 +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: []
|