How to get the true macOS version in a x86_64 app built with an outdated macOS SDK running on an Apple Silicon mac? - macos

I'm working on an app that, due to restrictions that are beyond my control, is being built as an x86_64 app using an outdated macOS SDK (in this case the macOS 10.15 SDK).
It runs fine on an Apple Silicon mac using Rosetta 2, but the app needs to get the current version of macOS, and the available APIs lie to it under these conditions, consistently reporting the version is 10.16 when really it should be macOS 11.x or 12.x.
In other circumstances where the system API lies, I've been able to get the real info using sysctl, but in this case calling sysctlbyname("kern.osproductversion", ...) still lies to my app and reports 10.16.
How can I get the true version of macOS under these circumstances?

The only solution I've found so far is to launch the sysctl command line utility as a separate process and use it to query the system version. Here's a C++ implementation using Qt:
QProcess *p = new QProcess;
p->setProgram("/usr/sbin/sysctl");
p->setArguments({"-b", "kern.osproductversion"});
p->start();
if (!p->waitForFinished(2000)) {
// handle unlikely error here
}
QByteArray systemVersion = p->readAllStandardOutput();
On the bright side, this only ever needs to be executed once as the system version presumably won't change over the course of a process's life. Nonetheless I'll leave this question open in case someone has a better solution.

Related

How to install XCode 9 GM on MacOS Sierra 10.12?

I actually built a Hackintosh to learn programming with Xcode. It runs on my Asus X555LA laptop. I downloaded the latest Xcode 9 GM build from the Apple Site (not from App store). After extracting, when I tried to install, it shows "You can't use this version of the application "Xcode" with this version of macOS; You have macOS 10.12. The application requires macOS 10.12.6 or later".
Is there any tweak to make it run on my Sierra 10.12 itself? I can't really think about upgrading the macOS version as it's a Hackintosh. I followed this guide to install macOS on my Asus laptop.
Xcode requires latest macOS, you have no choice, you need to upgrade the macOS version on your Hackintosh. Or better: Reinstall macOS in a recommended way on your PC, if you're doing Hackintosh... :)
The guide you linked is very poor... Never use premade install images, because these have been modified in an uncertain way, and you don't want to install a premade undocumented mess to your computer. It might be packed with threats, malwares, spy tools and so on.. It's the worst thing I can imagine in security aspect to install an OS image from uncertain source.
Also, there is no universal macOS installer for PCs - even though many are trying to find a way to create it: it's a bad idea and it will never succeed because there are so many PC parts, millions of differently built computers..
The only way to create a stable fully functional Hackintosh is to know your hardware and create an installer flash drive for that specific PC. First you have to download the latest macOS Sierra from AppStore, this is the only source that you can trust, because it's downloading from Apple's servers. Then install a small program, called Clover bootloader to the flash drive to make it bootable.
This is the only full and up to date guide for PC laptops. If you have questions, register to the linked site and start a new forum thread posting your questions. They will help you but please read this guide at least 3-4 times carefully because everything is described here.

How do you debug an app for an older version of Mac OS X?

I am developing an app using Xcode 4.6 on an OS X 10.8 machine. The app deployment target is set to 10.6, which is what we need to support. But when I archive the app (compile, link and embed resources+frameworks) and deploy (aka copy) it to the 10.6 test machine, it crashes with a generic Segmentation fault. It works fine on 10.7.
I can't compile the project in Xcode on the older Mac because the app is built using the newer compiler (it uses ARC, implicit property synthesis, the new objective-c literal syntax, etc.). It also wouldn't type check because the base SDK is 10.8 and it references some 10.8 tokens which the compiler on the 10.6 machine doesn't know about.
Any suggestions on how to go about debugging the app?
I'm not affiliated with this company/software in any way, but Deploymate is a paid app which can scan your app for SDK usage and tell you when you are calling selectors and APIs that are unavailable on older OS versions. This can help you track down exceptions and crashes relating to API usage.
You are very likely using one or more 10.7+ APIs that crash on 10.6. With a 10.8 target SDK you allow all the calls to function that are available in that SDK. However apps are bound late so this doesn't crash when you do not actually call those functions. You need an explicit check similar to this (here for the full screen feature):
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
if (runningOnLionOrLater) {
[mainWindow setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
[toggleFullscreenItem setHidden: NO];
}
#endif
One way to determine the current version is:
int macVersion;
if (Gestalt(gestaltSystemVersion, &macVersion) == noErr) {
runningOnLionOrLater = macVersion > MAC_OS_X_VERSION_10_6;
}
For debugging the problematic calls simply set the base SDK to 10.6 and XCode should mark those functions that are not available there.
While there is no real good solution to this (I've seen simply different behaviors on different macOS versions) and no way to simply simulate an older macOS version, if you have a machine to spare:
It is possible to use an external HD, partition it and install different macOS versions. They all can be bootable and it's a matter (pain) of restarting the machine for every OS version.

confusion of how to make osx app backward compatible & how to test them

after reading the apple SDK guide
https://developer.apple.com/library/mac/#documentation/developertools/conceptual/cross_development/Overview/overview.html
I'm still confused of how to make the mac app backward compatible & how to test them properly
I have an app, I run it and tested it on Mountain Lion 10.8 without any problem, however I want to make this app backward compatible so that other users can run it on a mac 10.6 - 10.7 machine.
I have an apple developer id and I can download the old versions of 10.7 and 10.6, but the problem is, I have a 2011 macbook air which is currently running 10.8, and that's the only apple machine that I have. Can I test the 10.7 and 10.6 by using vmware or parallels?
in my project settings, I set the target deployment to 10.6 (as I want 10.6 users to run my app), but should I set my SDK to 10.8 or 10.7? if I set the SDK to 10.8 but having the target deployment set to 10.6, if I fix all the xcode warnings will it run successfully on 10.6??
from the SDK drop down, I can only set to 10.8 or 10.7, but 10.6 is missing, how do I fix that?
thanks in advance
I develop on a 10.8 box and support back to 10.5. Just a couple of months ago we dropped 10.4 PPC support, and I'm still cleaning out some of the 10.2-specific code. This may get a little rant-y, but I've been doing old versions for a long time. I have some opinions on the matter.
No matter what Apple says in their docs, if you want to support 10.6, then build with the 10.6 SDK. Do not rely on distribution target.
I have had this discussion with the Xcode engineers, and while they hold to Apple's party line that you should always build with the latest SDK, they also acknowledge that it's generally insane to do so. If you build against the 10.8 SDK and mark your deployment target at 10.6, you will get no warnings for using methods that do not exist on 10.6. The only way you will discover that you've used a nonexistent method is that it might give you strange bugs when run on 10.6. That's insane.
Remember, OS X doesn't crash when you send an unknown selector. It just aborts the current runloop. So the bugs are even harder to track down then on iOS, where it crashes the app.
Sure, you can do weak linking. Talk about dangerous.... Yes, there are a few times this is useful, but the compiler gives you no warning if you don't do it correctly. If I'm going to do weak linking like this, I go the other way, linking against the old SDK and copying the new function's prototype into my implementation. That way I have documentation of every function I think I'm going to weak-link.
Download the old SDKs and symlink them into your Xcode distribution.
Guard them jealously. Apple will try to delete them every time you upgrade Xcode. Make your own copies and stick them in /SDKs or somewhere else away from Xcode. I provide a script called fix-xcode to manage the symlinks automatically. Am I bitter at Apple for their relentless insistance on deleting my old SDKs? Yes, I am.
You can run 10.6 Server in a VM legally. You can run 10.7+ Desktop in a VM legally. These are good ways to test your code.
Or you can do what I do and have a small pile of old MacBooks each with two or three partitions on them that you reboot all the time.
Now that 10.7 comes from App Store, it's a little harder to make VMs. My strong recommendation is to snapshot your image immediately after install, and make a clean backup copy of it. You'll want to be able to clone that image from time to time when you need to get back to a "raw" machine.
Get in the habit of squirreling away SDKs as they come out. 10.8 will be old some day. You might as well make a copy now while it's easy.
Whether you support individual dot-releases or not, it can be very helpful to keep around the upgrade packages for individual dot releases. When you encounter customers running non-current releases, it's nice to be able to check whether an "unreproducible" bug in fact is easily reproducible on their specific version. Whether this is worth it or not depends heavily on your product and customers. It was a life-saver for me when 10.4.11 made major changes to WebKit during a dot release...
Invest in a small NAS or a big external USB drive (though I've had trouble with those failing when used extensively, so I prefer a RAID). You'll need the space. You want to hold onto lots of VMs and lots of SDKs and sometimes even old versions of Xcode.
Adding to Rob Napier's great in-depth answer:
To use an old SDK, put the SDK (or a symlink) to it here:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
With XCode 7.3 or later, you need you to open this file and change "MinimumSDKVersion" (otherwise XCode will refuse to use the old SDK):
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Info.plist
You can install multiple versions of Mac OS on a single machine, booting between each.
The SDK should be the latest (10.8).
See 2.
One alternative to 1 that I've considered (I am in the same boat) is to create a Snow Leopard Hackintosh using an old PC and just installing Lion and Mountain Lion on my MBP.
You need to do these settings :
1.Set the Base SDK to Current version of Mac (ex. 10.7)
2.Set the Deployment SDK to older version (ex.1.4)

Python 3.1.1 on Mac OS X 10.6 Snow Leopard

I've spent some time today playing with getting the source for python 3.1.1 to build on my MacBook Pro using the --enable-framework and --enable-universalsdk options with no success. I will humbly admit that I have no real clue why I can't compile 3.1.1 on Snow Leopard, I did make sure to get the new Xcode version for Snow Leopard, and made sure I also installed the 10.4u SDK. It seems to be choking on the 10.4 SDK during the make stage, and has several error regarding headers for wchar, cursor, and ncursor during the configure stage. I have been able to get a make from a plain configure, and most the test pass, but that just isn't challenging enough. Has anyone else attempted to build python 3.1.1 on a Mac running Snow Leopard
There is an automated installer here: http://python.org/ftp/python/3.1.1/python-3.1.1.dmg
You need to set MACOSX_DEPLOYMENT_TARGET if you actually want to use an older SDK.
If you target 10.6, it may be that PPC building is not supported anymore, according to this bug report. In fact, that may be the case even if you target 10.4, using XCode 3.2 (haven't tried myself).
I don't have 10.6 installed yet so I can't say for sure it will work without issue but, in general, if you want to build a batteries-included framework build optimized for 10.6 of Python on OS X, you're best off using the installer build script in the source tree at Mac/BuildScript/build-installer.py after applying the patch in the bug report Martin referred to. Something like this should work [untested]:
./build-installer.py --sdk-path=/Developer/SDKs/MacOSX10.6.sdk --universal-archs=intel --dep-target=10.6 --src-dir=... --build-dir=...
That will build everything including dependent third-party libraries and the documentation but, be forewarned, you'll probably have to tweak things until you get it right and a few things aren't supported yet in 64-bit, most notably, tkinter. As mentioned above, the standard python.org 3.1.1 installer should likely work OK as long as you don't need 64-bit support.
[EDIT: I should clarify that, WRT 64-bit support, the problem isn't in tkinter, rather that the Apple-supplied versions of Tk in 10.5 and earlier were 32-bit only and so there was code in setup.py to prevent attempting to build a 64-bit version of tkinter on OSX. Perhaps that check can be removed now if the 10.6 Tk is 64-bit.]
Kenneth Reitz's soluton doesn't work for me. In fact, the install works fine but my default PATH still points to /usr/bin/python (v2.6.1.). I vaguely recall that we should be modifying our ~/.profile to point to /.../Frameworks and I expected the installer to do this for me (nope).
Anyway, /Library/Frameworks/Python.framework/Versions/3.1/bin exists so we could add it.
But I'm curious why the python bin in there does a crash and burn on me.
No time to resolve this now. Bye.

Test build of Cocoa application not compatible with tester's version of OS X

I've been building a basic Cocoa application with Core Data and Interface Builder, and no extra coding, frameworks, or header files. I sent it to someone to test on their machine (a last-gen G5 iMac), and they got a message saying that their machine couldn't run it. I discovered the switch to compile for PPC, so I built a PPC version of the application to try out, and that produced the following error message:
You cannot use this version of Application on this version of Mac OS X.
I'm running Xcode 3.2.1, Interface Builder 3.2.1, and OS 10.6.2. The conversation with my tester was a bit confusing; at first it sounded like she only had Tiger on her machine, saying Leopard was incompatible (I corrected and said that Leopard should be, it's Snow Leopard that isn't), and then by the end of the conversation she was about certain that her machine was running Leopard, but had already shut it off by then. So I'm not sure which version of OS X is on the offending iMac, but it's the latest version of either 10.4.11 or 10.5.8 (the tester is in a remote location, so I can't verify personally at the moment).
What can I tweak to try and improve compatibility on my tester's machine?
If they're seeing that message, it's most likely because your app has the LSMinimumSystemVersion key (Minimum system version) set in the Info.plist. You should take this key out or set it to the actual the minimum OS X version you support.
Once you do this, you may well run into the next problem. (Probably a dynamic linker error as a result of using a framework or API that didn't yet exist on 10.4 or 10.5.)
The main problem here is that you're sending it out to a system where you haven't actually tried it. If you plan to support 10.4, 10.5, or both, I highly recommend that you find a spare hard drive, partition it up, and install 10.4.11 and 10.5.8. There are many issues that will crop up on older OS's and if you haven't tried it yourself, it's unlikely it will work smoothly on the first try.

Resources