Xcode 12 ProcessXCFramework fails to copy headers on build

I'm trying to build and run my app from Xcode 12 but the ProcessXCFramework step fails telling me that it could'n't copy the headers from my xcframework files :

Code Block
ProcessXCFramework /Users/username/xyz_no_spaces/libgpg-error.xcframework (in target 'MyApp' from project 'MyApp')
cd /Users/username/xyz_no_spaces/MyApp
builtin-process-xcframework --xcframework /Users/username/xyz_no_spaces/libgpg-error.xcframework --platform ios --target-path /Users/username/Library/Developer/Xcode/DerivedData/MyApp-gyqvfqslpvdvpubdhccubciywesh/Build/Products/Debug-iphoneos
error: “gpg-error.h” couldn’t be copied to “Debug-iphoneos” because an item with the same name already exists. (in target 'MyApp' from project 'MyApp')

Note: the file does not already exist at the target path (or maybe it's just deleted after it fails, I don't know..)
I get this message for all 6 of my xcframeworks which are all set to 'Do not embed'. Works fine on Xcode 11. So I guess it's either an Xcode 12 bug or I need to check a box somewhere when moving to 12.

I've tried removing the frameworks completely and re-adding them. Nuking the DerivedData folder and recompiling from scratch. No love. :(

Has anyone found a workaround for this?

In case my frameworks are somehow malformed (I did merge ios-x86_64-maccatalyst dylibs into them back in the day, but removing them makes no difference) maybe someone can spot what's wrong with this example file structure:

Code Block
libgpg-error.xcframework
Info.plist
ios-armv7_armv7s_arm64
Headers
gpg-error.h
libgpg-error.a
ios-i386_x86_64-simulator
Headers
gpg-error.h
libgpg-error.a
ios-x86_64-maccatalyst
Headers
gpg-error.h
libgpg-error.a

Lipo -info on all of the dylibs match the architectures in the folder names. (And has worked fine for the last year using Xcode 11.)
The info.plist:
Code Block <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-armv7_armv7s_arm64</string>
<key>LibraryPath</key>
<string>libgpg-error.a</string>
<key>SupportedArchitectures</key>
<array>
<string>armv7</string>
<string>armv7s</string>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
<dict>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-x86_64-maccatalyst</string>
<key>LibraryPath</key>
<string>libgpg-error.a</string>
<key>SupportedArchitectures</key>
<array>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>maccatalyst</string>
</dict>
<dict>
<key>HeadersPath</key>
<string>Headers</string>
<key>LibraryIdentifier</key>
<string>ios-i386_x86_64-simulator</string>
<key>LibraryPath</key>
<string>libgpg-error.a</string>
<key>SupportedArchitectures</key>
<array>
<string>i386</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>


Accepted Reply

This appears to be an issue for XCFrameworks that include headers, which, unfortunately, is likely to be most that use dynamic or static libraries. For Beta 1, the workaround is to:
  1. Remove (or change the name) of the "Headers" value in the Info.plist for all library entries.

  2. Add a custom user header search path via the Build Settings to point back into your XCFramework. If you have different headers per platform, you'll need to conditionalize each setting based on the SDK.

Building now will result in the expected behavior.

Replies

We ran into the same issue, and just found a workaround.
So in most of the cases, the header is located at MyFramework.xcframework/ios-arm64armv7armv7s/Headers/MyHeader.h. If your project includes another xcframework also containing MyHeader.h, you will get this copy header error.
The workaround is putting all the headers in a subfolder, for instance we can move the header to MyFramework.xcframework/ios-arm64armv7armv7s/Headers/*my*/MyHeader.h and AnotherFramework.xcframework/ios-arm64armv7armv7s/Headers/*another*/MyHeader.h, then during the build process there will no conflict any more.