CMake: Parent directory and trailing slashes

The task is to get the parent directory of a given directory where the given directory is already known to be a directory.

An example where the input directory is already known to be a directory (and not a file) is a target include directory (properties INCLUDE_DIRECTORIES and INTERFACE_INCLUDE_DIRECTORIES).

With CMake prior to version 3.20 there is the get_filename_component function:

get_filename_component(filename_component "${directory}" DIRECTORY)

With CMake >= 3.20 get_filename_component is deprecated in favor of cmake_path. A naive way would be to directly call this function:

cmake_path(GET directory PARENT_PATH cmake_path_naive)

But there is a glitch with cmake_path when directory already contains a trailing slash (“/”).

Calling target_include_directories with trailing slashes might be a bad style, but is still valid. In such a case plain cmake_path returns back plain directory.

The workaround is to add a “/..” and normalize this new path:

set(directory_patched "${directory}/..")
cmake_path(NORMAL_PATH directory_patched)
cmake_path(GET directory_patched PARENT_PATH cmake_path_correct)

For /path/parent/child/ this results in /path/parent/ for which in turn cmake_path(GET directory_patched PARENT_PATH ...) correctly returns /parent/path.

See this github repo for example CMake code.