cocoapods-binary-cache 0.1.1
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 +7 -0
- data/lib/cocoapods-binary-cache.rb +4 -0
- data/lib/cocoapods-binary-cache/cache/all.rb +9 -0
- data/lib/cocoapods-binary-cache/cache/validation_result.rb +69 -0
- data/lib/cocoapods-binary-cache/cache/validator.rb +21 -0
- data/lib/cocoapods-binary-cache/cache/validator_accumulated.rb +4 -0
- data/lib/cocoapods-binary-cache/cache/validator_base.rb +92 -0
- data/lib/cocoapods-binary-cache/cache/validator_dependencies_graph.rb +20 -0
- data/lib/cocoapods-binary-cache/cache/validator_dev_pods.rb +22 -0
- data/lib/cocoapods-binary-cache/cache/validator_exclusion.rb +14 -0
- data/lib/cocoapods-binary-cache/cache/validator_non_dev_pods.rb +13 -0
- data/lib/cocoapods-binary-cache/cache/validator_with_podfile.rb +9 -0
- data/lib/cocoapods-binary-cache/dependencies_graph/dependencies_graph.rb +95 -0
- data/lib/cocoapods-binary-cache/dependencies_graph/graph_visualizer.rb +74 -0
- data/lib/cocoapods-binary-cache/gem_version.rb +6 -0
- data/lib/cocoapods-binary-cache/helper/benchmark_show.rb +11 -0
- data/lib/cocoapods-binary-cache/helper/checksum.rb +12 -0
- data/lib/cocoapods-binary-cache/helper/json.rb +37 -0
- data/lib/cocoapods-binary-cache/helper/lockfile.rb +67 -0
- data/lib/cocoapods-binary-cache/helper/path_utils.rb +8 -0
- data/lib/cocoapods-binary-cache/helper/podspec.rb +17 -0
- data/lib/cocoapods-binary-cache/hooks/post_install.rb +16 -0
- data/lib/cocoapods-binary-cache/hooks/pre_install.rb +141 -0
- data/lib/cocoapods-binary-cache/main.rb +21 -0
- data/lib/cocoapods-binary-cache/pod-binary/LICENSE.txt +22 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb +25 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +36 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb +90 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/names.rb +36 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/passer.rb +25 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/podfile_options.rb +2 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/prebuild_sandbox.rb +71 -0
- data/lib/cocoapods-binary-cache/pod-binary/helper/target_checker.rb +45 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration.rb +12 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb +93 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/patch/embed_framework_script.rb +36 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/patch/resolve_dependencies.rb +23 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +28 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/remove_target_files.rb +29 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/source_installer.rb +111 -0
- data/lib/cocoapods-binary-cache/pod-binary/integration/validation.rb +20 -0
- data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +224 -0
- data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +69 -0
- data/lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb +11 -0
- data/lib/cocoapods-binary-cache/pod-binary/tool/tool.rb +12 -0
- data/lib/cocoapods-binary-cache/pod-rome/LICENSE.txt +22 -0
- data/lib/cocoapods-binary-cache/pod-rome/build_framework.rb +247 -0
- data/lib/cocoapods-binary-cache/prebuild_cache.rb +49 -0
- data/lib/cocoapods-binary-cache/prebuild_output/metadata.rb +47 -0
- data/lib/cocoapods-binary-cache/prebuild_output/output.rb +71 -0
- data/lib/cocoapods-binary-cache/scheme_editor.rb +35 -0
- data/lib/cocoapods-binary-cache/state_store.rb +11 -0
- data/lib/cocoapods-binary-cache/ui.rb +9 -0
- data/lib/cocoapods_plugin.rb +5 -0
- data/lib/command/binary.rb +18 -0
- data/lib/command/config.rb +31 -0
- data/lib/command/executor/base.rb +20 -0
- data/lib/command/executor/fetcher.rb +44 -0
- data/lib/command/executor/prebuilder.rb +58 -0
- data/lib/command/executor/pusher.rb +19 -0
- data/lib/command/executor/visualizer.rb +20 -0
- data/lib/command/fetch.rb +23 -0
- data/lib/command/helper/zip.rb +20 -0
- data/lib/command/prebuild.rb +29 -0
- data/lib/command/visualize.rb +30 -0
- metadata +193 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pod
|
2
|
+
class Installer
|
3
|
+
def validate_every_pod_only_have_one_form
|
4
|
+
multi_targets_pods = pod_targets
|
5
|
+
.group_by(&:pod_name)
|
6
|
+
.select do |_, targets|
|
7
|
+
is_multi_targets = targets.map { |t| t.platform.name }.uniq.count > 1
|
8
|
+
is_multi_forms = targets.map { |t| prebuilt_pod_targets.include?(t) }.uniq.count > 1
|
9
|
+
is_multi_targets && is_multi_forms
|
10
|
+
end
|
11
|
+
return if multi_targets_pods.empty?
|
12
|
+
|
13
|
+
warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
|
14
|
+
warnings += multi_targets_pods
|
15
|
+
.map { |name, targets| " #{name}: #{targets.map { |t| t.platform.name }}" }
|
16
|
+
.join("\n")
|
17
|
+
raise Informative, warnings
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require_relative "../pod-rome/build_framework"
|
3
|
+
require_relative "../prebuild_output/output"
|
4
|
+
require_relative "helper/passer"
|
5
|
+
require_relative "helper/target_checker"
|
6
|
+
|
7
|
+
# patch prebuild ability
|
8
|
+
module Pod
|
9
|
+
class PrebuildInstaller < Installer
|
10
|
+
def initialize(options)
|
11
|
+
super(options[:sandbox], options[:podfile], options[:lockfile])
|
12
|
+
@cache_validation = options[:cache_validation]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def local_manifest
|
18
|
+
@local_manifest ||= sandbox.manifest
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Analyzer::SpecsState]
|
22
|
+
def prebuild_pods_changes
|
23
|
+
return nil if local_manifest.nil?
|
24
|
+
|
25
|
+
if @prebuild_pods_changes.nil?
|
26
|
+
changes = local_manifest.detect_changes_with_podfile(podfile)
|
27
|
+
@prebuild_pods_changes = Analyzer::SpecsState.new(changes)
|
28
|
+
# save the chagnes info for later stage
|
29
|
+
Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes
|
30
|
+
end
|
31
|
+
@prebuild_pods_changes
|
32
|
+
end
|
33
|
+
|
34
|
+
def blacklisted?(name)
|
35
|
+
PodPrebuild::StateStore.excluded_pods.include?(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def cache_hit?(name)
|
39
|
+
@cache_validation.hit?(name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def should_not_prebuild_vendor_pod(name)
|
43
|
+
return true if blacklisted?(name)
|
44
|
+
return false if Pod::Podfile::DSL.prebuild_all_vendor_pods
|
45
|
+
|
46
|
+
cache_hit?(name)
|
47
|
+
end
|
48
|
+
|
49
|
+
public
|
50
|
+
|
51
|
+
def prebuild_output
|
52
|
+
@prebuild_output ||= PodPrebuild::Output.new(sandbox)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Build the needed framework files
|
56
|
+
def prebuild_frameworks!
|
57
|
+
UI.puts "Start prebuild_frameworks"
|
58
|
+
|
59
|
+
# build options
|
60
|
+
sandbox_path = sandbox.root
|
61
|
+
existed_framework_folder = sandbox.generate_framework_path
|
62
|
+
bitcode_enabled = Pod::Podfile::DSL.bitcode_enabled
|
63
|
+
targets = []
|
64
|
+
|
65
|
+
if Pod::Podfile::DSL.prebuild_all_vendor_pods
|
66
|
+
UI.puts "Rebuild all vendor frameworks"
|
67
|
+
targets = pod_targets
|
68
|
+
elsif !local_manifest.nil?
|
69
|
+
UI.puts "Update some frameworks"
|
70
|
+
changes = prebuild_pods_changes
|
71
|
+
added = changes.added
|
72
|
+
changed = changes.changed
|
73
|
+
unchanged = changes.unchanged
|
74
|
+
|
75
|
+
existed_framework_folder.mkdir unless existed_framework_folder.exist?
|
76
|
+
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
|
77
|
+
|
78
|
+
# additions
|
79
|
+
missing = unchanged.reject { |pod_name| exsited_framework_pod_names.include?(pod_name) }
|
80
|
+
|
81
|
+
root_names_to_update = (added + changed + missing)
|
82
|
+
root_names_to_update += PodPrebuild::StateStore.cache_validation.missed
|
83
|
+
|
84
|
+
# transform names to targets
|
85
|
+
cache = []
|
86
|
+
targets = root_names_to_update.map do |pod_name|
|
87
|
+
tars = Pod.fast_get_targets_for_pod_name(pod_name, pod_targets, cache) || []
|
88
|
+
raise "There's no target named (#{pod_name}) in Pod.xcodeproj" if tars.empty?
|
89
|
+
|
90
|
+
tars
|
91
|
+
end.flatten
|
92
|
+
|
93
|
+
# add the dendencies
|
94
|
+
dependency_targets = targets.map(&:recursive_dependent_targets).flatten.uniq || []
|
95
|
+
targets = (targets + dependency_targets).uniq
|
96
|
+
else
|
97
|
+
UI.puts "Rebuild all frameworks"
|
98
|
+
targets = pod_targets
|
99
|
+
end
|
100
|
+
|
101
|
+
targets = targets.reject { |pod_target| should_not_prebuild_vendor_pod(pod_target.name) }
|
102
|
+
targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) } unless Podfile::DSL.dev_pods_enabled
|
103
|
+
|
104
|
+
# build!
|
105
|
+
Pod::UI.puts "Prebuild frameworks (total #{targets.count})"
|
106
|
+
Pod::UI.puts targets.map(&:name)
|
107
|
+
|
108
|
+
Pod::Prebuild.remove_build_dir(sandbox_path)
|
109
|
+
targets.each do |target|
|
110
|
+
unless target.should_build?
|
111
|
+
Pod::UI.puts "Skip prebuilding #{target.label} because of no source files".yellow
|
112
|
+
next
|
113
|
+
end
|
114
|
+
|
115
|
+
output_path = sandbox.framework_folder_path_for_target_name(target.name)
|
116
|
+
output_path.mkpath unless output_path.exist?
|
117
|
+
Pod::Prebuild.build(
|
118
|
+
sandbox_path,
|
119
|
+
target,
|
120
|
+
Pod::Podfile::DSL.prebuild_config,
|
121
|
+
output_path,
|
122
|
+
bitcode_enabled,
|
123
|
+
Pod::Podfile::DSL.custom_device_build_options,
|
124
|
+
Pod::Podfile::DSL.custom_simulator_build_options
|
125
|
+
)
|
126
|
+
collect_metadata(target, output_path)
|
127
|
+
end
|
128
|
+
Pod::Prebuild.remove_build_dir(sandbox_path)
|
129
|
+
|
130
|
+
# copy vendored libraries and frameworks
|
131
|
+
targets.each do |target|
|
132
|
+
root_path = sandbox.pod_dir(target.name)
|
133
|
+
target_folder = sandbox.framework_folder_path_for_target_name(target.name)
|
134
|
+
|
135
|
+
# If target shouldn't build, we copy all the original files
|
136
|
+
# This is for target with only .a and .h files
|
137
|
+
unless target.should_build?
|
138
|
+
Prebuild::Passer.target_names_to_skip_integration_framework << target.name
|
139
|
+
FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
target.spec_consumers.each do |consumer|
|
144
|
+
file_accessor = Sandbox::FileAccessor.new(root_path, consumer)
|
145
|
+
lib_paths = file_accessor.vendored_frameworks || []
|
146
|
+
lib_paths += file_accessor.vendored_libraries
|
147
|
+
# @TODO dSYM files
|
148
|
+
lib_paths.each do |lib_path|
|
149
|
+
relative = lib_path.relative_path_from(root_path)
|
150
|
+
destination = target_folder + relative
|
151
|
+
destination.dirname.mkpath unless destination.dirname.exist?
|
152
|
+
FileUtils.cp_r(lib_path, destination, :remove_destination => true)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# save the pod_name for prebuild framwork in sandbox
|
158
|
+
targets.each do |target|
|
159
|
+
sandbox.save_pod_name_for_target target
|
160
|
+
end
|
161
|
+
|
162
|
+
# Remove useless files
|
163
|
+
# remove useless pods
|
164
|
+
all_needed_names = pod_targets.map(&:name).uniq
|
165
|
+
useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
|
166
|
+
all_needed_names.include? name
|
167
|
+
end
|
168
|
+
useless_target_names.each do |name|
|
169
|
+
UI.puts "Remove: #{name}"
|
170
|
+
path = sandbox.framework_folder_path_for_target_name(name)
|
171
|
+
path.rmtree if path.exist?
|
172
|
+
end
|
173
|
+
|
174
|
+
if Podfile::DSL.dont_remove_source_code
|
175
|
+
# just remove the tmp files
|
176
|
+
path = sandbox.root + "Manifest.lock.tmp"
|
177
|
+
path.rmtree if path.exist?
|
178
|
+
else
|
179
|
+
# only keep manifest.lock and framework folder in _Prebuild
|
180
|
+
to_remain_files = ["Manifest.lock", File.basename(existed_framework_folder)]
|
181
|
+
to_delete_files = sandbox_path.children.reject { |file| to_remain_files.include?(File.basename(file)) }
|
182
|
+
to_delete_files.each { |file| file.rmtree if file.exist? }
|
183
|
+
end
|
184
|
+
|
185
|
+
updated_target_names = targets.map { |target| target.label.to_s }
|
186
|
+
deleted_target_names = useless_target_names
|
187
|
+
Pod::UI.puts "Targets to prebuild: #{updated_target_names}"
|
188
|
+
Pod::UI.puts "Targets to cleanup: #{deleted_target_names}"
|
189
|
+
|
190
|
+
prebuild_output.write_delta_file(updated_target_names, deleted_target_names)
|
191
|
+
prebuild_output.process_prebuilt_dev_pods
|
192
|
+
end
|
193
|
+
|
194
|
+
def clean_delta_file
|
195
|
+
prebuild_output.clean_delta_file
|
196
|
+
end
|
197
|
+
|
198
|
+
def collect_metadata(target, output_path)
|
199
|
+
metadata = PodPrebuild::Metadata.in_dir(output_path)
|
200
|
+
metadata.framework_name = target.framework_name
|
201
|
+
metadata.static_framework = target.static_framework?
|
202
|
+
resource_paths = target.resource_paths
|
203
|
+
metadata.resources = resource_paths.is_a?(Hash) ? resource_paths.values.flatten : resource_paths
|
204
|
+
metadata.resource_bundles = target
|
205
|
+
.file_accessors
|
206
|
+
.map { |f| f.resource_bundles.keys }
|
207
|
+
.flatten
|
208
|
+
.map { |name| "#{name}.bundle" }
|
209
|
+
metadata.build_settings = pods_project.targets
|
210
|
+
.detect { |native_target| native_target.name == target.name }
|
211
|
+
.build_configurations
|
212
|
+
.detect { |config| config.name == Pod::Podfile::DSL.prebuild_config }
|
213
|
+
.build_settings
|
214
|
+
metadata.save!
|
215
|
+
end
|
216
|
+
|
217
|
+
# patch the post install hook
|
218
|
+
old_method2 = instance_method(:run_plugins_post_install_hooks)
|
219
|
+
define_method(:run_plugins_post_install_hooks) do
|
220
|
+
old_method2.bind(self).call
|
221
|
+
prebuild_frameworks! if Pod.is_prebuild_stage && Pod::Podfile::DSL.prebuild_job?
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative "tool/tool"
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Podfile
|
5
|
+
module DSL
|
6
|
+
def config_cocoapods_binary_cache(options)
|
7
|
+
apply_config = lambda do |config|
|
8
|
+
DSL.send("#{config}=", options[config]) unless options[config].nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
apply_config.call(:prebuild_config)
|
12
|
+
apply_config.call(:prebuild_job)
|
13
|
+
apply_config.call(:prebuild_all) # TODO (thuyen): Revise this option
|
14
|
+
apply_config.call(:prebuild_all_vendor_pods)
|
15
|
+
apply_config.call(:excluded_pods)
|
16
|
+
apply_config.call(:dev_pods_enabled)
|
17
|
+
apply_config.call(:bitcode_enabled)
|
18
|
+
apply_config.call(:dont_remove_source_code)
|
19
|
+
apply_config.call(:custom_device_build_options)
|
20
|
+
apply_config.call(:custom_simulator_build_options)
|
21
|
+
apply_config.call(:save_cache_validation_to)
|
22
|
+
apply_config.call(:validate_prebuilt_settings)
|
23
|
+
end
|
24
|
+
|
25
|
+
@prebuild_config = "Debug"
|
26
|
+
@prebuild_job = false
|
27
|
+
@prebuild_all = false
|
28
|
+
@prebuild_all_vendor_pods = false
|
29
|
+
@excluded_pods = Set.new
|
30
|
+
@dev_pods_enabled = false
|
31
|
+
@bitcode_enabled = false
|
32
|
+
@dont_remove_source_code = false
|
33
|
+
@custom_device_build_options = []
|
34
|
+
@custom_simulator_build_options = []
|
35
|
+
@save_cache_validation_to = nil
|
36
|
+
# A proc to validate the provided build settings (per target) with the build settings of the prebuilt frameworks
|
37
|
+
# For example, in Podfile:
|
38
|
+
# -----------------------------------------------
|
39
|
+
# validate_prebuilt_settings do |target|
|
40
|
+
# settings = {}
|
41
|
+
# settings["MACH_O_TYPE"] == "staticlib"
|
42
|
+
# settings["SWIFT_VERSION"] == swift_version_of(target)
|
43
|
+
# settings
|
44
|
+
# end
|
45
|
+
# -----------------------------------------------
|
46
|
+
@validate_prebuilt_settings = nil
|
47
|
+
|
48
|
+
class << self
|
49
|
+
attr_accessor :prebuild_config
|
50
|
+
attr_accessor :prebuild_job
|
51
|
+
attr_accessor :prebuild_all
|
52
|
+
attr_accessor :prebuild_all_vendor_pods
|
53
|
+
attr_accessor :excluded_pods
|
54
|
+
attr_accessor :dev_pods_enabled
|
55
|
+
attr_accessor :bitcode_enabled
|
56
|
+
attr_accessor :dont_remove_source_code
|
57
|
+
attr_accessor :custom_device_build_options
|
58
|
+
attr_accessor :custom_simulator_build_options
|
59
|
+
attr_accessor :save_cache_validation_to
|
60
|
+
attr_accessor :validate_prebuilt_settings
|
61
|
+
|
62
|
+
alias prebuild_job? prebuild_job
|
63
|
+
alias prebuild_all? prebuild_all
|
64
|
+
alias prebuild_all_vendor_pods? prebuild_all_vendor_pods
|
65
|
+
alias dev_pods_enabled? dev_pods_enabled
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative "helper/passer"
|
2
|
+
require_relative "helper/podfile_options"
|
3
|
+
require_relative "helper/prebuild_sandbox"
|
4
|
+
|
5
|
+
Pod::HooksManager.register("cocoapods-binary-cache", :pre_install) do |installer_context|
|
6
|
+
PodPrebuild::PreInstallHook.new(installer_context).run
|
7
|
+
end
|
8
|
+
|
9
|
+
Pod::HooksManager.register("cocoapods-binary-cache", :post_install) do |installer_context|
|
10
|
+
PodPrebuild::PostInstallHook.new(installer_context).run
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Boris Bügling <boris@icculus.org>
|
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.
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'fourflusher'
|
2
|
+
require 'xcpretty' # TODO (thuyen): Revise this dependency
|
3
|
+
|
4
|
+
PLATFORMS = { 'iphonesimulator' => 'iOS',
|
5
|
+
'appletvsimulator' => 'tvOS',
|
6
|
+
'watchsimulator' => 'watchOS' }
|
7
|
+
|
8
|
+
# Build specific target to framework file
|
9
|
+
# @param [PodTarget] target
|
10
|
+
# a specific pod target
|
11
|
+
#
|
12
|
+
def build_for_iosish_platform(sandbox,
|
13
|
+
build_dir,
|
14
|
+
output_path,
|
15
|
+
target,
|
16
|
+
configuration,
|
17
|
+
device,
|
18
|
+
simulator,
|
19
|
+
bitcode_enabled,
|
20
|
+
custom_build_options = [], # Array<String>
|
21
|
+
custom_build_options_simulator = [], # Array<String>
|
22
|
+
enable_device_build = false
|
23
|
+
)
|
24
|
+
|
25
|
+
deployment_target = target.platform.deployment_target.to_s
|
26
|
+
|
27
|
+
target_label = target.label # name with platform if it's used in multiple platforms
|
28
|
+
Pod::UI.puts "Prebuilding #{target_label}..."
|
29
|
+
|
30
|
+
other_options = []
|
31
|
+
# bitcode enabled
|
32
|
+
other_options += ['BITCODE_GENERATION_MODE=bitcode'] if bitcode_enabled
|
33
|
+
# make less arch to iphone simulator for faster build
|
34
|
+
custom_build_options_simulator += ['ARCHS=x86_64', 'ONLY_ACTIVE_ARCH=NO'] if simulator == 'iphonesimulator'
|
35
|
+
|
36
|
+
# paths
|
37
|
+
target_name = target.name # equals target.label, like "AFNeworking-iOS" when AFNetworking is used in multiple platforms.
|
38
|
+
module_name = target.product_module_name
|
39
|
+
device_framework_path = "#{build_dir}/#{configuration}-#{device}/#{target_name}/#{module_name}.framework"
|
40
|
+
simulator_framework_path = "#{build_dir}/#{configuration}-#{simulator}/#{target_name}/#{module_name}.framework"
|
41
|
+
simulator_target_products_path = "#{build_dir}/#{configuration}-#{simulator}/#{target_name}"
|
42
|
+
|
43
|
+
if !Dir.exist?(simulator_framework_path)
|
44
|
+
is_succeed, = xcodebuild(
|
45
|
+
sandbox,
|
46
|
+
target_label,
|
47
|
+
configuration,
|
48
|
+
simulator,
|
49
|
+
deployment_target,
|
50
|
+
other_options + custom_build_options_simulator
|
51
|
+
)
|
52
|
+
raise "Build simulator framework failed: #{target_label}" unless is_succeed
|
53
|
+
else
|
54
|
+
puts "Simulator framework already exist at: #{simulator_framework_path}"
|
55
|
+
end
|
56
|
+
|
57
|
+
unless enable_device_build
|
58
|
+
FileUtils.cp_r Dir["#{simulator_target_products_path}/*"], output_path
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
if !Dir.exist?(device_framework_path)
|
63
|
+
is_succeed, = xcodebuild(
|
64
|
+
sandbox,
|
65
|
+
target_label,
|
66
|
+
configuration,
|
67
|
+
device,
|
68
|
+
deployment_target,
|
69
|
+
other_options + custom_build_options
|
70
|
+
)
|
71
|
+
raise "Build device framework failed: #{target_label}" unless is_succeed
|
72
|
+
else
|
73
|
+
puts "Device framework already exist at: #{device_framework_path}"
|
74
|
+
end
|
75
|
+
|
76
|
+
device_binary = device_framework_path + "/#{module_name}"
|
77
|
+
simulator_binary = simulator_framework_path + "/#{module_name}"
|
78
|
+
return unless File.file?(device_binary) && File.file?(simulator_binary)
|
79
|
+
|
80
|
+
# the device_lib path is the final output file path
|
81
|
+
# combine the binaries
|
82
|
+
tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
|
83
|
+
lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary} #{simulator_binary}`
|
84
|
+
puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
|
85
|
+
FileUtils.mv tmp_lipoed_binary_path, device_binary, :force => true
|
86
|
+
|
87
|
+
# collect the swiftmodule file for various archs.
|
88
|
+
device_swiftmodule_path = device_framework_path + "/Modules/#{module_name}.swiftmodule"
|
89
|
+
simulator_swiftmodule_path = simulator_framework_path + "/Modules/#{module_name}.swiftmodule"
|
90
|
+
if File.exist?(device_swiftmodule_path)
|
91
|
+
FileUtils.cp_r simulator_swiftmodule_path + "/.", device_swiftmodule_path
|
92
|
+
end
|
93
|
+
|
94
|
+
# combine the generated swift headers
|
95
|
+
# (In xcode 10.2, the generated swift headers vary for each archs)
|
96
|
+
# https://github.com/leavez/cocoapods-binary/issues/58
|
97
|
+
simulator_generated_swift_header_path = simulator_framework_path + "/Headers/#{module_name}-Swift.h"
|
98
|
+
device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
|
99
|
+
if File.exist? simulator_generated_swift_header_path
|
100
|
+
device_header = File.read(device_generated_swift_header_path)
|
101
|
+
simulator_header = File.read(simulator_generated_swift_header_path)
|
102
|
+
# https://github.com/Carthage/Carthage/issues/2718#issuecomment-473870461
|
103
|
+
combined_header_content = %Q{
|
104
|
+
#if TARGET_OS_SIMULATOR // merged by cocoapods-binary
|
105
|
+
|
106
|
+
#{simulator_header}
|
107
|
+
|
108
|
+
#else // merged by cocoapods-binary
|
109
|
+
|
110
|
+
#{device_header}
|
111
|
+
|
112
|
+
#endif // merged by cocoapods-binary
|
113
|
+
}
|
114
|
+
File.write(device_generated_swift_header_path, combined_header_content.strip)
|
115
|
+
end
|
116
|
+
|
117
|
+
# handle the dSYM files
|
118
|
+
device_dsym = "#{device_framework_path}.dSYM"
|
119
|
+
if File.exist? device_dsym
|
120
|
+
# lipo the simulator dsym
|
121
|
+
simulator_dsym = "#{simulator_framework_path}.dSYM"
|
122
|
+
if File.exist? simulator_dsym
|
123
|
+
tmp_lipoed_binary_path = "#{output_path}/#{module_name}.draft"
|
124
|
+
lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_dsym}/Contents/Resources/DWARF/#{module_name} #{simulator_dsym}/Contents/Resources/DWARF/#{module_name}`
|
125
|
+
puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
|
126
|
+
FileUtils.mv tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}", :force => true
|
127
|
+
end
|
128
|
+
# move
|
129
|
+
FileUtils.mv device_dsym, output_path, :force => true
|
130
|
+
end
|
131
|
+
|
132
|
+
# output
|
133
|
+
output_path.mkpath unless output_path.exist?
|
134
|
+
FileUtils.mv device_framework_path, output_path, :force => true
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
def xcodebuild(sandbox, target, configuration, sdk='macosx', deployment_target=nil, other_options=[])
|
139
|
+
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk} )
|
140
|
+
platform = PLATFORMS[sdk]
|
141
|
+
args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
|
142
|
+
args += other_options
|
143
|
+
|
144
|
+
args_str = args.join(" ")
|
145
|
+
cmd = "xcodebuild #{args_str} 2>&1"
|
146
|
+
puts "xcodebuild command: #{cmd}"
|
147
|
+
log = `#{cmd}`
|
148
|
+
|
149
|
+
exit_code = $?.exitstatus # Process::Status
|
150
|
+
is_succeed = (exit_code == 0)
|
151
|
+
|
152
|
+
if !is_succeed
|
153
|
+
begin
|
154
|
+
if log.include?('** BUILD FAILED **')
|
155
|
+
# use xcpretty to print build log
|
156
|
+
# 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
|
157
|
+
printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => 'auto'})
|
158
|
+
log.each_line do |line|
|
159
|
+
printer.pretty_print(line)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
raise "shouldn't be handle by xcpretty"
|
163
|
+
end
|
164
|
+
rescue
|
165
|
+
puts log.red
|
166
|
+
end
|
167
|
+
end
|
168
|
+
[is_succeed, log]
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
module Pod
|
174
|
+
class Prebuild
|
175
|
+
|
176
|
+
# Build the frameworks with sandbox and targets
|
177
|
+
#
|
178
|
+
# @param [String] sandbox_root_path
|
179
|
+
# The sandbox root path where the targets project place
|
180
|
+
#
|
181
|
+
# [PodTarget] target
|
182
|
+
# The pod targets to build
|
183
|
+
#
|
184
|
+
# [Pathname] output_path
|
185
|
+
# output path for generated frameworks
|
186
|
+
#
|
187
|
+
def self.build(sandbox_root_path, target, configuration, output_path, bitcode_enabled = false, custom_build_options=[], custom_build_options_simulator=[])
|
188
|
+
return if target.nil?
|
189
|
+
|
190
|
+
sandbox_root = Pathname(sandbox_root_path)
|
191
|
+
sandbox = Pod::Sandbox.new(sandbox_root)
|
192
|
+
build_dir = self.build_dir(sandbox_root)
|
193
|
+
|
194
|
+
# -- build the framework
|
195
|
+
case target.platform.name
|
196
|
+
when :ios
|
197
|
+
build_for_iosish_platform(
|
198
|
+
sandbox,
|
199
|
+
build_dir,
|
200
|
+
output_path,
|
201
|
+
target,
|
202
|
+
configuration,
|
203
|
+
"iphoneos",
|
204
|
+
"iphonesimulator",
|
205
|
+
bitcode_enabled,
|
206
|
+
custom_build_options,
|
207
|
+
custom_build_options_simulator
|
208
|
+
)
|
209
|
+
when :osx
|
210
|
+
xcodebuild(
|
211
|
+
sandbox,
|
212
|
+
target.label,
|
213
|
+
configuration,
|
214
|
+
"macosx",
|
215
|
+
nil,
|
216
|
+
custom_build_options
|
217
|
+
)
|
218
|
+
# when :tvos then build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator')
|
219
|
+
when :watchos
|
220
|
+
build_for_iosish_platform(
|
221
|
+
sandbox,
|
222
|
+
build_dir,
|
223
|
+
output_path,
|
224
|
+
target,
|
225
|
+
configuration,
|
226
|
+
"watchos",
|
227
|
+
"watchsimulator",
|
228
|
+
true,
|
229
|
+
custom_build_options,
|
230
|
+
custom_build_options_simulator
|
231
|
+
)
|
232
|
+
else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
|
233
|
+
|
234
|
+
raise Pod::Informative, "The build directory was not found in the expected location" unless build_dir.directory?
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.remove_build_dir(sandbox_root)
|
238
|
+
path = build_dir(sandbox_root)
|
239
|
+
path.rmtree if path.exist?
|
240
|
+
end
|
241
|
+
|
242
|
+
def self.build_dir(sandbox_root)
|
243
|
+
sandbox_root.parent + "build"
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|