Directory

Operations to manipule directories. It requires CMake 3.20 or newer.

Synopsis

directory(SCAN <output-list-var> [...])
directory(SCAN_DIRS <output-list-var> [...])
directory(FIND_LIB <output-lib-var> [...])
directory(COLLECT_SOURCES_BY_LOCATION [...])
directory(COLLECT_SOURCES_BY_POLICY [...])

Usage

directory(SCAN <output-list-var> [...])

Recursively get files and directories:

directory(SCAN <output-list-var>
         LIST_DIRECTORIES <on|off>
         RELATIVE <on|off>
         ROOT_DIR <directory-path>
         <INCLUDE_REGEX|EXCLUDE_REGEX> <regular-expression>)

Recursively scans files and directories under ROOT_DIR, applies an optional filter based on INCLUDE_REGEX or EXCLUDE_REGEX, and stores the result in <output-list-var>.

Paths are returned as relative to ROOT_DIR if RELATIVE is on, or as absolute paths if RELATIVE is off.

If LIST_DIRECTORIES is on, directories are included in the result. If LIST_DIRECTORIES is off, only files are listed.

Example usage:

directory(SCAN result_list
  LIST_DIRECTORIES off
  RELATIVE on
  ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
  INCLUDE_REGEX ".*[.]cpp$|.*[.]cc$|.*[.]cxx$"
)
# output is:
#   src/main.cpp;src/util.cpp;lib/module.cpp
directory(SCAN_DIRS <output-list-var> [...])

Recursively get directories only:

directory(SCAN_DIRS <output-list-var>
         RECURSE <on|off>
         RELATIVE <on|off>
         ROOT_DIR <directory-path>
         <INCLUDE_REGEX|EXCLUDE_REGEX> <regular-expression>)

Scan and collect all directories under ROOT_DIR that match the regular expression provided with either INCLUDE_REGEX or EXCLUDE_REGEX, and store the result in <output-list-var>.

If RECURSE is on, the function traverses subdirectories recursively. If RECURSE is off, only the directories directly under ROOT_DIR are considered.

The paths in the result are returned relative to ROOT_DIR if RELATIVE is on, or as absolute paths if RELATIVE is off.

Example usage:

directory(SCAN_DIRS matched_dirs
  RECURSE on
  RELATIVE on
  ROOT_DIR "${CMAKE_SOURCE_DIR}"
  INCLUDE_REGEX "include"
)
# output is:
#   src/include;src/lib/include
directory(FIND_LIB <output-lib-var> [...])

Recursively search for libs:

directory(FIND_LIB <output-lib-var>
          FIND_IMPLIB <output-implib-var>
          NAME <raw-filename>
          <STATIC|SHARED>
          RELATIVE <on|off>
          ROOT_DIR <directory-path>)

Search recursively in ROOT_DIR for a library and, on DLL platforms, its import library. The name to search for is given via NAME, which should represent the base name of the library (without prefix or suffix).

The matching uses system-defined prefixes and suffixes depending on the STATIC (by CMAKE_STATIC_LIBRARY_PREFIX and CMAKE_STATIC_LIBRARY_SUFFIX) or SHARED (by CMAKE_SHARED_LIBRARY_PREFIX and CMAKE_SHARED_LIBRARY_SUFFIX) flag, as well as CMAKE_FIND_LIBRARY_PREFIXES and CMAKE_FIND_LIBRARY_SUFFIXES if defined. This makes the behavior similar to find_library(), but more robust.

Note

The different value of prefix and suffix that the variables used to search for libraries can take are:

# With GCC on Windows
# CMAKE_SHARED_LIBRARY_PREFIX: lib
# CMAKE_SHARED_LIBRARY_SUFFIX: .dll
# CMAKE_STATIC_LIBRARY_PREFIX: lib
# CMAKE_STATIC_LIBRARY_SUFFIX: .a
# CMAKE_FIND_LIBRARY_PREFIXES: lib;
# CMAKE_FIND_LIBRARY_SUFFIXES: .dll.a;.a;.lib

# With MSVC on Windows
# CMAKE_SHARED_LIBRARY_PREFIX:
# CMAKE_SHARED_LIBRARY_SUFFIX: .dll
# CMAKE_STATIC_LIBRARY_PREFIX:
# CMAKE_STATIC_LIBRARY_SUFFIX: .lib
# CMAKE_FIND_LIBRARY_PREFIXES: ;lib
# CMAKE_FIND_LIBRARY_SUFFIXES: .dll.lib;.lib;.a

If a matching library is found, its path is stored in <output-lib-var>. If a matching import library is found, its path is stored in <output-implib-var>. If RELATIVE is set to on, the results are relative to ROOT_DIR. Otherwise, absolute paths are returned.

If no match is found, the values will be <output-lib-var>-NOTFOUND and <output-implib-var>-NOTFOUND. In STATIC mode, <output-implib-var>-NOTFOUND is always returned, because an import library is only for a shared library. If multiple matches are found, a fatal error is raised.

This command is especially useful to locate dependency artifacts when configuring Imported Target manually (see also CMake's guide to binary import and export). The resulting paths are typically used to set properties like IMPORTED_LOCATION and IMPORTED_IMPLIB on an imported target, particularly in development or custom build setups where standard find_library() behavior is not sufficient.

Example usage:

directory(FIND_LIB mylib_path
  FIND_IMPLIB mylib_import
  NAME "zlib1"
  SHARED
  RELATIVE on
  ROOT_DIR "${CMAKE_SOURCE_DIR}/libs"
)
# output is:
#   lib=lib/zlib1.dll
#   implib=lib/zlib1.lib
directory(COLLECT_SOURCES_BY_LOCATION [...])

Recursively get source and header file in a dir:

directory(COLLECT_SOURCES_BY_LOCATION
          [SRC_DIR <dir-path>
          SRC_SOURCE_FILES <output-list-var>
          SRC_HEADER_FILES <output-list-var>]
          [INCLUDE_DIR <dir-path>
          INCLUDE_HEADER_FILES <output-list-var>])

Recursively collect source and header files from specified directories and store them in output variables.

If the SRC_DIR option is specified, the command searches the directory recursively for C++ source files with the following extensions: .cpp, .cc, or .cxx, and header files with the extensions .h, .hpp, .hxx, .inl, or .tpp.

Source files found in SRC_DIR are assigned to the variable specified by SRC_SOURCE_FILES, and header files are assigned to the variable specified by SRC_HEADER_FILES.

If the INCLUDE_DIR option is specified, only header files are collected recursively using the same extensions as above. These are assigned to the variable specified by INCLUDE_HEADER_FILES.

Both SRC_DIR and INCLUDE_DIR may be specified simultaneously. In that case, files are collected from both locations and stored into their respective output variables.

At least one of SRC_DIR or INCLUDE_DIR must be provided. If neither is specified, or if any of the corresponding output variable arguments are missing, the command raises a fatal error.

Example usage:

directory(COLLECT_SOURCES_BY_LOCATION
  SRC_DIR "${CMAKE_SOURCE_DIR}/src"
  SRC_SOURCE_FILES src_sources
  SRC_HEADER_FILES src_headers
  INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include"
  INCLUDE_HEADER_FILES include_headers
)

# Or
directory(COLLECT_SOURCES_BY_LOCATION
  SRC_DIR "${CMAKE_SOURCE_DIR}/src"
  SRC_SOURCE_FILES src_sources
  SRC_HEADER_FILES src_headers
)

# Or
directory(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include"
  INCLUDE_HEADER_FILES include_headers
)
directory(COLLECT_SOURCES_BY_POLICY [...])

Recursively get source and header file according to a policy:

directory(COLLECT_SOURCES_BY_POLICY
          PUBLIC_HEADERS_SEPARATED <on|off> [<include-dir-path>]
          SRC_DIR <dir-path>
          SRC_SOURCE_FILES <output-list-var>
          PUBLIC_HEADER_DIR <output-var>
          PUBLIC_HEADER_FILES <output-list-var>
          PRIVATE_HEADER_DIR <output-var>
          PRIVATE_HEADER_FILES <output-list-var>)

Recursively collect source and header files from specified directories according to a header separation policy.

This command collects source files with extensions .cpp, .cc, or .cxx from the directory specified by SRC_DIR and stores them in the variable referenced by SRC_SOURCE_FILES.

The behavior for header files depends on the policy value given to PUBLIC_HEADERS_SEPARATED:

  • If PUBLIC_HEADERS_SEPARATED on <include-dir-path> is specified:

    • Public headers are collected from <include-dir-path> and stored in the variable referenced by PUBLIC_HEADER_FILES.

    • The variable referenced by PUBLIC_HEADER_DIR is set to <include-dir-path>.

    • Private headers are collected from SRC_DIR and stored in the variable referenced by PRIVATE_HEADER_FILES.

    • The variable referenced by PRIVATE_HEADER_DIR is set to SRC_DIR.

  • If PUBLIC_HEADERS_SEPARATED off is specified:

    • All headers are treated as public and collected from SRC_DIR.

    • The variable referenced by PUBLIC_HEADER_FILES contains the header file list.

    • The variable referenced by PUBLIC_HEADER_DIR is set to SRC_DIR.

    • The variables referenced by PRIVATE_HEADER_DIR and PRIVATE_HEADER_FILES are set to empty.

If the policy is set to on, but <include-dir-path> is missing or does not refer to an existing directory, a fatal error is raised.

Example usage:

directory(COLLECT_SOURCES_BY_POLICY
  PUBLIC_HEADERS_SEPARATED on "${CMAKE_SOURCE_DIR}/include/mylib"
  SRC_DIR "${CMAKE_SOURCE_DIR}/src"
  SRC_SOURCE_FILES sources
  PUBLIC_HEADER_DIR public_headers_dir
  PUBLIC_HEADER_FILES public_headers
  PRIVATE_HEADER_DIR private_headers_dir
  PRIVATE_HEADER_FILES private_headers
)