MantisBT - CMake
View Issue Details
0012646CMakeCMakepublic2012-01-01 04:102016-06-10 14:31
Hugo Leisink 
Kitware Robot 
normalfeatureN/A
closedmoved 
MacMacOS X10.6
CMake 2.8.6 
 
0012646: install() overwrites existing destination file
The install() function overwrites the destination file if it exists. This behaviour is not desirable for configuration files. I would like to have an install_config() function which does not overwrite an existing destination file.

Optionally, it saves the destination file as <filename>.dist, so users can see what has changed in the new default configuration file.
No tags attached.
Issue History
2012-01-01 04:10Hugo LeisinkNew Issue
2012-01-01 04:57Hugo LeisinkNote Added: 0028082
2012-01-02 13:37Brad KingNote Added: 0028092
2012-01-02 13:37Brad KingStatusnew => backlog
2012-01-11 03:38Hugo LeisinkNote Added: 0028255
2012-01-14 08:32Hugo LeisinkNote Added: 0028300
2012-01-14 09:20Eric NOULARDNote Added: 0028301
2012-01-16 04:31Hugo LeisinkNote Added: 0028306
2012-01-16 05:26Hugo LeisinkNote Edited: 0028306bug_revision_view_page.php?bugnote_id=28306#r505
2012-01-16 05:27Hugo LeisinkNote Edited: 0028306bug_revision_view_page.php?bugnote_id=28306#r506
2012-01-16 06:17Hugo LeisinkNote Edited: 0028306bug_revision_view_page.php?bugnote_id=28306#r507
2012-01-16 07:57Eric NOULARDNote Added: 0028309
2012-01-16 08:23Hugo LeisinkNote Added: 0028310
2012-01-16 08:23Hugo LeisinkNote Edited: 0028310bug_revision_view_page.php?bugnote_id=28310#r509
2012-01-16 08:25Hugo LeisinkNote Edited: 0028310bug_revision_view_page.php?bugnote_id=28310#r510
2012-01-16 08:30Brad KingNote Added: 0028311
2012-01-16 08:31Brad KingNote Edited: 0028311bug_revision_view_page.php?bugnote_id=28311#r512
2012-01-16 08:32Brad KingNote Edited: 0028311bug_revision_view_page.php?bugnote_id=28311#r513
2012-01-16 09:14Hugo LeisinkNote Added: 0028317
2012-01-16 10:06Hugo LeisinkNote Edited: 0028317bug_revision_view_page.php?bugnote_id=28317#r515
2012-01-18 03:21Hugo LeisinkNote Edited: 0028310bug_revision_view_page.php?bugnote_id=28310#r518
2013-08-18 11:54SM0SVXNote Added: 0033731
2013-08-18 12:01SM0SVXNote Edited: 0033731bug_revision_view_page.php?bugnote_id=33731#r1241
2016-06-10 14:28Kitware RobotNote Added: 0041950
2016-06-10 14:28Kitware RobotStatusbacklog => resolved
2016-06-10 14:28Kitware RobotResolutionopen => moved
2016-06-10 14:28Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0028082)
Hugo Leisink   
2012-01-01 04:57   
I use this macro as an alternative:

install(CODE "
    macro(copy_if_not_exists SRC DEST)
        if(NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
            message(\"-- Installing: \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
            execute_process(COMMAND \${CMAKE_COMMAND} -E copy \"\${SRC}\" \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
        else()
            message(\"-- Skipping : \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
        endif()
    endmacro()
")
(0028092)
Brad King   
2012-01-02 13:37   
Moving to backlog for now. Please bring this proposal up on the mailing list for more broad discussion:

  http://www.cmake.org/mailman/listinfo/cmake [^]

Rather than a new command I think this could be implemented as an optional argument to the normal install() command.

FYI in your workaround you can use the file(INSTALL) command instead of execute_process. Look at how it is invoked from generated cmake_install scripts.
(0028255)
Hugo Leisink   
2012-01-11 03:38   
When I use file(INSTALL), I get the following error:
Command install() is not scriptable
(0028300)
Hugo Leisink   
2012-01-14 08:32   
I find it very strange that you put this in the backlog. You clearly don't understand the importance of the described feature.
(0028301)
Eric NOULARD   
2012-01-14 09:20   
Hi Hugo,

Putting a feature request or bug report to backlog does not necessarily
means that the request is overlooked.
Usually the greatest matter is **time**.

Is there any patch available?
How much time/effort does this need for a clean fix?
Clean fix meaning: no regression and possible a new automatic test?
Who will do the work?

The urgency to fix usually depends on:
Is this a [major] regression?
Is there any workaround available?
Has the new feature been thoroughly discussed on the ML?

From this criterion the "importance" of a feature is usually vary from
the viewpoint, because one may have time but not knowledge, another
may have knowledge but no time etc...

So your feature request has no patch proposal,
has not been discussed on the ML,
does not contain new regression test
and there is at least one workaround.

Concerning:

> file(INSTALL)
> Command install() is not scriptable

you probably misread Brad's comment.

1- install(FILE ...) is NOT scriptable
2- file(INSTALL ...) IS scriptable.

it easy to mismatch those two because they have mirror
names and parameter name.
(0028306)
Hugo Leisink   
2012-01-16 04:31   
(edited on: 2012-01-16 06:17)
file(INSTALL) doesn't do the trick. To check if the destination file exists or not, I need to specify the full path of the destination file. file(INSTALL) requires a directory as the destination. So, if I want to install /path/to/file.conf, file(INSTALL) saves it is as /path/to/file.conf/file.conf. I'm sure there is some trick via get_file_compontent that solves it. But this kind of hackery only proves my point even more.

I find it kind of strange that you ask me for a patch proposal and 'Who will do the work?'. You are a CMake developer right? How about... you? Or one of the other CMake developers? And what you call a workaround, I see it more as a dirty hack.

Do you agree that for a lot of software, the proper installation of configuration files is required (and not overwriting existing ones)? If so, why doesn't CMake support this?

(0028309)
Eric NOULARD   
2012-01-16 07:57   
Hi Hugo,

Just to be clear,
I am a **spare time** CMake developer meaning that is not my
paid work to work on CMake.
On the contrary, some other developers are paid for working on CMake
but then I would bet they have to work for their customer paying the
service first. I'm pretty sure you can by Kitware services if you want.

As far as I'm concerned,
my spare time being limited I have to chose what I can do
and what I want to do.
This does not mean your request is not reasonable I simply don't have
currently the time or will to handle it.

Concerning "proper installation" of config file. I agree but when I want
a clean install I do not use "make install" but use packager like RPM
or DEB for which I can specify that a particular file should not be overwritten.
Again I do not pretend it's THE way to go, just it's mine.

> If so, why doesn't CMake support this?

I suggest you ask that question on the mailing list in order to get feedback from other CMake users.
(0028310)
Hugo Leisink   
2012-01-16 08:23   
(edited on: 2012-01-18 03:21)
I'm not saying that *you* must be doing the implementation. All I'm trying to say is that I find it strange that when I submit a feature request, I'm asked for a patch and asked who will do the work. To be honest, I don't care who does the work. All I do is submit an idea. You can say "crap idea, we won't do it", "we'll take a look at it in the future", "great idea" or something like that. But returning the request (which was more or less done) feels weird.

That my feature request was placed on the backlog was an indication for me that my idea was not relevant. Which I thought was very strange for a thing I believe to be a must-have feature for a tool like CMake. As a software developer, I don't want to rely on third-party tools like RPM and APT for a proper installation of my software. Specially not because my software is also designed for BSD, on which ports, which is nothing more than a collection of makefiles, is the way to go when installing software.

(0028311)
Brad King   
2012-01-16 08:30   
(edited on: 2012-01-16 08:32)
Just to complete the workaround, file(INSTALL) does work:
install(CODE "
macro(copy_if_not_exists SRC DEST)
  if(NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
    file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/\${DEST}\" FILES \"\${SRC}\")
  
else()
    message(\"-- Skipping : \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
  endif()
endmacro()
copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/foo.config\" etc)
")


(0028317)
Hugo Leisink   
2012-01-16 09:14   
(edited on: 2012-01-16 10:06)
I don't believe this will work, because ${DEST} is a directory. The "if(NOT EXISTS" check should be done for the destination file, not the destination directory. The hackish 'workaround' that works for now (will do some more testing) is this:

# CopyIfNotExists, by Hugo Leisink <hugo@leisink.net>
install(CODE "
    macro(copy_if_not_exists SRC DEST)
        get_filename_component(filename \${SRC} NAME)
        if(NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${filename}\")
            file(INSTALL \"\${SRC}\" DESTINATION \"\${CMAKE_INSTALL_PREFIX}/\${DEST}\")
        else()
            message(\"-- Skipping : \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${filename}\")
        endif()
    endmacro()
")

Yes, you may include it in 2.8.8 if you like :)

(0033731)
SM0SVX   
2013-08-18 11:54   
(edited on: 2013-08-18 12:01)
A bit modified and more easily reused variant of the workaround since it is "packaged" as a CMake function. The semantics should be the same as install(FILE ...) regarding file path handling. I went back to use execute_process since I wanted to be compatible with CentOS 5 (CMake 2.6-patch 4). If compatibility with older CMake is not necessary the file(INSTALL ...) row may be uncommented and the rows below it may be removed.

Usage:
install_if_not_exists(source_file destination_directory)


function(install_if_not_exists src dest)
  if(NOT IS_ABSOLUTE "${src}")
    set(src "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
  endif()
  get_filename_component(src_name "${src}" NAME)
  if (NOT IS_ABSOLUTE "${dest}")
    set(dest "${CMAKE_INSTALL_PREFIX}/${dest}")
  endif()
  install(CODE "
    if(NOT EXISTS \"\$ENV{DESTDIR}${dest}/${src_name}\")
      #file(INSTALL \"${src}\" DESTINATION \"${dest}\")
      message(STATUS \"Installing: \$ENV{DESTDIR}${dest}/${src_name}\")
      execute_process(COMMAND \${CMAKE_COMMAND} -E copy \"${src}\"
                      \"\$ENV{DESTDIR}${dest}/${src_name}\"
                      RESULT_VARIABLE copy_result
                      ERROR_VARIABLE error_output)
      if(copy_result)
        message(FATAL_ERROR \${error_output})
      endif()
    else()
      message(STATUS \"Skipping  : \$ENV{DESTDIR}${dest}/${src_name}\")
    endif()
  ")
endfunction(install_if_not_exists)


(0041950)
Kitware Robot   
2016-06-10 14:28   
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.