Why Command-Line-Tool not honor the macOS Deployment Target setting

I am testing the if #avilable feature on swift by writing a command-line tool.
I found 2 interesting minor issues.

  1. It seems that the "macOS Deployment Target" setting does not work in a command-line tool project. Even though I set 12.0 as the deployment target, It stills could run in the 11.0 system.

  2. '@available' for global variable does not work in script mode. Why is that?

import os
import Foundation

@available(macOS 12.0, *)
let logger = Logger()

if #available(macOS 12.0, *) {
    let logger = Logger()
    logger.log("Look it's macOS 12.0 or above...")
} else {
    os_log("Well, it's macOS 11.0 or below...")
}

Even though I set 12.0 as the deployment target, it stills could run
in the 11.0 system.

I’m not 100% sure what you mean by this but I suspect that it’s:

  • You build a tool with a (for example) macOS 12 deployment target.

  • Xcode correctly encodes that in the binary.

    % vtool -show-build MyTool
    MyTool (architecture x86_64):
    …
        minos 12.0
    …
    MyTool (architecture arm64):
    …
    
  • But macOS 11 lets you run it anyway:

    % sw_vers
    ProductName:	macOS
    ProductVersion:	11.6.1
    BuildVersion:	20G224
    % ./MyTool
    2021-12-01 09:11:09.652 MyTool[570:8417433] Hello Cruel World!
    

If so, that’s a known limitation of macOS. High-level APIs, like those used by the Finder, will detect, and refuse to launch an app with a deployment target higher than the current system. Low-level APIs, those used by the shell, do not.

We have a bug on file about this (r. 19339406) but fixing it is a challenge because of compatibility concerns.

In the meantime, if this is a big deal for you then add your own OS version check to the start of main (well, the Swift equivalent).

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

3 Likes