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

Probably a bug in Xcode 12; will file a Radar.

Eventually I got it to build and run by copying the headers for each framework to the ..../DerivedData/MyApp-gyqvfqslpvdvpubdhccubciywesh/Build/Products/Debug-iphoneos/include folder manually.

If anyone has a solid workaround I'd love to hear it!
Exact same problem on Xcode 12.0 beta (12A6159). Fails very early in the target that uses an XCFramework, and I checked, there's no duplicate for that file (only referenced once). I suspect a bug in the build system.

My log for reference:

Code Block
ProcessXCFramework /xxxxxxx/xxxxxxx.xcframework (in target 'xxxxxxx' from project 'xxxxxxx')
    cd /xxxxxx
    builtin-process-xcframework --xcframework /xxxxxxx/xxxxxxx.xcframework --platform ios --target-path /xxxxxxx/Build/Products/Debug-iphoneos
error: “xxxxxxx.h” couldn’t be copied to “Debug-iphoneos” because an item with the same name already exists. (in target 'xxxxxxx' from project 'xxxxxxx')


Thank you for reporting this issue. I can confirm that I can reproduce and we will be taking a look at the underlying issue.
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.
Just tested Xcode 12.0 beta 2 (12A6163b), same problem.
Xcode 12.0 beta 2 (12A6163b) still have this issue. What version do you plan to solve ?

same issue for me :/
Experiencing the same issue with my project. I have 4 XCFrameworks in my code. If I compile 5 times, it gets past the ProcessXCFramework errors, but then of course it fails finding headers after that. It basically once for each framework. I believe it is looking for the .a file of the library, which gets copied correctly, before it moves on to the next one.
This is fixed in Xcode Beta 3
This is still happening in Xcode Version 12.0 beta 4 (12A8179i).

The ProcessXCFramework step seems to copy the Header directory from each of our XCFrameworks into the same Build/Products/Release/include directory, apparently overwriting the headers from one XCFramework with those of the next.

I'm not sure why Xcode would even need to create a temporary build copy of the contents of the XCFramework Header directory at all. That seems odd.

  • Still stuck this issue in Xcode 14.2: trying to use 2 XCframeworks for different open-source libraries, oless and qpdf, each provided a header file Types.h (different content). Could anybody please provide a solution?

Add a Comment
This is still happening in Xcode 12.0 beta 6 (12A8189n).

I have filed a report on Feedback Assistant.
Checking build settings option "Build Libraries for Distribution" to YES and running archive fixed the issue for me on Xcode Version 12.0 beta 6 (12A8189n)
This is such a bad bug that is still not fixed as of Xcode 12.0.1!
Update: Also completely busted for Xcode 12.2 (Beta 2).

This is such a ridiculous issue! This on top of the code signing and copying issues with binary targets make them completely unusable for production. Such a shame.
Still seeing this issue on 12.2 (12B45b)