[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