cocoapods-precompile 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5f5662367c1b4c3744285ba48862a33a411a9493
4
+ data.tar.gz: ea7906382f28b789e658fa3d7305fc0c8196e553
5
+ SHA512:
6
+ metadata.gz: b854a293a523da0bf8c58758ffbbd81b7bdcfcc3c3430d891ec6fbee272dfa4d5d1f6b5cef370e0d8781c343a01f51adc60ceb68ed8a321a429907ff74878efd
7
+ data.tar.gz: e8d667141d30e59794471b5615330419f9f224ea0a6230831a14c9b152a6b83d15ab8d653f6ff02a3584e8cfe3011aec00a20099bfdb9cdc41d5db57765f2f83
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: HglQwElI8cEeKc5oXzoVbBBprgb8k7RUr0YOH1N1fhpNW7HJpJtSLzUBPC5T+Sv5RPSicaxY/oXeYE6x4E7Oadf7Gy2tmM9iwwJQh6YgZ/foh9G9obHZtTerhB4wY2cjguBXDmLqiMRiJzNTZRvoUnESBKakPbK/ODY0mHT+LDdMwZk2QsMjD3fRc5M7JRR29jr56jzVuUdy0lR4TRoc2+yIRqp2vFNtcbKdzKuYgzcdE9xzPh0FQzgiImA5uGDruyAgoNeOlGxDPZdnm7fw/epLmq8fUIZanReI30QnJeIErFwMCVeN1zVqQiWRgv8qGi8Z0ZKOzvcu7oKuaeXo5xSkTfkAc9I0LbcRd3UHCluAr9JHuERNwkn1qx5W0DdngTKrPM65ZABQxk4KUHt+5yd6Dv7lR9GrGD3teNZDga/X8u0tQIkoPIl76ZjXRh0bmCDQM/zWaTKkh7eX/YXQKgrjrEecZMeZfsLds789MK2QO17QlbHTVno+HBr0Rah6nHI0/vl1xqHthHCb/Y9SBXmLQ7+ySNXmj7YxPjpD6m8kEEUDTQQdgjS7vMInqJiSekGBImu2VQA/qZP1+WEBha5nX2ADfvsAWfUdsdQfuTbv07RnIG+3quzSl5U1UPVR9f7EsqpTtxflLJCqVdaz2ndQBO6NXAnRhA90cfAFd9s=
20
+ gem: cocoapods-binary
21
+ on:
22
+ tags: true
23
+ repo: leavez/cocoapods-binary
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cocoapods-binary.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,75 @@
1
+
2
+ <p align="center"><img src="/test/logo.png" width="622"></p>
3
+
4
+ [![Build Status](https://travis-ci.org/leavez/cocoapods-binary.svg?branch=master)](https://travis-ci.org/leavez/cocoapods-binary)
5
+
6
+ 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.
7
+
8
+ ## Why
9
+
10
+ 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.
11
+
12
+ This plugin implements this simple wish. Replace the source code in pod target with prebuilt frameworks.
13
+
14
+ Why don't use Carthage? While Carthage also integrates libs in form of frameworks, there several reasons to use CocoaPods with this plugin:
15
+
16
+ - Pod is a good simple form to organize files, manage dependencies. (private or local pods)
17
+ - Fast switch between source code and binary, or partial source code, partial binaries.
18
+ - Some libs don't support Carthage.
19
+
20
+ ## How it works
21
+
22
+ 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.
23
+
24
+ #### Under the hood
25
+
26
+ ( You could leave this paragraph for further reading, and try it now. )
27
+
28
+ 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.
29
+
30
+ Then in the flowing normal install process, we hook the integration functions to modify pod specification to using our frameworks.
31
+
32
+ ## Installation
33
+
34
+ $ gem install cocoapods-binary
35
+
36
+ ## Usage
37
+
38
+ ``` ruby
39
+ plugin 'cocoapods-binary'
40
+
41
+ use_frameworks!
42
+ # all_binary!
43
+
44
+ target "HP" do
45
+ pod "ExpectoPatronum", :binary => true
46
+ end
47
+ ```
48
+
49
+ - Add `plugin 'cocoapods-binary'` in the head of Podfile
50
+ - Add `:binary => true` as a option of one specific pod, or add `all_binary!` before all targets, which makes all pods binaries.
51
+ - pod install, and that's all
52
+
53
+ **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.
54
+
55
+ #### Options
56
+
57
+ If you want to disable binary for a specific pod when using `all_binary!`, place a `:binary => false` to it.
58
+
59
+ 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.
60
+
61
+ If bitcode is needed, add a `enable_bitcode_for_prebuilt_frameworks!` before all targets in Podfile
62
+
63
+
64
+ #### Known Issues
65
+
66
+ - doesn't support watchos now
67
+ - 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'`
68
+
69
+ ## License
70
+
71
+ MIT
72
+
73
+ Appreciate a 🌟 if you like it.
74
+
75
+
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
+
@@ -0,0 +1,26 @@
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/gem_version.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cocoapods-precompile'
8
+ spec.version = CocoapodsPrecompile::VERSION
9
+ spec.authors = ['iiiCeBlink']
10
+ spec.email = ['zakariyyasv@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/iiiCeBlink/cocoapods-binary'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/).reject{|f| f.start_with? "test/"}
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.4.0", "< 2.0"
22
+ spec.add_dependency "fourflusher", "~> 2.0"
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.3'
25
+ spec.add_development_dependency 'rake'
26
+ end
@@ -0,0 +1,266 @@
1
+ require_relative 'helper/podfile_options'
2
+ require_relative 'helper/feature_switches'
3
+ require_relative 'helper/prebuild_sandbox'
4
+ require_relative 'helper/passer'
5
+ require_relative 'helper/names'
6
+
7
+
8
+
9
+ # NOTE:
10
+ # This file will only be loaded on normal pod install step
11
+ # so there's no need to check is_prebuild_stage
12
+
13
+
14
+
15
+ # Provide a special "download" process for prebuilded pods.
16
+ #
17
+ # As the frameworks is already exsited in local folder. We
18
+ # just create a symlink to the original target folder.
19
+ #
20
+ module Pod
21
+ class Installer
22
+ class PodSourceInstaller
23
+
24
+ def install_for_prebuild!(standard_sanbox)
25
+ return if standard_sanbox.local? self.name
26
+
27
+ # make a symlink to target folder
28
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
29
+ # if spec used in multiple platforms, it may return multiple paths
30
+ target_names = prebuild_sandbox.existed_target_names_for_pod_name(self.name)
31
+
32
+ def walk(path, &action)
33
+ path.children.each do |child|
34
+ result = action.call(child, &action)
35
+ if child.directory?
36
+ walk(child, &action) if result
37
+ end
38
+ end
39
+ end
40
+ def make_link(source, target)
41
+ source = Pathname.new(source)
42
+ target = Pathname.new(target)
43
+ target.parent.mkpath unless target.parent.exist?
44
+ relative_source = source.relative_path_from(target.parent)
45
+ FileUtils.ln_sf(relative_source, target)
46
+ end
47
+ def mirror_with_symlink(source, basefolder, target_folder)
48
+ target = target_folder + source.relative_path_from(basefolder)
49
+ make_link(source, target)
50
+ end
51
+
52
+ target_names.each do |name|
53
+
54
+ # symbol link copy all substructure
55
+ real_file_folder = prebuild_sandbox.framework_folder_path_for_target_name(name)
56
+
57
+ # If have only one platform, just place int the root folder of this pod.
58
+ # If have multiple paths, we use a sperated folder to store different
59
+ # platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework
60
+
61
+ target_folder = standard_sanbox.pod_dir(self.name)
62
+ if target_names.count > 1
63
+ target_folder += real_file_folder.basename
64
+ end
65
+ target_folder.rmtree if target_folder.exist?
66
+ target_folder.mkpath
67
+
68
+
69
+ walk(real_file_folder) do |child|
70
+ source = child
71
+ # only make symlink to file and `.framework` folder
72
+ if child.directory? and child.extname == ".framework"
73
+ mirror_with_symlink(source, real_file_folder, target_folder)
74
+ next false # return false means don't go deeper
75
+ elsif child.file?
76
+ mirror_with_symlink(source, real_file_folder, target_folder)
77
+ next true
78
+ else
79
+ next true
80
+ end
81
+ end
82
+
83
+
84
+ # symbol link copy resource for static framework
85
+ hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}
86
+
87
+ path_objects = hash[name]
88
+ if path_objects != nil
89
+ path_objects.each do |object|
90
+ make_link(object.real_file_path, object.target_file_path)
91
+ end
92
+ end
93
+ end # of for each
94
+
95
+ end # of method
96
+
97
+ end
98
+ end
99
+ end
100
+
101
+
102
+ # Let cocoapods use the prebuild framework files in install process.
103
+ #
104
+ # the code only effect the second pod install process.
105
+ #
106
+ module Pod
107
+ class Installer
108
+
109
+
110
+ # Remove the old target files if prebuild frameworks changed
111
+ def remove_target_files_if_needed
112
+
113
+ changes = Pod::Prebuild::Passer.prebuild_pods_changes
114
+ updated_names = []
115
+ if changes == nil
116
+ updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_pod_names
117
+ else
118
+ added = changes.added
119
+ changed = changes.changed
120
+ deleted = changes.deleted
121
+ updated_names = added + changed + deleted
122
+ end
123
+
124
+ updated_names.each do |name|
125
+ root_name = Specification.root_name(name)
126
+ next if self.sandbox.local?(root_name)
127
+
128
+ # delete the cached files
129
+ target_path = self.sandbox.pod_dir(root_name)
130
+ target_path.rmtree if target_path.exist?
131
+
132
+ support_path = sandbox.target_support_files_dir(root_name)
133
+ support_path.rmtree if support_path.exist?
134
+ end
135
+
136
+ end
137
+
138
+
139
+ # Modify specification to use only the prebuild framework after analyzing
140
+ old_method2 = instance_method(:resolve_dependencies)
141
+ define_method(:resolve_dependencies) do
142
+
143
+ # Remove the old target files, else it will not notice file changes
144
+ self.remove_target_files_if_needed
145
+
146
+ # call original
147
+ old_method2.bind(self).()
148
+ # ...
149
+ # ...
150
+ # ...
151
+ # after finishing the very complex orginal function
152
+
153
+
154
+ # check
155
+ self.validate_every_pod_only_have_one_form
156
+
157
+
158
+ # prepare
159
+ cache = []
160
+
161
+ def add_vendered_framework(spec, platform, added_framework_file_path)
162
+ if spec.attributes_hash[platform] == nil
163
+ spec.attributes_hash[platform] = {}
164
+ end
165
+ vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
166
+ vendored_frameworks = [vendored_frameworks] if vendored_frameworks.kind_of?(String)
167
+ vendored_frameworks += [added_framework_file_path]
168
+ spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
169
+ end
170
+ def empty_source_files(spec)
171
+ spec.attributes_hash["source_files"] = []
172
+ ["ios", "watchos", "tvos", "osx"].each do |plat|
173
+ if spec.attributes_hash[plat] != nil
174
+ spec.attributes_hash[plat]["source_files"] = []
175
+ end
176
+ end
177
+ end
178
+
179
+ specs = self.analysis_result.specifications
180
+ prebuilt_specs = (specs.select do |spec|
181
+ self.prebuild_pod_names.include? spec.root.name
182
+ end)
183
+
184
+ prebuilt_specs.each do |spec|
185
+
186
+ # Use the prebuild framworks as vendered frameworks
187
+ # get_corresponding_targets
188
+ targets = Pod.fast_get_targets_for_pod_name(spec.root.name, self.pod_targets, cache)
189
+ targets.each do |target|
190
+ # the framework_file_path rule is decided when `install_for_prebuild`,
191
+ # as to compitable with older version and be less wordy.
192
+ framework_file_path = target.framework_name
193
+ framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
194
+ add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
195
+ end
196
+ # Clean the source files
197
+ # we just add the prebuilt framework to specific platform and set no source files
198
+ # for all platform, so it doesn't support the sence that 'a pod perbuild for one
199
+ # platform and not for another platform.'
200
+ empty_source_files(spec)
201
+
202
+ # to avoid the warning of missing license
203
+ spec.attributes_hash["license"] = {}
204
+ end
205
+
206
+ end
207
+
208
+
209
+ # Override the download step to skip download and prepare file in target folder
210
+ old_method = instance_method(:install_source_of_pod)
211
+ define_method(:install_source_of_pod) do |pod_name|
212
+
213
+ # copy from original
214
+ pod_installer = create_pod_installer(pod_name)
215
+ # \copy from original
216
+
217
+ if self.prebuild_pod_names.include? pod_name
218
+ pod_installer.install_for_prebuild!(self.sandbox)
219
+ else
220
+ pod_installer.install!
221
+ end
222
+
223
+ # copy from original
224
+ @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
225
+ # \copy from original
226
+ end
227
+
228
+
229
+ end
230
+ end
231
+
232
+ # A fix in embeded frameworks script.
233
+ #
234
+ # The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
235
+ # to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
236
+ # we override the `readlink` to a fixed version.
237
+ #
238
+ module Pod
239
+ module Generator
240
+ class EmbedFrameworksScript
241
+
242
+ old_method = instance_method(:script)
243
+ define_method(:script) do
244
+
245
+ script = old_method.bind(self).()
246
+ patch = <<-SH.strip_heredoc
247
+ #!/bin/sh
248
+
249
+ # ---- this is added by cocoapods-binary ---
250
+ # Readlink cannot handle relative symlink well, so we override it to a new one
251
+ # If the path isn't an absolute path, we add a realtive prefix.
252
+ readlink () {
253
+ path=`/usr/bin/readlink $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
+ patch + script
263
+ end
264
+ end
265
+ end
266
+ end