cocoapods-precompile 0.1.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 +7 -0
- data/.gitignore +32 -0
- data/.travis.yml +23 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +75 -0
- data/Rakefile +13 -0
- data/cocoapods-precompile.gemspec +26 -0
- data/lib/cocoapods-binary/Integration.rb +266 -0
- data/lib/cocoapods-binary/Main.rb +110 -0
- data/lib/cocoapods-binary/Prebuild.rb +212 -0
- data/lib/cocoapods-binary/gem_version.rb +3 -0
- data/lib/cocoapods-binary/helper/feature_switches.rb +97 -0
- data/lib/cocoapods-binary/helper/names.rb +78 -0
- data/lib/cocoapods-binary/helper/passer.rb +41 -0
- data/lib/cocoapods-binary/helper/podfile_options.rb +130 -0
- data/lib/cocoapods-binary/helper/prebuild_sandbox.rb +73 -0
- data/lib/cocoapods-binary/rome/build_framework.rb +138 -0
- data/lib/cocoapods-binary/tool/tool.rb +12 -0
- data/lib/cocoapods-precompile.rb +1 -0
- data/lib/cocoapods_plugin.rb +2 -0
- data/spec/spec_helper.rb +50 -0
- metadata +130 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../tool/tool'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Prebuild
|
5
|
+
|
6
|
+
# Pass the data between the 2 steps
|
7
|
+
#
|
8
|
+
# At step 2, the normal pod install, it needs some info of the
|
9
|
+
# prebuilt step. So we store it here.
|
10
|
+
#
|
11
|
+
class Passer
|
12
|
+
|
13
|
+
# indicate the add/remove/update of prebuit pods
|
14
|
+
# @return [Analyzer::SpecsState]
|
15
|
+
#
|
16
|
+
class_attr_accessor :prebuild_pods_changes
|
17
|
+
|
18
|
+
|
19
|
+
# represent the path of resurces to copy
|
20
|
+
class ResourcePath
|
21
|
+
attr_accessor :real_file_path
|
22
|
+
attr_accessor :target_file_path
|
23
|
+
end
|
24
|
+
# Save the resoures for static framework, and used when installing the prebuild framework
|
25
|
+
# static framework needs copy the resurces mannully
|
26
|
+
#
|
27
|
+
# @return [Hash<String, [Passer::ResourcePath]>]
|
28
|
+
class_attr_accessor :resources_to_copy_for_static_framework
|
29
|
+
self.resources_to_copy_for_static_framework = {}
|
30
|
+
|
31
|
+
# Some pod won't be build in prebuild stage even if it have `binary=>true`.
|
32
|
+
# The targets of this pods have `oshould_build? == true`.
|
33
|
+
# We should skip integration (patch spec) for this pods
|
34
|
+
#
|
35
|
+
# @return [Array<String>]
|
36
|
+
class_attr_accessor :target_names_to_skip_integration_framework
|
37
|
+
self.target_names_to_skip_integration_framework = []
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Pod
|
2
|
+
|
3
|
+
class Prebuild
|
4
|
+
def self.keyword
|
5
|
+
:binary
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Podfile
|
10
|
+
class TargetDefinition
|
11
|
+
|
12
|
+
## --- option for setting using prebuild framework ---
|
13
|
+
def parse_prebuild_framework(name, requirements)
|
14
|
+
|
15
|
+
should_prebuild = Pod::Podfile::DSL.prebuild_all
|
16
|
+
|
17
|
+
options = requirements.last
|
18
|
+
if options.is_a?(Hash) && options[Pod::Prebuild.keyword] != nil
|
19
|
+
should_prebuild = options.delete(Pod::Prebuild.keyword)
|
20
|
+
requirements.pop if options.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
pod_name = Specification.root_name(name)
|
24
|
+
set_prebuild_for_pod(pod_name, should_prebuild)
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_prebuild_for_pod(pod_name, should_prebuild)
|
28
|
+
|
29
|
+
if should_prebuild == true
|
30
|
+
@prebuild_framework_pod_names ||= []
|
31
|
+
@prebuild_framework_pod_names.push pod_name
|
32
|
+
else
|
33
|
+
@should_not_prebuild_framework_pod_names ||= []
|
34
|
+
@should_not_prebuild_framework_pod_names.push pod_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def prebuild_framework_pod_names
|
39
|
+
names = @prebuild_framework_pod_names || []
|
40
|
+
if parent != nil and parent.kind_of? TargetDefinition
|
41
|
+
names += parent.prebuild_framework_pod_names
|
42
|
+
end
|
43
|
+
names
|
44
|
+
end
|
45
|
+
def should_not_prebuild_framework_pod_names
|
46
|
+
names = @should_not_prebuild_framework_pod_names || []
|
47
|
+
if parent != nil and parent.kind_of? TargetDefinition
|
48
|
+
names += parent.should_not_prebuild_framework_pod_names
|
49
|
+
end
|
50
|
+
names
|
51
|
+
end
|
52
|
+
|
53
|
+
# ---- patch method ----
|
54
|
+
# We want modify `store_pod` method, but it's hard to insert a line in the
|
55
|
+
# implementation. So we patch a method called in `store_pod`.
|
56
|
+
old_method = instance_method(:parse_inhibit_warnings)
|
57
|
+
|
58
|
+
define_method(:parse_inhibit_warnings) do |name, requirements|
|
59
|
+
parse_prebuild_framework(name, requirements)
|
60
|
+
old_method.bind(self).(name, requirements)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
module Pod
|
69
|
+
class Installer
|
70
|
+
|
71
|
+
def prebuild_pod_targets
|
72
|
+
@prebuild_pod_targets ||= (
|
73
|
+
all = []
|
74
|
+
|
75
|
+
aggregate_targets = self.aggregate_targets
|
76
|
+
aggregate_targets.each do |aggregate_target|
|
77
|
+
target_definition = aggregate_target.target_definition
|
78
|
+
targets = aggregate_target.pod_targets || []
|
79
|
+
|
80
|
+
# filter prebuild
|
81
|
+
prebuild_names = target_definition.prebuild_framework_pod_names
|
82
|
+
if not Podfile::DSL.prebuild_all
|
83
|
+
targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) }
|
84
|
+
end
|
85
|
+
dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
|
86
|
+
targets = (targets + dependency_targets).uniq
|
87
|
+
|
88
|
+
# filter should not prebuild
|
89
|
+
explict_should_not_names = target_definition.should_not_prebuild_framework_pod_names
|
90
|
+
targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) }
|
91
|
+
|
92
|
+
all += targets
|
93
|
+
end
|
94
|
+
|
95
|
+
all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
|
96
|
+
all.uniq
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# the root names who needs prebuild, including dependency pods.
|
101
|
+
def prebuild_pod_names
|
102
|
+
@prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def validate_every_pod_only_have_one_form
|
107
|
+
|
108
|
+
multi_targets_pods = self.pod_targets.group_by do |t|
|
109
|
+
t.pod_name
|
110
|
+
end.select do |k, v|
|
111
|
+
v.map{|t| t.platform.name }.count > 1
|
112
|
+
end
|
113
|
+
|
114
|
+
multi_targets_pods = multi_targets_pods.reject do |name, targets|
|
115
|
+
contained = targets.map{|t| self.prebuild_pod_targets.include? t }
|
116
|
+
contained.uniq.count == 1 # all equal
|
117
|
+
end
|
118
|
+
|
119
|
+
return if multi_targets_pods.empty?
|
120
|
+
|
121
|
+
warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
|
122
|
+
warnings += multi_targets_pods.map{|name, targets| " #{name}: #{targets.map{|t|t.platform.name}}"}.join("\n")
|
123
|
+
raise Informative, warnings
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative "names"
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class PrebuildSandbox < Sandbox
|
5
|
+
|
6
|
+
# [String] standard_sandbox_path
|
7
|
+
def self.from_standard_sanbox_path(path)
|
8
|
+
prebuild_sandbox_path = Pathname.new(path).realpath + "_Prebuild"
|
9
|
+
self.new(prebuild_sandbox_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_standard_sandbox(sandbox)
|
13
|
+
self.from_standard_sanbox_path(sandbox.root)
|
14
|
+
end
|
15
|
+
|
16
|
+
def standard_sanbox_path
|
17
|
+
self.root.parent
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate_framework_path
|
21
|
+
self.root + "GeneratedFrameworks"
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param name [String] pass the target.name (may containing platform suffix)
|
25
|
+
# @return [Pathname] the folder containing the framework file.
|
26
|
+
def framework_folder_path_for_target_name(name)
|
27
|
+
self.generate_framework_path + name
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def exsited_framework_target_names
|
32
|
+
exsited_framework_name_pairs.map {|pair| pair[0]}.uniq
|
33
|
+
end
|
34
|
+
def exsited_framework_pod_names
|
35
|
+
exsited_framework_name_pairs.map {|pair| pair[1]}.uniq
|
36
|
+
end
|
37
|
+
def existed_target_names_for_pod_name(pod_name)
|
38
|
+
exsited_framework_name_pairs.select {|pair| pair[1] == pod_name }.map { |pair| pair[0]}
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
def save_pod_name_for_target(target)
|
44
|
+
folder = framework_folder_path_for_target_name(target.name)
|
45
|
+
return unless folder.exist?
|
46
|
+
flag_file_path = folder + "#{target.pod_name}.pod_name"
|
47
|
+
File.write(flag_file_path.to_s, "")
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def pod_name_for_target_folder(target_folder_path)
|
54
|
+
name = Pathname.new(target_folder_path).children.find do |child|
|
55
|
+
child.to_s.end_with? ".pod_name"
|
56
|
+
end
|
57
|
+
name = name.basename(".pod_name").to_s unless name.nil?
|
58
|
+
name ||= Pathname.new(target_folder_path).basename.to_s # for compatibility with older version
|
59
|
+
end
|
60
|
+
|
61
|
+
# Array<[target_name, pod_name]>
|
62
|
+
def exsited_framework_name_pairs
|
63
|
+
return [] unless generate_framework_path.exist?
|
64
|
+
generate_framework_path.children().map do |framework_path|
|
65
|
+
if framework_path.directory? && (not framework_path.children.empty?)
|
66
|
+
[framework_path.basename.to_s, pod_name_for_target_folder(framework_path)]
|
67
|
+
else
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end.reject(&:nil?).uniq
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'fourflusher'
|
2
|
+
|
3
|
+
CONFIGURATION = "Release"
|
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
|
+
device,
|
17
|
+
simulator,
|
18
|
+
bitcode_enabled,
|
19
|
+
simulator_default_arch)
|
20
|
+
|
21
|
+
deployment_target = target.platform.deployment_target.to_s
|
22
|
+
|
23
|
+
target_label = target.label # name with platform if it's used in multiple platforms
|
24
|
+
Pod::UI.puts "Prebuilding #{target_label}..."
|
25
|
+
|
26
|
+
other_options = []
|
27
|
+
if bitcode_enabled
|
28
|
+
other_options += ['OTHER_CFLAGS="-fembed-bitcode"']
|
29
|
+
end
|
30
|
+
xcodebuild(sandbox, target_label, device, deployment_target, other_options)
|
31
|
+
xcodebuild(sandbox, target_label, simulator, deployment_target, other_options + ["ARCHS=#{simulator_default_arch}",'ONLY_ACTIVE_ARCH=NO'])
|
32
|
+
|
33
|
+
# paths
|
34
|
+
target_name = target.name # equals target.label, like "AFNeworking-iOS" when AFNetworking is used in multiple platforms.
|
35
|
+
module_name = target.product_module_name
|
36
|
+
device_framwork_path = "#{build_dir}/#{CONFIGURATION}-#{device}/#{target_name}/#{module_name}.framework"
|
37
|
+
simulator_framwork_path = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{target_name}/#{module_name}.framework"
|
38
|
+
|
39
|
+
device_binary = device_framwork_path + "/#{module_name}"
|
40
|
+
simulator_binary = simulator_framwork_path + "/#{module_name}"
|
41
|
+
return unless File.file?(device_binary) && File.file?(simulator_binary)
|
42
|
+
|
43
|
+
# the device_lib path is the final output file path
|
44
|
+
# combine the bianries
|
45
|
+
tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
|
46
|
+
lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary} #{simulator_binary}`
|
47
|
+
puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
|
48
|
+
FileUtils.mv tmp_lipoed_binary_path, device_binary, :force => true
|
49
|
+
|
50
|
+
# collect the swiftmodule file for various archs.
|
51
|
+
device_swiftmodule_path = device_framwork_path + "/Modules/#{module_name}.swiftmodule"
|
52
|
+
simulator_swiftmodule_path = simulator_framwork_path + "/Modules/#{module_name}.swiftmodule"
|
53
|
+
if File.exist?(device_swiftmodule_path)
|
54
|
+
FileUtils.cp_r simulator_swiftmodule_path + "/.", device_swiftmodule_path
|
55
|
+
end
|
56
|
+
|
57
|
+
# output
|
58
|
+
output_path.mkpath unless output_path.exist?
|
59
|
+
FileUtils.mv device_framwork_path, output_path, :force => true
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil, other_options=[])
|
64
|
+
args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{CONFIGURATION} -sdk #{sdk} )
|
65
|
+
platform = PLATFORMS[sdk]
|
66
|
+
args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
|
67
|
+
args += other_options
|
68
|
+
Pod::Executable.execute_command 'xcodebuild', args, true
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
module Pod
|
74
|
+
class Prebuild
|
75
|
+
|
76
|
+
# Build the frameworks with sandbox and targets
|
77
|
+
#
|
78
|
+
# @param [String] sandbox_root_path
|
79
|
+
# The sandbox root path where the targets project place
|
80
|
+
#
|
81
|
+
# [PodTarget] target
|
82
|
+
# The pod targets to build
|
83
|
+
#
|
84
|
+
# [Pathname] output_path
|
85
|
+
# output path for generated frameworks
|
86
|
+
#
|
87
|
+
def self.build(sandbox_root_path, target, output_path, bitcode_enabled = false)
|
88
|
+
|
89
|
+
return unless not target == nil
|
90
|
+
|
91
|
+
sandbox_root = Pathname(sandbox_root_path)
|
92
|
+
sandbox = Pod::Sandbox.new(sandbox_root)
|
93
|
+
build_dir = self.build_dir(sandbox_root)
|
94
|
+
|
95
|
+
# -- build the framework
|
96
|
+
case target.platform.name
|
97
|
+
when :ios then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'iphoneos', 'iphonesimulator', bitcode_enabled, "x86_64")
|
98
|
+
when :osx then xcodebuild(sandbox, target.label)
|
99
|
+
# when :tvos then build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator')
|
100
|
+
when :watchos then build_for_iosish_platform(sandbox, build_dir, output_path, target, 'watchos', 'watchsimulator', true, "i386")
|
101
|
+
else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
|
102
|
+
|
103
|
+
raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?
|
104
|
+
|
105
|
+
# # --- copy the vendored libraries and framework
|
106
|
+
# frameworks = build_dir.children.select{ |path| File.extname(path) == ".framework" }
|
107
|
+
# Pod::UI.puts "Built #{frameworks.count} #{'frameworks'.pluralize(frameworks.count)}"
|
108
|
+
|
109
|
+
# pod_target = target
|
110
|
+
# consumer = pod_target.root_spec.consumer(pod_target.platform.name)
|
111
|
+
# file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(pod_target.pod_name), consumer)
|
112
|
+
# frameworks += file_accessor.vendored_libraries
|
113
|
+
# frameworks += file_accessor.vendored_frameworks
|
114
|
+
|
115
|
+
# frameworks.uniq!
|
116
|
+
|
117
|
+
# frameworks.each do |framework|
|
118
|
+
# FileUtils.mkdir_p destination
|
119
|
+
# FileUtils.cp_r framework, destination, :remove_destination => true
|
120
|
+
# end
|
121
|
+
# build_dir.rmtree if build_dir.directory?
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.remove_build_dir(sandbox_root)
|
125
|
+
path = build_dir(sandbox_root)
|
126
|
+
path.rmtree if path.exist?
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def self.build_dir(sandbox_root)
|
132
|
+
# don't know why xcode chose this folder
|
133
|
+
sandbox_root.parent + 'build'
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-binary/gem_version'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
ROOT = Pathname.new(File.expand_path('../../', __FILE__))
|
3
|
+
$:.unshift((ROOT + 'lib').to_s)
|
4
|
+
$:.unshift((ROOT + 'spec').to_s)
|
5
|
+
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'bacon'
|
8
|
+
require 'mocha-on-bacon'
|
9
|
+
require 'pretty_bacon'
|
10
|
+
require 'pathname'
|
11
|
+
require 'cocoapods'
|
12
|
+
|
13
|
+
Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
14
|
+
|
15
|
+
require 'cocoapods_plugin'
|
16
|
+
|
17
|
+
#-----------------------------------------------------------------------------#
|
18
|
+
|
19
|
+
module Pod
|
20
|
+
|
21
|
+
# Disable the wrapping so the output is deterministic in the tests.
|
22
|
+
#
|
23
|
+
UI.disable_wrap = true
|
24
|
+
|
25
|
+
# Redirects the messages to an internal store.
|
26
|
+
#
|
27
|
+
module UI
|
28
|
+
@output = ''
|
29
|
+
@warnings = ''
|
30
|
+
|
31
|
+
class << self
|
32
|
+
attr_accessor :output
|
33
|
+
attr_accessor :warnings
|
34
|
+
|
35
|
+
def puts(message = '')
|
36
|
+
@output << "#{message}\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
def warn(message = '', actions = [])
|
40
|
+
@warnings << "#{message}\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
def print(message)
|
44
|
+
@output << message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
#-----------------------------------------------------------------------------#
|