How to get the working directory of the cmake process? - cmake

How to get the working directory from which cmake was called?
I know that I can run execute_process() at the beginning of my CMake code but maybe there is some better way like a built-in variable to the working directory of the CMake process.
What I want to achieve is to convert a relative path given in a CMake variable (given with -D...) to an absolute path in CMake.

What I want to achieve is to convert a relative path given in a CMake variable (given with -D...) to an absolute path in CMake.
Then simply create a cache variable of type PATH (for directories) or FILEPATH in your CMakeLists.txt. CMake will convert untyped command line arguments to absolute paths automatically.
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(test NONE)
set(input_file "" CACHE FILEPATH "some input file")
message(STATUS "${input_file}")
$ cmake -S . -B build -Dinput_file=foo.txt
-- /path/to/foo.txt
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
See the documentation:
It is possible for the cache entry to exist prior to the call but have no type set if it was created on the cmake(1) command line by a user through the -D<var>=<value> option without specifying a type. In this case the set command will add the type. Furthermore, if the <type> is PATH or FILEPATH and the <value> provided on the command line is a relative path, then the set command will treat the path as relative to the current working directory and convert it to an absolute path.
Here: https://cmake.org/cmake/help/latest/command/set.html?highlight=current%20working%20directory
Relatedly, when running in script mode (rather than project mode), several of the usual variables are set to the current working directory:
When run in -P script mode, CMake sets the variables CMAKE_BINARY_DIR, CMAKE_SOURCE_DIR, CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR to the current working directory.
https://cmake.org/cmake/help/latest/variable/CMAKE_SOURCE_DIR.html

Related

Cmake - how include paths with only read access? [duplicate]

Is it possible to specify an include directory when running cmake. For example
cmake . -INCLUDE=/foo/bar
The header files are in a separate directory from the sources that I would like to compile, and I would like to remedy this without tinkering with the Makefile generated by cmake.
Update
The project does have a CMakeLists.txt. Excerpt:
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
Can ${EO_SOURCE_DIR} be set from the command line?
If the path to your headers is fixed in relation to your sources, then you should be able to avoid having to pass this info via the command line.
Say your project's directory structure is:
/CMakeLists.txt
/my_sources/main.cpp
/my_sources/foo.cpp
/my_includes/foo.hpp
and in your CMakeLists.txt, you currently have something like:
add_executable(MyExe my_sources/main.cpp my_sources/foo.cpp)
then to add the /my_includes folder to the the list of include search paths, you only need to add the following:
include_directories(my_includes)
For further info about include_directories, run
cmake --help-command include_directories
Answer to update in question:
Yes, using the -D command line option just do
cmake . -DEO_SOURCE_DIR:PATH=<Path to required dir>
The variable ${EO_SOURCE_DIR} gets cached as a result of this, so you only need this -D argument once (unless the required path changes or you delete your CMakeCache file, etc.)
Proper way to do this is to define a variable in CMakeLists.txt and ask user to set it:
set(YOURLIB_INCLUDE_DIR "" CACHE FILEPATH "Path to yourlib includes")
if(NOT EXISTS ${YOURLIB_INCLUDE_DIR}/header.h)
message(SEND_ERROR "Can't find header.h in ${YOURLIB_INCLUDE_DIR})
endif()
include_directories(${YOURLIB_INCLUDE_DIR})
Now you can set it from the command line: cmake -D YOURLIB_INCLUDE_DIR=/path/to/yourlib/include .

CMake: Convert relative path to absolute path or the cmake command line arguments

I'm running my cmake (3.16) from outside the source. Usually with these arguments
cmake -S ./avionics_apps/ -B build -DINPUT_DIR:PATH=./other-build/
What is the way to convert the relative path set in INPUT_DIR variable to the absolute path that would equally work for out and in source builds? get_filename_component can be used, but it requires some base path. However, I couldn't yet find a variable in cmake that specifies the directory from which cmake was run. There are binary and source directories. But the in-source build the CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR are the same.
Thanks #fdk1342 for the hint. How the automatic conversion can be achieved:
When pass the variable via command line, do not specify its type:
-DINPUT_DIR=./other-build/
When declare the variable in CMakeLists.txt, do specify type as PATH or FILEPATH
set(INPUT_DIR "" CACHE PATH "Input directory")
Implicit creation of CACHE variable works too:
find_path(INPUT_DIR foo.h)
When both conditions are fulfilled, a value of the variable will be automatically converted into the absolute path.
Actually, this is described in the description of the set command:
It is possible for the cache entry to exist prior to the call but have no type set if it was created on the cmake(1) command line by a user through the -D<var>=<value> option without specifying a type. In this case the set command will add the type. Furthermore, if the <type> is PATH or FILEPATH and the <value> provided on the command line is a relative path, then the set command will treat the path as relative to the current working directory and convert it to an absolute path.

Command: `cmake . .`

I use cmake (https://cmake.org) to compile a program. However, I don't understand this command:
cmake . .
The command line reference shows that the positional arguments to cmake are either <path-to-source> or <path-to-existing-build>. However, the use of two positional arguments (as in your case) is not documented. It causes the first position argument to be the <path-to-source> (assuming it contains a CMakeList.txt), and the second to be the project binary directory.
Using two current directory (.) position arguments is equivalent to using only one, as the project binary directory defaults to the current directory if none is provided on the command line. Usually when using CMake and creating an out-of-source build, CMake would be run from the project binary directory, and the path to the source directory (only) is provided. This is the recommended use case.

Where does cmake look for .cmake scripts?

I am trying to execute_process in cmake like this
execute_process(COMMAND ${CMAKE_COMMAND} -P myScript.cmake
This only works if the file, myScript.cmake is in the same working directory.
Three related questions:
Does cmake have a standard location to look for .cmake scripts?
Is there a cmake variable I can define to tell cmake where to look? or
Should I always give a full path to the script (i.e., -P ${PATH_VAR}/myScript.cmake)?
Does cmake have a standard location to look for .cmake scripts?
For execute_process, no. The find_XXX commands (e.g. find_file) and include do though.
Is there a cmake variable I can define to tell cmake where to look?
Again, for execute_process, no. For find_xxx or include, you can set the variable CMAKE_MODULE_PATH.
Should I always give a full path to the script (i.e., -P ${PATH_VAR}/myScript.cmake)?
That's a good option; passing a full path leaves no room for uncertainty. However, you can get away with a relative path too. The default working directory for execute_process is the CMAKE_BINARY_DIR, so you can pass the path to the script relative to that.
Alternatively you can specify the WORKING_DIRECTORY in the execute_process call either as a full path or relative to the CMAKE_BINARY_DIR.
If you feel your script is in a standard location, you could consider "finding" it first using a call to find_file. This would yield the full path to the script if found and that variable can be used in your execute_process call.

cmake detect empty directory during build time

I have a custom command that is executed if a directory exists. I need to know if the directory is not empty before executing another command.
Question: How to read, detect or get the number of files of a directory?
You can run regular CMake code as script using cmake -P as part of build process.
The script itself would contain somethng like
file(GLOB RESULT DIR)
list(LENGTH RESULT RES_LEN)
if(RES_LEN EQUAL 0)
# DIR is empty, do something
endif()