cocoapods-binary-matchup 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22d50ce597d1eddea065b2472fea259fe5a063a304638f56781a6eb740a3368b
4
- data.tar.gz: dae5536d6035f67546136f12ffe1fc52d602bdffc8dd5eeba120fec2313c4cd7
3
+ metadata.gz: ef4ec458a15107993da7504bba8fe4efb967cc17b5a6c1071c398baf00909a94
4
+ data.tar.gz: 560eed7893ffa1943dead01c79a0895554ed69aa3b28335a79cb107fd2ffc555
5
5
  SHA512:
6
- metadata.gz: 2ef8031c70e49c8f815594f8e4222a425b823b74cfd76c7d2f850398c7d8b52a174f102094eac7cb126976030d53ab233c9361bb55e04761f948d3a5f1a777a9
7
- data.tar.gz: 8cf8d948c812075b068479e25737a0d43999831f2dea87a018d6d62fe8c1049d96bb27076f88173ed91d4bd4ae1939669d768402ee9e8ce8e5c215c14014d909
6
+ metadata.gz: 3bcbce4a8e58f5dd65096887e7a192a97eb906c1f53e57700ccfe54636db507440d13310f3f6f7f52e0ab78d4541238b1c3a0ee65c0d185e544b173d7252c45d
7
+ data.tar.gz: '09f215849f244b80f884d7093488a72d50b4988af5d96844466507db75f8da6041f02c32649accf8528c1ccda92390db43eb6c418bfbbdb68c550694adfdc56e'
data/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ .DS_Store
2
+ pkg
3
+ .idea/
4
+
5
+ test/Pods
6
+
7
+ ## Various settings
8
+ *.pbxuser
9
+ !default.pbxuser
10
+ *.mode1v3
11
+ !default.mode1v3
12
+ *.mode2v3
13
+ !default.mode2v3
14
+ *.perspectivev3
15
+ !default.perspectivev3
16
+ xcuserdata/
17
+
18
+ ## Other
19
+ *.moved-aside
20
+ *.xccheckout
21
+ *.xcscmblueprint
22
+
23
+ ### Xcode Patch ###
24
+ *.xcodeproj/*
25
+ !*.xcodeproj/project.pbxproj
26
+ !*.xcodeproj/xcshareddata/
27
+ !*.xcworkspace/contents.xcworkspacedata
28
+ /*.gcno
29
+ test/Binary.xcworkspace/contents.xcworkspacedata
30
+ test/Binary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
31
+ test/Podfile
32
+ test/Podfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,23 @@
1
+ osx_image: xcode9.3
2
+ language: objective-c
3
+ cache:
4
+ - cocoapods
5
+ - bundler
6
+ before_install:
7
+ - gem install cocoapods
8
+ script:
9
+ - rake install
10
+ - cd test
11
+ - sh test.sh
12
+ - cd ..
13
+
14
+ # auto deploy on tagging
15
+ # automatically set by `travis setup rubygems`
16
+ deploy:
17
+ provider: rubygems
18
+ api_key:
19
+ secure: rubygems_36250bc5acbeefaa1a7985a22146376d17725f0583417826
20
+ gem: cocoapods-binary-matchup
21
+ on:
22
+ tags: true
23
+ repo: omiapp/cocoapods-binary-matchup
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cocoapods-binary-matchup.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'cocoapods'
8
+
9
+ gem 'mocha'
10
+ gem 'bacon'
11
+ gem 'mocha-on-bacon'
12
+ gem 'prettybacon'
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2018 leavez <gaojiji@gmail.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # cocoapods-binary
2
+
3
+ [![Build Status](https://travis-ci.org/leavez/cocoapods-binary.svg?branch=master)](https://travis-ci.org/leavez/cocoapods-binary)
4
+
5
+ A CocoaPods plugin to integrate pods in form of prebuilt frameworks, not source code, by adding **just one flag** in podfile. Speed up compiling dramatically.
6
+
7
+ ## Why
8
+
9
+ You may wonder why CocoaPods doesn't have a function to integrate libs in form of binaries, if there are dozens or hundreds of pods in your podfile and compile them for a great many times meaninglessly. Too many source code of libs slow down your compile and the response of IDE (e.g. code completion), and then reduce work efficiency, leaving us time to think about the meaning of life.
10
+
11
+ This plugin implements this simple wish. Replace the source code in pod target with prebuilt frameworks.
12
+
13
+ Why don't use Carthage? While Carthage also integrates libs in form of frameworks, there several reasons to use CocoaPods with this plugin:
14
+
15
+ - Pod is a good simple form to organize files, manage dependencies. (private or local pods)
16
+ - Fast switch between source code and binary, or partial source code, partial binaries.
17
+ - Some libs don't support Carthage.
18
+
19
+ ## How it works
20
+
21
+ It will compile the source code of pods during the pod install process, and make CocoaPods use them. Which pod should be compiled is controlled by the flag in Podfile.
22
+
23
+ #### Under the hood
24
+
25
+ ( You could leave this paragraph for further reading, and try it now. )
26
+
27
+ The plugin will do a separated completed 'Pod install' in the standard pre-install hook. But we filter the pods by the flag in Podfile here. Then build frameworks with this generated project by using xcodebuild. Store the frameworks in `Pods/_Prebuild` and save the manifest.lock file for the next pod install.
28
+
29
+ Then in the flowing normal install process, we hook the integration functions to modify pod specification to using our frameworks.
30
+
31
+ ## Installation
32
+
33
+ $ gem install cocoapods-binary
34
+
35
+ ## Usage
36
+
37
+ ``` ruby
38
+ plugin 'cocoapods-binary'
39
+
40
+ use_frameworks!
41
+ # all_binary!
42
+
43
+ target "HP" do
44
+ pod "ExpectoPatronum", :binary => true
45
+ end
46
+ ```
47
+
48
+ - Add `plugin 'cocoapods-binary'` in the head of Podfile
49
+ - Add `:binary => true` as a option of one specific pod, or add `all_binary!` before all targets, which makes all pods binaries.
50
+ - pod install, and that's all
51
+
52
+ **Note**: cocoapods-binary require `use_frameworks!`. If your worry about the boot time and other problems introduced by dynamic framework, static framework is a good choice. Another [plugin](https://github.com/leavez/cocoapods-static-swift-framework) made by me to make all pods static frameworks is recommended.
53
+
54
+ #### Options
55
+
56
+ If you want to disable binary for a specific pod when using `all_binary!`, place a `:binary => false` to it.
57
+
58
+ If your `Pods` folder is excluded from git, you may add `keep_source_code_for_prebuilt_frameworks!` in the head of Podfile to speed up pod install, as it won't download all the sources every time prebuilt pods have changes.
59
+
60
+ If bitcode is needed, add a `enable_bitcode_for_prebuilt_frameworks!` before all targets in Podfile
61
+
62
+
63
+ #### Known Issues
64
+
65
+ - doesn't support watchos now
66
+ - dSYM files is missing for dynamic frameworks using this plugin. Walkaround: Don't use this plugin for a release build. Add a if condition with ENV around `plugin 'cocoapods-binary'`
67
+
68
+ ## License
69
+
70
+ MIT
71
+
72
+ Appreciate a 🌟 if you like it.
73
+
74
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ def specs(dir)
4
+ FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ')
5
+ end
6
+
7
+ desc 'Runs all the specs'
8
+ task :specs do
9
+ sh "bundle exec bacon #{specs('**')}"
10
+ end
11
+
12
+ task :default => :specs
13
+
Binary file
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cocoapods-binary-matchup/gem_version.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cocoapods-binary-matchup'
8
+ spec.version = CocoapodsBinary::VERSION
9
+ spec.authors = ['leavez']
10
+ spec.email = ['gaojiji@gmail.com']
11
+ spec.description = %q{integrate pods in form of prebuilt frameworks conveniently, reducing compile time}
12
+ spec.summary = %q{A CocoaPods plugin to integrate pods in form of prebuilt frameworks, not source code, by adding just one flag in podfile. Speed up compiling dramatically.}
13
+ spec.homepage = 'https://github.com/omiapp/cocoapod_binary_matchup'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/).reject{|f| f.start_with?("test/") || f.start_with?('demo/')}
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency "cocoapods", ">= 1.5.0", "< 2.0"
22
+ spec.add_dependency "fourflusher", "~> 2.0"
23
+ spec.add_dependency "xcpretty", "~> 0.3.0"
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.3'
26
+ spec.add_development_dependency 'rake'
27
+ end
@@ -0,0 +1,293 @@
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/target_checker'
6
+
7
+
8
+ # NOTE:
9
+ # This file will only be loaded on normal pod install step
10
+ # so there's no need to check is_prebuild_stage
11
+
12
+
13
+
14
+ # Provide a special "download" process for prebuilded pods.
15
+ #
16
+ # As the frameworks is already exsited in local folder. We
17
+ # just create a symlink to the original target folder.
18
+ #
19
+ require_relative 'Integration_cache'
20
+
21
+ module Pod
22
+ class Installer
23
+ class PodSourceInstaller
24
+
25
+ def install_for_prebuild!(standard_sanbox)
26
+ return if standard_sanbox.local? self.name
27
+ UI.puts "install_for_prebuild! start: #{self.name}"
28
+
29
+ # 获取pod版本信息
30
+ pod_version = Pod::PrebuildCache::Cache.get_pod_version(standard_sanbox, self.name)
31
+ target_folder = standard_sanbox.pod_dir(self.name)
32
+ target_folder.rmtree if target_folder.exist?
33
+
34
+ # 1. 首先尝试从缓存恢复
35
+ if Pod::PrebuildCache::Cache.copy_from_cache_if_exists(self.name, pod_version, target_folder.to_s)
36
+ UI.puts "📦 Successfully restored #{self.name} (#{pod_version}) from cache"
37
+ return
38
+ end
39
+
40
+ # 2. 如果缓存不存在,从预构建目录拷贝
41
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
42
+ real_file_folder = prebuild_sandbox.framework_folder_path_for_pod_name(self.name)
43
+
44
+ if real_file_folder.exist?
45
+ # 拷贝到pods目录
46
+ FileUtils.cp_r(real_file_folder, target_folder, :remove_destination => true)
47
+ UI.puts "📦 Copied prebuilt files for #{self.name}: #{real_file_folder} -> #{target_folder}"
48
+
49
+ # 3. 同时保存到缓存(如果缓存不存在)
50
+ Pod::PrebuildCache::Cache.save_to_cache(self.name, pod_version, target_folder.to_s)
51
+ else
52
+ UI.puts "⚠️ Warning: Prebuilt files not found for #{self.name} at #{real_file_folder}"
53
+ # 如果预构建文件不存在,创建空目录避免错误
54
+ target_folder.mkpath
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ # Let cocoapods use the prebuild framework files in install process.
64
+ #
65
+ # the code only effect the second pod install process.
66
+ #
67
+ module Pod
68
+ class Installer
69
+
70
+
71
+ # Remove the old target files if prebuild frameworks changed
72
+ def remove_target_files_if_needed
73
+
74
+ changes = Pod::Prebuild::Passer.prebuild_pods_changes
75
+ updated_names = []
76
+ if changes == nil
77
+ updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_names
78
+ else
79
+ added = changes.added
80
+ changed = changes.changed
81
+ deleted = changes.deleted
82
+ updated_names = added + changed + deleted
83
+ end
84
+
85
+ updated_names.each do |name|
86
+ root_name = Specification.root_name(name)
87
+ next if self.sandbox.local?(root_name)
88
+ # 只有当不是预构建的pod时才删除,避免删除刚拷贝的预构建文件
89
+ next if self.prebuild_pod_names.include?(root_name)
90
+
91
+ # delete the cached files
92
+ target_path = self.sandbox.pod_dir(root_name)
93
+ target_path.rmtree if target_path.exist?
94
+
95
+ support_path = sandbox.target_support_files_dir(root_name)
96
+ support_path.rmtree if support_path.exist?
97
+ end
98
+
99
+ end
100
+
101
+
102
+ # Modify specification to use only the prebuild framework after analyzing
103
+ old_method2 = instance_method(:resolve_dependencies)
104
+ define_method(:resolve_dependencies) do
105
+
106
+ # Remove the old target files, else it will not notice file changes
107
+ self.remove_target_files_if_needed
108
+
109
+ # call original
110
+ old_method2.bind(self).()
111
+
112
+ # check the pods
113
+ # Although we have did it in prebuild stage, it's not sufficient.
114
+ # Same pod may appear in another target in form of source code.
115
+ Prebuild.check_one_pod_should_have_only_one_target(self.prebuild_pod_targets)
116
+ UI.puts "🔍 prebuild_pod_names (cached): #{self.prebuild_pod_names}"
117
+
118
+ # FIXED: 在主安装阶段强制重新计算 prebuild_pod_names
119
+ # 避免使用过期的缓存(可能在 aggregate_targets 初始化前被缓存为空)
120
+ fresh_prebuild_pod_names = self.refresh_prebuild_pod_names!
121
+ UI.puts "🔍 prebuild_pod_names (fresh): #{fresh_prebuild_pod_names}"
122
+
123
+ #
124
+ specs = self.analysis_result.specifications
125
+ prebuilt_specs = (specs.select do |spec|
126
+ self.prebuild_pod_names.include? spec.root.name
127
+ end)
128
+
129
+ # make sturcture to fast get target by name
130
+ name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
131
+ sum[target.name] = target
132
+ sum
133
+ end
134
+
135
+ prebuilt_specs.each do |spec|
136
+ # `spec` may be a subspec, so we use the root's name
137
+ root_name = spec.root.name
138
+
139
+ target = name_to_target_hash[root_name]
140
+ next if Prebuild::Passer.target_names_to_skip_integration_framework.include? target.pod_name
141
+
142
+ # use the prebuilt framework
143
+ original_vendored_frameworks = spec.attributes_hash["vendored_frameworks"] || []
144
+ if original_vendored_frameworks.kind_of?(String)
145
+ original_vendored_frameworks = [original_vendored_frameworks]
146
+ end
147
+ framework_name = target.framework_name
148
+ if framework_name.kind_of?(Array)
149
+ original_vendored_frameworks += framework_name
150
+ else
151
+ # 始终使用Build目录下的路径,因为我们的install_for_prebuild!会复制framework到Build目录
152
+ original_vendored_frameworks += [framework_name]
153
+ end
154
+ spec.attributes_hash["vendored_frameworks"] = original_vendored_frameworks
155
+
156
+ # 对于静态库类型的pod,需要保留头文件,不能完全清空source_files
157
+ # 检查是否有vendored_libraries(静态库)
158
+ vendored_libraries = spec.attributes_hash["vendored_libraries"] || []
159
+ if vendored_libraries.kind_of?(String)
160
+ vendored_libraries = [vendored_libraries]
161
+ end
162
+
163
+ # 不管是静态库还是动态框架,都需要智能处理source_files
164
+ # 保留头文件和重要文件,清空.m/.swift等源码文件
165
+ current_source_files = spec.attributes_hash["source_files"] || []
166
+ if current_source_files.kind_of?(String)
167
+ current_source_files = [current_source_files]
168
+ end
169
+
170
+ if current_source_files.empty?
171
+ # 如果原来就没有source_files,不做处理
172
+ spec.attributes_hash["source_files"] = []
173
+ else
174
+ # 智能处理source_files:保留头文件相关模式,清空源码文件模式
175
+ header_files = current_source_files.select { |file_pattern|
176
+ pattern = file_pattern.to_s
177
+ # 检查是否是头文件相关的模式,使用更精确的正则表达式
178
+ pattern.match?(/\*+\.h$/) || # 匹配 "*.h", "**/*.h" 等
179
+ pattern.match?(/\*+\.hpp$/) || # 匹配 "*.hpp", "**/*.hpp" 等
180
+ pattern.match?(/\*+\.hh$/) || # 匹配 "*.hh", "**/*.hh" 等
181
+ pattern.match?(/\*+\.modulemap$/) || # 匹配 "*.modulemap"
182
+ pattern.match?(/\/\*\.h$/) || # 匹配 "Sources/*.h" 等
183
+ pattern.match?(/\/\*\.hpp$/) || # 匹配 "Sources/*.hpp" 等
184
+ pattern.match?(/\/\*\.hh$/) || # 匹配 "Sources/*.hh" 等
185
+ pattern.match?(/\/\*\.modulemap$/) || # 匹配 "Sources/*.modulemap"
186
+ pattern.end_with?('.h', '.hpp', '.hh', '.modulemap') || # 直接的头文件路径
187
+ pattern.match?(/\*\*?\/\*$/) # 通用通配符保留,如 "Sources/*", "**/*"
188
+ }
189
+
190
+ # 如果没有找到明确的头文件模式,保留原有的source_files
191
+ # 这样可以避免意外删除重要的头文件
192
+ if header_files.empty?
193
+ spec.attributes_hash["source_files"] = current_source_files
194
+ else
195
+ UI.puts "📋 #{spec.root.name} header_files: #{header_files}"
196
+ spec.attributes_hash["source_files"] = header_files
197
+ end
198
+ end
199
+
200
+ # to remove the resurce bundle target.
201
+ # When specify the "resource_bundles" in podspec, xcode will generate a bundle
202
+ # target after pod install. But the bundle have already built when the prebuit
203
+ # phase and saved in the framework folder. We will treat it as a normal resource
204
+ # file.
205
+ # https://github.com/leavez/cocoapods-binary/issues/29
206
+ if spec.attributes_hash["resource_bundles"]
207
+ bundle_names = spec.attributes_hash["resource_bundles"].keys
208
+ spec.attributes_hash["resource_bundles"] = nil
209
+ current_resources = spec.attributes_hash["resources"] || []
210
+
211
+ if current_resources.kind_of?(String)
212
+ current_resources = [current_resources]
213
+ end
214
+
215
+ current_resources += bundle_names.map{|n| n+".bundle"}
216
+ spec.attributes_hash["resources"] = current_resources
217
+ end
218
+
219
+ # to avoid the warning of missing license
220
+ spec.attributes_hash["license"] = {}
221
+ end
222
+
223
+ end
224
+
225
+
226
+ # Override the download step to skip download and prepare file in target folder
227
+ old_method = instance_method(:install_source_of_pod)
228
+ define_method(:install_source_of_pod) do |pod_name|
229
+
230
+ # copy from original
231
+ pod_installer = create_pod_installer(pod_name)
232
+ # \copy from original
233
+ UI.puts "🔍 Installing pod: #{pod_name}"
234
+ UI.puts "🔍 prebuild_pod_names: #{self.prebuild_pod_names}"
235
+ UI.puts "🔍 is_prebuild_pod: #{self.prebuild_pod_names.include?(pod_name)}"
236
+
237
+ if self.prebuild_pod_names.include? pod_name
238
+ UI.puts "📦 Installing prebuild pod: #{pod_name}"
239
+ pod_installer.install_for_prebuild!(self.sandbox)
240
+ else
241
+ UI.puts "📥 Installing source pod: #{pod_name}"
242
+ pod_installer.install!
243
+ end
244
+
245
+ # copy from original
246
+ @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
247
+ # \copy from original
248
+ end
249
+
250
+
251
+ end
252
+ end
253
+
254
+ # A fix in embeded frameworks script.
255
+ #
256
+ # The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
257
+ # to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
258
+ # we override the `readlink` to a fixed version.
259
+ #
260
+ module Pod
261
+ module Generator
262
+ class EmbedFrameworksScript
263
+
264
+ old_method = instance_method(:script)
265
+ define_method(:script) do
266
+
267
+ script = old_method.bind(self).()
268
+ patch = <<-SH.strip_heredoc
269
+ #!/bin/sh
270
+
271
+ # ---- this is added by cocoapods-binary ---
272
+ # Readlink cannot handle relative symlink well, so we override it to a new one
273
+ # If the path isn't an absolute path, we add a realtive prefix.
274
+ old_read_link=`which readlink`
275
+ readlink () {
276
+ path=`$old_read_link $1`;
277
+ if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
278
+ echo $path;
279
+ else
280
+ echo "`dirname $1`/$path";
281
+ fi
282
+ }
283
+ # ---
284
+ SH
285
+
286
+ # patch the rsync for copy dSYM symlink
287
+ script = script.gsub "rsync --delete", "rsync --copy-links --delete"
288
+
289
+ patch + script
290
+ end
291
+ end
292
+ end
293
+ end