What is the difference between install(FILES) and file(INSTALL)? - cmake

I'm trying to move a file to a specific location, and I did it like this:
file(INSTALL file.txt DESTINATION ../install_dir)
This worked fine. This moved file.txt to the specified destination.
However then I tried like this:
install(FILES ./file.txt DESTINATION ./install_dir)
Using install(FILES) doesn't copy files like I expect. The file is not installed at that location when I run the CMake configure command.
Can someone please explain the difference to me? Why is it that file(INSTALL) works when running the configure command, but install(FILES) doesn't?

The two commands do different things. install(FILES fil DESTINATION dest) instructs CMake to generate a build rule so that file fil is copied into dest when running the install step (make install or equivalent).
file(INSTALL ...) is evaluated immediately at configure time, while CMake is parsing the CMakeLists.txt file. Note that this signature is primarily intended for CMake's internal implementation of the above mentioned installation step: it prints install-themed status messages etc. If you just want to copy a file at configure time, you might want to prefer file(COPY) or file(COPY_IF_DIFFERENT).

Related

Find a CMake file-generating add_custom_command example in which DEPENDS option is necessary

I want a simple example to illustrate the DEPENDS option of file generating add_custom_command(OUTPUT ...), that is, if we comment the DEPENDS part, the example will give different output or totally crash.
In the following example (there are files london and good.cpp in the current working directory), DEPENDS is dispensable:
cmake_minimum_required(VERSION 3.10)
project(Tutorial VERSION 1.0)
add_custom_command(OUTPUT foo
COMMAND cp london foo
#DEPENDS london
COMMENT "I'm testing the new method.")
add_executable(cake good.cpp foo)
I did read the documentation. I have little knowledge about building system, neither Make nor CMake. The first sentence Specify files on which the command depends. confuses me. I don't understand how a command depends on other files, in my casual example, the command line itself seems to locate everything. I want a CMake code example to show how command depends on other files, with the necessary help of DEPENDS.
The phrase in documentation
Specify files on which the command depends.
is better understandable as
Specify files on which content of the command's output file(s) depends.
As one could guess, a content of the output file of the command cp london foo depends only from london, so it is reasonable to specify option DEPENDS london for add_custom_command.
As a build system, CMake uses information in DEPENDS for decide, whether to run the command or not. If:
OUTPUT file has already been created on previous run, and
since previous run the DEPENDS file has not been updated,
then the command won't be run again. The reasoning is simple: no needs to run the command if it results with the same file(s).
Taking into account source (CMAKE_SOURCE_DIR) and build (CMAKE_BINARY_DIR) directories separation, the example could be rewritten as follows:
cmake_minimum_required(VERSION 3.10)
project(Tutorial VERSION 1.0)
add_custom_command(
OUTPUT foo # relative path denotes a file in the build directory
COMMAND cp ${CMAKE_SOURCE_DIR}/london foo # The command will be run from the build directory,
# so need to use absolute path for the file in the source directory
DEPENDS london # relative path is resolved in the source directory,
# assuming that corresponded file is already existed
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} # specifies a directory from which run the COMMAND
# build directory is used by default, so the option can be omitted
COMMENT "I'm testing the new method."
)
add_executable(cake
good.cpp # relative path is resolved in the source directory,
# assuming that corresponded file is already existed
foo # because given file is absent in the source directory,
# the path is resolved relative to the build directory.
)
When build the project the first time, both foo and executable will be built.
When build the project the second time (without changing in london) nothing will be rebuilt.
When change london file and build the project again, foo will be re-built (because it depends on london). As foo is rebuilt, the executable will be rebuilt too, because it depends on foo.

CMake custom command always executes

In my CMakeLists.txt, I define a custom target and command:
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv
COMMAND python3
${CMAKE_CURRENT_SOURCE_DIR}/tests/genVectors.py)
add_custom_target(TEST_VECTORS
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv)
add_executable(VectorTest tests/VectorTest.cpp)
add_dependencies(VectorTest TEST_VECTORS)
It always generates new CSV files even though the files exist. I only need to generate the vectors (with genVectors.py python file) if they do not exist. Is that something wrong with my configuration?
The OUTPUT option of add_custom_command does not guarantee that the generated files are placed here; it just tells CMake that the generated files are expected to be placed there. It is likely that your python script is generating files at a relative path, so they are just being placed somewhere in your CMake binary directory (your build folder). So while your files may be generated correctly, your custom target doesn't see them because it is looking in CMAKE_CURRENT_SOURCE_DIR. Thus, the custom target will always trigger the custom command to re-run.
CMake runs add_custom_command from the CMAKE_CURRENT_BINARY_DIR by default, but you can change it to run from CMAKE_CURRENT_SOURCE_DIR by adding the WORKING_DIRECTORY option. This way, the generated files will be placed at the expected location, and achieve your desired behavior. Try something like this:
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv
COMMAND python3
${CMAKE_CURRENT_SOURCE_DIR}/tests/genVectors.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(TEST_VECTORS
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv)
add_executable(VectorTest tests/VectorTest.cpp)
add_dependencies(VectorTest TEST_VECTORS)
You can try to generate your file at time of configuration(i.e. while calling cmake). By this way it will created only once.
You can remove add_custom_command and use execute_process to create your files.

install(FILES "${CMAKE_CFG_INTDIR}/Abc_Win.dll" DESTINATION "Bin")

Because the 'Abc_Win.dll' is shared ('dll') and needs to be copied to the target-EXE I added a custom target - like this. I'm working with MS-VisualStudio 2005-2011 and using cmake 2.8.8.
add_custom_target( "Abc_Win.dll" )
add_custom_command( TARGET "Abc_Win.dll" POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"MyDllSource/${CMAKE_CFG_INTDIR}/Abc_Win.dll"
"MyExeDest/${MWEB_CMAKE_CFG_INTDIR}/Abc_Win.dll" )
set_property(Abc_Win.dll" PROPERTY FOLDER ${MWEB_FOLDER_ADDON}/${MWEB_FOLDER_RTE})
All above working like I expect and the 'Abc_Win.dll' get on the right place when I build.
Now I add an the following install command - expecting 'Abc_Win.dll' in "Bin"-Directory beside my EXE.
install(FILES "MyDllSource/${CMAKE_CFG_INTDIR}/Abc_Win.dll" DESTINATION "Bin")
When I build now the CMakePredefinedTargets->INSTALL (doesn't matter which MS-StudioVersion I use) I get always a build error in the cmake generated file 'cmake_install.cmake':
file INSTALL cannot find
"MyDllSource/$(Configuration)/Abc_Win.dll"
I understand that cmake does not uses build-rules from MS-VS - like it does it for add_custom_command. It also seems to be that this cmake-file has no glue from the Content $(CONFIGRATION) which is set actual to 'Debug'.
Has anybody an idea how to solve this Problem? Help would be very appreciated. Thanks.
There's an undocumented variable you can use here: CMAKE_INSTALL_CONFIG_NAME.
Unless you happen to have defined this yourself in your CMakeLists.txt, it will be undefined when CMake runs.
However, when you use install commands in your CMakeLists.txt, CMake generates a file called "cmake_install.cmake" in the root of your build tree (same place as CMakeCache.txt). This is executed at install time, and it sets CMAKE_INSTALL_CONFIG_NAME to your current configuration in Visual Studio.
There's another slight twist; to avoid CMake expanding ${CMAKE_INSTALL_CONFIG_NAME} in the install command (it would expand to an empty string), you need to escape it with a \.
So, you just need to change your install command to:
install(FILES "MyDllSource/\${CMAKE_INSTALL_CONFIG_NAME}/Abc_Win.dll"
DESTINATION "Bin")

CMake Configure File Build Rule

I'm using CMake for my build system and in the project, we will have a bunch of configuration files. Some of them will just need to be copied over, some will need to be modified per computer. I'm currently using CMake's "configure_file" command to copy/replace parts of the file. This works great, and I love how I can use any variable from CMake in the configure routine.
But if you change the original file, CMake will not pick this up and you have to rerun cmake for it to configure the directory. When I run "make", I want it to pick up that I've changed the file and rerun configure.
It will also reconfigure files always, even if the file it is overwriting is newer. I want it to act like a custom target.
I think I can do this with add_custom_command, but I don't think I can run a CMake command from add_custom_command. So is there anyway to duplicate the behaviour that configure_file does in CMake?
I recently upgraded to CMake 2.8. It seems like it automatically has the exact behavior I wanted.
I do not think this has an easy answer. I see two options:
To trigger a re-run of cmake if an input changes, you might be able to make your input file depend on CMakeLists.txt.
To run a cmake command as part of and add_custom_command, there is the variable ${CMAKE_COMMAND}, which will give you the path to the running cmake. You could, as part of the configure step, generate a fragment of CMake code (that calls configure_file) that is invoked using the -P option. Either pass substitutions on the command line using -D, or write them to the CMake fragment.

How to best handle data files with CMake?

I've got a CMake project that contains code and a few data files (images to be precise).
My directory structure is like this:
src
data
src contains the source code, data the data files. CMake suggests out of source builds, so when I invoke make, I have the executable program, but not the data files, thus I cannot execute the program.
Of course, make install would copy my data files to the required location and make it work, therefore I develop like this right now:
cmake -DCMAKE_INSTALL_DIR=dist
<edit source code>
make install
dist/myprogram.exe
That's okay if I'm working with the command line and an editor, but I recently decided to move to Eclipse CDT. Generating an Eclipse project from CMake works great, but manually executing the install target from Eclipse is not so nice.
How do you people tackle this problem? Does your program have some clever algorithms to try and find its data directory even if it's not where the binary is? Or do you not use out of source builds?
configure_file should solve that problem.
I have a CMakeLists.txt file in my data directory which contains the following:
configure_file(data_file ${CMAKE_CURRENT_BINARY_DIR}/data_file COPYONLY)
This copies the specified file into the build directory when cmake is invoked, so it is available in the same location even in out of source builds.
configure_file does not support directories however while the file command does:
file(COPY assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
And if copying the files takes too much time (they are images...) you could make it even better by creating a "custom" data_header.h with configure_file which contains the paths to the data still in your source-directory.
This is what I do: I have a file "global_build_config.h.in" in my source, containing the following:
const char* const global_testdatapath = "#Test_Data_Path#";
and then use configure_file in CMake:
# Assume CMake knows a variable Test_Data_Path, it will be filled in automatically
# in the generated config/Global_Build_Config.h
configure_file( Global_Build_Config.h.in ${CMAKE_BINARY_DIR}/config/Global_Build_Config.h )
# The config directory should be added as a include-searchpath
include_directories( ${CMAKE_BINARY_DIR}/config/ )
I can then #include "Global_Build_Config.h" in my cpp files and refer to the fixed path.
Your question is a bit old, but in case you're still interested (or someone else), I have a similar scenario where I copy testdata for a unit-test target:
add_custom_command( TARGET ${UTEST_EXE_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Copying unit test data.."
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_HOME_DIRECTORY}/utest/testdata ${CMAKE_BINARY_DIR}
)
So the main idea is to use a post-build target, and it is executed after each build. For me, it's not much data, and the filesystem caches it, so I don't feel the copy process at all. You could probably enhance this by copying with copy_if_different. In that case, however, you have to create a list of your image files and write a loop, because the command is file based. With the GLOB command, this shouldn't be hard to do if you need to.