Discussion:
[CMake] Only install file if it does not exist?
Bob Tanner
2009-09-09 05:29:21 UTC
Permalink
I must be missing something simple?

During "make install" I only want to install a set of files if the do
not exist in destination.

MACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)
ADD_CUSTOM_COMMAND (
TARGET COPY
IF (NOT EXISTS ${DESTINATION})
COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE} ${DESTINATION}
ENDIF (NOT EXISTS ${DESTINATION})
)

ADD_CUSTOM_TARGET (
COPY ALL
COMMENT "Copy file: ${SOURCE} ${DESTINATION}"
)

ENDMACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)

Works the first time, but if I delete the destination file a make
install won't install it again.

Any help?
--
Bob Tanner <***@real-time.com> | Phone : (952 943-8700
http://www.real-time.com, Linux, OSX, VMware | Fax : (952)943-8500
Key fingerprint = F785 DDFC CF94 7CE8 AA87 3A9D 3895 26F1 0DDB E378
Eric Noulard
2009-09-09 07:20:56 UTC
Permalink
Post by Bob Tanner
I must be missing something simple?
During "make install" I only want to install a set of files if the do not
exist in destination.
MACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)
       ADD_CUSTOM_COMMAND (
               TARGET COPY
               IF (NOT EXISTS ${DESTINATION})
                       COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE}
${DESTINATION}
               ENDIF (NOT EXISTS ${DESTINATION})
       )
       ADD_CUSTOM_TARGET (
               COPY ALL
               COMMENT "Copy file: ${SOURCE} ${DESTINATION}"
       )
ENDMACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)
Works the first time, but if I delete the destination file a make install
won't install it again.
With your current macro the file is "installed" at CMake run time and
not during "make install".

You may check that fact if you rerun cmake the file is copied again.

You should look at the install(SCRIPT or install(CODE command
in order to execute CMake script at "install time".
--
Erk
Membre de l'April - « promouvoir et défendre le logiciel libre » -
http://www.april.org
David Cole
2009-09-09 10:53:15 UTC
Permalink
Or just use "install(FILES" -- it already does the "if not exists, if newer
than" checks...
Actually, what you have now is a strange combination of checking for the
file's existence at "CMake configure" time, but then running a custom
command at "make" time -- both of which happen before "make install"
entirely.


HTH,
David
Post by Eric Noulard
Post by Bob Tanner
I must be missing something simple?
During "make install" I only want to install a set of files if the do not
exist in destination.
MACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)
ADD_CUSTOM_COMMAND (
TARGET COPY
IF (NOT EXISTS ${DESTINATION})
COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE} ${DESTINATION}
ENDIF (NOT EXISTS ${DESTINATION})
)
ADD_CUSTOM_TARGET (
COPY ALL
COMMENT "Copy file: ${SOURCE} ${DESTINATION}"
)
ENDMACRO (COPY_IF_DOES_NOT_EXIST SOURCE DESTINATION)
Works the first time, but if I delete the destination file a make install
won't install it again.
With your current macro the file is "installed" at CMake run time and
not during "make install".
You may check that fact if you rerun cmake the file is copied again.
You should look at the install(SCRIPT or install(CODE command
in order to execute CMake script at "install time".
--
Erk
Membre de l'April - « promouvoir et défendre le logiciel libre » -
http://www.april.org
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
http://www.cmake.org/Wiki/CMake_FAQ
http://www.cmake.org/mailman/listinfo/cmake
Bob Tanner
2009-09-10 04:15:18 UTC
Permalink
On 2009-09-09 05:53:15 -0500, David Cole
Post by David Cole
Or just use "install(FILES" -- it already does the "if not exists, if newer
than" checks...
INSTALL (
FILES ${CMAKE_CURRENT_SOURCE_DIR}/sample_features
DESTINATION etc
RENAME features
)

Using that, if "etc/features" exists and I run "make install" features
gets overwritten every time.

$ file etc/features
etc/features: ASCII English text

$ echo "XXXXXXXXX" >> etc/features
$ grep "XXXXXXXXX" etc/features
XXXXXXXXX

$ cd path/in-source/build
$ make install

$ grep "XXXXXXXXX" etc/features
$ echo $?
1

Here is the Makefile login I'm attempting to mimic:

if [ ! -f $(DESTDIR)$(SYSCONFDIR)/features ]; then \
$(INSTALLDATA) ${srcdir}/sample_features $(DESTDIR)$(SYSCONFDIR)/features ; \
fi
--
Bob Tanner <***@real-time.com> | Phone : (952 943-8700
http://www.real-time.com, Linux, OSX, VMware | Fax : (952)943-8500
Key fingerprint = F785 DDFC CF94 7CE8 AA87 3A9D 3895 26F1 0DDB E378
Eric Noulard
2009-09-10 06:12:43 UTC
Permalink
Post by Bob Tanner
Post by David Cole
Or just use "install(FILES" -- it already does the "if not exists, if newer
than" checks...
INSTALL (
       FILES ${CMAKE_CURRENT_SOURCE_DIR}/sample_features
       DESTINATION etc
       RENAME features
)
Yes I think you want a different behavior than that.

I think you want:
"Do not install if FILE IS ALREADY THERE"

but I think INSTALL(FILES do
"Dot not install IF FILE EXISTS OR IS NEWER"

You should try to:

1) put your initial CMake script logic using IF(EXISTS "...
in a CopyIfNotExists.cmake file

2) use INSTALL(SCRIPT CopyIfNotExists.cmake)

You may have to write parameterized CopyIfNotExists.cmake.in which
configured using CONFIGURE_FILE because CopyIfNotExists.cmake
will be executed at install time with no variables coming from your
CMakeLists.txt defined.

So the most general way may be :

0) Write your parameterized CMake script CopyIfNotExists.cmake.in

1) CONFIGURE_FILE(CopyIfNotExists.cmake.in CopyIfNotExists.cmake)
This step will replace appropriate vars in CopyIfNotExists.cmake.in
with value coming from your current config.

2) INSTALL(SCRIPT CopyIfNotExists.cmake)

Should makes it possible to run any CMake scripts at install time.
Note however that in the CopyIfNotExists.cmake[.in] scripts you are
in CMake scripting mode (the one used when CMake -P) so you
may not use INSTALL command inside that one
(anyone correct me if I'm wrong)
but you already did that using the "cmake -E copy"
--
Erk
Membre de l'April - « promouvoir et défendre le logiciel libre » -
http://www.april.org
Bob Tanner
2009-09-11 18:36:36 UTC
Permalink
On 2009-09-10 01:12:43 -0500, Eric Noulard
Post by Eric Noulard
0) Write your parameterized CMake script CopyIfNotExists.cmake.in
1) CONFIGURE_FILE(CopyIfNotExists.cmake.in CopyIfNotExists.cmake)
This step will replace appropriate vars in CopyIfNotExists.cmake.in
with value coming from your current config.
2) INSTALL(SCRIPT CopyIfNotExists.cmake)
Thank you for your help!

I tried this approach.

CMakeLists.txt

INSTALL (SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/CopyIfNotExists.cmake)

CopyIfNotExists.cmake

MACRO (COPY_IF_NOT_EXISTS _SRC _DEST)
MESSAGE ("Copy ${CMAKE_CURRENT_SOURCE_DIR}/${_SRC} to
${CMAKE_INSTALL_PREFIX}/${_DEST}")
IF (NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${_DEST})
EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${_SRC}

${CMAKE_INSTALL_PREFIX}/${_DEST})
ENDIF (NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${_DEST})
ENDMACRO (COPY_IF_NOT_EXISTS _SRC _DEST)

COPY_IF_NOT_EXISTS ("sample_features" "etc/features")

The problem is ${CMAKE_CURRENT_SOURCE_DIR} is set to the out-of-source
build directory.

Is this why you said to use a parameterized cmake script?
--
Bob Tanner <***@real-time.com> | Phone : (952 943-8700
http://www.real-time.com, Linux, OSX, VMware | Fax : (952)943-8500
Key fingerprint = F785 DDFC CF94 7CE8 AA87 3A9D 3895 26F1 0DDB E378
Eric Noulard
2009-09-11 18:47:40 UTC
Permalink
Post by Bob Tanner
0)  Write your parameterized  CMake script CopyIfNotExists.cmake.in
1)  CONFIGURE_FILE(CopyIfNotExists.cmake.in CopyIfNotExists.cmake)
    This step will replace appropriate vars in CopyIfNotExists.cmake.in
    with value coming from your current config.
2)  INSTALL(SCRIPT CopyIfNotExists.cmake)
Thank you for your help!
I tried this approach.
CMakeLists.txt
INSTALL (SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/CopyIfNotExists.cmake)
CopyIfNotExists.cmake
MACRO (COPY_IF_NOT_EXISTS _SRC _DEST)
       MESSAGE ("Copy ${CMAKE_CURRENT_SOURCE_DIR}/${_SRC} to
${CMAKE_INSTALL_PREFIX}/${_DEST}")
       IF (NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${_DEST})
               EXECUTE_PROCESS (COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${_SRC}
${CMAKE_INSTALL_PREFIX}/${_DEST})
       ENDIF (NOT EXISTS ${CMAKE_INSTALL_PREFIX}/${_DEST})
ENDMACRO (COPY_IF_NOT_EXISTS _SRC _DEST)
COPY_IF_NOT_EXISTS ("sample_features" "etc/features")
The problem is ${CMAKE_CURRENT_SOURCE_DIR} is set to the out-of-source build
directory.
Is this why you said to use a parameterized  cmake script?
Yes you are right.
Most (if not all) variable you expect to use are not defined when
CopyIfNotExists.cmake is invoked.
--
Erk
Membre de l'April - « promouvoir et défendre le logiciel libre » -
http://www.april.org
Continue reading on narkive:
Loading...