36

When using Clang's or GCC's Darwin backends to create executables for OSX, the flag -mmacosx-version-min=version can be used to set the earliest version of OSX the executable will run on.

Is there any way to trace back from a given executable which flag was used to compile it? I.e. is there a way to determine which minimum OSX version is targeted by a given executable?

earl
  • 38,011
  • 6
  • 55
  • 58
  • 1
    For the record, Apple haven’t contributed to GCC since its licence was changed to GPLv3. Whenever possible, use Clang/LLVM. –  Jun 17 '13 at 13:35
  • 1
    Short answer `otool -l /path/to/bin | grep -E -A4 '(LC_VERSION_MIN_MACOSX|LC_BUILD_VERSION)' | grep -B1 sdk`; this also works with ARM64 machines like M1. `version` or `minos` gives the minimum supported macOS version, while `sdk` gives SDK version. – legends2k Aug 20 '21 at 06:02

2 Answers2

57

Use otool -l /path/to/binary and inspect the LC_VERSION_MIN_MACOSX load command; specifically, the version field.

For example, a binary compiled with the 10.8 SDK with deployment target (-mmacosx-version-min) 10.8 should have an LC_VERSION_MIN_MACOSX like this:

Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.8
      sdk 10.8

whereas a binary compiled with the 10.8 SDK with deployment target 10.7 should have an LC_VERSION_MIN_MACOSX load command like this:

Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.7
      sdk 10.8
  • 1
    Is there any way to get this information for static libraries (".a" files)? – j b Apr 13 '14 at 17:14
  • 2
    This works also for static libraries (.a files). You'll see such load command per each object in the library. There's a nice UI application for Mac called 'MachOView" that allows comfortable browsing of binaries, and easy searching for these load commands. – Motti Shneor Sep 05 '16 at 14:00
  • wow, thanks! however, is there a way to find out this information with the stock tools built into macOS? 'otool' is part of the Developer Tools – user1259710 Jan 28 '19 at 21:28
  • is there a library or system api to do this programatically? – electronic_coder Jan 20 '20 at 12:14
  • @electronic_coder Yes, there is an API to do it programmatically. Look at the source of otool (https://github.com/opensource-apple/cctools/tree/master/otool). – prewett Mar 25 '20 at 19:51
  • This is a great solution. I'm using it in my build scripts since a while. Unfortunately it seems that it doesn't work with arm64 (Apple Silicon) binaries. I'm using `otool -l -arch x86_64 /path/to/binary` to get the minimum version of my fat binary. – ndreisg Jan 05 '21 at 16:31
10

The load command that is mentioned in the accepted answer is not listed when I build a modern macOS executable. However LC_BUILD_VERSION does contain the minos and sdk fields:

Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 11.0
      sdk 11.1
   ntools 1
     tool 3
  version 609.8
prideout
  • 2,715
  • 1
  • 21
  • 24
  • I noticed this too. See this screenshot with both types of output, from binaries that were built in the same CI run but by different tools (PyInstaller vs Rust): https://github.com/ActivityWatch/activitywatch/pull/544#issuecomment-751801675 – erb Dec 28 '20 at 17:52
  • 2
    The reason why you don't see the `LC_VERSION_MIN_MACOSX` is probably because your binary is for architecture arm64 or universal and you have an Apple Silicon Mac. Note that in case of a universal binary the `minos` field does not necessarily reflect the actual minimum SDK if it is lower than 11.0. Use `otool -l -arch x86_64 /path/to/binary` for universal binaries. – ndreisg Jan 05 '21 at 16:44
  • 1
    Ah, it is true that I'm using Apple Silicon. – prideout Jan 05 '21 at 19:17
  • I'm not seeing it either, on intel with big sur – CiNN Jan 06 '21 at 22:47
  • ok looks like if i build with CFLAGS=-mmacosx-version-min=10.10 I do see the LC_VERSION_MIN_MACOSX in the binary, and I lose LC_BUILD_VERSION – CiNN Jan 07 '21 at 01:37