Built for macOS not UIKit for Mac

Hi


I've started looking at running my iPad app in macOS 10.15 using Xcode 11. I've run through the steps to add Mac support but when I build it complains that some of the libraries I use at link time are compiled for macOS and not "UIKit for Mac". Surely they are both x64 architecture so I'm slightly confused. I can't find any documentation about this - does anyone have any idea on how I would rebuild these libraries so that they are supported?


Thanks,

Mike.

Accepted Reply

Libraries coming into the UIKit for Mac environment need to be compiled for the iOS platform, not the macOS platform. You may need to alter your Base SDK setting to reflect this. Some other helpful notes:

  • Ensure that the VALID_ARCHS and ARCHS settings are their defaults and not overridden. Overriding these settings can prevent the build from selecting the right architecture for your build.
  • Ensure Perform Single Object Pre-Link is the default value of No (GENERATE_MASTER_OBJECT_FILE is the raw setting name)


When analyzing build settings, I like to use the All | Levels view in Xcode, in order to see a grid of levels where a setting is located, annotated with a green box around the level where the setting is overridden. When I say let these settings be their default value, I mean that the green highlight should be on the Default column in this view and not any other level unless you have a clear reason for overriding any of these.


If you are looking at this grid for a specific target, you can clear a setting at this level by selecting the setting row and pressing the Delete key. If you need to clear a setting at the project level, you should select the project instead of a specific target in the list on the left side of the setting grid, and clear the overridden setting from there.

Replies

Same problem. It looks from the release notes that we're supposed to build something called an "XCFramework". However, there is no documentation on such a thing, and it is not part of the XCode target templates. I think the idea is to take all the architecture-specific library files or framework files (libfoo.a for intel, libfoo.a for arm, etc), and then build some kind of package containing all the architectures. The appropriate architectures are in my project, but it is looking for a "UIKit for Mac" version even though these libraries are architecturally way below UIKit and thus not relevant to it. I'm presuming we need a "XCFramework" to work around this limitation. At this point only random guesswork with xcodebuild seems like the way to do that, but hopefully some session later this week will reveal the magic command here.

I have not been sucessful yet, but here's the command. There's a wwdc session on Thursday, June 6th, 3:00pm PST. Hopefully the answers are coming in this session, but I'm going to a lab today. I have to get OpenSSL working.


$ xcodebuild -create-xcframework -help

OVERVIEW: Utility for packaging multiple build configurations of a given library or framework into a single xcframework.


USAGE:

xcodebuild -create-xcframework -framework <path> [-framework <path>...] -output <path>

xcodebuild -create-xcframework -library <path> [-headers <path>] [-library <path> [-headers <path>]...] -output <path>


OPTIONS:

-framework <path> Adds a framework from the given <path>.

-library <path> Adds a static or dynamic library from the given <path>.

-headers <path> Adds the headers from the given <path>. Only applicable with -library.

-output <path> The <path> to write the xcframework to.

-help Show this help content.Chriss-MacBook-Pro:~ cvbuskirk$

I gave this a try yesterday by putting one of my dynamic x64 libraries in an xcframework but got a similiar error when adding it in to the link phase. Fingers crossed you're right and we get more info tomorrow!

Oddly, the information on XCFramework was not in a UIKitForMac talk, but instead in the "Binary Frameworks for Swift" talk even though this whole thing has nothing whatsoever to do with Swift.


Anyway, I'm working on OpenSSL and ffmpeg will be next. The problem is that the create XCFramework command is not smart enough to figure out what to do if you pass it existing multi-architecture binaries (the way XCode 10 required) – it actuallu errors out. So have to go back through the build scripts and rip out the last 7 years of improvements along those lines and make sure every single arch is a separate .a file. At least that's what I think is needed, not really sure until it runs and works.

-create-xcframework is either buggy or I'm doing it wrong, but since it isn't documented, there's no way to know what error 8 is. I've also encountered error 9 fwiw. Fortunately, the raw build script output each architecture, but seems create-xcframework doesn't like it.


xcodebuild -create-xcframework -library ~/src/OpenSSL-for-iPhone-master/bin/iPhoneOS12.2-arm64.sdk/lib/libcrypto.a -library ~/src/OpenSSL-for-iPhone-master/bin/iPhoneOS12.2-armv7.sdk/lib/libcrypto.a -headers ~/src/OpenSSL-for-iPhone-master/bin/iPhoneOS12.2-arm64.sdk/include/openssl -output ~/Desktop/libcrypto.xcframework


The operation couldn’t be completed. (XCBCore.XCFrameworkValidationError error 8.)


Note that reducing the number of architectures to 1 in the above call does succeed.

There is some work being done on OpenSSL.


https://github.com/krzyzanowskim/OpenSSL/issues/60

Reading up on few posts out there, I was able to compile crypto and ssl for x86_64 (uikitformac) by adding to CFLAGS "-target x86_64-apple-ios13.0-macabi". It seems we also have to sign the binaries, which was fine. However I'm looking for a way to exclude this from simulator builds. I don't currently see a way to specify this for an xcframework. Has anyone found a way to do this?

Would you share with us your script to compile and sign?

I ended up not using an xcframework after all, just linking different libs based on SDK which is what I was previously doing. So the necessary pieces were compiling openssl for UIKitForMac, and then code signing.


To compile I added to the openssl macOS Configure scripts, under the darwin64-x86_64-cc variant (10-main.conf). I added "CFLAGS => add("-target x86_64-apple-ios13.0-macabi")". Though you could create a new variant just for this.


To sign, I used the codesign utility, "codesign --sign <SHA-1> <lib>". The sha was from my Apple Developer certificate, and I believe that needs to align with the code signing identity for the target.

Thanks for this - works perfectly!! Now to try and make my app not look awful in macOS!! 🙂

That didn't work for me with OpenSSL 1.1.1c. The error from Xcode says it was Built for macOS not UIKit for Mac (as before).


Though, even if it had worked, it would have only solved building. It seems we need either an XCFramework, or all 9 or so variants (the many ARM architectures, simulators, iOS/tvOS, Bitcode, UIKitForMac) bundled up otool fat binary style (not sure that is possible, but it used to work great until 2 weeks ago).


And then this whole silliness needs to be repeated for every other library.

Libraries coming into the UIKit for Mac environment need to be compiled for the iOS platform, not the macOS platform. You may need to alter your Base SDK setting to reflect this. Some other helpful notes:

  • Ensure that the VALID_ARCHS and ARCHS settings are their defaults and not overridden. Overriding these settings can prevent the build from selecting the right architecture for your build.
  • Ensure Perform Single Object Pre-Link is the default value of No (GENERATE_MASTER_OBJECT_FILE is the raw setting name)


When analyzing build settings, I like to use the All | Levels view in Xcode, in order to see a grid of levels where a setting is located, annotated with a green box around the level where the setting is overridden. When I say let these settings be their default value, I mean that the green highlight should be on the Default column in this view and not any other level unless you have a clear reason for overriding any of these.


If you are looking at this grid for a specific target, you can clear a setting at this level by selecting the setting row and pressing the Delete key. If you need to clear a setting at the project level, you should select the project instead of a specific target in the list on the left side of the setting grid, and clear the overridden setting from there.

Problem. Confirmed that lipo cannot combine multiple same-architectures in the same library even if they have a different target (lipo x86-64 with x86-64/x86_64-apple-ios13.0-macabi is not allowed).


Problem. Including multiple same-name libraries in Xcode only shows 1 copy in the project Libraries settings so you can't specify for instance this copy of libcrypto.a is for iOS and this copy is for uikitformac.


Thus, I assume the libaries need to be combined with XCFramework in a way that 'xcodebuild -create-xcframework' currently errors out with error 8 or 9.


The "correct" answer marked above is referring to libraries built with Xcode which is not the topic of this thread (see previous references to OpenSSL, ffmpeg is also a good example, many more). The only solution apparent right now is to use XCFramework in a way that is not currently documented, and xcodebuild does not seem to generate the needed format right now per previous messages in this thread.


One path forward right now might be to create an XCFramework by hand using the pieces of xcodebuild that do work as a guide.

Agreed the selected Apple provided answer is wrong for this thread, and you are right about xcframework seemingly the only way to get this done. I can't seem to get past errors as well.


Another thought is using Cocoapods and their vendored frameworks, but I'm already seeing push back against that.


What Apple needs to do is fix xcframeworks or proivde some kind of decent documentation for us to adopt it.

re: "The "correct" answer marked above is referring to libraries built with Xcode which is not the topic of this thread"


If you're referring to my answer, that's incorrect. I compiled openssl via the configure script (external to Xcode) by modifying the target per my comments. I was able to successfully compile openssl for UIKitForMac, not macOS.


The only issue I found was that it seems like we can't be selective about xcframeworks in terms of excluding them from the simulator. My current solution works as long as I don't intend to release a macOS app, which should remain true since running iPad on Mac covers what I need.