CMake Error: file INSTALL destination is not a directory - cmake

I am running the command "sudo make install", the relevant cmake_install.cmake file is at the bottom. The exact error message I receive is:
CMake Error at cmake_install.cmake:36 (file):
file INSTALL destination:
~/Desktop/Geant/geant4.10.04-install/share/Geant4-10.4.0/geant4make is not
a directory.
Makefile:104: recipe for target 'install' failed
make: *** [install] Error 1
This is perplexing to me as I can navigate to that exact directory, it exists and whats more, it was made during this installation, so the make install is creating this directory and then saying that it doesn't exist...
Also, when I originally did the cmake command, my CMAKE_INSTALL_PREFIX is "~/Desktop/Geant/geant4.10.04-install", but since the make install command was able to make the geant4.10.04-install directory in the correct place, I don't think that is the problem.
The first 50ish lines of the cmake_install.cmake file (I can post the rest if need be...) :
# Install script for directory: /home/kagnew/Desktop/Geant/geant4.10.04
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "~/Desktop/Geant/geant4.10.04-install")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "Release")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Install shared libraries without execute permission?
if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
set(CMAKE_INSTALL_SO_NO_EXE "1")
endif()
if(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Development")
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/share/Geant4-10.4.0/geant4make" TYPE FILE MESSAGE_LAZY PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE FILES "/home/kagnew/Desktop/Geant/geant4-build/InstallTreeFiles/geant4make.sh")
endif()
UPDATE: As suggested by Tsyvarev, changing the beginning of my prefix path from "~" to "/home/user/" seems to have fixed the problem

Using the environmental variable $ENV{HOME} is preferable to hardcoding /home/<user> because it will use the correct top-level directory (i.e. /Users instead of /home on macOS, if you're doing a cross-platform build), and it will automatically expand to include the name of the user invoking cmake, making it better suited to collaborative environments.
Additionally, using $ENV{HOME} should make the sudo in front of make install unnecessary, though depending on when the variable is expanded, $ENV{HOME} may refer to the user invoking cmake or the user invoking make install (i.e. /root if you use sudo), so your mileage may vary.
EDIT: I found my way to this question because I was getting the same "CMake Error: file INSTALL destination is not a directory" output due to using ~. It would seem that for certain purposes CMake just really doesn't like ~. $ENV{HOME} has exactly the same value as ~, except that CMake doesn't freak out when you try to use it in CMAKE_INSTALL_PREFIX.

Related

CMake: Ask user permission to install dependencies

Many build systems (such as make) sometimes prompt the user to confirm his intention if large dependencies must be downloaded and installed from the internet to continue with the build process.
What is the best way to achieve this from CMake?
My example application. I'm adapting a CMakeLists.txt file that installs Google Test framework if it isn't found. How should I modify this to ask the user for permission before installing it?
Alternatively, perhaps this is not possible/standard and I should instead just require the user to pass a variable definition when calling CMake, to assert his consent to the download?
# Quote from:
# https://github.com/pabloariasal/modern-cmake-sample/blob/master/libjsonutils/test/CMakeLists.txt
# Commit hash 0c8272b621f2bfd819c406b575517fdeb05a38a7
# ---------------------- Below original contents. ------------------------------
# see /opt/local/share/cmake-3.16/Modules/FindGTest.cmake
find_package(GTest QUIET)
# NOTE: the upper case GTEST! CK
if(NOT GTEST_FOUND)
# Download and unpack googletest at configure time
# but only if needed! CK
configure_file(${CMAKE_SOURCE_DIR}/cmake/GoogleTest-CMakeLists.txt.in
${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
endif()
# Now simply link against gtest as needed. Eg
add_executable(json_utils_test src/main.cpp)
target_compile_features(json_utils_test PRIVATE cxx_auto_type)
target_link_libraries(json_utils_test gtest_main JSONUtils::jsonutils)
add_test(NAME json_utils_test
COMMAND json_utils_test)
Passing a variable to CMake is a proper way for specify an user decision.
Asking a user for confirm some default decision looks nice... but I fear CMake has no ready-to-use tools for that. Note, that configuration of the project could be requested both in shell/terminal (via cmake executable) and from CMake GUI, which is not connected with the user input.
Instead of asking the user for confirmation during the configuration process, you may fail configuration (e.g. with message(FATAL_ERROR)). But ship this fail with the message describing the variable a user needs to set.
# Variable-option for a user.
option(DOWNLOAD_GTEST "Whether GTest is needed to be downloaded" OFF)
if (DOWNLOAD_GTEST)
# User explicitly requests to download gtest.
# Do not try 'find_package' at all.
#
# Download and unpack googletest at configure time
configure_file(${CMAKE_SOURCE_DIR}/cmake/GoogleTest-CMakeLists.txt.in
${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt)
...
else()
# GTest download hasn't been requested.
# Try to find installed variant.
find_package(GTest)
if(NOT GTEST_FOUND)
# No installed variant has been found.
# Fail configuration with a notion about 'DOWNLOAD_GTEST' variable.
message(FATAL_ERROR "GTest has not been found. If you want to automatically download it, please set variable 'DOWNLOAD_GTEST': cmake -DDOWNLOAD_GTEST=ON")
endif()
endif()
With that CMakeLists.txt, if a user doesn't explicitly set variable DOWNLOAD_GTEST, then it is set to OFF. In that case GTest is searched with find_package. If search fails, then configuration process fails too but with a suggestion to set the variable.
If a user reruns cmake with the variable DOWNLOAD_GTEST set to ON, then GTest will be downloaded without extra messages.

Installing no longer existing files

I have a list of various files that I want to install, by executing a resulting INSTALL project. This works, but sometimes files are no longer available, when the install operation is executed. Environment is a build server, where files get moved around -> this causes the build to be faulty.
An easy way to fix this behaviour is in the OPTIONAL parameter of the install command. So my question is: Is there a way to output warnings at runtime, if the install command failed?
Here is my code, to recreate the issue. In the src directory there are files "1.txt" and "2.txt". I build the cmakelists.txt and then delete "2.txt". After that, I execute the INSTALL solution I got.
cmake_minimum_required(VERSION 3.0)
project(documentation)
set(SOURCEDOCUMENTATION "D:/projects/side_master/src/documentation/src")
set(TARGETDOCUMENTATION "D:/projects/side_master/src/documentation/tgt")
file (GLOB files_to_install "${SOURCEDOCUMENTATION}/*")
foreach(file_to_install ${files_to_install})
install(FILES ${file_to_install} DESTINATION ${TARGETDOCUMENTATION} OPTIONAL)
endforeach()
The error (without the OPTIONAL parameter):
-- Install configuration: "Debug"
-- Installing: D:/projects/side_master/src/documentation/tgt/1.txt
CMake Error at cmake_install.cmake:56 (file):
file INSTALL cannot find
"D:/projects/side_master/src/documentation/src/2.txt".
What I want to get is a generated message, like this:
File "D:/projects/side_master/src/documentation/src/2.txt" not found.
You could make use of the install(SCRIPT ...) or install(CODE ...) signatures of the CMake install command, to run custom installation steps specific to your use case. The custom steps here would check for the existence of the files (using CMake's EXISTS logic) to be installed, and print a warning message if the file does not exist. The custom installation command could look something like this:
install(CODE "
if(NOT EXISTS ${file_to_install})
message(WARNING \"File ${file_to_install} not found during installation.\")
endif()
")

error while working with Makefile project

I am trying to debug my Makefile based project which I have imported in CLion. I created a simple CMake file as below
cmake_minimum_required(VERSION 2.8.4)
project(Project1)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
add_custom_target(myProject COMMAND make -j4 DEBUG=1
CLION_EXE_DIR=${PACKAGE_DIR})
CMake tool shows me error: CMake executable not specified. I tried adding add_executable(myProject ${SOURCE_FILES}) with correct source files, but still same error.
Where as on Edit Configurations page, I cannot select any Configuration. The drop down for Configuration is empty. At the bottom I get error Error: Configuration is not specified..
When I try to debug the program, I get a warning message Configuration is still incorrect. Do you want to edit it again? I click on Continue Anyway, which compiles the program as I expect and it generates the correct executable file as well. But it cannot run the executable because of the errors in the Configurations.
I assume "CMake executable" refers to the location of the executable cmake which is called to configure your project. Probably you have to search for a setting in CLion where you can define /usr/bin/cmake or whereever your cmake resides.
This solved the problem for me (Ubuntu):
sudo apt-get install cmake

What is INSTALL_DIR useful for in ExternalProject_Add command?

I don't understand the usage of INSTALL_DIR in ExternalProject_Add command. I try to use it but it does not seem to work. Here is an example of a CMakeLists.txt, using Eigen library which compiles quickly:
cmake_minimum_required (VERSION 2.6)
project (example CXX)
include(ExternalProject)
include(ProcessorCount)
set(CMAKE_VERBOSE_MAKEFILE ON)
ProcessorCount(N)
if(NOT N EQUAL 0)
set(CMAKE_BUILD_FLAGS -j${N})
endif()
ExternalProject_Add
(
mylib
PREFIX myprefix
DOWNLOAD_COMMAND wget http://bitbucket.org/eigen/eigen/get/3.2.4.tar.gz && tar xvzf 3.2.4.tar.gz -C mylib --strip-components=1
)
I chose the following project hierarchy:
project
CMakeLists.txt
build/
From build repository, I type:
cmake ..
make
The installation process fails with the following message:
file cannot create directory: /usr/local/include/eigen3.
Maybe need administrative privileges.
As far as I understand, it means that I need to define a "prefix" during the configuration step:
cmake -D CMAKE_INSTALL_PREFIX=$INSTALL_DIR ..
But, the INSTALL_DIR variable is already defined in the ExternalProject_Add command. However, I get the same error when I modify the value of INSTALL_DIR by adding
INSTALL_DIR myprefix/src/install
in the ExternalProject_Add command.
So, what is INSTALL_DIR useful for?
What am I doing wrong?
Of course, I know how to provide my own configuration command to add a prefix and solve the problem. But it is not my question. My question is: if I have to do that, what is the purpose of INSTALL_DIR?
From what I found in this discussion https://www.mail-archive.com/cmake#cmake.org/msg51663.html (scroll to the end of the page to navigate through the thread messages) it is indeed pretty common thing to use CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/contrib
Furthermore, lurking through the ExternalProject.cmake module I found out that the only effect setting this directory has is that CMake will create directory specified in INSTALL_DIR before doing anything else.
Also, it will set the property that you can gather through ExternalProject_Get_Property(${project_name} install_dir) command.
And that's pretty much it.
// As of CMake version 3.2.2

Why set failed in CMAKE scripts

Suppose CMAKE_BINARY_DIR = C://a//b//c, and if I run the following cmake script:
cmake_minimum_required( VERSION 2.6 )
set(project_name "hello_cmake")
project(${project_name})
add_executable(hello src/main.cpp)
if(WIN32)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory" )
else()
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory")
endif()
I expect CMAKE_INSTALL_PREFIX = C://a//b//c//install if I do not define CMAKE_INSTALL_PREFIX when I first call cmake .. from the folder C://a//b//c. However, it does not work in that way, and CMAKE_INSTALL_PREFIX is given a strange folder: C://Program Files (x86)//hello_cmake. Any ideas?
This is the recommended CMake incantation for handling CMAKE_INSTALL_PREFIX:
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
SET(CMAKE_INSTALL_PREFIX <path> CACHE PATH <comment> FORCE)
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
Note the FORCE in the set. Apparently, the CMAKE_INSTALL_PREFIX is set fairly early in the invocation of CMake, which means it will already be set in the cache by the time you get to this line. Thus the need for FORCE.
Source is an email discussion on CMake mailing list: http://www.cmake.org/pipermail/cmake/2010-December/041135.html