CMake can't re-run itself after upgrading via Homebrew
Branching off of !3929 (closed) for further discussion.
Background: When the Homebrew package manager installs a package, it's not placed directly in /usr/local
, but instead in a versioned prefix; for cmake, e.g. /usr/local/Cellar/cmake/3.14.4
. After installation, the package is "linked" into /usr/local
by creating symlinks to the files in the versioned prefix; e.g. /usr/local/bin/cmake -> ../Cellar/cmake/3.14.4/bin/cmake
, /usr/local/share/cmake/Modules/CMake.cmake -> ../../../Cellar/cmake/3.14.4/share/cmake/Modules/CMake.cmake
. This is normally file; if a package hardcodes paths relative to the configure-time (versioned) prefix, they'll be present, and if it references paths relative to an executable or library, they'll be present in /usr/local
.
However, this results in a problem with CMake's current behavior around CMAKE_COMMAND
and related variables, which are currently generated relative to the binary after resolving all symlinks, and can end up "hardcoded" in generated build files, e.g. for when the build re-runs cmake
. The path in the build files ends up being the versioned path, which isn't stable. This means that after the CMake package is updated via Homebrew, the project build will continue to run using the old CMake version until it's manually re-run (which may be desirable in some cases, but can be surprising as a default, and differs from the behavior with any other package manager), and once the old version is removed by brew cleanup
, any attempt by the build files to run cmake
will fail, requiring the user to reconfigure the build manually.
This behavior was introduced in cae34d2d, which referenced "mac symlinks to the executable". I'm not sure what case that was referring to, but presumably it involved a single symlink to the executable without corresponding symlinks to the resource files or other auxiliary files.
In !3929 (closed), I propose a solution that addresses both cases: if the relevant resource files appear to be present at a path relative to the executable, it assumes any symlinks are part of some versioning scheme like this, and uses the original path from _NSGetExecutablePath
in build files. Otherwise, it assumes that we're in the single-file-symlink case, and the behavior is the same as in the current code.