In my root level CMake, I want to do both:
install its sub-directory "dir" as is on the machine: Using install(DIRECTORY dir) command
execute CMakeLists.txt of this sub-directory "dir" during build: Using add_subdirectory(dir) command.
It sounds logically possible to me, but I am not sure if that is really possibly as I might be missing something here.
Can somebody please confirm if both install(DIRECTORY dir) and sub_directory(dir) can be executed on a sub-directory "dir" from its parent directory's CMakeLists.txt ?
Related
I'm currently working on a project that is being built using CMake; it is then subsequently packaged up with CPack into an RPM.
The following is packaged into the RPM:
Several Executables
Configuration files
Some more context:
This project is running using OpenMPI, and there are X amount of nodes, depending on user input AND based on the # of nodes the user specifies, X docker containers are spawned.
There are instances of each executable running in tandem on each container
There is an OpenMPI crash and it is difficult to debug without GDB
The executables have been compiled as Release. However, if I want to make debugging possible I have been compiling the CMake project as Debug.
The executables are created as Debug. I have the VERBOSE=1 flag on when making the package and can confirm that -g flag is present, and the executables have debug symbols when loading them into GDB locally
Some lines in the CMakeLists.txt:
# Bunch of compilation lines above
install(TARGETS executable_1 executable_2 executable_3 DESTINATION bin) # Installs the executables into a local bin dir
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_INSTALL_PREFIX /usr)
install(DIRECTORY bin/ DESTINATION /usr/bin)
install(DIRECTORY config/ DESTINATION /etc/PROJECT_NAME FILES_MATCHING PATTERN "*")
# Making of the package
set(CPACK_PACKAGE_NAME "PROJECT_NAME")
set(CPACK_PACKAGE_VERSION 0.1)
set(CPACK_PACKAGE_RELEASE 1)
set(CPACK_GENERATOR "RPM")
set(CPACK_PACKAGE_VENDOR "ME")
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_RPM_PACKAGE_AUTOREQ 0)
set(CPACK_RPM_PACKAGE_RELOCATABLE True)
include(CPack)
The problem:
When CPack is doing its thing and creating the RPM, the executables can be packaged into the RPM, but the problem is they have improper permissions; aka when the executables are installed on the Containers, they cannot be executed. I can address this by adding:
# Bunch of compilation lines above
install(TARGETS executable_1 executable_2 executable_3 DESTINATION bin) # Installs the executables into a local bin dir
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_INSTALL_PREFIX /usr)
# Permissions Fix
set(PROGRAM_PERMISSIONS_DEFAULT
OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
install(DIRECTORY bin/ PERMISSIONS ${PROGRAM_PERMISSIONS_DEFAULT} DESTINATION /usr/bin)
install(DIRECTORY config/ DESTINATION /etc/PROJECT_NAME FILES_MATCHING PATTERN "*")
# Making of the package
set(CPACK_PACKAGE_NAME "PROJECT_NAME")
set(CPACK_PACKAGE_VERSION 0.1)
set(CPACK_PACKAGE_RELEASE 1)
set(CPACK_GENERATOR "RPM")
set(CPACK_PACKAGE_VENDOR "ME")
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_RPM_PACKAGE_AUTOREQ 0)
set(CPACK_RPM_PACKAGE_RELOCATABLE True)
include(CPack)
After adding the permissions, the permission are fixed, but for some reason the executables that are copied do not have debug symbols anymore; my local executables in the bin/ folder are the proper executables which have symbols, but the executables packaged into the RPM DOT NOT have debug symbols. Meaning somewhere along the way, something really odd is happening.
My question is, why? Either way results in a different problem. I'm wondering if there is a way to make sure the permissions are correct AND the proper executables get copied and packaged into the RPM. Any suggestions would be much appreciated.
Thanks!
Do not use absolute install destinations and do not read CMAKE_INSTALL_PREFIX, if you can avoid it. Using absolute install destinations (possibly indirectly through the use of CMAKE_INSTALL_PREFIX) forces you to run the install target with privileges that allow the process to modify those absolute paths. This usually means you have to use sudo to run the install target, even when installing to a directory owned by the standard user.
Since running cpack involves running the install target with the install prefix replaced with a directory inside the build directory (basically cmake --install ... --prefix ...), you can avoid the need for root privileges, if you use relative install locations.
My preferred the install logic here would be:
# allow the installation into any directory below the file system root
set(CMAKE_INSTALL_PREFIX /)
# set the default executable install location, see https://cmake.org/cmake/help/latest/command/install.html#installing-targets
# Note: could be set "globally", i.e. from the toplevel CMakeLists.txt allowing installation of individual targets
set(CMAKE_INSTALL_BINDIR usr/bin)
install(TARGETS executable_1 executable_2 executable_3 RUNTIME)
#preferrably replace this with install(FILES ... TYPE BIN) to install individual files
set(PROGRAM_PERMISSIONS_DEFAULT
OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
install(DIRECTORY bin/ PERMISSIONS ${PROGRAM_PERMISSIONS_DEFAULT} DESTINATION usr/bin)
# preferrably replace this with install(FILES ... TYPE SYSCONFIG)
install(DIRECTORY config/ DESTINATION etc/PROJECT_NAME FILES_MATCHING PATTERN "*")
# Making of the package
...
I assume in your scenario somewhere along the way you got the file permissions incorrect the cmake build / install / package process.
I want to download and use this repo:(https://github.com/rstebbing/subdivision-regression)
I have downloaded this repo, it's dependencies and their dependencies. Once downloaded, I've changed the CMakeList files (as instructed) with the new locations of the packages but when I try and 'sudo make install' it can't find the packages and won't install.
I am on a linux machine.
I downloaded these dependencies: ceres, common, gflags, rapidjson and believed they are install correctly.
When installing the subdivision I follow the git instructions and change the paths and ran cmake fine. When I use 'sudo make install' i get the error:
In file included from subdivision/doosabin/doosabin_pyx.h:12:0,
from subdivision/doosabin/doosabin_.cpp:615:
cpp/doosabin/include/doosabin.h:20:10: fatal error: Eigen/Dense: No such file or directory
#include "Eigen/Dense"
^~~~~~~~~~~~~
Even though I have specified the path to this file in the cpp/doosabin/CMakeLists and site.cfg:
site.cfg:
[Include]
EIGEN_INCLUDE ="/home/hert5584/RStebbing/eigen-git-mirror/"
COMMON_CPP_INCLUDE ="/home/hert5584/RStebbing/common/cpp/"ccd
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
PROJECT(DOO-SABIN)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
SET ( CMAKE_CXX_FLAGS "-std=c++11" )
MACRO(EXPECT_FILES VARIABLE)
FOREACH(EXPECTED_FILE ${ARGN})
IF (NOT EXISTS ${${VARIABLE}}/${EXPECTED_FILE})
MESSAGE(FATAL_ERROR
"Caller defined ${VARIABLE}: ${${VARIABLE}} does not contain "
"${EXPECTED_FILE}.")
ENDIF (NOT EXISTS ${${VARIABLE}}/${EXPECTED_FILE})
ENDFOREACH()
ENDMACRO(EXPECT_FILES)
SET(EIGEN_INCLUDE_DIR "/home/hert5584/RStebbing/eigen-git-mirror/")
EXPECT_FILES(EIGEN_INCLUDE_DIR Eigen/Dense)
INCLUDE_DIRECTORIES(${EIGEN_INCLUDE_DIR})
I also tested this without changing subdivision CMake files and only changing subdivions-regression and got a similar error about not finding functions.
Any help on how to install this properly, or any ideas about what I am doing wrong would be amazing!
Thank you
I made a mistake in setting up CMake. I was changing the paths manually inside the CMakeList files whereas it should be done with cmake:
cmake -DCOMMON_CPP_INCLUDE_DIR=/home/RStebbing/common/cpp -DEIGEN_INCLUDE_DIR=/home/RStebbing/eigen-git-mirror ../subdivision/cpp/doosabin/
Now working
I'm using CMake in the CLion IDE, and in my CMakeLists.txt I use the following command in order to copy some resource files into the binary directory:
file(COPY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_BINARY_DIR})
This works whenever my CMake project is reloaded in CLion. However, whenever I just try to build, the files aren't copied again. How do I fix this? Am I using the wrong command?
Use add_custom_target:
add_custom_target(copy_res_directory ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_SOURCE_DIR}/res" "${CMAKE_BINARY_DIR}/res"
COMMENT "Copy res directory to build tree"
VERBATIM)
Use configure_file(... COPYONLY)
I am new to CMake and am having a problem with how the files created by CMake are being organized.
First I will detail the file tree. I am trying to build a simple library with an example program from two source directories (Grid and examples) and a build directory. So, I have three CmakeLists.txt file. So, the top directory looks like this: CMakeLists.txt, /Grid, /examples, and /build.
This CMakeLists.txt contains:
project(talyfem)
cmake_minimum_required(VERSION 2.8.4)
set(CMAKE_CXX_FLAGS "-g")
add_subdirectory(examples Grid)
Within the Grid folder CmakeLists.txt is:
add_library(${PROJECT_NAME} FEMElm.cpp Grid.cpp GridField.cpp SuperGrid.cpp SuperGrid3D.cpp)
Within the examples folder CmakeLists.txt is:
set(EXAMPLES example1)
foreach(example ${EXAMPLES})
add_executable(${example} ${example}.cpp)
target_link_libraries(${example} ${PROJECT_NAME})
endforeach(example)
I run CMake from the build directory as: Cmake ../
When I do this it creates a strange file structure that I can't figure out and doesn't seem correct. First, it creates a ../build/CMakeFiles folder, which is what I would expect. But, then it creates a ../build/Grid folder and within this folder is another CMakeFiles folder that then contains an example1.dir folder. If I switch the order of the sub-directories, which Grid first and examples second the opposite occurs with Grid.dir being inside a examples sub-directory.
This doesn't seem correct and I would appreciate any assistance in fixing this problem.
I would expect that ../build/CMakeFiles should contain a Grid.dir and an examples.dir folder.
The error is in the way you use add_subdirectory. From CMake Docs:
add_subdirectory(source_dir [binary_dir]
[EXCLUDE_FROM_ALL])
So when you give add_subdirectory two arguments the first is interpreted as a source directory, and the second as the directory where this source should be built.
What you want is to call add_subdirectory twice:
add_subdirectory(examples)
add_subdirectory(Grid)
How do I tell cmake where it should output its build data?
Let's say I have a dir with the source code called src/,
and then since cmake outputs a lot of files I would like him to put all of that in
a dir called build/.
BUT I would like him to put the generated Makefile in the project root,
so I don't have to go into the build dir to build the application.
Is this possible with cmake?
I have managed to get the cmake out put if I fun cmake in the build dir like this:
cd build/
cmake ../src/
make
./hello
But it would be nice to stay in the project root and type something like this
cmake
make
./hello
I guess that I need to put a CMakeList.txt in the project root with some magic commands telling him where he could put the object files and where he can find the source code.
Thanks
Update:
Since my question is a little bit vague.
After I have run the cmake commands this is how I would like my tree to look like:
src/CMakeLists.txt
src/hello.c
src/hello.h
build/CMakeCache.txt
build/CMakeFiles/
build/cmake_install.cmake
CMakeLists.txt
Makefile
So the question is how should the CMakeLists.txt look like in this setup.
CMakeLists.txt
src/CMakeLists.txt
But maybe that is not possible?
BUT I would like him to put the generated Makefile in the project root, so I don't have to go into the build
dir to build the application.
cmake not designed for that, as I know,
BUT you can stay in the project root and type:
make -C build
./hello
with custom build rules or set_target_properties,
you can force cmake to put result executable to
sources directory or you can use
./build/hello
Type "cd build && cmake .." you need only once,
after that make will automaticaly start cmake, if something
changed.
cmake wants you to have a fresh build directory.
Okay, i get what you want. I think, you can achieve this with some machinery in CMakeLists.txt. Of course, it's not option if you are not project developer.
In root CMakeLists.txt you can add file(WRITE ...) command, which would write Makefile into ${CMAKE_SOURCE_DIR}. This Makefile would contain these commands for every target:
<target>:
cd ${CMAKE_BUILD_DIR} && ${CMAKE_MAKE_PROGRAM} <target>
So, now you can run make from source dir and it will build your project in build dir.
Simply use
cmake .
make
in your src directory. The (.) dot on unix systems addresses the current directory. Keep in mind doing so is actually not recommended since there will be a lot of build files in your src directory you'll have to clean up afterwards or at release time.