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.

Answered by DTS Engineer in 364522022

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.

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.

Accepted Answer

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.

You likely did not remove the previous library from your build. Make sure it's cleared from Frameworks in the General tab as well as the Build Phase - Link with Binary Libraries.


I can assure you this will compile openssl for UIKitForMac.

@edford

Hi can you help me this error? I managed to build xcframework file ‘libjre_emul.xcframework’. My static library project includes ‘libjre_emul.xcframework’. Building the project with iOS device or simulator succeeds but for mac app I get a build error.


“error: Unable to find a suitable library in the XCFramework ‘libjre_emul.xcframework’ (in target ‘AirNote’)“.


In ‘libjre_emul.xcframework’ I included binary built for mac too.

As Xcode 11 is still in beta, you should make a note of the exact command line invocations you made, and open a bug report with those commands, the built xcframework you created, and how you are using the xcframework in a client application.

Hi @edford, is there a way to keep GENERATE_MASTER_OBJECT_FILE = YES for our static lib and build the project for UIKitForMac?

speaking fo xcodebuild: has anyone figured out yet how to build (a library or app) for the UIKit for Mac destination using xcodebuild? `-sdk` onkly lets me distinguish between "iphoneos" and "iphonesimulator" 😟.

My previous posted advice was to help people get started with Beta 1, as I talked to developers not able to build with that setting in the WWDC labs. In those cases, they also didn't have a real need for that setting to be enabled at all. If you have a real need for that build option to be available with UIKIt for Mac and it doesn't currently work for you with Beta 3, please open a feedback item.

I have the same issue while creating xcframework for my framework to support sdks - iphoneos , iphonesimulator and macos. I tried to do the same on macos catalina beta with xcode 11 beta 5.
I was able to create archive for sdks - iphoneos and iphoneSimulator but I am facing issues while using -sdk macos.
I getting error :


.... error: 'UIKit/UIKit.h' file not found

#import <UIKit/UIKit.h>

^

<unknown>:0: error: could not build Objective-C module 'MyFramework'


** ARCHIVE FAILED **


I searched and found that UIKit framework is only available for iOS and not for macos.
So, not sure how to achive this.
Really appreciate if someone can help here.


I tried adding the CFLAGS as you mentioned but it still failed.


The changes I have done is -

* added the CFLAGS=-target x86_64-apple-ios13.0-macabi

* I ran against the sdk - iPhoneSimulator

But it failed with the below mentioned error no matter which sdk I use :


ld: building for UIKitForMac, but linking in .tbd file (/Applications/Xcode11-beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/usr/lib/libSystem.tbd) built for iOS Simulator, file '/Applications/Xcode11-beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk/usr/lib/libSystem.tbd' for architecture x86_64


clang: error: linker command failed with exit code 1



And the similar error I get if i run it against iPhoneOS sdk.

I believe somewhere I have to specify the linking option but not sure where.


Can you please suggest what is wrong here? I am stuck at this place.



Thanks.

Hi.


For Xcode IDE GUI, I can successfully build the macOS Catalyst framework. The build settings works well.


But my use case is : How can I use `xcodebuild` command line, to do the same thing to build macOS Catalyst framwork ?


I've tried both of them:


- sdk: iphoenos, iphonesimulator, macosx (note there are no any oher SDK like maccatalyst)

- destination: 'platform=macOS,arch=x86_64,variant=Mac Catalyst' there is one interesting, but does not solve the problem

- CFLAGS="-target x86_64-apple-ios13.0-macabi", whether added or not does not cause anything different on product


Because for us, we need to combine all the individual framework into a XCFramework and automate our build pipeline. Build on Xcode GUI, drag and drop then run script, this is not way we want to do. Because it need `people manual do things`.


Hope for reply.

Hello! Did you manage to find a solution from building from cmd line using xcodebuild? If not, what worked for us was: xcodebuild -verbose clean build -project testprj.xcodeproj -scheme "testprj" -configuration "Debug" -destination 'platform=macOS,arch=x86_64,variant=Mac Catalyst' SKIP_INSTALL=NO Very important is to set the " -scheme" flag.

Built for macOS not UIKit for Mac
 
 
Q