Support hard-links for CMAKE_INSTALL_MODE
What's wrong with Symlinks?
While the symlink support in CMAKE_INSTALL_MODE
is great for local development (turning installs "for free"), it's actually quite troublesome when you try to use this for an actual installation or in a CI/CD context where the installed package is typically supposed to out-last the corresponding build folder.
And then there is also the huge catch that with any form of package system chained outside of the CMake install step, symlinks usually have a special semantic and usually end up inside a package. After all - the package system can't really distinguish between a symlink that's supposed to be targeting outside of the package and one that shouldn't have!
Then there's also yet another elephant in the room: Whatever software attempts to work with the installed components needs to be symlink-compatible to function at all. That's not a given! Especially under Windows, the support for "Vista style symlinks" - .symlink
files - is pretty much non-existent.
What else to use?
Now, there are plenty of reasons why symlinks are actually a pretty bad idea to use. But let's take a look at the alternatives, what works and what wouldn't:
Linux
For Linux systems, we only have one alternative - true hardlinks. Any software observing the CMake install prefix is agnostic to it even being a hardlink. There's merely the catch that hardlinks - unlike symlinks - can only reside in the same file system.
cp -lrP
e.g. behaves exactly as you expect - you get a hard link for files, and it behaves exactly as it should. Directories are not hard-linked, only the contents. So this prevents e.g. temporary files from the install-prefix from back-propagating into the build or source tree!
There's also a couple of very nice side effects, such as that when hard-link a relative soft-link, it's effectively pointing to the correct new relative location. (Also check #14609 - neither install nor the copy commands in CMake correctly deal with relative symlinks in source directories at all!)
Hardlinks do not require elevated permissions to create. They just work. And if they are not supported by the file system, a flat copy simply behaves exactly as you'd expect too. They do share permissions in the file system with the original file - but that's more of a feature than an issue as well.
Windows
For Windows systems, there's junctions and hardlinks. The first one unfortunately only works for directories, but otherwise behaves more like a soft-link in Linux (it can turn invalid if the target is gone, and turn valid again later). Hard-links are only for files. But both are usually entirely transparent to software accessing the file system - neither a junction nor a hard-link behaves like a special type of file as it would had in Linux!
In terms of permissions required, we are in a bit of a ditch here. Hard links require administrator privileges, junctions don't. But since junctions can't be used with files, you can't use them to make a directory structure.
Even though the use of hard links requires elevated privileges, I would still recommend to use only hardlinks and avoid the use of junctions (even when asked to install directories!) due to the unexpected behavior of junctions to turn invalid. And to likewise mimic the behavior of a cp -lrP
, so directories are copied and only files are linked.
In any case - .symlink
files as introduced in CMake 3.22 are pretty much the worst possible solution, and don't work more often than they would work.