为什么Homebrew会创建/usr/local/opt目录,我应该使用它吗?

45

我对使用Homebrew还很陌生,现在我正在尝试弄清楚它如何工作,以便在自己的项目中使用一些库(例如boost、gsl、openblas)。

我已经明白每个配方都是由Homebrew安装在/usr/local/Cellar/中,然后在usr/local/bin、usr/local/lib和usr/local/include中建立符号链接,所以它似乎不会与操作系统中已安装的库造成混淆(参见理解homebrew和keg-only依赖项)。但我发现每个配方也链接到了一个/usr/local/opt目录。

那么我的问题是为什么有这个/usr/local/opt目录(它有点冗余),以及我应该使用哪个路径来使用配方(通常是/usr/local/Cellar或/usr/local/或/usr/local/opt)?

3个回答

83

它提供了一个公式内容的路径,跨版本升级不会改变。

考虑这种情况:假设您使用Homebrew构建了libfoo.dylib。它的版本是2.0.0,所以它位于/usr/local/Cellar/libfoo/2.0.0/lib/libfoo.dylib。您想要从另一个正在构建的程序链接到它,因此您将-L/usr/local/Cellar/libfoo/2.0.0/lib -lfoo传递给gcc。您的程序编译成功。稍后,您升级到了libfoo 2.0.1并删除了v2.0.0。现在,/usr/local/Cellar/libfoo/2.0.0/lib/libfoo.dylib不存在,因此您的程序无法运行,因为它无法动态加载libfoo。

那没关系。libfoo.dylib也可以在/usr/local/lib/libfoo.dylib中找到。它是指向libfoo的最新版本的符号链接,因此应该始终存在。因此,您将-L/usr/local/lib -lfoo传递给您的程序并编译它。稍后,您升级到了libfoo 2.0.1。没有问题,因为/usr/local/lib/libfoo.dylib仍然存在,并指向v2.0.1的副本。

这很好,Homebrew使用了这个系统一段时间。问题在于,某些公式是“Keg-only”,因此它们不会从/usr/local中创建符号链接。(通常它们是“Keg-only”是因为它们会覆盖OS X附带的库的版本,而超越OS X库可能会导致问题。)假设您想要链接到一个只有Keg版本的库。它没有从/usr/local/lib中创建符号链接,因此您必须给出安装在/usr/local/Cellar中的版本的完整路径,这将带您回到上面列出的第一个问题。

/usr/local/opt解决了这个问题。它提供了一个地方,用于将当前版本的所有公式建立符号链接,无论它们是否是keg-only。现在,当您想要编译程序时,可以使用-L/usr/local/opt/libfoo/lib -lfoo,您的程序将链接到最新版本的libfoo,即使您升级它,甚至如果它是keg-only。


1
谢谢你的回答!(顺便帮我重新打开这个问题)所以我想最安全的选择是始终使用 /usr/local/opt,但为什么 Homebrew 仍然使用 /usr/local/lib 为非 keg-only 创建符号链接呢? - Pierre Marchand

6

补充 mipadi 的答案:

在名为 '/usr/local/opt' 的文章中写道:

将文件存储在一致的位置是保持系统干净和可维护的重要部分。在大多数Linux系统上,大多数软件都是使用包管理器安装的。包管理器跟踪已安装的文件,因此可以最小化对软件的更新和删除的副作用。

然而,有时必须安装未通过包管理器提供的软件。为了最小化文件系统上的副作用,这样的软件安装在 /usr/local 目录下。UNIX风格的软件安装将文件放置在本地根目录下的bin、lib、share、etc等子目录中,但通常将软件安装到特定于包的目录中,并从本地根目录添加软链接。这样做可以轻松删除软件,只需删除特定于包的目录以及指向该目录的任何链接即可。

有些软件提供本地安装说明,鼓励直接在 /usr/local 中创建特定于包的目录。这不利于良好组织,因为它将 UNIX 层次结构目录与特定于包的目录混合在一起。软件安装到特定于包的目录中已经在 /opt 目录中完成,因此按照相同的约定将本地安装的特定于包的目录放置在 /usr/local/opt 目录下是有意义的。

在目录名称中包含版本号不是必需的,但对于本地安装的软件来说是一个好习惯,因为它允许同时安装和测试多个版本。要运行特定版本的软件,请直接在包目录下运行可执行文件。可以通过控制从 /usr/local/bin 链接的可执行文件来将任何版本设置为默认版本。例如,可以安装并测试新软件版本而无需删除旧版本。当新版本准备就绪时,可以更新 /usr/local/bin 中的链接以指向它。不再需要旧版本的软件后,可以将其删除。

来源:版权所有 © 2014 Extellisys


0

我发现在我的 macOS 文件系统中的 /usr/local/opt 目录下有许多与其他程序相关的符号链接,例如 opensslgnutls 等等。因此我认为这个(/usr/local/opt)特定目录不仅仅是为 HomeBrew 创建的,它可能适用于更广泛的可执行过程范围。

顺便说一句 1:我查阅了“文件系统层次结构标准(FHS)”的主页。在“第4章 /usr 层次结构”中没有关于 /usr/local/opt 的描述。这有点奇怪。

顺便说一句 2:我已经通过 HomeBrew 安装了 GNU Stow。当我输入命令 brew --prefix stow 时,终端显示路径为 /usr/local/opt/stow。然后我尝试使用命令 open /usr/local/opt/stow 在终端中打开它。它打开了一个路径为 /usr/local/Cellar/stow/2.3.1 的目录。


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