0

I have a file called adhoc.cpp.proto in ${SRC_DIR}. I need to copy it to a file named adhoc.cpp in ${SRC_DIR} in preparation for some other tasks. I prefer to create the file if it does not exists, but I'll take an unconditional copy to keep things simple.

According to Copy file from source directory to binary directory using CMake I should be able to use configure_file(old new COPYONLY) or file(COPY old DESTINATION new). Neither work for me. configure_file(old new COPYONLY) does nothing, and file(COPY old DESTINATION new) creates a directory called new and puts the file old in it.

According to the file command docs GENERATE may also work. The problem is, I can't figure out how to use it from the docs and I can't find examples of it.

How do I unconditionally copy ${SRC_DIR}/old to ${SRC_DIR}/new?


In case it is needed, testing is happening on Fedora 28 with:

$ cmake --version
cmake version 3.11.2

But I need this to work back to CMake 2.8, which is what is found in the field for current distros.


$ cat CMakeLists.txt
# <head notes ...>

cmake_minimum_required(VERSION 2.8.6)
if (${CMAKE_VERSION} VERSION_LESS "3.0.0")
  project(cryptopp)
  set(cryptopp_VERSION_MAJOR 7)
  set(cryptopp_VERSION_MINOR 0)
  set(cryptopp_VERSION_PATCH 0)
else ()
  cmake_policy(SET CMP0048 NEW)
  project(cryptopp VERSION 7.0.0)
  if (NOT ${CMAKE_VERSION} VERSION_LESS "3.1.0")
    cmake_policy(SET CMP0054 NEW)
  endif ()
endif ()

set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR})

include(GNUInstallDirs)
include(CheckCXXCompilerFlag)

# Create adhoc.cpp from adhoc.cpp.proto.
# configure_file(adhoc.cpp.proto adhoc.cpp COPYONLY)
# file(COPY ${SRC_DIR}/adhoc.cpp.proto DESTINATION/${SRC_DIR} adhoc.cpp)
file(COPY ${SRC_DIR}/adhoc.cpp.proto DESTINATION ${SRC_DIR} adhoc.cpp)
...

configure_file(adhoc.cpp.proto adhoc.cpp COPYONLY) produces:

cmake_build$ rm -rf * && rm -rf ../adhoc.cpp && cmake ..
-- The C compiler identification is GNU 8.2.1
...
# Nothing is copied
cmake_build$ ls ../adhoc*
../adhoc.cpp.proto

file(COPY ${SRC_DIR}/adhoc.cpp.proto DESTINATION ${SRC_DIR}/adhoc.cpp) creates directories:

cmake_build$ rm -rf * && rm -rf ../adhoc.cpp && cmake ..
-- The C compiler identification is GNU 8.2.1
...
# Puts old file in directory
cmake_build$ ls ../adhoc*
../adhoc.cpp.proto

../adhoc.cpp:
adhoc.cpp.proto

file(COPY ${SRC_DIR}/adhoc.cpp.proto ${SRC_DIR}/adhoc.cpp DESTINATION ${SRC_DIR}) fails:

cmake_build$ rm -rf * && rm -rf ../adhoc.cpp && cmake ..
-- The C compiler identification is GNU 8.2.1
...
CMake Error at CMakeLists.txt:65 (file):
  file COPY cannot find "/home/test/cryptopp/adhoc.cpp".

file(GENERATE OUTPUT ${SRC_DIR}/adhoc.cpp ${SRC_DIR}/adhoc.cpp.proto CONDITION true) fails, too (as does CONDITION 1):

cmake_build$ rm -rf * && rm -rf ../adhoc.cpp && cmake ..
-- The C compiler identification is GNU 8.2.1
...
CMake Error at CMakeLists.txt:66 (file):
  file Incorrect arguments to GENERATE subcommand.

file(WRITE ${SRC_DIR}/adhoc.cpp file(READ ${SRC_DIR}/adhoc.cpp.proto)) creates the file but it does not evaluate the file(READ ...) expression:

cmake_build$ rm -rf * && rm -rf ../adhoc.cpp && cmake ..
-- The C compiler identification is GNU 8.2.1
...

$ cat ../adhoc.cpp
file(READ/home/test/cryptopp/adhoc.cpp.proto)
jww
  • 97,681
  • 90
  • 411
  • 885
  • Did my answer help you? – Bernhard Nov 08 '18 at 13:56
  • @Bernhard - No, it did not work for me. CMake creates a directory with the new filename and then copies the original file into the directory. – jww Nov 08 '18 at 14:09
  • Wait, you want to copy from the source directory into the source directory? Why? That does not make sense to me – Bernhard Nov 08 '18 at 16:44
  • @Bernhard - We are unpacking a template file. – jww Nov 08 '18 at 16:48
  • That does not mean anything to me in this context. One of the reasons to use cmake is to clearly separate source and build. Either unpack into build and compile from there, or unpack it in source before cmake – Bernhard Nov 08 '18 at 18:16
  • @Bernhard - My bad. Let me rephrase... We are trying to copy and rename a file in one operation. – jww Nov 08 '18 at 18:19
  • The thing that I don't get is why the destination is the source directory – Bernhard Nov 09 '18 at 03:46

1 Answers1

1

You have found the right commands. Both configure_file and file(COPY) are perfectly capable to do what you want.

For file(COPY), keep in mind that the DESTINATION is a directory, not a filename. It will create the directory in case it is does not exists. You are creating a directory adhoc.cpp in your source directory. That is why you probably have a rm -rf ../adhoc.cpp.

Your configure_file seems legit. But, configure_file says that if the destination is a directory, it will place it in there. Maybe you have a conflict with the other things you did.

My recommendation to prevent these things it to always have an out-of-source build, rather than in-source as you have it now. Is ${SRC_DIR} something you define yourself? Why not ${CMAKE_CURRENT_SOURCE_DIR}? Although in this case I don't think you need to do this anyhow, that's for CMake to figure out.

Bernhard
  • 3,619
  • 1
  • 25
  • 50