Last active
September 14, 2021 19:50
-
-
Save wojciech-kulik/e2470d8280b5ca4cf81201205fd2bffc to your computer and use it in GitHub Desktop.
Duplicated frameworks remover
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# DuplicatedFrameworksRemover.rb | |
# Created by Wojciech Kulik on 14/09/2021. | |
# | |
# Description: | |
# This code fixes warnings caused by linking the same frameworks in multiple targets. | |
# | |
# Sample warning: "objc[1111]: Class XXXX is implemented in both path/FrameworkName1 and path/FrameworkName2. | |
# One of the two will be used. Which one is undefined." | |
# Usage: | |
# - Put this file next to your Podfile | |
# - Add in the Podfile: | |
# load 'DuplicatedFrameworksRemover.rb' | |
# | |
# post_install do |installer| | |
# remove_duplicated_frameworks('Pods-YourMainTargetName', installer) | |
# end | |
def remove_duplicated_frameworks(app_pod_name, installer) | |
test_targets = get_test_targets(app_pod_name, installer) | |
puts "Detected test targets: #{test_targets}" | |
puts "Removing duplicated frameworks from OTHER_LDFLAGS" | |
targets = installer.aggregate_targets.select { |x| !test_targets.include?(x.name) } | |
# Checks each pair of targets if they have common pods. Duplicates are removed from the first one's xcconfig. | |
for i in 0..targets.size-1 do | |
target = targets[i] | |
remainingAppPodTargets = targets[i+1..targets.size-1].flat_map(&:pod_targets) | |
target.xcconfigs.each do |config_name, config_file| | |
# Removes all frameworks which exist in other pods | |
remainingAppPodTargets | |
.flat_map { |pod_target| get_framework_names(pod_target) } | |
.each { |framework| config_file.frameworks.delete(framework) } | |
# Saves updated xcconfig | |
xcconfig_path = target.xcconfig_path(config_name) | |
config_file.save_as(xcconfig_path) | |
end | |
end | |
end | |
def get_test_targets(app_pod_name, installer) | |
installer.aggregate_targets | |
.find { |x| x.name == app_pod_name } | |
.user_project | |
.targets | |
.select { |x| is_test_target(x) } | |
.map { |x| "Pods-#{x}" } | |
.uniq | |
end | |
def is_test_target(target) | |
target.build_configurations.any? do |config| | |
target.build_settings(config.name)["TEST_TARGET_NAME"] != nil | |
end | |
end | |
def get_framework_names(pod_target) | |
frameworkNames = pod_target.specs.flat_map do |spec| | |
# We should take framework names from 'vendored_frameworks'. | |
# If it's not defined, we use 'spec.name' instead. | |
# | |
# spec.name can be defined like Framework/Something - we take the first part | |
# because that's what appears in OTHER_LDFLAGS. | |
frameworkPaths = unless spec.attributes_hash['ios'].nil? | |
then spec.attributes_hash['ios']['vendored_frameworks'] | |
else spec.attributes_hash['vendored_frameworks'] | |
end || [spec.name.split(/\//, 2).first] | |
map_paths_to_filenames(frameworkPaths) | |
end | |
frameworkNames.uniq | |
end | |
def map_paths_to_filenames(paths) | |
Array(paths).map(&:to_s).map do |filename| | |
extension = File.extname filename | |
File.basename filename, extension | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment