Can I get the system home directory in CMake on Linux?
Home directory is referred to by the HOME
environment variable, so you can access it in CMake script by:
$ENV{HOME}
How do I get project root dir in the cmake install [code] section?
Is it a bug? Or I do something wrong?
No, it's just that not all variables are available in install(CODE)
segments. Here's a simple demo of detecting all the variables available there:
cmake_minimum_required(VERSION 3.24)
project(example)
install(CODE [[
get_property(vars DIRECTORY PROPERTY VARIABLES)
foreach (var IN LISTS vars)
message(STATUS "${var} = ${${var}}")
endforeach ()
]])
See in the terminal:
$ cmake -S . -B build
-- Install configuration: ""
-- CMAKE_ARGC = 4
-- CMAKE_ARGV0 = /home/reinking/.local/lib/python3.9/site-packages/cmake/data/bin/cmake
-- CMAKE_ARGV1 = -DCMAKE_INSTALL_PREFIX=foo
-- CMAKE_ARGV2 = -P
-- CMAKE_ARGV3 = /path/to/build/cmake_install.cmake
-- CMAKE_BINARY_DIR = /path/to
-- CMAKE_COMMAND = /home/reinking/.local/lib/python3.9/site-packages/cmake/data/bin/cmake
-- CMAKE_CPACK_COMMAND = /home/reinking/.local/lib/python3.9/site-packages/cmake/data/bin/cpack
-- CMAKE_CROSSCOMPILING = FALSE
-- CMAKE_CTEST_COMMAND = /home/reinking/.local/lib/python3.9/site-packages/cmake/data/bin/ctest
-- CMAKE_CURRENT_BINARY_DIR = /path/to
-- CMAKE_CURRENT_LIST_DIR = /path/to/build
-- CMAKE_CURRENT_LIST_FILE = /path/to/build/cmake_install.cmake
-- CMAKE_CURRENT_SOURCE_DIR = /path/to
-- CMAKE_FILES_DIRECTORY = /CMakeFiles
-- CMAKE_HOST_SYSTEM_NAME = Linux
-- CMAKE_HOST_UNIX = 1
-- CMAKE_INSTALL_CONFIG_NAME =
-- CMAKE_INSTALL_PREFIX = foo
-- CMAKE_INSTALL_PREFIX = foo
-- CMAKE_INSTALL_SO_NO_EXE = 1
-- CMAKE_MAJOR_VERSION = 3
-- CMAKE_MINOR_VERSION = 24
-- CMAKE_OBJDUMP = /usr/bin/objdump
-- CMAKE_PATCH_VERSION = 1
-- CMAKE_ROOT = /home/reinking/.local/lib/python3.9/site-packages/cmake/data/share/cmake-3.24
-- CMAKE_SCRIPT_MODE_FILE = /path/to/build/cmake_install.cmake
-- CMAKE_SOURCE_DIR = /path/to
-- CMAKE_TWEAK_VERSION = 0
-- CMAKE_VERSION = 3.24.1
-- UNIX = 1
So if you want to bake a variable into your install script, you'll have to generate the file. Here's one technique:
string(CONFIGURE [[
set(PROJECT_SOURCE_DIR "@PROJECT_SOURCE_DIR@")
message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
]] install_script @ONLY)
install(CODE "${install_script}")
How to specify the path where CMake is installed in the CMakeLists.txt
CMake will use whatever path the running CMake executable is in. Furthermore, it may get confused if you switch paths between runs without clearing the cache.
So what you have to do is simply instead of running cmake <path_to_src>
from the command line, run ~/usr/cmake-path/bin/cmake <path_to_src>
.
You may want to add an alias or a shell script to the path that is a little more typeable (so you only have to type my_cmake <path_to_src>
or something like that).
Note that there is no clean way to solve this by just editing the CMakeLists.txt
. While in theory you could have CMake 2.6 run an outer CMake script that does nothing but running an inner CMake script from a 3.0 executable, that's just a dirty hack. Just run the correct executable from the command line and you should be fine.
How to install binaries to user's home directory by CPack?
You may use environment variable HOME
for refer to user's home directory:
set(CPACK_PACKAGING_INSTALL_PREFIX "$ENV{HOME}/${CPACK_PACKAGE_NAME}")
Finding the source root directory in CMake for ROS
Disclaimer: the question is still a bit unclear to me, so apologies in advance if the answer does not reflect your needs.
If the problem you want to solve is that you have a lot of directories like src
in which the same top-level CMakeLists.txt
is linked and you want to include a specific CMakeExtras.txt
that resides in each particular directory, then you can solve this by adding:
include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeExtras.txt)
to your top-level CMakeLists.txt
. According to the documentation:
This the full path to the source directory that is currently being processed by cmake
and should solve this issue (i.e. the variable refers to the directory being processed, not to the CMakeLists.txt
where it is used).
If instead your issue is how to compute the src
path, given that a link to the top level CMakelists.txt
is there, then you simply want to use PROJECT_SOURCE_DIR which:
is the source directory of the most recent project() command.
CMAKE include src and install directories on different OS
On windows usually the install prefix is something like C:/Program Files/<Package Name>
, the usual install prefix on Unix being /usr/local
. Usually this directory contains subdirectories like include
containing the headers, lib
containing (import) libraries, ect..
Using MSVC for the Windows targets those include directories are not automatically available to the compiler.
This is the reason why you should try to use find_package
, if package configuration scripts or find scripts are provided by the installation which has the added benefit of also adding any dependencies with just 2 commands in your cmake project (find_package
and target_link_libraries
). If the package is installed in the default location, find_package
should be able to locate the scripts to load without specifying the install location manually.
For packages not providing this kind of info, writing a find script of your own creating imported targets allows for easy reuse.
Can something like this work?
install(FILES include/sort/sort.hpp DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${CMAKE_PROJECT_NAME}/sort)
In general you should avoid hardcoding absolute destination paths into your install paths. Instead use destination paths relative to the install prefix, since the install prefix may be overwritten, e.g. if the user runs the installation via cmake --install <build dir> --prefix <install directory>
or when using cpack
to generate a package.
Usually you place public headers of your library in a separate directory, even in your sources (which you seem to be doing) and install the directory with
install(DIRECTORY include/sort TYPE INCLUDE)
Resulting in cmake choosing the exact location based on its defaults for the include files for the target system.
Using cmake: General use of directories and especially default location of output binaries
Build directory is UNRELATED to the place, where deliverable files will be installed.
Build directory is a working directory, where compiler, linker and other tools generate deliverable files with some other auxiliary files. E.g., object files (.o
) are auxiliary files: they are produced by compiler, used by the linker and are never installed. Also, build directory contains Makefile
s and some other files, used by make
.
When install files, make install
takes deliverable files from build directory, and place them into their final locations. After that project is ready for use, and build directory can be removed.
Place, where deliverable files are installed, is controlled by variable
CMAKE_INSTALL_PREFIX
which you can set in cmake gui tool after the first configuration occures. Normally, binary files are installed into bin/
subdirectory relative to that prefix, so you may set CMAKE_INSTALL_PREFIX to /usr/local
for get executables being installed into /usr/local/bin/
.
As for build directory, you may create it anywhere. Usually, it is created in the directory where user has write access, so neither configuration nor build requires root priveleges. E.g., you may choose /home/<user>/cmake-build
.
How to make cmake output to the build directory?
The usual way to do this, rather than changing variables to set the path, is simply to create the output directory, change to it, and run cmake from there. So instead of cmake .
you usually have cmake ..
or similar.
I understand the initial impulse to say "But I expect my build system to write output somewhere else." But CMake is not usually used in the way you were initially expecting, and other people who run your CMake build won't expect what you were expecting, so it's probably best to just use the built-in, default behavior, which is to put the output wherever cmake
was run.
Put another way: You are fighting against the tool. Don't do that.
Related Topics
Apache Httpd VS. Tomcat 7: Port 80 VS. Port 8080
Unix - Combine All Rows into a Comma-Separated Single Row
Graphics Card Memory and Virtual Address Space of a Process
Checking If a Screen of The Specified Name Exists
Stdin into Zip Command, How to Specify a File Name
Linux Append Console Output to a Logfile
How to Sleep 10 Seconds Before Running a Linux Command
How to Generate a Static HTML File from a Swagger Documentation
What's The Purpose of Mmap Memory Protection Prot_None
Linux Service Can't Load Library Path in The /Etc/Ld.So.Conf.D
Under What Circumstances Does The Read() Syscall Return 0
How to Add Export Statement in a Bash_Profile File
How to Access Environment Variables Inside .Gdbinit and Inside Gdb Itself
Alsa: How to Duplicate a Stream on 2 Outputs and Save System Configs