presets: Support loading from arbitrary file Allow CMake, CTest, and CPack to read presets from a path given by command-line argument instead of always requiring `CMakePresets.json` or `CMakeUserPresets.json` in the source tree. This makes the presets feature more extensible to cases in which the user doesn't have access to the presets defined in the source tree (e.g., if the source tree is not writable). For now, there is no equivalent implementation of such an option in the `cmake-gui`, nor for the recent presets functionality implemented in `ctest_configure` and `ctest_build`. Fixes: #27329
diff --git a/Help/guide/tutorial/Configuration and Cache Variables.rst b/Help/guide/tutorial/Configuration and Cache Variables.rst index 9e865d7..7da09ed 100644 --- a/Help/guide/tutorial/Configuration and Cache Variables.rst +++ b/Help/guide/tutorial/Configuration and Cache Variables.rst
@@ -506,6 +506,12 @@ Command line flags can be mixed with presets. Command line flags have precedence over values found in a preset. +.. note:: + On CMake 4.4 and newer, CMake can also load presets from any file specified + with :option:`cmake --presets-file`. This can be useful when reusing settings + across multiple projects, since it avoids having to duplicate them in + separate ``CMakePresets.json`` files for each project. + Presets also support limited macros, variables that can be brace-expanded inside the preset. The only one of interest to us is the ``${sourceDir}`` macro, which expands to the root directory of the project. We can use this to set our
diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst index 086aa52..12d6b84 100644 --- a/Help/guide/user-interaction/index.rst +++ b/Help/guide/user-interaction/index.rst
@@ -425,7 +425,7 @@ presets can set the build directory, generator, cache variables, environment variables, and other command-line options. All of these options can be overridden by the -user. The full details of the CMake preset format +user. The full details of the CMake presets format are listed in the :manual:`cmake-presets(7)` manual. Using presets on the command-line
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index b94e9cb..8985502 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst
@@ -35,6 +35,13 @@ project is using Git, ``CMakePresets.json`` may be tracked, and ``CMakeUserPresets.json`` should be added to the ``.gitignore``. +.. versionadded:: 4.4 + + CMake also supports specifying a file from which to read presets via the + :cmake-option:`--presets-file` option. If this option is specified, neither + of ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present, and any presets defined in those files will be ignored/unavailable. + Format ======
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index de24ccb..7b7680f 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst
@@ -686,12 +686,15 @@ .. option:: --preset <preset>, --preset=<preset> - Reads a :manual:`preset <cmake-presets(7)>` from ``CMakePresets.json`` and - ``CMakeUserPresets.json`` files, which must be located in the same directory - as the top level ``CMakeLists.txt`` file. The preset may specify the - generator, the build directory, a list of variables, and other arguments to - pass to CMake. At least one of ``CMakePresets.json`` or - ``CMakeUserPresets.json`` must be present. + Reads a :manual:`preset <cmake-presets(7)>` from CMake presets files. + ``CMakePresets.json`` and ``CMakeUserPresets.json`` are the default files, + which must be located in the same directory as the top level + ``CMakeLists.txt`` file. A file can also be specified with + :cmake-option:`--presets-file`. + + The preset may specify the generator, the build directory, a list of + variables, and other arguments to pass to CMake. + The :manual:`CMake GUI <cmake-gui(1)>` also recognizes and supports ``CMakePresets.json`` and ``CMakeUserPresets.json`` files. For full details on these files, see :manual:`cmake-presets(7)`. @@ -699,26 +702,49 @@ The presets are read before all other command line options, although the :cmake-option:`-S` option can be used to specify the source directory containing the ``CMakePresets.json`` and ``CMakeUserPresets.json`` files. - If :cmake-option:`-S` is not given, the current directory is assumed to - be the top level source directory and must contain the presets files. The - options specified by the chosen preset (variables, generator, etc.) can all - be overridden by manually specifying them on the command line. For example, - if the preset sets a variable called ``MYVAR`` to ``1``, but the user sets - it to ``2`` with a ``-D`` argument, the value ``2`` is preferred. + If neither :cmake-option:`-S` nor :cmake-option:`--presets-file` are given, + the current working directory is assumed to be the top level source directory + and must contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. + + The options specified by the chosen preset (variables, generator, etc.) + can all be overridden by manually specifying them on the command line. + For example, if the preset sets a variable called ``MYVAR`` to ``1``, + but the user sets it to ``2`` with a :cmake-option:`-D` argument, + the value ``2`` is preferred. .. versionadded:: 3.21 - The ``-B`` option may optionally be specified with a different binary - directory than the one specified by the ``binaryDir`` key of the - configure preset. + The :cmake-option:`-B` option may optionally be specified with a different + binary directory than the one specified by the + :preset:`configurePresets.binaryDir` field. + + .. versionchanged:: 4.4 + If :cmake-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present. In prior versions, the presence of these files in the top-level + source directory (whether via :cmake-option:`-S` or the current working + directory) was strictly required. + +.. option:: --presets-file <file>, --presets-file=<file> + + .. versionadded:: 4.4 + + Reads :manual:`presets <cmake-presets(7)>` from the given ``<file>``. The + specified path may be absolute or relative to the current working directory. + If ``--presets-file`` is given, presets defined in ``CMakePresets.json`` and + ``CMakeUserPresets.json`` will be ignored. .. option:: --list-presets[=<type>] Lists the available presets of the specified ``<type>``. Valid values for ``<type>`` are ``configure``, ``build``, ``test``, ``package``, or ``all``. - If ``<type>`` is omitted, ``configure`` is assumed. The current working - directory must contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json`` - unless the :cmake-option:`-S` option is used to specify a different top level - source directory. + If ``<type>`` is omitted, ``configure`` is assumed. + + .. versionchanged:: 4.4 + If :cmake-option:`--presets-file` is specified, the presets defined in the + given ``<file>`` will be listed. Otherwise, the top-level source directory + (whether via :cmake-option:`-S` or the current working directory) must + contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. + In prior versions, the latter was strictly required. .. option:: --debugger @@ -806,6 +832,18 @@ .. versionchanged:: 4.4 ``cmake --build <dir> --preset`` no longer needs to be called from the directory containing ``CMakePresets.json`` or ``CMakeUserPresets.json``. + If :cmake-build-option:`--presets-file` is specified, CMake will use that + file; otherwise, the presets file(s) can be inferred from the current + build directory's ``CMakeCache.txt``. + +.. option:: --presets-file <file>, --presets-file=<file> + + .. versionadded:: 4.4 + + Reads :manual:`presets <cmake-presets(7)>` from the given ``<file>``. The + specified path may be absolute or relative to the current working directory. + If ``--presets-file`` is given, presets defined in ``CMakePresets.json`` and + ``CMakeUserPresets.json`` will be ignored. .. option:: --list-presets @@ -814,6 +852,9 @@ .. versionchanged:: 4.4 ``cmake --build <dir> --list-presets`` no longer needs to be called from the directory containing ``CMakePresets.json`` or ``CMakeUserPresets.json``. + If :cmake-build-option:`--presets-file` is specified, only presets defined + in the given ``<file>`` will be listed; otherwise, the presets file(s) are + inferred from the current build directory's ``CMakeCache.txt``. .. option:: -j [<jobs>], --parallel [<jobs>] @@ -1913,7 +1954,6 @@ Use a workflow :manual:`preset <cmake-presets(7)>` to specify a workflow. The project binary directory is inferred from the initial configure preset. - The current working directory must contain CMake presets files. .. versionchanged:: 3.31 When following immediately after the ``--workflow`` option, @@ -1924,10 +1964,31 @@ $ cmake --workflow my-preset + .. versionchanged:: 4.4 + If :cmake-workflow-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present. Otherwise, they are required to be present in the top level + source directory. In prior versions, this was strictly required. + +.. option:: --presets-file <file>, --presets-file=<file> + + .. versionadded:: 4.4 + + Reads :manual:`presets <cmake-presets(7)>` from the given ``<file>``. The + specified path may be absolute or relative to the current working directory. + If ``--presets-file`` is given, presets defined in ``CMakePresets.json`` and + ``CMakeUserPresets.json`` will be ignored. + .. option:: --list-presets - Lists the available workflow presets. The current working directory must - contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. + Lists the available workflow presets. + + .. versionchanged:: 4.4 + If :cmake-workflow-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present, and only presets defined in the given ``<file>`` will be listed. + Otherwise, they are required to be present in the top level source + directory. In prior versions, this was strictly required. .. option:: --fresh
diff --git a/Help/manual/cpack.1.rst b/Help/manual/cpack.1.rst index c0fe0cc..686d153 100644 --- a/Help/manual/cpack.1.rst +++ b/Help/manual/cpack.1.rst
@@ -124,13 +124,33 @@ Use a package :manual:`preset <cmake-presets(7)>` to specify package options. The project binary directory is inferred from the - :preset:`packagePresets.configurePreset` key. The current working directory - must contain ``CMakePresets.json`` or ``CMakeUserPresets.json``. + :preset:`packagePresets.configurePreset` key. + + .. versionchanged:: 4.4 + If :cpack-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present. Otherwise, they are required to be present in the top level + source directory. In prior versions, this was strictly required. + +.. option:: --presets-file <file>, --presets-file=<file> + + .. versionadded:: 4.4 + + Reads :manual:`presets <cmake-presets(7)>` from the given ``<file>``. The + specified path may be absolute or relative to the current working directory. + If ``--presets-file`` is given, presets defined in ``CMakePresets.json`` and + ``CMakeUserPresets.json`` will be ignored. .. option:: --list-presets - Lists the available package presets. The current working directory must - contain ``CMakePresets.json`` or ``CMakeUserPresets.json``. + Lists the available package presets. + + .. versionchanged:: 4.4 + If :cpack-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present, and only presets defined in the given ``<file>`` will be listed. + Otherwise, they are required to be present in the top level source + directory. In prior versions, this was strictly required. .. include:: include/OPTIONS_HELP.rst
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 0d98bf4..c64fd81 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst
@@ -71,19 +71,40 @@ Use a test :manual:`preset <cmake-presets(7)>` to specify test options. The project binary directory is inferred from the - :preset:`testPresets.configurePreset` key. The current working directory must - contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. + :preset:`testPresets.configurePreset` key. .. versionadded:: 3.30 The :ctest-option:`--test-dir` option may be specified with a different binary directory than the one specified by the :preset:`testPresets.configurePreset` key. + .. versionchanged:: 4.4 + If :ctest-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present. Otherwise, they are required to be present in the top level + source directory. In prior versions, this was strictly required. + +.. option:: --presets-file <file>, --presets-file=<file> + + .. versionadded:: 4.4 + + Reads :manual:`presets <cmake-presets(7)>` from the given ``<file>``. The + specified path may be absolute or relative to the current working directory. + If ``--presets-file`` is given, presets defined in ``CMakePresets.json`` and + ``CMakeUserPresets.json`` will be ignored. + .. option:: --list-presets Lists the available test presets. The current working directory must contain ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. + .. versionchanged:: 4.4 + If :ctest-option:`--presets-file` is specified, neither of + ``CMakePresets.json`` nor ``CMakeUserPresets.json`` are required to be + present, and only presets defined in the given ``<file>`` will be listed. + Otherwise, they are required to be present in the top level source + directory. In prior versions, this was strictly required. + .. option:: -C <cfg>, --build-config <cfg> Choose configuration to test.
diff --git a/Help/release/dev/presets-file-arg.rst b/Help/release/dev/presets-file-arg.rst new file mode 100644 index 0000000..7cfc969 --- /dev/null +++ b/Help/release/dev/presets-file-arg.rst
@@ -0,0 +1,11 @@ +presets-file-arg +---------------- + +* :manual:`cmake(1)`, :manual:`ctest(1)`, and :manual:`cpack(1)` gained + ``--presets-file`` arguments to support loading + :manual:`presets <cmake-presets(7)>` from the specified file instead of + ``CMakePresets.json`` and/or ``CMakeUserPresets.json``. See + :option:`cmake --presets-file`, + :option:`cmake --build --presets-file <cmake--build --presets-file>`, + :option:`cmake --workflow --presets-file <cmake--workflow --presets-file>`, + :option:`ctest --presets-file`, and :option:`cpack --presets-file` for details.
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 85bec08..c595378 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx
@@ -47,7 +47,7 @@ cmDocumentationEntry const cmDocumentationUsage = { {}, " cpack [options]" }; -cmDocumentationEntry const cmDocumentationOptions[14] = { +cmDocumentationEntry const cmDocumentationOptions[] = { { "-G <generators>", "Override/define CPACK_GENERATOR" }, { "-C <Configurations>", "Specify the project configuration(s)" }, { "-D <var>=<value>", "Set a CPack variable." }, @@ -61,6 +61,7 @@ { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" }, { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" }, { "--preset", "Read arguments from a package preset" }, + { "--presets-file", "Load package presets from the given file" }, { "--list-presets", "List available package presets" } }; @@ -162,6 +163,12 @@ return true; }; + auto const presetFileLambda = [&presetsArgs](std::string const& value, + cmake*, cmMakefile*) -> bool { + presetsArgs.PresetsFile = cmSystemTools::ToNormalizedPathOnDisk(value); + return true; + }; + using CommandArgument = cmCommandLineArgument<bool(std::string const&, cmake*, cmMakefile*)>; @@ -204,6 +211,8 @@ CommandArgument::setToValue(presetsArgs.PresetName) }, CommandArgument{ "--list-presets", CommandArgument::Values::Zero, CommandArgument::setToTrue(presetsArgs.ListPresets) }, + CommandArgument{ "--presets-file", "No file specified for --presets-file", + CommandArgument::Values::One, presetFileLambda }, CommandArgument{ "-D", CommandArgument::Values::One, CommandArgument::RequiresSeparator::No, [&log, &definitions](std::string const& arg, cmake*, @@ -262,7 +271,8 @@ }; cmCMakePresetsGraph presetsGraph; - auto result = presetsGraph.ReadProjectPresets(workingDirectory); + auto result = presetsGraph.ReadProjectPresets(workingDirectory, + presetsArgs.PresetsFile); if (result != true) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Could not read presets from "
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 7bbf5a3..6546088 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -81,7 +81,7 @@ mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); cmCMakePresetsGraph presetsGraph; - if (!presetsGraph.ReadProjectPresets(sourceDirectory)) { + if (!presetsGraph.ReadProjectPresets(sourceDirectory, "")) { status.SetError( cmStrCat("Could not read presets from \"", sourceDirectory, "\": ", presetsGraph.parseState.GetErrorMessage()));
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index bede3b1..3e9e1dc 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -64,7 +64,7 @@ if (!presetName.empty()) { cmCMakePresetsGraph presetsGraph; - if (!presetsGraph.ReadProjectPresets(sourceDirectory)) { + if (!presetsGraph.ReadProjectPresets(sourceDirectory, "")) { status.SetError( cmStrCat("Could not read presets from \"", sourceDirectory, "\": ", presetsGraph.parseState.GetErrorMessage()));
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 42df704..eb743bc 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx
@@ -541,7 +541,7 @@ void QCMake::loadPresets() { auto result = this->CMakePresetsGraph.ReadProjectPresets( - this->SourceDirectory.toStdString(), + this->SourceDirectory.toStdString(), "", cmCMakePresetsGraph::ReadOption::AllowNoFiles); if (!result) { emit this->presetLoadError(
diff --git a/Source/cmCMakePresetsArgs.h b/Source/cmCMakePresetsArgs.h index e501eba..7228c9d 100644 --- a/Source/cmCMakePresetsArgs.h +++ b/Source/cmCMakePresetsArgs.h
@@ -13,6 +13,7 @@ virtual void Clear() { this->PresetName.clear(); } std::string PresetName; + std::string PresetsFile; protected: cmCMakePresetsArgsBase() = default;
diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index 408ff49..212a97b 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx
@@ -1142,12 +1142,13 @@ } bool cmCMakePresetsGraph::ReadProjectPresets(std::string const& sourceDir, + std::string const& presetsFile, ReadOption readFilesOption) { this->SourceDir = cmSystemTools::CollapseFullPath(sourceDir); this->ClearPresets(); - if (!this->ReadProjectPresetsInternal(readFilesOption)) { + if (!this->ReadProjectPresetsInternal(presetsFile, readFilesOption)) { this->ClearPresets(); return false; } @@ -1184,28 +1185,40 @@ } bool cmCMakePresetsGraph::ReadProjectPresetsInternal( - ReadOption readFilesOption) + std::string const& presetsFile, ReadOption readFilesOption) { bool haveOneFile = false; File* file; - std::string filename = GetUserFilename(this->SourceDir); + std::string filename; std::vector<File*> inProgressFiles; - if (cmSystemTools::FileExists(filename)) { - if (!this->ReadJSONFile(filename, RootType::User, ReadReason::Root, - inProgressFiles, file, this->errors)) { - return false; - } - haveOneFile = true; - } else { - filename = GetFilename(this->SourceDir); + if (!presetsFile.empty()) { + filename = presetsFile; if (cmSystemTools::FileExists(filename)) { - if (!this->ReadJSONFile(filename, RootType::Project, ReadReason::Root, + if (!this->ReadJSONFile(filename, RootType::Any, ReadReason::Root, inProgressFiles, file, this->errors)) { return false; } haveOneFile = true; } + } else { + filename = GetUserFilename(this->SourceDir); + if (cmSystemTools::FileExists(filename)) { + if (!this->ReadJSONFile(filename, RootType::User, ReadReason::Root, + inProgressFiles, file, this->errors)) { + return false; + } + haveOneFile = true; + } else { + filename = GetFilename(this->SourceDir); + if (cmSystemTools::FileExists(filename)) { + if (!this->ReadJSONFile(filename, RootType::Project, ReadReason::Root, + inProgressFiles, file, this->errors)) { + return false; + } + haveOneFile = true; + } + } } assert(inProgressFiles.empty());
diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h index 1d69d7d..74063e4 100644 --- a/Source/cmCMakePresetsGraph.h +++ b/Source/cmCMakePresetsGraph.h
@@ -460,7 +460,7 @@ }; bool ReadProjectPresets( - std::string const& sourceDir, + std::string const& sourceDir, std::string const& presetsFile, ReadOption readFilesOption = ReadOption::RequireFiles); std::string GetGeneratorForPreset(std::string const& presetName) const; @@ -479,6 +479,7 @@ private: enum class RootType { + Any, Project, User, }; @@ -489,7 +490,8 @@ Included, }; - bool ReadProjectPresetsInternal(ReadOption readFilesOption); + bool ReadProjectPresetsInternal(std::string const& presetsFile, + ReadOption readFilesOption); bool ReadJSONFile(std::string const& filename, RootType rootType, ReadReason readReason, std::vector<File*>& inProgressFiles, File*& file, std::string& errMsg);
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 27f6819..9bec12f 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx
@@ -1507,7 +1507,8 @@ auto const workingDirectory = cmSystemTools::GetLogicalWorkingDirectory(); cmCMakePresetsGraph settingsFile; - auto result = settingsFile.ReadProjectPresets(workingDirectory); + auto result = + settingsFile.ReadProjectPresets(workingDirectory, args.PresetsFile); if (result != true) { cmSystemTools::Error(cmStrCat("Could not read presets from ", workingDirectory, ":\n", @@ -1998,6 +1999,13 @@ [&presetsArgs](std::string const& presetArg) -> bool { presetsArgs.PresetName = presetArg; return true; + } }, + CommandArgument{ "--presets-file", "'--presets-file' requires an argument", + CommandArgument::Values::One, + [&presetsArgs](std::string const& presetFileArg) -> bool { + presetsArgs.PresetsFile = + cmSystemTools::ToNormalizedPathOnDisk(presetFileArg); + return true; } } }; auto const isPresetArgument = [&](std::string const& arg) -> bool { @@ -2606,8 +2614,8 @@ } } - // TestProgressOutput only supported if console supports it and not logging - // to a file + // TestProgressOutput only supported if console supports it and not + // logging to a file this->Impl->TestProgressOutput = this->Impl->TestProgressOutput && !this->Impl->OutputLogFile && this->ProgressOutputSupportedByConsole(); #ifdef _WIN32
diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b08f2d3..2918cd1 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx
@@ -1434,6 +1434,13 @@ return true; }); arguments.emplace_back( + "--presets-file", "No file specified for --presets-file", + CommandArgument::Values::One, + [&presetsArgs](std::string const& value, cmake*) -> bool { + presetsArgs.PresetsFile = cmSystemTools::ToNormalizedPathOnDisk(value); + return true; + }); + arguments.emplace_back( "--list-presets", CommandArgument::Values::ZeroOrOne, [&](std::string const& value, cmake*) -> bool { if (value.empty() || value == "configure") { @@ -2016,7 +2023,8 @@ using ListPresets = cmCMakePresetsConfigureArgs::ListPresetsOption; cmCMakePresetsGraph presetsGraph; - auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory()); + auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory(), + args.PresetsFile); if (result != true) { std::string errorMsg = cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ":\n", @@ -3929,7 +3937,8 @@ cmSystemTools::GetLogicalWorkingDirectory()); } cmCMakePresetsGraph settingsFile; - auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory()); + auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory(), + presetsArgs.PresetsFile); if (result != true) { cmSystemTools::Error( cmStrCat("Could not read presets from ", this->GetHomeDirectory(), @@ -4282,7 +4291,8 @@ this->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory()); cmCMakePresetsGraph settingsFile; - auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory()); + auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory(), + args.PresetsFile); if (result != true) { cmSystemTools::Error(cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ":\n",
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 6c41883..d7f0c88 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx
@@ -76,6 +76,8 @@ cmDocumentationEntry const cmDocumentationOptions[] = { { "--preset <preset>,--preset=<preset>", "Specify a configure preset." }, + { "--presets-file <file>,--presets-file=<file>", + "Specify the path to a presets file." }, { "--list-presets[=<type>]", "List available presets." }, { "--workflow [<options>]", "Run a workflow preset." }, { "-E", "CMake command mode. Run \"cmake -E\" for a summary of commands." }, @@ -516,6 +518,10 @@ buildArgs.verbose = true; return true; }; + auto presetFileLambda = [&](std::string const& value) -> bool { + presetsArgs.PresetsFile = cmSystemTools::ToNormalizedPathOnDisk(value); + return true; + }; using CommandArgument = cmCommandLineArgument<bool(std::string const& value)>; @@ -524,6 +530,8 @@ CommandArgument{ "--preset", "No preset specified for --preset", CommandArgument::Values::One, CommandArgument::setToValue(presetsArgs.PresetName) }, + CommandArgument{ "--presets-file", "No file specified for --presets-file", + CommandArgument::Values::One, presetFileLambda }, CommandArgument{ "--list-presets", CommandArgument::Values::Zero, CommandArgument::setToTrue(presetsArgs.ListPresets) }, CommandArgument{ "-j", CommandArgument::Values::ZeroOrOne, @@ -633,6 +641,8 @@ " <dir> = Project binary directory to be built.\n" " --preset <preset>, --preset=<preset>\n" " = Specify a build preset.\n" + " --presets-file <file>, --presets-file=<file>\n" + " = Specify the path to a presets file.\n" " --list-presets[=<type>]\n" " = List available build presets.\n" " --parallel [<jobs>], -j [<jobs>]\n" @@ -989,6 +999,13 @@ CommandArgument{ "--preset", "No preset specified for --preset", CommandArgument::Values::One, CommandArgument::setToValue(presetsArgs.PresetName) }, + CommandArgument{ "--presets-file", "No file specified for --presets-file", + CommandArgument::Values::One, + [&presetsArgs](std::string const& value) -> bool { + presetsArgs.PresetsFile = + cmSystemTools::ToNormalizedPathOnDisk(value); + return true; + } }, CommandArgument{ "--list-presets", CommandArgument::Values::Zero, CommandArgument::setToTrue(presetsArgs.ListPresets) }, CommandArgument{ "--fresh", CommandArgument::Values::Zero, @@ -1031,10 +1048,11 @@ std::cerr << "Usage: cmake --workflow <options>\n" "Options:\n" - " --preset <preset> = Workflow preset to execute.\n" - " --list-presets = List available workflow presets.\n" - " --fresh = Configure a fresh build tree, removing any " - "existing cache file.\n" + " --preset <preset> = Workflow preset to execute.\n" + " --presets-file <file> = Path to a presets file.\n" + " --list-presets = List available workflow presets.\n" + " --fresh = Configure a fresh build tree, removing any " + "existing cache file.\n" ; /* clang-format on */ return 1;
diff --git a/Tests/RunCMake/CMakePresets/NoPresetFileArgument-result.txt b/Tests/RunCMake/CMakePresets/NoPresetFileArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/NoPresetFileArgument-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetFileArgument-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetFileArgument-stderr.txt new file mode 100644 index 0000000..29d37ad --- /dev/null +++ b/Tests/RunCMake/CMakePresets/NoPresetFileArgument-stderr.txt
@@ -0,0 +1,2 @@ +^CMake Error: No file specified for --presets-file +CMake Error: Run 'cmake --help' for all supported options\.$
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.cmake b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.cmake new file mode 100644 index 0000000..d15bd8d --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.cmake
@@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) + +test_variable(PRESETS_FILE "UNINITIALIZED" "OtherCMakePresetsFile.json")
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.json.in b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.json.in new file mode 100644 index 0000000..af68ee8 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFile.json.in
@@ -0,0 +1,54 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "OtherCMakePresetsFile", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "PRESETS_FILE": "OtherCMakePresetsFile.json" + } + } + ], + "buildPresets": [ + { + "name": "OtherCMakePresetsFile", + "configurePreset": "OtherCMakePresetsFile" + } + ], + "testPresets": [ + { + "name": "OtherCMakePresetsFile", + "configurePreset": "OtherCMakePresetsFile" + } + ], + "packagePresets": [ + { + "name": "OtherCMakePresetsFile", + "configurePreset": "OtherCMakePresetsFile" + } + ], + "workflowPresets": [ + { + "name": "OtherCMakePresetsFile", + "steps": [ + { + "type": "configure", + "name": "OtherCMakePresetsFile" + }, + { + "type": "build", + "name": "OtherCMakePresetsFile" + }, + { + "type": "test", + "name": "OtherCMakePresetsFile" + }, + { + "type": "package", + "name": "OtherCMakePresetsFile" + } + ] + } + ] +}
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakePresets.json.in b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakePresets.json.in new file mode 100644 index 0000000..4b7648d --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakePresets.json.in
@@ -0,0 +1,13 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "OtherCMakePresetsFile", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "PRESETS_FILE": "CMakePresets.json" + } + } + ] +}
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakeUserPresets.json.in b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakeUserPresets.json.in new file mode 100644 index 0000000..185f46d --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileCMakeUserPresets.json.in
@@ -0,0 +1,13 @@ +{ + "version": 1, + "configurePresets": [ + { + "name": "OtherCMakePresetsFile", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "PRESETS_FILE": "CMakeUserPresets.json" + } + } + ] +}
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileList-stdout.txt b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileList-stdout.txt new file mode 100644 index 0000000..7ec3a37 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileList-stdout.txt
@@ -0,0 +1,19 @@ +^Available configure presets: + + "OtherCMakePresetsFile" + +Available build presets: + + "OtherCMakePresetsFile" + +Available test presets: + + "OtherCMakePresetsFile" + +Available package presets: + + "OtherCMakePresetsFile" + +Available workflow presets: + + "OtherCMakePresetsFile"$
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileRelPath.cmake b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileRelPath.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileRelPath.cmake
diff --git a/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileSubdir.cmake b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileSubdir.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/OtherCMakePresetsFileSubdir.cmake
diff --git a/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-result.txt b/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-stderr.txt b/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-stderr.txt new file mode 100644 index 0000000..668f949 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist-stderr.txt
@@ -0,0 +1,4 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresets/PresetsFileArgNoExist: +File not found: [^ +]*/FileDoesNotExist\.json$
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index 303e0c9..d7a0eb6 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -30,6 +30,33 @@ endif() configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY) + set(_presets_file) + if(CMakePresets_FILE_ARG) + cmake_path(GET RunCMake_TEST_SOURCE_DIR PARENT_PATH CMakePresets_FILE_ARG_DIRECTORY) + cmake_path(APPEND CMakePresets_FILE_ARG_DIRECTORY "_OtherCMakePresetsFiles") + if(NOT RunCMake_TEST_SOURCE_DIR_NO_CLEAN) + file(REMOVE_RECURSE "${CMakePresets_FILE_ARG_DIRECTORY}") + file(MAKE_DIRECTORY "${CMakePresets_FILE_ARG_DIRECTORY}") + endif() + if(CMakePresets_FILE_ARG_RELATIVE) + cmake_path(RELATIVE_PATH + CMakePresets_FILE_ARG_DIRECTORY + BASE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}" + OUTPUT_VARIABLE CMakePresets_FILE_ARG_RELATIVE_PATH + ) + set(_presets_file "--presets-file=${CMakePresets_FILE_ARG_RELATIVE_PATH}/${CMakePresets_FILE_ARG}") + else() + set(_presets_file "--presets-file=${CMakePresets_FILE_ARG_DIRECTORY}/${CMakePresets_FILE_ARG}") + endif() + foreach(_presets_file_arg IN ITEMS ${CMakePresets_FILE_ARG} ${CMakePresets_FILE_ARG_EXTRA_FILES}) + configure_file( + "${RunCMake_SOURCE_DIR}/${_presets_file_arg}.in" + "${CMakePresets_FILE_ARG_DIRECTORY}/${_presets_file_arg}" + @ONLY + ) + endforeach() + endif() + if(NOT CMakePresets_FILE) set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in") endif() @@ -93,6 +120,7 @@ ${_make_program} ${_unused_cli} ${_preset} + ${_presets_file} ${_log_level} ${ARGN} ) @@ -313,6 +341,7 @@ run_cmake_presets(NoPresetArgument --preset) run_cmake_presets(NoPresetArgumentEq --preset= -DA=B) run_cmake_presets(UseHiddenPreset) +run_cmake_presets(NoPresetFileArgument --preset GoodNoArgs --presets-file) # Test CMakeUserPresets.json unset(CMakePresets_FILE) @@ -326,6 +355,30 @@ run_cmake_presets(UserDuplicateCross) run_cmake_presets(UserInheritance) +# Test --presets-file=<file> +# <file> should be preferred over CMakePresets.json and CMakeUserPresets.json +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/OtherCMakePresetsFileCMakePresets.json.in") +set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/OtherCMakePresetsFileCMakeUserPresets.json.in") +# <file> must exist +run_cmake_presets(PresetsFileArgNoExist --presets-file=FileDoesNotExist.json) +set(CMakePresets_FILE_ARG OtherCMakePresetsFile.json) +run_cmake_presets(OtherCMakePresetsFile) +# --list-presets should only list the presets defined in <file> +run_cmake_presets(OtherCMakePresetsFileList --list-presets=all) +# <file> can be specified via relative path on the command line +set(CMakePresets_FILE_ARG_RELATIVE 1) +run_cmake_presets(OtherCMakePresetsFileRelPath --preset OtherCMakePresetsFile) +set(CMakePresets_FILE_ARG "subdir/OtherCMakePresetsFileSubdir.json") +set(CMakePresets_FILE_ARG_EXTRA_FILES "subdir/IncludeRelativeToSubdir.json") +# Files included by <file> should have paths evaluated relative to <file> +run_cmake_presets(OtherCMakePresetsFileSubdir) +run_cmake_presets(OtherCMakePresetsFileSubdir --preset=IncludeRelativeToSubdir) +unset(CMakePresets_FILE) +unset(CMakeUserPresets_FILE) +unset(CMakePresets_FILE_ARG) +unset(CMakePresets_FILE_ARG_RELATIVE) +unset(CMakePresets_FILE_ARG_EXTRA_FILES) + # Test listing presets set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListPresets.json.in") run_cmake_presets(ListPresets --list-presets)
diff --git a/Tests/RunCMake/CMakePresets/subdir/IncludeRelativeToSubdir.json.in b/Tests/RunCMake/CMakePresets/subdir/IncludeRelativeToSubdir.json.in new file mode 100644 index 0000000..56db1ad --- /dev/null +++ b/Tests/RunCMake/CMakePresets/subdir/IncludeRelativeToSubdir.json.in
@@ -0,0 +1,10 @@ +{ + "version": 4, + "configurePresets": [ + { + "name": "IncludeRelativeToSubdir", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ] +}
diff --git a/Tests/RunCMake/CMakePresets/subdir/OtherCMakePresetsFileSubdir.json.in b/Tests/RunCMake/CMakePresets/subdir/OtherCMakePresetsFileSubdir.json.in new file mode 100644 index 0000000..e8a5f7f --- /dev/null +++ b/Tests/RunCMake/CMakePresets/subdir/OtherCMakePresetsFileSubdir.json.in
@@ -0,0 +1,13 @@ +{ + "version": 4, + "include": [ + "IncludeRelativeToSubdir.json" + ], + "configurePresets": [ + { + "name": "OtherCMakePresetsFileSubdir", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ] +}
diff --git a/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.cmake b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.cmake
diff --git a/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.json.in b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.json.in new file mode 100644 index 0000000..474c669 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFile.json.in
@@ -0,0 +1,16 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "buildPresets": [ + { + "name": "default-from-other-file", + "configurePreset": "default" + } + ] +}
diff --git a/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFileListPresets-build-x-stdout.txt b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFileListPresets-build-x-stdout.txt new file mode 100644 index 0000000..ee586df --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/OtherCMakePresetsFileListPresets-build-x-stdout.txt
@@ -0,0 +1,3 @@ +^Available build presets: + + "default-from-other-file"$
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-result.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-stderr.txt new file mode 100644 index 0000000..50d4e2b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/PresetsFileNoArg-build-stderr.txt
@@ -0,0 +1 @@ +^CMake Error: No file specified for --presets-file
diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index 92378d3..50a4e8e 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake
@@ -26,6 +26,12 @@ configure_file("${CMakePresetsBuild_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY) endif() + set(_presets_file) + if(CMakePresets_FILE_ARG) + set(_presets_file "--presets-file=${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}") + configure_file("${RunCMake_SOURCE_DIR}/${CMakePresets_FILE_ARG}.in" "${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}" @ONLY) + endif() + if(NOT CMakeUserPresets_FILE) set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in") endif() @@ -50,11 +56,11 @@ if(eq) run_cmake_command(${name}-build-${BUILD_PRESET} - ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset=${BUILD_PRESET}" ${ARGN}) + ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset=${BUILD_PRESET}" ${_presets_file} ${ARGN}) set(eq 0) else() run_cmake_command(${name}-build-${BUILD_PRESET} - ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset" "${BUILD_PRESET}" ${ARGN}) + ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset" "${BUILD_PRESET}" ${_presets_file} ${ARGN}) set(eq 1) endif() endforeach() @@ -74,9 +80,17 @@ run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset" "") run_cmake_build_presets(Condition "default" "enabled;disabled" "") +set(CMakePresets_FILE_ARG "OtherCMakePresetsFile.json") +run_cmake_build_presets(OtherCMakePresetsFile "default" "default-from-other-file" "") +set(CMakePresetsBuild_BUILD_ONLY 1) +run_cmake_build_presets(OtherCMakePresetsFileListPresets "" "x" "--list-presets" "") +unset(CMakePresetsBuild_BUILD_ONLY) +unset(CMakePresets_FILE_ARG) + set(CMakePresetsBuild_BUILD_ONLY 1) run_cmake_command(PresetsNoArg-build ${CMAKE_COMMAND} "--build" "--preset") run_cmake_command(PresetsNoArgEq-build ${CMAKE_COMMAND} "--build" "--preset=") +run_cmake_Command(PresetsFileNoArg-build ${CMAKE_COMMAND} "--build" "--presets-file") run_cmake_build_presets(ListPresets "x" "x" "--list-presets" "") run_cmake_build_presets(NoConfigurePreset "x" "noConfigurePreset" "") run_cmake_build_presets(Invalid "x" "hidden;vendorMacro" "")
diff --git a/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.cmake b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.cmake new file mode 100644 index 0000000..a9068c7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.cmake
@@ -0,0 +1,4 @@ +set(CPACK_PACKAGE_NAME OtherCMakePresetsFile) +set(CPACK_GENERATOR "TGZ;TXZ") + +include(CPack)
diff --git a/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.json.in b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.json.in new file mode 100644 index 0000000..a015307 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFile.json.in
@@ -0,0 +1,22 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ], + "packagePresets": [ + { + "name": "default-from-other-file", + "configurePreset": "default" + } + ] +}
diff --git a/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFileListPresets-package-x-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFileListPresets-package-x-stdout.txt new file mode 100644 index 0000000..7e03528 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/OtherCMakePresetsFileListPresets-package-x-stdout.txt
@@ -0,0 +1,3 @@ +^Available package presets: + + "default-from-other-file"$
diff --git a/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-result.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-stderr.txt new file mode 100644 index 0000000..c532031 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/PresetsFileNoArg-package-stderr.txt
@@ -0,0 +1 @@ +^CMake Error: No file specified for --presets-file$
diff --git a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake index 969fda2..b8c1eb3 100644 --- a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake
@@ -33,6 +33,12 @@ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) endif() + set(_presets_file) + if(CMakePresets_FILE_ARG) + set(_presets_file "--presets-file=${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}") + configure_file("${RunCMake_SOURCE_DIR}/${CMakePresets_FILE_ARG}.in" "${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}" @ONLY) + endif() + foreach(ASSET ${CMakePresetsPackage_ASSETS}) configure_file("${RunCMake_SOURCE_DIR}/${ASSET}" "${RunCMake_TEST_SOURCE_DIR}" COPYONLY) endforeach() @@ -63,11 +69,11 @@ if(eq) run_cmake_command(${name}-package-${PACKAGE_PRESET} - ${CMAKE_CPACK_COMMAND} "--preset=${PACKAGE_PRESET}" ${ARGN}) + ${CMAKE_CPACK_COMMAND} "--preset=${PACKAGE_PRESET}" ${_presets_file} ${ARGN}) set(eq 0) else() run_cmake_command(${name}-package-${PACKAGE_PRESET} - ${CMAKE_CPACK_COMMAND} "--preset" "${PACKAGE_PRESET}" ${ARGN}) + ${CMAKE_CPACK_COMMAND} "--preset" "${PACKAGE_PRESET}" ${_presets_file} ${ARGN}) set(eq 1) endif() endforeach() @@ -101,5 +107,11 @@ run_cmake_package_presets(Good "default" "build-default-debug" "no-environment;with-environment;generators;configurations;variables;config-file;debug;verbose;package-name;package-version;package-directory;vendor-name") run_cmake_package_presets(ListPresets "default" "" "x" "--list-presets") +set(CMakePresets_FILE_ARG "OtherCMakePresetsFile.json") +run_cmake_package_presets(OtherCMakePresetsFile "default" "default" "default-from-other-file" "") +run_cmake_package_presets(OtherCMakePresetsFileListPresets "" "" "x" "--list-presets") +unset(CMakePresets_FILE_ARG) + run_cmake_command(PresetsNoArg-package ${CMAKE_CPACK_COMMAND} "--preset") run_cmake_command(PresetsNoArgEq-package ${CMAKE_CPACK_COMMAND} "--preset=") +run_cmake_command(PresetsFileNoArg-package ${CMAKE_CPACK_COMMAND} "--presets-file")
diff --git a/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.cmake b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.cmake new file mode 100644 index 0000000..3b3b9f9 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.cmake
@@ -0,0 +1,5 @@ +enable_testing() +add_test(testa ${CMAKE_COMMAND} -E echo testa) +add_test(testb ${CMAKE_COMMAND} -E echo testb) +add_test(testc ${CMAKE_COMMAND} -E echo testc) +add_test(testd ${CMAKE_COMMAND} -E echo testd)
diff --git a/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.json.in b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.json.in new file mode 100644 index 0000000..7fb2df5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFile.json.in
@@ -0,0 +1,16 @@ +{ + "version": 2, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build" + } + ], + "testPresets": [ + { + "name": "default-from-other-file", + "configurePreset": "default" + } + ] +}
diff --git a/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFileListPresets-text-x-stdout.txt b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFileListPresets-text-x-stdout.txt new file mode 100644 index 0000000..7623488 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/OtherCMakePresetsFileListPresets-text-x-stdout.txt
@@ -0,0 +1,3 @@ +^Available test presets: + + "default-from-other-file"$
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-result.txt b/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-stderr.txt b/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-stderr.txt new file mode 100644 index 0000000..5235262 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/PresetsFileNoArg-test-stderr.txt
@@ -0,0 +1 @@ +^CMake Error: '--presets-file' requires an argument$
diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake index 42dfe18..2b320f5 100644 --- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake
@@ -37,6 +37,12 @@ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) endif() + set(_presets_file) + if(CMakePresets_FILE_ARG) + set(_presets_file "--presets-file=${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}") + configure_file("${RunCMake_SOURCE_DIR}/${CMakePresets_FILE_ARG}.in" "${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}" @ONLY) + endif() + foreach(ASSET ${CMakePresetsTest_ASSETS}) configure_file("${RunCMake_SOURCE_DIR}/${ASSET}" "${RunCMake_TEST_SOURCE_DIR}" COPYONLY) endforeach() @@ -65,11 +71,11 @@ if(eq) run_cmake_command(${name}-test-${TEST_PRESET} - ${CMAKE_CTEST_COMMAND} "--preset=${TEST_PRESET}" ${ARGN}) + ${CMAKE_CTEST_COMMAND} "--preset=${TEST_PRESET}" ${_presets_file} ${ARGN}) set(eq 0) else() run_cmake_command(${name}-test-${TEST_PRESET} - ${CMAKE_CTEST_COMMAND} "--preset" "${TEST_PRESET}" ${ARGN}) + ${CMAKE_CTEST_COMMAND} "--preset" "${TEST_PRESET}" ${_presets_file} ${ARGN}) set(eq 1) endif() endforeach() @@ -97,6 +103,7 @@ run_cmake_command(PresetsNoArg-test ${CMAKE_CTEST_COMMAND} "--preset") run_cmake_command(PresetsNoArgEq-test ${CMAKE_CTEST_COMMAND} "--preset=") +run_cmake_command(PresetsFileNoArg-test ${CMAKE_CTEST_COMMAND} "--presets-file") set(CMakePresetsTest_FILE "${RunCMake_SOURCE_DIR}/Condition.json.in") run_cmake_test_presets(ConditionListPresets "" "" "x" "--list-presets") @@ -123,6 +130,7 @@ run_cmake_test_presets(Passthrough "default" "" "basic;inherit;execOnly") run_cmake_test_presets(PassthroughCombined "default" "" "combined" "--" "--cli-arg") -set(CMakePresetsTest_NO_CONFIGURE 1) -set(CMakePresetsTest_NO_BUILD 0) +set(CMakePresets_FILE_ARG OtherCMakePresetsFile.json) +run_cmake_test_presets(OtherCMakePresetsFile "default" "" "default-from-other-file") +run_cmake_test_presets(OtherCMakePresetsFileListPresets "" "" "x" "--list-presets")
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt index 8e23c9b..71a61f5 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/InvalidOption-stderr.txt
@@ -1,6 +1,7 @@ ^Unknown argument -DINVALID_OPTION Usage: cmake --workflow <options> Options: - --preset <preset> = Workflow preset to execute\. - --list-presets = List available workflow presets\. - --fresh = Configure a fresh build tree, removing any existing cache file\.$ + --preset <preset> = Workflow preset to execute\. + --presets-file <file> = Path to a presets file\. + --list-presets = List available workflow presets\. + --fresh = Configure a fresh build tree, removing any existing cache file\.$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.cmake b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.cmake new file mode 100644 index 0000000..31ce7ff --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.cmake
@@ -0,0 +1,8 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") + +add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}") + +enable_testing() +add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -E echo "Testing the test step at ${CMAKE_BINARY_DIR}") + +include(CPack)
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.json.in b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.json.in new file mode 100644 index 0000000..4b3f7c3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFile.json.in
@@ -0,0 +1,57 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default", + "configuration": "Debug" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "configuration": "Debug" + } + ], + "packagePresets": [ + { + "name": "default", + "configurePreset": "default", + "generators": [ + "External" + ], + "configurations": ["Debug"] + } + ], + "workflowPresets": [ + { + "name": "OtherCMakePresetsFile", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + } + ] +}
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFileListPresets-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFileListPresets-stdout.txt new file mode 100644 index 0000000..194fbfd --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/OtherCMakePresetsFileListPresets-stdout.txt
@@ -0,0 +1,3 @@ +^Available workflow presets: + + "OtherCMakePresetsFile"$
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-stderr.txt new file mode 100644 index 0000000..50d4e2b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/PresetsFileNoArg-workflow-stderr.txt
@@ -0,0 +1 @@ +^CMake Error: No file specified for --presets-file
diff --git a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake index fac8dfc..e121b1c 100644 --- a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake
@@ -35,6 +35,12 @@ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) endif() + set(_presets_file) + if(CMakePresets_FILE_ARG) + set(_presets_file "--presets-file=${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}") + configure_file("${RunCMake_SOURCE_DIR}/${CMakePresets_FILE_ARG}.in" "${RunCMake_TEST_SOURCE_DIR}/${CMakePresets_FILE_ARG}" @ONLY) + endif() + foreach(ASSET ${CMakePresets_ASSETS}) configure_file("${RunCMake_SOURCE_DIR}/${ASSET}.in" "${RunCMake_TEST_SOURCE_DIR}/${ASSET}" @ONLY) endforeach() @@ -54,7 +60,7 @@ set(eq 1 PARENT_SCOPE) set(preset_arg "--preset" "${name}") endif() - run_cmake_command("${name}" "${CMAKE_COMMAND}" "--workflow" ${preset_arg} ${ARGN}) + run_cmake_command("${name}" "${CMAKE_COMMAND}" "--workflow" ${preset_arg} ${_presets_file} ${ARGN}) endfunction() set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) @@ -80,9 +86,15 @@ unset(CMakeUserPresets_FILE) unset(CMakePresets_ASSETS) +set(CMakePresets_FILE_ARG "OtherCMakePresetsFile.json") +run_cmake_workflow_presets(OtherCMakePresetsFile) +run_cmake_workflow_presets(OtherCMakePresetsFileListPreset --list-presets) +unset(CMakePresets_FILE_ARG) + run_cmake_workflow_presets(ListPresets --list-presets) run_cmake_command(PresetsNoArg-workflow ${CMAKE_COMMAND} "--workflow" "--preset") run_cmake_command(PresetsNoArgEq-workflow ${CMAKE_COMMAND} "--workflow" "--preset=") +run_cmake_command(PresetsFileNoArg-workflow ${CMAKE_COMMAND} "--workflow" "--presets-file") run_cmake_workflow_presets(InvalidOption -DINVALID_OPTION) set(RunCMake_TEST_NO_CLEAN TRUE)