确定二进制文件编译的最低OSX版本

43

在使用Clang或GCC的Darwin后端为OSX创建可执行文件时,可以使用标志-mmacosx-version-min=version来设置可执行文件将在哪个最早的OSX版本上运行。

有没有办法从给定的可执行文件中跟踪回用于编译它的标志?也就是说,有没有办法确定给定可执行文件所针对的最低OSX版本?


1
值得一提的是,自从GCC的许可证更改为GPLv3以来,苹果公司就没有对其做出过贡献。尽可能使用Clang/LLVM。 - user557219
1
简短回答:otool -l /path/to/bin | grep -E -A4 '(LC_VERSION_MIN_MACOSX|LC_BUILD_VERSION)' | grep -B1 sdk;此方法也适用于 ARM64 机器,如 M1。versionminos 显示最低支持的 macOS 版本,而 sdk 显示 SDK 版本。 - legends2k
3个回答

64

使用otool -l /path/to/binary命令并检查LC_VERSION_MIN_MACOSX加载命令,特别是版本字段。

例如,使用10.8 SDK编译且部署目标(-mmacosx-version-min)为10.8的二进制文件应该具有如下LC_VERSION_MIN_MACOSX

Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.8
      sdk 10.8

而一个使用10.8 SDK进行编译,部署目标为10.7的二进制文件应该有一个像这样的LC_VERSION_MIN_MACOSX加载命令:

Load command 9
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.7
      sdk 10.8

2
有没有办法获取静态库(“.a”文件)的这些信息? - j b
2
这也适用于静态库(.a文件)。您将在库中的每个对象中看到这样的加载命令。有一个名为“MachOView”的Mac UI应用程序,可以轻松浏览二进制文件,并轻松搜索这些加载命令。 - Motti Shneor
哇,谢谢!不过,有没有一种方法可以使用内置于 macOS 的股票工具找到这些信息呢?'otool' 是开发者工具的一部分。 - user1259710
有没有库或系统API可以以编程方式完成这个任务? - electronic_coder
@electronic_coder 是的,有一个API可以编程实现它。查看otool的源代码(https://github.com/opensource-apple/cctools/tree/master/otool)。 - prewett
1
这是一个很好的解决方案。我已经使用它在我的构建脚本中有一段时间了。不幸的是,它似乎不能与arm64(Apple Silicon)二进制文件一起使用。我正在使用otool -l -arch x86_64 /path/to/binary来获取我的fat二进制文件的最小版本。 - ndreisg

15

在被接受的答案中提到的“load”命令,在我构建现代macOS可执行文件时未列出。但是LC_BUILD_VERSION包含minossdk字段:

Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 11.0
      sdk 11.1
   ntools 1
     tool 3
  version 609.8

我也注意到了这一点。请查看此屏幕截图,其中包含两种输出类型,它们是由相同的 CI 运行构建的二进制文件,但使用不同的工具(PyInstaller vs Rust)进行构建:https://github.com/ActivityWatch/activitywatch/pull/544#issuecomment-751801675 - erb
3
你看不到 LC_VERSION_MIN_MACOSX 的原因可能是因为你的二进制文件是针对 arm64 或通用架构,并且你使用的是 Apple Silicon Mac。请注意,在通用二进制文件的情况下,如果 minos 字段低于 11.0,则不一定反映实际的最小 SDK。对于通用二进制文件,请使用 otool -l -arch x86_64 /path/to/binary - ndreisg
1
啊,我确实正在使用苹果芯片。 - prideout
我也看不到,在Big Sur上使用Intel。 - CiNN
好的,看起来如果我使用CFLAGS=-mmacosx-version-min=10.10进行构建,我会在二进制文件中看到LC_VERSION_MIN_MACOSX,并且我会失去LC_BUILD_VERSION。 - CiNN

8

一种不使用 otool | grep 的替代方法是使用 vtool (适用于 macOS 10.15 及更高版本)。

例如:

 vtool -show-build ./test
test (architecture x86_64):
Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform MACOS
    minos 12.0
      sdk 12.3
   ntools 1
     tool LD
  version 764.0
test (architecture arm64):
Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform MACOS
    minos 12.0
      sdk 12.3
   ntools 1
     tool LD
  version 764.0

正如评论中所指出的那样,这不适用于静态库或目标文件。来自man vtool

     Currently vtool only operates on final linked binaries, such as executable files, dynamic libraries, and bundles. Because the
     executable code in Mach-O final linked binaries cannot be moved or resized, and because the load commands reside between the mach
     header and the executable code, there is only a limited amount of space available for vtool to save changes. Set operations that
     add or resize load commands may fail if there isn't enough space in the Mach-O file availble to hold the new load commands.

vtool 可以编辑 mach 头文件中的构建和源代码版本,前提是有足够空间进行修改。


与使用otool -l的答案相比,这似乎无法在静态库上工作(在Intel、macOS 12.5、XCode 13上)。 - emmenlau
1
是的。这在 man vtool 中有记录。很抱歉我在回答中遗漏了它。作为交换,您可以设置或删除相关的加载命令,前提是机器头部有足够的空间。 - Theoretical Economist
这比在otool输出中查看LC_BUILD_VERSION要好,因为vtoolplatformtool数字解码为可读的字符串。 - rob mayoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接