[MacPorts] #65354: iTerm2 @3.4.15_3: SafeAreaInsets are still breaking builds on older systems
MacPorts
noreply at macports.org
Mon Jun 20 14:45:31 UTC 2022
#65354: iTerm2 @3.4.15_3: SafeAreaInsets are still breaking builds on older systems
----------------------+----------------------
Reporter: Gandoon | Owner: markemer
Type: defect | Status: assigned
Priority: Normal | Milestone:
Component: ports | Version: 2.7.2
Resolution: | Keywords:
Port: iTerm2 |
----------------------+----------------------
Comment (by kencu):
This is a bit long, and I was going to avoid discussing it here, but a)
you asked and b) might as well get it right. I sense you are a person who
appreciates a good amount of verbage, so I will try to be both long winded
and complete here.
The way Apple has approached supporting code for older deployment targets
changed about five years ago, so things you may read on the web about the
way to use the Availability Macros might have changed now and will be out
of date perhaps.
The way Apple wants you to do this now is as follows: use the most current
MacOS system, use the most current Xcode, use the most current MacOSX SDK,
and then set your deployment target to the be the oldest system that you
are prepared to support with your code.
In your code, when you are trying to use features that don't exist on
older systems that you still want to support, you guard those newer
features like this:
{{{
if (@available(macOS 12, *)) {
// use some newer feature in 12.x
} else {
//either don't use it, or use a fallback implementation
}
}}}
The compiler will change that @available call into code that tests the
system your application is actually running on, and follow the right code
path for whatever system you are running on.
If you try to use a feature that doesn't exist on your deployment target,
the compiler will even tell you that you need to add an @availability
guard for it -- isn't that helpful? Great!
NOW -- we take MacPorts. We don't want to exactly follow Apple's plans
here. We want to compile this code against an older SDK, say 10.15, but
that older SDK doesn't know anything about the newer features in the 12.3
SDK.
So when you try to compile code that stumbles across the newer features,
even if they are guarded by an @availability block, the code will not
compile. This is what you stumbled across with {{{safeAreaInsets}}}.
We (MacPorts) wants to get this code to compile against the older SDK. To
do that, we need to completely block out the part that the older SDK
doesn't know about, and skip all of Apple's @availability tricks.
So we want to test the version of the SDK we are building against, and not
try to compile that code if the SDK is too old to manage it. The system we
are running on will taken care of by the @available block, if we can
compile it.
OK so far?
Now, {{{MAC_OS_X_VERSION_MAX_ALLOWED}}} is set in the SDK to the version
of the SDK. So this tells us if the SDK will know about the new features
or not. This then tells us if it is safe to try to compile the new code
surrounded by the @available block. If our SDK is too old, compiling will
fail. If the SDK is new enough, compiling will succeed. So that is the one
we want to use.
MacPorts modification to Apple's procedure, to allow compiling on older
SDKs:
{{{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000
if (@available(macOS 12, *)) {
// use some newer feature in 12.x
} else {
#endif
//either don't use it, or use a fallback implementation
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 12000
}
#endif
}}}
We don't ever care (with this method) about
{{{MAC_OS_X_VERSION_MIN_REQUIRED}}} as the @available code takes care of
that issue, and it is not relevant here for us to deal with.
This lets the code block work properly on newer systems (compiling the
code, even for older deployment targets) and also for older systems (with
older SDKs that don't support compiling the code at all).
In practice, {{{MAC_OS_X_VERSION_MIN_REQUIRED}}} and
{{{MAC_OS_X_VERSION_MAX_ALLOWED}}} are often set to the same thing, so the
point is moot. But it could be that someone tries to build this code on a
newer system with an older deployment target, and in that case, using
{{{MAC_OS_X_VERSION_MIN_REQUIRED}}} would have broken the whole @available
mechanism (by not compiling it in at all, which is wrong).
In the old days, in old code, before the @available mechanism was used, we
used to use {{{MAC_OS_X_VERSION_MIN_REQUIRED}}} to do the thing that
@available() does now. I believe that people found it very very confusing,
and I have seen tremendous variability in how it was coded, so I think
Apple sat down and came up with a newer, more clear, method.
In code that uses @available, there will be almost no need I can think of
to ever use {{{MAC_OS_X_VERSION_MIN_REQUIRED}}}.
--
Ticket URL: <https://trac.macports.org/ticket/65354#comment:16>
MacPorts <https://www.macports.org/>
Ports system for macOS
More information about the macports-tickets
mailing list