Skip to content

Commit cfc63e1

Browse files
authored
Merge pull request leavez#26 from leavez/watch
support multiple platform simultaneously (e.g. watchOS and iOS)
2 parents c44e490 + 589bc22 commit cfc63e1

File tree

25 files changed

+997
-132
lines changed

25 files changed

+997
-132
lines changed

lib/cocoapods-binary/Integration.rb

Lines changed: 88 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
require_relative 'helper/feature_switches'
33
require_relative 'helper/prebuild_sandbox'
44
require_relative 'helper/passer'
5+
require_relative 'helper/names'
6+
57

68

79
# NOTE:
@@ -24,13 +26,9 @@ def install_for_prebuild!(standard_sanbox)
2426

2527
# make a symlink to target folder
2628
prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
27-
real_file_folder = prebuild_sandbox.framework_folder_path_for_pod_name(self.name)
28-
29-
target_folder = standard_sanbox.pod_dir(self.name)
30-
target_folder.rmtree if target_folder.exist?
31-
target_folder.mkdir
32-
33-
# make a relatvie symbol link for all children
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+
3432
def walk(path, &action)
3533
path.children.each do |child|
3634
result = action.call(child, &action)
@@ -50,31 +48,51 @@ def mirror_with_symlink(source, basefolder, target_folder)
5048
target = target_folder + source.relative_path_from(basefolder)
5149
make_link(source, target)
5250
end
53-
54-
# symbol link copy all substructure
55-
walk(real_file_folder) do |child|
56-
source = child
57-
# only make symlink to file and `.framework` folder
58-
if child.directory? and child.extname == ".framework"
59-
mirror_with_symlink(source, real_file_folder, target_folder)
60-
next false # return false means don't go deeper
61-
elsif child.file?
62-
mirror_with_symlink(source, real_file_folder, target_folder)
63-
next true
64-
else
65-
next true
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
6664
end
67-
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+
6883

69-
# symbol link copy resource for static framework
70-
hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}
71-
path_objects = hash[self.name]
72-
if path_objects != nil
73-
path_objects.each do |object|
74-
make_link(object.real_file_path, object.target_file_path)
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
7592
end
76-
end
77-
end
93+
end # of for each
94+
95+
end # of method
7896

7997
end
8098
end
@@ -95,7 +113,7 @@ def remove_target_files_if_needed
95113
changes = Pod::Prebuild::Passer.prebuild_pods_changes
96114
updated_names = []
97115
if changes == nil
98-
updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_names
116+
updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_pod_names
99117
else
100118
added = changes.added
101119
changed = changes.changed
@@ -127,45 +145,59 @@ def remove_target_files_if_needed
127145

128146
# call original
129147
old_method2.bind(self).()
148+
# ...
149+
# ...
150+
# ...
151+
# after finishing the very complex orginal function
130152

131153

132-
# check the prebuilt targets
133-
targets = self.prebuild_pod_targets
134-
targets_have_different_platforms = targets.select {|t| t.pod_name != t.name }
154+
# check
155+
self.validate_every_pod_only_have_one_form
135156

136-
if targets_have_different_platforms.count > 0
137-
names = targets_have_different_platforms.map(&:pod_name)
138-
STDERR.puts "[!] Binary doesn't support pods who integrate in 2 or more platforms simultaneously: #{names}".red
139-
exit
140-
end
157+
158+
# prepare
159+
cache = []
141160

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
142178

143179
specs = self.analysis_result.specifications
144180
prebuilt_specs = (specs.select do |spec|
145181
self.prebuild_pod_names.include? spec.root.name
146182
end)
147-
148-
# make sturcture to fast get target by name
149-
name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
150-
sum[target.name] = target
151-
sum
152-
end
153183

154184
prebuilt_specs.each do |spec|
155-
# `spec` may be a subspec, so we use the root's name
156-
root_name = spec.root.name
157-
158-
target = name_to_target_hash[root_name]
159-
next if Prebuild::Passer.target_names_to_skip_integration_framework.include? target.pod_name
160185

161-
# use the prebuilt framework
162-
original_vendored_frameworks = spec.attributes_hash["vendored_frameworks"] || []
163-
if original_vendored_frameworks.kind_of?(String)
164-
original_vendored_frameworks = [original_vendored_frameworks]
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)
165195
end
166-
original_vendored_frameworks += [target.framework_name]
167-
spec.attributes_hash["vendored_frameworks"] = original_vendored_frameworks
168-
spec.attributes_hash["source_files"] = []
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)
169201

170202
# to avoid the warning of missing license
171203
spec.attributes_hash["license"] = {}

lib/cocoapods-binary/Main.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def keep_source_code_for_prebuilt_frameworks!
4848
# check user_framework is on
4949
podfile = installer_context.podfile
5050
podfile.target_definition_list.each do |target_definition|
51-
next if target_definition.prebuild_framework_names.empty?
51+
next if target_definition.prebuild_framework_pod_names.empty?
5252
if not target_definition.uses_frameworks?
5353
STDERR.puts "[!] Cocoapods-binary requires `use_frameworks!`".red
5454
exit

lib/cocoapods-binary/Prebuild.rb

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ def have_exact_prebuild_cache?
4343
unchanged = changes.unchanged
4444
deleted = changes.deleted
4545

46-
unchange_framework_names = (added + unchanged)
47-
48-
exsited_framework_names = sandbox.exsited_framework_names
46+
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
4947
missing = unchanged.select do |pod_name|
50-
not exsited_framework_names.include?(pod_name)
48+
not exsited_framework_pod_names.include?(pod_name)
5149
end
5250

5351
needed = (added + changed + deleted + missing)
@@ -58,7 +56,7 @@ def have_exact_prebuild_cache?
5856
# The install method when have completed cache
5957
def install_when_cache_hit!
6058
# just print log
61-
self.sandbox.exsited_framework_names.each do |name|
59+
self.sandbox.exsited_framework_target_names.each do |name|
6260
UI.puts "Using #{name}"
6361
end
6462
end
@@ -82,24 +80,21 @@ def prebuild_frameworks!
8280
deleted = changes.deleted
8381

8482
existed_framework_folder.mkdir unless existed_framework_folder.exist?
85-
exsited_framework_names = sandbox.exsited_framework_names
83+
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
8684

8785
# additions
8886
missing = unchanged.select do |pod_name|
89-
not exsited_framework_names.include?(pod_name)
87+
not exsited_framework_pod_names.include?(pod_name)
9088
end
9189

9290

9391
root_names_to_update = (added + changed + missing)
9492

9593
# transform names to targets
96-
name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
97-
sum[target.name] = target
98-
sum
99-
end
100-
targets = root_names_to_update.map do |root_name|
101-
name_to_target_hash[root_name]
102-
end || []
94+
cache = []
95+
targets = root_names_to_update.map do |pod_name|
96+
Pod.fast_get_targets_for_pod_name(pod_name, self.pod_targets, cache)
97+
end.flatten
10398

10499
# add the dendencies
105100
dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
@@ -117,8 +112,8 @@ def prebuild_frameworks!
117112
Pod::Prebuild.remove_build_dir(sandbox_path)
118113
targets.each do |target|
119114
next unless target.should_build?
115+
output_path = sandbox.framework_folder_path_for_target_name(target.name)
120116

121-
output_path = sandbox.framework_folder_path_for_pod_name(target.name)
122117
output_path.mkpath unless output_path.exist?
123118
Pod::Prebuild.build(sandbox_path, target, output_path, bitcode_enabled)
124119

@@ -134,19 +129,20 @@ def prebuild_frameworks!
134129
end
135130
Prebuild::Passer.resources_to_copy_for_static_framework[target.name] = path_objects
136131
end
132+
137133
end
138134
Pod::Prebuild.remove_build_dir(sandbox_path)
139135

140136

141137
# copy vendored libraries and frameworks
142138
targets.each do |target|
143139
root_path = self.sandbox.pod_dir(target.name)
144-
target_folder = sandbox.framework_folder_path_for_pod_name(target.name)
140+
target_folder = sandbox.framework_folder_path_for_target_name(target.name)
145141

146142
# If target shouldn't build, we copy all the original files
147143
# This is for target with only .a and .h files
148144
if not target.should_build?
149-
Prebuild::Passer.target_names_to_skip_integration_framework << target.pod_name
145+
Prebuild::Passer.target_names_to_skip_integration_framework << target.name
150146
FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
151147
next
152148
end
@@ -164,15 +160,20 @@ def prebuild_frameworks!
164160
end
165161
end
166162
end
163+
164+
# save the pod_name for prebuild framwork in sandbox
165+
targets.each do |target|
166+
sandbox.save_pod_name_for_target target
167+
end
167168

168169
# Remove useless files
169170
# remove useless pods
170171
all_needed_names = self.pod_targets.map(&:name).uniq
171-
useless_names = sandbox.exsited_framework_names.reject do |name|
172+
useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
172173
all_needed_names.include? name
173174
end
174-
useless_names.each do |name|
175-
path = sandbox.framework_folder_path_for_pod_name(name)
175+
useless_target_names.each do |name|
176+
path = sandbox.framework_folder_path_for_target_name(name)
176177
path.rmtree if path.exist?
177178
end
178179

lib/cocoapods-binary/helper/feature_switches.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ def self.enable_prebuild_patch(value)
3838
end
3939

4040
if should_prebuild and (not local)
41-
if current_target_definition.platform == :watchos
42-
# watchos isn't supported currently
43-
Pod::UI.warn "Binary doesn't support watchos currently: #{name}. You can manually set `binary => false` for this pod to suppress this warning."
44-
return
45-
end
4641
old_method.bind(self).(name, *args)
4742
end
4843
end

0 commit comments

Comments
 (0)