Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 88 additions & 56 deletions lib/cocoapods-binary/Integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
require_relative 'helper/feature_switches'
require_relative 'helper/prebuild_sandbox'
require_relative 'helper/passer'
require_relative 'helper/names'



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

# make a symlink to target folder
prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
real_file_folder = prebuild_sandbox.framework_folder_path_for_pod_name(self.name)

target_folder = standard_sanbox.pod_dir(self.name)
target_folder.rmtree if target_folder.exist?
target_folder.mkdir

# make a relatvie symbol link for all children
# if spec used in multiple platforms, it may return multiple paths
target_names = prebuild_sandbox.existed_target_names_for_pod_name(self.name)

def walk(path, &action)
path.children.each do |child|
result = action.call(child, &action)
Expand All @@ -50,31 +48,51 @@ def mirror_with_symlink(source, basefolder, target_folder)
target = target_folder + source.relative_path_from(basefolder)
make_link(source, target)
end

# symbol link copy all substructure
walk(real_file_folder) do |child|
source = child
# only make symlink to file and `.framework` folder
if child.directory? and child.extname == ".framework"
mirror_with_symlink(source, real_file_folder, target_folder)
next false # return false means don't go deeper
elsif child.file?
mirror_with_symlink(source, real_file_folder, target_folder)
next true
else
next true
target_names.each do |name|

# symbol link copy all substructure
real_file_folder = prebuild_sandbox.framework_folder_path_for_target_name(name)

# If have only one platform, just place int the root folder of this pod.
# If have multiple paths, we use a sperated folder to store different
# platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework

target_folder = standard_sanbox.pod_dir(self.name)
if target_names.count > 1
target_folder += real_file_folder.basename
end
end
target_folder.rmtree if target_folder.exist?
target_folder.mkpath


walk(real_file_folder) do |child|
source = child
# only make symlink to file and `.framework` folder
if child.directory? and child.extname == ".framework"
mirror_with_symlink(source, real_file_folder, target_folder)
next false # return false means don't go deeper
elsif child.file?
mirror_with_symlink(source, real_file_folder, target_folder)
next true
else
next true
end
end


# symbol link copy resource for static framework
hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}
path_objects = hash[self.name]
if path_objects != nil
path_objects.each do |object|
make_link(object.real_file_path, object.target_file_path)
# symbol link copy resource for static framework
hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}

path_objects = hash[name]
if path_objects != nil
path_objects.each do |object|
make_link(object.real_file_path, object.target_file_path)
end
end
end
end
end # of for each

end # of method

end
end
Expand All @@ -95,7 +113,7 @@ def remove_target_files_if_needed
changes = Pod::Prebuild::Passer.prebuild_pods_changes
updated_names = []
if changes == nil
updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_names
updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_pod_names
else
added = changes.added
changed = changes.changed
Expand Down Expand Up @@ -127,45 +145,59 @@ def remove_target_files_if_needed

# call original
old_method2.bind(self).()
# ...
# ...
# ...
# after finishing the very complex orginal function


# check the prebuilt targets
targets = self.prebuild_pod_targets
targets_have_different_platforms = targets.select {|t| t.pod_name != t.name }
# check
self.validate_every_pod_only_have_one_form

if targets_have_different_platforms.count > 0
names = targets_have_different_platforms.map(&:pod_name)
STDERR.puts "[!] Binary doesn't support pods who integrate in 2 or more platforms simultaneously: #{names}".red
exit
end

# prepare
cache = []

def add_vendered_framework(spec, platform, added_framework_file_path)
if spec.attributes_hash[platform] == nil
spec.attributes_hash[platform] = {}
end
vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
vendored_frameworks = [vendored_frameworks] if vendored_frameworks.kind_of?(String)
vendored_frameworks += [added_framework_file_path]
spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
end
def empty_source_files(spec)
spec.attributes_hash["source_files"] = []
["ios", "watchos", "tvos", "osx"].each do |plat|
if spec.attributes_hash[plat] != nil
spec.attributes_hash[plat]["source_files"] = []
end
end
end

specs = self.analysis_result.specifications
prebuilt_specs = (specs.select do |spec|
self.prebuild_pod_names.include? spec.root.name
end)

# make sturcture to fast get target by name
name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
sum[target.name] = target
sum
end

prebuilt_specs.each do |spec|
# `spec` may be a subspec, so we use the root's name
root_name = spec.root.name

target = name_to_target_hash[root_name]
next if Prebuild::Passer.target_names_to_skip_integration_framework.include? target.pod_name

# use the prebuilt framework
original_vendored_frameworks = spec.attributes_hash["vendored_frameworks"] || []
if original_vendored_frameworks.kind_of?(String)
original_vendored_frameworks = [original_vendored_frameworks]
# Use the prebuild framworks as vendered frameworks
# get_corresponding_targets
targets = Pod.fast_get_targets_for_pod_name(spec.root.name, self.pod_targets, cache)
targets.each do |target|
# the framework_file_path rule is decided when `install_for_prebuild`,
# as to compitable with older version and be less wordy.
framework_file_path = target.framework_name
framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
end
original_vendored_frameworks += [target.framework_name]
spec.attributes_hash["vendored_frameworks"] = original_vendored_frameworks
spec.attributes_hash["source_files"] = []
# Clean the source files
# we just add the prebuilt framework to specific platform and set no source files
# for all platform, so it doesn't support the sence that 'a pod perbuild for one
# platform and not for another platform.'
empty_source_files(spec)

# to avoid the warning of missing license
spec.attributes_hash["license"] = {}
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods-binary/Main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def keep_source_code_for_prebuilt_frameworks!
# check user_framework is on
podfile = installer_context.podfile
podfile.target_definition_list.each do |target_definition|
next if target_definition.prebuild_framework_names.empty?
next if target_definition.prebuild_framework_pod_names.empty?
if not target_definition.uses_frameworks?
STDERR.puts "[!] Cocoapods-binary requires `use_frameworks!`".red
exit
Expand Down
41 changes: 21 additions & 20 deletions lib/cocoapods-binary/Prebuild.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,9 @@ def have_exact_prebuild_cache?
unchanged = changes.unchanged
deleted = changes.deleted

unchange_framework_names = (added + unchanged)

exsited_framework_names = sandbox.exsited_framework_names
exsited_framework_pod_names = sandbox.exsited_framework_pod_names
missing = unchanged.select do |pod_name|
not exsited_framework_names.include?(pod_name)
not exsited_framework_pod_names.include?(pod_name)
end

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

existed_framework_folder.mkdir unless existed_framework_folder.exist?
exsited_framework_names = sandbox.exsited_framework_names
exsited_framework_pod_names = sandbox.exsited_framework_pod_names

# additions
missing = unchanged.select do |pod_name|
not exsited_framework_names.include?(pod_name)
not exsited_framework_pod_names.include?(pod_name)
end


root_names_to_update = (added + changed + missing)

# transform names to targets
name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
sum[target.name] = target
sum
end
targets = root_names_to_update.map do |root_name|
name_to_target_hash[root_name]
end || []
cache = []
targets = root_names_to_update.map do |pod_name|
Pod.fast_get_targets_for_pod_name(pod_name, self.pod_targets, cache)
end.flatten

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

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

Expand All @@ -134,19 +129,20 @@ def prebuild_frameworks!
end
Prebuild::Passer.resources_to_copy_for_static_framework[target.name] = path_objects
end

end
Pod::Prebuild.remove_build_dir(sandbox_path)


# copy vendored libraries and frameworks
targets.each do |target|
root_path = self.sandbox.pod_dir(target.name)
target_folder = sandbox.framework_folder_path_for_pod_name(target.name)
target_folder = sandbox.framework_folder_path_for_target_name(target.name)

# If target shouldn't build, we copy all the original files
# This is for target with only .a and .h files
if not target.should_build?
Prebuild::Passer.target_names_to_skip_integration_framework << target.pod_name
Prebuild::Passer.target_names_to_skip_integration_framework << target.name
FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
next
end
Expand All @@ -164,15 +160,20 @@ def prebuild_frameworks!
end
end
end

# save the pod_name for prebuild framwork in sandbox
targets.each do |target|
sandbox.save_pod_name_for_target target
end

# Remove useless files
# remove useless pods
all_needed_names = self.pod_targets.map(&:name).uniq
useless_names = sandbox.exsited_framework_names.reject do |name|
useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
all_needed_names.include? name
end
useless_names.each do |name|
path = sandbox.framework_folder_path_for_pod_name(name)
useless_target_names.each do |name|
path = sandbox.framework_folder_path_for_target_name(name)
path.rmtree if path.exist?
end

Expand Down
5 changes: 0 additions & 5 deletions lib/cocoapods-binary/helper/feature_switches.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ def self.enable_prebuild_patch(value)
end

if should_prebuild and (not local)
if current_target_definition.platform == :watchos
# watchos isn't supported currently
Pod::UI.warn "Binary doesn't support watchos currently: #{name}. You can manually set `binary => false` for this pod to suppress this warning."
return
end
old_method.bind(self).(name, *args)
end
end
Expand Down
Loading