Skip to content

Commit

Permalink
Merge pull request CocoaPods#10826 from dnkoutso/unique_output_xcfram…
Browse files Browse the repository at this point in the history
…ework_path

Place frameworks from xcframeworks into a unique folder name to avoid duplicate outputs.
  • Loading branch information
dnkoutso committed Jul 30, 2021
2 parents 07ee195 + 24c151f commit 7b53ec8
Show file tree
Hide file tree
Showing 17 changed files with 61 additions and 32 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -80,6 +80,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`

##### Bug Fixes

* Place frameworks from xcframeworks into a unique folder name to avoid duplicate outputs.
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#10106](https://github.com/CocoaPods/CocoaPods/issues/10106)

* Update pod in Pods folder when changing the pod from branch to version in Podfie.
[gonghonglou](https://github.com/gonghonglou)
[#10825](https://github.com/CocoaPods/CocoaPods/pull/10825)
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods/generator/copy_xcframework_script.rb
Expand Up @@ -218,7 +218,7 @@ def shell_escape(value)
def install_xcframework_args(xcframework, slices)
root = xcframework.path
args = [shell_escape("${PODS_ROOT}/#{root.relative_path_from(sandbox_root)}")]
args << shell_escape(xcframework.name)
args << shell_escape(xcframework.target_name)
is_framework = xcframework.build_type.framework?
args << shell_escape(is_framework ? 'framework' : 'library')
slices.each do |slice|
Expand Down
3 changes: 2 additions & 1 deletion lib/cocoapods/generator/embed_frameworks_script.rb
Expand Up @@ -159,8 +159,9 @@ def script
end
xcframeworks_by_config.each do |config, xcframeworks|
xcframeworks.select { |xcf| xcf.build_type.dynamic_framework? }.each do |xcframework|
target_name = xcframework.target_name
name = xcframework.name
contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{name}/#{name}.framework"\n)
contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{target_name}/#{name}.framework"\n)
end
end
script << "\n" unless contents_by_config.empty?
Expand Down
Expand Up @@ -183,7 +183,7 @@ def add_copy_xcframeworks_script_phase(native_target)
output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}"
output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path)
output_paths_by_config[output_paths_key] = xcframeworks.map do |xcf|
"#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcf.name}"
"#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcf.target_name}"
end
end

Expand Down
13 changes: 8 additions & 5 deletions lib/cocoapods/sandbox/file_accessor.rb
Expand Up @@ -177,7 +177,7 @@ def vendored_dynamic_frameworks
#
def vendored_static_xcframeworks
vendored_xcframeworks.select do |path|
Xcode::XCFramework.new(path).build_type == BuildType.static_framework
Xcode::XCFramework.new(spec.name, path).build_type == BuildType.static_framework
end
end

Expand Down Expand Up @@ -239,14 +239,17 @@ def self.vendored_frameworks_headers(framework)
Pathname.glob(headers_dir + '**/' + GLOB_PATTERNS[:public_header_files])
end

# @param [Pathname] framework
# @param [String] target_name
# The target name this .xcframework belongs to
#
# @param [Pathname] framework_path
# The path to the .xcframework
#
# @return [Array<Pathname>] The paths to all the headers included in the
# vendored xcframework
#
def self.vendored_xcframework_headers(framework)
xcframework = Xcode::XCFramework.new(framework)
def self.vendored_xcframework_headers(target_name, framework_path)
xcframework = Xcode::XCFramework.new(target_name, framework_path)
xcframework.slices.flat_map do |slice|
vendored_frameworks_headers(slice.path)
end
Expand All @@ -260,7 +263,7 @@ def vendored_frameworks_headers
self.class.vendored_frameworks_headers(framework)
end.uniq
paths.concat Array.new(vendored_xcframeworks.flat_map do |framework|
self.class.vendored_xcframework_headers(framework)
self.class.vendored_xcframework_headers(spec.name, framework)
end)
paths
end
Expand Down
12 changes: 7 additions & 5 deletions lib/cocoapods/target/build_settings.rb
Expand Up @@ -140,12 +140,12 @@ def self.define_build_settings_method(method_name, build_setting: false,
end
private_class_method :define_build_settings_method

# @param [XCFramework] xcframework the xcframework thats slice will be copied to the intermediates dir
# @param [XCFramework] xcframework the xcframework slice that will be copied to the intermediates dir
#
# @return [String] the path to the directory containing the xcframework slice
#
def self.xcframework_intermediate_dir(xcframework)
"#{XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcframework.name}"
"#{XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcframework.target_name}"
end

class << self
Expand Down Expand Up @@ -508,12 +508,14 @@ def select_maximal_pod_targets(pod_targets)
pod_targets - subset_targets
end

# @param [String] target_name the name of the target this xcframework belongs to
#
# @param [Pathname,String] path the path to the xcframework bundle
#
# @return [Xcode::XCFramework] the xcframework at the given path
#
def load_xcframework(path)
Xcode::XCFramework.new(path)
def load_xcframework(target_name, path)
Xcode::XCFramework.new(target_name, path)
end

# A subclass that generates build settings for a {PodTarget}
Expand Down Expand Up @@ -735,7 +737,7 @@ def initialize(target, non_library_spec = nil, configuration: nil)

# @return [Array<Xcode::XCFramework>]
define_build_settings_method :vendored_xcframeworks, :memoized => true do
file_accessors.flat_map(&:vendored_xcframeworks).map { |path| load_xcframework(path) }
file_accessors.flat_map(&:vendored_xcframeworks).map { |path| load_xcframework(target.label, path) }
end

# @return [Array<String>]
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods/target/pod_target.rb
Expand Up @@ -443,7 +443,7 @@ def xcframeworks
@xcframeworks ||= begin
file_accessors.each_with_object({}) do |file_accessor, hash|
frameworks = file_accessor.vendored_xcframeworks.map do |framework_path|
Xcode::XCFramework.new(framework_path)
Xcode::XCFramework.new(label, framework_path)
end
hash[file_accessor.spec.name] = frameworks
end
Expand Down
11 changes: 8 additions & 3 deletions lib/cocoapods/xcode/xcframework.rb
Expand Up @@ -5,6 +5,10 @@
module Pod
module Xcode
class XCFramework
# @return [String] target_name the target name this XCFramework belongs to
#
attr_reader :target_name

# @return [Pathname] path the path to the .xcframework on disk
#
attr_reader :path
Expand All @@ -23,12 +27,13 @@ class XCFramework

# Initializes an XCFramework instance with a path on disk
#
# @param [Pathname, String] path
# The path to the .xcframework on disk
# @param [String] target_name @see target_name
# @param [Pathname, String] path @see path
#
# @return [XCFramework] the xcframework at the given path
#
def initialize(path)
def initialize(target_name, path)
@target_name = target_name
@path = Pathname.new(path).tap do |p|
raise 'Absolute path is required' unless p.absolute?
end
Expand Down
2 changes: 1 addition & 1 deletion spec/cocoapods-integration-specs
Submodule cocoapods-integration-specs updated 28 files
+1 −1 ...ibrary_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks-output-files.xcfilelist
+1 −1 ...all_vendored_static_library_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks.sh
+2 −2 install_vendored_static_library_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.debug.xcconfig
+2 −2 ...ll_vendored_static_library_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig
+2 −2 ...ed_static_library_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.debug.xcconfig
+2 −2 ..._static_library_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.release.xcconfig
+2 −2 ...work/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.debug.xcconfig
+2 −2 ...rk/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.release.xcconfig
+1 −1 ...static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks-output-files.xcfilelist
+1 −1 install_vendored_static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks.sh
+1 −1 install_vendored_static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.debug.xcconfig
+1 −1 install_vendored_static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig
+1 −1 ...l_vendored_static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.debug.xcconfig
+1 −1 ...vendored_static_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.release.xcconfig
+1 −1 ...work/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.debug.xcconfig
+1 −1 ...rk/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.release.xcconfig
+2 −2 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-Unit-Tests-frameworks.sh
+1 −1 ...ndored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks-output-files.xcfilelist
+1 −1 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib-xcframeworks.sh
+1 −1 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.debug.xcconfig
+1 −1 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig
+1 −1 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.debug.xcconfig
+1 −1 install_vendored_xcframework/after/Pods/Target Support Files/BananaLib/BananaLib.unit-tests.release.xcconfig
+1 −1 ...pport Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration-frameworks-Debug-input-files.xcfilelist
+1 −1 ...ort Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration-frameworks-Release-input-files.xcfilelist
+2 −2 ...ework/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration-frameworks.sh
+1 −1 ...work/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.debug.xcconfig
+1 −1 ...rk/after/Pods/Target Support Files/Pods-XCFrameworkIntegration/Pods-XCFrameworkIntegration.release.xcconfig
6 changes: 3 additions & 3 deletions spec/unit/generator/copy_xcframeworks_script_spec.rb
Expand Up @@ -3,15 +3,15 @@
module Pod
describe CopyXCFrameworksScript = Generator::CopyXCFrameworksScript do
it 'installs xcframeworks' do
xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))
xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))
generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.ios)
generator.send(:script).should.include <<-SH.strip_heredoc
install_xcframework "${PODS_ROOT}/../../spec/fixtures/CoconutLib.xcframework" "CoconutLib" "framework" "ios-armv7_arm64" "ios-i386_x86_64-simulator"
SH
end

it 'installs xcframeworks using the correct platform' do
xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))
xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))
generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.macos)
generator.send(:script).should.include <<-SH.strip_heredoc
install_xcframework "${PODS_ROOT}/../../spec/fixtures/CoconutLib.xcframework" "CoconutLib" "framework" "macos-x86_64"
Expand All @@ -31,7 +31,7 @@ module Pod
end

it 'does not embed static frameworks' do
xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))
xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))
generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.ios)
Xcode::LinkageAnalyzer.stubs(:dynamic_binary?).returns(false)
# Second argument to `install_xcframework` is a boolean indicating whether to embed the framework
Expand Down
13 changes: 12 additions & 1 deletion spec/unit/generator/embed_frameworks_script_spec.rb
Expand Up @@ -54,7 +54,7 @@ module Pod
end

it 'installs intermediate XCFramework slices' do
xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))
xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))
generator = Pod::Generator::EmbedFrameworksScript.new({}, 'Debug' => [xcframework])
result = generator.send(:script)
result.should.include <<-SH.strip_heredoc
Expand All @@ -63,5 +63,16 @@ module Pod
fi
SH
end

it 'installs intermediate XCFramework slices based on the correct target name and framework name' do
xcframework = Xcode::XCFramework.new('SomeLib', fixture('CoconutLib.xcframework'))
generator = Pod::Generator::EmbedFrameworksScript.new({}, 'Debug' => [xcframework])
result = generator.send(:script)
result.should.include <<-SH.strip_heredoc
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${PODS_XCFRAMEWORKS_BUILD_DIR}/SomeLib/CoconutLib.framework"
fi
SH
end
end
end
Expand Up @@ -815,7 +815,7 @@ module Pod
Xcode::FrameworkPaths.new('${BUILT_PRODUCTS_DIR}/ReleaseCompiledFramework/CompiledFramework.framework'),
]
xcframeworks = [
Xcode::XCFramework.new(fixture('CoconutLib.xcframework')),
Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')),
]
xcframeworks[0].stubs(:build_type).returns(BuildType.dynamic_framework)
TargetIntegrator.embed_frameworks_output_paths(paths, xcframeworks).sort.should == %w(
Expand All @@ -827,7 +827,7 @@ module Pod

it 'does not include static xcframeworks in the embed frameworks output paths' do
xcframeworks = [
Xcode::XCFramework.new(fixture('CoconutLib.xcframework')),
Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')),
]
xcframeworks[0].stubs(:build_type).returns(BuildType.static_framework)
TargetIntegrator.embed_frameworks_output_paths([], xcframeworks).should == []
Expand Down
Expand Up @@ -1854,14 +1854,14 @@ class PodsProjectGenerator

describe 'xcframeworks' do
it 'raises if a vendored xcframework has slices of mixed linkage' do
@pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))])
@pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))])
Pod::Xcode::LinkageAnalyzer.stubs(:dynamic_binary?).returns(true, false, true, false, true, false, true)
e = ->() { @installer.install! }.should.raise Informative
e.message.should.include? 'Unable to install vendored xcframework `CoconutLib` for Pod `BananaLib`, because it contains both static and dynamic frameworks.'
end

it 'raises if a vendored xcframework is empty' do
xcframework = Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))
xcframework = Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))
xcframework.stubs(:slices).returns([])
@pod_target.stubs(:xcframeworks).returns('Debug' => [xcframework])
e = ->() { @installer.install! }.should.raise Informative
Expand Down Expand Up @@ -1893,7 +1893,7 @@ class PodsProjectGenerator
end

it 'creates the copy xcframeworks script phase if needed' do
@pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))])
@pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))])
@installer.expects(:create_copy_xcframeworks_script).once
@installer.install!
end
Expand Down
Expand Up @@ -144,7 +144,7 @@ class PodTargetIntegrator
resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle']
@watermelon_pod_target.stubs(:framework_paths).returns('WatermelonLib' => framework_paths)
@watermelon_pod_target.stubs(:resource_paths).returns('WatermelonLib' => resource_paths)
@watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))])
@watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))])
test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [],
:shell_script_build_phases => [], :project => @project,
:name => 'WatermelonLib-Unit-Tests')
Expand Down Expand Up @@ -176,7 +176,7 @@ class PodTargetIntegrator
resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle']
@watermelon_pod_target.stubs(:framework_paths).returns('WatermelonLib' => framework_paths)
@watermelon_pod_target.stubs(:resource_paths).returns('WatermelonLib' => resource_paths)
@watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))])
@watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))])
test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [],
:shell_script_build_phases => [], :project => @project,
:name => 'WatermelonLib-Unit-Tests')
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/target/aggregate_target_spec.rb
Expand Up @@ -49,7 +49,7 @@ module Pod

it 'returns whether it has xcframeworks to embed' do
@target.stubs(:xcframeworks_by_config).returns(
'DEBUG' => [Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))],
'DEBUG' => [Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))],
)
@target.includes_xcframeworks?.should.be.true
@target.stubs(:xcframeworks_by_config).returns('DEBUG' => [], 'RELEASE' => [])
Expand Down
Expand Up @@ -221,6 +221,7 @@ def pod_target(spec, target_definition)
:spec => spec,
)
xcframework = stub('xcframework',
:target_name => 'PodTarget',
:name => 'VendoredXCFramework',
:build_type => BuildType.static_library,
:slices => [stub('slice', :binary_path => Pathname.new('/tmp/path/to/libVendoredXCFramework.a'))],
Expand Down Expand Up @@ -255,6 +256,7 @@ def pod_target(spec, target_definition)
:uses_swift? => false,
:build_product_path => 'BPP',
:product_basename => 'PodTarget',
:label => 'PodTarget',
:target_definitions => [target_definition],
:root_spec => spec,
)
Expand Down
5 changes: 3 additions & 2 deletions spec/unit/xcode/xcframework_spec.rb
Expand Up @@ -7,9 +7,10 @@ module Xcode
describe 'when parsing `Info.plist`' do
before do
@framework_path = fixture('CoconutLib.xcframework')
@framework = XCFramework.new(@framework_path)
@framework = XCFramework.new('CoconutLib', @framework_path)
end

# shit
it 'reads the format version' do
@framework.format_version.should == Pod::Version.new('1.0')
end
Expand Down Expand Up @@ -85,7 +86,7 @@ module Xcode
describe 'library packaging' do
before do
@framework_path = fixture('xcframeworks/StaticLibrary/CoconutLib.xcframework')
@framework = XCFramework.new(@framework_path)
@framework = XCFramework.new('CoconutLib', @framework_path)
end

it 'reads the library slices' do
Expand Down

0 comments on commit 7b53ec8

Please sign in to comment.