Cmake: Convert Relative Path to Absolute Path, with Build Directory as Current Directory

In CMake, you can convert relative paths to absolute paths using

get_filename_component(ABSOLUTE_PATH ${RELATIVE_PATH} ABSOLUTE)

However, paths such as ../../other_program/ are based on the source directory (i.e. the directory where the CMakeLists.txt files is), not the build directory (i.e. the directory from which cmake is called). This can lead to some confusion if you give a relative path as a command line option.

Is there a way to tell get_filename_component that it should base the relative path on the current binary dir instead of the current source dir?

2

4 Answers

From the docs of get_filename_component (highlighting be me) :

get_filename_component(<VAR> <FileName>
                       <COMP> [BASE_DIR <BASE_DIR>]
                       [CACHE])

Set <VAR> to the absolute path of <FileName>, where <COMP> is one of:

ABSOLUTE = Full path to file REALPATH = Full path to existing file with symlinks resolved

If the provided <FileName> is a relative path, it is evaluated relative to the given base directory <BASE_DIR>. If no base directory is provided, the default base directory will be CMAKE_CURRENT_SOURCE_DIR.

Paths are returned with forward slashes and have no trailing slashes. If the optional CACHE argument is specified, the result variable is added to the cache.

Thus, you use:

get_filename_component(buildDirRelFilePath "${myFile}"
                       REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")

To convert an absolute path to a file into a relative paths, you might use the file command:

file(RELATIVE_PATH <variable> <directory> <file>)

Compute the relative path from a <directory> to a <file> and store it in the <variable>.

file(RELATIVE_PATH buildDirRelFilePath "${CMAKE_BINARY_DIR}" "${myFile}")
5
get_filename_component(MY_RESULT_ABSOLUTE_PATH_VAR
                       "${CMAKE_CURRENT_LIST_DIR}/${MY_RELATIVE_PATH_VAR}"
                       ABSOLUTE)
4

You could check whether path is absolute with if(IS_ABSOLUTE path) and if it isn't prepend the base directory you want. For example,

if(NOT IS_ABSOLUTE ${p})
    set(p "${CMAKE_CURRENT_BINARY_DIR}/${p}")
endif()

CMake 3.20 comes with a new way to do this, using the cmake_path command:

cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE]
                                    [OUTPUT_VARIABLE <out-var>])

BASE_DIRECTORY defaults to CMAKE_CURRENT_SOURCE_DIR, but can be overriden.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Elena Rostova

Elena Rostova

Lead Health, Wellness & Medical Journalist

Elena Rostova holds a Master's degree in Public Health Journalism. She covers groundbreaking medical research, holistic wellness trends, mental health awareness, and nutritional science.

Share this article
Twitter Facebook Pinterest