MantisBT - CMake
View Issue Details
0014609CMakeCMakepublic2013-11-30 18:412016-06-10 14:31
irwin 
Kitware Robot 
normalminoralways
closedmoved 
CMake 2.8.12 
 
0014609: cmake -E copy and cmake -E copy_directory commands need an option to NOT follow symlinks on Linux
It is known but not documented (see bug 13204) that both "cmake -E copy" and "cmake -E copy_directory" currently follow symlinks on Linux. This results in a particularly bad situation when attempting to copy a directory that happens to contain a broken symlink, e.g.,

software@raven> ls -l test_symlink
total 0
lrwxrwxrwx 1 software software 3 Nov 30 13:29 new -> old

software@raven> cmake -E copy_directory test_symlink test_symlink1
Error copying directory from "test_symlink" to "test_symlink1".

When I encountered this much too generic error message when using copy_directory for a very large directory recently I initially had no idea whether I was dealing with an i/o error or whatever, and it is only by chance that I discovered a botched exit from emacs in that directory had created a broken symlink.

Thus, at minimum bug 13204 should be fixed and also copy_directory (and copy) should have a much more specific error message identifying both the symlink and the non-existent file that is causing the trouble.

In addition, a (Unix-only) option to NOT follow symlinks should also be implemented for copy_directory and copy. After all, every GNU utility by default does not follow symlinks on Unix so it would be nice if at least this option was implemented for the cmake -E copy_directory and cmake -E copy commands on Unix.
No tags attached.
related to 0013204closed Kitware Robot Docs don't say what happens to symlinks in copy_directory 
Issue History
2013-11-30 18:41irwinNew Issue
2013-12-01 15:12irwinNote Added: 0034618
2013-12-02 09:41Brad KingRelationship addedrelated to 0013204
2013-12-03 08:47Brad KingNote Added: 0034688
2013-12-03 13:30irwinNote Added: 0034700
2013-12-03 13:51Brad KingNote Added: 0034701
2013-12-03 14:31irwinNote Added: 0034702
2014-03-05 14:16unledevNote Added: 0035315
2014-03-05 14:43Brad KingNote Added: 0035317
2014-03-05 14:43Brad KingStatusnew => backlog
2016-06-10 14:29Kitware RobotNote Added: 0042438
2016-06-10 14:29Kitware RobotStatusbacklog => resolved
2016-06-10 14:29Kitware RobotResolutionopen => moved
2016-06-10 14:29Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0034618)
irwin   
2013-12-01 15:12   
Following a tip in the comments to bug 13204, I confirmed that
code (again undocumented concerning what it does with symlinks)
already exists in cmake to NOT follow symlinks. Here is an example:

software@raven> cat test_symlink.cmake
file(COPY test_symlink/ DESTINATION test_symlink1)
software@raven> ls -l test_symlink
total 0
lrwxrwxrwx 1 software software 3 Nov 30 13:29 new -> old
software@raven> rm -rf test_symlink1
software@raven> cmake -P test_symlink.cmake
software@raven> ls -l test_symlink1
total 0
lrwxrwxrwx 1 software software 3 Dec 1 11:22 new -> old

Still another treatment of symlinks is implemented by the
file(GLOB_RECURSE ... signature) which by default does not follow
symlinks but which has a FOLLOW_SYMLINKS option.

So CMake is a rather self-contradictory mess right now with how it treats
symlinks; some commands (e.g., the -E copy and -E copy_directory
commands) always follow symlinks, some commands (e.g., the file(COPY
...) command) never following symlinks, and at least one command (the
file(GLOB_RECURSE ...) command) by default does not follow symlinks
but has a FOLLOW_SYMLINKS option. Of course, those contradictory
symlink treatments mean that the fundamental implementations already
exist to pick just one model for dealing with symlinks in all cases.
So, in principle, it should be straightforward to implement that.

When picking the model for the preferred treatment of symlinks, I
would advocate following the file(GLOB_RECURSE ...) model in all cases
since that model is similar to how the GNU tools treat symlinks and
therefore causes the least surprise for Unix users.
(0034688)
Brad King   
2013-12-03 08:47   
Rather than trying to change the "-E copy" behavior and worry about compatibility it is probably better to add a new "-E cp" command with options acting more like the *nix "cp" command.

Meanwhile you can work around this by using a "cmake -P mycopy.cmake" script to use file(COPY).
(0034700)
irwin   
2013-12-03 13:30   
We already have two copy variants, -E copy and -E copy_directory which is bad enough without introducing yet a third variant. Instead, I would go the other way and simply focus everything on implementing -E copy with useful options such as --recursive, --dereference, and --no-dereference (taking the names and meanings of those options from the GNU cp command). Then -E copy_directory could be implemented and documented as being identical to -E copy with the --recursive option. You could stop at that point with absolutely no backwards incompatibility introduced with --dereference the default option for -E copy. However, I would urge one step further which would be to simply change that default to --no-dereference (to be consistent with the GNU defaults) using a policy to deal with that backwards incompatibility issue. For me that whole approach is much cleaner than introducing an additional variant of the -E copy command with absolutely no difference to -E copy other than the choice of default options.
(0034701)
Brad King   
2013-12-03 13:51   
Re 0014609:0034700: A policy cannot work for "cmake -E" commands because they run outside the project configuration process which is the scope for policies.

It is much simpler to define "cmake -E cp" with the proper behavior and deprecated the other copy variants (at first in documentation and later with a runtime warning). Then compatibility is automatic because we know "cmake -E copy" will always have the old behavior. The new "cp" name implies cp-like semantics too, where "copy" implies old Windows "copy" semantics which do not deal with symlinks.
(0034702)
irwin   
2013-12-03 14:31   
Given that constraint about the scope of policies, then your plan (especially including deprecation of -E copy and -E copy_directory which answers [at least in the long term] my concern about too many copy variants) is a good one. And I like your point about choosing the name of the new command as "cp" to emphasize the GNU cp-like semantics.
(0035315)
unledev   
2014-03-05 14:16   
Any news on this? Got bitten by this unexpected behavior :/
(0035317)
Brad King   
2014-03-05 14:43   
Re 0014609:0035315: No one is actively working on it. The solution is described in 0014609:0034701 and is to create a new "cmake -E cp" with the right semantics. A full POSIX-compatible cp implementation is non-trivial. We can take a subset of it so long as the default behavior matches for all file types and unsupported options are rejected rather than ignored so that they can be added later.
(0042438)
Kitware Robot   
2016-06-10 14:29   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.