CMakeTargetsFile¶
Provide operations to configure binary targets using a JSON configuration file. It requires CMake 3.20 or newer.
Introduction¶
In a CMake build project, there is no native and straightforward way to
separate the declaration of a binary target from its definition. Both are
typically performed together when writing commands in a CMakeLists.txt
file. However, in many use cases, the sequence of commands used to define
targets is identical across projects, with only the data changing. The
definition logic for the binary target remains the same, while only its
declarations (i.e., its configuration) change.
The purpose of this module is to simplify the automated creation of binary targets by allowing their settings to be declared in a standardized JSON configuration file. The structure of this file is defined using a JSON schema. Various commands are provided to read and interpret this configuration file.
The configuration file must be named CMakeTargets.json
and can reside
anywhere in the project's directory.
Note
CMake is currently developing the Common Package Specification to standardize the way packages are declared and to improve their integration via the System Package Registry. It is therefore possible that this module may become obsolete in the future. In the meantime, it will continue to evolve to reflect updates introduced in upcoming versions.
Format¶
The CMake targets declaration file is a JSON document with an object as the
root (click to download
):
{
"$schema": "schema.json",
"$id": "schema.json",
"targets": {
"src": {
"name": "fruit-salad",
"type": "executable",
"build": {
"compileFeatures": ["cxx_std_20"],
"compileDefinitions": ["MY_DEFINE=42", "MY_OTHER_DEFINE", "MY_OTHER_DEFINE=42"],
"compileOptions": [],
"linkOptions": []
},
"mainFile": "src/main.cpp",
"pchFile": "include/fruit_salad_pch.h",
"headerPolicy": {
"mode": "split",
"includeDir": "include"
},
"dependencies": {
"AppleLib": {
"rulesFile": "FindAppleLib.cmake",
"minVersion": 2,
"autodownload": true,
"optional": false
},
"BananaLib": {
"rulesFile": "FindBananaLib.cmake",
"minVersion": 4,
"autodownload": false,
"optional": true
}
}
},
"src/apple": {
"name": "apple",
"type": "staticLib",
"build": {
"compileFeatures": [],
"compileDefinitions": [],
"compileOptions": [],
"linkOptions": []
},
"mainFile": "src/apple/main.cpp",
"pchFile": "src/apple/apple_pch.h",
"headerPolicy": {
"mode": "merged"
},
"dependencies": {}
},
"src/banana": {
"name": "banana",
"type": "staticLib",
"build": {
"compileFeatures": [],
"compileDefinitions": [],
"compileOptions": [],
"linkOptions": []
},
"mainFile": "src/banana/main.cpp",
"pchFile": "src/banana/banana_pch.h",
"headerPolicy": {
"mode": "merged"
},
"dependencies": {}
}
}
}
The JSON document must be conformed to the CMakeTargets.json schema
described below.
The root object recognizes the following fields:
$schema
An optional string that provides a URI to the JSON schema that describes the structure of this JSON document. This field is used for validation and autocompletion in editors that support JSON schema. It doesn't affect the behavior of the document itself. If this field is not specified, the JSON document will still be valid, but tools that use JSON schema for validation and autocompletion may not function correctly. The module does not perform schema validation automatically. Use
$schema
to document the schema version or to enable external validation and tooling workflows.$id
An optional string that provides a unique identifier for the JSON document or the schema resource. The value must be a valid URI or a relative URI reference. When present,
$id
can be used by external tooling to disambiguate or resolve the schema/resource and to avoid collisions between different schema documents. The module stores this property but does not interpret or enforce any semantics associated with$id
.targets
The required root property containing the set of targets defined in the file. Its value is an object whose keys are unique directory paths that identify the parent folder containing the source files for each target. For example:
src
,src/apple
.Each path must be relative to the project root and must not include a trailing slash. The directory path serves as the unique identifier for the target within the file because it is assumed that there can be no more than one target defined per folder.
The value for each key is a target definition object as described in the following subsections. The key name (directory path) can be used internally to organize and retrieve target configurations during the CMake building process.
Each entry of a
targets
is a JSON object that may contain the following properties:name
A required string specifying the human-meaningful name of the target. This name must be unique across all targets listed in the same
targets
object. Two targets within the same file must not share the same name, even if their directory paths differ. The name is used to create a CMake target.type
A required string specifying the kind of binary to generate for this target. Valid values are:
staticLib
- a static library.sharedLib
- a shared (dynamic) library.interfaceLib
- a header-only library.executable
- an executable program.
The type influences how the target is built and linked by the consuming CMake logic.
build
A required object describing build settings. It contains the following array properties:
compileFeatures
A list of optional compile features to pass to the target. It is used as a parameter for the
target_compile_features()
command. The property is required, but the array can be empty.compileDefinitions
A list of optional preprocessor definitions applied when compiling this target. It is used as a parameter for the
target_compile_definitions()
command. The property is required, but the array can be empty.compileOptions
A list of compiler options to pass when building this target. It is used as a parameter for the
target_compile_options()
command. The property is required, but the array can be empty.linkOptions
A list of linker options to pass when building this target. It is used as a parameter for the
target_link_options()
command. The property is required, but the array can be empty.
All four properties must be present. Lists may be empty to indicate no entries.
mainFile
A required string specifying the path to the main source file for this target. The path must be relative to the project root. The file must exist and have a
.cpp
,.cc
, or.cxx
extension.pchFile
An optional string specifying the path to the precompiled header file (PCH) for this target. The path must be relative to the project root. If present, it must have one of the following extensions:
.h
,.hpp
,.hxx
,.inl
,.tpp
. If not specified, the target is considered to have no PCH.headerPolicy
A required object describing how header files are organized within the project. It has the following properties:
mode
A required string specifying whether all header files are grouped in a a single common folder or whether public headers are separated from private headers. Valid values are:
split
- public headers are stored in a different folder (e.g.,include/
) than private headers (e.g.,src/
).merged
- public and private headers are in the same folder (e.g.,src/
).
includeDir
Required only if
mode
issplit
. A path relative to the project root specifying the folder ininclude/
where the public headers are located. The path must start withinclude
(e.g.,include
,include/mylib
) and must not include a trailing slash.
dependencies
The required object property specifying the set of dependencies needed by the target. Its value is an object whose keys are the names of the dependencies. Each name must be unique within the
dependencies
object.Each entry of a
dependencies
object is a JSON object that may contain the following properties:rulesFile
A required path to a CMake file ending in
.cmake
that defines how to integrate the dependency into the build system.minVersion
A required integer specifying the minimum acceptable version of the dependency. This value is used as the
VERSION
argument tofind_package()
calls for that dependency.autodownload
A required boolean indicating whether the dependency may be automatically downloaded if not found locally.
optional
A required boolean indicating whether the dependency is optional. If
true
and the dependency cannot be found, it is ignored and not linked. Iffalse
and the dependency is missing, the build will fail.
Schema¶
This file
provides a machine-
readable JSON schema for the CMakeTargets.json
format.
Synopsis¶
cmake_targets_file(LOAD <json-file-path>) cmake_targets_file(IS_LOADED <output-var>) cmake_targets_file(GET_LOADED_FILE <output-var>) cmake_targets_file(HAS_CONFIG <output-var> TARGET <target-dir-path>) cmake_targets_file(GET_SETTINGS <output-map-var> TARGET <target-dir-path>) cmake_targets_file(GET_KEYS <output-list-var> TARGET <target-dir-path>) cmake_targets_file(GET_VALUE <output-var> TARGET <target-dir-path> KEY <setting-name>) cmake_targets_file(PRINT_CONFIGS []) cmake_targets_file(PRINT_TARGET_CONFIG <target-dir-path>)
Usage¶
- cmake_targets_file(LOAD <json-file-path>)¶
Load and parses a targets configuration file in JSON format.
Note
During loading, no checks are performed on property values to ensure that they comply with the
CMakeTargets.json schema
. The command only verifies that the expected JSON structure is present and that the properties are defined.This behavior is intended to give users more flexibility and to avoid code duplication in cases where both syntactic and semantic validation may be required.
The
<json-file-path>
specifies the location of the configuration file to load. It must refer to an existing file on disk and must have a.json
extension. The file must conform to theCMakeTargets.json schema
.When this command is invoked, the JSON content is read into memory and stored in global properties for later retrieval. Each target entry described in the JSON file is parsed into an independent configuration
Map
, keyed by its directory path. Both the original raw JSON and the list of target directory paths are preserved.The following global properties are initialized:
TARGETS_CONFIG_<target-dir-path>
For each target directory path in the configuration file, stores the serialized key-value
Map
of its parsed properties.TARGETS_CONFIG_RAW_JSON
Contains the loaded JSON file as text.
TARGETS_CONFIG_LIST
Holds the list of all target directory paths defined in the file. They serve as value to get the target configurations stored in
TARGETS_CONFIG_<target-dir-path>
.TARGETS_CONFIG_LOADED
Set to
on
once the configuration is successfully loaded, otherwise tooff
.
This command must be called exactly once before using any other module operation. If the configuration is already loaded, calling
cmake_targets_file(LOAD)
again will replace the current configuration in memory.Each target's configuration is stored separately in a global property named
TARGETS_CONFIG_<target-dir-path>
. These properties are of typeMap
, where each JSON block is represented as a flat tree list.Keys in the map are derived from the JSON property names. Nested properties are flattened by concatenating their successive parent keys, separated by a dot (
.
). For example, the JSON keyrulesFile
from the above example is stored in the map asdependencies.AppleLib.rulesFile
. The list of all keys for a target's map can be retrieved using thecmake_targets_file(GET_KEYS)
command.Since CMake does not support two-dimensional arrays, and because a
Map
is itself a particular type of list, JSON arrays are serialized before being stored. Elements in a serialized array are separated by a pipe (|
) character. For example, the JSON array["MY_DEFINE=42", "MY_OTHER_DEFINE", "MY_OTHER_DEFINE=42"]
becomeMY_DEFINE=42|MY_OTHER_DEFINE|MY_OTHER_DEFINE=42
. And to avoid conflicts, pipe characters (|
) are first escaped with a slash (\|
).Example usage:
cmake_targets_file(LOAD "${CMAKE_SOURCE_DIR}/CMakeTargets.json") get_property(raw_json GLOBAL PROPERTY "TARGETS_CONFIG_RAW_JSON") get_property(is_loaded GLOBAL PROPERTY "TARGETS_CONFIG_LOADED") get_property(paths_list GLOBAL PROPERTY "TARGETS_CONFIG_LIST") get_property(apple_config GLOBAL PROPERTY "TARGETS_CONFIG_src/apple") get_property(banana_config GLOBAL PROPERTY "TARGETS_CONFIG_src/banana") get_property(src_config GLOBAL PROPERTY "TARGETS_CONFIG_src") message("'src' array is: ${src_config}") # output is: # 'src' array is: name:fruit-salad;type:executable;mainFile:src/main.cpp; # pchFile:include/fruit_salad_pch.h;build.compileFeatures:cxx_std_20; # build.compileDefinitions:MY_DEFINE=42|MY_OTHER_DEFINE| # MY_OTHER_DEFINE=42;build.compileOptions:;build.linkOptions:; # headerPolicy.mode:split;headerPolicy.includeDir:include;dependencies: # AppleLib|BananaLib;dependencies.AppleLib.rulesFile:FindAppleLib.cmake; # dependencies.AppleLib.minVersion:2;dependencies.AppleLib.autodownload: # ON;dependencies.AppleLib.optional:OFF;dependencies.BananaLib.rulesFile # :FindBananaLib.cmake;dependencies.BananaLib.minVersion:4;dependencies. # BananaLib.autodownload:OFF;dependencies.BananaLib.optional:ON
- cmake_targets_file(IS_LOADED <output-var>)¶
Set
<output-var>
toon
if a targets configuration file has been loaded with success, oroff
otherwise. This checks the global propertyTARGETS_CONFIG_LOADED
set by a successful invocation of thecmake_targets_file(LOAD)
command.Example usage:
cmake_targets_file(LOAD "${CMAKE_SOURCE_DIR}/CMakeTargets.json") cmake_targets_file(IS_LOADED is_file_loaded) message("file_loaded: ${is_file_loaded}") # output is: # file_loaded: on
- cmake_targets_file(GET_LOADED_FILE <output-var>)¶
Set
<output-var>
to the full JSON content of the currently loaded targets configuration file. The content is retrieved from the global propertyTARGETS_CONFIG_RAW_JSON
, which is set by a successful invocation of thecmake_targets_file(LOAD)
command.An error is raised if no configuration file is loaded.
Example usage:
cmake_targets_file(GET_LOADED_FILE json_file_content) message("json_file_content: ${json_file_content}") # output is: # json_file_content: { # "$schema": "schema.json", # "$id": "schema.json", # "targets": { # ... # } # }
- cmake_targets_file(HAS_CONFIG <output-var> TARGET <target-dir-path>)¶
Set
<output-var>
toon
if a configuration exists for the given target directory path<target-dir-path>
, oroff
otherwise.Example usage :
cmake_targets_file(HAS_CONFIG is_target_configured TARGET "src") message("is_target_configured (src): ${is_target_configured}") # output is: # is_target_configured (src): on
- cmake_targets_file(GET_SETTINGS <output-map-var> TARGET <target-dir-path>)¶
Retrieves the list of all settings defined for a given target configuration in the global property
TARGETS_CONFIG_<target-dir-path>
.The
<target-dir-path>
specifies the directory path of the target whose configuration settings should be retrieved. This must correspond to a path listed in the global propertyTARGETS_CONFIG_LIST
, and must match one of the keys in thetargets
JSON object of the loaded configuration file.The result is stored in
<output-var>
as aMap
.An error is raised if no configuration file has been previously loaded with the
cmake_targets_file(LOAD)
command or if theTARGET
does not exist in the loaded configuration file.Example usage:
cmake_targets_file(GET_SETTINGS target_config_map TARGET "src") message("target_config (src): ${target_config_map}") # output is: # target_config (src): name:fruit-salad;type:executable;mainFile: # src/main.cpp;pchFile:include/fruit_salad_pch.h;...
- cmake_targets_file(GET_KEYS <output-list-var> TARGET <target-dir-path>)¶
Retrieves the list of all setting keys defined for a given target configuration in the global property
TARGETS_CONFIG_<target-dir-path>
.The
<target-dir-path>
specifies the directory path of the target whose configuration settings should be retrieved. This must correspond to a path listed in the global propertyTARGETS_CONFIG_LIST
, and must match one of the keys in thetargets
JSON object of the loaded configuration file.The result is stored in
<output-var>
as a semicolon-separated list.An error is raised if no configuration file has been previously loaded with the
cmake_targets_file(LOAD)
command or if theTARGET
does not exist in the loaded configuration file.Example usage:
cmake_targets_file(GET_KEYS setting_keys TARGET "src") message("setting_keys: ${setting_keys}") # With the JSON example above, output is: # setting_keys: name;type;mainFile;pchFile;build.compileFeatures;build. # compileDefinitions;build.compileOptions;build.linkOptions;headerPolicy. # mode;headerPolicy.includeDir;dependencies;dependencies.AppleLib. # rulesFile;dependencies.AppleLib.minVersion;dependencies.AppleLib. # autodownload;dependencies.AppleLib.optional;dependencies.BananaLib. # rulesFile;dependencies.BananaLib.minVersion;dependencies.BananaLib. # autodownload;dependencies.BananaLib.optional
- cmake_targets_file(GET_VALUE <output-var> TARGET <target-dir-path> KEY <setting-name>)¶
Retrieves the value associated to a specific setting key
<setting-name>
defined for a given target configuration in the global propertyTARGETS_CONFIG_<target-dir-path>
.The
<target-dir-path>
specifies the directory path of the target whose configuration setting should be retrieved. This must correspond to a path listed in the global propertyTARGETS_CONFIG_LIST
, and must match one of the keys in thetargets
JSON object of the loaded configuration file.The
<setting-name>
specifies the flattened key name as stored in theMap
TARGETS_CONFIG_<target-dir-path>
. Nested JSON properties are concatenated using a dot (.
) separator (e.g.,build.compileDefinitions
).The result is stored in
<output-var>
as a value or a deserialized list.An error is raised if no configuration file has been previously loaded with the
cmake_targets_file(LOAD)
command or if theTARGET
does not exist in the loaded configuration file or if theKEY
does not exist in the target configuration.Example usage:
cmake_targets_file(GET_VALUE setting_value TARGET "src" KEY "type") message("setting_value (type): ${setting_value}") # output is: # setting_value (type): executable cmake_targets_file(GET_VALUE setting_value TARGET "src" KEY "build.compileDefinitions") message("setting_value (build.compileDefinitions): ${setting_value}") # output is: # setting_value (build.compileDefinitions): MY_DEFINE=42;MY_OTHER_DEFINE; # MY_OTHER_DEFINE=42 cmake_targets_file(GET_VALUE setting_value TARGET "src" KEY "dependencies") message("setting_value (dependencies): ${setting_value}") # output is: # setting_value (dependencies): AppleLib;BananaLib
- cmake_targets_file(PRINT_CONFIGS [])¶
Prints the configuration of all targets defined in the currently loaded configuration file. It is primarily intended for debugging or inspecting the parsed target settings after loading a configuration file.
An error is raised if no configuration file has been previously loaded with the
cmake_targets_file(LOAD)
commandExample usage:
cmake_targets_file(PRINT_CONFIGS) # output is: # -- Target: fruit-salad # -- type: executable # -- mainFile: src/main.cpp # -- pchFile: include/fruit_salad_pch.h # -- build.compileFeatures: cxx_std_20 # ...
- cmake_targets_file(PRINT_TARGET_CONFIG <target-dir-path>)¶
Prints the configuration of a given target configuration in the global property
TARGETS_CONFIG_<target-dir-path>
. It is primarily intended for debugging or inspecting a parsed target settings after loading a configuration file.The
<target-dir-path>
specifies the directory path of the target whose configuration setting should be retrieved. This must correspond to a path listed in the global propertyTARGETS_CONFIG_LIST
, and must match one of the keys in thetargets
JSON object of the loaded configuration file.An error is raised if no configuration file has been previously loaded with the
cmake_targets_file(LOAD)
command.Example usage:
cmake_targets_file(PRINT_TARGET_CONFIG "src") # output is: # -- Target: fruit-salad # -- type: executable # -- mainFile: src/main.cpp # -- pchFile: include/fruit_salad_pch.h # -- build.compileFeatures: cxx_std_20 # ...